351 * LWP_DispatchProcess();
355 *
while (empty(q)) LWP_WaitProcess(q);
357 * LWP_DispatchProcess();
363 * The next routine, write process(), sits in a loop, putting messages on the
364 * shared queue and signalling the reader, which is waiting
for activity on the
365 * queue. Signalling a thread is accomplished via the LWP SignalProcess()
369 *
static write_process()
372 *
for (mesg = messages; *mesg != 0; mesg++)
375 * LWP_SignalProcess(q);
381 *
finally, here is the main routine
for this demo pseudocode. It starts by
382 * calling the LWP initialization routine. Next, it creates some number of
383 * reader threads with calls to LWP CreateProcess() in addition to the single
384 * writer thread. When all threads terminate, they will signal the main routine
385 * on the done variable. Once signalled, the main routine will reap all the
386 * threads with the help of the LWP DestroyProcess() function.
395 * LWP_InitializeProcessSupport(0, &
id);
397 *
for (i = 0; i < nreaders; i++)
398 * LWP_CreateProcess(read_process, STACK_SIZE, 0, i,
"Reader",
402 * LWP_CreateProcess(write_process, STACK_SIZE, 1, 0,
"Writer", &writer);
404 *
for (i = 0; i <= nreaders; i++)
405 * LWP_WaitProcess(&done);
408 *
for (i = nreaders-1; i >= 0; i--)
409 * LWP_DestroyProcess(readers[i]);
413 * \subsection sec2-2-2 Section 2.2.2: Locking
415 * The LWP locking facility exports a number of routines and macros that allow
416 * a C programmer
using LWP threading to place read and write locks on shared
417 * data structures. This locking facility was also written with simplicity in
420 * In order to invoke the locking mechanism, an
object of type
struct Lock must
421 * be associated with the
object. After being initialized with a call to
422 * LockInit(), the lock
object is used in invocations of various macros,
423 * including ObtainReadLock(), ObtainWriteLock(), ReleaseReadLock(),
424 * ReleaseWriteLock(), ObtainSharedLock(), ReleaseSharedLock(), and
427 * Lock semantics specify that any number of readers may hold a lock in the
428 * absence of a writer. Only a single writer may acquire a lock at any given
429 * time. The lock
package guarantees fairness, legislating that each reader and
430 * writer will eventually obtain a given lock. However, this fairness is only
431 * guaranteed if the priorities of the competing processes are identical. Note
432 * that ordering is not guaranteed by this package.
434 * Shared locks are read locks that can be "boosted" into write locks. These
435 * shared locks have an unusual locking matrix. Unboosted shared locks are
436 * compatible with read locks, yet incompatible with write locks and other
437 * shared locks. In essence, a thread holding a shared lock on an object has
438 * effectively read-locked it, and has the option to promote it to a write lock
439 * without allowing any other writer to enter the critical region during the
440 * boost operation itself.
442 * It is illegal for a process to request a particular lock more than once
443 * without first releasing it. Failure to obey this restriction will cause
444 * deadlock. This restriction is not enforced by the LWP code.
446 * Here is a simple pseudocode fragment serving as an example of the available
447 * locking operations. It defines a struct Vnode object, which contains a lock
448 * object. The get vnode() routine will look up a struct Vnode object by name,
449 * and then either read-lock or write-lock it.
451 * As with the high-level LWP example above, the locking routines introduced
452 * here will be fully defined later, in Section 2.3.2.
455 * #include <afs/lock.h>
459 * struct Lock lock; Used to lock
this vnode
465 *
struct Vnode *get_vnode(name, how)
char *name;
471 * ObtainReadLock(&v->lock);
473 * ObtainWriteLock(&v->lock);
478 * \subsection sec2-2-3 Section 2.2.3: IOMGR
481 * The IOMGR facility associated with the LWP service allows threads to wait on
482 * various unix events. The exported IOMGR Select() routine allows a thread to
483 * wait on the same set of events as the unix select() call. The parameters to
484 * these two routines are identical. IOMGR Select() puts the calling LWP to
485 * sleep until no threads are active. At this point, the built-in IOMGR thread,
486 * which runs at the lowest priority, wakes up and coalesces all of the select
487 * requests together. It then performs a single select() and wakes up all
488 * threads affected by the result.
490 * The IOMGR Signal() routine allows an LWP to wait on the delivery of a unix
491 * signal. The IOMGR thread installs a signal handler to catch all deliveries
492 * of the unix signal. This signal handler posts information about the signal
493 * delivery to a global data structure. The next time that the IOMGR thread
494 * runs, it delivers the signal to any waiting LWP.
496 * Here is a pseudocode example of the use of the IOMGR facility, providing the
497 * blueprint for an implemention a thread-level socket listener.
500 *
void rpc_SocketListener()
502 *
int ReadfdMask, WritefdMask, ExceptfdMask, rc;
503 *
struct timeval *tvp;
506 * ExceptfdMask = ReadfdMask = (1 << rpc_RequestSocket);
509 * rc = IOMGR_Select(8*
sizeof(
int), &ReadfdMask, &WritefdMask,
510 * &ExceptfdMask, tvp);
518 * SystemError(
"IOMGR_Select");
525 *
default: Should never occur
531 * \subsection sec2-2-4 Section 2.2.4: Timer
533 * The timer
package exports a number of routines that assist in manipulating
534 * lists of objects of type struct TM Elem. These struct TM Elem timers are
535 * assigned a timeout value by the user and inserted in a package-maintained
536 * list. The time remaining to each timer's timeout is kept up to date by the
537 * package under user control. There are routines to remove a timer from its
538 * list, to return an expired timer from a list, and to return the next timer
541 * A timer is commonly used by inserting a field of type struct TM Elem into a
542 * structure. After setting the desired timeout value, the structure is
543 * inserted into a list by means of its timer field.
545 * Here is a simple pseudocode example of how the timer package may be used.
546 * After calling the package initialization function, TM Init(), the pseudocode
547 * spins in a loop. first, it updates all the timers via TM Rescan() calls.
548 * Then, it pulls out the first expired timer object with TM GetExpired() (if
549 * any), and processes it.
552 * static struct TM_Elem *requests;
554 * TM_Init(&requests); ...
556 * TM_Rescan(requests);
557 * expired = TM_GetExpired(requests);
560 * . . . process expired element . . .
564 * \subsection sec2-2-5 Section 2.2.5: Fast Time
567 * The fast time routines allows a caller to determine the current time of day
568 * without incurring the expense of a kernel call. It works by mapping the page
569 * of the kernel that holds the time-of-day variable and examining it directly.
570 * Currently,
this package only works on Suns. The routines may be called on
571 * other architectures, but they will run more slowly.
573 * The initialization routine for this package is fairly expensive, since it
574 * does a lookup of a kernel symbol via nlist(). If the client application
575 * program only runs for only a short time, it may wish to call FT Init() with
576 * the notReally parameter set to TRUE in order to prevent the lookup from
577 * taking place. This is useful if you are using another package that uses the
578 * fast time facility.
580 * \subsection sec2-2-6 Section 2.2.6: Preemption
583 * The preemption package provides a mechanism by which control can pass
584 * between lightweight processes without the need for explicit calls to LWP
585 * DispatchProcess(). This effect is achieved by periodically interrupting the
586 * normal flow of control to check if other (higher priority) procesess are
589 * The package makes use of the BSD interval timer facilities, and so will
590 * cause programs that make their own use of these facilities to malfunction.
591 * In particular, use of alarm(3) or explicit handling of SIGALRM is
592 * disallowed. Also, calls to sleep(3) may return prematurely.
594 * Care should be taken that routines are re-entrant where necessary. In
595 * particular, note that stdio(3) is not re-entrant in general, and hence
596 * multiple threads performing I/O on the same fiLE structure may function
599 * An example pseudocode routine illustrating the use of this preemption
600 * facility appears below.
603 * #include <sys/time.h>
604 * #include "preempt.h"
605 * ... struct timeval tv;
606 * LWP_InitializeProcessSupport( ... );
609 * PRE_InitPreempt(&tv);
610 * PRE_PreemptMe(); ...
611 * PRE_BeginCritical(); ...
612 * PRE_EndCritical(); ...
616 * \section sec2-3 Section 2.3: Interface Specifications
618 * \subsection sec2-3-1 Section 2.3.1: LWP
621 * This section covers the calling interfaces to the LWP package. Please note
622 * that LWP macros (e.g., ActiveProcess) are also included here, rather than
623 * being relegated to a different section.
625 * \subsubsection sec2-3-1-1 Section 2.3.1.1: LWP_InitializeProcessSupport
626 * _ Initialize the LWP
package 629 * int LWP_InitializeProcessSupport(IN int priority; OUT PROCESS *pid)
631 * This
function initializes the LWP package. In addition, it turns the current
632 * thread of control into the initial process with the specified priority. The
633 * process ID of
this initial thread is returned in the pid parameter. This
634 * routine must be called before any other routine in the LWP library. The
635 * scheduler will NOT be invoked as a result of calling
636 * LWP_InitializeProcessSupport().
638 * LWP EBADPRI The given priority is invalid, either negative or too large.
640 * \subsubsection sec2-3-1-2 Section 2.3.1.2: LWP_TerminateProcessSupport
641 * _ End process support, perform cleanup
644 *
int LWP_TerminateProcessSupport()
646 * This routine terminates the LWP threading support and cleans up after it by
647 * freeing any auxiliary storage used. This routine must be called from within
648 * the process that invoked LWP InitializeProcessSupport(). After LWP
649 * TerminateProcessSupport() has been called, it is acceptable to call LWP
650 * InitializeProcessSupport() again in order to restart LWP process support.
652 * ---Always succeeds, or performs an abort().
654 * \subsubsection sec2-3-1-3 Section 2.3.1.3: LWP_CreateProcess _ Create a
658 *
int LWP_CreateProcess(IN
int (*ep)(); IN
int stacksize; IN
int priority; IN
659 *
char *parm; IN
char *name; OUT PROCESS *pid)
661 * This function is used to create a new lightweight process with a given
662 * printable name. The ep argument identifies the function to be used as the
663 * body of the thread. The argument to be passed to this function is contained
664 * in parm. The new thread's stack size in bytes is specified in stacksize, and
665 * its execution priority in priority. The pid parameter is used to return the
666 * process ID of the new thread.
668 * If the thread is successfully created, it will be marked as runnable. The
669 * scheduler is called before the LWP CreateProcess() call completes, so the
670 * new thread may indeed begin its execution before the completion. Note that
671 * the new thread is guaranteed NOT to run before the call completes if the
672 * specified priority is lower than the caller's. On the other hand, if the new
673 * thread's priority is higher than the caller's, then it is guaranteed to run
674 * before the creation call completes.
676 * LWP EBADPRI The given priority is invalid, either negative or too large.
677 * \n LWP NOMEM Could not allocate memory to satisfy the creation request.
679 * \subsubsection sec2-3-1-4 Section: 2.3.1.4: LWP_DestroyProcess _ Create
683 *
int LWP_DestroyProcess(IN PROCESS pid)
685 * This routine destroys the thread identified by pid. It will be terminated
686 * immediately, and its internal storage will be reclaimed. A thread is allowed
687 * to destroy itself. In this case, of course, it will only get to see the
688 * return code if the operation fails. Note that a thread may also destroy
689 * itself by returning from the parent C routine.
691 * The scheduler is called by this operation, which may cause an arbitrary
692 * number of threads to execute before the caller regains the processor.
694 * LWP EINIT The LWP package has not been initialized.
696 * \subsubsection sec2-3-1-5 Section 2.3.1.5: WaitProcess _ Wait on an
700 *
int LWP WaitProcess(IN
char *event)
702 * This routine puts the thread making the call to sleep until another LWP
703 * calls the LWP SignalProcess() or LWP NoYieldSignal() routine with the
704 * specified event. Note that signalled events are not queued. If a signal
705 * occurs and no thread is awakened, the signal is lost. The scheduler is
706 * invoked by the LWP WaitProcess() routine.
708 * LWP EINIT The LWP package has not been initialized.
709 * \n LWP EBADEVENT The given event pointer is null.
711 * \subsubsection sec2-3-1-6 Section 2.3.1.6: MwaitProcess _ Wait on a set
715 *
int LWP MwaitProcess(IN
int wcount; IN
char *evlist[])
717 * This function allows a thread to wait for wcount signals on any of the items
718 * in the given evlist. Any number of signals of a particular event are only
719 * counted once. The evlist is a null-terminated list of events to wait for.
720 * The scheduler will be invoked.
722 * LWP EINIT The LWP package has not been initialized.
723 * \n LWP EBADCOUNT An illegal number of events has been supplied.
725 * \subsubsection sec2-3-1-7 Section 2.3.1.7: SignalProcess _ Signal an
729 *
int LWP SignalProcess(IN
char *event)
731 * This routine causes the given event to be signalled. All threads waiting for
732 * this event (exclusively) will be marked as runnable, and the scheduler will
733 * be invoked. Note that threads waiting on multiple events via LWP
734 * MwaitProcess() may not be marked as runnable. Signals are not queued.
735 * Therefore, if no thread is waiting for the signalled event, the signal will
738 * LWP EINIT The LWP package has not been initialized. LWP EBADEVENT A null
739 * event pointer has been provided. LWP ENOWAIT No thread was waiting on the
742 * \subsubsection sec2-3-1-8 Section 2.3.1.8: NoYieldSignal _ Signal an
743 * event without invoking scheduler
746 *
int LWP NoYieldSignal(IN
char *event)
748 * This function is identical to LWP SignalProcess() except that the scheduler
749 * will not be invoked. Thus, control will remain with the signalling process.
751 * LWP EINIT The LWP package has not been initialized. LWP EBADEVENT A null
752 * event pointer has been provided. LWP ENOWAIT No thread was waiting on the
755 * \subsubsection sec2-3-1-9 Section 2.3.1.9: DispatchProcess _ Yield
756 * control to the scheduler
759 *
int LWP DispatchProcess()
761 * This routine causes the calling thread to yield voluntarily to the LWP
762 * scheduler. If no other thread of appropriate priority is marked as runnable,
763 * the caller will continue its execution.
765 * LWP EINIT The LWP package has not been initialized.
767 * \subsubsection sec2-3-1-10 Section 2.3.1.10: CurrentProcess _ Get the
768 * current thread's ID
771 *
int LWP CurrentProcess(IN PROCESS *pid)
773 * This call places the current lightweight process ID in the pid parameter.
775 * LWP EINIT The LWP package has not been initialized.
777 * \subsubsection sec2-3-1-11 Section 2.3.1.11: ActiveProcess _ Get the
778 * current thread's ID (macro)
781 *
int LWP ActiveProcess()
783 * This macro's value is the current lightweight process ID. It generates a
784 * value identical to that acquired by calling the LWP CurrentProcess()
785 * function described above if the LWP package has been initialized. If no such
786 * initialization has been done, it will return a value of zero.
788 * \subsubsection sec2-3-1-12 Section: 2.3.1.12: StackUsed _ Calculate
792 *
int LWP StackUsed(IN PROCESS pid; OUT
int *max; OUT
int *used)
794 * This function returns the amount of stack space allocated to the thread
795 * whose identifier is pid, and the amount actually used so far. This is
796 * possible if the global variable lwp stackUseEnabled was TRUE when the thread
797 * was created (it is set this way by default). If so, the thread's stack area
798 * was initialized with a special pattern. The memory still stamped with this
799 * pattern can be determined, and thus the amount of stack used can be
800 * calculated. The max parameter is always set to the thread's stack allocation
801 * value, and used is set to the computed stack usage if lwp stackUseEnabled
802 * was set when the process was created, or else zero.
804 * LWP NO STACK Stack usage was not enabled at thread creation time.
806 * \subsubsection sec2-3-1-13 Section 2.3.1.13: NewRock _ Establish
807 * thread-specific storage
810 *
int LWP NewRock (IN
int tag; IN
char **value)
812 * This function establishes a "rock", or thread-specific information,
813 * associating it with the calling LWP. The tag is intended to be any unique
814 * integer value, and the value is a pointer to a character array containing
817 * Users of the LWP package must coordinate their choice of tag values. Note
818 * that a tag's value cannot be changed. Thus, to obtain a mutable data
819 * structure, another level of indirection is required. Up to MAXROCKS (4)
820 * rocks may be associated with any given thread.
822 * ENOROCKS A rock with the given tag field already exists. All of the MAXROCKS
826 * \subsubsection sec2-3-1-14 Section: 2.3.1.14: GetRock _ Retrieve
827 * thread-specific storage
830 *
int LWP GetRock(IN
int tag; OUT **value)
832 * This routine recovers the thread-specific information associated with the
833 * calling process and the given tag, if any. Such a rock had to be established
834 * through a LWP NewRock() call. The rock's value is deposited into value.
836 * LWP EBADROCK A rock has not been associated with the given tag for this
839 * \subsection sec2-3-2 Section 2.3.2: Locking
842 * This section covers the calling interfaces to the locking package. Many of
843 * the user-callable routines are actually implemented as macros.
845 * \subsubsection sec2-3-2-1 Section 2.3.2.1: Lock Init _ Initialize lock
849 *
void Lock Init(IN struct Lock *lock)
851 * This function must be called on the given lock
object before any other
852 * operations can be performed on it.
854 * ---No value is returned.
856 * \subsubsection sec2-3-2-2 Section 2.3.2.2: ObtainReadLock _ Acquire a
860 *
void ObtainReadLock(IN struct Lock *lock)
862 * This macro obtains a read lock on the specified lock
object. Since this is a
863 * macro and not a function call, results are not predictable if the value of
864 * the lock parameter is a side-effect producing expression, as it will be
865 * evaluated multiple times in the course of the macro interpretation.
866 * Read locks are incompatible with write, shared, and boosted shared locks.
868 * ---No value is returned.
870 * \subsubsection sec2-3-2-3 Section 2.3.2.3: ObtainWriteLock _ Acquire a
874 *
void ObtainWriteLock(IN struct Lock *lock)
876 * This macro obtains a write lock on the specified lock
object. Since this is
877 * a macro and not a function call, results are not predictable if the value of
878 * the lock parameter is a side-effect producing expression, as it will be
879 * evaluated multiple times in the course of the macro interpretation.
881 * Write locks are incompatible with all other locks.
883 * ---No value is returned.
885 * \subsubsection sec2-3-2-4 Section 2.3.2.4: ObtainSharedLock _ Acquire a
889 *
void ObtainSharedLock(IN struct Lock *lock)
891 * This macro obtains a shared lock on the specified lock
object. Since this is
892 * a macro and not a function call, results are not predictable if the value of
893 * the lock parameter is a side-effect producing expression, as it will be
894 * evaluated multiple times in the course of the macro interpretation.
896 * Shared locks are incompatible with write and boosted shared locks, but are
897 * compatible with read locks.
899 * ---No value is returned.
901 * \subsubsection sec2-3-2-5 Section 2.3.2.5: ReleaseReadLock _ Release
905 *
void ReleaseReadLock(IN struct Lock *lock)
907 * This macro releases the specified lock. The lock must have been previously
908 * read-locked. Since this is a macro and not a function call, results are not
909 * predictable if the value of the lock parameter is a side-effect producing
910 * expression, as it will be evaluated multiple times in the course of the
911 * macro interpretation. The results are also unpredictable if the lock was not
912 * previously read-locked by the thread calling ReleaseReadLock().
914 * ---No value is returned.
916 * \subsubsection sec2-3-2-6 Section 2.3.2.6: ReleaseWriteLock _ Release
920 *
void ReleaseWriteLock(IN struct Lock *lock)
922 * This macro releases the specified lock. The lock must have been previously
923 * write-locked. Since this is a macro and not a function call, results are not
924 * predictable if the value of the lock parameter is a side-effect producing
925 * expression, as it will be evaluated multiple times in the course of the
926 * macro interpretation. The results are also unpredictable if the lock was not
927 * previously write-locked by the thread calling ReleaseWriteLock().
929 * ---No value is returned.
931 * \subsubsection sec2-3-2-7 Section 2.3.2.7: ReleaseSharedLock _ Release
935 *
void ReleaseSharedLock(IN struct Lock *lock)
937 * This macro releases the specified lock. The lock must have been previously
938 * share-locked. Since this is a macro and not a function call, results are not
939 * predictalbe if the value of the lock parameter is a side-effect producing
940 * expression, as it will be evaluated multiple times in the course of the
941 * macro interpretation. The results are also unpredictable if the lock was not
942 * previously share-locked by the thread calling ReleaseSharedLock().
944 * ---No value is returned.
946 * \subsubsection sec2-3-2-8 Section 2.3.2.8: CheckLock _ Determine state
950 *
void CheckLock(IN struct Lock *lock)
952 * This macro produces an integer that specifies the status of the indicated
953 * lock. The value will be -1 if the lock is write-locked, 0 if unlocked, or
954 * otherwise a positive integer that indicates the number of readers (threads
955 * holding read locks). Since this is a macro and not a function call, results
956 * are not predictable if the value of the lock parameter is a side-effect
957 * producing expression, as it will be evaluated multiple times in the course
958 * of the macro interpretation.
960 * ---No value is returned.
962 * \subsubsection sec2-3-2-9 Section 2.3.2.9: BoostLock _ Boost a shared
966 *
void BoostLock(IN struct Lock *lock)
968 * This macro promotes ("boosts") a shared lock into a write lock. Such a boost
969 * operation guarantees that no other writer can get into the critical section
970 * in the process. Since this is a macro and not a function call, results are
971 * not predictable if the value of the lock parameter is a side-effect
972 * producing expression, as it will be evaluated multiple times in the course
973 * of the macro interpretation.
975 * ---No value is returned.
977 * \subsubsection sec2-3-2-10 Section 2.3.2.10: UnboostLock _ Unboost a
981 *
void UnboostLock(IN struct Lock *lock)
983 * This macro demotes a boosted shared lock back down into a regular shared
984 * lock. Such an unboost operation guarantees that no other writer can get into
985 * the critical section in the process. Since this is a macro and not a
986 * function call, results are not predictable if the value of the lock
987 * parameter is a side-effect producing expression, as it will be evaluated
988 * multiple times in the course of the macro interpretation.
990 * ---No value is returned.
992 * \subsection sec2-3-3 Section 2.3.3: IOMGR
995 * This section covers the calling interfaces to the I/O management package.
997 * \subsubsection sec2-3-3-1 Section: 2.3.3.1: IOMGR Initialize _
998 * Initialize the package
1001 *
int IOMGR Initialize()
1003 * This function initializes the IOMGR package. Its main task is to create the
1004 * IOMGR thread itself, which runs at the lowest possible priority (0). The
1005 * remainder of the lightweight processes must be running at priority 1 or
1006 * greater (up to a maximum of LWP MAX PRIORITY (4)) for the IOMGR package to
1007 * function correctly.
1009 * -1 The LWP and/or timer package haven't been initialized.
1010 * \n <misc> Any errors that may be returned by the LWP CreateProcess()
1013 * \subsubsection sec2-3-3-2 Section 2.3.3.2: IOMGR finalize _ Clean up
1014 * the IOMGR facility
1017 *
int IOMGR finalize()
1019 * This routine cleans up after the IOMGR package when it is no longer needed.
1020 * It releases all storage and destroys the IOMGR thread itself.
1022 * <misc> Any errors that may be returned by the LWP DestroyProcess() routine.
1024 * \subsubsection sec2-3-3-3 Section 2.3.3.3: IOMGR Select _ Perform a
1025 * thread-level select()
1028 *
int IOMGR Select (IN
int numfds; IN
int *rfds; IN
int *wfds; IN
int *xfds;
1029 * IN truct timeval *timeout)
1031 * This routine performs an LWP version of unix select() operation. The
1032 * parameters have the same meanings as with the unix call. However, the return
1033 * values will be simplified (see below). If this is a polling select (i.e.,
1034 * the value of timeout is null), it is done and the IOMGR Select() function
1035 * returns to the user with the results. Otherwise, the calling thread is put
1036 * to sleep. If at some point the IOMGR thread is the only runnable process, it
1037 * will awaken and collect all select requests. The IOMGR will then perform a
1038 * single select and awaken the appropriate processes. This will force a return
1039 * from the affected IOMGR Select() calls.
1041 * -1 An error occurred.
1042 * \n 0 A timeout occurred.
1043 * \n 1 Some number of file descriptors are ready.
1045 * \subsubsection sec2-3-3-4 Section 2.3.3.4: IOMGR Signal _ Associate
1046 * unix and LWP signals
1049 *
int IOMGR Signal(IN
int signo; IN
char *event)
1051 * This function associates an LWP signal with a unix signal. After this call,
1052 * when the given unix signal signo is delivered to the (heavyweight unix)
1053 * process, the IOMGR thread will deliver an LWP signal to the event via LWP
1054 * NoYieldSignal(). This wakes up any lightweight processes waiting on the
1055 * event. Multiple deliveries of the signal may be coalesced into one LWP
1056 * wakeup. The call to LWP NoYieldSignal() will happen synchronously. It is
1057 * safe for an LWP to check for some condition and then go to sleep waiting for
1058 * a unix signal without having to worry about delivery of the signal happening
1059 * between the check and the call to LWP WaitProcess().
1061 * LWP EBADSIG The signo value is out of range.
1062 * \n LWP EBADEVENT The event pointer is null.
1064 * \subsubsection sec2-3-3-5 Section 2.3.3.5: IOMGR CancelSignal _ Cancel
1065 * unix and LWP signal association
1068 *
int IOMGR CancelSignal(IN
int signo)
1070 * This routine cancels the association between a unix signal and an LWP event.
1071 * After calling this function, the unix signal signo will be handled however
1072 * it was handled before the corresponding call to IOMGR Signal().
1074 * LWP EBADSIG The signo value is out of range.
1076 * \subsubsection sec2-3-3-6 Section 2.3.3.6: IOMGR Sleep _ Sleep for a
1080 *
void IOMGR Sleep(IN
unsigned seconds)
1082 * This function calls IOMGR Select() with zero file descriptors and a timeout
1083 * structure set up to cause the thread to sleep for the given number of
1086 * ---No value is returned.
1088 * \subsection sec2-3-4 Section 2.3.4: Timer
1091 * This section covers the calling interface to the timer package associated
1092 * with the LWP facility.
1094 * \subsubsection sec2-3-4-1 Section 2.3.4.1: TM Init _ Initialize a timer
1098 *
int TM Init(IN struct TM Elem **list)
1100 * This function causes the specified timer list to be initialized. TM Init()
1101 * must be called before any other timer operations are applied to the list.
1103 * -1 A null timer list could not be produced.
1105 * \subsubsection sec2-3-4-2 Section 2.3.4.2: TM final _ Clean up a timer
1109 *
int TM final(IN struct TM Elem **list)
1111 * This routine is called when the given empty timer list is no longer needed.
1112 * All storage associated with the list is released.
1114 * -1 The list parameter is invalid.
1116 * \subsubsection sec2-3-4-3 Section 2.3.4.3: TM Insert _ Insert an
object 1120 *
void TM Insert(IN struct TM Elem **list; IN struct TM Elem *elem)
1122 * This routine enters an new element, elem, into the list denoted by list.
1123 * Before the new element is queued, its TimeLeft field (the amount of time
1124 * before the
object comes due) is set to the value stored in its TotalTime
1125 * field. In order to keep TimeLeft fields current, the TM Rescan() function
1128 * ---No return value is generated.
1130 * \subsubsection sec2-3-4-4 Section 2.3.4.4: TM Rescan _ Update all
1131 * timers in the list
1134 *
int TM Rescan(IN struct TM Elem *list)
1136 * This function updates the TimeLeft fields of all timers on the given list.
1137 * This is done by checking the time-of-day clock. Note: this is the only
1138 * routine other than TM Init() that updates the TimeLeft field in the elements
1141 * Instead of returning a value indicating success or failure, TM Rescan()
1142 * returns the number of entries that were discovered to have timed out.
1144 * ---Instead of error codes, the number of entries that were discovered to
1145 * have timed out is returned.
1147 * \subsubsection sec2-3-4-5 Section 2.3.4.5: TM GetExpired _ Returns an
1151 * struct TM Elem *TM GetExpired(IN struct TM Elem *list)
1153 * This routine searches the specified timer list and returns a pointer to an
1154 * expired timer element from that list. An expired timer is one whose TimeLeft
1155 * field is less than or equal to zero. If there are no expired timers, a null
1156 * element pointer is returned.
1158 * ---Instead of error codes, an expired timer pointer is returned, or a null
1159 * timer pointer if there are no expired timer objects.
1161 * \subsubsection sec2-3-4-6 Section 2.3.4.6: TM GetEarliest _ Returns
1162 * earliest unexpired timer
1165 * struct TM Elem *TM GetEarliest(IN struct TM Elem *list)
1167 * This function returns a pointer to the timer element that will be next to
1168 * expire on the given list. This is defined to be the timer element with the
1169 * smallest (positive) TimeLeft field. If there are no timers on the list, or
1170 * if they are all expired, this function will return a null pointer.
1172 * ---Instead of error codes, a pointer to the next timer element to expireis
1173 * returned, or a null timer
object pointer if they are all expired.
1175 * \subsubsection sec2-3-4-7 Section 2.3.4.7: TM eql _ Test for equality
1179 *
bool TM eql(IN struct timemval *t1; IN struct timemval *t2)
1181 * This function compares the given timestamps, t1 and t2, for equality. Note
1182 * that the function return value,
bool, has been set via typedef to be
1183 * equivalent to
unsigned char.
1185 * 0 If the two timestamps differ.
1186 * \n 1 If the two timestamps are identical.
1188 * \subsection sec2-3-5 Section 2.3.5: Fast Time
1190 * This section covers the calling interface to the fast time package
1191 * associated with the LWP facility.
1193 * \subsubsection sec2-3-5-1 Section 2.3.5.1: FT Init _ Initialize the
1197 *
int FT Init(IN
int printErrors; IN
int notReally)
1199 * This routine initializes the fast time package, mapping in the kernel page
1200 * containing the time-of-day variable. The printErrors argument, if non-zero,
1201 * will cause any errors in initalization to be printed to stderr. The
1202 * notReally parameter specifies whether initialization is really to be done.
1203 * Other calls in this package will do auto-initialization, and hence the
1204 * option is offered here.
1206 * -1 Indicates that future calls to FT GetTimeOfDay() will still work, but
1207 * will not be able to access the information directly, having to make a
1208 * kernel call every time.
1210 * \subsubsection sec2-3-5-2 Section 2.3.5.2: FT GetTimeOfDay _ Initialize
1211 * the fast time package
1214 *
int FT GetTimeOfDay(IN struct timeval *tv; IN struct timezone *tz)
1216 * This routine is meant to mimic the parameters and behavior of the unix
1217 * gettimeofday() function. However, as implemented, it simply calls
1218 * gettimeofday() and then does some bound-checking to make sure the value is
1221 * <misc> Whatever value was returned by gettimeofday() internally.
1223 * \subsection sec2-3-6 Section 2.3.6: Preemption
1225 * This section covers the calling interface to the preemption package
1226 * associated with the LWP facility.
1228 * \subsubsection sec2-3-6-1 Section 2.3.6.1: PRE InitPreempt _ Initialize
1229 * the preemption package
1232 *
int PRE InitPreempt(IN struct timeval *slice)
1234 * This function must be called to initialize the preemption package. It must
1235 * appear sometime after the call to LWP InitializeProcessSupport() and
1236 * sometime before the first call to any other preemption routine. The slice
1237 * argument specifies the time slice size to use. If the slice pointer is set
1238 * to null in the call, then the default time slice, DEFAULTSLICE (10
1239 * milliseconds), will be used. This routine uses the unix interval timer and
1240 * handling of the unix alarm signal, SIGALRM, to implement this timeslicing.
1242 * LWP EINIT The LWP package hasn't been initialized.
1243 * \n LWP ESYSTEM Operations on the signal vector or the interval timer have
1246 * \subsubsection sec2-3-6-2 Section 2.3.6.2: PRE EndPreempt _ finalize
1247 * the preemption package
1250 *
int PRE EndPreempt()
1252 * This routine finalizes use of the preemption package. No further preemptions
1253 * will be made. Note that it is not necessary to make this call before exit.
1254 * PRE EndPreempt() is provided only for those applications that wish to
1255 * continue after turning off preemption.
1257 * LWP EINIT The LWP package hasn't been initialized.
1258 * \n LWP ESYSTEM Operations on the signal vector or the interval timer have
1261 * \subsubsection sec2-3-6-3 Section 2.3.6.3: PRE PreemptMe _ Mark thread
1265 *
int PRE PreemptMe()
1267 * This macro is used to signify the current thread as a candidate for
1268 * preemption. The LWP InitializeProcessSupport() routine must have been called
1269 * before PRE PreemptMe().
1271 * ---No return code is generated.
1273 * \subsubsection sec2-3-6-4 Section 2.3.6.4: PRE BeginCritical _ Enter
1274 * thread critical section
1277 *
int PRE BeginCritical()
1279 * This macro places the current thread in a critical section. Upon return, and
1280 * for as
long as the thread is in the critical section, involuntary
1281 * preemptions of this LWP will no longer occur.
1283 * ---No return code is generated.
1285 * \subsubsection sec2-3-6-5 Section 2.3.6.5: PRE EndCritical _ Exit
1286 * thread critical section
1289 *
int PRE EndCritical()
1291 * This macro causes the executing thread to leave a critical section
1292 * previously entered via PRE BeginCritical(). If involuntary preemptions were
1293 * possible before the matching PRE BeginCritical(), they are once again
1296 * ---No return code is generated.
1298 * \page chap3 Chapter 3 -- Rxkad
1301 * \section sec3-1 Section 3.1: Introduction
1304 * The rxkad security module is offered as one of the built-in Rx
1305 * authentication models. It is based on the Kerberos system developed by MIT's
1306 * Project Athena. Readers wishing detailed information regarding Kerberos
1307 * design and implementation are directed to [2]. This chapter is devoted to
1308 * defining how Kerberos authentication services are made available as Rx
1309 * components, and assumes the reader has some familiarity with Kerberos.
1310 * Included are descriptions of how client-side and server-side Rx security
1311 * objects (struct rx securityClass; see Section 5.3.1.1) implementing this
1312 * protocol may be generated by an Rx application. Also, a description appears
1313 * of the set of routines available in the associated struct rx securityOps
1314 * structures, as covered in Section 5.3.1.2. It is strongly recommended that
1315 * the reader become familiar with this section on struct rx securityOps before
1318 * \section sec3-2 Section 3.2: Definitions
1321 * An important set of definitions related to the rxkad security package is
1322 * provided by the rxkad.h include file. Determined here are various values for
1323 * ticket lifetimes, along with structures for encryption keys and Kerberos
1324 * principals. Declarations for the two routines required to generate the
1325 * different rxkad security objects also appear here. The two functions are
1326 * named rxkad NewServerSecurityObject() and rxkad NewClientSecurityObject().
1327 * In addition, type field values, encryption levels, security index
1328 * operations, and statistics structures may be found in this file.
1329 * \section sec3-3 Section 3.3: Exported Objects
1331 * To be usable as an Rx security module, the rxkad facility exports routines
1332 * to create server-side and client-side security objects. The server
1333 * authentication
object is incorporated into the server code when calling rx
1334 * NewService(). The client authentication
object is incorporated into the
1335 * client code every time a connection is established via rx NewConnection().
1336 * Also, in order to implement these security objects, the rxkad module must
1337 * provide definitions for some subset of the generic security operations as
1338 * defined in the appropriate struct rx securityOps variable.
1340 * \subsection sec3-3-1 Section 3.3.1: Server-Side Mechanisms
1342 * \subsubsection sec3-3-1-1 Section 3.3.1.1: Security Operations
1345 * The server side of the rxkad module fills in all but two of the possible
1346 * routines associated with an Rx security
object, as described in Section
1350 * static struct rx_securityOps rxkad_server_ops = {
1352 * rxkad_NewConnection,
1353 * rxkad_PreparePacket,
1355 * rxkad_CheckAuthentication,
1356 * rxkad_CreateChallenge,
1357 * rxkad_GetChallenge,
1359 * rxkad_CheckResponse,
1360 * rxkad_DestroyConnection,
1366 * The rxkad service does not need to take any special action each time a
1367 * packet belonging to a call in an rxkad Rx connection is physically
1368 * transmitted. Thus, a routine is not supplied
for the op SendPacket()
1369 *
function slot. Similarly, no preparatory work needs to be done previous to
1370 * the reception of a response packet from a security challenge, so the op
1371 * GetResponse() function slot is also empty.
1373 * \subsubsection sec3-3-1-2 Section 3.3.1.2: Security Object
1376 * The exported routine used to generate an rxkad-specific server-side security
1377 * class
object is named rxdad NewServerSecurityObject(). It is declared with
1378 * four parameters, as follows:
1381 * struct rx_securityClass *
1382 * rxkad_NewServerSecurityObject(a_level, a_getKeyRockP, a_getKeyP, a_userOKP)
1383 * rxkad_level a_level;
1384 *
char *a_getKeyRockP;
1385 *
int (*a_getKeyP)();
1386 *
int (*a_userOKP)();
1390 * The first argument specifies the desired level of encryption, and may take
1391 * on the following values (as defined in rxkad.h):
1392 * \li rxkad clear: Specifies that packets are to be sent entirely in the
1393 * clear, without any encryption whatsoever.
1394 * \li rxkad auth: Specifies that packet sequence numbers are to be encrypted.
1395 * \li rxkad crypt: Specifies that the entire data packet is to be encrypted.
1398 * The second and third parameters represent, respectively, a pointer to a
1399 * private data area, sometimes called a "rock", and a procedure reference that
1400 * is called with the key version number accompanying the Kerberos ticket and
1401 * returns a pointer to the server's decryption key. The fourth argument, if
1402 * not null, is a pointer to a function that will be called for every new
1403 * connection with the client's name, instance, and cell. This routine should
1404 * return zero if the user is not acceptable to the server.
1406 * \subsection sec3-3-2 Section 3.3.2: Client-Side Mechanisms
1408 * \subsubsection sec3-3-2-1 Section 3.3.2.1: Security Operations
1411 * The client side of the rxkad module fills in relatively few of the routines
1412 * associated with an Rx security
object, as demonstrated below. The general Rx
1413 * security
object, of which this is an instance, is described in detail in
1417 * static struct rx_securityOps rxkad_client_ops = {
1419 * rxkad_NewConnection,
1420 * rxkad_PreparePacket,
1425 * rxkad_GetResponse,
1427 * rxkad_CheckPacket,
1428 * rxkad_DestroyConnection,
1437 * As expected, routines are defined
for use when someone destroys a security
1438 * object (rxkad Close()) and when an Rx connection using the rxkad model
1439 * creates a new connection (rxkad NewConnection()) or deletes an existing one
1440 * (rxkad DestroyConnection()). Security-specific operations must also be
1441 * performed in behalf of rxkad when packets are created (rxkad
1442 * PreparePacket()) and received (rxkad CheckPacket()). finally, the client
1443 * side of an rxkad security
object must also be capable of constructing
1444 * responses to security challenges from the server (rxkad GetResponse()) and
1445 * be willing to reveal statistics on its own operation (rxkad GetStats()).
1447 * \subsubsection sec3-3-2-2 Section 3.3.2.2: Security Object
1450 * The exported routine used to generate an rxkad-specific client-side security
1451 * class
object is named rxkad NewClientSecurityObject(). It is declared with
1452 * five parameters, specified below:
1455 * struct rx_securityClass * rxkad_NewClientSecurityObject(
1462 * rxkad_level a_level;
1463 * struct ktc_encryptionKey *a_sessionKeyP;
1470 * The first parameter, a level, specifies the level of encryption desired for
1471 * this security
object, with legal choices being identical to those defined
1472 * for the server-side security
object described in Section 3.3.1.2. The second
1473 * parameter, a sessionKeyP, provides the session key to use. The ktc
1474 * encryptionKey structure is defined in the rxkad.h include file, and consists
1475 * of an array of 8 characters. The third parameter, a kvno, provides the key
1476 * version number associated with a sessionKeyP. The fourth argument, a
1477 * ticketLen, communicates the length in bytes of the data stored in the fifth
1478 * parameter, a ticketP, which points to the Kerberos ticket to use for the
1479 * principal for which the security
object will operate.
1481 * \page chap4 Chapter 4 -- Rx Support Packages
1483 * \section sec4-1 Section 4.1: Introduction
1485 * This chapter documents three packages defined directly in support of the Rx
1487 * \li rx queue: Doubly-linked queue package.
1488 * \li rx clock: Clock package, using the 4.3BSD interval timer.
1489 * \li rx event: Future events package.
1491 * References to constants, structures, and functions defined by these support
1492 * packages will appear in the following API chapter.
1494 * \section sec4-2 Section 4.2: The rx queue Package
1497 * This package provides a doubly-linked queue structure, along with a full
1498 * suite of related operations. The main concern behind the coding of this
1499 * facility was efficiency. All functions are implemented as macros, and it is
1500 * suggested that only simple expressions be used for all parameters.
1502 * The rx queue facility is defined by the rx queue.h include file. Some macros
1503 * visible in this file are intended for rx queue internal use only. An
1504 * understanding of these "hidden" macros is important, so they will also be
1505 * described by this document.
1507 * \subsection sec4-2-1 Section 4.2.1: struct queue
1510 * The queue structure provides the linkage information required to maintain a
1511 * queue of objects. The queue structure is prepended to any user-defined data
1512 * type which is to be organized in this fashion.
1514 * \li struct queue *prev - Pointer to the previous queue header.
1515 * \li struct queue *next - Pointer to the next queue header.
1517 * Note that a null Rx queue consists of a single struct queue
object whose
1518 * next and previous pointers refer to itself.
1520 * \subsection sec4-2-2 Section 4.2.2: Internal Operations
1523 * This section describes the internal operations defined for Rx queues. They
1524 * will be referenced by the external operations documented in Section 4.2.3.
1526 * \subsection sec4-2-2-1 Section 4.2.2.1: Q(): Coerce type to a queue
1530 * \
#define _Q(x) ((struct queue *)(x)) 1532 * This operation coerces the user structure named by x to a queue element. Any
1533 * user structure
using the rx queue
package must have a struct queue as its
1536 * \subsubsection sec4-2-2-2 Section 4.2.2.2: QA(): Add a queue element
1537 * before/after another element
1540 * \#define _QA(q,i,a,b) (((i->a=q->a)->b=i)->b=q, q->a=i)
1542 * This operation adds the queue element referenced by i either before or after
1543 * a queue element represented by q. If the (a, b) argument pair corresponds to
1544 * an element's (next, prev) fields, the new element at i will be linked after
1545 * q. If the (a, b) argument pair corresponds to an element's (prev, next)
1546 * fields, the new element at i will be linked before q.
1548 * \subsubsection sec4-2-2-3 QR(): Remove a queue element
1551 * \#define _QR(i) ((_Q(i)->prev->next=_Q(i)->next)->prev=_Q(i)->prev)
1553 * This operation removes the queue element referenced by i from its queue. The
1554 * prev and next fields within queue element i itself is not updated to reflect
1555 * the fact that it is no longer part of the queue.
1557 * \subsubsection sec4-2-2-4 QS(): Splice two queues together
1560 * \#define _QS(q1,q2,a,b) if (queue_IsEmpty(q2));
else 1561 * ((((q2->a->b=q1)->a->b=q2->b)->a=q1->a, q1->a=q2->a), queue_Init(q2))
1563 * This operation takes the queues identified by q1 and q2 and splices them
1564 * together into a single queue. The order in which the two queues are appended
1565 * is determined by the a and b arguments. If the (a, b) argument pair
1566 * corresponds to q1
's (next, prev) fields, then q2 is appended to q1. If the 1567 * (a, b) argument pair corresponds to q1's (prev, next) fields, then q is
1570 * This
internal QS() routine uses two exported queue operations, namely queue
1571 * Init() and queue IsEmpty(), defined in Sections 4.2.3.1 and 4.2.3.16
1572 * respectively below.
1574 * \subsection sec4-2-3 Section 4.2.3: External Operations
1576 * \subsubsection sec4-2-3-1 Section 4.2.3.1: queue Init(): Initialize a
1580 * \
#define queue_Init(q) (_Q(q))->prev = (_Q(q))->next = (_Q(q)) 1582 * The queue header referred to by the q argument is initialized so that it
1583 * describes a null (empty) queue. A queue head is simply a queue element.
1585 * \subsubsection sec4-2-3-2 Section 4.2.3.2: queue Prepend(): Put element
1586 * at the head of a queue
1589 * \#define queue_Prepend(q,i) _QA(_Q(q),_Q(i),next,prev)
1591 * Place queue element i at the head of the queue denoted by q. The new queue
1592 * element, i, should not currently be on any queue.
1594 * \subsubsection sec4-2-3-3 Section 4.2.3.3: queue Append(): Put an
1595 * element a the tail of a queue
1598 * \#define queue_Append(q,i) _QA(_Q(q),_Q(i),prev,next)
1600 * Place queue element i at the tail of the queue denoted by q. The new queue
1601 * element, i, should not currently be on any queue.
1603 * \subsection sec4-2-3-4 Section 4.2.3.4: queue InsertBefore(): Insert a
1604 * queue element before another element
1607 * \#define queue_InsertBefore(i1,i2) _QA(_Q(i1),_Q(i2),prev,next)
1609 * Insert queue element i2 before element i1 in i1
's queue. The new queue 1610 * element, i2, should not currently be on any queue. 1612 * \subsubsection sec4-2-3-5 Section 4.2.3.5: queue InsertAfter(): Insert 1613 * a queue element after another element 1616 * \#define queue_InsertAfter(i1,i2) _QA(_Q(i1),_Q(i2),next,prev) 1618 * Insert queue element i2 after element i1 in i1's queue. The new queue
1619 * element, i2, should not currently be on any queue.
1621 * \subsubsection sec4-2-3-6 Section: 4.2.3.6: queue SplicePrepend():
1622 * Splice one queue before another
1625 * \#define queue_SplicePrepend(q1,q2) _QS(_Q(q1),_Q(q2),next,prev)
1627 * Splice the members of the queue located at q2 to the beginning of the queue
1628 * located at q1, reinitializing queue q2.
1630 * \subsubsection sec4-2-3-7 Section 4.2.3.7: queue SpliceAppend(): Splice
1631 * one queue after another
1634 * \#define queue_SpliceAppend(q1,q2) _QS(_Q(q1),_Q(q2),prev,next)
1636 * Splice the members of the queue located at q2 to the end of the queue
1637 * located at q1, reinitializing queue q2. Note that the implementation of
1638 * queue SpliceAppend() is identical to that of queue SplicePrepend() except
1639 * for the order of the next and prev arguments to the internal queue splicer,
1642 * \subsubsection sec4-2-3-8 Section 4.2.3.8: queue Replace(): Replace the
1643 * contents of a queue with that of another
1646 * \#define queue_Replace(q1,q2) (*_Q(q1) = *_Q(q2),
1647 * \n _Q(q1)->next->prev = _Q(q1)->prev->next = _Q(q1),
1648 * \n queue_Init(q2))
1650 * Replace the contents of the queue located at q1 with the contents of the
1651 * queue located at q2. The prev and next fields from q2 are copied into the
1652 * queue object referenced by q1, and the appropriate element pointers are
1653 * reassigned. After the replacement has occurred, the queue header at q2 is
1656 * \subsubsection sec4-2-3-9 Section 4.2.3.9: queue Remove(): Remove an
1657 * element from its queue
1660 * \#define queue_Remove(i) (_QR(i), _Q(i)->next = 0)
1662 * This function removes the queue element located at i from its queue. The
1663 * next field for the removed entry is zeroed. Note that multiple removals of
1664 * the same queue item are not supported.
1666 * \subsubsection sec4-2-3-10 Section 4.2.3.10: queue MoveAppend(): Move
1667 * an element from its queue to the end of another queue
1670 * \#define queue_MoveAppend(q,i) (_QR(i), queue_Append(q,i))
1672 * This macro removes the queue element located at i from its current queue.
1673 * Once removed, the element at i is appended to the end of the queue located
1676 * \subsubsection sec4-2-3-11 Section 4.2.3.11: queue MovePrepend(): Move
1677 * an element from its queue to the head of another queue
1680 * \#define queue_MovePrepend(q,i) (_QR(i), queue_Prepend(q,i))
1682 * This macro removes the queue element located at i from its current queue.
1683 * Once removed, the element at i is inserted at the head fo the queue located
1686 * \subsubsection sec4-2-3-12 Section 4.2.3.12: queue first(): Return the
1687 * first element of a queue, coerced to a particular type
1690 * \#define queue_first(q,s) ((struct s *)_Q(q)->next)
1692 * Return a pointer to the first element of the queue located at q. The
1693 * returned pointer value is coerced to conform to the given s structure. Note
1694 * that a properly coerced pointer to the queue head is returned if q is empty.
1696 * \subsubsection sec4-2-3-13 Section 4.2.3.13: queue Last(): Return the
1697 * last element of a queue, coerced to a particular type
1700 * \#define queue_Last(q,s) ((struct s *)_Q(q)->prev)
1702 * Return a pointer to the last element of the queue located at q. The returned
1703 * pointer value is coerced to conform to the given s structure. Note that a
1704 * properly coerced pointer to the queue head is returned if q is empty.
1706 * \subsubsection sec4-2-3-14 Section 4.2.3.14: queue Next(): Return the
1707 * next element of a queue, coerced to a particular type
1710 * \#define queue_Next(i,s) ((struct s *)_Q(i)->next)
1712 * Return a pointer to the queue element occuring after the element located at
1713 * i. The returned pointer value is coerced to conform to the given s
1714 * structure. Note that a properly coerced pointer to the queue head is
1715 * returned if item i is the last in its queue.
1717 * \subsubsection sec4-2-3-15 Section 4.2.3.15: queue Prev(): Return the
1718 * next element of a queue, coerced to a particular type
1721 * \#define queue_Prev(i,s) ((struct s *)_Q(i)->prev)
1723 * Return a pointer to the queue element occuring before the element located at
1724 * i. The returned pointer value is coerced to conform to the given s
1725 * structure. Note that a properly coerced pointer to the queue head is
1726 * returned if item i is the first in its queue.
1728 * \subsubsection sec4-2-3-16 Section 4.2.3.16: queue IsEmpty(): Is the
1729 * given queue empty?
1732 * \#define queue_IsEmpty(q) (_Q(q)->next == _Q(q))
1734 * Return a non-zero value if the queue located at q does not have any elements
1735 * in it. In this case, the queue consists solely of the queue header at q
1736 * whose next and prev fields reference itself.
1738 * \subsubsection sec4-2-3-17 Section 4.2.3.17: queue IsNotEmpty(): Is the
1739 * given queue not empty?
1742 * \#define queue_IsNotEmpty(q) (_Q(q)->next != _Q(q))
1744 * Return a non-zero value if the queue located at q has at least one element
1745 * in it other than the queue header itself.
1747 * \subsubsection sec4-2-3-18 Section 4.2.3.18: queue IsOnQueue(): Is an
1748 * element currently queued?
1751 * \#define queue_IsOnQueue(i) (_Q(i)->next != 0)
1753 * This macro returns a non-zero value if the queue item located at i is
1754 * currently a member of a queue. This is determined by examining its next
1755 * field. If it is non-null, the element is considered to be queued. Note that
1756 * any element operated on by queue Remove() (Section 4.2.3.9) will have had
1757 * its next field zeroed. Hence, it would cause a non-zero return from this
1760 * \subsubsection sec4-2-3-19 Section 4.2.3.19: queue Isfirst(): Is an
1761 * element the first on a queue?
1764 * \#define queue_Isfirst(q,i) (_Q(q)->first == _Q(i))
1766 * This macro returns a non-zero value if the queue item located at i is the
1767 * first element in the queue denoted by q.
1769 * \subsubsection sec4-2-3-20 Section 4.2.3.20: queue IsLast(): Is an
1770 * element the last on a queue?
1773 * \#define queue_IsLast(q,i) (_Q(q)->prev == _Q(i))
1775 * This macro returns a non-zero value if the queue item located at i is the
1776 * last element in the queue denoted by q.
1778 * \subsubsection sec4-2-3-21 Section 4.2.3.21: queue IsEnd(): Is an
1779 * element the end of a queue?
1782 * \#define queue_IsEnd(q,i) (_Q(q) == _Q(i))
1784 * This macro returns a non-zero value if the queue item located at i is the
1785 * end of the queue located at q. Basically, it determines whether a queue
1786 * element in question is also the queue header structure itself, and thus does
1787 * not represent an actual queue element. This function is useful for
1788 * terminating an iterative sweep through a queue, identifying when the search
1789 * has wrapped to the queue header.
1791 * \subsubsection sec4-2-3-22 Section 4.2.3.22: queue Scan(): for loop
1792 * test for scanning a queue in a forward direction
1795 * \#define queue_Scan(q, qe, next, s)
1796 * \n (qe) = queue_first(q, s), next = queue_Next(qe, s);
1797 * \n !queue_IsEnd(q, qe);
1798 * \n (qe) = (next), next = queue_Next(qe, s)
1800 * This macro may be used as the body of a
for loop test intended to scan
1801 * through each element in the queue located at q. The qe argument is used as
1802 * the
for loop variable. The next argument is used to store the next value
for 1803 * qe in the upcoming loop iteration. The s argument provides the name of the
1804 * structure to which each queue element is to be coerced. Thus, the values
1805 * provided
for the qe and next arguments must be of type (
struct s *).
1807 * An example of how queue Scan() may be used appears in the code fragment
1808 * below. It declares a structure named mystruct, which is suitable for
1809 * queueing. This queueable structure is composed of the queue pointers
1810 * themselves followed by an integer value. The actual queue header is kept in
1811 * demoQueue, and the currItemP and nextItemP variables are used to step
1812 * through the demoQueue. The queue Scan() macro is used in the for loop to
1813 * generate references in currItemP to each queue element in turn for each
1814 * iteration. The loop is used to increment every queued structure's myval
1822 *
struct queue demoQueue;
1823 *
struct mystruct *currItemP, *nextItemP;
1825 *
for (queue_Scan(&demoQueue, currItemP, nextItemP, mystruct)) {
1826 * currItemP->myval++;
1831 * Note that extra initializers can be added before the body of the queue
1832 * Scan() invocation above, and extra expressions can be added afterwards.
1834 * \subsubsection sec4-2-3-23 Section 4.2.3.23: queue ScanBackwards(): for
1835 * loop test for scanning a queue in a reverse direction
1838 *
#define queue_ScanBackwards(q, qe, prev, s) 1839 * \n (qe) = queue_Last(q, s), prev = queue_Prev(qe, s);
1840 * \n !queue_IsEnd(q, qe);
1841 * \n (qe) = prev, prev = queue_Prev(qe, s)
1843 * This macro is identical to the queue Scan() macro described above in Section
1844 * 4.2.3.22 except for the fact that the given queue is scanned backwards,
1845 * starting at the last item in the queue.
1847 * \section sec4-3 Section 4.3: The rx clock Package
1850 * This package maintains a clock which is independent of the time of day. It
1851 * uses the unix 4.3BSD interval timer (e.g., getitimer(), setitimer()) in
1852 * TIMER REAL mode. Its definition and interface may be found in the rx clock.h
1855 * \subsection sec4-3-1 Section 4.3.1: struct clock
1858 * This structure is used to represent a clock value as understood by this
1859 * package. It consists of two fields, storing the number of seconds and
1860 * microseconds that have elapsed since the associated clock Init() routine has
1864 * \n
long sec -Seconds since call to clock Init().
1865 * \n
long usec -Microseconds since call to clock Init().
1867 * \subsection sec4-3-2 Section 4.3.12: clock nUpdates
1870 * The integer-valued clock nUpdates is a variable exported by the rx clock
1871 * facility. It records the number of times the clock value is actually
1872 * updated. It is bumped each time the clock UpdateTime() routine is called, as
1873 * described in Section 4.3.3.2.
1875 * \subsection sec4-3-3 Section 4.3.3: Operations
1877 * \subsubsection sec4-3-3-1 Section 4.3.3.1: clock Init(): Initialize the
1881 * This routine uses the unix setitimer() call to initialize the unix interval
1882 * timer. If the setitimer() call fails, an error message will appear on
1883 * stderr, and an exit(1) will be executed.
1885 * \subsubsection sec4-3-3-2 Section 4.3.3.2: clock UpdateTime(): Compute
1889 * The clock UpdateTime() function calls the unix getitimer() routine in order
1890 * to update the current time. The exported clock nUpdates variable is
1891 * incremented each time the clock UpdateTime() routine is called.
1893 * \subsubsection sec4-3-3-3 Section 4.3.3.3: clock GetTime(): Return the
1894 * current clock time
1897 * This macro updates the current time if necessary, and returns the current
1898 * time into the cv argument, which is declared to be of type (struct clock *).
1899 * 4.3.3.4 clock Sec(): Get the current clock time, truncated to seconds
1900 * This macro returns the
long value of the sec field of the current time. The
1901 * recorded time is updated if necessary before the above value is returned.
1903 * \subsubsection sec4-3-3-5 Section 4.3.3.5: clock ElapsedTime(): Measure
1904 * milliseconds between two given clock values
1907 * This macro returns the elapsed time in milliseconds between the two clock
1908 * structure pointers provided as arguments, cv1 and cv2.
1910 * \subsubsection sec4-3-3-6 Section 4.3.3.6: clock Advance(): Advance the
1911 * recorded clock time by a specified clock value
1914 * This macro takes a single (struct clock *) pointer argument, cv, and adds
1915 * this clock value to the internal clock value maintined by the package.
1917 * \subsubsection sec4-3-3-7 Section 4.3.3.7: clock Gt(): Is a clock value
1918 * greater than another?
1921 * This macro takes two parameters of type (struct clock *), a and b. It
1922 * returns a nonzero value if the a parameter points to a clock value which is
1923 * later than the one pointed to by b.
1925 * \subsubsection sec4-3-3-8 Section 4.3.3.8: clock Ge(): Is a clock value
1926 * greater than or equal to another?
1929 * This macro takes two parameters of type (struct clock *), a and b. It
1930 * returns a nonzero value if the a parameter points to a clock value which is
1931 * greater than or equal to the one pointed to by b.
1933 * \subsubsection sec4-3-3-9 Section 4.3.3.9: clock Gt(): Are two clock
1937 * This macro takes two parameters of type (struct clock *), a and b. It
1938 * returns a non-zero value if the clock values pointed to by a and b are
1941 * \subsubsection sec4.3.3.10 Section 4.3.3.10: clock Le(): Is a clock
1942 * value less than or equal to another?
1945 * This macro takes two parameters of type (struct clock *), a and b. It
1946 * returns a nonzero value if the a parameter points to a clock value which is
1947 * less than or equal to the one pointed to by b.
1949 * \subsubsection sec4-3-3-11 Section 4.3.3.11: clock Lt(): Is a clock
1950 * value less than another?
1953 * This macro takes two parameters of type (struct clock *), a and b. It
1954 * returns a nonzero value if the a parameter points to a clock value which is
1955 * less than the one pointed to by b.
1957 * \subsubsection sec4-3-3-12 Section 4.3.3.12: clock IsZero(): Is a clock
1961 * This macro takes a single parameter of type (struct clock *), c. It returns
1962 * a non-zero value if the c parameter points to a clock value which is equal
1965 * \subsubsection sec4-3-3-13 Section 4.3.3.13: clock Zero(): Set a clock
1969 * This macro takes a single parameter of type (struct clock *), c. It sets the
1970 * given clock value to zero.
1971 * \subsubsection sec4-3-3-14 Section 4.3.3.14: clock Add(): Add two clock
1974 * This macro takes two parameters of type (struct clock *), c1 and c2. It adds
1975 * the value of the time in c2 to c1. Both clock values must be positive.
1977 * \subsubsection sec4-3-3-15 Section 4.3.3.15: clock Sub(): Subtract two
1981 * This macro takes two parameters of type (struct clock *), c1 and c2. It
1982 * subtracts the value of the time in c2 from c1. The time pointed to by c2
1983 * should be less than the time pointed to by c1.
1985 * \subsubsection sec4-3-3-16 Section 4.3.3.16: clock Float(): Convert a
1986 * clock time into floating point
1989 * This macro takes a single parameter of type (struct clock *), c. It
1990 * expresses the given clock value as a floating point number.
1992 * \section sec4-4 Section 4.4: The rx event Package
1995 * This package maintains an event facility. An event is defined to be
1996 * something that happens at or after a specified clock time, unless cancelled
1997 * prematurely. The clock times used are those provided by the rx clock
1998 * facility described in Section 4.3 above. A user routine associated with an
1999 * event is called with the appropriate arguments when that event occurs. There
2000 * are some restrictions on user routines associated with such events. first,
2001 * this user-supplied routine should not cause process preemption. Also, the
2002 * event passed to the user routine is still resident on the event queue at the
2003 * time of invocation. The user must not remove this event explicitly (via an
2004 * event Cancel(), see below). Rather, the user routine may remove or schedule
2005 * any other event at this time.
2007 * The events recorded by this package are kept queued in order of expiration
2008 * time, so that the first entry in the queue corresponds to the event which is
2009 * the first to expire. This interface is defined by the rx event.h include
2012 * \subsection sec4-4-1 Section 4.4.1: struct rxevent
2015 * This structure defines the format of an Rx event record.
2018 * \n struct queue junk -The queue to which this event belongs.
2019 * \n struct clock eventTime -The clock time recording when this event comes
2021 * \n
int (*func)() -The user-supplied function to call upon expiration.
2022 * \n
char *arg -The first argument to the (*func)() function above.
2023 * \n
char *arg1 -The second argument to the (*func)() function above.
2025 * \subsection sec4-4-2 Section 4.4.2: Operations
2028 * This section covers the interface routines provided for the Rx event
2031 * \subsubsection sec4-4-2-1 Section 4.4.2.1: rxevent Init(): Initialize
2035 * The rxevent Init() routine takes two arguments. The first, nEvents, is an
2036 * integer-valued parameter which specifies the number of event structures to
2037 * allocate at one time. This specifies the appropriate granularity of memory
2038 * allocation by the event package. The second parameter, scheduler, is a
2039 * pointer to an integer-valued function. This function is to be called when an
2040 * event is posted (added to the set of events managed by the package) that is
2041 * scheduled to expire before any other existing event.
2043 * This routine sets up future event allocation block sizes, initializes the
2044 * queues used to manage active and free event structures, and recalls that an
2045 * initialization has occurred. Thus, this function may be safely called
2048 * \subsubsection sec4-4-2-2 Section 4.4.2.2: rxevent Post(): Schedule an
2052 * This function constructs a new event based on the information included in
2053 * its parameters and then schedules it. The rxevent Post() routine takes four
2054 * parameters. The first is named when, and is of type (struct clock *). It
2055 * specifies the clock time at which the event is to occur. The second
2056 * parameter is named func and is a pointer to the integer-valued function to
2057 * associate with the event that will be created. When the event comes due,
2058 * this function will be executed by the event package. The next two arguments
2059 * to rxevent Post() are named arg and arg1, and are both of type (
char *).
2060 * They serve as the two arguments thath will be supplied to the func routine
2061 * when the event comes due.
2063 * If the given event is set to take place before any other event currently
2064 * posted, the scheduler routine established when the rxevent Init() routine
2065 * was called will be executed. This gives the application a chance to react to
2066 * this new event in a reasonable way. One might expect that this scheduler
2067 * routine will alter sleep times used by the application to make sure that it
2068 * executes in time to handle the new event.
2070 * \subsubsection sec4-4-2-3 Section 4.4.2.3: rxevent Cancel 1(): Cancel
2071 * an event (internal use)
2074 * This routine removes an event from the set managed by this package. It takes
2075 * a single parameter named ev of type (struct rxevent *). The ev argument
2076 * identifies the pending event to be cancelled.
2078 * The rxevent Cancel 1() routine should never be called directly. Rather, it
2079 * should be accessed through the rxevent Cancel() macro, described in Section
2082 * \subsubsection sec4-4-2-4 Section 4.4.2.4: rxevent Cancel(): Cancel an
2083 * event (external use)
2086 * This macro is the proper way to call the rxevent Cancel 1() routine
2087 * described in Section 4.4.2.3 above. Like rxevent Cancel 1(), it takes a
2088 * single argument. This event ptr argument is of type (struct rxevent *), and
2089 * identi
#es the pending event to be cancelled. This macro #rst checks to see 2090 *
if event ptr is null. If not, it calls rxevent Cancel 1() to perform the
2091 * real work. The event ptr argument is zeroed after the cancellation operation
2094 * \subsubsection sec4-4-2-5 Section 4.4.2.4: rxevent RaiseEvents():
2095 * Initialize the
event package 2098 * This function processes all events that have expired relative to the current
2099 * clock time maintained by the event package. Each qualifying event is removed
2100 * from the queue in order, and its user-supplied routine (func()) is executed
2101 * with the associated arguments.
2103 * The rxevent RaiseEvents() routine takes a single output parameter named
2104 * next, defined to be of type (struct clock *). Upon completion of rxevent
2105 * RaiseEvents(), the relative time to the next event due to expire is placed
2106 * in next. This knowledge may be used to calculate the amount of sleep time
2107 * before more event processing is needed. If there is no recorded event which
2108 * is still pending at this point, rxevent RaiseEvents() returns a zeroed clock
2111 * \subsubsection sec4-4-2-6 Section 4.4.2.6: rxevent TimeToNextEvent():
2112 * Get amount of time until the next event expires
2115 * This function returns the time between the current clock value as maintained
2116 * by the event package and the the next event's expiration time. This
2117 * information is placed in the single output argument,interval, defined to be
2118 * of type (struct clock *). The rxevent TimeToNextEvent() function returns
2119 * integer-valued quantities. If there are no scheduled events, a zero is
2120 * returned. If there are one or more scheduled events, a 1 is returned. If
2121 * zero is returned, the interval argument is not updated.
2123 * \page chap5 Chapter 5 -- Programming Interface
2125 * \section sec5-1 Section 5.1: Introduction
2128 * This chapter documents the API for the Rx facility. Included are
2129 * descriptions of all the constants, structures, exported variables, macros,
2130 * and interface functions available to the application programmer. This
2131 * interface is identical regardless of whether the application lives within
2132 * the unix kernel or above it.
2134 * This chapter actually provides more information than what may be strictly
2135 * considered the Rx API. Many objects that were intended to be opaque and for
2136 * Rx internal use only are also described here. The reason driving the
2137 * inclusion of this "extra" information is that such exported Rx interface
2138 * files as rx.h make these objects visible to application programmers. It is
2139 * prefereable to describe these objects here than to ignore them and leave
2140 * application programmers wondering as to their meaning.
2142 * An example application illustrating the use of this interface, showcasing
2143 * code from both server and client sides, appears in the following chapter.
2145 * \section sec5-2 Section 5.2: Constants
2148 * This section covers the basic constant definitions of interest to the Rx
2149 * application programmer. Each subsection is devoted to describing the
2150 * constants falling into the following categories:
2151 * \li Configuration quantities
2152 * \li Waiting options
2153 * \li Connection ID operations
2154 * \li Connection flags
2155 * \li Connection types
2159 * \li Packet header flags
2162 * \li Packet classes
2163 * \li Conditions prompting ack packets
2166 * \li Debugging values
2168 * An attempt has been made to relate these constant definitions to the objects
2169 * or routines that utilize them.
2171 * \subsection sec5-2-1 Section 5.2.1: Configuration Quantities
2174 * These definitions provide some basic Rx configuration parameters, including
2175 * the number of simultaneous calls that may be handled on a single connection,
2176 * lightweight thread parameters, and timeouts for various operations.
2183 * Default idle dead time for connections, in seconds.
2190 * The maximum number of Rx services that may be installed within one
2194 * RX PROCESS MAXCALLS
2198 * The maximum number of asynchronous calls active simultaneously on any given
2199 * Rx connection. This value must be set to a power of two.
2202 * RX DEFAULT STACK SIZE
2206 * Default lightweight thread stack size, measured in bytes. This value may be
2207 * overridden by calling the rx_SetStackSize() macro.
2210 * RX PROCESS PRIORITY
2212 * LWP NORMAL PRIORITY
2214 * This is the priority under which an Rx thread should run. There should not
2215 * generally be any reason to change this setting.
2218 * RX CHALLENGE TIMEOUT
2222 * The number of seconds before another authentication request packet is
2230 * Maximum number of individual acknowledgements that may be carried in an Rx
2231 * acknowledgement packet.
2233 * \subsection sec5-2-2 Section 5.2.2: Waiting Options
2236 * These definitions provide readable values indicating whether an operation
2237 * should block when packet buffer resources are not available.
2244 * Wait until the associated operation completes.
2251 * Don't wait if the associated operation would block.
2253 * \subsection sec5-2-3 Section 5.2.3: Connection ID Operations
2256 * These values assist in extracting the call channel number from a connection
2257 * identifier. A call channel is the index of a particular asynchronous call
2258 * structure within a single Rx connection.
2265 * Number of bits to right-shift to isolate a connection ID. Must be set to
2266 * the log (base two) of RX MAXCALLS.
2273 * Mask used to isolate a call channel from a connection ID field.
2280 * Mask used to isolate the connection ID from its field, masking out the call
2281 * channel information.
2283 * \subsection sec5-2-4 Section 5.2.4: Connection Flags
2286 * The values defined here appear in the flags field of Rx connections, as
2287 * defined by the rx connection structure described in Section 5.3.2.2.
2290 * RX CONN MAKECALL WAITING
2294 * rx MakeCall() is waiting for a channel.
2297 * RX CONN DESTROY ME
2301 * Destroy this (client) connection after its last call completes.
2304 * RX CONN USING PACKET CKSUM
2308 * This packet is using security-related check-summing (a non-zero header,
2309 * spare field has been seen.)
2311 * \subsection sec5-2-5 Section 5.2.5: Connection Types
2314 * Rx stores different information in its connection structures, depending on
2315 * whether the given connection represents the server side (the one providing
2316 * the service) or the client side (the one requesting the service) of the
2317 * protocol. The type field within the connection structure (described in
2318 * Section 5.3.2.2) takes on the following values to differentiate the two
2319 * types of connections, and identifies the fields that are active within the
2320 * connection structure.
2323 * RX CLIENT CONNECTION
2327 * This is a client-side connection.
2334 * This is a server-side connection.
2336 * \subsection sec5-2-6 Section 5.2.6: Call States
2339 * An Rx call on a particular connection may be in one of several states at any
2340 * instant in time. The following definitions identify the range of states that
2341 * a call may assume.
2348 * The call structure has never been used, and is thus still completely
2356 * A call is not yet in progress, but packets have arrived for it anyway. This
2357 * only applies to calls within server-side connections.
2364 * This call is fully active, having an attached lightweight thread operating
2372 * The call structure is "dallying" after its lightweight thread has completed
2373 * its most recent call. This is a "hot-standby" condition, where the call
2374 * structure preserves state from the previous call and thus optimizes the
2375 * arrival of further, related calls.
2377 * \subsection sec5-2-7 Section 5.2.7: Call Flags:
2380 * These values are used within the flags field of a variable declared to be of
2381 * type struct rx call, as described in Section 5.3.2.4. They provide
2382 * additional information as to the state of the given Rx call, such as the
2383 * type of event for which it is waiting (if any) and whether or not all
2384 * incoming packets have been received in support of the call.
2387 * RX CALL READER WAIT
2391 * Reader is waiting for next packet.
2394 * RX CALL WAIT WINDOW ALLOC
2398 * Sender is waiting for a window so that it can allocate buffers.
2401 * RX CALL WAIT WINDOW SEND
2405 * Sender is waiting for a window so that it can send buffers.
2408 * RX CALL WAIT PACKETS
2412 * Sender is waiting for packet buffers.
2415 * RX CALL RECEIVE DONE
2419 * The call is waiting for a lightweight thread to be assigned to the operation
2420 * it has just received.
2423 * RX CALL RECEIVE DONE
2427 * All packets have been received on this call.
2434 * The receive queue has been cleared when in precall state.
2436 * \subsection sec5-2-8 Section 5.2.8: Call Modes
2439 * These values define the modes of an Rx call when it is in the RX STATE
2440 * ACTIVE state, having a lightweight thread assigned to it.
2447 * We are sending or ready to send.
2454 * We are receiving or ready to receive.
2461 * Something went wrong in the current conversation.
2468 * The server side has flushed (or the client side has read) the last reply
2471 * \subsection sec5-2-9 Section 5.2.9: Packet Header Flags
2474 * Rx packets carry a flag field in their headers, providing additional
2475 * information regarding the packet's contents. The Rx packet header's flag
2476 * field's bits may take the following values:
2479 * RX CLIENT INITIATED
2483 * Signifies that a packet has been sent/received from the client side of the
2491 * The Rx calls' peer entity requests an acknowledgement.
2498 * This is the final packet from this side of the call.
2505 * There are more packets following this, i.e., the next sequence number seen
2506 * by the receiver should be greater than this one, rather than a
2507 * retransmission of an earlier sequence number.
2512 * (RX CLIENT INITIATED | RX LAST PACKET)
2514 * This flag is preset once per Rx packet. It doesn't change on retransmission
2517 * \subsection sec5-3-10 Section 5.2.10: Packet Sizes
2520 * These values provide sizing information on the various regions within Rx
2521 * packets. These packet sections include the IP/UDP headers and bodies as well
2522 * Rx header and bodies. Also covered are such values as different maximum
2523 * packet sizes depending on whether they are targeted to peers on the same
2524 * local network or a more far-flung network. Note that the MTU term appearing
2525 * below is an abbreviation for Maximum Transmission Unit.
2532 * The number of bytes taken up by IP/UDP headers.
2535 * RX MAX PACKET SIZE
2537 * (1500 - RX IPUDP SIZE)
2539 * This is the Ethernet MTU minus IP and UDP header sizes.
2544 * sizeof (struct rx header)
2546 * The number of bytes in an Rx packet header.
2549 * RX MAX PACKET DATA SIZE
2551 * (RX MAX PACKET SIZE RX - HEADER SIZE)
2553 * Maximum size in bytes of the user data in a packet.
2556 * RX LOCAL PACKET SIZE
2558 * RX MAX PACKET SIZE
2560 * Packet size in bytes to use when being sent to a host on the same net.
2563 * RX REMOTE PACKET SIZE
2565 * (576 - RX IPUDP SIZE)
2567 * Packet size in bytes to use when being sent to a host on a different net.
2569 * \subsection sec5-2-11 Section 5.2.11: Packet Types
2572 * The following values are used in the packetType field within a struct rx
2573 * packet, and define the different roles assumed by Rx packets. These roles
2574 * include user data packets, different flavors of acknowledgements, busies,
2575 * aborts, authentication challenges and responses, and debugging vehicles.
2578 * RX PACKET TYPE DATA
2582 * A user data packet.
2585 * RX PACKET TYPE ACK
2589 * Acknowledgement packet.
2592 * RX PACKET TYPE BUSY
2596 * Busy packet. The server-side entity cannot accept the call at the moment,
2597 * but the requestor is encouraged to try again later.
2600 * RX PACKET TYPE ABORT
2604 * Abort packet. No response is needed for this packet type.
2607 * RX PACKET TYPE ACKALL
2611 * Acknowledges receipt of all packets on a call.
2614 * RX PACKET TYPE CHALLENGE
2618 * Challenge the client's identity, requesting credentials.
2621 * RX PACKET TYPE RESPONSE
2625 * Response to a RX PACKET TYPE CHALLENGE authentication challenge packet.
2628 * RX PACKET TYPE DEBUG
2632 * Request for debugging information.
2639 * The number of Rx packet types defined above. Note that it also includes
2640 * packet type 0 (which is unused) in the count.
2643 * The RX PACKET TYPES definition provides a mapping of the above values to
2644 * human-readable string names, and is exported by the rx packetTypes variable
2645 * catalogued in Section 5.4.9.
2660 * \subsection sec5-2-12 Section 5.2.12: Packet Classes
2663 * These definitions are used internally to manage alloction of Rx packet
2664 * buffers according to quota classifications. Each packet belongs to one of
2665 * the following classes, and its buffer is derived from the corresponding
2669 * RX PACKET CLASS RECEIVE
2673 * Receive packet for user data.
2676 * RX PACKET CLASS SEND
2680 * Send packet for user data.
2683 * RX PACKET CLASS SPECIAL
2687 * A special packet that does not hold user data, such as an acknowledgement or
2688 * authentication challenge.
2691 * RX N PACKET CLASSES
2695 * The number of Rx packet classes defined above.
2697 * \subsection sec5-2-13 Section 5.2.13: Conditions Prompting Ack Packets
2700 * Rx acknowledgement packets are constructed and sent by the protocol
2701 * according to the following reasons. These values appear in the Rx packet
2702 * header of the ack packet itself.
2709 * The peer has explicitly requested an ack on this packet.
2716 * A duplicate packet has been received.
2719 * RX ACK OUT OF SEQUENCE
2723 * A packet has arrived out of sequence.
2726 * RX ACK EXCEEDS WINDOW
2730 * A packet sequence number higher than maximum value allowed by the call's
2731 * window has been received.
2738 * No packet buffer space is available.
2745 * Acknowledgement for keep-alive purposes.
2748 * RX ACK PING RESPONSE
2752 * Response to a RX ACK PING packet.
2759 * An ack generated due to a period of inactivity after normal packet
2762 * \subsection 5-2-14 Section 5.2.14: Acknowledgement Types
2765 * These are the set of values placed into the acks array in an Rx
2766 * acknowledgement packet, whose data format is defined by struct rx ackPacket.
2767 * These definitions are used to convey positive or negative acknowledgements
2768 * for a given range of packets.
2775 * Receiver doesn't currently have the associated packet; it may never hae been
2776 * received, or received and then later dropped before processing.
2783 * Receiver has the associated packet queued, although it may later decide to
2786 * \subsection sec5-2-15 Section 5.2.15: Error Codes
2789 * Rx employs error codes ranging from -1 to -64. The Rxgen stub generator may
2790 * use other error codes less than -64. User programs calling on Rx, on the
2791 * other hand, are expected to
return positive error codes. A
return value of
2792 * zero is interpreted as an indication that the given operation completed
2800 * A connection has been inactive past Rx
's tolerance levels and has been shut 2804 * RX INVALID OPERATION 2808 * An invalid operation has been attempted, including such protocol errors as 2809 * having a client-side call send data after having received the beginning of a 2810 * reply from its server-side peer. 2817 * The (optional) timeout value placed on this call has been exceeded (see 2818 * Sections 5.5.3.4 and 5.6.5). 2825 * Unexpected end of data on a read operation. 2832 * An unspecified low-level Rx protocol error has occurred. 2839 * A generic user abort code, used when no more specific error code needs to be 2840 * communicated. For example, Rx clients employing the multicast feature (see 2841 * Section 1.2.8) take advantage of this error code. 2843 * \subsection sec5-2-16 Section 5.2.16: Debugging Values 2846 * Rx provides a set of data collections that convey information about its 2847 * internal status and performance. The following values have been defined in 2848 * support of this debugging and statistics-collection feature. 2850 * \subsubsection sec5-3-16-1 Section 5.2.16.1: Version Information 2853 * Various versions of the Rx debugging/statistics interface are in existance, 2854 * each defining different data collections and handling certain bugs. Each Rx 2855 * facility is stamped with a version number of its debugging/statistics 2856 * interface, allowing its clients to tailor their requests to the precise data 2857 * collections that are supported by a particular Rx entity, and to properly 2858 * interpret the data formats received through this interface. All existing Rx 2859 * implementations should be at revision M. 2862 * RX DEBUGI VERSION MINIMUM 2866 * The earliest version of Rx statistics available. 2873 * The latest version of Rx statistics available. 2876 * RX DEBUGI VERSION W SECSTATS 2880 * Identifies the earliest version in which statistics concerning Rx security 2881 * objects is available. 2884 * RX DEBUGI VERSION W GETALLCONN 2888 * The first version that supports getting information about all current Rx 2889 * connections, as specified y the RX DEBUGI GETALLCONN debugging request 2890 * packet opcode described below. 2893 * RX DEBUGI VERSION W RXSTATS 2897 * The first version that supports getting all the Rx statistics in one 2898 * operation, as specified by the RX DEBUGI RXSTATS debugging request packet 2899 * opcode described below. 2902 * RX DEBUGI VERSION W UNALIGNED CONN 2906 * There was an alignment problem discovered when returning Rx connection 2907 * information in older versions of this debugging/statistics interface. This 2908 * identifies the last version that exhibited this alignment problem. 2910 * \subsubsection sec5-2-16-2 Section 5.2.16.2: Opcodes 2913 * When requesting debugging/statistics information, the caller specifies one 2914 * of the following supported data collections: 2917 * RX DEBUGI GETSTATS 2921 * Get basic Rx statistics. 2928 * Get information on all Rx connections considered "interesting" (as defined 2929 * below), and no others. 2932 * RX DEBUGI GETALLCONN 2936 * Get information on all existing Rx connection structures, even 2937 * "uninteresting" ones. 2944 * Get all available Rx stats. 2947 * An Rx connection is considered "interesting" if it is waiting for a call 2948 * channel to free up or if it has been marked for destruction. If neither is 2949 * true, a connection is still considered interesting if any of its call 2950 * channels is actively handling a call or in its preparatory pre-call state. 2951 * Failing all the above conditions, a connection is still tagged as 2952 * interesting if any of its call channels is in either of the RX MODE SENDING 2953 * or RX MODE RECEIVING modes, which are not allowed when the call is not 2956 * \subsubsection sec5-2-16-3 Section 5.2.16.3: Queuing 2959 * These two queueing-related values indicate whether packets are present on 2960 * the incoming and outgoing packet queues for a given Rx call. These values 2961 * are only used in support of debugging and statistics-gathering operations. 2968 * Packets available in in queue. 2975 * Packets available in out queue. 2977 * \section sec5-3 Section 5.3: Structures 2980 * This section describes the major exported Rx data structures of interest to 2981 * application programmers. The following categories are utilized for the 2982 * purpose of organizing the structure descriptions: 2983 * \li Security objects 2984 * \li Protocol objects 2985 * \li Packet formats 2986 * \li Debugging and statistics 2989 * Please note that many fields described in this section are declared to be 2990 * VOID. This is defined to be char, and is used to get around some compiler 2992 * \subsection sec5-3-1 Section 5.3.1: Security Objects 2995 * As explained in Section 1.2.1, Rx provides a modular, extensible security 2996 * model. This allows Rx applications to either use one of the built-in 2997 * security/authentication protocol packages or write and plug in one of their 2998 * own. This section examines the various structural components used by Rx to 2999 * support generic security and authentication modules. 3001 * \subsubsection sec5-3-1-1 Section 5.3.1.1: struct rx securityOps 3004 * As previously described, each Rx security object must export a fixed set of 3005 * interface functions, providing the full set of operations defined on the 3006 * object. The rx securityOps structure defines the array of functions 3007 * comprising this interface. The Rx facility calls these routines at the 3008 * appropriate times, without knowing the specifics of how any particular 3009 * security object implements the operation. 3011 * A complete description of these interface functions, including information 3012 * regarding their exact purpose, parameters, and calling conventions, may be 3013 * found in Section 5.5.7. 3016 * \li int (*op Close)() - React to the disposal of a security object. 3017 * \li int (*op NewConnection)() - Invoked each time a new Rx connection 3018 * utilizing the associated security object is created. 3019 * \li int (*op PreparePacket)() - Invoked each time an outgoing Rx packet is 3020 * created and sent on a connection using the given security object. 3021 * \li int (*op SendPacket)() - Called each time a packet belonging to a call 3022 * in a connection using the security object is physically transmitted. 3023 * \li int (*op CheckAuthentication)() - This function is executed each time it 3024 * is necessary to check whether authenticated calls are being perfomed on a 3025 * connection using the associated security object. 3026 * \li int (*op CreateChallenge)() - Invoked each time a server-side challenge 3027 * event is created by Rx, namely when the identity of the principal associated 3028 * with the peer process must be determined. 3029 * \li int (*op GetChallenge)() - Called each time a client-side packet is 3030 * constructed in response to an authentication challenge. 3031 * \li int (*op GetResponse)() - Executed each time a response to a challenge 3032 * event must be received on the server side of a connection. 3033 * \li int (*op CheckResponse)() - Invoked each time a response to an 3034 * authentication has been received, validating the response and pulling out 3035 * the required authentication information. 3036 * \li int (*op CheckPacket) () - Invoked each time an Rx packet has been 3037 * received, making sure that the packet is properly formatted and that it 3038 * hasn't been altered.
3039 * \li int (*op DestroyConnection)() - Called each time an Rx connection
3040 * employing the given security
object is destroyed.
3041 * \li int (*op GetStats)() - Executed each time a request
for statistics on
3042 * the given security
object has been received.
3043 * \li int (*op Spare1)()-
int (*op Spare3)() - Three spare
function slots,
3044 * reserved
for future use.
3046 * \subsubsection sec5-3-1-2 Section 5.2.1.2:
struct rx securityClass
3049 * Variables of type
struct rx securityClass are used to represent
3050 * instantiations of a particular security model employed by Rx. It consists of
3051 * a pointer to the
set of interface operations implementing the given security
3052 *
object, along with a pointer to
private storage as necessary to support its
3053 * operations. These security objects are also reference-counted, tracking the
3054 * number of Rx connections in existance that use the given security
object. If
3055 * the reference count drops to zero, the security module may garbage-collect
3056 * the space taken by the unused security
object.
3059 * \li
struct rx securityOps *ops - Pointer to the array of interface functions
3060 *
for the security
object.
3061 * \li VOID *privateData - Pointer to a region of storage used by the security
3062 *
object to support its operations.
3063 * \li
int refCount - A reference count on the security
object, tracking the
3064 * number of Rx connections employing
this model.
3066 * \subsubsection sec5-3-1-3 Section 5.3.1.3:
struct rx
3067 * securityObjectStats
3070 * This structure is used to report characteristics
for an instantiation of a
3071 * security
object on a particular Rx connection, as well as performance
3072 * figures
for that
object. It is used by the debugging portions of the Rx
3073 * package. Every security
object defines and manages fields such as level and
3074 * flags differently.
3077 * \li
char type - The type of security
object being implemented. Existing
3079 * \li 0: The null security package.
3080 * \li 1: An obsolete Kerberos-like security
object.
3081 * \li 2: The rxkad discipline (see Chapter 3).
3082 * \li
char level - The level at which encryption is utilized.
3083 * \li
char sparec[10] - Used solely
for alignment purposes.
3084 * \li
long flags - Status flags regarding aspects of the connection relating
3085 * to the security
object.
3086 * \li u
long expires - Absolute time when the authentication information
3087 * cached by the given connection expires. A value of zero indicates that the
3088 * associated authentication information is valid
for all time.
3089 * \li u
long packetsReceived - Number of packets received on
this particular
3090 * connection, and thus the number of incoming packets handled by the
3091 * associated security
object.
3092 * \li u
long packetsSent - Number of packets sent on
this particular
3093 * connection, and thus the number of outgoing packets handled by the
3094 * associated security
object.
3095 * \li u
long bytesReceived - Overall number of
"payload" bytes received (i.e.,
3096 * packet bytes not associated with IP headers, UDP headers, and the security
3097 * module
's own header and trailer regions) on this connection. 3098 * \li u long bytesSent - Overall number of "payload" bytes sent (i.e., packet 3099 * bytes not associated with IP headers, UDP headers, and the security module's
3100 * own header and trailer regions) on
this connection.
3101 * \li
short spares[4] - Several shortword spares, reserved
for future use.
3102 * \li
long sparel[8] - Several longword spares, reserved
for future use.
3104 * \subsection sec5-3-2 Section 5.3.2: Protocol Objects
3107 * The structures describing the main abstractions and entities provided by Rx,
3108 * namely services, peers, connections and calls are covered in
this section.
3110 * \subsubsection sec5-3-2-1 Section 5.3.2.1:
struct rx service
3113 * An Rx-based server exports services, or specific RPC interfaces that
3114 * accomplish certain tasks. Services are identified by (host-address,
3115 * UDP-port, serviceID) triples. An Rx service is installed and initialized on
3116 * a given host through the use of the rx NewService() routine (See Section
3117 * 5.6.3). Incoming calls are stamped with the Rx service type, and must match
3118 * an installed service to be accepted. Internally, Rx services also carry
3119 *
string names for purposes of identification. These strings are useful to
3120 * remote debugging and statistics-gathering programs. The use of a service ID
3121 * allows a single server process to export multiple, independently-specified
3124 * Each Rx service contains one or more security classes, as implemented by
3125 * individual security objects. These security objects implement end-to-end
3126 * security protocols. Individual peer-to-peer connections established on
3127 * behalf of an Rx service will select exactly one of the supported security
3128 * objects to define the authentication procedures followed by all calls
3129 * associated with the connection. Applications are not limited to using only
3130 * the core set of built-in security objects offered by Rx. They are free to
3131 * define their own security objects in order to execute the specific protocols
3134 * It is possible to specify both the minimum and maximum number of lightweight
3135 * processes available to handle simultaneous calls directed to an Rx service.
3136 * In addition, certain procedures may be registered with the service and
3137 * called at set times in the course of handling an RPC request.
3140 * \li u
short serviceId - The associated service number.
3141 * \li u
short servicePort - The chosen UDP port for this service.
3142 * \li
char *serviceName - The human-readable service name, expressed as a
3144 * \li
string. osi socket socket - The socket structure or file descriptor used
3146 * \li u
short nSecurityObjects - The number of entries in the array of
3147 * supported security objects.
3148 * \li struct rx securityClass **securityObjects - The array of pointers to the
3150 * vice's security class objects.
3151 * \li
long (*executeRequestProc)() - A pointer to the routine to call when an
3152 * RPC request is received for this service.
3153 * \li VOID (*destroyConnProc)() - A pointer to the routine to call when one of
3154 * the server-side connections associated with this service is destroyed.
3155 * \li VOID (*newConnProc)() - A pointer to the routine to call when a
3156 * server-side connection associated with this service is created.
3157 * \li VOID (*beforeProc)() - A pointer to the routine to call before an
3158 * individual RPC call on one of this service's connections is executed.
3159 * \li VOID (*afterProc)() - A pointer to the routine to call after an
3160 * individual RPC call on one of this service's connections is executed.
3161 * \li
short nRequestsRunning - The number of simultaneous RPC calls currently
3162 * in progress for this service.
3163 * \li
short maxProcs - This field has two meanings. first, maxProcs limits the
3164 * total number of requests that may execute in parallel for any one service.
3165 * It also guarantees that this many requests may be handled in parallel if
3166 * there are no active calls for any other service.
3167 * \li
short minProcs - The minimum number of lightweight threads (hence
3168 * requests) guaranteed to be simultaneously executable.
3169 * \li
short connDeadTime - The number of seconds until a client of this
3170 * service will be declared to be dead, if it is not responding to the RPC
3172 * \li
short idleDeadTime - The number of seconds a server-side connection for
3173 * this service will wait for packet I/O to resume after a quiescent period
3174 * before the connection is marked as dead.
3176 * \subsubsection sec5-3-2-2 Section 5.3.2.2: struct rx connection
3179 * An Rx connection represents an authenticated communication path, allowing
3180 * multiple asynchronous conversations (calls). Each connection is identified
3181 * by a connection ID. The low-order bits of the connection ID are reserved so
3182 * they may be stamped with the index of a particular call channel. With up to
3183 * RX MAXCALLS concurrent calls (set to 4 in this implementation), the bottom
3184 * two bits are set aside for this purpose. The connection ID is not sufficient
3185 * by itself to uniquely identify an Rx connection. Should a client crash and
3186 * restart, it may reuse a connection ID, causing inconsistent results. In
3187 * addition to the connection ID, the epoch, or start time for the client side
3188 * of the connection, is used to identify a connection. Should the above
3189 * scenario occur, a different epoch value will be chosen by the client,
3190 * differentiating this incarnation from the orphaned connection record on the
3193 * Each connection is associated with a parent service, which defines a set of
3194 * supported security models. At creation time, an Rx connection selects the
3195 * particular security protocol it will implement, referencing the associated
3196 * service. The connection structure maintains state about the individual calls
3197 * being simultaneously handled.
3200 * \li struct rx connection *next - Used for internal queueing.
3201 * \li struct rx peer *peer - Pointer to the connection's peer information (see
3203 * \li u
long epoch - Process start time of the client side of the connection.
3204 * \li u
long cid - Connection identifier. The call channel (i.e., the index
3205 * into the connection's array of call structures) may appear in the bottom
3207 * \li VOID *rock - Pointer to an arbitrary region of memory in support of the
3208 * connection's operation. The contents of this area are opaque to the Rx
3209 * facility in general, but are understood by any special routines used by this
3211 * \li struct rx call *call[RX MAXCALLS] - Pointer to the call channel
3212 * structures, describing up to RX MAXCALLS concurrent calls on this
3214 * \li u
long callNumber[RX MAXCALLS] - The set of current call numbers on each
3215 * of the call channels.
3216 * \li
int timeout - Obsolete; no longer used.
3217 * \li u
char flags - Various states of the connection; see Section 5.2.4 for
3218 * individual bit definitions.
3219 * \li u
char type - Whether the connection is a server-side or client-side
3220 * one. See Section 5.2.5 for individual bit definitions.
3221 * \li u
short serviceId - The service ID that should be stamped on requests.
3222 * This field is only used by client-side instances of connection structures.
3223 * \li struct rx service *service - A pointer to the service structure
3224 * associated with this connection. This field is only used by server-side
3225 * instances of connection structures.
3226 * \li u
long serial - Serial number of the next outgoing packet associated
3227 * with this connection.
3228 * \li u
long lastSerial - Serial number of the last packet received in
3229 * association with this connection. This field is used in computing packet
3231 * \li u
short secondsUntilDead - Maximum numer of seconds of silence that
3232 * should be tolerated from the connection's peer before calls will be
3233 * terminated with an RX CALL DEAD error.
3234 * \li u
char secondsUntilPing - The number of seconds between "pings"
3235 * (keep-alive probes) when at least one call is active on this connection.
3236 * \li u
char securityIndex - The index of the security
object being used by
3237 * this connection. This number selects a slot in the security class array
3238 * maintained by the service associated with the connection.
3239 * \li
long error - Records the latest error code for calls occurring on this
3241 * \li struct rx securityClass *securityObject - A pointer to the security
3242 *
object used by this connection. This should coincide with the slot value
3243 * chosen by the securityIndex field described above.
3244 * \li VOID *securityData - A pointer to a region dedicated to hosting any
3245 * storage required by the security
object being used by this connection.
3246 * \li u
short securityHeaderSize - The length in bytes of the portion of the
3247 * packet header before the user's data that contains the security module's
3249 * \li u
short securityMaxTrailerSize - The length in bytes of the packet
3250 * trailer, appearing after the user's data, as mandated by the connection's
3252 * \li struct rxevent *challengeEvent -Pointer to an event that is scheduled
3253 * when the server side of the connection is challenging the client to
3254 * authenticate itself.
3255 * \li
int lastSendTime - The last time a packet was sent on this connection.
3256 * \li
long maxSerial - The largest serial number seen on incoming packets.
3257 * \li u
short hardDeadTime - The maximum number of seconds that any call on
3258 * this connection may execute. This serves to throttle runaway calls.
3260 * \subsubsection sec5-3-2-3 Section 5.3.2.3: struct rx peer
3263 * For each connection, Rx maintains information describing the entity, or
3264 * peer, on the other side of the wire. A peer is identified by a (host,
3265 * UDP-port) pair. Included in the information kept on this remote
3266 * communication endpoint are such network parameters as the maximum packet
3267 * size supported by the host, current readings on round trip time to
3268 * retransmission delays, and packet skew (see Section 1.2.7). There are also
3269 * congestion control fields, ranging from descriptions of the maximum number
3270 * of packets that may be sent to the peer without pausing and retransmission
3271 * statistics. Peer structures are shared between connections whenever
3272 * possible, and hence are reference-counted. A peer
object may be
3273 * garbage-collected if it is not actively referenced by any connection
3274 * structure and a sufficient period of time has lapsed since the reference
3275 * count dropped to zero.
3278 * \li struct rx peer *next - Use to access internal lists.
3279 * \li u
long host - Remote IP address, in network byte order
3280 * \li u
short port - Remote UDP port, in network byte order
3281 * \li
short packetSize - Maximum packet size for this host, if known.
3282 * \li u
long idleWhen - When the refCount reference count field (see below)
3284 * \li
short refCount - Reference count for this structure
3285 * \li u
char burstSize - Reinitialization size for the burst field (below).
3286 * \li u
char burst - Number of packets that can be transmitted immediately
3288 * \li struct clock burstWait - Time delay until new burst aimed at this peer
3290 * \li struct queue congestionQueue - Queue of RPC call descriptors that are
3291 * waiting for a non-zero burst value.
3292 * \li
int rtt - Round trip time to the peer, measured in milliseconds.
3293 * \li struct clock timeout - Current retransmission delay to the peer.
3294 * \li
int nSent - Total number of distinct data packets sent, not including
3296 * \li
int reSends - Total number of retransmissions for this peer since the
3297 * peer structure instance was created.
3298 * \li u
long inPacketSkew - Maximum skew on incoming packets (see Section
3300 * \li u
long outPacketSkew - Peer-reported maximum skew on outgoing packets
3301 * (see Section 1.2.7).
3303 * \subsubsection sec5-3-2-4 Section 5.3.2.4: struct rx call
3306 * This structure records the state of an active call proceeding on a given Rx
3307 * connection. As described above, each connection may have up to RX MAXCALLS
3308 * calls active at any one instant, and thus each connection maintains an array
3309 * of RX MAXCALLS rx call structures. The information contained here is
3310 * specific to the given call; "permanent" call state, such as the call number,
3311 * is maintained in the connection structure itself.
3314 * \li struct queue queue item header - Queueing information for this
3316 * \li struct queue tq - Queue of outgoing ("transmit") packets.
3317 * \li struct queue rq - Queue of incoming ("receive") packets.
3318 * \li
char *bufPtr - Pointer to the next byte to fill or read in the call's
3319 * current packet, depending on whether it is being transmitted or received.
3320 * \li u
short nLeft - Number of bytes left to read in the first packet in the
3321 * reception queue (see field rq).
3322 * \li u
short nFree - Number of bytes still free in the last packet in the
3323 * transmission queue (see field tq).
3324 * \li struct rx packet *currentPacket - Pointer to the current packet being
3325 * assembled or read.
3326 * \li struct rx connection *conn - Pointer to the parent connection for this
3328 * \li u
long *callNumber - Pointer to call number field within the call's
3330 * \li u
char channel - Index within the parent connection's call array that
3331 * describes this call.
3332 * \li u
char dummy1, dummy2 - These are spare fields, reserved for future use.
3333 * \li u
char state - Current call state. The associated bit definitions appear
3335 * \li u
char mode - Current mode of a call that is in RX STATE ACTIVE state.
3336 * The associated bit definitions appear in Section 5.2.8.
3337 * \li u
char flags - Flags pertaining to the state of the given call. The
3338 * associated bit definitions appear in Section 5.2.7.
3339 * \li u
char localStatus - Local user status information, sent out of band.
3340 * This field is currently not in use, set to zero.
3341 * \li u
char remoteStatus - Remote user status information, received out of
3342 * band. This field is currently not in use, set to zero.
3343 * \li
long error - Error condition for this call.
3344 * \li u
long timeout - High level timeout for this call
3345 * \li u
long rnext - Next packet sequence number expected to be received.
3346 * \li u
long rprev - Sequence number of the previous packet received. This
3347 * number is used to decide the proper sequence number for the next packet to
3348 * arrive, and may be used to generate a negative acknowledgement.
3349 * \li u
long rwind - Width of the packet receive window for this call. The
3350 * peer must not send packets with sequence numbers greater than or equal to
3352 * \li u
long tfirst - Sequence number of the first unacknowledged transmit
3353 * packet for this call.
3354 * \li u
long tnext - Next sequence number to use for an outgoing packet.
3355 * \li u
long twind - Width of the packet transmit window for this call. Rx
3356 * cannot assign a sequence number to an outgoing packet greater than or equal
3357 * to tfirst + twind.
3358 * \li struct rxevent *resendEvent - Pointer to a pending retransmission event,
3360 * \li struct rxevent *timeoutEvent - Pointer to a pending timeout event, if
3362 * \li struct rxevent *keepAliveEvent - Pointer to a pending keep-alive event,
3363 * if this is an active call.
3364 * \li struct rxevent *delayedAckEvent - Pointer to a pending delayed
3365 * acknowledgement packet event, if any. Transmission of a delayed
3366 * acknowledgement packet is scheduled after all outgoing packets for a call
3367 * have been sent. If neither a reply nor a new call are received by the time
3368 * the delayedAckEvent activates, the ack packet will be sent.
3369 * \li
int lastSendTime - Last time a packet was sent for this call.
3370 * \li
int lastReceiveTime - Last time a packet was received for this call.
3371 * \li VOID (*arrivalProc)() - Pointer to the procedure to call when reply is
3373 * \li VOID *arrivalProcHandle - Pointer to the handle to pass to the
3374 * arrivalProc as its first argument.
3375 * \li VOID *arrivalProcArg - Pointer to an additional argument to pass to the
3376 * given arrivalProc.
3377 * \li u
long lastAcked - Sequence number of the last packet "hard-acked" by
3378 * the receiver. A packet is considered to be hard-acked if an acknowledgement
3379 * is generated after the reader has processed it. The Rx facility may
3380 * sometimes "soft-ack" a windowfull of packets before they have been picked up
3382 * \li u
long startTime - The time this call started running.
3383 * \li u
long startWait - The time that a server began waiting for input data
3386 * \subsection sec5-3-3 Section 5.3.3: Packet Formats
3389 * The following sections cover the different data formats employed by the
3390 * suite of Rx packet types, as enumerated in Section 5.2.11. A description of
3391 * the most commonly-employed Rx packet header appears first, immediately
3392 * followed by a description of the generic packet container and descriptor.
3393 * The formats for Rx acknowledgement packets and debugging/statistics packets
3394 * are also examined.
3396 * \subsubsection sec5-3-3-1 Section 5.3.3.1: struct rx header
3399 * Every Rx packet has its own header region, physically located after the
3400 * leading IP/UDP headers. This header contains connection, call, security, and
3401 * sequencing information. Along with a type identifier, these fields allow the
3402 * receiver to properly interpret the packet. In addition, every client relates
3403 * its "epoch", or Rx incarnation date, in each packet. This assists in
3404 * identifying protocol problems arising from reuse of connection identifiers
3405 * due to a client restart. Also included in the header is a byte of
3406 * user-defined status information, allowing out-of-band channel of
3407 * communication for the higher-level application using Rx as a transport
3411 * \li u
long epoch - Birth time of the client Rx facility.
3412 * \li u
long cid - Connection identifier, as defined by the client. The last
3413 * RX CIDSHIFT bits in the cid field identify which of the server-side RX
3414 * MAXCALLS call channels is to receive the packet.
3415 * \li u
long callNumber - The current call number on the chosen call channel.
3416 * \li u
long seq - Sequence number of this packet. Sequence numbers start with
3417 * 0 for each new Rx call.
3418 * \li u
long serial - This packet's serial number. A new serial number is
3419 * stamped on each packet transmitted (or retransmitted).
3420 * \li u
char type - What type of Rx packet this is; see Section 5.2.11 for the
3421 * list of legal definitions.
3422 * \li u
char flags - Flags describing this packet; see Section 5.2.9 for the
3423 * list of legal settings.
3424 * \li u
char userStatus - User-defined status information, uninterpreted by
3425 * the Rx facility itself. This field may be easily set or retrieved from Rx
3426 * packets via calls to the rx GetLocalStatus(), rx SetLocalStatus(), rx
3427 * GetRemoteStatus(), and rx SetRemoteStatus() macros.
3428 * \li u
char securityIndex - Index in the associated server-side service class
3429 * of the security
object used by this call.
3430 * \li u
short serviceId - The server-provided service ID to which this packet
3432 * \li u
short spare - This field was originally a true spare, but is now used
3433 * by the built-in rxkad security module for packet header checksums. See the
3434 * descriptions of the related rx IsUsingPktChecksum(), rx GetPacketCksum(),
3435 * and rx SetPacketCksum() macros.
3437 * \subsubsection sec5-3-3-2 Section 5.3.3.2: struct rx packet
3440 * This structure is used to describe an Rx packet, and includes the wire
3441 * version of the packet contents, where all fields exist in network byte
3442 * order. It also includes acknowledgement, length, type, and queueing
3446 * \li struct queue queueItemHeader - field used for internal queueing.
3447 * \li u
char acked - If non-zero, this field indicates that this packet has
3448 * been tentatively (soft-) acknowledged. Thus, the packet has been accepted by
3449 * the rx peer entity on the other side of the connection, but has not yet
3450 * necessarily been passed to the true reader. The sender is not free to throw
3451 * the packet away, as it might still get dropped by the peer before it is
3452 * delivered to its destination process.
3453 * \li
short length - Length in bytes of the user data section.
3454 * \li u
char packetType - The type of Rx packet described by this record. The
3455 * set of legal choices is available in Section 5.2.11.
3456 * \li struct clock retryTime - The time when this packet should be
3457 * retransmitted next.
3458 * \li struct clock timeSent - The last time this packet was transmitted.
3459 * \li struct rx header header - A copy of the internal Rx packet header.
3460 * \li wire - The text of the packet as it appears on the wire. This structure
3461 * has the following sub-fields:
3462 * \li u
long head[RX HEADER SIZE/sizeof(
long)] The wire-level contents of
3463 * IP, UDP, and Rx headers.
3464 * \li u
long data[RX MAX PACKET DATA SIZE/sizeof(
long)] The wire form of
3465 * the packet's "payload", namely the user data it carries.
3467 * \subsubsection sec5-3-3-3 Section 5.3.3.3: struct rx ackPacket
3470 * This is the format for the data portion of an Rx acknowledgement packet,
3471 * used to inform a peer entity performing packet transmissions that a subset
3472 * of its packets has been properly received.
3475 * \li u
short bufferSpace - Number of packet buffers available. Specifically,
3476 * the number of packet buffers that the ack packet's sender is willing to
3477 * provide for data on this or subsequent calls. This number does not have to
3478 * fully accurate; it is acceptable for the sender to provide an estimate.
3479 * \li u
short maxSkew - The maximum difference seen between the serial number
3480 * of the packet being acknowledged and highest packet yet received. This is an
3481 * indication of the degree to which packets are arriving out of order at the
3483 * \li u
long firstPacket - The serial number of the first packet in the list
3484 * of acknowledged packets, as represented by the acks field below.
3485 * \li u
long previousPacket - The previous packet serial number received.
3486 * \li u
long serial - The serial number of the packet prompted the
3488 * \li u
char reason - The reason given for the acknowledgement; legal values
3489 * for this field are described in Section 5.2.13.
3490 * \li u
char nAcks - Number of acknowledgements active in the acks array
3491 * immediately following.
3492 * \li u
char acks[RX MAXACKS] - Up to RX MAXACKS packet acknowledgements. The
3493 * legal values for each slot in the acks array are described in Section
3494 * 5.2.14. Basically, these fields indicate either positive or negative
3498 * All packets with serial numbers prior to firstPacket are implicitly
3499 * acknowledged by this packet, indicating that they have been fully processed
3500 * by the receiver. Thus, the sender need no longer be concerned about them,
3501 * and may release all of the resources that they occupy. Packets with serial
3502 * numbers firstPacket + nAcks and higher are not acknowledged by this ack
3503 * packet. Packets with serial numbers in the range [firstPacket, firstPacket +
3504 * nAcks) are explicitly acknowledged, yet their sender-side resources must not
3505 * yet be released, as there is yet no guarantee that the receiver will not
3506 * throw them away before they can be processed there.
3508 * There are some details of importance to be noted. For one, receiving a
3509 * positive acknowlegement via the acks array does not imply that the
3510 * associated packet is immune from being dropped before it is read and
3511 * processed by the receiving entity. It does, however, imply that the sender
3512 * should stop retransmitting the packet until further notice. Also, arrival of
3513 * an ack packet should prompt the transmitter to immediately retransmit all
3514 * packets it holds that have not been explicitly acknowledged and that were
3515 * last transmitted with a serial number less than the highest serial number
3516 * acknowledged by the acks array.
3517 * Note: The fields in this structure are always kept in wire format, namely in
3518 * network byte order.
3520 * \subsection sec5-3-4 Section 5.3.4: Debugging and Statistics
3523 * The following structures are defined in support of the debugging and
3524 * statistics-gathering interfaces provided by Rx.
3526 * \subsubsection sec5-3-4-1 Section 5.3.4.1: struct rx stats
3529 * This structure maintains Rx statistics, and is gathered by such tools as the
3530 * rxdebug program. It must be possible for all of the fields placed in this
3531 * structure to be successfully converted from their on-wire network byte
3532 * orderings to the host-specific ordering.
3535 * \li
int packetRequests - Number of packet allocation requests processed.
3536 * \li
int noPackets[RX N PACKET CLASSES] - Number of failed packet requests,
3537 * organized per allocation class.
3538 * \li
int socketGreedy - Whether the SO GREEDY setting succeeded for the Rx
3540 * \li
int bogusPacketOnRead - Number of inappropriately
short packets
3542 * \li
int bogusHost - Contains the host address from the last bogus packet
3544 * \li
int noPacketOnRead - Number of attempts to read a packet off the wire
3545 * when there was actually no packet there.
3546 * \li
int noPacketBuffersOnRead - Number of dropped data packets due to lack
3547 * of packet buffers.
3548 * \li
int selects - Number of selects waiting for a packet arrival or a
3550 * \li
int sendSelects - Number of selects forced when sending packets.
3551 * \li
int packetsRead[RX N PACKET TYPES] - Total number of packets read,
3552 * classified by type.
3553 * \li
int dataPacketsRead - Number of unique data packets read off the wire.
3554 * \li
int ackPacketsRead - Number of ack packets read.
3555 * \li
int dupPacketsRead - Number of duplicate data packets read.
3556 * \li
int spuriousPacketsRead - Number of inappropriate data packets.
3557 * \li
int packetsSent[RX N PACKET TYPES] - Number of packet transmissions,
3558 * broken down by packet type.
3559 * \li
int ackPacketsSent - Number of ack packets sent.
3560 * \li
int pingPacketsSent - Number of ping packets sent.
3561 * \li
int abortPacketsSent - Number of abort packets sent.
3562 * \li
int busyPacketsSent - Number of busy packets sent.
3563 * \li
int dataPacketsSent - Number of unique data packets sent.
3564 * \li
int dataPacketsReSent - Number of retransmissions.
3565 * \li
int dataPacketsPushed - Number of retransmissions pushed early by a
3566 * negative acknowledgement.
3567 * \li
int ignoreAckedPacket - Number of packets not retransmitted because they
3568 * have already been acked.
3569 * \li
int struct clock totalRtt - Total round trip time measured for packets,
3570 * used to compute average time figure.
3571 * \li struct clock minRtt - Minimum round trip time measured for packets.
3572 * struct clock maxRtt - Maximum round trip time measured for packets.
3573 * \li
int nRttSamples - Number of round trip samples.
3574 * \li
int nServerConns - Number of server connections.
3575 * \li
int nClientConns - Number of client connections.
3576 * \li
int nPeerStructs - Number of peer structures.
3577 * \li
int nCallStructs - Number of call structures physically allocated (using
3578 * the internal storage allocator routine).
3579 * \li
int nFreeCallStructs - Number of call structures which were pulled from
3580 * the free queue, thus avoiding a call to the internal storage allocator
3582 * \li
int spares[10] - Ten integer spare fields, reserved for future use.
3584 * \subsubsection sec5-3-4-2 Section 5.3.4.2: struct rx debugIn
3587 * This structure defines the data format for a packet requesting one of the
3588 * statistics collections maintained by Rx.
3591 * \li
long type - The specific data collection that the caller desires. Legal
3592 * settings for this field are described in Section 5.2.16.2.
3593 * \li
long index - This field is only used when gathering information on Rx
3594 * connections. Choose the index of the server-side connection record of which
3595 * we are inquiring. This field may be used as an iterator, stepping through
3596 * all the connection records, one per debugging request, until they have all
3599 * \subsubsection sec5-3-4-3 Section 5.3.4.3: struct rx debugStats
3602 * This structure describes the data format for a reply to an RX DEBUGI
3603 * GETSTATS debugging request packet. These fields are given values indicating
3604 * the current state of the Rx facility.
3607 * \li
long nFreePackets - Number of packet buffers currently assigned to the
3609 * \li
long packetReclaims - Currently unused.
3610 * \li
long callsExecuted - Number of calls executed since the Rx facility was
3612 * \li
char waitingForPackets - Is Rx currently blocked waiting for a packet
3613 * buffer to come free?
3614 * \li
char usedFDs - If the Rx facility is executing in the kernel, return the
3615 * number of unix file descriptors in use. This number is not directly related
3616 * to the Rx package, but rather describes the state of the machine on which Rx
3618 * \li
char version - Version number of the debugging package.
3619 * \li
char spare1[1] - Byte spare, reserved for future use.
3620 * \li
long spare2[10] - Set of 10 longword spares, reserved for future use.
3622 * \subsubsection sec5-3-4-4 Section 5.3.4.4: struct rx debugConn
3625 * This structure defines the data format returned when a caller requests
3626 * information concerning an Rx connection. Thus, rx debugConn defines the
3627 * external packaging of interest to external parties. Most of these fields are
3628 * set from the rx connection structure, as defined in Section 5.3.2.2, and
3629 * others are obtained by indirecting through such objects as the connection's
3630 * peer and call structures.
3633 * \li
long host - Address of the host identified by the connection's peer
3635 * \li
long cid - The connection ID.
3636 * \li
long serial - The serial number of the next outgoing packet associated
3637 * with this connection.
3638 * \li
long callNumber[RX MAXCALLS] - The current call numbers for the
3639 * individual call channels on this connection.
3640 * \li
long error - Records the latest error code for calls occurring on this
3642 * \li
short port - UDP port associated with the connection's peer.
3643 * \li
char flags - State of the connection; see Section 5.2.4 for individual
3645 * \li
char type - Whether the connection is a server-side or client-side one.
3646 * See Section 5.2.5 for individual bit definitions.
3647 * \li
char securityIndex - Index in the associated server-side service class
3648 * of the security
object being used by this call.
3649 * \li
char sparec[3] - Used to force alignment for later fields.
3650 * \li
char callState[RX MAXCALLS] - Current call state on each call channel.
3651 * The associated bit definitions appear in Section 5.2.7.
3652 * \li
char callMode[RX MAXCALLS] - Current mode of all call channels that are
3653 * in RX STATE ACTIVE state. The associated bit definitions appear in Section
3655 * \li
char callFlags[RX MAXCALLS] - Flags pertaining to the state of each of
3656 * the connection's call channels. The associated bit definitions appear in
3658 * \li
char callOther[RX MAXCALLS] - Flag field for each call channel, where
3659 * the presence of the RX OTHER IN flag indicates that there are packets
3660 * present on the given call's reception queue, and the RX OTHER OUT flag
3661 * indicates the presence of packets on the transmission queue.
3662 * \li struct rx securityObjectStats secStats - The contents of the statistics
3663 * related to the security
object selected by the securityIndex field, if any.
3664 * \li
long epoch - The connection's client-side incarnation time.
3665 * \li
long sparel[10] - A set of 10 longword fields, reserved for future use.
3667 * \subsubsection sec5-3-4-5 Section 5.3.4.5: struct rx debugConn vL
3670 * This structure is identical to rx debugConn defined above, except for the
3671 * fact that it is missing the sparec field. This sparec field is used in rx
3672 * debugConn to fix an alignment problem that was discovered in version L of
3673 * the debugging/statistics interface (hence the trailing "tt vL tag in the
3674 * structure name). This alignment problem is fixed in version M, which
3675 * utilizes and exports the rx debugConn structure exclusively. Information
3676 * regarding the range of version-numbering values for the Rx
3677 * debugging/statistics interface may be found in Section 5.2.16.1.
3678 * \section sec5-4 Section 5.4: Exported Variables
3681 * This section describes the set of variables that the Rx facility exports to
3682 * its applications. Some of these variables have macros defined for the sole
3683 * purpose of providing the caller with a convenient way to manipulate them.
3684 * Note that some of these exported variables are never meant to be altered by
3685 * application code (e.g., rx nPackets).
3687 * \subsection sec5-4-1 Section 5.4.1: rx connDeadTime
3690 * This integer-valued variable determines the maximum number of seconds that a
3691 * connection may remain completely inactive, without receiving packets of any
3692 * kind, before it is eligible for garbage collection. Its initial value is 12
3693 * seconds. The rx SetRxDeadTime macro sets the value of this variable.
3695 * \subsection sec5-4-2 Section 5.4.2: rx idleConnectionTime
3698 * This integer-valued variable determines the maximum number of seconds that a
3699 * server connection may "idle" (i.e., not have any active calls and otherwise
3700 * not have sent a packet) before becoming eligible for garbage collection. Its
3701 * initial value is 60 seconds.
3703 * \subsection sec5-4-3 Section 5.4.3: rx idlePeerTime
3706 * This integer-valued variable determines the maximum number of seconds that
3707 * an Rx peer structure is allowed to exist without any connection structures
3708 * referencing it before becoming eligible for garbage collection. Its initial
3709 * value is 60 seconds.
3711 * \subsection sec5-4-4 Section 5.4.4: rx extraQuota
3714 * This integer-valued variable is part of the Rx packet quota system (see
3715 * Section 1.2.6), which is used to avoid system deadlock. This ensures that
3716 * each server-side thread has a minimum number of packets at its disposal,
3717 * allowing it to continue making progress on active calls. This particular
3718 * variable records how many extra data packets a user has requested be
3719 * allocated. Its initial value is 0.
3721 * \subsection sec5-4-5 Section 5.4.5: rx extraPackets
3724 * This integer-valued variable records how many additional packet buffers are
3725 * to be created for each Rx server thread. The caller, upon setting this
3726 * variable, is applying some application-specific knowledge of the level of
3727 * network activity expected. The rx extraPackets variable is used to compute
3728 * the overall number of packet buffers to reserve per server thread, namely rx
3729 * nPackets, described below. The initial value is 32 packets.
3731 * \subsection sec5-4-6 Section 5.4.6: rx nPackets
3734 * This integer-valued variable records the total number of packet buffers to
3735 * be allocated per Rx server thread. It takes into account the quota packet
3736 * buffers and the extra buffers requested by the caller, if any.
3737 * \note This variable should never be set directly; the Rx facility itself
3738 * computes its value. Setting it incorrectly may result in the service
3739 * becoming deadlocked due to insufficient resources. Callers wishing to
3740 * allocate more packet buffers to their server threads should indicate that
3741 * desire by setting the rx extraPackets variable described above.
3743 * \subsection sec5-4-7 Section 5.4.7: rx nFreePackets
3746 * This integer-valued variable records the number of Rx packet buffers not
3747 * currently used by any call. These unused buffers are collected into a free
3750 * \subsection sec5-4-8 Section 5.4.8: rx stackSize
3753 * This integer-valued variable records the size in bytes for the lightweight
3754 * process stack. The variable is initially set to RX DEFAULT STACK SIZE, and
3755 * is typically manipulated via the rx SetStackSize() macro.
3757 * \subsection sec5-4-9 Section 5.4.9: rx packetTypes
3760 * This variable holds an array of
string names used to describe the different
3761 * roles for Rx packets. Its value is derived from the RX PACKET TYPES
3762 * definition found in Section 5.2.11.
3764 * \subsection sec5-4-10 Section 5.4.10: rx stats
3767 * This variable contains the statistics structure that keeps track of Rx
3768 * statistics. The struct rx stats structure it provides is defined in Section
3771 * \section sec5-5 Section 5.5: Macros
3774 * Rx uses many macro definitions in preference to calling C functions
3775 * directly. There are two main reasons for doing this:
3776 * \li field selection: Many Rx operations are easily realized by returning the
3777 * value of a particular structure's field. It is wasteful to invoke a C
3778 * routine to simply fetch a structure's field, incurring unnecessary function
3779 * call overhead. Yet, a convenient, procedure-oriented operation is still
3780 * provided to Rx clients for such operations by the use of macros. For
3781 * example, the rx ConnectionOf() macro, described in Section 5.5.1.1, simply
3782 * indirects through the Rx call structure pointer parameter to deliver the
3784 * \li Performance optimization: In some cases, a simple test or operation can
3785 * be performed to accomplish a particular task. When this simple,
3786 * straightforward operation fails, then a true C routine may be called to
3787 * handle to more complex (and rarer) situation. The Rx macro rx Write(),
3788 * described in Section 5.5.6.2, is a perfect example of this type of
3789 * optimization. Invoking rx Write() first checks to determine whether or not
3790 * the outgoing call's internal buffer has enough room to accept the specified
3791 * data bytes. If so, it copies them into the call's buffer, updating counts
3792 * and pointers as appropriate. Otherwise, rx Write() calls the rx WriteProc()
3793 * to do the work, which in this more complicated case involves packet
3794 * manipulations, dispatches, and allocations. The result is that the common,
3795 * simple cases are often handled in-line, with more complex (and rarer) cases
3796 * handled through true function invocations.
3798 * The set of Rx macros is described according to the following categories.
3799 * \li field selections/assignments
3800 * \li Boolean operations
3801 * \li Service attributes
3802 * \li Security-related operations
3803 * \li Sizing operations
3804 * \li Complex operation
3805 * \li Security operation invocations
3807 * \subsection sec5-5-1 Section 5.5.1: field Selections/Assignments
3810 * These macros facilitate the fetching and setting of fields from the
3811 * structures described Chapter 5.3.
3813 * \subsubsection sec5-5-1-1 Section 5.5.1.1: rx ConnectionOf()
3816 * \
#define rx_ConnectionOf(call) ((call)->conn) 3818 * Generate a reference to the connection field within the given Rx call
3819 * structure. The value supplied as the call argument must resolve into an
3820 *
object of type (
struct rx call *). An application of the rx ConnectionOf()
3821 * macro itself yields an
object of type rx peer.
3823 * \subsubsection sec5-5-1-2 Section 5.5.1.2: rx PeerOf()
3826 * \#define rx_PeerOf(conn) ((conn)->peer)
3828 * Generate a reference to the peer field within the given Rx call structure.
3829 * The value supplied as the conn argument must resolve into an
object of type
3830 * (
struct rx connection *). An instance of the rx PeerOf() macro itself
3831 * resolves into an
object of type rx peer.
3833 * \subsubsection sec5-5-1-3 Section 5.5.1.3: rx HostOf()
3836 * \
#define rx_HostOf(peer) ((peer)->host) 3838 * Generate a reference to the host field within the given Rx peer structure.
3839 * The value supplied as the peer argument must resolve into an
object of type
3840 * (
struct rx peer *). An instance of the rx HostOf() macro itself resolves
3841 * into an
object of type u
long.
3843 * \subsubsection sec5-5-1-4 Section 5.5.1.4: rx PortOf()
3846 * \
#define rx_PortOf(peer) ((peer)->port) 3848 * Generate a reference to the port field within the given Rx peer structure.
3849 * The value supplied as the peer argument must resolve into an
object of type
3850 * (
struct rx peer *). An instance of the rx PortOf() macro itself resolves
3851 * into an
object of type u
short.
3853 * \subsubsection sec5-5-1-5 Section 5.5.1.5: rx GetLocalStatus()
3856 * \
#define rx_GetLocalStatus(call, status) ((call)->localStatus) 3858 * Generate a reference to the localStatus field, which specifies the local
3859 * user status sent out of band, within the given Rx call structure. The value
3860 * supplied as the call argument must resolve into an
object of type (
struct rx
3861 * call *). The second argument, status, is not used. An instance of the rx
3862 * GetLocalStatus() macro itself resolves into an
object of type u
char.
3864 * \subsubsection sec5-5-1-6 Section 5.5.1.6: rx SetLocalStatus()
3867 * \
#define rx_SetLocalStatus(call, status) ((call)->localStatus = (status)) 3869 * Assign the contents of the localStatus field, which specifies the local user
3870 * status sent out of band, within the given Rx call structure. The value
3871 * supplied as the call argument must resolve into an
object of type (
struct rx
3872 * call *). The second argument, status, provides the
new value of the
3873 * localStatus field, and must resolve into an
object of type u
char. An
3874 * instance of the rx GetLocalStatus() macro itself resolves into an
object 3875 * resulting from the assignment, namely the u
char status parameter.
3877 * \subsubsection sec5-5-1-7 Section 5.5.1.7: rx GetRemoteStatus()
3880 * \
#define rx_GetRemoteStatus(call) ((call)->remoteStatus) 3882 * Generate a reference to the remoteStatus field, which specifies the remote
3883 * user status received out of band, within the given Rx call structure. The
3884 * value supplied as the call argument must resolve into an
object of type
3885 * (
struct rx call *). An instance of the rx GetRemoteStatus() macro itself
3886 * resolves into an
object of type u
char.
3888 * \subsubsection sec5-5-1-8 Section 5.5.1.8: rx Error()
3891 * \
#define rx_Error(call) ((call)->error) 3893 * Generate a reference to the error field, which specifies the current error
3894 * condition, within the given Rx call structure. The value supplied as the
3895 * call argument must resolve into an
object of type (
struct rx call *). An
3896 * instance of the rx Error() macro itself resolves into an
object of type
3899 * \subsubsection sec5-5-1-9 Section 5.5.1.9: rx DataOf()
3902 * \
#define rx_DataOf(packet) ((char *) (packet)->wire.data) 3904 * Generate a reference to the beginning of the data portion within the given
3905 * Rx packet as it appears on the wire. Any encryption headers will be resident
3906 * at
this address. For Rx packets of type RX PACKET TYPE DATA, the actual user
3907 * data will appear at the address returned by the rx DataOf macro plus the
3908 * connection
's security header size. The value supplied as the packet argument 3909 * must resolve into an object of type (struct rx packet *). An instance of the 3910 * rx DataOf() macro itself resolves into an object of type (u long *). 3912 * \subsubsection sec5-5-1-10 Section 5.5.1.10: rx GetDataSize() 3915 * \#define rx_GetDataSize(packet) ((packet)->length) 3917 * Generate a reference to the length field, which specifies the number of 3918 * bytes of user data contained within the wire form of the packet, within the 3919 * given Rx packet description structure. The value supplied as the packet 3920 * argument must resolve into an object of type (struct rx packet *). An 3921 * instance of the rx GetDataSize() macro itself resolves into an object of 3924 * \subsubsection sec5-5-1-11 Section 5.5.1.11: rx SetDataSize() 3927 * \#define rx_SetDataSize(packet, size) ((packet)->length = (size)) 3929 * Assign the contents of the length field, which specifies the number of bytes 3930 * of user data contained within the wire form of the packet, within the given 3931 * Rx packet description structure. The value supplied as the packet argument 3932 * must resolve into an object of type (struct rx packet *). The second 3933 * argument, size, provides the new value of the length field, and must resolve 3934 * into an object of type short. An instance of the rx SetDataSize() macro 3935 * itself resolves into an object resulting from the assignment, namely the 3936 * short length parameter. 3938 * \subsubsection sec5-5-1-12 Section 5.5.1.12: rx GetPacketCksum() 3941 * \#define rx_GetPacketCksum(packet) ((packet)->header.spare) 3943 * Generate a reference to the header checksum field, as used by the built-in 3944 * rxkad security module (See Chapter 3), within the given Rx packet 3945 * description structure. The value supplied as the packet argument must 3946 * resolve into an object of type (struct rx packet *). An instance of the rx 3947 * GetPacketCksum() macro itself resolves into an object of type u short. 3949 * \subsubsection sec5-5-1-13 Section 5.5.1.13: rx SetPacketCksum() 3952 * \#define rx_SetPacketCksum(packet, cksum) ((packet)->header.spare = (cksum)) 3954 * Assign the contents of the header checksum field, as used by the built-in 3955 * rxkad security module (See Chapter 3), within the given Rx packet 3956 * description structure. The value supplied as the packet argument must 3957 * resolve into an object of type (struct rx packet *). The second argument, 3958 * cksum, provides the new value of the checksum, and must resolve into an 3959 * object of type u short. An instance of the rx SetPacketCksum() macro itself 3960 * resolves into an object resulting from the assignment, namely the u short 3961 * checksum parameter. 3963 * \subsubsection sec5-5-1-14 Section 5.5.1.14: rx GetRock() 3966 * \#define rx_GetRock(obj, type) ((type)(obj)->rock) 3968 * Generate a reference to the field named rock within the object identified by 3969 * the obj pointer. One common Rx structure to which this macro may be applied 3970 * is struct rx connection. The specified rock field is casted to the value of 3971 * the type parameter, which is the overall value of the rx GetRock() macro. 3973 * \subsubsection sec5-5-1-15 Section 5.5.1.15: rx SetRock() 3976 * \#define rx_SetRock(obj, newrock) ((obj)->rock = (VOID *)(newrock)) 3978 * Assign the contents of the newrock parameter into the rock field of the 3979 * object pointed to by obj. The given object's rock field must be of type
3980 * (VOID *). An instance of the rx SetRock() macro itself resolves into an
3981 *
object resulting from the assignment and is of type (VOID *).
3983 * \subsubsection sec5-5-1-16 Section 5.5.1.16: rx SecurityClassOf()
3986 * \
#define rx_SecurityClassOf(conn) ((conn)->securityIndex) 3988 * Generate a reference to the security index field of the given Rx connection
3989 * description structure. This identifies the security
class used by the
3990 * connection. The value supplied as the conn argument must resolve into an
3991 *
object of type (
struct rx connection *). An instance of the rx
3992 * SecurityClassOf() macro itself resolves into an
object of type u
char.
3994 * \subsubsection sec5-5-1-17 Section 5.5.1.17: rx SecurityObjectOf()
3997 * \
#define rx_SecurityObjectOf(conn) ((conn)->securityObject) 3999 * Generate a reference to the security
object in use by the given Rx
4000 * connection description structure. The choice of security
object determines
4001 * the authentication protocol enforced by the connection. The value supplied
4002 * as the conn argument must resolve into an
object of type (
struct rx
4003 * connection *). An instance of the rx SecurityObjectOf() macro itself
4004 * resolves into an
object of type (struct rx securityClass *).
4006 * \subsection sec5-5-2 Section 5.5.2: Boolean Operations
4009 * The macros described in this section all return Boolean values. They are
4010 * used to query such things as the whether a connection is a server-side or
4011 * client-side one and if extra levels of checksumming are being used in Rx
4014 * \subsubsection sec5-5-2-1 Section 5.5.2.1: rx IsServerConn()
4017 * \
#define rx_IsServerConn(conn) ((conn)->type == RX_SERVER_CONNECTION) 4019 * Determine whether or not the Rx connection specified by the conn argument is
4020 * a server-side connection. The value supplied
for conn must resolve to an
4021 *
object of type
struct rx connection. The result is determined by testing
4022 * whether or not the connection
's type field is set to RX SERVER CONNECTION. 4023 * \note Another macro, rx ServerConn(), performs the identical operation. 4025 * \subsubsection sec5-5-2-2 Section 5.5.2.2: rx IsClientConn() 4028 * \#define rx_IsClientConn(conn) ((conn)->type == RX_CLIENT_CONNECTION) 4030 * Determine whether or not the Rx connection specified by the conn argument is 4031 * a client-side connection. The value supplied for conn must resolve to an 4032 * object of type struct rx connection. The result is determined by testing 4033 * whether or not the connection's type field is
set to RX CLIENT CONNECTION.
4034 * \note Another macro, rx ClientConn(), performs the identical operation.
4036 * \subsubsection sec5-5-2-3 Section 5.5.2.2: rx IsUsingPktCksum()
4039 * \#define rx_IsUsingPktCksum(conn) ((conn)->flags &
4040 * RX_CONN_USING_PACKET_CKSUM)
4042 * Determine whether or not the Rx connection specified by the conn argument is
4043 * checksum-ming the headers of all packets on its calls. The value supplied
4044 *
for conn must resolve to an
object of type
struct rx connection. The result
4045 * is determined by testing whether or not the connection
's flags field has the 4046 * RX CONN USING PACKET CKSUM bit enabled. 4048 * \subsection sec5-5-3 Section 5.5.3: Service Attributes 4051 * This section describes user-callable macros that manipulate the attributes 4052 * of an Rx service. Note that these macros must be called (and hence their 4053 * operations performed) before the given service is installed via the 4054 * appropriate invocation of the associated rx StartServer() function. 4056 * \subsubsection sec5-5-3-1 Section 5.5.3.1: rx SetStackSize() 4059 * rx_stackSize = (((stackSize) stackSize) > rx_stackSize) ? stackSize : 4062 * Inform the Rx facility of the stack size in bytes for a class of threads to 4063 * be created in support of Rx services. The exported rx stackSize variable 4064 * tracks the high-water mark for all stack size requests before the call to rx 4065 * StartServer(). If no calls to rx SetStackSize() are made, then rx stackSize 4066 * will retain its default setting of RX DEFAULT STACK SIZE. 4068 * In this macro, the first argument is not used. It was originally intended 4069 * that thread stack sizes would be settable on a per-service basis. However, 4070 * calls to rx SetStackSize() will ignore the service parameter and set the 4071 * high-water mark for all Rx threads created after the use of rx 4072 * SetStackSize(). The second argument, stackSize, specifies determines the new 4073 * stack size, and should resolve to an object of type int. The value placed in 4074 * the stackSize parameter will not be recorded in the global rx stackSize 4075 * variable unless it is greater than the variable's current setting.
4077 * An instance of the rx SetStackSize() macro itself resolves into the result
4078 * of the assignment, which is an
object of type
int.
4080 * \subsubsection sec5-5-3-2 Section 5.5.3.2: rx SetMinProcs()
4083 * \
#define rx_SetMinProcs(service, min) ((service)->minProcs = (min)) 4085 * Choose min as the minimum number of threads guaranteed to be available
for 4086 * parallel execution of the given Rx service. The service parameter should
4087 * resolve to an
object of type
struct rx service. The min parameter should
4088 * resolve to an
object of type
short. An instance of the rx SetMinProcs()
4089 * macro itself resolves into the result of the assignment, which is an
object 4092 * \subsubsection sec5-5-3-3 Section 5.5.3.3: rx SetMaxProcs()
4095 * \#define rx_SetMaxProcs(service, max) ((service)->maxProcs = (max))
4097 * Limit the maximum number of threads that may be made available to the given
4098 * Rx service
for parallel execution to be max. The service parameter should
4099 * resolve to an
object of type
struct rx service. The max parameter should
4100 * resolve to an
object of type
short. An instance of the rx SetMaxProcs()
4101 * macro itself resolves into the result of the assignment, which is an
object 4104 * \subsubsection sec5-5-3-4 Section 5.5.3.4: rx SetIdleDeadTime()
4107 * \#define rx_SetIdleDeadTime(service, time) ((service)->idleDeadTime =
4110 * Every Rx service has a maximum amount of time it is willing to have its
4111 * active calls sit idle (i.e., no
new data is read or written
for a call
4112 * marked as RX STATE ACTIVE) before unilaterally shutting down the call. The
4113 * expired call will have its error field
set to RX CALL TIMEOUT. The operative
4114 * assumption in
this situation is that the client code is exhibiting a
4115 * protocol error that prevents progress from being made on
this call, and thus
4116 * the call
's resources on the server side should be freed. The default value, 4117 * as recorded in the service's idleDeadTime field, is
set at service creation
4118 * time to be 60 seconds. The rx SetIdleTime() macro allows a caller to
4119 * dynamically set this idle call timeout value.
4121 * The service parameter should resolve to an
object of type struct rx service.
4122 * Also, the time parameter should resolve to an
object of type
short. finally,
4123 * an instance of the rx SetIdleDeadTime() macro itself resolves into the
4124 * result of the assignment, which is an
object of type
short.
4126 * \subsubsection sec5-5-3-5 Section 5.5.3.5: rx SetServiceDeadTime()
4129 * \
#define rx_SetServiceDeadTime(service, seconds) 4130 * ((service)->secondsUntilDead = (seconds))
4131 * \note This macro definition is obsolete and should NOT be used. Including it
4132 * in application code will generate a compile-time error, since the service
4133 * structure no longer has such a field defined.
4135 * See the description of the rx SetConnDeadTime() macro below to see how hard
4136 * timeouts may be
set for situations of complete call inactivity.
4138 * \subsubsection sec5-5-3-6 Section 5.5.3.6: rx SetRxDeadTime()
4141 * \#define rx_SetRxDeadTime(seconds) (rx_connDeadTime = (seconds))
4143 * Inform the Rx facility of the maximum number of seconds of complete
4144 * inactivity that will be tolerated on an active call. The exported rx
4145 * connDeadTime variable tracks
this value, and is initialized to a value of 12
4146 * seconds. The current value of rx connDeadTime will be copied into
new Rx
4147 * service and connection records upon their creation.
4149 * The seconds argument determines the value of rx connDeadTime, and should
4150 * resolve to an
object of type
int. An instance of the rx SetRxDeadTime()
4151 * macro itself resolves into the result of the assignment, which is an
object 4154 * \subsubsection sec5-5-3-7 Section 5.5.3.7: rx SetConnDeadTime()
4157 * \#define rx_SetConnDeadTime(conn, seconds) (rxi_SetConnDeadTime(conn,
4160 * Every Rx connection has a maximum amount of time it is willing to have its
4161 * active calls on a server connection sit without receiving packets of any
4162 * kind from its peer. After such a quiescent time, during which neither data
4163 * packets (regardless of whether they are properly sequenced or duplicates)
4164 * nor keep-alive packets are received, the call
's error field is set to RX 4165 * CALL DEAD and the call is terminated. The operative assumption in this 4166 * situation is that the client making the call has perished, and thus the 4167 * call's resources on the server side should be freed. The
default value, as
4168 * recorded in the connection
's secondsUntilDead field, is set at connection 4169 * creation time to be the same as its parent service. The rx SetConnDeadTime() 4170 * macro allows a caller to dynamically set this timeout value. 4172 * The conn parameter should resolve to an object of type struct rx connection. 4173 * Also, the seconds parameter should resolve to an object of type int. 4174 * finally, an instance of the rx SetConnDeadTime() macro itself resolves into 4175 * the a call to rxi SetConnDeadTime(), whose return value is void. 4177 * \subsubsection sec5-5-3-8 Section 5.5.3.8: rx SetConnHardDeadTime() 4180 * \#define rx_SetConnHardDeadTime(conn, seconds) ((conn)->hardDeadTime = 4183 * It is convenient to be able to specify that calls on certain Rx connections 4184 * have a hard absolute timeout. This guards against protocol errors not caught 4185 * by other checks in which one or both of the client and server are looping. 4186 * The rx SetConnHardDeadTime() macro is available for this purpose. It will 4187 * limit calls on the connection identified by the conn parameter to execution 4188 * times of no more than the given number of seconds. By default, active calls 4189 * on an Rx connection may proceed for an unbounded time, as long as they are 4190 * not totally quiescent (see Section 5.5.3.7 for a description of the rx 4191 * SetConnDeadTime()) or idle (see Section 5.5.3.4 for a description of the rx 4192 * SetIdleDeadTime()). 4194 * The conn parameter should resolve to an object of type (struct rx connection 4195 * *). The seconds parameter should resolve to an object of type u short. An 4196 * instance of the rx SetConnHardDeadTime() macro itself resolves into the 4197 * result of the assignment, which is an object of type u short. 4199 * \subsubsection sec5-5-3-9 Section 5.5.3.9: rx GetBeforeProc() 4202 * \#define rx_GetBeforeProc(service) ((service)->beforeProc) 4204 * Return a pointer of type (VOID *)() to the procedure associated with the 4205 * given Rx service that will be called immediately upon activation of a server 4206 * thread to handle an incoming call. The service parameter should resolve to 4207 * an object of type struct rx service. 4209 * When an Rx service is first created (via a call to the rx NewService() 4210 * function), its beforeProc field is set to a null pointer. See the 4211 * description of the rx SetBeforeProc() below. 4213 * \subsubsection sec5-5-3-10 Section 5.5.3.10: rx SetBeforeProc() 4216 * \#define rx_SetBeforeProc(service, proc) ((service)->beforeProc = (proc)) 4218 * Instruct the Rx facility to call the procedure identified by the proc 4219 * parameter immediately upon activation of a server thread to handle an 4220 * incoming call. The specified procedure will be called with a single 4221 * parameter, a pointer of type struct rx call, identifying the call this 4222 * thread will now be responsible for handling. The value returned by the 4223 * procedure, if any, is discarded. 4225 * The service parameter should resolve to an object of type struct rx service. 4226 * The proc parameter should resolve to an object of type (VOID *)(). An 4227 * instance of the rx SetBeforeProc() macro itself resolves into the result of 4228 * the assignment, which is an object of type (VOID *)(). 4230 * \subsubsection sec5-5-3-11 Section 5.5.3.11: rx GetAfterProc() 4233 * \#define rx_GetAfterProc(service) ((service)->afterProc) 4235 * Return a pointer of type (VOID *)() to the procedure associated with the 4236 * given Rx service that will be called immediately upon completion of the 4237 * particular Rx call for which a server thread was activated. The service 4238 * parameter should resolve to an object of type struct rx service. 4240 * When an Rx service is first created (via a call to the rx NewService() 4241 * function), its afterProc field is set to a null pointer. See the description 4242 * of the rx SetAfterProc() below. 4244 * \subsubsection sec5-5-3-12 Section 5.5.3.12: rx SetAfterProc() 4247 * \#define rx_SetAfterProc(service, proc) ((service)->afterProc = (proc)) 4249 * Instruct the Rx facility to call the procedure identified by the proc 4250 * parameter immediately upon completion of the particular Rx call for which a 4251 * server thread was activated. The specified procedure will be called with a 4252 * single parameter, a pointer of type struct rx call, identifying the call 4253 * this thread just handled. The value returned by the procedure, if any, is 4256 * The service parameter should resolve to an object of type struct rx service. 4257 * The proc parameter should resolve to an object of type (VOID *)(). An 4258 * instance of the rx SetAfterProc() macro itself resolves into the result of 4259 * the assignment, which is an object of type (VOID *)(). 4261 * \subsubsection sec5-5-3-13 Section 5.5.3.13: rx SetNewConnProc() 4264 * \#define rx_SetNewConnProc(service, proc) ((service)->newConnProc = (proc)) 4266 * Instruct the Rx facility to call the procedure identified by the proc 4267 * parameter as the last step in the creation of a new Rx server-side 4268 * connection for the given service. The specified procedure will be called 4269 * with a single parameter, a pointer of type (struct rx connection *), 4270 * identifying the connection structure that was just built. The value returned 4271 * by the procedure, if any, is discarded. 4273 * The service parameter should resolve to an object of type struct rx service. 4274 * The proc parameter should resolve to an object of type (VOID *)(). An 4275 * instance of the rx SetNewConnProc() macro itself resolves into the result of 4276 * the assignment, which is an object of type (VOID *)(). 4277 * \note There is no access counterpart defined for this macro, namely one that 4278 * returns the current setting of a service's newConnProc.
4280 * \subsubsection sec5-5-3-14 Section 5.5.3.14: rx SetDestroyConnProc()
4283 * \#define rx_SetDestroyConnProc(service, proc) ((service)->destroyConnProc =
4286 * Instruct the Rx facility to call the procedure identified by the proc
4287 * parameter just before a server connection associated with the given Rx
4288 * service is destroyed. The specified procedure will be called with a single
4289 * parameter, a pointer of type (
struct rx connection *), identifying the
4290 * connection about to be destroyed. The value returned by the procedure,
if 4291 * any, is discarded.
4293 * The service parameter should resolve to an
object of type
struct rx service.
4294 * The proc parameter should resolve to an
object of type (VOID *)(). An
4295 * instance of the rx SetDestroyConnProc() macro itself resolves into the
4296 * result of the assignment, which is an
object of type (VOID *)().
4297 * \note There is no access counterpart defined
for this macro, namely one that
4298 * returns the current setting of a service
's destroyConnProc. 4300 * \subsection sec5-5-4 Section 5.5.4: Security-Related Operations 4303 * The following macros are callable by Rx security modules, and assist in 4304 * getting and setting header and trailer lengths, setting actual packet size, 4305 * and finding the beginning of the security header (or data). 4307 * \subsubsection sec5-5-4-1 Section 5.5.4.1: rx GetSecurityHeaderSize() 4310 * \#define rx_GetSecurityHeaderSize(conn) ((conn)->securityHeaderSize) 4312 * Generate a reference to the field in an Rx connection structure that records 4313 * the length in bytes of the associated security module's packet header data.
4315 * The conn parameter should resolve to an
object of type
struct rx connection.
4316 * An instance of the rx GetSecurityHeaderSize() macro itself resolves into an
4317 *
object of type u
short.
4319 * \subsubsection sec5-5-4-2 Section 5.5.4.2: rx SetSecurityHeaderSize()
4322 * \#define rx_SetSecurityHeaderSize(conn, length) ((conn)->securityHeaderSize
4325 * Set the field in a connection structure that records the length in bytes of
4326 * the associated security module
's packet header data. 4328 * The conn parameter should resolve to an object of type struct rx connection. 4329 * The length parameter should resolve to an object of type u short. An 4330 * instance of the rx SetSecurityHeaderSize() macro itself resolves into the 4331 * result of the assignment, which is an object of type u short. 4333 * \subsubsection sec5-5-4-3 Section 5.5.4.3: rx 4334 * GetSecurityMaxTrailerSize() 4337 * \#define rx_GetSecurityMaxTrailerSize(conn) ((conn)->securityMaxTrailerSize) 4339 * Generate a reference to the field in an Rx connection structure that records 4340 * the maximum length in bytes of the associated security module's packet
4343 * The conn parameter should resolve to an
object of type
struct rx connection.
4344 * An instance of the rx GetSecurityMaxTrailerSize() macro itself resolves into
4345 * an
object of type u
short.
4347 * \subsubsection sec5-5-4-4 Section 5.5.4.4: rx
4348 * SetSecurityMaxTrailerSize()
4351 * \#define rx_SetSecurityMaxTrailerSize(conn, length)
4352 * ((conn)->securityMaxTrailerSize = (length))
4354 * Set the field in a connection structure that records the maximum length in
4355 * bytes of the associated security module
's packet trailer data. 4357 * The conn parameter should resolve to an object of type struct rx connection. 4358 * The length parameter should resolve to an object of type u short. An 4359 * instance of the rx SetSecurityHeaderSize() macro itself resolves into the 4360 * result of the assignment, which is an object of type u short. 4362 * \subsection sec5-5-5 Section 5.5.5: Sizing Operations 4365 * The macros described in this section assist the application programmer in 4366 * determining the sizes of the various Rx packet regions, as well as their 4367 * placement within a packet buffer. 4369 * \subsubsection sec5-5-5-1 Section 5.5.5.1: rx UserDataOf() 4372 * \#define rx_UserDataOf(conn, packet) (((char *) (packet)->wire.data) + 4373 * (conn)->securityHeaderSize) 4375 * Generate a pointer to the beginning of the actual user data in the given Rx 4376 * packet, that is associated with the connection described by the conn 4377 * pointer. User data appears immediately after the packet's security header
4378 * region, whose length is determined by the security module used by the
4379 * connection. The conn parameter should resolve to an
object of type
struct rx
4380 * connection. The packet parameter should resolve to an
object of type
struct 4381 * rx packet. An instance of the rx UserDataOf() macro itself resolves into an
4382 *
object of type (
char *).
4384 * \subsubsection sec5-5-5-2 Section 5.5.5.2: rx MaxUserDataSize()
4387 * \#define rx_MaxUserDataSize(conn)
4388 * \n ((conn)->peer->packetSize
4389 * \n -RX_HEADER_SIZE
4390 * \n -(conn)->securityHeaderSize
4391 * \n -(conn)->securityMaxTrailerSize)
4393 * Return the maximum number of user data bytes that may be carried by a packet
4394 * on the Rx connection described by the conn pointer. The overall packet size
4395 * is reduced by the IP, UDP, and Rx headers, as well as the header and trailer
4396 * areas required by the connection
's security module. 4398 * The conn parameter should resolve to an object of type struct rx connection. 4399 * An instance of the rx MaxUserDataSize() macro itself resolves into the an 4400 * object of type (u short). 4402 * \subsection sec5-5-6 Section 5.5.6: Complex Operations 4405 * Two Rx macros are designed to handle potentially complex operations, namely 4406 * reading data from an active incoming call and writing data to an active 4407 * outgoing call. Each call structure has an internal buffer that is used to 4408 * collect and cache data traveling through the call. This buffer is used in 4409 * conjunction with reading or writing to the actual Rx packets traveling on 4410 * the wire in support of the call. The rx Read() and rx Write() macros allow 4411 * their caller to simply manipulate the internal data buffer associated with 4412 * the Rx call structures whenever possible, thus avoiding the overhead 4413 * associated with a function call. When buffers are either filled or drained 4414 * (depending on the direction of the data flow), these macros will then call 4415 * functions to handle the more complex cases of generating or receiving 4416 * packets in support of the operation. 4418 * \subsubsection sec5-5-6-1 Section 5.5.6.1: rx Read() 4421 * \#define rx_Read(call, buf, nbytes) 4422 * \n ((call)->nLeft > (nbytes) ? 4423 * \n bcopy((call)->bufPtr, (buf), (nbytes)), 4424 * \n (call)->nLeft -= (nbytes), (call)->bufPtr += (nbytes), (nbytes) 4425 * \n : rx_ReadProc((call), (buf), (nbytes))) 4427 * Read nbytes of data from the given Rx call into the buffer to which buf 4428 * points. If the call's
internal buffer has at least nbytes bytes already
4429 * filled, then
this is done in-line with a copy and some pointer and counter
4430 * updates within the call structure. If the call
's internal buffer doesn't
4431 * have enough data to satisfy the request, then the rx ReadProc() function
4432 * will handle this more complex situation.
4434 * In either case, the rx Read() macro returns the number of bytes actually
4435 * read from the call, resolving to an
object of type
int. If rx Read() returns
4436 * fewer than nbytes bytes, the call status should be checked via the rx
4439 * \subsubsection sec5-5-6-2 Section 5.5.6.2: rx Write()
4442 * \
#define rx_Write(call, buf, nbytes) 4443 * \n ((call)->nFree > (nbytes) ?
4444 * \n bcopy((buf), (call)->bufPtr, (nbytes)),
4445 * \n (call)->nFree -= (nbytes),
4446 * \n (call)->bufPtr += (nbytes), (nbytes)
4447 * \n : rx_WriteProc((call), (buf), (nbytes)))
4449 * Write nbytes of data from the buffer pointed to by buf into the given Rx
4450 * call. If the call
's internal buffer has at least nbytes bytes free, then 4451 * this is done in-line with a copy and some pointer and counter updates within 4452 * the call structure. If the call's
internal buffer doesn
't have room, then 4453 * the rx WriteProc() function will handle this more complex situation. 4455 * In either case, the rx Write() macro returns the number of bytes actually 4456 * written to the call, resolving to an object of type int. If zero is 4457 * returned, the call status should be checked via the rx Error() macro. 4459 * \subsection sec5-5-7 Section 5.5.7: Security Operation Invocations 4462 * Every Rx security module is required to implement an identically-named set 4463 * of operations, through which the security mechanism it defines is invoked. 4464 * This characteristic interface is reminiscent of the vnode interface defined 4465 * and popularized for file systems by Sun Microsystems [4]. The structure 4466 * defining this function array is described in Section 5.3.1.1. 4468 * These security operations are part of the struct rx securityClass, which 4469 * keeps not only the ops array itself but also any private data they require 4470 * and a reference count. Every Rx service contains an array of these security 4471 * class objects, specifying the range of security mechanisms it is capable of 4472 * enforcing. Every Rx connection within a service is associated with exactly 4473 * one of that service's security objects, and every call issued on the
4474 * connection will execute the given security protocol.
4476 * The macros described below facilitate the execution of the security module
4477 *
interface functions. They are covered in the same order they appear in the
4478 *
struct rx securityOps declaration.
4480 * \subsubsection sec5-5-7-1 Section 5.5.7.1: RXS OP()
4483 * #
if defined(__STDC__) && !defined(__HIGHC__)
4484 * #define RXS_OP(obj, op, args)
4485 * ((obj->ops->op_ ## op) ? (*(obj)->ops->op_ ## op)args : 0)
4487 * #define RXS_OP(obj, op, args)
4488 * ((obj->ops->op_op) ? (*(obj)->ops->op_op)args : 0)
4493 * The RXS OP macro represents the workhorse macro in
this group, used by all
4494 * the others. It takes three arguments, the first of which is a pointer to the
4495 * security
object to be referenced. This obj parameter must resolve to an
4496 *
object of type (
struct rx securityOps *). The second parameter identifies
4497 * the specific op to be performed on
this security
object. The actual text of
4498 *
this op argument is used to name the desired opcode
function. The third and
4499 *
final argument, args, specifies the text of the argument list to be fed to
4500 * the chosen security
function. Note that
this argument must contain the
4501 * bracketing parentheses
for the
function call
's arguments. In fact, note that 4502 * each of the security function access macros defined below provides the 4503 * enclosing parentheses to this third RXS OP() macro. 4505 * \subsubsection sec5-5-7-2 Section 5.5.7.1: RXS Close() 4508 * \#define RXS_Close(obj) RXS_OP(obj, Close, (obj)) 4510 * This macro causes the execution of the interface routine occupying the op 4511 * Close() slot in the Rx security object identified by the obj pointer. This 4512 * interface function is invoked by Rx immediately before a security object is 4513 * discarded. Among the responsibilities of such a function might be 4514 * decrementing the object's refCount field, and thus perhaps freeing up any
4515 * space contained within the security
object's private storage region, 4516 * referenced by the object's privateData field.
4518 * The obj parameter must resolve into an
object of type (
struct rx securityOps
4519 * *). In generating a call to the security
object's op Close() routine, the 4520 * obj pointer is used as its single parameter. An invocation of the RXS 4521 * Close() macro results in a return value identical to that of the op Close() 4522 * routine, namely a value of type int. 4524 * \subsubsection sec5-5-7-3 Section 5.5.7.3: RXS NewConnection() 4527 * \#define RXS_NewConnection(obj, conn) RXS_OP(obj, NewConnection, (obj, 4530 * This macro causes the execution of the interface routine in the op 4531 * NewConnection() slot in the Rx security object identified by the obj 4532 * pointer. This interface function is invoked by Rx immediately after a 4533 * connection using the given security object is created. Among the 4534 * responsibilities of such a function might be incrementing the object's
4535 * refCount field, and setting any per-connection information based on the
4536 * associated security
object's private storage region, as referenced by the 4537 * object's privateData field.
4539 * The obj parameter must resolve into an
object of type (
struct rx securityOps
4540 * *). The conn argument contains a pointer to the newly-created connection
4541 * structure, and must resolve into an
object of type (
struct rx connection *).
4543 * In generating a call to the routine located at the security
object's op 4544 * NewConnection() slot, the obj and conn pointers are used as its two 4545 * parameters. An invocation of the RXS NewConnection() macro results in a 4546 * return value identical to that of the op NewConnection() routine, namely a 4547 * value of type int. 4549 * \subsubsection sec5-5-7-4 Section 5.5.7.4: RXS PreparePacket() 4552 * \#define RXS_PreparePacket(obj, call, packet) 4553 * \n RXS_OP(obj, PreparePacket, (obj, call, packet)) 4555 * This macro causes the execution of the interface routine in the op 4556 * PreparePacket() slot in the Rx security object identified by the obj 4557 * pointer. This interface function is invoked by Rx each time it prepares an 4558 * outward-bound packet. Among the responsibilities of such a function might be 4559 * computing information to put into the packet's security header and/or
4562 * The obj parameter must resolve into an
object of type (
struct rx securityOps
4563 * *). The call argument contains a pointer to the Rx call to which the given
4564 * packet belongs, and must resolve to an
object of type (
struct rx call *).
4565 * The
final argument, packet, contains a pointer to the packet itself. It
4566 * should resolve to an
object of type (
struct rx packet *).
4568 * In generating a call to the routine located at the security
object's op 4569 * PreparePacket() slot, the obj, call, and packet pointers are used as its 4570 * three parameters. An invocation of the RXS PreparePacket() macro results in 4571 * a return value identical to that of the op PreparePacket() routine, namely a 4572 * value of type int. 4574 * \subsubsection sec5-5-7-5 Section 5.5.7.5: RXS SendPacket() 4577 * \#define RXS_SendPacket(obj, call, packet) RXS_OP(obj, SendPacket, (obj, 4580 * This macro causes the execution of the interface routine occupying the op 4581 * SendPacket() slot in the Rx security object identified by the obj pointer. 4582 * This interface function is invoked by Rx each time it physically transmits 4583 * an outward-bound packet. Among the responsibilities of such a function might 4584 * be recomputing information in the packet's security header and/or trailer.
4586 * The obj parameter must resolve into an
object of type (
struct rx securityOps
4587 * *). The call argument contains a pointer to the Rx call to which the given
4588 * packet belongs, and must resolve to an
object of type (
struct rx call *).
4589 * The
final argument, packet, contains a pointer to the packet itself. It
4590 * should resolve to an
object of type (
struct rx packet *).
4592 * In generating a call to the routine located at the security
object's op 4593 * SendPacket() slot, the obj, call, and packet pointers are used as its three 4594 * parameters. An invocation of the RXS SendPacket() macro results in a return 4595 * value identical to that of the op SendPacket() routine, namely a value of 4598 * \subsubsection sec5-5-7-6 Section 5.5.7.6: RXS CheckAuthentication() 4601 * \#define RXS_CheckAuthentication(obj, conn) RXS_OP(obj, CheckAuthentication, 4604 * This macro causes the execution of the interface routine in the op 4605 * CheckAuthentication() slot in the Rx security object identified by the obj 4606 * pointer. This interface function is invoked by Rx each time it needs to 4607 * check whether the given connection is one on which authenticated calls are 4608 * being performed. Specifically, a value of 0 is returned if authenticated 4609 * calls are not being executed on this connection, and a value of 1 is 4610 * returned if they are. 4612 * The obj parameter must resolve into an object of type (struct rx securityOps 4613 * *). The conn argument contains a pointer to the Rx connection checked as to 4614 * whether authentication is being performed, and must resolve to an object of 4615 * type (struct rx connection *). 4617 * In generating a call to the routine in the security object's op
4618 * CheckAuthentication() slot, the obj and conn pointers are used as its two
4619 * parameters. An invocation of the RXS CheckAuthentication() macro results in
4620 * a return value identical to that of the op CheckAuthentication() routine,
4621 * namely a value of type
int.
4623 * \subsubsection sec5-5-7-7 Section 5.5.7.7: RXS CreateChallenge()
4626 * \
#define RXS_CreateChallenge(obj, conn) RXS_OP(obj, CreateChallenge, (obj, 4629 * This macro causes the execution of the
interface routine in the op
4630 * CreateChallenge() slot in the Rx security
object identified by the obj
4631 * pointer. This interface function is invoked by Rx each time a challenge
4632 * event is constructed for a given connection. Among the responsibilities of
4633 * such a function might be marking the connection as temporarily
4634 * unauthenticated until the given challenge is successfully met.
4636 * The obj parameter must resolve into an
object of type (struct rx securityOps
4637 * *). The conn argument contains a pointer to the Rx connection for which the
4638 * authentication challenge is being constructed, and must resolve to an
object 4639 * of type (struct rx connection *).
4641 * In generating a call to the routine located at the security
object's op
4642 * CreateChallenge() slot, the obj and conn pointers are used as its two
4643 * parameters. An invocation of the RXS CreateChallenge() macro results in a
4644 * return value identical to that of the op CreateChallenge() routine, namely a
4645 * value of type
int.
4647 * \subsubsection sec5-5-7-8 Section 5.5.7.8: RXS GetChallenge()
4650 * \
#define RXS_GetChallenge(obj, conn, packet) RXS_OP(obj, GetChallenge, (obj, 4653 * This macro causes the execution of the
interface routine occupying the op
4654 * GetChallenge() slot in the Rx security
object identified by the obj pointer.
4655 * This interface function is invoked by Rx each time a challenge packet is
4656 * constructed for a given connection. Among the responsibilities of such a
4657 * function might be constructing the appropriate challenge structures in the
4658 * area of packet dedicated to security matters.
4660 * The obj parameter must resolve into an
object of type (struct rx securityOps
4661 * *). The conn argument contains a pointer to the Rx connection to which the
4662 * given challenge packet belongs, and must resolve to an
object of type
4663 * (struct rx connection *). The final argument, packet, contains a pointer to
4664 * the challenge packet itself. It should resolve to an
object of type (struct
4667 * In generating a call to the routine located at the security
object's op
4668 * GetChallenge() slot, the obj, conn, and packet pointers are used as its
4669 * three parameters. An invocation of the RXS GetChallenge() macro results in a
4670 * return value identical to that of the op GetChallenge() routine, namely a
4671 * value of type
int.
4673 * \subsubsection sec5-5-7-9 Section 5.5.7.9: RXS GetResponse()
4676 * \
#define RXS_GetResponse(obj, conn, packet) RXS_OP(obj, GetResponse, (obj, 4679 * This macro causes the execution of the
interface routine occupying the op
4680 * GetResponse() slot in the Rx security
object identified by the obj pointer.
4681 * This interface function is invoked by Rx on the server side each time a
4682 * response to a challenge packet must be received.
4684 * The obj parameter must resolve into an
object of type (struct rx securityOps
4685 * *). The conn argument contains a pointer to the Rx client connection that
4686 * must respond to the authentication challenge, and must resolve to a (struct
4687 * rx connection *)
object. The final argument, packet, contains a pointer to
4688 * the packet to be built in response to the challenge. It should resolve to an
4689 *
object of type (struct rx packet *).
4691 * In generating a call to the routine located at the security
object's op
4692 * GetResponse() slot, the obj, conn, and packet pointers are used as its three
4693 * parameters. An invocation of the RXS GetResponse() macro results in a return
4694 * value identical to that of the op GetResponse() routine, namely a value of
4697 * \subsubsection sec5-5-7-10 Section 5.5.7.10: RXS CheckResponse()
4700 * \
#define RXS_CheckResponse(obj, conn, packet) RXS_OP(obj, CheckResponse, 4701 * (obj, conn, packet))
4703 * This macro causes the execution of the
interface routine in the op
4704 * CheckResponse() slot in the Rx security
object identified by the obj
4705 * pointer. This interface function is invoked by Rx on the server side each
4706 * time a response to a challenge packet is received for a given connection.
4707 * The responsibilities of such a function might include verifying the
4708 * integrity of the response, pulling out the necessary security information
4709 * and storing that information within the affected connection, and otherwise
4710 * updating the state of the connection.
4712 * The obj parameter must resolve into an
object of type (struct rx securityOps
4713 * *). The conn argument contains a pointer to the Rx server connection to
4714 * which the given challenge response is directed. This argument must resolve
4715 * to an
object of type (struct rx connection *). The final argument, packet,
4716 * contains a pointer to the packet received in response to the challenge
4717 * itself. It should resolve to an
object of type (struct rx packet *).
4719 * In generating a call to the routine located at the security
object's op
4720 * CheckResponse() slot, the obj, conn, and packet pointers are ued as its
4721 * three parameters. An invocation of the RXS CheckResponse() macro results in
4722 * a return value identical to that of the op CheckResponse() routine, namely a
4723 * value of type
int.
4725 * \subsubsection sec5-5-7-11 Section 5.5.7.11: RXS CheckPacket()
4728 * \
#define RXS_CheckPacket(obj, call, packet) RXS_OP(obj, CheckPacket, (obj, 4731 * This macro causes the execution of the
interface routine occupying the op
4732 * CheckPacket() slot in the Rx security
object identified by the obj pointer.
4733 * This interface function is invoked by Rx each time a packet is received. The
4734 * responsibilities of such a function might include verifying the integrity of
4735 * given packet, detecting any unauthorized modifications or tampering.
4737 * The obj parameter must resolve into an
object of type (struct rx securityOps
4738 * *). The conn argument contains a pointer to the Rx connection to which the
4739 * given challenge response is directed, and must resolve to an
object of type
4740 * (struct rx connection *). The final argument, packet, contains a pointer to
4741 * the packet received in response to the challenge itself. It should resolve
4742 * to an
object of type (struct rx packet *).
4744 * In generating a call to the routine located at the security
object's op
4745 * CheckPacket() slot, the obj, conn, and packet pointers are used as its three
4746 * parameters. An invocation of the RXS CheckPacket() macro results in a return
4747 * value identical to that of the op CheckPacket() routine, namely a value of
4750 * Please note that any non-zero return will cause Rx to abort all calls on the
4751 * connection. Furthermore, the connection itself will be marked as being in
4752 * error in such a case, causing it to reject any further incoming packets.
4754 * \subsubsection sec5-5-7-12 Section 5.5.7.12: RXS DestroyConnection()
4757 * \
#define RXS_DestroyConnection(obj, conn) RXS_OP(obj, DestroyConnection, 4760 * This macro causes the execution of the
interface routine in the op
4761 * DestroyConnection() slot in the Rx security
object identified by the obj
4762 * pointer. This interface function is invoked by Rx each time a connection
4763 * employing the given security
object is being destroyed. The responsibilities
4764 * of such a function might include deleting any private data maintained by the
4765 * security module for this connection.
4767 * The obj parameter must resolve into an
object of type (struct rx securityOps
4768 * *). The conn argument contains a pointer to the Rx connection being reaped,
4769 * and must resolve to a (struct rx connection *)
object.
4771 * In generating a call to the routine located at the security
object's op
4772 * DestroyConnection() slot, the obj and conn pointers are used as its two
4773 * parameters. An invocation of the RXS DestroyConnection() macro results in a
4774 * return value identical to that of the op DestroyConnection() routine, namely
4775 * a value of type
int.
4777 * \subsubsection sec5-5-7-13 Section 5.5.7.13: RXS GetStats()
4780 * \
#define RXS_GetStats(obj, conn, stats) RXS_OP(obj, GetStats, (obj, conn, 4783 * This macro causes the execution of the
interface routine in the op
4784 * GetStats() slot in the Rx security
object identified by the obj pointer.
4785 * This interface function is invoked by Rx each time current statistics
4786 * concerning the given security
object are desired.
4788 * The obj parameter must resolve into an
object of type (struct rx securityOps
4789 * *). The conn argument contains a pointer to the Rx connection using the
4790 * security
object to be examined, and must resolve to an
object of type
4791 * (struct rx connection *). The final argument, stats, contains a pointer to a
4792 * region to be filled with the desired statistics. It should resolve to an
4793 *
object of type (struct rx securityObjectStats *).
4795 * In generating a call to the routine located at the security
object's op
4796 * GetStats() slot, the obj, conn, and stats pointers are used as its three
4797 * parameters. An invocation of the RXS GetStats() macro results in a return
4798 * value identical to that of the op GetStats() routine, namely a value of type
4801 * \section sec5-6 Section 5.6: Functions
4804 * Rx exports a collection of functions that, in conjuction with the macros
4805 * explored in Section 5.5, allows its clients to set up and export services,
4806 * create and tear down connections to these services, and execute remote
4807 * procedure calls along these connections.
4809 * This paper employs two basic categorizations of these Rx routines. One set
4810 * of functions is meant to be called directly by clients of the facility, and
4811 * are referred to as the exported operations. The individual members of the
4812 * second set of functions are not meant to be called directly by Rx clients,
4813 * but rather are called by the collection of defined macros, so they must
4814 * still be lexically visible. These indirectly-executed routines are referred
4815 * to here as the semi-exported operations.
4817 * All Rx routines return zero upon success. The range of error codes employed
4818 * by Rx is defined in Section 5.2.15.
4820 * \subsection sec5-6-1 Section 5.6.1: Exported Operations
4822 * \subsection sec5-6-2 Section 5.6.2: rx Init _ Initialize Rx
4825 *
int rx Init(IN
int port)
4827 * Initialize the Rx facility. If a non-zero port number is provided, it
4828 * becomes the default port number for any service installed later. If 0 is
4829 * provided for the port, a random port will be chosen by the system. The rx
4830 * Init() function sets up internal tables and timers, along with starting up
4831 * the listener thread.
4833 * RX ADDRINUSE The port provided has already been taken.
4835 * \subsection sec5-6-3 Section 5.6.3: rx NewService _ Create and install
4839 * struct rx service *rx NewService(IN u
short port; IN u
short serviceId; IN
4840 *
char *serviceName; IN struct rx securityClass **securityObjects; IN
int 4841 * nSecurityObjects; IN
long (*serviceProc)())
4843 * Create and advertise a new Rx service. A service is uniquely named by a UDP
4844 * port number plus a non-zero 16-bit serviceId on the given host. The port
4845 * argument may be set to zero if rx Init() was called with a non-zero port
4846 * number, in which case that original port will be used. A serviceName must
4847 * also be provided, to be used for identification purposes (e.g., the service
4848 * name might be used for probing for statistics). A pointer to an array of
4849 * nSecurityObjects security objects to be associated with the new service is
4850 * given in . securityObjects. The service's executeRequestProc() pointer is
4851 * set to serviceProc.
4853 * The function returns a pointer to a descriptor for the requested Rx service.
4854 * A null return value indicates that the new service could not be created.
4855 * Possible reasons include:
4856 * \li The serviceId parameter was found to be zero.
4857 * \li A port value of zero was specified at Rx initialization time (i.e., when
4858 * rx init() was called), requiring a non-zero value for the port parameter
4860 * \li Another Rx service is already using serviceId.
4861 * \li Rx has already created the maximum RX MAX SERVICES Rx services (see
4864 * (struct rx service *) NULL The new Rx service could not be created, due to
4865 * one of the errors listed above.
4867 * \subsection sec5-6-4 Section 5.6.4: rx NewConnection _ Create a new
4868 * connection to a given service
4871 * struct rx connection *rx NewConnection( IN u
long shost, IN u
short sport,
4872 * IN u
short sservice, IN struct rx securityClass *securityObject, IN
int 4873 * service SecurityIndex)
4875 * Create a new Rx client connection to service sservice on the host whose IP
4876 * address is contained in shost and to that host's sport UDP port. The
4877 * corresponding Rx service identifier is expected in sservice. The caller also
4878 * provides a pointer to the security
object to use for the connection in
4879 * securityObject, along with that
object's serviceSecurityIndex among the
4880 * security objects associated with service sservice via a previous rx
4881 * NewService() call (see Section 5.6.3).
4882 * \note It is permissible to provide a null value for the securityObject
4883 * parameter if the chosen serviceSecurityIndex is zero. This corresponds to
4884 * the pre-defined null security
object, which does not engage in authorization
4885 * checking of any kind.
4887 * --- A pointer to an initialized Rx connection is always returned, unless osi
4888 * Panic() is called due to memory allocation failure.
4890 * \subsection sec5-6-5 Section 5.6.5: rx NewCall _ Start a new call on
4891 * the given connection
4894 * struct rx call *rx NewCall( IN struct rx connection *conn)
4896 * Start a new Rx remote procedure call on the connection specified by the conn
4897 * parameter. The existing call structures (up to RX MAXCALLS of them) are
4898 * examined in order. The first non-active call encountered (i.e., either
4899 * unused or whose call->state is RX STATE DALLY) will be appropriated and
4900 * reset if necessary. If all call structures are in active use, the RX CONN
4901 * MAKECALL WAITING flag is set in the conn->flags field, and the thread
4902 * handling this request will sleep until a call structure comes free. Once a
4903 * call structure has been reserved, the keep-alive protocol is enabled for it.
4905 * The state of the given connection determines the detailed behavior of the
4906 * function. The conn->timeout field specifies the absolute upper limit of the
4907 * number of seconds this particular call may be in operation. After this time
4908 * interval, calls to such routines as rx SendData() or rx ReadData() will fail
4909 * with an RX CALL TIMEOUT indication.
4911 * --- A pointer to an initialized Rx call is always returned, unless osi
4912 * Panic() is called due to memory allocation failure.
4914 * \subsection sec5-6-6 Section 5.6.6: rx EndCall _ Terminate the given
4919 * \param IN struct rx call *call,
4923 * Indicate that the Rx call described by the structure located at call is
4924 * finished, possibly prematurely. The value passed in the rc parameter is
4925 * returned to the peer, if appropriate. The final error code from processing
4926 * the call will be returned as rx EndCall()'s value. The given call's state
4927 * will be set to RX STATE DALLY, and threads waiting to establish a new call
4928 * on this connection are signalled (see the description of the rx NewCall() in
4931 * -1 Unspecified error has occurred.
4933 * \subsection sec5-6-7 Section 5.6.7: rx StartServer _ Activate installed
4937 *
void rx StartServer( IN
int donateMe)
4939 * This function starts server threads in support of the Rx services installed
4940 * via calls to rx NewService() (see Section 5.6.3). This routine first
4941 * computes the number of server threads it must create, governed by the
4942 * minProcs and maxProcs fields in the installed service descriptors. The
4943 * minProcs field specifies the minimum number of threads that are guaranteed
4944 * to be concurrently available to the given service. The maxProcs field
4945 * specifies the maximum number of threads that may ever be concurrently
4946 * assigned to the particular service, if idle threads are available. Using
4947 * this information, rx StartServer() computes the correct overall number of
4948 * threads as follows: For each installed service, minProcs threads will be
4949 * created, enforcing the minimality guarantee. Calculate the maximum
4950 * difference between the maxProcs and minProcs fields for each service, and
4951 * create this many additional server threads, enforcing the maximality
4954 * If the value placed in the donateMe argument is zero, then rx StartServer()
4955 * will simply return after performing as described above. Otherwise, the
4956 * thread making the rx StartServer() call will itself begin executing the
4957 * server thread loop. In this case, the rx StartServer() call will never
4962 * \subsection sec5-6-8 Section 5.6.8: rx PrintStats -- Print basic
4963 * statistics to a file
4966 *
void rx PrintStats( IN FILE *file)
4968 * Prints Rx statistics (basically the contents of the struct rx stats holding
4969 * the statistics for the Rx facility) to the open file descriptor identified
4970 * by file. The output is ASCII text, and is intended for human consumption.
4971 * \note This function is available only if the Rx package has been compiled
4972 * with the RXDEBUG flag.
4976 * \subsection sec5-6-9 Section 5.6.9: rx PrintPeerStats _ Print peer
4977 * statistics to a file
4979 *
void rx PrintPeerStats( IN FILE *file, IN struct rx peer *peer)
4981 * Prints the Rx peer statistics found in peer to the open file descriptor
4982 * identified by file. The output is in normal ASCII text, and is intended for
4983 * human consumption.
4984 * \note This function is available only if the Rx package has been compiled
4985 * with the RXDEBUG flag.
4989 * \subsection sec5-6-10 Section 5.6.10: rx finalize _ Shut down Rx
4993 *
void rx finalize()
4995 * This routine may be used to shut down the Rx facility for either server or
4996 * client applications. All of the client connections will be gracefully
4997 * garbage-collected after their active calls are cleaned up. The result of
4998 * calling rx finalize() from a client program is that the server-side entity
4999 * will be explicitly advised that the client has terminated. This notification
5000 * frees the server-side application from having to probe the client until its
5001 * records eventually time out, and also allows it to free resources currently
5002 * assigned to that client's support.
5006 * \subsection sec5-6-11 Section 5.6.11: Semi-Exported Operations
5009 * As described in the introductory text in Section 5.6, entries in this
5010 * lexically-visible set of Rx functions are not meant to be called directly by
5011 * client applications, but rather are invoked by Rx macros called by users.
5013 * \subsection sec5-6-12 Section 5.6.12: rx WriteProc _ Write data to an
5017 *
int rx WriteProc( IN struct rx call *call, IN
char *buf, IN
int nbytes)
5019 * Write nbytes of data from buffer buf into the Rx call identified by the call
5020 * parameter. The value returned by rx WriteProc() reports the number of bytes
5021 * actually written into the call. If zero is returned, then the rx Error()
5022 * macro may be used to obtain the call status.
5024 * This routine is called by the rx Write() macro, which is why it must be
5025 * exported by the Rx facility.
5027 * Indicates error in the given Rx call; use the rx Error() macro to determine
5030 * \subsection sec5-6-13 Section 5.6.13: rx ReadProc _ Read data from an
5034 *
int rx ReadProc( IN struct rx call *call, IN
char *buf, IN
int nbytes)
5036 * Read up to nbytes of data from the Rx call identified by the call parameter
5037 * into the buf buffer. The value returned by rx ReadProc() reports the number
5038 * of bytes actually read from the call. If zero is returned, then the rx
5039 * Error() macro may be used to obtain the call status.
5041 * This routine is called by the rx Read() macro, which is why it must be
5042 * exported by the Rx facility.
5044 * Indicates error in the given Rx call; use the rx Error() macro to determine
5047 * \subsection sec5-6-1 Section 5.6.1: rx FlushWrite -- Flush buffered
5048 * data on outgoing call
5051 *
void rx FlushWrite( IN struct rx call *call)
5053 * Flush any buffered data on the given Rx call to the stream. If the call is
5054 * taking place on a server connection, the call->mode is set to RX MODE EOF.
5055 * If the call is taking place on a client connection, the call->mode is set to
5056 * RX MODE RECEIVING.
5060 * \subsection sec5-6-15 Section 5.6.15: rx SetArrivalProc _ Set function
5061 * to invoke upon call packet arrival
5064 *
void rx SetArrivalProc( IN struct rx call *call, IN VOID (*proc)(), IN VOID
5065 * *handle, IN VOID *arg)
5067 * Establish a procedure to be called when a packet arrives for a call. This
5068 * routine will be called at most once after each call, and will also be called
5069 * if there is an error condition on the call or the call is complete. The rx
5070 * SetArrivalProc() function is used by multicast Rx routines to build a
5071 * selection function that determines which of several calls is likely to be a
5072 * good one to read from. The implementor's comments in the Rx code state that,
5073 * due to the current implementation, it is probably only reasonable to use rx
5074 * SetArrivalProc() immediately after an rx NewCall(), and to only use it once.
5078 * \page chap6 Chapter 6 -- Example Server and Client
5080 * \section sec6-1 Section 6.1: Introduction
5083 * This chapter provides a sample program showing the use of Rx. Specifically,
5084 * the rxdemo application, with all its support files, is documented and
5085 * examined. The goal is to provide the reader with a fully-developed and
5086 * operational program illustrating the use of both regular Rx remote procedure
5087 * calls and streamed RPCs. The full text of the rxdemo application is
5088 * reproduced in the sections below, along with additional commentary.
5090 * Readers wishing to directly experiment with this example Rx application are
5091 * encouraged to examine the on-line version of rxdemo. Since it is a program
5092 * of general interest, it has been installed in the usr/contrib tree in the
5093 * grand.central.org cell. This area contains user-contributed software for the
5094 * entire AFS community. At the top of this tree is the
5095 * /afs/grand.central.org/darpa/usr/contrib directory. Both the server-side and
5096 * client-side rxdemo binaries (rxdemo server and rxdemo client, respectively)
5097 * may be found in the bin subdirectory. The actual sources reside in the
5098 * .site/grand.central.org/rxdemo/src subdirectory.
5100 * The rxdemo code is composed of two classes of files, namely those written by
5101 * a human programmer and those generated from the human-written code by the
5102 * Rxgen tool. Included in the first group of files are:
5103 * \li rxdemo.xg This is the RPC interface definition file, providing
5104 * high-level definitions of the supported calls.
5105 * \li rxdemo client.c: This is the rxdemo client program, calling upon the
5106 * associated server to perform operations defined by rxdemo.xg.
5107 * \li rxdemo server.c: This is the rxdemo server program, implementing the
5108 * operations promised in rxdemo.xg.
5109 * \li Makefile: This is the file that directs the compilation and
5110 * installation of the rxdemo code.
5112 * The class of automatically-generated files includes the following items:
5113 * \li rxdemo.h: This header file contains the set of constant definitions
5114 * present in rxdemo.xg, along with information on the RPC opcodes defined for
5116 * \li rxdemo.cs.c: This client-side stub file performs all the marshalling and
5117 * unmarshalling of the arguments for the RPC routines defined in rxdemo.xg.
5118 * \li rxdemo.ss.c: This stub file similarly defines all the marshalling and
5119 * unmarshalling of arguments for the server side of the RPCs, invokes the
5120 * routines defined within rxdemo server.c to implement the calls, and also
5121 * provides the dispatcher function.
5122 * \li rxdemo.xdr.c: This module defines the routines required to convert
5123 * complex user-defined data structures appearing as arguments to the Rx RPC
5124 * calls exported by rxdemo.xg into network byte order, so that correct
5125 * communication is guaranteed between clients and server with different memory
5128 * The chapter concludes with a section containing sample output from running
5129 * the rxdemo server and client programs.
5131 * \section sec6-2 Section 6.2: Human-Generated files
5134 * The rxdemo application is based on the four human-authored files described
5135 * in this section. They provide the basis for the construction of the full set
5136 * of modules needed to implement the specified Rx service.
5138 * \subsection sec6-2-1 Section 6.2.1: Interface file: rxdemo.xg
5141 * This file serves as the RPC interface definition file for this application.
5142 * It defines various constants, including the Rx service port to use and the
5143 * index of the null security
object (no encryption is used by rxdemo). It
5144 * defines the RXDEMO MAX and RXDEMO MIN constants, which will be used by the
5145 * server as the upper and lower bounds on the number of Rx listener threads to
5146 * run. It also defines the set of error codes exported by this facility.
5147 * finally, it provides the RPC function declarations, namely Add() and
5148 * Getfile(). Note that when building the actual function definitions, Rxgen
5149 * will prepend the value of the package line in this file, namely "RXDEMO ",
5150 * to the function declarations. Thus, the generated functions become RXDEMO
5151 * Add() and RXDEMO Getfile(), respectively. Note the use of the split keyword
5152 * in the RXDEMO Getfile() declaration, which specifies that this is a streamed
5153 * call, and actually generates two client-side stub routines (see Section
5179 * %
#include <rx/rx.h> 5180 * %#include <rx/rx_null.h>
5181 * %#define RXDEMO_SERVER_PORT 8000
5182 * %#define RXDEMO_SERVICE_PORT 0
5183 * %#define RXDEMO_SERVICE_ID 4
5184 * %#define RXDEMO_NULL_SECOBJ_IDX 0
5190 * %#define RXDEMO_MAX 3
5195 * %#define RXDEMO_MIN 2
5199 * %#define RXDEMO_NULL 0
5203 * %#define RXDEMO_NAME_MAX_CHARS 64
5207 * %#define RXDEMO_BUFF_BYTES 512
5217 * %#define RXDEMO_CODE_SUCCESS 0
5218 * %#define RXDEMO_CODE_CANT_OPEN 1
5219 * %#define RXDEMO_CODE_CANT_STAT 2
5220 * %#define RXDEMO_CODE_CANT_READ 3
5221 * %#define RXDEMO_CODE_WRITE_ERROR 4
5234 * Add(IN
int a,
int b, OUT
int *result) = 1;
5247 * Getfile(IN
string a_nameToRead<RXDEMO_NAME_MAX_CHARS>, OUT
int *a_result)
5251 * \subsection sec6-2-2 Section 6.2.2: Client Program: rxdemo client.c
5254 * The rxdemo client program, rxdemo client, calls upon the associated server
5255 * to perform operations defined by rxdemo.xg. After its header, it defines a
5256 *
private GetIPAddress() utility routine, which given a character
string host
5257 * name will return its IP address.
5281 *
#include <sys/types.h> 5282 * #include <netdb.h>
5283 * #include <stdio.h>
5284 * #include
"rxdemo.h" 5285 *
static char pn[] =
"rxdemo";
5286 *
static u_long GetIpAddress(a_hostName)
char *a_hostName;
5288 *
static char rn[] =
"GetIPAddress";
5289 *
struct hostent *hostEntP;
5290 * u_long hostIPAddr;
5291 * hostEntP = gethostbyname(a_hostName);
5292 *
if (hostEntP == (
struct hostent *)0) {
5293 * printf(
"[%s:%s] Host '%s' not found\n",
5294 * pn, rn, a_hostName);
5297 *
if (hostEntP->h_length !=
sizeof(u_long)) {
5298 * printf(
"[%s:%s] Wrong host address length (%d bytes instead of 5300 * pn, rn, hostEntP->h_length,
sizeof(u_long));
5303 * bcopy(hostEntP->h_addr, (
char *)&hostIPAddr,
sizeof(hostIPAddr));
5304 *
return(hostIPAddr);
5309 * The main program section of the client code, after handling its command line
5310 * arguments, starts off by initializing the Rx facility.
5317 *
struct rx_connection *rxConnP;
5318 *
struct rx_call *rxCallP;
5319 * u_long hostIPAddr;
5321 *
struct rx_securityClass *nullSecObjP;
5322 *
int operand1, operand2;
5324 *
char fileName[64];
5325 *
long fileDataBytes;
5326 *
char buff[RXDEMO_BUFF_BYTES+1];
5327 *
int currBytesToRead;
5328 *
int maxBytesToRead;
5329 *
int bytesReallyRead;
5331 * printf(
"\n%s: Example Rx client process\n\n", pn);
5332 *
if ((argc < 2) || (argc > 3)) {
5333 * printf(
"Usage: rxdemo <HostName> [PortToUse]");
5336 * hostIPAddr = GetIpAddress(argv[1]);
5338 * demoUDPPort = atoi(argv[2]);
5340 * demoUDPPort = RXDEMO_SERVER_PORT;
5342 * code = rx_Init(htons(demoUDPPort));
5344 * printf(
"** Error calling rx_Init(); code is %d\n", code);
5348 * nullSecObjP = rxnull_NewClientSecurityObject();
5349 *
if (nullSecObjP == (
struct rx_securityClass *)0) {
5350 * printf(
"%s: Can't create a null client-side security 5356 * printf(
"Connecting to Rx server on '%s', IP address 0x%x, UDP port 5357 * %d\n", argv[1], hostIPAddr, demoUDPPort);
5358 * rxConnP = rx_NewConnection(hostIPAddr, RXDEMO_SERVER_PORT,
5359 * RXDEMO_SERVICE_ID, nullSecObjP, RXDEMO_NULL_SECOBJ_IDX);
5360 *
if (rxConnP == (
struct rx_connection *)0) {
5361 * printf(
"rxdemo: Can't create connection to server!\n");
5364 * printf(
" ---> Connected.\n");
5368 * The rx Init() invocation initializes the Rx library and defines the desired
5369 * service UDP port (in network byte order). The rxnull
5370 * NewClientSecurityObject() call creates a client-side Rx security
object that
5371 * does not perform any authentication on Rx calls. Once a client
5372 * authentication
object is in hand, the program calls rx NewConnection(),
5373 * specifying the host, UDP port, Rx service ID, and security information
5374 * needed to establish contact with the rxdemo server entity that will be
5375 * providing the service.
5377 * With the Rx connection in place, the program may perform RPCs. The first one
5378 * to be invoked is RXDEMO Add():
5384 * printf("Asking server to add %d and %d: ", operand1, operand2);
5385 * code = RXDEMO_Add(rxConnP, operand1, operand2, &sum);
5387 * printf(
" // ** Error in the RXDEMO_Add RPC: code is %d\n", code);
5390 * printf(
"Reported sum is %d\n", sum);
5394 * The first argument to RXDEMO Add() is a pointer to the Rx connection
5395 * established above. The client-side body of the RXDEMO Add() function was
5396 * generated from the rxdemo.xg interface file, and resides in the rxdemo.cs.c
5397 * file (see Section 6.3.1). It gives the appearance of being a normal C
5400 * The second RPC invocation involves the more complex, streamed RXDEMO
5401 * Getfile() function. More of the internal Rx workings are exposed in this
5402 * type of call. The first additional detail to consider is that we must
5403 * manually create a new Rx call on the connection.
5407 * printf("Name of file to read from server: ");
5408 * scanf("%s", fileName);
5409 * maxBytesToRead = RXDEMO_BUFF_BYTES;
5410 * printf("Setting up an Rx call for RXDEMO_Getfile...");
5411 * rxCallP = rx_NewCall(rxConnP);
5412 * if (rxCallP == (struct rx_call *)0) {
5413 * printf(
"** Can't create call\n");
5420 * Once the Rx call structure has been created, we may begin executing the call
5421 * itself. Having been declared to be split in the
interface file, Rxgen
5422 * creates two
function bodies
for rxdemo Getfile() and places them in
5423 * rxdemo.cs.c. The first, StartRXDEMO Getfile(), is responsible for
5424 * marshalling the outgoing arguments and issuing the RPC. The second,
5425 * EndRXDEMO Getfile(), takes care of unmarshalling the non-streamed OUT
5426 * function parameters. The following code fragment illustrates how the RPC is
5427 * started, using the StartRXDEMO Getfile() routine to pass the call parameters
5432 * code = StartRXDEMO_Getfile(rxCallP, fileName);
5434 * printf(
"** Error calling StartRXDEMO_Getfile(); code is %d\n",
5441 * Once the call parameters have been shipped, the server will commence
5442 * delivering the
"stream" data bytes back to the client on the given Rx call
5443 * structure. The first longword to come back on the stream specifies the
5444 * number of bytes to follow.
5447 * Begin reading the data being shipped from the server in response to * our
5448 * setup call. The first longword coming back on the Rx call is
5449 * the number of bytes to follow. It appears in network byte order,
5450 * so we have to fix it up before referring to it.
5453 * bytesReallyRead = rx_Read(rxCallP, &fileDataBytes,
sizeof(
long));
5454 *
if (bytesReallyRead !=
sizeof(
long)) {
5455 * printf(
"** Only %d bytes read for file length; should have been %d\n",
5456 * bytesReallyRead,
sizeof(
long));
5459 * fileDataBytes = ntohl(fileDataBytes);
5463 * Once the client knows how many bytes will be sent, it runs a loop in which
5464 * it reads a buffer at a time from the Rx call stream,
using rx Read() to
5465 * accomplish this. In this application, all that is done with each
5466 * newly-acquired buffer of information is printing it out.
5470 * printf("[file contents (%d bytes) fetched over the Rx call appear
5471 * below]\n\n", fileDataBytes);
5472 * while (fileDataBytes > 0)
5474 * currBytesToRead = (fileDataBytes > maxBytesToRead ? maxBytesToRead :
5476 * bytesReallyRead = rx_Read(rxCallP, buff, currBytesToRead);
5477 *
if (bytesReallyRead != currBytesToRead)
5479 * printf(
"\nExpecting %d bytes on this read, got %d instead\n",
5480 * currBytesToRead, bytesReallyRead);
5484 * buff[currBytesToRead] = 0;
5485 * printf(
"%s", buff);
5487 * fileDataBytes -= currBytesToRead;
5492 * After
this loop terminates, the Rx stream has been drained of all data. The
5493 * Rx call is concluded by invoking the second of the two
5494 * automatically-generated functions, EndRXDEMO Getfile(), which retrieves the
5495 * call
's OUT parameter from the server. 5498 * /* finish off the Rx call, getting the OUT parameters. */ 5499 * printf("\n\n[End of file data]\n"); 5500 * code = EndRXDEMO_Getfile(rxCallP, &getResults); 5503 * printf("** Error getting file transfer results; code is %d\n", 5510 * With both normal and streamed Rx calls accomplished, the client demo code 5511 * concludes by terminating the Rx call it set up earlier. With that done, the 5515 * /* finish off the Rx call. */ 5516 * code = rx_EndCall(rxCallP, code); 5518 * printf("Error in calling rx_EndCall(); code is %d\n", code); 5520 * printf("\n\nrxdemo complete.\n"); 5523 * \subsection sec6-2-3 Server Program: rxdemo server.c 5526 * The rxdemo server program, rxdemo server, implements the operations promised 5527 * in the rxdemo.xg interface file. 5529 * After the initial header, the external function RXDEMO ExecuteRequest() is 5530 * declared. The RXDEMO ExecuteRequest() function is generated automatically by 5531 * rxgen from the interface file and deposited in rxdemo.ss.c. The main program 5532 * listed below will associate this RXDEMO ExecuteRequest() routine with the Rx 5533 * service to be instantiated. 5536 * /*====================================================================== 5537 * % % Advanced Research Projects Agency and Transarc Corporation. % %% % 5538 * (C) Copyright 1991 Transarc Corporation % %% % Redistribution and use in 5539 * source and binary forms are permitted % % provided that: (1) source 5540 * distributions retain this entire copy- % % right notice and comment, and 5541 * (2) distributions including binaries % % display the following 5542 * acknowledgement: % %% % ''This product includes software developed by 5543 * Transarc % % Corporation and its contributors'' % %% % in the documentation 5544 * or other materials mentioning features or % % use of this software. Neither 5545 * the name of Transarc nor the names % % of its contributors may be used to 5546 * endorse or promote products % % derived from this software without specific 5547 * prior written % % permission. % %% % THIS SOFTWARE IS PROVIDED "AS IS" AND 5548 * WITHOUT ANY EXPRESS OR IMPLIED % % WARRANTIES, INCLUDING, WITHOUT 5550 * THE IMPLIED WARRANTIES OF % % MERCHANTABILITY AND FITNESS FOR A PARTICULAR 5552 * ====================================================================== */ 5554 * /* Server portion of the example RXDEMO application, using both % 5555 * standard and streamed calls. % % Edward R. Zayas % Transarc Corporation % 5556 * % % The United States Government has rights in this work pursuant % 5557 * to contract no. MDA972-90-C-0036 between the United States Defense % */ 5559 * #include <sys/types.h> 5560 * #include <sys/stat.h> 5561 * #include <sys/file.h> 5562 * #include <netdb.h> 5563 * #include <stdio.h> 5564 * #include "rxdemo.h" 5565 * #define N_SECURITY_OBJECTS 1 5566 * extern RXDEMO_ExecuteRequest(); 5570 * After choosing either the default or user-specified UDP port on which the Rx 5571 * service will be established, rx Init() is called to set up the library. 5578 * static char pn[] = "rxdemo_server"; /* Program name */ 5579 * struct rx_securityClass 5580 * (securityObjects[1]); /* Security objs */ 5581 * struct rx_service *rxServiceP; /* Ptr to Rx service descriptor */ 5582 * struct rx_call *rxCallP; /* Ptr to Rx call descriptor */ 5583 * int demoUDPPort; /* UDP port of Rx service */ 5584 * int fd; /* file descriptor */ 5585 * int code; /* Return code */ 5586 * printf("\n%s: Example Rx server process\n\n", pn); 5588 * printf("Usage: rxdemo [PortToUse]"); 5592 * demoUDPPort = atoi(argv[1]); 5594 * demoUDPPort = RXDEMO_SERVER_PORT; 5596 * /* Initialize the Rx facility, telling it the UDP port number this 5597 * * server will use for its single service. */ 5599 * printf("Listening on UDP port %d\n", demoUDPPort); 5600 * code = rx_Init(demoUDPPort); 5602 * printf("** Error calling rx_Init(); code is %d\n", code); 5608 * A security object specific to the server side of an Rx conversation is 5609 * created in the next code fragment. As with the client side of the code, a 5610 * "null" server security object, namely one that does not perform any 5611 * authentication at all, is constructed with the rxnull 5612 * NewServerSecurityObject() function. 5615 * /* Create a single server-side security object. In this case, the 5616 * * null security object (for unauthenticated connections) will be used 5617 * * to control security on connections made to this server. */ 5619 * securityObjects[RXDEMO_NULL_SECOBJ_IDX] = 5620 * rxnull_NewServerSecurityObject(); 5621 * if (securityObjects[RXDEMO_NULL_SECOBJ_IDX] == (struct rx_securityClass 5623 * printf("** Can't create server-side security object\n
"); 5629 * The rxdemo server program is now in a position to create the desired Rx 5630 * service, primed to recognize exactly those interface calls defined in 5631 * rxdemo.xg. This is accomplished by calling the rx NewService() library 5632 * routine, passing it the security object created above and the generated Rx 5633 * dispatcher routine. 5636 * /* Instantiate a single sample service. The rxgen-generated procedure 5637 * * called to dispatch requests is passed in (RXDEMO_ExecuteRequest). */ 5639 * rxServiceP = rx_NewService( 0, 5640 * RXDEMO_SERVICE_ID, 5644 * RXDEMO_ExecuteRequest 5646 * if (rxServiceP == (struct rx_service *) 0) { 5647 * printf("** Can
't create Rx service\n"); 5653 * The final step in this main routine is to activate servicing of calls to the 5654 * exported Rx interface. Specifically, the proper number of threads are 5655 * created to handle incoming interface calls. Since we are passing a non-zero 5656 * argument to the rx StartServer() call, the main program will itself begin 5657 * executing the server thread loop, never returning from the rx StartServer() 5658 * call. The print statement afterwards should never be executed, and its 5659 * presence represents some level of paranoia, useful for debugging 5660 * malfunctioning thread packages. 5663 * /* Start up Rx services, donating this thread to the server pool. */ 5664 * rx_StartServer(1); 5665 * /* We should never return from the previous call. */ 5666 * printf("** rx_StartServer() returned!!\n"); exit(1); 5671 * Following the main procedure are the functions called by the 5672 * automatically-generated routines in the rxdemo.ss.c module to implement the 5673 * specific routines defined in the Rx interface. 5675 * The first to be defined is the RXDEMO Add() function. The arguments for this 5676 * routine are exactly as they appear in the interface definition, with the 5677 * exception of the very first. The a rxCallP parameter is a pointer to the Rx 5678 * structure describing the call on which this function was activated. All 5679 * user-supplied routines implementing an interface function are required to 5680 * have a pointer to this structure as their first parameter. Other than 5681 * printing out the fact that it has been called and which operands it 5682 * received, all that RXDEMO Add() does is compute the sum and place it in the 5685 * Since RXDEMO Add() is a non-streamed function, with all data travelling 5686 * through the set of parameters, this is all that needs to be done. To mark a 5687 * successful completion, RXDEMO Add() returns zero, which is passed all the 5688 * way through to the RPC's client.
5691 *
int RXDEMO_Add(a_rxCallP, a_operand1, a_operand2, a_resultP)
5692 *
struct rx_call *a_rxCallP;
5693 *
int a_operand1, a_operand2;
5696 * printf(
"\t[Handling call to RXDEMO_Add(%d, %d)]\n",
5697 * a_operand1, a_operand2);
5698 * *a_resultP = a_operand1 + a_operand2;
5704 * The next and
final interface routine defined in this file is RXDEMO
5705 * Getfile(). Declared as a split
function in the
interface file, RXDEMO
5706 * Getfile() is an example of a streamed Rx call. As with RXDEMO Add(), the
5707 * initial parameter is required to be a pointer to the Rx call structure with
5708 * which this routine is associated, Similarly, the other parameters appear
5709 * exactly as in the interface definition, and are handled identically.
5711 * The difference between RXDEMO Add() and RXDEMO Getfile() is in the use of
5712 * the rx Write() library routine by RXDEMO Getfile() to feed the desired
5713 * file's data directly into the Rx call stream. This is an example of the use
5714 * of the a rxCallP argument, providing all the information necessary to
5715 * support the rx Write() activity.
5717 * The RXDEMO Getfile() function begins by printing out the fact that it's been
5718 * called and the name of the requested file. It will then attempt to open the
5719 * requested file and stat it to determine its size.
5722 *
int RXDEMO_Getfile(a_rxCallP, a_nameToRead, a_resultP)
5723 * struct rx_call *a_rxCallP;
5724 *
char *a_nameToRead;
5727 *
struct stat fileStat;
5729 *
long nbofileBytes;
5731 *
int bytesReallyWritten;
5733 *
int maxBytesToSend;
5735 *
char buff[RXDEMO_BUFF_BYTES+1];
5737 * maxBytesToSend = RXDEMO_BUFF_BYTES;
5738 * printf(
"\t[Handling call to RXDEMO_Getfile(%s)]\n", a_nameToRead);
5739 * fd = open(a_nameToRead, O_RDONLY, 0444);
5741 * printf(
"\t\t[**Can't open file '%s']\n", a_nameToRead);
5742 * *a_resultP = RXDEMO_CODE_CANT_OPEN;
5745 * printf(
"\t\t[file opened]\n");
5747 * code = fstat(fd, &fileStat);
5749 * a_resultP = RXDEMO_CODE_CANT_STAT;
5750 * printf(
"\t\t[file closed]\n");
5754 * fileBytes = fileStat.st_size;
5755 * printf(
"\t\t[file has %d bytes]\n", fileBytes);
5759 * Only standard unix operations have been used so far. Now that the file is
5760 * open, we must first feed the size of the file, in bytes, to the Rx call
5761 * stream. With
this information, the client code can then determine how many
5762 * bytes will follow on the stream. As with all data that flows through an Rx
5763 * stream, the longword containing the file size, in bytes, must be converted
5764 * to network byte order before being sent. This insures that the recipient may
5765 * properly interpret the streamed information, regardless of its memory
5769 * nbofileBytes = htonl(fileBytes);
5771 * bytesReallyWritten = rx_Write(a_rxCallP, &nbofileBytes,
sizeof(
long));
5772 *
if (bytesReallyWritten !=
sizeof(
long)) {
5773 * printf(
"** %d bytes written instead of %d for file length\n",
5774 * bytesReallyWritten,
sizeof(
long));
5775 * *a_resultP = RXDEMO_CODE_WRITE_ERROR;
5776 * printf(
"\t\t[file closed]\n");
5783 * Once the number of file bytes has been placed in the stream, the RXDEMO
5784 * Getfile() routine runs a loop, reading a buffer's worth of the file and then
5785 * inserting that buffer of file data into the Rx stream at each iteration.
5786 * This loop executes until all of the file's bytes have been shipped. Notice
5787 * there is no special end-of-file character or marker inserted into the
5790 * The body of the loop checks for both unix read() and rx Write errors. If
5791 * there is a problem reading from the unix file into the transfer buffer, it
5792 * is reflected back to the client by setting the error return parameter
5793 * appropriately. Specifically, an individual unix read() operation could fail
5794 * to return the desired number of bytes. Problems with rx Write() are handled
5795 * similarly. All errors discovered in the loop result in the file being
5796 * closed, and RXDEMO Getfile() exiting with a non-zero return value.
5800 * while (fileBytes > 0) {
5803 * bytesToSend = (fileBytes > maxBytesToSend ?
5804 * maxBytesToSend : fileBytes);
5805 * bytesRead = read(fd, buff, bytesToSend);
5806 *
if (bytesRead != bytesToSend) {
5807 * printf(
"Read %d instead of %d bytes from the file\n",
5808 * bytesRead, bytesToSend);
5809 * *a_resultP = RXDEMO_CODE_WRITE_ERROR;
5810 * printf(
"\t\t[file closed]\n");
5815 * bytesReallyWritten = rx_Write(a_rxCallP, buff, bytesToSend);
5816 *
if (bytesReallyWritten != bytesToSend) {
5817 * printf(
"%d file bytes written instead of %d\n",
5818 * bytesReallyWritten, bytesToSend);
5819 * *a_resultP = RXDEMO_CODE_WRITE_ERROR;
5820 * printf(
"\t\t[file closed]\n");
5825 * fileBytes -= bytesToSend;
5830 * Once all of the file
's bytes have been shipped to the remote client, all 5831 * that remains to be done is to close the file and return successfully. 5834 * /* Close the file, then return happily. */ 5835 * *a_resultP = RXDEMO_CODE_SUCCESS; 5836 * printf("\t\t[file closed]\n"); 5839 * } /* RXDEMO_Getfile */ 5842 * \subsection sec6-2-4 Section 6.2.4: Makefile 5845 * This file directs the compilation and installation of the rxdemo code. It 5846 * specifies the locations of libraries, include files, sources, and such tools 5847 * as Rxgen and install, which strips symbol tables from executables and places 5848 * them in their target directories. This Makefile demostrates cross-cell 5849 * software development, with the rxdemo sources residing in the 5850 * grand.central.org cell and the AFS include files and libraries accessed from 5851 * their locations in the transarc.com cell. 5853 * In order to produce and install the rxdemo server and rxdemo client 5854 * binaries, the system target should be specified on the command line when 5860 * A note of caution is in order concerning generation of the rxdemo binaries. 5861 * While tools exist that deposit the results of all compilations to other 5862 * (architecture-specific) directories, and thus facilitate multiple 5863 * simultaneous builds across a variety of machine architectures (e.g., 5864 * Transarc's washtool), the assumption is made here that compilations will
5865 * take place directly in the directory containing all the rxdemo sources.
5866 * Thus, a user will have to execute a make clean command to
remove all
5867 * machine-specific
object, library, and executable files before compiling
for 5868 * a different architecture. Note, though, that the binaries are installed into
5869 * a directory specifically reserved
for the current machine type.
5870 * Specifically, the
final pathname component of the ${PROJ DIR}bin
5871 * installation target is really a symbolic link to ${PROJ DIR}.bin/@sys.
5873 * Two libraries are needed to support the rxdemo code. The first is obvious,
5874 * namely the Rx librx.a library. The second is the lightweight thread
package 5875 * library, liblwp.a, which implements all the threading operations that must
5876 * be performed. The include files are taken from the unix /usr/include
5877 * directory, along with various AFS-specific directories. Note that for
5878 * portability reasons, this Makefile only contains fully-qualified AFS
5879 * pathnames and "standard" unix pathnames (such as /usr/include).
5908 * TOOL_CELL = grand.central.org
5909 * AFS_INCLIB_CELL = transarc.com
5910 * USR_CONTRIB = /afs/${TOOL_CELL}/darpa/usr/contrib/
5911 * PROJ_DIR = ${USR_CONTRIB}.site/grand.central.org/rxdemo/
5912 * AFS_INCLIB_DIR = /afs/${AFS_INCLIB_CELL}/afs/dest/
5913 * RXGEN = ${AFS_INCLIB_DIR}bin/rxgen
5914 * INSTALL = ${AFS_INCLIB_DIR}bin/install
5915 * LIBS = ${AFS_INCLIB_DIR}lib/librx.a \ ${AFS_INCLIB_DIR}lib/liblwp.a
5918 * -I${AFS_INCLIB_DIR}include \
5919 * -I${AFS_INCLIB_DIR}include/afs \
5920 * -I${AFS_INCLIB_DIR} \
5926 * ${INSTALL} rxdemo_client
5928 * ${INSTALL} rxdemo_server
5931 * all: rxdemo_client rxdemo_server
5933 * rxdemo_client: rxdemo_client.o ${LIBS} rxdemo.cs.o ${CC} ${CFLAGS}
5934 * -o rxdemo_client rxdemo_client.o rxdemo.cs.o ${LIBS}
5936 * rxdemo_server: rxdemo_server.o rxdemo.ss.o ${LIBS} ${CC} ${CFLAGS}
5937 * -o rxdemo_server rxdemo_server.o rxdemo.ss.o ${LIBS}
5939 * rxdemo_client.o: rxdemo.h
5941 * rxdemo_server.o: rxdemo.h
5943 * rxdemo.cs.c rxdemo.ss.c rxdemo.er.c rxdemo.h: rxdemo.xg rxgen rxdemo.xg
5945 * clean: rm -f *.o rxdemo.cs.c rxdemo.ss.c rxdemo.xdr.c rxdemo.h \
5946 * rxdemo_client rxdemo_server core
5949 * \section sec6-3 Section 6.3: Computer-Generated files
5952 * The four human-generated files described above provide all the information
5953 * necessary to construct the full set of modules to support the rxdemo example
5954 * application. This section describes those routines that are generated from
5955 * the base set by Rxgen, filling out the code required to implement an Rx
5958 * \subsection sec6-3-1 Client-Side Routines: rxdemo.cs.c
5961 * The rxdemo client.c program, described in Section 6.2.2, calls the
5962 * client-side stub routines contained in this module in order to make rxdemo
5963 * RPCs. Basically, these client-side stubs are responsible for creating new Rx
5964 * calls on the given connection parameter and then marshalling and
5965 * unmarshalling the rest of the interface call parameters. The IN and INOUT
5966 * arguments, namely those that are to be delivered to the server-side code
5967 * implementing the call, must be packaged in network byte order and shipped
5968 * along the given Rx call. The return parameters, namely those objects
5969 * declared as INOUT and OUT, must be fetched from the server side of the
5970 * associated Rx call, put back in host byte order, and inserted into the
5971 * appropriate parameter variables.
5973 * The first part of rxdemo.cs.c echoes the definitions appearing in the
5974 * rxdemo.xg interface file, and also #includes another Rxgen-generated file,
5985 * #include "rxdemo.h"
5986 * #define RXDEMO_CODE_WRITE_ERROR 4
5988 * #include <rx/rx.h>
5989 * #include <rx/rx_null.h>
5990 * #define RXDEMO_SERVER_PORT 8000
5991 * #define RXDEMO_SERVICE_PORT 0
5992 * #define RXDEMO_SERVICE_ID 4
5993 * #define RXDEMO_NULL_SECOBJ_IDX 0
5994 * #define RXDEMO_MAX 3
5995 * #define RXDEMO_MIN 2
5996 * #define RXDEMO_NULL 0
5997 * #define RXDEMO_NAME_MAX_CHARS 64
5998 * #define RXDEMO_BUFF_BYTES 512
5999 * #define RXDEMO_CODE_SUCCESS 0
6000 * #define RXDEMO_CODE_CANT_OPEN 1
6001 * #define RXDEMO_CODE_CANT_STAT 2
6002 * #define RXDEMO_CODE_CANT_READ 3
6003 * #define RXDEMO_CODE_WRITE_ERROR 4
6007 * The next code fragment defines the client-side stub for the RXDEMO Add()
6008 * routine, called by the rxdemo client program to execute the associated RPC.
6011 * int RXDEMO_Add(z_conn, a, b, result) register struct rx_connection *z_conn;
6015 *
struct rx_call *z_call = rx_NewCall(z_conn);
6016 *
static int z_op = 1;
6019 * xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
6021 *
if ((!xdr_int(&z_xdrs, &z_op))
6022 * || (!xdr_int(&z_xdrs, &a))
6023 * || (!xdr_int(&z_xdrs, &b))) {
6024 * z_result = RXGEN_CC_MARSHAL;
6028 * z_xdrs.x_op = XDR_DECODE;
6029 *
if ((!xdr_int(&z_xdrs, result))) {
6030 * z_result = RXGEN_CC_UNMARSHAL;
6033 * z_result = RXGEN_SUCCESS;
6034 * fail:
return rx_EndCall(z_call, z_result);
6039 * The very first operation performed by RXDEMO Add() occurs in the local
6040 * variable declarations, where z call is set to point to the structure
6041 * describing a newly-created Rx call on the given connection. An XDR
6042 * structure, z xdrs, is then created for the given Rx call with xdrrx
6043 * create(). This XDR
object is used to deliver the proper arguments, in
6044 * network byte order, to the matching server stub code. Three calls to xdr
6045 *
int() follow, which insert the appropriate Rx opcode and the two operands
6046 * into the Rx call. With the IN arguments thus transmitted, RXDEMO Add()
6047 * prepares to pull the value of the single OUT parameter. The z xdrs XDR
6048 * structure, originally set to XDR ENCODE objects, is now reset to XDR DECODE
6049 * to convert further items received into host byte order. Once the return
6050 * parameter promised by the function is retrieved, RXDEMO Add() returns
6053 * Should any failure occur in passing the parameters to and from the server
6054 * side of the call, the branch to fail will invoke Rx EndCall(), which advises
6055 * the server that the call has come to a premature end (see Section 5.6.6 for
6056 * full details on rx EndCall() and the meaning of its return value).
6058 * The next client-side stub appearing in this generated file handles the
6059 * delivery of the IN parameters for StartRXDEMO Getfile(). It operates
6060 * identically as the RXDEMO Add() stub routine in this respect, except that it
6061 * does not attempt to retrieve the OUT parameter. Since this is a streamed
6062 * call, the number of bytes that will be placed on the Rx stream cannot be
6063 * determined at compile time, and must be handled explicitly by rxdemo
6067 *
int StartRXDEMO_Getfile(z_call, a_nameToRead)
6068 * register struct rx_call *z_call;
6069 *
char * a_nameToRead;
6071 *
static int z_op = 2;
6074 * xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
6076 *
if ((!xdr_int(&z_xdrs, &z_op)) || (!xdr_string(&z_xdrs, &a_nameToRead,
6077 * RXDEMO_NAME_MAX_CHARS))) {
6078 * z_result = RXGEN_CC_MARSHAL;
6081 * z_result = RXGEN_SUCCESS;
6082 * fail:
return z_result;
6087 * The
final stub routine appearing in
this generated file, EndRXDEMO
6088 * Getfile(), handles the
case where rxdemo client.c has already successfully
6089 * recovered the unbounded streamed data appearing on the call, and then simply
6090 * has to fetch the OUT parameter. This routine behaves identially to the
6091 * latter portion of RXDEMO Getfile().
6094 *
int EndRXDEMO_Getfile(z_call, a_result)
6095 *
register struct rx_call *z_call;
6101 * xdrrx_create(&z_xdrs, z_call, XDR_DECODE);
6102 *
if ((!xdr_int(&z_xdrs, a_result))) {
6103 * z_result = RXGEN_CC_UNMARSHAL;
6106 * z_result = RXGEN_SUCCESS; fail:
6111 * \subsection sec6-3-2 Server-Side Routines: rxdemo.ss.c
6114 * This generated file provides the core components required to implement the
6115 * server side of the rxdemo RPC service. Included in
this file is the
6116 * generated dispatcher routine, RXDEMO ExecuteRequest(), which the rx
6117 * NewService() invocation in rxdemo server.c uses to construct the body of
6118 * each listener thread's loop. Also included are the server-side stubs to
6119 * handle marshalling and unmarshalling of parameters for each defined RPC call
6120 * (i.e., RXDEMO Add() and RXDEMO Getfile()). These stubs are called by RXDEMO
6121 * ExecuteRequest(). The routine to be called by RXDEMO ExecuteRequest()
6122 * depends on the opcode received, which appears as the very first longword in
6125 * As usual, the first fragment is copyright information followed by the body
6126 * of the definitions from the interface file.
6141 *
#include "rxdemo.h" 6142 * #include <rx/rx.h>
6143 * #include <rx/rx_null.h>
6144 * #define RXDEMO_SERVER_PORT 8000
6145 * #define RXDEMO_SERVICE_PORT 0
6146 * #define RXDEMO_SERVICE_ID 4
6147 * #define RXDEMO_NULL_SECOBJ_IDX 0
6148 * #define RXDEMO_MAX 3
6149 * #define RXDEMO_MIN 2
6150 * #define RXDEMO_NULL 0
6151 * #define RXDEMO_NAME_MAX_CHARS 64
6152 * #define RXDEMO_BUFF_BYTES 512
6153 * #define RXDEMO_CODE_SUCCESS 0
6154 * #define RXDEMO_CODE_CANT_OPEN 1
6155 * #define RXDEMO_CODE_CANT_STAT 2
6156 * #define RXDEMO_CODE_CANT_READ 3
6157 * #define RXDEMO_CODE_WRITE_ERROR 4
6161 * After
this preamble, the first server-side stub appears. This RXDEMO Add()
6162 * routine is basically the inverse of the RXDEMO Add() client-side stub
6163 * defined in rxdemo.cs.c. Its job is to unmarshall the IN parameters for the
6164 * call, invoke the "true" server-side RXDEMO Add() routine (defined in rxdemo
6165 * server.c), and then package and ship the OUT parameter. Being so similar to
6166 * the client-side RXDEMO Add(), no further discussion is offered here.
6169 *
long _RXDEMO_Add(z_call, z_xdrs)
6170 * struct rx_call *z_call;
6176 *
if ((!xdr_int(z_xdrs, &a)) || (!xdr_int(z_xdrs, &b)))
6178 * z_result = RXGEN_SS_UNMARSHAL;
6181 * z_result = RXDEMO_Add(z_call, a, b, &result);
6182 * z_xdrs->x_op = XDR_ENCODE;
6183 *
if ((!xdr_int(z_xdrs, &result)))
6184 * z_result = RXGEN_SS_MARSHAL;
6185 * fail:
return z_result;
6190 * The second server-side stub, RXDEMO Getfile(), appears next. It operates
6191 * identically to RXDEMO Add(), first unmarshalling the IN arguments, then
6192 * invoking the routine that actually performs the server-side work
for the
6193 * call, then finishing up by returning the OUT parameters.
6196 *
long _RXDEMO_Getfile(z_call, z_xdrs)
6197 *
struct rx_call *z_call;
6201 *
char * a_nameToRead=(
char *)0;
6203 *
if ((!xdr_string(z_xdrs, &a_nameToRead, RXDEMO_NAME_MAX_CHARS))) {
6204 * z_result = RXGEN_SS_UNMARSHAL;
6207 * z_result = RXDEMO_Getfile(z_call, a_nameToRead, &a_result);
6208 * z_xdrs->x_op = XDR_ENCODE;
6209 *
if ((!xdr_int(z_xdrs, &a_result)))
6210 * z_result = RXGEN_SS_MARSHAL;
6211 * fail: z_xdrs->x_op = XDR_FREE;
6212 *
if (!xdr_string(z_xdrs, &a_nameToRead, RXDEMO_NAME_MAX_CHARS))
6215 * fail1:
return RXGEN_SS_XDRFREE;
6220 * The next portion of the automatically generated server-side module sets up
6221 * the dispatcher routine
for incoming Rx calls. The above stub routines are
6222 * placed into an array in opcode order.
6225 *
long _RXDEMO_Add();
6226 *
long _RXDEMO_Getfile();
6227 *
static long (*StubProcsArray0[])() = {_RXDEMO_Add, _RXDEMO_Getfile};
6231 * The dispatcher routine itself, RXDEMO ExecuteRequest, appears next. This is
6232 * the
function provided to the rx NewService() call in rxdemo server.c, and it
6233 * is used as the body of each listener thread's service loop. When activated,
6234 * it decodes the first longword in the given Rx call, which contains the
6235 * opcode. It then dispatches the call based on this opcode, invoking the
6236 * appropriate server-side stub as organized in the StubProcsArray.
6239 * RXDEMO_ExecuteRequest(z_call)
6240 * register struct rx_call *z_call;
6245 * xdrrx_create(&z_xdrs, z_call, XDR_DECODE);
6246 *
if (!xdr_int(&z_xdrs, &op))
6247 * z_result = RXGEN_DECODE;
6248 *
else if (op < RXDEMO_LOWEST_OPCODE || op > RXDEMO_HIGHEST_OPCODE)
6249 * z_result = RXGEN_OPCODE;
6251 * z_result = (*StubProcsArray0[op -RXDEMO_LOWEST_OPCODE])(z_call,
6257 * \subsection sec6-3-3 External Data Rep file: rxdemo.xdr.c
6260 * This file is created to provide the special routines needed to map any
6261 * user-defined structures appearing as Rx arguments into and out of network
6262 * byte order. Again, all on-thewire data appears in network byte order,
6263 * insuring proper communication between servers and clients with different
6264 * memory organizations.
6266 * Since the rxdemo example application does not define any special structures
6267 * to pass as arguments in its calls,
this generated file contains only the
set 6268 * of definitions appearing in the
interface file. In general, though, should
6269 * the user define a
struct xyz and use it as a parameter to an RPC function,
6270 *
this file would contain a routine named xdr xyz(), which converted the
6271 * structure field-by-field to and from network byte order.
6294 * #include
"rxdemo.h" 6295 * #include <rx/rx.h>
6296 * #include <rx/rx_null.h>
6297 * #define RXDEMO_SERVER_PORT 8000
6298 * #define RXDEMO_SERVICE_PORT 0
6299 * #define RXDEMO_SERVICE_ID 4
6300 * #define RXDEMO_NULL_SECOBJ_IDX 0
6301 * #define RXDEMO_MAX 3
6302 * #define RXDEMO_MIN 2
6303 * #define RXDEMO_NULL 0
6304 * #define RXDEMO_NAME_MAX_CHARS 64
6305 * #define RXDEMO_BUFF_BYTES 512
6306 * #define RXDEMO_CODE_SUCCESS 0
6307 * #define RXDEMO_CODE_CANT_OPEN 1
6308 * #define RXDEMO_CODE_CANT_STAT 2
6309 * #define RXDEMO_CODE_CANT_READ 3
6310 * #define RXDEMO_CODE_WRITE_ERROR 4
6313 * \section sec6-4 Section 6.4: Sample Output
6316 * This section contains the output generated by running the example rxdemo
6317 * server and rxdemo client programs described above. The server end was run on
6318 * a machine named Apollo, and the client program was run on a machine named
6321 * The server program on Apollo was started as follows:
6322 * \li apollo: rxdemo_server
6323 * \li rxdemo_server: Example Rx server process
6324 * \li Listening on UDP port 8000
6326 * At
this point, rxdemo server has initialized its Rx module and started up
6327 * its listener LWPs, which are sleeping on the arrival of an RPC from any
6330 * The client portion was then started on Bigtime:
6331 * \n bigtime: rxdemo_client apollo
6332 * \n rxdemo: Example Rx client process
6333 * \n Connecting to Rx server on
'apollo', IP address 0x1acf37c0, UDP port 8000
6334 * \n ---> Connected. Asking server to add 1 and 2: Reported sum is 3
6336 * The command line instructs rxdemo client to connect to the rxdemo server on
6337 * host apollo and to use the standard port defined
for this service. It
6338 * reports on the successful Rx connection establishment, and immediately
6339 * executes an rxdemo Add(1, 2) RPC. It reports that the sum was successfully
6340 * received. When the RPC request arrived at the server and was dispatched by
6341 * the rxdemo server code, it printed out the following line:
6342 * \n [Handling call to RXDEMO_Add(1, 2)]
6344 * Next, rxdemo client prompts for the name of the file to read from the rxdemo
6345 * server. It is told to fetch the Makefile for the Rx demo directory. The
6346 * server is executing in the same directory in which it was compiled, so an
6347 * absolute name for the Makefile is not required. The client echoes the
6349 * \n Name of file to read from server: Makefile Setting up an Rx call for
6350 * RXDEMO_Getfile...done
6352 * As with the rxdemo Add() call, rxdemo server receives this RPC, and prints
6353 * out the following information:
6354 * \li [Handling call to RXDEMO_Getfile(Makefile)]
6356 * \li [file has 2450 bytes]
6359 * It successfully opens the named file, and reports on its size in bytes. The
6360 * rxdemo server program then executes the streamed portion of the rxdemo
6361 * Getfile call, and when complete, indicates that the file has been closed.
6362 * Meanwhile, rxdemo client prints out the reported size of the file, follows
6363 * it with the file's contents, then advises that the test run has completed:
6366 * [file contents (2450 bytes) fetched over the Rx call appear below]
6387 * TOOL_CELL = grand.central.org
6388 * AFS_INCLIB_CELL = transarc.com
6389 * USR_CONTRIB = /afs/${TOOL_CELL}/darpa/usr/contrib/
6390 * PROJ_DIR = ${USR_CONTRIB}.site/grand.central.org/rxdemo/
6391 * AFS_INCLIB_DIR = /afs/${AFS_INCLIB_CELL}/afs/dest/
6392 * RXGEN = ${AFS_INCLIB_DIR}bin/rxgen
6393 * INSTALL = ${AFS_INCLIB_DIR}bin/install
6394 * LIBS = ${AFS_INCLIB_DIR}lib/librx.a \ ${AFS_INCLIB_DIR}lib/liblwp.a
6397 * -I${AFS_INCLIB_DIR}include \
6398 * -I${AFS_INCLIB_DIR}include/afs \
6399 * -I${AFS_INCLIB_DIR} \
6405 * ${INSTALL} rxdemo_client ${PROJ_DIR}bin
6406 * ${INSTALL} rxdemo_server ${PROJ_DIR}bin
6408 * all: rxdemo_client rxdemo_server
6410 * rxdemo_client: rxdemo_client.o ${LIBS} rxdemo.cs.o ${CC} ${CFLAGS}
6411 * -o rxdemo_client rxdemo_client.o rxdemo.cs.o ${LIBS}
6413 * rxdemo_server: rxdemo_server.o rxdemo.ss.o ${LIBS} ${CC} ${CFLAGS}
6414 * -o rxdemo_server rxdemo_server.o rxdemo.ss.o ${LIBS}
6416 * rxdemo_client.o: rxdemo.h
6418 * rxdemo_server.o: rxdemo.h
6420 * rxdemo.cs.c rxdemo.ss.c rxdemo.er.c rxdemo.h: rxdemo.xg rxgen rxdemo.xg
6422 * clean: rm -f *.o rxdemo.cs.c rxdemo.ss.c rxdemo.xdr.c rxdemo.h \
6423 * rxdemo_client rxdemo_server core
6425 * [End of file data]
6430 * The rxdemo server program continues to run after handling these calls,
6431 * offering its services to any other callers. It can be killed by sending it
6432 * an interrupt signal
using Control-C (or whatever mapping has been
set up
for 6433 * the shell
's interrupt character). 6435 * \section Bibliography Bibliography 6437 * \li [1] Transarc Corporation. AFS 3.0 System Administrator's Guide,
6438 * F-30-0-D102, Pittsburgh, PA, April 1990.
6439 * \li [2] S.P. Miller, B.C. Neuman, J.I. Schiller, J.H. Saltzer. Kerberos
6440 * Authentication and Authorization System, Project Athena Technical Plan,
6441 * Section E.2.1, M.I.T., December 1987.
6442 * \li [3] Bill Bryant. Designing an Authentication System: a Dialogue
6443 * in Four Scenes, Project Athena
internal document, M.I.T, draft of 8 February
6445 * \li [4] S. R. Kleinman. Vnodes: An Architecture
for Multiple file
6446 * System Types in Sun UNIX, Conference Proceedings, 1986 Summer Usenix
6447 * Technical Conference, pp. 238-247, El Toro, CA, 1986.