Intial commit
This commit is contained in:
1
prospero/lib/ardp/.gitignore
vendored
Normal file
1
prospero/lib/ardp/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
32
prospero/lib/ardp/FILES
Normal file
32
prospero/lib/ardp/FILES
Normal file
@@ -0,0 +1,32 @@
|
||||
FILES
|
||||
Makefile
|
||||
ardp.doc
|
||||
ardp_abort.c
|
||||
ardp_accept.c
|
||||
ardp_add2req.c
|
||||
ardp_breply.c
|
||||
ardp_error.c
|
||||
ardp_get_nxt.c
|
||||
ardp_headers.c
|
||||
ardp_int_err.c
|
||||
ardp_mutexes.c
|
||||
ardp_perrno.c
|
||||
ardp_pr_actv.c
|
||||
ardp_ptalloc.c
|
||||
ardp_reply.c
|
||||
ardp_respond.c
|
||||
ardp_retriev.c
|
||||
ardp_rqalloc.c
|
||||
ardp_send.c
|
||||
ardp_showbuf.c
|
||||
ardp_snd_pkt.c
|
||||
ardp_srv_ini.c
|
||||
ardp_xmit.c
|
||||
dnscache_alloc.c
|
||||
dnscache_alloc.h
|
||||
flocks.c
|
||||
flocks.h
|
||||
hostname2adr.c
|
||||
p__th_self_num.c
|
||||
unixerrstr.c
|
||||
usc_lic_str.c
|
||||
246
prospero/lib/ardp/Makefile.in
Executable file
246
prospero/lib/ardp/Makefile.in
Executable file
@@ -0,0 +1,246 @@
|
||||
#
|
||||
# Makefile for Prospero Directory Service ARDP library.
|
||||
SOURCEBASE = ../..
|
||||
include $(SOURCEBASE)/Makefile.config
|
||||
|
||||
CFLAGS += -I$(ARCHIE_ROOT)/include
|
||||
|
||||
|
||||
CFILES = ardp_abort.c \
|
||||
ardp_accept.c \
|
||||
ardp_add2req.c \
|
||||
ardp_breply.c \
|
||||
ardp_error.c \
|
||||
ardp_get_nxt.c \
|
||||
ardp_headers.c \
|
||||
ardp_int_err.c \
|
||||
ardp_mutexes.c \
|
||||
ardp_perrno.c \
|
||||
ardp_pr_actv.c \
|
||||
ardp_ptalloc.c \
|
||||
ardp_reply.c \
|
||||
ardp_respond.c \
|
||||
ardp_retriev.c \
|
||||
ardp_rqalloc.c \
|
||||
ardp_send.c \
|
||||
ardp_showbuf.c \
|
||||
ardp_snd_pkt.c \
|
||||
ardp_srv_ini.c \
|
||||
ardp_xmit.c \
|
||||
dnscache_alloc.c \
|
||||
flocks.c \
|
||||
hostname2adr.c \
|
||||
p__th_self_num.c \
|
||||
restrict.c \
|
||||
unixerrstr.c \
|
||||
usc_lic_str.c
|
||||
|
||||
OBJECTS = ardp_abort.o \
|
||||
ardp_accept.o \
|
||||
ardp_add2req.o \
|
||||
ardp_breply.o \
|
||||
ardp_error.o \
|
||||
ardp_get_nxt.o \
|
||||
ardp_headers.o \
|
||||
ardp_int_err.o \
|
||||
ardp_mutexes.o \
|
||||
ardp_perrno.o \
|
||||
ardp_pr_actv.o \
|
||||
ardp_ptalloc.o \
|
||||
ardp_reply.o \
|
||||
ardp_respond.o \
|
||||
ardp_retriev.o \
|
||||
ardp_rqalloc.o \
|
||||
ardp_send.o \
|
||||
ardp_showbuf.o \
|
||||
ardp_snd_pkt.o \
|
||||
ardp_srv_ini.o \
|
||||
ardp_xmit.o \
|
||||
dnscache_alloc.o \
|
||||
flocks.o \
|
||||
hostname2adr.o \
|
||||
p__th_self_num.o \
|
||||
restrict.o \
|
||||
unixerrstr.o \
|
||||
usc_lic_str.o
|
||||
|
||||
all: ${RDP_LIB}
|
||||
|
||||
install:
|
||||
cp ${RDP_LIB} ${P_BINARIES}/${RDP_LIB}
|
||||
$(RANLIB) ${P_BINARIES}/${RDP_LIB}
|
||||
|
||||
${RDP_LIB}: ${OBJECTS}
|
||||
rm -f ${RDP_LIB}
|
||||
ar r${AR_FLAGS} ${RDP_LIB} ${OBJECTS}
|
||||
$(RANLIB) ${RDP_LIB}
|
||||
|
||||
# Dependencies
|
||||
ardp_abort.o : ../../include/posix_signal.h \
|
||||
../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h ../../include/implicit_fixes.h \
|
||||
../../include/ardp.h \
|
||||
../../include/../lib/ardp/flocks.h \
|
||||
../../include/pfs.h ../../include/pmachine.h
|
||||
ardp_accept.o : \
|
||||
../../include/ardp.h \
|
||||
../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
|
||||
../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/pserver.h ../../include/plog.h \
|
||||
../../include/pprot.h
|
||||
ardp_add2req.o : \
|
||||
../../include/ardp.h \
|
||||
../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
ardp_breply.o : \
|
||||
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
ardp_error.o : ../../include/ardp.h \
|
||||
../../include/pfs_threads.h \
|
||||
../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/perrno.h
|
||||
ardp_get_nxt.o : \
|
||||
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
|
||||
../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
ardp_headers.o : \
|
||||
../../include/ardp.h ../../include/pfs_threads.h \
|
||||
../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
ardp_int_err.o : ../../include/ardp.h \
|
||||
../../include/pfs_threads.h \
|
||||
../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
ardp_mutexes.o : ../../include/pfs_threads.h \
|
||||
../../include/pfs_utils.h \
|
||||
../../include/ardp.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
ardp_perrno.o : ../../include/ardp.h \
|
||||
../../include/pfs_threads.h \
|
||||
../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
ardp_pr_actv.o : \
|
||||
../../include/ardp.h \
|
||||
../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
|
||||
../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/perrno.h
|
||||
ardp_ptalloc.o : \
|
||||
../../include/ardp.h \
|
||||
../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/mitra_macros.h
|
||||
ardp_reply.o : \
|
||||
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
ardp_respond.o : \
|
||||
../../include/ardp.h \
|
||||
../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/plog.h
|
||||
ardp_retriev.o : \
|
||||
../../include/ardp.h ../../include/pfs_threads.h \
|
||||
../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/perrno.h
|
||||
ardp_rqalloc.o : \
|
||||
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
ardp_send.o : \
|
||||
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
|
||||
../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/perrno.h ../../include/pcompat.h
|
||||
ardp_showbuf.o :
|
||||
ardp_snd_pkt.o : \
|
||||
../../include/ardp.h ../../include/pfs_threads.h \
|
||||
../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/plog.h \
|
||||
../../include/perrno.h
|
||||
ardp_srv_ini.o : \
|
||||
../../include/ardp.h \
|
||||
../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/plog.h
|
||||
ardp_xmit.o : \
|
||||
../../include/ardp.h \
|
||||
../../include/pfs_threads.h ../../include/pfs_utils.h \
|
||||
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
|
||||
../../include/pfs.h ../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
dnscache_alloc.o : dnscache_alloc.h ../../include/pfs.h \
|
||||
../../include/pfs_utils.h ../../include/ardp.h \
|
||||
../../include/pfs_threads.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/mitra_macros.h
|
||||
flocks.o : ../../include/pfs.h ../../include/pfs_utils.h \
|
||||
../../include/ardp.h \
|
||||
../../include/pfs_threads.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/plog.h \
|
||||
flocks.h ../../include/mitra_macros.h
|
||||
hostname2adr.o : ../../include/ardp.h \
|
||||
../../include/pfs_threads.h \
|
||||
../../include/pfs_utils.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h \
|
||||
../../include/perrno.h ../../include/string_with_strcasecmp.h \
|
||||
../../include/pserver.h dnscache_alloc.h ../../include/pcompat.h \
|
||||
../../include/mitra_macros.h
|
||||
p__th_self_num.o : ../../include/pfs_threads.h \
|
||||
../../include/pfs_utils.h \
|
||||
../../include/ardp.h \
|
||||
../../include/list_macros.h \
|
||||
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
|
||||
../../include/pmachine.h \
|
||||
../../include/implicit_fixes.h
|
||||
unixerrstr.o : ../../include/pmachine.h
|
||||
usc_lic_str.o :
|
||||
85
prospero/lib/ardp/Makefile.tmp
Executable file
85
prospero/lib/ardp/Makefile.tmp
Executable file
@@ -0,0 +1,85 @@
|
||||
#
|
||||
# Makefile for Prospero Directory Service ARDP library.
|
||||
SOURCEBASE = ../..
|
||||
include $(SOURCEBASE)/Makefile.config
|
||||
|
||||
CFILES = ardp_abort.c \
|
||||
ardp_accept.c \
|
||||
ardp_add2req.c \
|
||||
ardp_breply.c \
|
||||
ardp_error.c \
|
||||
ardp_get_nxt.c \
|
||||
ardp_headers.c \
|
||||
ardp_int_err.c \
|
||||
ardp_mutexes.c \
|
||||
ardp_perrno.c \
|
||||
ardp_pr_actv.c \
|
||||
ardp_ptalloc.c \
|
||||
ardp_reply.c \
|
||||
ardp_respond.c \
|
||||
ardp_retriev.c \
|
||||
ardp_rqalloc.c \
|
||||
ardp_send.c \
|
||||
ardp_showbuf.c \
|
||||
ardp_snd_pkt.c \
|
||||
ardp_srv_ini.c \
|
||||
ardp_xmit.c \
|
||||
dnscache_alloc.c \
|
||||
flocks.c \
|
||||
hostname2adr.c \
|
||||
p__th_self_num.c \
|
||||
unixerrstr.c \
|
||||
usc_lic_str.c
|
||||
|
||||
OBJECTS = ardp_abort.o \
|
||||
ardp_accept.o \
|
||||
ardp_add2req.o \
|
||||
ardp_breply.o \
|
||||
ardp_error.o \
|
||||
ardp_get_nxt.o \
|
||||
ardp_headers.o \
|
||||
ardp_int_err.o \
|
||||
ardp_mutexes.o \
|
||||
ardp_perrno.o \
|
||||
ardp_pr_actv.o \
|
||||
ardp_ptalloc.o \
|
||||
ardp_reply.o \
|
||||
ardp_respond.o \
|
||||
ardp_retriev.o \
|
||||
ardp_rqalloc.o \
|
||||
ardp_send.o \
|
||||
ardp_showbuf.o \
|
||||
ardp_snd_pkt.o \
|
||||
ardp_srv_ini.o \
|
||||
ardp_xmit.o \
|
||||
dnscache_alloc.o \
|
||||
flocks.o \
|
||||
hostname2adr.o \
|
||||
p__th_self_num.o \
|
||||
unixerrstr.o \
|
||||
usc_lic_str.o
|
||||
|
||||
all: ${RDP_LIB}
|
||||
|
||||
install:
|
||||
cp ${RDP_LIB} ${P_BINARIES}/${RDP_LIB}
|
||||
$(RANLIB) ${P_BINARIES}/${RDP_LIB}
|
||||
|
||||
${RDP_LIB}: ${OBJECTS}
|
||||
rm -f ${RDP_LIB}
|
||||
ar r${AR_FLAGS} ${RDP_LIB} ${OBJECTS}
|
||||
$(RANLIB) ${RDP_LIB}
|
||||
|
||||
# Dependencies
|
||||
setdependencies:
|
||||
gcc -M $(CFLAGS) $(CFILES) | sed \
|
||||
-e 's, [^ ]*\.c,,' \
|
||||
-e 's, /local/gnu/[^ ]*,,g' \
|
||||
-e 's, /usr/include/[^ ]*,,g' \
|
||||
-e 's, [./]*include/pthread\.h,,' \
|
||||
-e 's, [./]*include/pthread/[^ ]*,,g' \
|
||||
-e 's, [^ ]*/fsu_pthreads/include/[^ ]*,,g' \
|
||||
-e 's, [./]*include/usc-copyr\.h,,' \
|
||||
-e 's, [./]*include/usc-license\.h,,' \
|
||||
-e 's, [./]*include/uw-copyright\.h,,' \
|
||||
-e '/^[ ]*\\$$/d' | fixdep > dependency.list
|
||||
262
prospero/lib/ardp/ardp.doc
Normal file
262
prospero/lib/ardp/ardp.doc
Normal file
@@ -0,0 +1,262 @@
|
||||
To use the library, include the file <ardp.h>.
|
||||
|
||||
The current release has dependencies upon Prospero in a few places:
|
||||
|
||||
If you will not be using the Prospero pauth structure, undefine
|
||||
PROSPERO in ardp.h. The RREQ structure includes a reference to PAUTH
|
||||
by default.
|
||||
|
||||
The ARDP library server routines currently call the Prospero function
|
||||
plog(). A useful future direction is to make the logging function
|
||||
application-specific, and inactive by default.
|
||||
|
||||
The ardp_reply_bst() function depends upon Propero bstrings. It will
|
||||
not be included in the library if PROSPERO is not defined in ardp.h.
|
||||
|
||||
---
|
||||
Error handling: ARDP library functions return error codes between 1
|
||||
and 20. A return value of 0 is ARDP_SUCCESS. In addition, the global
|
||||
variable
|
||||
|
||||
extern int perrno;
|
||||
|
||||
is generally set to the number of the error. (We haven't actually
|
||||
checked every function in the ARDP library to guarantee this). This
|
||||
global variable is used in the ARDP library, and in the PFS library.
|
||||
|
||||
The function p_clear_errors() should be called from your application
|
||||
to clear this error indication. If you've linked with the PFS library
|
||||
version, then p_clear_errors() will also clear Prospero error and
|
||||
warning indications. This function is defined both in the PFS library
|
||||
and in the ARDP library; if you're a PFS library and an ARDP library
|
||||
user, place the PFS library version first in your link path. Its
|
||||
declaration is:
|
||||
extern void p_clear_errors(void);
|
||||
|
||||
Printed strings associated with these errors can be found in
|
||||
lib/pfs/perrmesg.c. These are not currently available through the
|
||||
ARDP library interface, although it does not depend upon them being
|
||||
present. A future direction is to make these strings available
|
||||
through the RDP library interface.
|
||||
|
||||
--
|
||||
The ARDP library is now completely safe for sending arbitrary
|
||||
length-coded binary data. (Until Prospero release Alpha.5.3, this was
|
||||
not the case -- the server library used to append nulls to packets.)
|
||||
|
||||
--
|
||||
Notes on the PTEXT structure:
|
||||
|
||||
The PTEXT structure has two members, ->text and ->start. On the user
|
||||
side, they are currently always the same; however, this is not always
|
||||
guaranteed to be the case in future releases of the ARDP library.
|
||||
->text is used for the start of data to be parsed by the higher-level
|
||||
application (e.g., Prospero). The ->length member of the PTEXT
|
||||
structure is relative to ->start, which in this case is the same as
|
||||
->text, but which is not guaranted to be so. Thus, if you need the
|
||||
length of the text (relative to the start of ->text), it is ->length -
|
||||
(->text - ->start).
|
||||
|
||||
--
|
||||
Notes on the functions:
|
||||
|
||||
In the functions that follow, more details on the function can be
|
||||
found in the header preceding the function in the source code. This
|
||||
documentation is solely for the purpose of helping you decide which
|
||||
functions to look at. (Another way of saying that we are well aware
|
||||
that this manual is pretty sketchy.) Functions in the library that
|
||||
are not described here should be considered internal and should not be
|
||||
called by the application.
|
||||
|
||||
The following functions are exported by the ardp library for use by
|
||||
the client side of a connection:
|
||||
|
||||
ardp_abort(req) Aborts the specified request, sending an
|
||||
abort message to the server if currently
|
||||
active. If req is null, will send aborts
|
||||
to servers for all active requests.
|
||||
|
||||
ardp_abort_on_int() Sets interrupt handler to abort any
|
||||
pending requests.
|
||||
|
||||
ardp_pr_active() Processes new responses to active requests.
|
||||
If making an asynchronous request (i.e. ttwait
|
||||
does not equal ARDP_WAIT_TILL_TO), then this
|
||||
function must be called periodically, either
|
||||
automatically within ardp_retrieve, explicitly,
|
||||
or initiated by an interrupt when
|
||||
a response becomes available on the UDP port.
|
||||
|
||||
ardp_retrieve(req,ttwait)
|
||||
Poll for, or wait for a pending request to
|
||||
complete.
|
||||
|
||||
ardp_send(req,dname,dest,ttwait)
|
||||
Sends request to host with domain name
|
||||
or socket address dest, and waits ttwait
|
||||
microseconds for response (-1 means till timeout).
|
||||
|
||||
ardp_set_retry(to,rt) Set retry time out (seconds) and count
|
||||
|
||||
The following functions are exported by the ardp library for use by
|
||||
the server side of a connection:
|
||||
|
||||
ardp_accept() Accepts new requests and places on appropriate
|
||||
queues for subsequent processing. This must
|
||||
be called periodically, either explicitly, or
|
||||
initiated by an interrupt when a request
|
||||
becomes available on the UDP port.
|
||||
|
||||
ardp_bind_port(portname)
|
||||
Takes the name of (or #number) of a port to
|
||||
be opened, on which the server will listen
|
||||
for requests.
|
||||
|
||||
RREQ ardp_get_nxt() Returns the next request to be processed.
|
||||
If none available, it will block until
|
||||
one is received.
|
||||
|
||||
|
||||
ardp_redirect(req,target)
|
||||
Sends a redirect to the client indicating the
|
||||
the request should be sent to a new target
|
||||
server identified in the second argument.
|
||||
|
||||
ardp_respond(req,opt) Used by a server to send the current response
|
||||
packet once filled in. It will add the packet
|
||||
to the transmission queue, and send it. To
|
||||
indicate completion of a response, the
|
||||
ARDP_RESP_COMPLETE option should be specified.
|
||||
If the ARDP_RESP_NOSEND option is specified,
|
||||
the packet will be added to the transmission queue
|
||||
but not sent.
|
||||
|
||||
ardp_refuse(req) Causes the specified request to be refused and
|
||||
notification sent to the client.
|
||||
|
||||
ardp_reply(req,flags,message)
|
||||
Queues message (appending it to the req structure)
|
||||
and possibly sends it and other queued data to the
|
||||
client. Will call ardp_respond() if any
|
||||
completed packets can be sent (i.e., sends a
|
||||
partial response to speed up client/server
|
||||
interaction). Message is a null-terminated buffer.
|
||||
Can't use this interface to send binary data
|
||||
that might contain nulls; see
|
||||
ardp_reply_bst() below.
|
||||
|
||||
ardp_rwait(req,timetowait,qpos,stime)
|
||||
This function is called by a server to specify
|
||||
a server requested time to wait for a response.
|
||||
This value is returned to the client which
|
||||
will treat it as an acknowledgment and will
|
||||
defer subsequent timeouts and retries until
|
||||
waiting the specified period. Non-zero values
|
||||
for qpos and stime will cause the current
|
||||
the specified queue position and expected
|
||||
system time to be provided to the client in
|
||||
the same message.
|
||||
|
||||
ardp_set_queuing_policy(pf,override)
|
||||
Sets a function used to determine queue
|
||||
ordering on the server.
|
||||
|
||||
ardp_set_prvport(fd) Sets a file descriptor that has already been
|
||||
opened as the input port on which the server
|
||||
will listen for requests.
|
||||
|
||||
The following functions are exported by the ardp library for use by
|
||||
both the client and server sides of a connection:
|
||||
|
||||
ardp_add2req(req,flags,buf,len)
|
||||
Adds text to a request which will subsequently
|
||||
be sent to the peer, and returns.
|
||||
|
||||
RREQ ardp_rqalloc() Allocate a new request structure
|
||||
ardp_rqfree(req) Free a request structure
|
||||
ardp_rqlfree(req) Free a list of request structures
|
||||
|
||||
PTEXT ardp_ptalloc() Allocate a new packet structure
|
||||
ardp_ptfree(pkt) Free a packet structure
|
||||
ardp_ptlfree(pkt) Free a list of packet structures
|
||||
|
||||
/********************/
|
||||
|
||||
Internal functions:
|
||||
ardp_showbuf() is used to display buffers that might contain
|
||||
nulls.
|
||||
|
||||
/******************/
|
||||
|
||||
Eventually to be built on top of the above:
|
||||
|
||||
rd_sbuf Synchronously send a buffer to a destination
|
||||
rd_sbufa Asynchronously send a buffer to a destination
|
||||
rd_sync Wait until all pending requests are complete
|
||||
|
||||
/********************/
|
||||
|
||||
The ARDP library respects the global integer variable pfs_debug.
|
||||
Levels of 9 or above cause the text of packets sent across the network
|
||||
to be displayed to stderr.
|
||||
|
||||
As of Prospero Alpha.5.3 release, an ARDP library pfs_debug level of
|
||||
11 or greater will cause \n and \t and \r to be printed as \n and \t
|
||||
and \r in the display of the contents of ARDP packets. Levels 9 and
|
||||
10 cause them to be displayed as themselves. All other control
|
||||
characters in packets are now displayed as a \ followed by the
|
||||
character's octal code. (In previous releases, they were displayed as
|
||||
literal text, and nulls in the packet caused the display of the packet
|
||||
text to be ignored.)
|
||||
|
||||
/*************/
|
||||
|
||||
The new ARDP_REPLY_BST() function accepts a Prospero BSTRING as its
|
||||
argument. This violates modularity of the ARDP library, since it
|
||||
requires the ARDP library to know about the bstrings layer. We need a
|
||||
new interface to ardp_reply() that will accept a length-coded buffer,
|
||||
and then a wrapper around it in the pfs library that will accept the
|
||||
bstring. Future directions for this function are noted at ISI in
|
||||
/nfs/pfs/notes/ardp-directions.
|
||||
|
||||
ardp_reply_bst(RREQ req, /* Request to which this is a response */
|
||||
int flags, /* Whether this is the final message */
|
||||
char *message) /* The data to be sent. Must be a bstring. */
|
||||
|
||||
/**** BUGS & future directions *****/
|
||||
|
||||
ardp_retrieve() and ardp_send() both call p_clear_errors() internally.
|
||||
This is inconsistent with the behavior of the rest of the ARDP library
|
||||
and of most of the PFs library, which do not clear error indications
|
||||
themselves.
|
||||
|
||||
|
||||
Look over ardp.h.
|
||||
-Make it independent of Prospero directory service: Put authentication
|
||||
stuff into ardp.h as a formal library. Alternatively, make the
|
||||
directory service use the 'app' optional member. (at least until the
|
||||
authentication stuff is better defined).
|
||||
|
||||
Make sure the app optional member is defined and explained in the ARDP stuff.
|
||||
|
||||
-Get rid of #define PROSPERO in ardp.h
|
||||
-ARDP_DEFAULT_PEER and ARDP_DEFAULT_PORT must become optional
|
||||
constants.
|
||||
|
||||
Change the ardp library interface so that the logging function is
|
||||
specified at runtime initialization.
|
||||
|
||||
ardp_reply should have the interface changed to accept a message
|
||||
length, just like ardp_add2req() does. Ditto any other functions in the
|
||||
libardp interface that expect just null terminated buffers. The ARDP
|
||||
library should be better documented for potential programmers.
|
||||
|
||||
Fix bug: ardp_respond() expects trailing null on buffer
|
||||
ardp_add2req() hands. (this is on the SWA todo list as a separate
|
||||
item).
|
||||
|
||||
SWA has rewritten ardp_add2req on paper; need to type in these
|
||||
simplifying changes.
|
||||
|
||||
|
||||
|
||||
109
prospero/lib/ardp/ardp_abort.c
Normal file
109
prospero/lib/ardp/ardp_abort.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>.
|
||||
*
|
||||
* Written by bcn 1/93 to abort pending requests
|
||||
*/
|
||||
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <posix_signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <pfs_threads.h>
|
||||
#include <list_macros.h>
|
||||
#include <implicit_fixes.h>
|
||||
#include <ardp.h>
|
||||
#include <pmachine.h>
|
||||
|
||||
extern RREQ ardp_activeQ; /* Info about active requests */
|
||||
extern int ardp_port; /* Opened UDP port */
|
||||
extern int pfs_debug; /* Debug level */
|
||||
extern int ardp_activeQ_len; /* Length of ardp_activeQ */
|
||||
|
||||
/*
|
||||
* ardp_abort - abort a pending request
|
||||
*
|
||||
* ardp_abort takes a pointer to a request structure of a request to
|
||||
* be aborted, sends an abort request to the server handling the pending,
|
||||
* request, and immediately returns. If the request is null (NOREQ), then
|
||||
* all requests on the ardp_activeQ are aborted.
|
||||
*/
|
||||
int
|
||||
ardp_abort(req)
|
||||
RREQ req; /* Request to be aborted */
|
||||
{
|
||||
PTEXT ptmp = NOPKT; /* Abort packet to be sent */
|
||||
RREQ rtmp = NOREQ; /* Current request to abort */
|
||||
int ns; /* Number of bytes actually sent */
|
||||
|
||||
if(req && (req->status != ARDP_STATUS_ACTIVE)) return(ARDP_BAD_REQ);
|
||||
|
||||
if(req) rtmp = req;
|
||||
else rtmp = ardp_activeQ;
|
||||
|
||||
ptmp = ardp_ptalloc();
|
||||
|
||||
/* Add header */
|
||||
ptmp->start -= 13;
|
||||
ptmp->length += 13;
|
||||
*(ptmp->start) = (char) 13;
|
||||
/* An unsequenced control packet */
|
||||
bzero(ptmp->start+3,10);
|
||||
/* Cancel flag */
|
||||
*(ptmp->start+12) = 0x01;
|
||||
|
||||
while(rtmp) {
|
||||
bcopy2(&(rtmp->cid),ptmp->start+1);
|
||||
if (pfs_debug >= 6) {
|
||||
if(rtmp->peer.sin_family == AF_INET)
|
||||
fprintf(stderr,"\nSending abort message (cid=%d) to %s(%d)...",
|
||||
ntohs(rtmp->cid),inet_ntoa(rtmp->peer_addr),PEER_PORT(rtmp));
|
||||
else fprintf(stderr,"\nSending abort message...");
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
ns = sendto(ardp_port,(char *)(ptmp->start), ptmp->length, 0,
|
||||
&(rtmp->peer), S_AD_SZ);
|
||||
if(ns != ptmp->length) {
|
||||
if (pfs_debug) {
|
||||
fprintf(stderr,"\nsent only %d/%d: ",ns, ptmp->length);
|
||||
perror("");
|
||||
}
|
||||
ardp_ptfree(ptmp);
|
||||
return(ARDP_NOT_SENT);
|
||||
}
|
||||
if (pfs_debug >= 6) fprintf(stderr,"Sent.\n");
|
||||
|
||||
rtmp->status = ARDP_STATUS_ABORTED;
|
||||
EXTRACT_ITEM(rtmp,ardp_activeQ);
|
||||
--ardp_activeQ_len;
|
||||
if(req) rtmp = NOREQ;
|
||||
else rtmp = rtmp->next;
|
||||
}
|
||||
|
||||
ardp_ptfree(ptmp);
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* ardp_trap_int - signal handler to abort request on ^C
|
||||
*/
|
||||
SIGNAL_RET_TYPE ardp_trap_int()
|
||||
{
|
||||
ardp_abort(NOREQ);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* ardp_abort_on_int - set up signal handler to abort request on ^C
|
||||
*/
|
||||
int
|
||||
ardp_abort_on_int()
|
||||
{
|
||||
signal(SIGINT,ardp_trap_int);
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
752
prospero/lib/ardp/ardp_accept.c
Normal file
752
prospero/lib/ardp/ardp_accept.c
Normal file
@@ -0,0 +1,752 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>
|
||||
*
|
||||
* Written by bcn 1991 as check_for_messages in rdgram.c (Prospero)
|
||||
* Modified by bcn 1/93 modularized and incorporated into new ardp library
|
||||
* Modified by swa 12/93 made handle arbitrary length ardp_runQ
|
||||
* Modified by swa 3/95 for bunyip; trapping errno 9 in bad rcvfrom.
|
||||
*/
|
||||
|
||||
/* This version of lib/ardp/ardp_accept.c will work both in Prospero
|
||||
Prealpha.17May94 and in the current (as of 3/21/95) working sources at ISI.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
/* Need types.h for u_short */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef AIX
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#ifdef SOLARIS
|
||||
#include <sys/signal.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <ardp.h>
|
||||
#include <pserver.h>
|
||||
#include <plog.h>
|
||||
#include <pprot.h>
|
||||
#include <pmachine.h>
|
||||
#include <pfs_threads.h> /* Mutex stuff */
|
||||
|
||||
#define LOG_PACKET(REQ,QP) \
|
||||
if((REQ)->priority || (pQlen > 4)) \
|
||||
if(pQNlen && (REQ)->priority) \
|
||||
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d (%d) - Priority %d", \
|
||||
QP, pQlen, pQNlen, (REQ)->priority, 0); \
|
||||
else if(pQNlen) \
|
||||
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d (%d)", \
|
||||
QP, pQlen, pQNlen, 0); \
|
||||
else if((REQ)->priority) \
|
||||
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d - Priority %d", \
|
||||
QP, pQlen, (REQ)->priority, 0); \
|
||||
else if(QP != pQlen) \
|
||||
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d", QP, pQlen, 0); \
|
||||
else plog(L_QUEUE_INFO, REQ, "Queued: %d", pQlen, 0);
|
||||
|
||||
|
||||
EXTERN_MUTEXED_DEF_INITIALIZER(RREQ,ardp_pendingQ,NOREQ); /*Pending requests*/
|
||||
int pQlen = 0; /* Length of pending queue */
|
||||
int pQNlen = 0; /* Number of niced requests */
|
||||
|
||||
static RREQ ardp_partialQ = NOREQ; /* Incomplete requests */
|
||||
int ptQlen = 0; /* Length of incomplete queue */
|
||||
int ptQmaxlen = 20; /* Max length of incomplete queue */
|
||||
EXTERN_MUTEXED_DEF_INITIALIZER(RREQ,ardp_runQ,NOREQ); /* Requests currently in
|
||||
progress */
|
||||
EXTERN_MUTEXED_DEF_INITIALIZER(RREQ,ardp_doneQ,NOREQ); /* Processed requests
|
||||
*/
|
||||
int dQlen = 0; /* Length of reply queue */
|
||||
/* Mutexed with ardp_doneQ */
|
||||
int dQmaxlen = 20; /* Max length of reply queue */
|
||||
|
||||
static struct timeval zerotime = {0, 0}; /* Used by select */
|
||||
|
||||
#define max(x,y) (x > y ? x : y)
|
||||
|
||||
extern int (*ardp_pri_func)(); /* Function to compare priorities */
|
||||
extern int ardp_pri_override; /* If 1, overide value in request */
|
||||
|
||||
/* C library error facility */
|
||||
|
||||
extern int ardp_srvport;
|
||||
extern int ardp_prvport;
|
||||
#ifdef ARCHIE
|
||||
#ifdef __STDC__
|
||||
extern int arch_get_etime(RREQ);
|
||||
#else
|
||||
extern int arch_get_etime();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static void ardp_update_cfields(RREQ existing, RREQ newvalues);
|
||||
static void ardp_header_ack_rwait(PTEXT tpkt, RREQ nreq, int is_ack_needed,
|
||||
int is_rwait_needed);
|
||||
|
||||
|
||||
int
|
||||
ardp_accept_and_wait(int timeout, int usec)
|
||||
{
|
||||
struct sockaddr_in from;
|
||||
int fromlen;
|
||||
int n = 0;
|
||||
PTEXT pkt;
|
||||
unsigned char flags1,flags2;
|
||||
unsigned short pid; /* protocol ID for higher-level protocol */
|
||||
int qpos; /* Position of new req in queue */
|
||||
int dpos; /* Position of dupe in queue */
|
||||
RREQ creq; /* Current request */
|
||||
RREQ treq; /* Temporary request pointer */
|
||||
RREQ nreq; /* New request pointer */
|
||||
RREQ areq = NOREQ; /* Request needing ack */
|
||||
RREQ match_in_runQ = NOREQ; /* if match found in runq for
|
||||
completed request. */
|
||||
int hdr_len;
|
||||
char *ctlptr;
|
||||
short stmp;
|
||||
int tmp;
|
||||
int check_for_ack = 1;
|
||||
fd_set readfds; /* Used for select */
|
||||
long now; /* Time - used for retries */
|
||||
long rr_time = 0; /* Time last retrans from done queue */
|
||||
|
||||
struct timeval time_out;
|
||||
time_out.tv_sec = timeout;
|
||||
time_out.tv_usec = usec;
|
||||
|
||||
|
||||
#ifdef PFS_THREADS
|
||||
/* Changed from original interface. This will try the lock and return
|
||||
an error if unsuccessful. Otherwise it will get the lock */
|
||||
if (p_th_mutex_trylock(p_th_mutexARDP_ACCEPT))
|
||||
return ARDP_SUCCESS; /* Being retrieved */
|
||||
#endif
|
||||
check_for_more:
|
||||
/* This is initialized afresh before each select(). Some operating
|
||||
systems, such as LINUX, modify the time_out parameter to SELECT().
|
||||
--swa, 6/19/94 */
|
||||
|
||||
time_out.tv_sec = timeout;
|
||||
time_out.tv_usec = usec;
|
||||
now = time(NULL);
|
||||
|
||||
/* Check both the prived and unprived ports if necessary */
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(ardp_srvport, &readfds);
|
||||
if(ardp_prvport != -1) FD_SET(ardp_prvport, &readfds);
|
||||
tmp = select(max(ardp_srvport,ardp_prvport) + 1,
|
||||
&readfds,(fd_set *)0,(fd_set *)0,&time_out);
|
||||
|
||||
if(tmp == 0) {
|
||||
if(areq) ardp_acknowledge(areq); areq = NOREQ;
|
||||
p_th_mutex_unlock(p_th_mutexARDP_ACCEPT);
|
||||
return ARDP_SUCCESS;
|
||||
}
|
||||
if(tmp < 0) {
|
||||
p_th_mutex_unlock(p_th_mutexARDP_ACCEPT);
|
||||
return ARDP_SELECT_FAILED;
|
||||
}
|
||||
creq = ardp_rqalloc();
|
||||
pkt = ardp_ptalloc();
|
||||
|
||||
/* There is a message waiting, add it to the queue */
|
||||
|
||||
fromlen = sizeof(from);
|
||||
if((ardp_prvport >= 0) && FD_ISSET(ardp_prvport,&readfds))
|
||||
n = recvfrom(ardp_prvport, pkt->dat, ARDP_PTXT_LEN_R, 0,
|
||||
(struct sockaddr *) &from, &fromlen);
|
||||
else {
|
||||
assert(FD_ISSET(ardp_srvport, &readfds));
|
||||
n = recvfrom(ardp_srvport, pkt->dat, ARDP_PTXT_LEN_R, 0,
|
||||
(struct sockaddr *) &from, &fromlen);
|
||||
}
|
||||
if (n <= 0) {
|
||||
plog(L_NET_ERR,NOREQ,"Bad recvfrom n = %d errno = %d %s",
|
||||
n, errno, unixerrstr(), 0);
|
||||
|
||||
/* I added this in response to a problem experienced by Bunyip.
|
||||
--swa, 3/21/95 */
|
||||
if (errno == 9) {
|
||||
if ((ardp_prvport >= 0) && FD_ISSET(ardp_prvport, &readfds))
|
||||
plog(L_NET_ERR, NOREQ, "The bad descriptor was descriptor #%d,
|
||||
represented internally by the variable ardp_prvport", ardp_prvport);
|
||||
else if (FD_ISSET(ardp_srvport, &readfds))
|
||||
plog(L_NET_ERR, NOREQ, "The bad descriptor was descriptor #%d,
|
||||
represented internally by the variable ardp_srvport", ardp_srvport);
|
||||
else
|
||||
internal_error("Something is wrong with your system's version
|
||||
of select(). No descriptors are readable; unclear how we got here.");
|
||||
|
||||
plog(L_NET_ERR, NOREQ,
|
||||
"This should never happen. Attempting to restart server with SIGUSR1.");
|
||||
kill(getpid(), SIGUSR1); /* sending restart signal to Prospero
|
||||
server or to whatever we hand*/
|
||||
|
||||
}
|
||||
ardp_rqfree(creq); ardp_ptfree(pkt);
|
||||
p_th_mutex_unlock(p_th_mutexARDP_ACCEPT);
|
||||
return ARDP_BAD_RECV;
|
||||
}
|
||||
|
||||
|
||||
bcopy(&from,&(creq->peer),sizeof(creq->peer));
|
||||
creq->cid = 0; creq->peer_ardp_version = 0;
|
||||
creq->rcvd_time.tv_sec = now;
|
||||
creq->prcvd_thru = 0;
|
||||
|
||||
if ( ! verify_acl_list(&from) ) {
|
||||
ardp_breply(creq, ARDP_R_COMPLETE, acl_message(),0);
|
||||
ardp_ptfree(pkt);
|
||||
goto check_for_more;
|
||||
}
|
||||
|
||||
pkt->start = pkt->dat;
|
||||
pkt->length = n;
|
||||
*(pkt->start + pkt->length) = '\0';
|
||||
pkt->mbz = 0; /* force zeros to catch runaway strings */
|
||||
|
||||
pkt->seq = 1;
|
||||
if((hdr_len = (unsigned char) *(pkt->start)) < 32) {
|
||||
ctlptr = pkt->start + 1;
|
||||
pkt->seq = 0;
|
||||
if(hdr_len >= 3) { /* Connection ID */
|
||||
bcopy2(ctlptr,&stmp);
|
||||
if(stmp) creq->cid = ntohs(stmp);
|
||||
ctlptr += 2;
|
||||
}
|
||||
if(hdr_len >= 5) { /* Packet number */
|
||||
bcopy2(ctlptr,&stmp);
|
||||
pkt->seq = ntohs(stmp);
|
||||
}
|
||||
else { /* No packet number specified, so this is the only one */
|
||||
pkt->seq = 1;
|
||||
creq->rcvd_tot = 1;
|
||||
}
|
||||
ctlptr += 2;
|
||||
if(hdr_len >= 7) { /* Total number of packets */
|
||||
bcopy2(ctlptr,&stmp); /* 0 means don't know */
|
||||
if(stmp) creq->rcvd_tot = ntohs(stmp);
|
||||
}
|
||||
ctlptr += 2;
|
||||
if(hdr_len >= 9) { /* Receievd through */
|
||||
bcopy2(ctlptr,&stmp); /* 0 means don't know */
|
||||
if(stmp) {
|
||||
creq->prcvd_thru = ntohs(stmp);
|
||||
}
|
||||
}
|
||||
ctlptr += 2;
|
||||
if(hdr_len >= 11) { /* Backoff */
|
||||
/* Not supported by server */
|
||||
}
|
||||
ctlptr += 2;
|
||||
|
||||
flags1 = flags2 = 0;
|
||||
if(hdr_len >= 12) flags1 = *ctlptr++; /* Flags */
|
||||
if(hdr_len >= 13) flags2 = *ctlptr++; /* Flags */
|
||||
|
||||
if(flags2 == 1) { /* Cancel request */
|
||||
EXTERN_MUTEXED_LOCK(ardp_pendingQ);
|
||||
treq = ardp_pendingQ;
|
||||
while(treq) {
|
||||
if((treq->cid == creq->cid) &&
|
||||
(treq->peer_port == creq->peer_port) &&
|
||||
(treq->peer_addr.s_addr == creq->peer_addr.s_addr)){
|
||||
plog(L_QUEUE_INFO,treq,
|
||||
"Request canceled by client - dequeued",0);
|
||||
pQlen--;if(treq->priority > 0) pQNlen--;
|
||||
EXTRACT_ITEM(treq,ardp_pendingQ);
|
||||
ardp_rqfree(treq);
|
||||
ardp_rqfree(creq); ardp_ptfree(pkt);
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
|
||||
goto check_for_more;
|
||||
}
|
||||
treq = treq->next;
|
||||
}
|
||||
plog(L_QUEUE_INFO,creq,
|
||||
"Request canceled by client - not on queue",0);
|
||||
ardp_rqfree(creq); ardp_ptfree(pkt);
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
|
||||
goto check_for_more;
|
||||
}
|
||||
|
||||
/* If the client specifies option flags and doesn't specify control
|
||||
info to match them, we probably should log this; right now we just
|
||||
silently ignore it. */
|
||||
if (ctlptr < pkt->start + hdr_len) /* if still control info */ {
|
||||
/* Priority specified. */
|
||||
if(flags1 & 0x2) {
|
||||
bcopy2(ctlptr,&stmp);
|
||||
creq->priority = ntohs(stmp);
|
||||
ctlptr += 2;
|
||||
}
|
||||
}
|
||||
if (ctlptr < pkt->start + hdr_len) /* if still control info */ {
|
||||
/* Higher-level protocol ID follows. */
|
||||
/* N.B.: used to be a bug here where this was 0x1; this is in
|
||||
variance with the ARDP spec and I've corrected the
|
||||
implementation to conform to the spec. */
|
||||
if(flags1 & 0x4) {
|
||||
bcopy2(ctlptr,&stmp);
|
||||
pid = ntohs(stmp);
|
||||
ctlptr += 2;
|
||||
}
|
||||
}
|
||||
if (ctlptr < pkt->start + hdr_len) /* if still control info */ {
|
||||
/* Window size follows (2 octets of information). */
|
||||
if(flags1 & 0x8) {
|
||||
bcopy2(ctlptr,&stmp);
|
||||
creq->pwindow_sz = ntohs(stmp);
|
||||
ctlptr += 2;
|
||||
if (creq->pwindow_sz == 0) {
|
||||
creq->pwindow_sz = ARDP_DEFAULT_WINDOW_SZ;
|
||||
plog(L_NET_INFO, creq,
|
||||
"Client explicity reset window size to server \
|
||||
default (%d)",
|
||||
ARDP_DEFAULT_WINDOW_SZ);
|
||||
} else {
|
||||
if (creq->pwindow_sz > ARDP_MAX_WINDOW_SZ) {
|
||||
plog(L_NET_INFO, creq, "Client set window size \
|
||||
to %d; server will limit it to %d", creq->pwindow_sz, ARDP_MAX_WINDOW_SZ);
|
||||
creq->pwindow_sz = ARDP_MAX_WINDOW_SZ;
|
||||
} else {
|
||||
plog(L_NET_INFO, creq,
|
||||
"Client set window size to %d", creq->pwindow_sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((creq->priority < 0) && (creq->priority != -42)) {
|
||||
plog(L_NET_RDPERR, creq, "Priority %d requested - ignored", creq->priority, 0);
|
||||
creq->priority = 0;
|
||||
}
|
||||
|
||||
if(pkt->seq == 1) creq->rcvd_thru = max(creq->rcvd_thru, 1);
|
||||
|
||||
pkt->length -= hdr_len;
|
||||
pkt->start += hdr_len;
|
||||
pkt->text = pkt->start;
|
||||
}
|
||||
else {
|
||||
/* When we are no longer getting any of these old format */
|
||||
/* requests, we know that everyone is using the new */
|
||||
/* reliable datagram protocol, and that they also */
|
||||
/* have the singleton response bug fixed. We can then */
|
||||
/* get rid of the special casing for singleton responses */
|
||||
|
||||
/* Lower the priority to encourage people to upgrade */
|
||||
creq->priority = 1;
|
||||
creq->peer_ardp_version = -1;
|
||||
#ifdef LOGOLDFORMAT
|
||||
plog(L_DIR_PWARN,creq,"Old RDP format",0);
|
||||
#endif LOGOLDFORMAT
|
||||
pkt->seq = 1;
|
||||
creq->rcvd_tot = 1;
|
||||
creq->rcvd_thru = 1;
|
||||
}
|
||||
|
||||
/* Check to see if it is already on done, partial, or pending */
|
||||
|
||||
/* Done queue */
|
||||
EXTERN_MUTEXED_LOCK(ardp_doneQ);
|
||||
treq = ardp_doneQ;
|
||||
CHECK_HEAD(treq);
|
||||
while(treq) {
|
||||
if((treq->cid != 0) && (treq->cid == creq->cid) &&
|
||||
(bcmp((char *) &(treq->peer),
|
||||
(char *) &from,sizeof(from))==0)){
|
||||
/* Request is already on doneQ */
|
||||
if(creq->prcvd_thru > treq->prcvd_thru) {
|
||||
treq->prcvd_thru = creq->prcvd_thru;
|
||||
rr_time = 0; /* made progress, don't supress retransmission */
|
||||
}
|
||||
nreq = treq;
|
||||
|
||||
/* Retransmit reply if not completely received */
|
||||
/* and if we didn't retransmit it this second */
|
||||
if((nreq->prcvd_thru != nreq->trns_tot) &&
|
||||
((rr_time != now) || (nreq != ardp_doneQ))) {
|
||||
PTEXT tpkt; /* Temporary pkt pointer */
|
||||
|
||||
plog(L_QUEUE_INFO,nreq,"Retransmitting reply (%d of %d ack)",
|
||||
nreq->prcvd_thru, nreq->trns_tot, 0);
|
||||
/* Transmit all outstanding packets */
|
||||
for (tpkt = nreq->trns; tpkt; tpkt = tpkt->next) {
|
||||
if((tpkt->seq <= (nreq->prcvd_thru + nreq->pwindow_sz)) &&
|
||||
((tpkt->seq == 0) || (tpkt->seq > nreq->prcvd_thru))) {
|
||||
/* (A) Request an ack at the end of a window
|
||||
(B) Request an ack in the last packet if the
|
||||
service has rescinded a wait request, but we
|
||||
aren't sure that the client knows this.
|
||||
*/
|
||||
ardp_header_ack_rwait(tpkt, nreq,
|
||||
/* do set ACK BIT: */
|
||||
(/*A*/ tpkt->seq ==
|
||||
(nreq->prcvd_thru
|
||||
+ nreq->pwindow_sz))
|
||||
|| /*B*/
|
||||
((tpkt->seq == nreq->trns_tot)
|
||||
/* last pkt */
|
||||
&& (nreq->svc_rwait_seq >
|
||||
nreq->prcvd_thru)),
|
||||
/* Might an RWAIT be needed? */
|
||||
(nreq->svc_rwait_seq >
|
||||
nreq->prcvd_thru));
|
||||
ardp_snd_pkt(tpkt,nreq);
|
||||
}
|
||||
}
|
||||
rr_time = now; /* Remember time of retransmission */
|
||||
}
|
||||
/* Move matched request to front of queue */
|
||||
/* nreq is definitely in ardp_doneQ right now. */
|
||||
/* This replaces much icky special-case code that used to be here
|
||||
-- swa, Feb 9, 1994 */
|
||||
EXTRACT_ITEM(nreq, ardp_doneQ);
|
||||
PREPEND_ITEM(nreq, ardp_doneQ);
|
||||
ardp_rqfree(creq); ardp_ptfree(pkt);
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_doneQ);
|
||||
goto check_for_more;
|
||||
}
|
||||
/* While we're checking the done queue also see if any */
|
||||
/* replies require follow up requests for acknowledgments */
|
||||
/* This is currently used when the server has requested that the client
|
||||
wait for a long time, and then has rescinded that wait request
|
||||
(because the message is done). Such a rescinding of the wait
|
||||
request should be received by the client, and the server is
|
||||
expecting an ACK. */
|
||||
/* You can add additional tests here if there are other circumstances
|
||||
under which you want the server to expect the client to send an
|
||||
acknowledgement. */
|
||||
if(check_for_ack && (treq->svc_rwait_seq > treq->prcvd_thru) &&
|
||||
(treq->retries_rem > 0) && (now >= treq->wait_till.tv_sec)) {
|
||||
#define ARDP_LOG_SPONTANEOUS_RETRANSMISSIONS
|
||||
#ifdef ARDP_LOG_SPONTANEOUS_RETRANSMISSIONS
|
||||
plog(L_QUEUE_INFO,treq,"Requested ack not received - pinging client (%d of %d/%d ack)",
|
||||
treq->prcvd_thru, treq->svc_rwait_seq, treq->trns_tot, 0);
|
||||
#endif /* ARDP_LOG_SPONTANEOUS_RETRANSMISSIONS */
|
||||
/* Resend the final packet only - to wake the client */
|
||||
if(treq->trns) ardp_snd_pkt(treq->trns->previous,treq);
|
||||
treq->timeout_adj.tv_sec = ARDP_BACKOFF(treq->timeout_adj.tv_sec);
|
||||
treq->wait_till.tv_sec = now + treq->timeout_adj.tv_sec;
|
||||
treq->retries_rem--;
|
||||
}
|
||||
CHECK_NEXT(treq);
|
||||
treq = treq->next;
|
||||
} /*while*/
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_doneQ);
|
||||
check_for_ack = 0; /* Only check once per call to ardp_accept */
|
||||
|
||||
/* If unsequenced control packet free it and check for more */
|
||||
if(pkt->seq == 0) {
|
||||
ardp_rqfree(creq); ardp_ptfree(pkt);
|
||||
goto check_for_more;
|
||||
}
|
||||
|
||||
/* Check if incomplete and match up with other incomplete requests */
|
||||
if(creq->rcvd_tot != 1) { /* Look for rest of request */
|
||||
treq = ardp_partialQ;
|
||||
while(treq) {
|
||||
if((treq->cid != 0) && (treq->cid == creq->cid) &&
|
||||
(bcmp((char *) &(treq->peer),
|
||||
(char *) &from,sizeof(from))==0)) {
|
||||
/* We found the rest of the request */
|
||||
/* coallesce and log and check_for more */
|
||||
PTEXT tpkt; /* Temporary pkt pointer */
|
||||
|
||||
ardp_update_cfields(treq,creq);
|
||||
if(creq->rcvd_tot) treq->rcvd_tot = creq->rcvd_tot;
|
||||
tpkt = treq->rcvd;
|
||||
while(tpkt) {
|
||||
if(tpkt->seq == treq->rcvd_thru+1) treq->rcvd_thru++;
|
||||
if(tpkt->seq == pkt->seq) {
|
||||
/* Duplicate - discard */
|
||||
plog(L_NET_INFO,creq,"Multi-packet duplicate received (pkt %d of %d)",
|
||||
pkt->seq, creq->rcvd_tot, 0);
|
||||
if(areq != treq) {
|
||||
if(areq) {
|
||||
ardp_acknowledge(areq);
|
||||
}
|
||||
areq = treq;
|
||||
}
|
||||
ardp_rqfree(creq); ardp_ptfree(pkt);
|
||||
goto check_for_more;
|
||||
}
|
||||
if(tpkt->seq > pkt->seq) {
|
||||
/* Insert new packet in rcvd */
|
||||
pkt->next = tpkt;
|
||||
pkt->previous = tpkt->previous;
|
||||
if(treq->rcvd == tpkt) treq->rcvd = pkt;
|
||||
else tpkt->previous->next = pkt;
|
||||
tpkt->previous = pkt;
|
||||
if(pkt->seq == treq->rcvd_thru+1) treq->rcvd_thru++;
|
||||
while(tpkt && (tpkt->seq == treq->rcvd_thru+1)) {
|
||||
treq->rcvd_thru++;
|
||||
tpkt = tpkt->next;
|
||||
}
|
||||
pkt = NOPKT;
|
||||
break;
|
||||
}
|
||||
tpkt = tpkt->next;
|
||||
}
|
||||
if(pkt) { /* Append at end of rcvd */
|
||||
APPEND_ITEM(pkt,treq->rcvd);
|
||||
if(pkt->seq == treq->rcvd_thru+1) treq->rcvd_thru++;
|
||||
pkt = NOPKT;
|
||||
}
|
||||
if(treq->rcvd_tot && (treq->rcvd_thru == treq->rcvd_tot)) {
|
||||
if(areq == treq) areq = NOREQ;
|
||||
creq = treq; EXTRACT_ITEM(creq, ardp_partialQ); --ptQlen;
|
||||
plog(L_NET_INFO,creq,"Multi-packet request complete",0);
|
||||
goto req_complete;
|
||||
}
|
||||
else {
|
||||
if(areq != treq) {
|
||||
if(areq) {
|
||||
ardp_acknowledge(areq);
|
||||
}
|
||||
areq = treq;
|
||||
}
|
||||
plog(L_NET_INFO, creq,
|
||||
"Multi-packet request continued (rcvd %d of %d)",
|
||||
creq->rcvd_thru, creq->rcvd_tot, 0);
|
||||
goto check_for_more;
|
||||
}
|
||||
}
|
||||
treq = treq->next;
|
||||
}
|
||||
/* This is the first packet we received in the request */
|
||||
/* log it and queue it and check for more */
|
||||
plog(L_NET_INFO,creq,"Multi-packet request received (pkt %d of %d)",
|
||||
pkt->seq, creq->rcvd_tot, 0);
|
||||
APPEND_ITEM(pkt,creq->rcvd);
|
||||
APPEND_ITEM(creq,ardp_partialQ); /* Add at end of incomp queue */
|
||||
if(++ptQlen > ptQmaxlen) {
|
||||
treq = ardp_partialQ; /* Remove from head of queue */
|
||||
EXTRACT_ITEM(ardp_partialQ,ardp_partialQ); ptQlen--;
|
||||
plog(L_NET_ERR, treq,
|
||||
"Too many incomplete requests - dropped (rthru %d of %d)",
|
||||
treq->rcvd_thru, treq->rcvd_tot, 0);
|
||||
ardp_rqfree(treq);
|
||||
}
|
||||
goto check_for_more;
|
||||
}
|
||||
|
||||
plog(L_NET_INFO, creq, "Received packet", 0);
|
||||
|
||||
req_complete:
|
||||
|
||||
qpos = 0; dpos = 1;
|
||||
|
||||
/* Insert this message at end of pending but make sure the */
|
||||
/* request is not already in pending */
|
||||
nreq = creq; creq = NOREQ;
|
||||
EXTERN_MUTEXED_LOCK(ardp_pendingQ);
|
||||
treq = ardp_pendingQ;
|
||||
|
||||
if(pkt) {
|
||||
nreq->rcvd_tot = 1;
|
||||
APPEND_ITEM(pkt,nreq->rcvd);
|
||||
}
|
||||
|
||||
EXTERN_MUTEXED_LOCK(ardp_runQ);
|
||||
for (match_in_runQ = ardp_runQ; match_in_runQ;
|
||||
match_in_runQ = match_in_runQ->next) {
|
||||
if((match_in_runQ->cid == nreq->cid) && (match_in_runQ->cid != 0) &&
|
||||
(bcmp((char *) &(match_in_runQ->peer),
|
||||
(char *) &(nreq->peer),sizeof(nreq->peer))==0)) {
|
||||
/* Request is running right now */
|
||||
ardp_update_cfields(match_in_runQ,nreq);
|
||||
plog(L_QUEUE_INFO,match_in_runQ,"Duplicate discarded (presently executing)",0);
|
||||
/*!! This looks strange - freeing but not removing from ardp_runQ*/
|
||||
ardp_rqfree(nreq);
|
||||
nreq = match_in_runQ;
|
||||
break; /* leave match_in_runQ set to nreq */
|
||||
}
|
||||
}
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_runQ);
|
||||
if (match_in_runQ) {
|
||||
/* do nothing; handled above. */
|
||||
} else if(ardp_pendingQ) {
|
||||
int keep_looking = 1; /* Keep looking for dup. Initially say to
|
||||
keep on looking. */
|
||||
|
||||
while(treq) {
|
||||
if((treq->cid != 0) && (treq->cid == nreq->cid) &&
|
||||
(bcmp((char *) &(treq->peer),
|
||||
(char *) &(nreq->peer),sizeof(treq->peer))==0)){
|
||||
/* Request is already on queue */
|
||||
ardp_update_cfields(treq,nreq);
|
||||
plog(L_QUEUE_INFO,treq,"Duplicate discarded (%d of %d)",dpos,pQlen,0);
|
||||
ardp_rqfree(nreq);
|
||||
nreq = treq;
|
||||
keep_looking = 0; /* We found the duplicate */
|
||||
break;
|
||||
}
|
||||
if((ardp_pri_override && ardp_pri_func && (ardp_pri_func(nreq,treq) < 0)) ||
|
||||
(!ardp_pri_override && ((nreq->priority < treq->priority) ||
|
||||
((treq->priority == nreq->priority) && ardp_pri_func &&
|
||||
(ardp_pri_func(nreq,treq) < 0))))) {
|
||||
if(ardp_pendingQ == treq) {
|
||||
nreq->previous = ardp_pendingQ->previous;
|
||||
nreq->next = ardp_pendingQ;
|
||||
ardp_pendingQ->previous = nreq;
|
||||
ardp_pendingQ = nreq;
|
||||
}
|
||||
else {
|
||||
nreq->next = treq;
|
||||
nreq->previous = treq->previous;
|
||||
nreq->previous->next = nreq;
|
||||
treq->previous = nreq;
|
||||
}
|
||||
pQlen++;
|
||||
if(nreq->priority > 0) pQNlen++;
|
||||
LOG_PACKET(nreq, dpos);
|
||||
qpos = dpos;
|
||||
keep_looking = 1; /* There may still be a duplicate */
|
||||
break;
|
||||
}
|
||||
if(!treq->next) {
|
||||
treq->next = nreq;
|
||||
nreq->previous = treq;
|
||||
ardp_pendingQ->previous = nreq;
|
||||
pQlen++;
|
||||
if(nreq->priority > 0) pQNlen++;
|
||||
LOG_PACKET(nreq,dpos+1);
|
||||
qpos = dpos+1;
|
||||
keep_looking = 0; /* Nothing more to check */
|
||||
break;
|
||||
}
|
||||
treq = treq->next;
|
||||
dpos++;
|
||||
}
|
||||
/* Save queue position to send to client if appropriate */
|
||||
qpos = dpos;
|
||||
/* If not added at end of queue, check behind packet for dup */
|
||||
if(keep_looking) {
|
||||
while(treq) {
|
||||
if((treq->cid == nreq->cid) && (treq->cid != 0) &&
|
||||
(bcmp((char *) &(treq->peer),
|
||||
(char *) &(nreq->peer),
|
||||
sizeof(treq->peer))==0)){
|
||||
/* Found a dup */
|
||||
plog(L_QUEUE_INFO,treq,"Duplicate replaced (removed at %d)", dpos, 0);
|
||||
pQlen--;if(treq->priority > 0) pQNlen--;
|
||||
EXTRACT_ITEM(treq,ardp_pendingQ);
|
||||
ardp_rqfree(treq);
|
||||
break;
|
||||
}
|
||||
treq = treq->next;
|
||||
dpos++;
|
||||
}
|
||||
} /* if keep_looking */
|
||||
}
|
||||
else {
|
||||
nreq->next = NULL;
|
||||
ardp_pendingQ = nreq;
|
||||
ardp_pendingQ->previous = nreq;
|
||||
pQlen++;if(nreq->priority > 0) pQNlen++;
|
||||
LOG_PACKET(nreq, dpos);
|
||||
qpos = dpos;
|
||||
}
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
|
||||
|
||||
/* Fill in queue position and system time */
|
||||
nreq->inf_queue_pos = qpos;
|
||||
/* nreq->inf_sys_time = **compute-system-time-here** */
|
||||
|
||||
#ifdef ARCHIE
|
||||
nreq -> inf_sys_time = arch_get_etime(nreq);
|
||||
#endif
|
||||
|
||||
/* Here we can optionally send a message telling the */
|
||||
/* client to back off. How long should depend on the */
|
||||
/* queue length and the mean service time */
|
||||
/* 15 min for now - the archie server is overloaded */
|
||||
#ifdef ARCHIE
|
||||
/* This is an old version of the Prospero clients that only archie servers
|
||||
will need to be able to talk to, so don't bother doing this test
|
||||
for anything but an archie server. */
|
||||
if((nreq->peer_ardp_version >= 0) && (sindex(nreq->rcvd->start,"VERSION 1")))
|
||||
nreq->peer_ardp_version = -2;
|
||||
/* Archie servers should request a longer wait. Other heavily used
|
||||
databases may want to have this command defined too. */
|
||||
ardp_rwait(nreq,900,nreq->inf_queue_pos,nreq->inf_sys_time);
|
||||
#endif
|
||||
|
||||
goto check_for_more;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static
|
||||
void
|
||||
ardp_update_cfields(RREQ existing,RREQ newvalues)
|
||||
{
|
||||
if(newvalues->prcvd_thru > existing->prcvd_thru)
|
||||
existing->prcvd_thru = newvalues->prcvd_thru;
|
||||
}
|
||||
|
||||
/* Rewrite the header of TPKT to conform to the status in nreq. The only
|
||||
fields
|
||||
we need to set are possibly the ACK bit in octet 11 and possibly the rwait
|
||||
field in octets 9 & 10. We always send the received-through field for the
|
||||
sake of simplicity of implementation. */
|
||||
static void ardp_header_ack_rwait(PTEXT tpkt, RREQ nreq, int is_ack_needed,
|
||||
int is_rwait_needed)
|
||||
{
|
||||
int new_hlength; /* new header length. */
|
||||
int old_hlength; /* old header length */
|
||||
unsigned short us_tmp; /* tmp for values. */
|
||||
old_hlength = tpkt->text - tpkt->start;
|
||||
/* If rwait needed, leave room for it. */
|
||||
new_hlength = 9; /* Include room for received-through count */
|
||||
if (is_rwait_needed)
|
||||
new_hlength = 11;
|
||||
if (is_ack_needed) new_hlength = 12;
|
||||
|
||||
/* Allocate space for new header. */
|
||||
tpkt->start = tpkt->text - new_hlength;
|
||||
tpkt->length += new_hlength - old_hlength;
|
||||
/* Set the header length and version # (zeroth octet) */
|
||||
/* Version # is zero in this version of the ARDP library; last 6 bytes
|
||||
of octet are header length. */
|
||||
*(tpkt->start) = (char) new_hlength;
|
||||
/* Set octets 1 through 8 of header */
|
||||
/* Connection ID (octets 1 & 2) */
|
||||
bcopy2(&(nreq->cid),tpkt->start+1);
|
||||
/* Sequence number (octets 3 & 4) */
|
||||
us_tmp = htons(tpkt->seq);
|
||||
bcopy2(&us_tmp,tpkt->start+3);
|
||||
/* Total packet count (octets 5 & 6) */
|
||||
us_tmp = htons(nreq->trns_tot);
|
||||
bcopy2(&us_tmp,tpkt->start+5);
|
||||
/* Received through (octets 7 & 8) */
|
||||
us_tmp = htons(nreq->rcvd_thru);
|
||||
bcopy2(&us_tmp,tpkt->start+7);
|
||||
/* Now set any options. */
|
||||
/* expected time 'till response */
|
||||
if (new_hlength > 9) {
|
||||
us_tmp = htons(nreq->svc_rwait);
|
||||
bcopy2(&us_tmp, tpkt->start+9);
|
||||
}
|
||||
if (new_hlength > 11) {
|
||||
tpkt->start[11] =
|
||||
is_ack_needed ? 0x80 /* ACK BIT */ : 0x00 /* Don't ack */;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ardp_accept() {
|
||||
return ardp_accept_and_wait(0,0);
|
||||
}
|
||||
|
||||
|
||||
163
prospero/lib/ardp/ardp_add2req.c
Normal file
163
prospero/lib/ardp/ardp_add2req.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>.
|
||||
*
|
||||
* Written by bcn 2/93 to add text to a request
|
||||
*/
|
||||
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ardp.h>
|
||||
#include <sys/types.h> /* so pmachine.h won't redefine it. */
|
||||
#include <pmachine.h> /* for bcopy() */
|
||||
|
||||
#define max(x,y) (x > y ? x : y)
|
||||
#define min(x,y) (x < y ? x : y)
|
||||
|
||||
/*
|
||||
* ardp_add2req - add text to request structure
|
||||
*
|
||||
* ardp_add2req takes a request structure, flags, a buffer containing text
|
||||
* to be added to the output queue of the request, and the length of the
|
||||
* buffer.
|
||||
*
|
||||
* If the specified length of the buffer is 0, ardp_add2req calculates
|
||||
* it using strlen (if the lenght is zero, the assumption is that the
|
||||
* buffer is null terminated).
|
||||
* If the buffer is a NULL pointer and the specified length is 0, then
|
||||
* it treated as a true zero-length buffer.
|
||||
*
|
||||
* If the flag ARDP_A2R_NOSPLITB is set, the request will not be split
|
||||
* across packets. If ARDP_A2R_NOSPLITL, the lines may not be split
|
||||
* across packets, and text added to a request without a trailing new
|
||||
* line will be deferred until a newline is added or ardp_add2req is called
|
||||
* without ARDP_A2R_NOSPLITL set. If ARDP_A2R_COMPLETE is specified, it
|
||||
* indicates this is the final text to be added to the request structure,
|
||||
* and no text will remain buffered. If there is still deferred text,
|
||||
* a newline will be added. If the flag ARDP_A2R_TAGLENGTH is specified,
|
||||
* the data written to the request will be tagged with a four octet length
|
||||
* field in network byte order.
|
||||
*
|
||||
* NOTE: If you use this function to add text to a request, then you
|
||||
* should use only this function. If this function is called on
|
||||
* a request previously constructed by hand, unexpected failures
|
||||
* may result.
|
||||
*
|
||||
* BUGS: ARDP_A2R_NOSPLITL is not currently supported unless
|
||||
* ARDP_A2R_NOSPLITB is also set.
|
||||
* ARDP_A2R_TAGLENGTH is not presently supported.
|
||||
* An ardp_flush_partial_line() is needed to handle some manifestations
|
||||
* of the ARDP_TOOLONG error. Alternatively, we might specify an
|
||||
* additional flag to ardp_add2req() to specify the behavior on an
|
||||
* ARDP_TOOLONG error.
|
||||
*/
|
||||
int
|
||||
ardp_add2req(RREQ req, /* Request to get the text */
|
||||
int flags, /* Options to add2req */
|
||||
char *buf, /* New text for request */
|
||||
int buflen) /* Length of the new text */
|
||||
{
|
||||
int remaining; /* Space remaining in pkt */
|
||||
int written; /* # Octets written */
|
||||
char *newline; /* last nl in string */
|
||||
int deflen; /* Length of deferred text */
|
||||
int extra; /* Extra space needed */
|
||||
long taglen; /* Length in net byte ord */
|
||||
PTEXT pkt = NOPKT; /* Current packet */
|
||||
PTEXT ppkt; /* Previous packet */
|
||||
|
||||
/* Note: New text gets written after pkt->ioptr. If */
|
||||
/* there is text waiting for a newline, then ->ioptr */
|
||||
/* may be beyond ->start+->length, which will be the */
|
||||
/* text up to the final newline seen so far */
|
||||
|
||||
/* XXX For now if NOSPLITL, must also specify NOSPLITB */
|
||||
if((flags & ARDP_A2R_NOSPLITL) && !(flags & ARDP_A2R_NOSPLITB))
|
||||
return(ARDP_FAILURE);
|
||||
|
||||
if(buf && !buflen) buflen = strlen(buf);
|
||||
if(!buf) buf = "";
|
||||
|
||||
keep_writing:
|
||||
|
||||
/* Find ot allocate last packet in ->outpkt */
|
||||
if(req->outpkt) pkt = req->outpkt->previous;
|
||||
if(!pkt) {
|
||||
if((pkt = ardp_ptalloc()) == NOPKT) return(ARDP_FAILURE);
|
||||
APPEND_ITEM(pkt,req->outpkt);
|
||||
}
|
||||
|
||||
deflen = pkt->ioptr - (pkt->start + pkt->length);
|
||||
|
||||
extra = deflen;
|
||||
if(flags & ARDP_A2R_NOSPLITL) extra += 1;
|
||||
if(flags & ARDP_A2R_TAGLENGTH) extra += 4;
|
||||
|
||||
if((flags & ARDP_A2R_NOSPLITB) && (buflen + extra > ARDP_PTXT_LEN))
|
||||
return(ARDP_TOOLONG);
|
||||
|
||||
remaining = ARDP_PTXT_LEN - (pkt->ioptr - pkt->start);
|
||||
|
||||
if(((flags & ARDP_A2R_NOSPLITB) && (remaining < buflen + 1)) ||
|
||||
((flags & ARDP_A2R_TAGLENGTH) && (remaining < 4)) ||
|
||||
(remaining == 0)) {
|
||||
ppkt = pkt;
|
||||
if((pkt = ardp_ptalloc()) == NOPKT) return(ARDP_FAILURE);
|
||||
if(ppkt->start + ppkt->length != ppkt->ioptr) {
|
||||
/* Must move deferred text to new packet */
|
||||
bcopy(ppkt->start+ppkt->length, pkt->start, deflen);
|
||||
ppkt->ioptr = ppkt->start + ppkt->length;
|
||||
*(ppkt->ioptr) = '\0';
|
||||
pkt->ioptr += deflen;
|
||||
}
|
||||
APPEND_ITEM(pkt,req->outpkt);
|
||||
remaining = ARDP_PTXT_LEN;
|
||||
}
|
||||
|
||||
if(flags & ARDP_A2R_TAGLENGTH) {
|
||||
taglen = htonl(buflen);
|
||||
bcopy4(&buflen,pkt->ioptr);
|
||||
pkt->ioptr += 4;
|
||||
remaining -= 4;
|
||||
}
|
||||
|
||||
written = min(remaining,buflen);
|
||||
bcopy(buf,pkt->ioptr,written);
|
||||
pkt->ioptr += written;
|
||||
if(flags & ARDP_A2R_NOSPLITL) {
|
||||
*(pkt->ioptr) = '\0'; /* To catch runaway strrchar */
|
||||
/* Find last newline */
|
||||
newline = strrchr(pkt->start + pkt->length,'\n');
|
||||
if(newline) pkt->length = newline + 1 - pkt->start;
|
||||
}
|
||||
else pkt->length = pkt->ioptr - pkt->start;
|
||||
/* Always need to stick on trailing NULL for sake of ardp_respond(),
|
||||
which expects it. */
|
||||
*pkt->ioptr = '\0';
|
||||
|
||||
/* In this case, ARDP_A@R_NOSPLITB was not specified, split it */
|
||||
if(written != buflen) {
|
||||
buf += written;
|
||||
buflen -= written;
|
||||
goto keep_writing;
|
||||
}
|
||||
|
||||
if(flags & ARDP_A2R_COMPLETE) {
|
||||
deflen = pkt->ioptr - (pkt->start + pkt->length);
|
||||
/* If deferred, write a newline */
|
||||
if(deflen) {
|
||||
*(pkt->ioptr++) = '\n';
|
||||
pkt->length = pkt->ioptr - pkt->start;
|
||||
/* Always need to stick on trailing NULL for sake of
|
||||
ardp_respond(), which expects it. */
|
||||
*pkt->ioptr = '\0';
|
||||
}
|
||||
}
|
||||
return ARDP_SUCCESS;
|
||||
}
|
||||
|
||||
68
prospero/lib/ardp/ardp_breply.c
Normal file
68
prospero/lib/ardp/ardp_breply.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*
|
||||
* Written by bcn 2/93 to send reply to request
|
||||
* Hacked by swa 11/94 to send length-coded reply to request.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ardp.h>
|
||||
|
||||
/*
|
||||
* ardp_breply - send a reply to a request that might contain binary data
|
||||
*
|
||||
* ardp_breply reply takes request to which a reply is to be sent
|
||||
* a flags field, and a message to be sent to the client in response
|
||||
* to the request, and a length count for the message. ardp_breply then adds
|
||||
* the response to the output queue for the request.
|
||||
*
|
||||
* A length count of 0 indicates that the buffer is null-terminated.
|
||||
* (implementation note: by passing the 0 down to ardp_add2req, we
|
||||
* allow there to be only one pass through the buffer instead of 2.)
|
||||
*
|
||||
* If space remains in the packet, the response is buffered pending
|
||||
* subsequent replies, unless the ARDP_REPL_COMPLETE has been specified,
|
||||
* in which case all data is sent. If the size of the buffered response
|
||||
* approaches the maximum packet size, the buffered data is sent, and
|
||||
* and a new packet is started to hold any remaining data from the current
|
||||
* message.
|
||||
*
|
||||
* The lower level function (ardp_respond) assigns packet numbers and
|
||||
* tags outgoing packets if necessary or a multi packet response.
|
||||
*/
|
||||
|
||||
int
|
||||
ardp_breply(RREQ req, /* Request to which this is a response */
|
||||
int flags, /* Whether this is the final message */
|
||||
char *message, /* The data to be sent. */
|
||||
int len) /* message length; 0 means null-terminated */
|
||||
{
|
||||
int tmp;
|
||||
|
||||
tmp = ardp_add2req(req,flags,message,len);
|
||||
if (tmp) return tmp;
|
||||
if(flags&ARDP_R_COMPLETE) return(ardp_respond(req,ARDP_R_COMPLETE));
|
||||
|
||||
/* Check to see if any packets are done */
|
||||
#if 1
|
||||
if(req->outpkt && req->outpkt->next) {
|
||||
#else
|
||||
/* This always yields the same results as the previous line but appears
|
||||
clunkier to me. */
|
||||
if(req->outpkt && (req->outpkt->previous != req->outpkt)) {
|
||||
#endif
|
||||
PTEXT tpkt; /* Temp to hold active packet */
|
||||
/* Hold out final packet */
|
||||
tpkt = req->outpkt->previous;
|
||||
EXTRACT_ITEM(tpkt,req->outpkt);
|
||||
tmp = ardp_respond(req,ARDP_R_INCOMPLETE);
|
||||
APPEND_ITEM(tpkt,req->outpkt);
|
||||
if (tmp) return tmp;
|
||||
}
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
34
prospero/lib/ardp/ardp_error.c
Normal file
34
prospero/lib/ardp/ardp_error.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*
|
||||
* Written by swa 11/93 to handle error reporting consistently in libardp
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <ardp.h>
|
||||
#include <perrno.h> /* For perrno */
|
||||
|
||||
/* See lib/ardp/usc_lic_str.c */
|
||||
extern char *usc_license_string;
|
||||
/* This is used in Prospero in lib/pfs/perrmesg.c. Change it there too if you
|
||||
change it here. */
|
||||
char *ardp___please_do_not_optimize_me_out_of_existence;
|
||||
|
||||
/* perrno is declared in ardp_perrno.c in case some older applications
|
||||
have explicitly declared their own perrno variable (a practice we now
|
||||
discourage). */
|
||||
|
||||
/* This function definition is shadowed in lib/pfs/perrmesg.c. Change it there
|
||||
too if you change it here. */
|
||||
|
||||
void
|
||||
p_clear_errors(void)
|
||||
{
|
||||
ardp___please_do_not_optimize_me_out_of_existence = usc_license_string;
|
||||
perrno = 0;
|
||||
}
|
||||
|
||||
88
prospero/lib/ardp/ardp_get_nxt.c
Normal file
88
prospero/lib/ardp/ardp_get_nxt.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>
|
||||
*
|
||||
* Written by bcn 1991 as get_next_request in rdgram.c (Prospero)
|
||||
* Modified by bcn 1/93 modularized and incorporated into new ardp library
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef AIX
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#include <ardp.h>
|
||||
#include <pmachine.h>
|
||||
|
||||
extern RREQ ardp_pendingQ;
|
||||
EXTERN_MUTEXED_DECL(RREQ,ardp_runQ);
|
||||
extern int pQNlen;
|
||||
extern int pQlen;
|
||||
extern int ardp_srvport;
|
||||
extern int ardp_prvport;
|
||||
|
||||
#define max(x,y) (x > y ? x : y)
|
||||
|
||||
/*
|
||||
* ardp_get_nxt - return next request for server
|
||||
*
|
||||
* ardp_get_nxt returns the next request to be processed by the server.
|
||||
* If no requests are pending, ardp_get_nxt waits until a request
|
||||
* arrives, then returns it.
|
||||
*/
|
||||
/* Called outside multithraded stuff; doesn't need to be mutexed. */
|
||||
RREQ
|
||||
ardp_get_nxt(void)
|
||||
{
|
||||
RREQ nextreq;
|
||||
fd_set readfds;
|
||||
int tmp;
|
||||
|
||||
tryagain:
|
||||
if (nextreq = ardp_get_nxt_nonblocking())
|
||||
return nextreq;
|
||||
/* if queue is empty, then wait till somethings comes */
|
||||
/* in, then go back to start */
|
||||
FD_ZERO(&readfds);
|
||||
if(ardp_srvport != -1) FD_SET(ardp_srvport, &readfds);
|
||||
if(ardp_prvport != -1) FD_SET(ardp_prvport, &readfds);
|
||||
tmp = select(max(ardp_srvport,ardp_prvport) + 1, &readfds,
|
||||
(fd_set *)0, (fd_set *)0, NULL);
|
||||
goto tryagain;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Nonblocking version of the above.
|
||||
* Returns NULL if no pending items.
|
||||
*/
|
||||
RREQ
|
||||
ardp_get_nxt_nonblocking(void)
|
||||
{
|
||||
ardp_accept();
|
||||
|
||||
/* return next message in queue */
|
||||
if (ardp_pendingQ) {
|
||||
/* Atomic test; save ourselves the trouble of going through the kernel
|
||||
if nothing in queue */
|
||||
EXTERN_MUTEXED_LOCK(ardp_pendingQ);
|
||||
if(ardp_pendingQ) {
|
||||
RREQ nextreq = ardp_pendingQ;
|
||||
|
||||
EXTRACT_ITEM(nextreq, ardp_pendingQ);
|
||||
pQlen--;if(nextreq->priority > 0) pQNlen--;
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
|
||||
nextreq->svc_start_time.tv_sec = time(NULL);
|
||||
EXTERN_MUTEXED_LOCK(ardp_runQ);
|
||||
APPEND_ITEM(nextreq,ardp_runQ);
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_runQ);
|
||||
return(nextreq);
|
||||
}
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
|
||||
}
|
||||
return NOREQ;
|
||||
}
|
||||
124
prospero/lib/ardp/ardp_headers.c
Normal file
124
prospero/lib/ardp/ardp_headers.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>.
|
||||
*
|
||||
* Written by bcn 1/93 For use in adrp_send
|
||||
*/
|
||||
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ardp.h>
|
||||
#include <pmachine.h> /* for bcopy() */
|
||||
|
||||
extern int ardp_priority; /* Override for 0 priority */
|
||||
extern int pfs_debug;
|
||||
|
||||
/*
|
||||
* ardp_headers - Add headers to packets to be sent to server
|
||||
*
|
||||
* ardp_headers takes pointer to a request structure and adds headers to
|
||||
* all the packets in the trns list. The fields for the headers are
|
||||
* taken from other fields in the request structure. If the priority is
|
||||
* zero, it is taken from the global vairable ardp_priority.
|
||||
*
|
||||
* If ardp_headers is called more than once, subsequent calls will
|
||||
* update the headers to conform to changes in the request fields.
|
||||
*/
|
||||
int
|
||||
ardp_headers(RREQ req)
|
||||
{
|
||||
PTEXT ptmp; /* Temporary packet pointer */
|
||||
|
||||
for(ptmp = req->trns; ptmp; ptmp = ptmp->next) {
|
||||
int old_hlength; /* Old header length */
|
||||
int new_hlength; /* New header length, whatever it may
|
||||
be. */
|
||||
unsigned short ftmp; /* Temporary for values of fields */
|
||||
/* Boolean: do we stamp this packet with the window size? */
|
||||
/* We will add an explicity window-size stamp to the first sent, if
|
||||
an explicit window size was set. This packet is the one stamped
|
||||
with sequence number 1. Thus we know that the window size message
|
||||
won't be lost. */
|
||||
int stamp_window_size = (req->flags & ARDP_FLAG_SEND_MY_WINDOW_SIZE)
|
||||
&& (ptmp->seq == 1);
|
||||
int stamp_priority = (req->priority || ardp_priority)
|
||||
&& (ptmp->seq == 1);
|
||||
|
||||
old_hlength = ptmp->text - ptmp->start;
|
||||
|
||||
/* XXX Should do further tests to make sure all packets present */
|
||||
if(ptmp->seq == 0) {
|
||||
if (pfs_debug >= 1)
|
||||
fprintf(stderr, "ardp: sequence number not set in packet\n");
|
||||
fflush(stderr);
|
||||
return(ARDP_BAD_REQ);
|
||||
}
|
||||
|
||||
/* If priority stamp or explicit client window size, need octets 11 and
|
||||
12 to be present. */
|
||||
if (stamp_priority || stamp_window_size) {
|
||||
new_hlength = 13; /* room for octets through 12 */
|
||||
if(req->priority || ardp_priority)
|
||||
new_hlength += 2; /* 2 octets for priority argument. */
|
||||
if (stamp_window_size)
|
||||
new_hlength += 2; /* 2 octets for window size */
|
||||
} else {
|
||||
new_hlength = 9; /* room for octets through 8 (received-through)
|
||||
*/
|
||||
}
|
||||
/* New header length now set. */
|
||||
|
||||
/* Allocate space for the new header */
|
||||
ptmp->start = ptmp->text - new_hlength;
|
||||
ptmp->length += new_hlength - old_hlength;
|
||||
/* Set the header length and version # (zeroth octet) */
|
||||
/* Version # is zero in this version of the ARDP library; last 6 bytes
|
||||
of octet are header length. */
|
||||
*(ptmp->start) = (char) new_hlength;
|
||||
/* Set octets 1 through 8 of header */
|
||||
/* Connection ID (octets 1 & 2) */
|
||||
bcopy2(&(req->cid),ptmp->start+1);
|
||||
/* Sequence number (octets 3 & 4) */
|
||||
ftmp = htons(ptmp->seq);
|
||||
bcopy2(&ftmp,ptmp->start+3);
|
||||
/* Total packet count (octets 5 & 6) */
|
||||
ftmp = htons(req->trns_tot);
|
||||
bcopy2(&ftmp,ptmp->start+5);
|
||||
/* Received through (octets 7 & 8) */
|
||||
ftmp = htons(req->rcvd_thru);
|
||||
bcopy2(&ftmp,ptmp->start+7);
|
||||
/* Now set any options. */
|
||||
if (new_hlength > 9) {
|
||||
char * optiondata; /* where options go. */
|
||||
/* zero out octets 9 and 10 (expected time 'till response). It is
|
||||
not defined for the client to specify this to the server,so
|
||||
it is always zero. */
|
||||
bzero2(ptmp->start + 9);
|
||||
/* set octet 11 (flags) initially clear */
|
||||
ptmp->start[11] = 0;
|
||||
/* Here Octet 12 (option) is zero (no special options). */
|
||||
ptmp->start[12] = 0;
|
||||
optiondata = ptmp->start + 13; /* additional octets start here */
|
||||
/* Priority */
|
||||
if(stamp_priority) {
|
||||
*(ptmp->start+11) |= 0x02; /* priority flag */
|
||||
if(req->priority) ftmp = htons(req->priority);
|
||||
else ftmp = htons(ardp_priority);
|
||||
bcopy2(&ftmp, optiondata);
|
||||
optiondata += 2;
|
||||
}
|
||||
if(stamp_window_size) {
|
||||
*(ptmp->start+11) |= 0x08; /* Set window size flag */
|
||||
ftmp = htons(req->window_sz);
|
||||
bcopy2(&ftmp, optiondata);
|
||||
optiondata += 2;
|
||||
}
|
||||
assert(optiondata == ptmp->start + new_hlength);
|
||||
}
|
||||
}
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
17
prospero/lib/ardp/ardp_int_err.c
Normal file
17
prospero/lib/ardp/ardp_int_err.c
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*
|
||||
* Written by swa 12/93 to handle error reporting consistently in libardp
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <ardp.h>
|
||||
|
||||
|
||||
/* Data definition. This may be reset by any client. */
|
||||
int (*internal_error_handler)(const char file[], int line, const char mesg[]) = 0;
|
||||
|
||||
85
prospero/lib/ardp/ardp_mutexes.c
Normal file
85
prospero/lib/ardp/ardp_mutexes.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 1993-1994 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <pfs_threads.h>
|
||||
#include <ardp.h>
|
||||
|
||||
#ifdef PFS_THREADS
|
||||
p_th_mutex p_th_mutexARDP_ACCEPT; /* declaration */
|
||||
p_th_mutex p_th_mutexPTEXT; /* declared in ardp_mutexes.c */
|
||||
p_th_mutex p_th_mutexARDP_RQALLOC; /* declared in ardp_mutexes.c */
|
||||
p_th_mutex p_th_mutexGETHOSTBYNAME; /* declared in pfs_mutexes.c */
|
||||
p_th_mutex p_th_mutexARDP_SELFNUM; /* declared in pfs_mutexes.c */
|
||||
p_th_mutex p_th_mutexDNSCACHE; /* declared in pfs_mutexes.c */
|
||||
p_th_mutex p_th_mutexALLDNSCACHE; /* declared in pfs_mutexes.c */
|
||||
p_th_mutex p_th_mutexFILES; /* declared on p__self_num.c */
|
||||
p_th_mutex p_th_mutexFILELOCK; /* declared in flock.c */
|
||||
#endif
|
||||
|
||||
void
|
||||
ardp_init_mutexes(void)
|
||||
{
|
||||
#ifdef PFS_THREADS
|
||||
EXTERN_MUTEXED_INIT_MUTEX(ardp_doneQ);
|
||||
EXTERN_MUTEXED_INIT_MUTEX(ardp_runQ);
|
||||
|
||||
p_th_mutex_init(p_th_mutexGETHOSTBYNAME);
|
||||
p_th_mutex_init(p_th_mutexARDP_ACCEPT);
|
||||
p_th_mutex_init(p_th_mutexPTEXT);
|
||||
p_th_mutex_init(p_th_mutexARDP_RQALLOC);
|
||||
p_th_mutex_init(p_th_mutexARDP_SELFNUM);
|
||||
p_th_mutex_init(p_th_mutexDNSCACHE);
|
||||
p_th_mutex_init(p_th_mutexALLDNSCACHE);
|
||||
p_th_mutex_init(p_th_mutexFILES);
|
||||
p_th_mutex_init(p_th_mutexFILELOCK);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
void
|
||||
ardp_diagnose_mutexes(void)
|
||||
{
|
||||
#ifdef PFS_THREADS
|
||||
DIAGMUTEX(ardp_doneQ,"ardp_doneQ");
|
||||
DIAGMUTEX(ardp_runQ,"ardp_runQ");
|
||||
DIAGMUTEX(GETHOSTBYNAME,"GETHOSTBYNAME");
|
||||
DIAGMUTEX(ARDP_ACCEPT,"ARDP_ACCEPT");
|
||||
DIAGMUTEX(PTEXT,"PTEXT");
|
||||
DIAGMUTEX(ARDP_RQALLOC,"ARDP_RQALLOC");
|
||||
DIAGMUTEX(ARDP_SELFNUM,"ARDP_SELFNUM");
|
||||
DIAGMUTEX(DNSCACHE,"DNSCACHE");
|
||||
DIAGMUTEX(ALLDNSCACHE,"ALLDNSCACHE");
|
||||
DIAGMUTEX(FILES,"FILES");
|
||||
DIAGMUTEX(FILELOCK,"FILELOCK");
|
||||
#endif
|
||||
}
|
||||
#endif /*NDEBUG*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
19
prospero/lib/ardp/ardp_perrno.c
Normal file
19
prospero/lib/ardp/ardp_perrno.c
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*
|
||||
* Written by swa 11/93 to handle error reporting consistently in libardp
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
#include <ardp.h>
|
||||
#include <pfs_threads.h>
|
||||
|
||||
#ifdef NEVERDEFINED
|
||||
int perrno = 0; /* Declare it. */
|
||||
#endif
|
||||
|
||||
EXTERN_INT_DEF(perrno);
|
||||
|
||||
420
prospero/lib/ardp/ardp_pr_actv.c
Normal file
420
prospero/lib/ardp/ardp_pr_actv.c
Normal file
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1992, 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>
|
||||
*
|
||||
* Written by bcn 1989-92 as part of dirsend.c in the Prospero distribution
|
||||
* Modified by bcn 1/93 moved to ardp library - added asynchrony
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef AIX
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include <ardp.h>
|
||||
#include <perrno.h>
|
||||
#include <pmachine.h> /* for bcopy() */
|
||||
|
||||
extern RREQ ardp_activeQ; /* Info about active requests */
|
||||
extern RREQ ardp_completeQ; /* Info about completed reqs */
|
||||
extern int ardp_port; /* Opened UDP port */
|
||||
extern int pfs_debug; /* Debug level */
|
||||
int ardp_activeQ_len; /* Length of activeQ */
|
||||
|
||||
static struct timeval zerotime = {0, 0}; /* Used by select */
|
||||
|
||||
#define max(x,y) (x > y ? x : y)
|
||||
|
||||
static ardp__pr_ferror(int errcode);
|
||||
|
||||
/*
|
||||
* ardp_process_active - process active requests
|
||||
*
|
||||
* ardp_process_active takes no arguments. It checks to see if any responses
|
||||
* are pending on the UDP port, and if so processes them, adding them
|
||||
* to the request structures on ardp_activeQ. If no requests are pending
|
||||
* ardp_process_active processes and requests requiring retries then
|
||||
* returns.
|
||||
*
|
||||
*/
|
||||
int
|
||||
ardp_process_active()
|
||||
{
|
||||
fd_set readfds; /* Used for select */
|
||||
struct sockaddr_in from; /* Reply received from */
|
||||
int from_sz; /* Size of address structure */
|
||||
int hdr_len; /* Header Length */
|
||||
char *ctlptr; /* Pointer to control field */
|
||||
unsigned short cid = 0; /* Connection ID from rcvd pkt */
|
||||
unsigned char rdflag11; /* First byte of flags (bit vect)*/
|
||||
unsigned char rdflag12; /* Second byte of flags (int) */
|
||||
unsigned char tchar; /* For decoding extra fields */
|
||||
unsigned short stmp; /* Temp short for conversions */
|
||||
unsigned long ltmp; /* Temp long for converions */
|
||||
int tmp; /* Temporaty return value */
|
||||
int nr; /* Number octest received */
|
||||
long now; /* The current time */
|
||||
|
||||
RREQ req = NOREQ; /* To store request info */
|
||||
PTEXT pkt = NOPKT; /* Packet being processed */
|
||||
PTEXT ptmp = NOPKT; /* Packet being processed */
|
||||
|
||||
assert(P_IS_THIS_THREAD_MASTER()); /* something_received not MT-Safe */
|
||||
check_for_pending:
|
||||
|
||||
/* Set list of file descriptors to be checked by select */
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(ardp_port, &readfds);
|
||||
|
||||
/* select - either recv is ready, or not */
|
||||
/* see if timeout or error or wrong descriptor */
|
||||
tmp = select(ardp_port + 1, &readfds, (fd_set *)0, (fd_set *)0, &zerotime);
|
||||
|
||||
/* If tmp is zero, then nothing to process, check for timeouts */
|
||||
if(tmp == 0) {
|
||||
now = time(NULL);
|
||||
req = ardp_activeQ;
|
||||
while(req) {
|
||||
if (req->status == ARDP_STATUS_ACKPEND) {
|
||||
ardp_xmit(req, -1 /* just ACK; send no data packets */);
|
||||
req->status = ARDP_STATUS_ACTIVE;
|
||||
}
|
||||
if((req->wait_till.tv_sec) && (now >= req->wait_till.tv_sec)) {
|
||||
if(req->retries_rem-- > 0) {
|
||||
req->timeout_adj.tv_sec = ARDP_BACKOFF(req->timeout_adj.tv_sec);
|
||||
if (pfs_debug >= 8) {
|
||||
fprintf(stderr,"Connection %d timed out - Setting timeout to %d seconds.\n",
|
||||
ntohs(req->cid), (int) req->timeout_adj.tv_sec);
|
||||
}
|
||||
req->wait_till.tv_sec = now + req->timeout_adj.tv_sec;
|
||||
ardp_xmit(req, req->pwindow_sz);
|
||||
} else {
|
||||
if(pfs_debug >= 8) {
|
||||
fprintf(stderr,"Connection %d timed out - Retry count exceeded.\n",
|
||||
ntohs(req->cid) );
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
req->status = ARDP_TIMEOUT;
|
||||
EXTRACT_ITEM(req,ardp_activeQ);
|
||||
--ardp_activeQ_len;
|
||||
APPEND_ITEM(req,ardp_completeQ);
|
||||
}
|
||||
}
|
||||
req = req->next;
|
||||
}
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
|
||||
/* If negative, then return an error */
|
||||
if((tmp < 0) || !FD_ISSET(ardp_port, &readfds)) {
|
||||
if (pfs_debug)
|
||||
fprintf(stderr, "select failed : returned %d port=%d\n",
|
||||
tmp, ardp_port);
|
||||
|
||||
return(ardp__pr_ferror(ARDP_SELECT_FAILED));
|
||||
}
|
||||
|
||||
/* Process incoming packets */
|
||||
pkt = ardp_ptalloc();
|
||||
pkt->start = pkt->dat;
|
||||
from_sz = sizeof(from);
|
||||
|
||||
if ((nr = recvfrom(ardp_port, pkt->start, sizeof(pkt->dat),
|
||||
0, &from, &from_sz)) < 0) {
|
||||
if (pfs_debug) perror("recvfrom");
|
||||
ardp_ptlfree(pkt);
|
||||
return(ardp__pr_ferror(ARDP_BAD_RECV));
|
||||
}
|
||||
pkt->length = nr;
|
||||
*(pkt->start + pkt->length) = '\0';
|
||||
|
||||
if (pfs_debug >= 6)
|
||||
fprintf(stderr,"Received packet from %s\n", inet_ntoa(from.sin_addr));
|
||||
|
||||
/* If the first byte is greater than 31 we have an old version */
|
||||
/* response - return error */
|
||||
if((hdr_len = (unsigned char) *(pkt->start)) > 31) {
|
||||
ardp_ptfree(pkt);
|
||||
if(ardp_activeQ->next == NOREQ)
|
||||
return(ardp__pr_ferror(ARDP_BAD_VERSION));
|
||||
else goto check_for_pending;
|
||||
}
|
||||
|
||||
/* For the current format, the first two bits are a version number */
|
||||
/* and the next six are the header length (including the first byte). */
|
||||
ctlptr = pkt->start + 1;
|
||||
|
||||
if(hdr_len >= 3) { /* Connection ID */
|
||||
bcopy2(ctlptr,&stmp);
|
||||
if(stmp) cid = stmp;
|
||||
ctlptr += 2;
|
||||
}
|
||||
|
||||
/* Match up response with request */
|
||||
req = ardp_activeQ;
|
||||
while(req) {
|
||||
if(cid == req->cid) break;
|
||||
req = req->next;
|
||||
}
|
||||
if(!req) { /* The request isn't on the active queue */
|
||||
if (pfs_debug>=6)
|
||||
fprintf(stderr,"Packet received for inactive request (cid %d)\n",
|
||||
ntohs(cid));
|
||||
ardp_ptfree(pkt);
|
||||
/* The following can be removed when old servers are gone */
|
||||
if((cid == 0) && (ardp_activeQ->next == NOREQ))
|
||||
return(ardp__pr_ferror(ARDP_BAD_VERSION));
|
||||
goto check_for_pending;
|
||||
}
|
||||
|
||||
if(hdr_len >= 5) { /* Packet number */
|
||||
bcopy2(ctlptr,&stmp);
|
||||
pkt->seq = ntohs(stmp);
|
||||
ctlptr += 2;
|
||||
}
|
||||
else { /* No packet number specified, so this is the only one */
|
||||
pkt->seq = 1;
|
||||
req->rcvd_tot = 1;
|
||||
}
|
||||
if(hdr_len >= 7) { /* Total number of packets */
|
||||
bcopy2(ctlptr,&stmp); /* 0 means don't know */
|
||||
if(stmp) req->rcvd_tot = ntohs(stmp);
|
||||
ctlptr += 2;
|
||||
}
|
||||
if(hdr_len >= 9) { /* Receievd through */
|
||||
bcopy2(ctlptr,&stmp); /* 1 means received request */
|
||||
req->prcvd_thru = max(ntohs(stmp),req->prcvd_thru);
|
||||
ctlptr += 2;
|
||||
}
|
||||
if(hdr_len >= 11) { /* Service requested wait */
|
||||
bcopy2(ctlptr,&stmp);
|
||||
if(stmp || (req->svc_rwait != ntohs(stmp))) {
|
||||
now = time(NULL);
|
||||
/* New or non-zero requested wait value */
|
||||
req->svc_rwait = ntohs(stmp);
|
||||
if(pfs_debug >= 8)
|
||||
fprintf(stderr,"Service asked us to wait %d seconds\n",
|
||||
req->svc_rwait);
|
||||
/* Adjust out timeout */
|
||||
req->timeout_adj.tv_sec = max(req->timeout.tv_sec,req->svc_rwait);
|
||||
req->wait_till.tv_sec = now + req->timeout_adj.tv_sec;
|
||||
/* Reset the retry count */
|
||||
req->retries_rem = req->retries;
|
||||
}
|
||||
ctlptr += 2;
|
||||
}
|
||||
if(hdr_len >= 12) { /* Flags (1st byte) */
|
||||
bcopy1(ctlptr,&rdflag11);
|
||||
if(rdflag11 & 0x80) {
|
||||
if(pfs_debug >= 8)
|
||||
fprintf(stderr,"Ack requested\n");
|
||||
req->status = ARDP_STATUS_ACKPEND;
|
||||
}
|
||||
if(rdflag11 & 0x40) {
|
||||
if(pfs_debug >= 8)
|
||||
fprintf(stderr,"Sequenced control packet\n");
|
||||
pkt->length = -1;
|
||||
}
|
||||
ctlptr += 1;
|
||||
}
|
||||
if(hdr_len >= 13) { /* Flags (2nd byte) */
|
||||
/* Reserved for future use */
|
||||
bcopy1(ctlptr,&rdflag12);
|
||||
ctlptr += 1;
|
||||
if(rdflag12 == 2) {
|
||||
/* Attempt to set back prcvd_thru */
|
||||
bcopy2(pkt->start+7,&stmp);
|
||||
req->prcvd_thru = ntohs(stmp);
|
||||
}
|
||||
if(rdflag12 == 1) {
|
||||
/* ARDP Connection Refused */
|
||||
if(pfs_debug >= 8)
|
||||
fprintf(stderr,"***ARDP connection refused by server***\n");
|
||||
req->status = ARDP_REFUSED;
|
||||
EXTRACT_ITEM(req,ardp_activeQ);
|
||||
--ardp_activeQ_len;
|
||||
APPEND_ITEM(req,ardp_completeQ);
|
||||
goto check_for_pending;
|
||||
}
|
||||
if(rdflag12 == 4) {
|
||||
/* Server Redirect */
|
||||
bcopy4(ctlptr,&(req->peer_addr));
|
||||
ctlptr += 4;
|
||||
bcopy2(ctlptr,&(req->peer_port));
|
||||
ctlptr += 2;
|
||||
if(pfs_debug >= 8)
|
||||
fprintf(stderr,"***ARDP redirect to %s(%d)***\n",
|
||||
inet_ntoa(req->peer_addr),PEER_PORT(req));
|
||||
ardp_xmit(req, req->pwindow_sz);
|
||||
}
|
||||
if(rdflag12 == 254) {
|
||||
tchar = *ctlptr;
|
||||
ctlptr++;
|
||||
if(tchar & 0x1) { /* Queue position */
|
||||
bcopy2(ctlptr,&stmp);
|
||||
req->inf_queue_pos = ntohs(stmp);
|
||||
if(pfs_debug >= 8)
|
||||
fprintf(stderr,"Current queue position on server is %d\n",
|
||||
req->inf_queue_pos);
|
||||
ctlptr += 2;
|
||||
}
|
||||
if(tchar & 0x2) { /* Expected system time */
|
||||
bcopy4(ctlptr,<mp);
|
||||
req->inf_sys_time = ntohl(ltmp);
|
||||
if(pfs_debug >= 8)
|
||||
fprintf(stderr,"Expected system time is %d seconds\n",
|
||||
req->inf_sys_time);
|
||||
ctlptr += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If ->seq 0, then an unsequenced control packet */
|
||||
if(pkt->seq == 0) {
|
||||
ardp_ptfree(pkt);
|
||||
goto check_for_pending;
|
||||
}
|
||||
if(pkt->length >= 0) pkt->length -= hdr_len;
|
||||
pkt->start += hdr_len;
|
||||
pkt->text = pkt->start;
|
||||
pkt->ioptr = pkt->start;
|
||||
|
||||
if(pfs_debug >= 8) fprintf(stderr,"Packet %d of %d (cid=%d)\n", pkt->seq,
|
||||
req->rcvd_tot, ntohs(req->cid));
|
||||
|
||||
if (req->rcvd == NOPKT) {
|
||||
/* Add it as the head of empty doubly linked list */
|
||||
req->rcvd = pkt;
|
||||
pkt->previous = pkt;
|
||||
if(pkt->seq == 1) {
|
||||
req->comp_thru = pkt;
|
||||
req->rcvd_thru = 1;
|
||||
/* If only one packet, then return it. We will assume */
|
||||
/* that it is not a sequenced control packet */
|
||||
if(req->rcvd_tot == 1) goto req_complete;
|
||||
}
|
||||
goto ins_done;
|
||||
}
|
||||
|
||||
if(req->comp_thru && (pkt->seq <= req->rcvd_thru))
|
||||
ardp_ptfree(pkt); /* Duplicate */
|
||||
else if(pkt->seq < req->rcvd->seq) { /* First (sequentially) */
|
||||
pkt->next = req->rcvd;
|
||||
pkt->previous = req->rcvd->previous;
|
||||
req->rcvd->previous = pkt;
|
||||
req->rcvd = pkt;
|
||||
if(req->rcvd->seq == 1) {
|
||||
req->comp_thru = req->rcvd;
|
||||
req->rcvd_thru = 1;
|
||||
}
|
||||
}
|
||||
else { /* Insert later in the packet list unless duplicate */
|
||||
ptmp = (req->comp_thru ? req->comp_thru : req->rcvd);
|
||||
while (pkt->seq > ptmp->seq) {
|
||||
if(ptmp->next == NULL) {
|
||||
/* Insert at end */
|
||||
ptmp->next = pkt;
|
||||
pkt->previous = ptmp;
|
||||
pkt->next = NULL;
|
||||
req->rcvd->previous = pkt;
|
||||
goto ins_done;
|
||||
}
|
||||
ptmp = ptmp->next;
|
||||
}
|
||||
if(ptmp->seq == pkt->seq) /* Duplicate */
|
||||
ardp_ptfree(pkt);
|
||||
else { /* insert before ptmp (we know were not first) */
|
||||
ptmp->previous->next = pkt;
|
||||
pkt->previous = ptmp->previous;
|
||||
pkt->next = ptmp;
|
||||
ptmp->previous = pkt;
|
||||
}
|
||||
}
|
||||
|
||||
ins_done:
|
||||
/* Find out how much is complete and remove sequenced control packets */
|
||||
while(req->comp_thru && req->comp_thru->next &&
|
||||
(req->comp_thru->next->seq == (req->comp_thru->seq + 1))) {
|
||||
/* We have added one more in sequence */
|
||||
if(pfs_debug >= 8)
|
||||
fprintf(stderr,"Packets now received through %d\n",
|
||||
req->comp_thru->next->seq);
|
||||
|
||||
if(req->comp_thru->length == -1) {
|
||||
/* Old comp_thru was a sequenced control packet */
|
||||
ptmp = req->comp_thru;
|
||||
req->comp_thru = req->comp_thru->next;
|
||||
req->rcvd_thru = req->comp_thru->seq;
|
||||
EXTRACT_ITEM(ptmp,req->rcvd);
|
||||
ardp_ptfree(ptmp);
|
||||
}
|
||||
else {
|
||||
/* Old comp_thru was a data packet */
|
||||
req->comp_thru = req->comp_thru->next;
|
||||
req->rcvd_thru = req->comp_thru->seq;
|
||||
}
|
||||
|
||||
/* Update outgoing packets */
|
||||
ardp_headers(req);
|
||||
|
||||
/* We've made progress, so reset timeout and retry count */
|
||||
req->timeout_adj.tv_sec = max(req->timeout.tv_sec,req->svc_rwait);
|
||||
req->retries_rem = req->retries;
|
||||
}
|
||||
|
||||
/* See if there are any gaps - possibly toggle GAP status */
|
||||
if(!req->comp_thru || req->comp_thru->next) {
|
||||
if (req->status == ARDP_STATUS_ACTIVE) req->status = ARDP_STATUS_GAPS;
|
||||
}
|
||||
else if (req->status == ARDP_STATUS_GAPS) req->status = ARDP_STATUS_ACTIVE;
|
||||
|
||||
/* If incomplete, wait for more */
|
||||
if (!(req->comp_thru) || (req->comp_thru->seq != req->rcvd_tot))
|
||||
goto check_for_pending;
|
||||
|
||||
req_complete:
|
||||
|
||||
if (pfs_debug >= 7) {
|
||||
fprintf(stderr,"The complete response has been received.\n");
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
|
||||
if(req->status == ARDP_STATUS_ACKPEND) {
|
||||
if (pfs_debug >= 7) {
|
||||
if (req->peer.sin_family == AF_INET)
|
||||
fprintf(stderr,"Acknowledging final packet to %s(%d)\n",
|
||||
inet_ntoa(req->peer_addr), PEER_PORT(req));
|
||||
else fprintf(stderr,"Acknowledging final packet\n");
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
ardp_xmit(req, req->pwindow_sz);
|
||||
}
|
||||
|
||||
req->status = ARDP_STATUS_COMPLETE;
|
||||
req->inpkt = req->rcvd;
|
||||
EXTRACT_ITEM(req,ardp_activeQ);
|
||||
--ardp_activeQ_len;
|
||||
APPEND_ITEM(req,ardp_completeQ);
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
ardp__pr_ferror(int errcode)
|
||||
{
|
||||
RREQ creq;
|
||||
|
||||
while(ardp_activeQ) {
|
||||
creq = ardp_activeQ;
|
||||
ardp_activeQ->status = errcode;
|
||||
EXTRACT_ITEM(creq,ardp_activeQ);
|
||||
--ardp_activeQ_len;
|
||||
APPEND_ITEM(creq,ardp_completeQ);
|
||||
}
|
||||
perrno = errcode;
|
||||
return(errcode);
|
||||
}
|
||||
73
prospero/lib/ardp/ardp_ptalloc.c
Normal file
73
prospero/lib/ardp/ardp_ptalloc.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the files
|
||||
* <uw-copyright.h> and <usc-copyr.h>.
|
||||
*
|
||||
* Written by bcn 1989-91 as part of the Prospero distribution
|
||||
* Modified by bcn 1/93 changed to conform to ardp.h
|
||||
* Modified by swa 12/93 threads added.
|
||||
*/
|
||||
|
||||
#include <uw-copyright.h>
|
||||
#include <usc-copyr.h>
|
||||
#include <ardp.h>
|
||||
#include <stdlib.h> /* For malloc or free */
|
||||
#include <pfs_threads.h>
|
||||
#include <mitra_macros.h>
|
||||
|
||||
/* "free" conflicted with free() - Mitra */
|
||||
static PTEXT lfree = NOPKT; /* locked with p_th_mutexPTEXT */
|
||||
int ptext_count = 0;
|
||||
int ptext_max = 0;
|
||||
|
||||
/*
|
||||
* ardp_ptalloc - allocate and initialize ptext structure
|
||||
*
|
||||
* ardp_ptalloc returns a pointer to an initialized structure of type
|
||||
* PTEXT. If it is unable to allocate such a structure, it
|
||||
* returns NULL (NOPKT).
|
||||
*/
|
||||
PTEXT
|
||||
ardp_ptalloc()
|
||||
{
|
||||
PTEXT pt;
|
||||
TH_STRUC_ALLOC(ptext,PTEXT,pt);
|
||||
|
||||
/* Initialize and fill in default values. */
|
||||
pt->seq = 0;
|
||||
pt->length = 0;
|
||||
/* The offset is to leave room for additional headers */
|
||||
pt->start = pt->dat + ARDP_PTXT_HDR;
|
||||
pt->text = pt->start;
|
||||
pt->ioptr = pt->start;
|
||||
pt->mbz = 0;
|
||||
return(pt);
|
||||
}
|
||||
|
||||
/*
|
||||
* ardp_ptfree - free a PTEXT structure
|
||||
*
|
||||
* ardp_ptfree takes a pointer to a PTEXT structure and adds it to
|
||||
* the free list for later reuse.
|
||||
*/
|
||||
void ardp_ptfree(pt)
|
||||
PTEXT pt;
|
||||
{
|
||||
TH_STRUC_FREE(ptext,PTEXT,pt);
|
||||
}
|
||||
|
||||
/*
|
||||
* ardp_ptlfree - free a PTEXT structure
|
||||
*
|
||||
* ardp_ptlfree takes a pointer to a PTEXT structure frees it and any linked
|
||||
* PTEXT structures. It is used to free an entrie list of PTEXT
|
||||
* structures.
|
||||
*/
|
||||
void ardp_ptlfree(pt)
|
||||
PTEXT pt;
|
||||
{
|
||||
TH_STRUC_LFREE(PTEXT,pt,ardp_ptfree);
|
||||
}
|
||||
|
||||
38
prospero/lib/ardp/ardp_reply.c
Normal file
38
prospero/lib/ardp/ardp_reply.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*
|
||||
* Written by bcn 2/93 to send reply to request
|
||||
* Gutted by swa 11/93 functionality moved to ardp_breply().
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ardp.h>
|
||||
|
||||
/*
|
||||
* ardp_reply - send a null-terminated string as a reply to a request
|
||||
*
|
||||
* ardp_reply reply takes request to which a reply is to be sent
|
||||
* a flags field, and a message to be sent to the client in response
|
||||
* to the request. ardp_reply then calls ardp_reply() to do the work.
|
||||
*
|
||||
* If space remains in the packet, the response is buffered pending
|
||||
* subsequent replies, unless the ARDP_REPL_COMPLETE has been specified,
|
||||
* in which case all data is sent. If the size of the buffered response
|
||||
* approaches the maximum packet size, the buffered data is sent, and
|
||||
* and a new packet is started to hold any remaining data from the current
|
||||
* message. (This is implemented by ardp_breply()).
|
||||
*/
|
||||
|
||||
int
|
||||
ardp_reply(RREQ req, /* Request to which this is a response */
|
||||
int flags, /* Whether this is the final message */
|
||||
char *message) /* The data to be sent */
|
||||
{
|
||||
return ardp_breply(req, flags, message, 0);
|
||||
}
|
||||
|
||||
471
prospero/lib/ardp/ardp_respond.c
Normal file
471
prospero/lib/ardp/ardp_respond.c
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Copyright (c) 1991 by the University of Washington
|
||||
* Copyright (c) 1992, 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the files
|
||||
* <uw-copyright.h> and <usc-copyr.h>.
|
||||
*
|
||||
* Written by bcn 1991 as transmit in rdgram.c (Prospero)
|
||||
* Modified by bcn 1/93 modularized and incorporated into new ardp library
|
||||
*/
|
||||
|
||||
#include <uw-copyright.h>
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ardp.h>
|
||||
#include <pmachine.h> /* for bcopy() */
|
||||
#include <plog.h>
|
||||
|
||||
EXTERN_MUTEXED_DECL(RREQ,ardp_doneQ);
|
||||
EXTERN_MUTEXED_DECL(RREQ,ardp_runQ);
|
||||
extern int ardp_srvport;
|
||||
extern int ardp_prvport;
|
||||
extern int dQlen; /* mutexed with ardp_doneQ */
|
||||
extern int dQmaxlen;
|
||||
int ardp_clear_doneQ_loginfo = 0; /* Clear log info from the doneQ.
|
||||
Set by the -n option to
|
||||
dirsrv. */
|
||||
|
||||
|
||||
/*
|
||||
* ardp_respond - respond to request
|
||||
*
|
||||
* ardp_respond takes a request block whose ->outpkt element is a pointer
|
||||
* to a list of packets that have not yet been returned. It moves the
|
||||
* packets to the transmission queue of the request (->trns) and assigns a
|
||||
* sequence number to each packet. If options is ARDP_R_COMPLETE, it
|
||||
* also sets the ->trns_tot field of the request indicating the total
|
||||
* number of packets in the response. if the ARDP_R_NOSEND option is
|
||||
* not specified, the current packet is also sent to the client.
|
||||
*
|
||||
* ardp_respond() expects the text of the packet to have a trailing null
|
||||
* at the end of it, which is transmitted for safety's sake.
|
||||
* (noted: swa, 8/5/93). This explains some bugs...
|
||||
*/
|
||||
int
|
||||
ardp_respond(req, options)
|
||||
RREQ req;
|
||||
int options;
|
||||
{
|
||||
char buf[ARDP_PTXT_DSZ];
|
||||
int sent;
|
||||
int retval = ARDP_SUCCESS; /* Return value */
|
||||
unsigned short cid = htons(req->cid);
|
||||
unsigned short nseq = 0;
|
||||
unsigned short ntotal = 0;
|
||||
unsigned short rcvdthru = 0;
|
||||
unsigned short bkoff = 0;
|
||||
PTEXT tpkt; /* Temporary pkt pointer */
|
||||
|
||||
*buf = '\0';
|
||||
|
||||
if(req->peer_ardp_version < 0) cid = 0;
|
||||
|
||||
if(req->status == ARDP_STATUS_FREE)
|
||||
internal_error("Attempt to respond to free RREQ\n");
|
||||
|
||||
if(!req->outpkt) return(ARDP_BAD_REQ);
|
||||
|
||||
more_to_process:
|
||||
|
||||
if(!req->trns) req->outpkt->seq = 1;
|
||||
else req->outpkt->seq = req->trns->previous->seq + 1;
|
||||
|
||||
if((options & ARDP_R_COMPLETE) && (req->outpkt->next == NOPKT)) {
|
||||
/* It's the last packet to send. */
|
||||
req->trns_tot = req->outpkt->seq; /* set the total # of packets; now
|
||||
known. */
|
||||
|
||||
/* Test this condition later to see if the server (us) needs to request
|
||||
that the client ACK. The server will request an ACK if we had
|
||||
previously told the client to back off and now are rescinding that.
|
||||
*/
|
||||
}
|
||||
nseq = htons((u_short) req->outpkt->seq);
|
||||
ntotal = htons((u_short) req->trns_tot);
|
||||
|
||||
if((req->peer_ardp_version < 0)&&(req->peer_ardp_version != -2)) {
|
||||
if(req->trns_tot) sprintf(buf, "MULTI-PACKET %d OF %d",
|
||||
req->outpkt->seq, req->trns_tot);
|
||||
else sprintf(buf,"MULTI-PACKET %d\n",req->outpkt->seq);
|
||||
}
|
||||
|
||||
/* Note that in the following, we don't have to make sure */
|
||||
/* there is room for the header in the packet because we */
|
||||
/* are the only one that moves back the start, and ptalloc */
|
||||
/* allocates space for us in all packets it creates */
|
||||
|
||||
/* If a single message and no connection ID to return, */
|
||||
/* and no pending server requested wait pending then */
|
||||
/* we can leave the control fields out */
|
||||
if((req->trns_tot == 1) && (req->svc_rwait == 0)) {
|
||||
/* Once V4 clients gone, the next if condition can be removed */
|
||||
if((req->peer_ardp_version > -1)||(req->peer_ardp_version == -2)) {
|
||||
if(req->cid == 0) {
|
||||
req->outpkt->start -= 1;
|
||||
req->outpkt->length += 1;
|
||||
*req->outpkt->start = (char) 1;
|
||||
}
|
||||
else {
|
||||
req->outpkt->start -= 3;
|
||||
req->outpkt->length += 3;
|
||||
*req->outpkt->start = (char) 3;
|
||||
bcopy2(&cid,req->outpkt->start+1); /* Conn ID */
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Fill in the control fields */
|
||||
else {
|
||||
/* For old versions, assume that svc_rwait of > 5 is too long. */
|
||||
/* For new versions, if we set the svc_rwait before to any non-default
|
||||
value, now set it to 0. (client's default). */
|
||||
|
||||
/* if we might have to set octet 11 flags (in this case, the ACK flag),
|
||||
then we need to send an 11-byte request.
|
||||
This is the case either:
|
||||
(a) if we need to clear a service requested wait or
|
||||
(b) if we are sending the last packet of a window, so that the
|
||||
client should ACK (or request a retry) before the next one goes.
|
||||
*/
|
||||
if (/* Case (A) -- clear wait */
|
||||
((req->peer_ardp_version < 0 && req->svc_rwait > 5)
|
||||
|| (req->peer_ardp_version == 0 && req->svc_rwait)
|
||||
|| (req->svc_rwait_seq > req->prcvd_thru))
|
||||
|| /* Case (B) -- sending last packet of a window */
|
||||
(req->outpkt->seq == req->prcvd_thru + req->pwindow_sz)) {
|
||||
req->outpkt->start -= 12;
|
||||
req->outpkt->length += 12;
|
||||
*req->outpkt->start = (char) 12;
|
||||
|
||||
rcvdthru = htons((u_short) req->rcvd_thru);
|
||||
bcopy2(&rcvdthru,req->outpkt->start+7); /* Recvd Through */
|
||||
|
||||
/* XXX Note that when all clients V5, new wait will be 0 */
|
||||
/* Assume we should cancel the wait and remember when reset */
|
||||
if((req->peer_ardp_version < 0 && req->svc_rwait > 5)
|
||||
|| (req->peer_ardp_version == 0 && req->svc_rwait)) {
|
||||
if(req->peer_ardp_version < 0)
|
||||
req->svc_rwait = 5;
|
||||
else
|
||||
req->svc_rwait = 0;
|
||||
req->svc_rwait_seq = req->outpkt->seq; /* This was the sequence
|
||||
number it was reset
|
||||
on. */
|
||||
/* We'll ask for an acknowledgement when we send the last
|
||||
packet of the response. */
|
||||
}
|
||||
bkoff = htons((u_short) req->svc_rwait);
|
||||
bcopy2(&bkoff,req->outpkt->start+9); /* New ttwait */
|
||||
/* Send an ACK IF: */
|
||||
if ((/* (A1) It's the last packet */
|
||||
(req->trns_tot && req->outpkt->seq == req->trns_tot)
|
||||
&& /* (A2) If we reduced a previously requested wait, and haven't
|
||||
yet had that reduction acknowledged, then ask for an
|
||||
acknowledgement. */
|
||||
(req->svc_rwait_seq > req->prcvd_thru))
|
||||
|| /* OR: Case (B) -- sending last packet of a window */
|
||||
(req->outpkt->seq == req->prcvd_thru + req->pwindow_sz)) {
|
||||
|
||||
req->retries_rem = 4;
|
||||
req->wait_till.tv_sec = time(NULL) + req->timeout_adj.tv_sec;
|
||||
*(req->outpkt->start+11) = 0x80; /* Request ack */
|
||||
} else {
|
||||
*(req->outpkt->start+11) = 0x00; /* Don't request ack */
|
||||
}
|
||||
}
|
||||
else {
|
||||
req->outpkt->start -= 7;
|
||||
req->outpkt->length += 7;
|
||||
*req->outpkt->start = (char) 7;
|
||||
}
|
||||
|
||||
bcopy2(&cid,req->outpkt->start+1); /* Conn ID */
|
||||
bcopy2(&nseq,req->outpkt->start+3); /* Pkt no */
|
||||
bcopy2(&ntotal,req->outpkt->start+5); /* Total */
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* commented out by swa@isi.edu, since nulls in packets are now significant
|
||||
to the ARDP library. Therefore, one should NOT be appended to each
|
||||
packet in the data area. */
|
||||
/* Make room for the trailing null */
|
||||
req->outpkt->length += 1;
|
||||
#endif
|
||||
|
||||
/* Only send if packet not yet received. */
|
||||
/* Do honor the window of req->pwindow_sz packets. */
|
||||
if((!(options & ARDP_R_NOSEND)) &&
|
||||
(req->outpkt->seq <= (req->prcvd_thru + req->pwindow_sz)) &&
|
||||
(req->outpkt->seq > req->prcvd_thru) /* This packet not yet received */
|
||||
) {
|
||||
retval = ardp_snd_pkt(req->outpkt,req);
|
||||
}
|
||||
|
||||
|
||||
/* Add packet to req->trns */
|
||||
tpkt = req->outpkt;
|
||||
EXTRACT_ITEM(tpkt,req->outpkt);
|
||||
APPEND_ITEM(tpkt,req->trns);
|
||||
|
||||
if(req->outpkt) goto more_to_process;
|
||||
|
||||
/* If complete then add request structure to done */
|
||||
/* queue in case we have to retry. */
|
||||
if(options & ARDP_R_COMPLETE) {
|
||||
RREQ match_in_runQ; /* Variable for indexing ardp_runQ */
|
||||
|
||||
/* Request has been processed, here you can accumulate */
|
||||
/* statistics on system time or service time */
|
||||
plog(L_QUEUE_COMP, req, "Requested service completed");
|
||||
|
||||
arch_set_etime(req); /* bajan */
|
||||
|
||||
EXTERN_MUTEXED_LOCK(ardp_runQ);
|
||||
for (match_in_runQ = ardp_runQ; match_in_runQ; match_in_runQ = match_in_runQ->next) {
|
||||
if(match_in_runQ == req) {
|
||||
EXTRACT_ITEM(req, ardp_runQ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* At this point, 'req' is the completed request structure. It is
|
||||
definitely not on the ardp_runQ, and if it was, it's been removed.
|
||||
*/
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_runQ);
|
||||
if((req->cid == 0) || (dQmaxlen <= 0)) {
|
||||
/* If request has no CID (can't be matched on a retry) or
|
||||
if done-Q max length is <= 0 (i.e., don't keep a doneQ), then
|
||||
just throw away the request now that it's done. --swa */
|
||||
#if 0 /* ask BCN about this. Should never be
|
||||
necessary, since req->outpkt is always going
|
||||
to be NULL or we wouldn't be here. */
|
||||
req->outpkt = NULL;
|
||||
#endif
|
||||
ardp_rqfree(req);
|
||||
}
|
||||
else {
|
||||
/* This item should be put on the doneQ; don't just throw it away.
|
||||
*/
|
||||
/* Note that this code will not handle a reduction in the size of
|
||||
dQmaxlen; if anywhere you reset it to a smaller value, that code
|
||||
will have to truncate the queue. */
|
||||
EXTERN_MUTEXED_LOCK(ardp_doneQ);
|
||||
if(dQlen <= dQmaxlen) {
|
||||
/* Add to start */
|
||||
#ifndef NDEBUG /* this helps debugging and slightly cuts down
|
||||
on memory usage of the doneq. */
|
||||
if (ardp_clear_doneQ_loginfo)
|
||||
ardp_rq_partialfree(req);
|
||||
#endif
|
||||
PREPEND_ITEM(req, ardp_doneQ);
|
||||
dQlen++;
|
||||
} else {
|
||||
/* The last item in the queue is ardp_doneQ->previous. */
|
||||
/* Use a variable to denote it, so that the EXTRACT_ITEM macro
|
||||
doesn't encounter problems (since it internally modifies the
|
||||
referent of the name ardp_doneQ->previous). */
|
||||
register RREQ doneQ_lastitem = ardp_doneQ->previous;
|
||||
/* Add new request to start */
|
||||
#ifndef NDEBUG /* this helps debugging and slightly cuts down
|
||||
on memory usage of the doneq. */
|
||||
if (ardp_clear_doneQ_loginfo)
|
||||
ardp_rq_partialfree(req);
|
||||
#endif
|
||||
PREPEND_ITEM(req, ardp_doneQ);
|
||||
|
||||
/* Now, prepare to remove the last item in the queue */
|
||||
/* If the request to remove was not acknowledged by the
|
||||
clients, log the fact */
|
||||
if(doneQ_lastitem->svc_rwait_seq >
|
||||
doneQ_lastitem->prcvd_thru) {
|
||||
plog(L_QUEUE_INFO,doneQ_lastitem,
|
||||
"Requested ack never received (%d of %d/%d ack)",
|
||||
doneQ_lastitem->prcvd_thru,
|
||||
doneQ_lastitem->svc_rwait_seq,
|
||||
doneQ_lastitem->trns_tot);
|
||||
}
|
||||
/* Now do the removal and free it. */
|
||||
EXTRACT_ITEM(doneQ_lastitem, ardp_doneQ);
|
||||
ardp_rqfree(doneQ_lastitem);
|
||||
}
|
||||
EXTERN_MUTEXED_UNLOCK(ardp_doneQ);
|
||||
}
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* ardp_rwait - sends a message to a client requesting
|
||||
* that it wait for service. This message indicates that
|
||||
* there may be a delay before the request can be processed.
|
||||
* The recipient should not attempt any retries until the
|
||||
* time specified in this message has elapsed. Depending on the
|
||||
* protocol version in use by the client, the additional
|
||||
* queue position and system time arguments may be returned.
|
||||
*/
|
||||
int
|
||||
ardp_rwait(RREQ req, /* Request to which this is a reply */
|
||||
int timetowait, /* How long client should wait */
|
||||
short qpos, /* Queue position */
|
||||
/* Note stime is a System call in solaris, changed to systemtime */
|
||||
int systemtime) /* System time */
|
||||
{
|
||||
PTEXT r = ardp_ptalloc();
|
||||
short cid = htons(req->cid);
|
||||
short nseq = 0;
|
||||
short zero = 0;
|
||||
short backoff;
|
||||
short stmp;
|
||||
int ltmp;
|
||||
int tmp;
|
||||
|
||||
if(req->peer_ardp_version < 0) cid = 0;
|
||||
|
||||
/* Remember that we sent a server requested wait and assume */
|
||||
/* it took effect, though request will be unsequenced */
|
||||
/* This seems bogus to me. Rather, more appropriate would be to send an
|
||||
unsequenced control packet if the requested wait is being extended and
|
||||
a sequenced packet if the wait is being shortened, since the shortening
|
||||
of the wait is an event which requires an acknowledgement. */
|
||||
/* Note, however, that this shortening is a way the current function is not
|
||||
used. */
|
||||
req->svc_rwait_seq = req->prcvd_thru; /* Mark the latest requested wait as
|
||||
definitely having been received.
|
||||
This is not necessary, actually --
|
||||
leaving this set to zero is ok. */
|
||||
req->svc_rwait = timetowait;
|
||||
|
||||
|
||||
|
||||
*r->start = (char) 11;
|
||||
r->length = 11;
|
||||
|
||||
backoff = htons((u_short) timetowait);
|
||||
|
||||
bcopy2(&cid,r->start+1); /* Connection ID */
|
||||
bcopy2(&nseq,r->start+3); /* Packet number */
|
||||
bcopy2(&zero,r->start+5); /* Total packets */
|
||||
bcopy2(&zero,r->start+7); /* Received through */
|
||||
bcopy2(&backoff,r->start+9); /* Backoff */
|
||||
|
||||
if((req->peer_ardp_version >= 0) && (qpos || systemtime)) {
|
||||
r->length = 14;
|
||||
bzero3(r->start+11);
|
||||
*(r->start+12) = (unsigned char) 254;
|
||||
if(qpos) *(r->start+13) |= (unsigned char) 1;
|
||||
if(systemtime) *(r->start+13) |= (unsigned char) 2;
|
||||
if(qpos) {
|
||||
stmp = htons(qpos);
|
||||
bcopy2(&stmp,r->start+r->length);
|
||||
r->length += 2;
|
||||
}
|
||||
if(systemtime) {
|
||||
ltmp = htonl(systemtime);
|
||||
bcopy4(<mp,r->start+r->length);
|
||||
r->length += 4;
|
||||
|
||||
}
|
||||
*r->start = (char) r->length;
|
||||
}
|
||||
|
||||
tmp = ardp_snd_pkt(r,req);
|
||||
ardp_ptfree(r);
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* ardp_refuse - sends a message to the recipient indicating
|
||||
* that its connection attempt has been refused.
|
||||
*/
|
||||
int
|
||||
ardp_refuse(RREQ req)
|
||||
{
|
||||
PTEXT r;
|
||||
short cid = htons(req->cid);
|
||||
short zero = 0;
|
||||
int tmp;
|
||||
|
||||
/* If old version won't understand refused */
|
||||
if(req->peer_ardp_version < 0) return(ARDP_FAILURE);
|
||||
|
||||
r = ardp_ptalloc();
|
||||
*r->start = (char) 13;
|
||||
r->length = 13;
|
||||
|
||||
bcopy2(&cid,r->start+1); /* Connection ID */
|
||||
bcopy2(&zero,r->start+3); /* Packet number */
|
||||
bcopy2(&zero,r->start+5); /* Total packets */
|
||||
bcopy2(&zero,r->start+7); /* Received through */
|
||||
bcopy2(&zero,r->start+9); /* Backoff */
|
||||
bzero2(r->start+11); /* Flags */
|
||||
*(r->start + 12) = (unsigned char) 1; /* Refused */
|
||||
|
||||
tmp = ardp_snd_pkt(r,req);
|
||||
ardp_ptfree(r);
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ardp_redirect - sends a message to the recipient indicating that
|
||||
* all unacknowledged packets should be sent to a new target destination.
|
||||
* The target specifies the host address and the UDP port in network
|
||||
* byte order. For now, redirections should only occur before any
|
||||
* request packets have been acknowledged, or response packets sent.
|
||||
*/
|
||||
int
|
||||
ardp_redirect(RREQ req, /* Request to be redirected */
|
||||
struct sockaddr_in *target) /* Address of new server */
|
||||
{
|
||||
PTEXT r;
|
||||
short cid = htons(req->cid);
|
||||
int tmp;
|
||||
|
||||
/* Old versions don't support redirection */
|
||||
if(req->peer_ardp_version < 0) return(ARDP_FAILURE);
|
||||
|
||||
r = ardp_ptalloc();
|
||||
|
||||
*r->start = (char) 19;
|
||||
r->length = 19;
|
||||
|
||||
bcopy2(&cid,r->start+1); /* Connection ID */
|
||||
bzero(r->start+3,9); /* Pktno, total, rcvd, swait, flags1 */
|
||||
*(r->start + 12) = '\004'; /* Redirect option */
|
||||
bcopy4(&(target->sin_addr),r->start+13);
|
||||
bcopy2(&(target->sin_port),r->start+17);
|
||||
|
||||
tmp = ardp_snd_pkt(r,req);
|
||||
ardp_ptfree(r);
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ardp_ack - sends an acknowledgment message to the client indicating
|
||||
* that all packets through req->rcvd_thru have been recived. It is
|
||||
* only called on receipt of a multi-packet server request.
|
||||
*/
|
||||
int
|
||||
ardp_acknowledge(RREQ req) /* Request to which this is a reply */
|
||||
{
|
||||
PTEXT r = ardp_ptalloc();
|
||||
short cid = htons(req->cid);
|
||||
short rcvd = htons(req->rcvd_thru);
|
||||
short zero = 0;
|
||||
int tmp;
|
||||
|
||||
*r->start = (char) 9;
|
||||
r->length = 9;
|
||||
|
||||
bcopy2(&cid,r->start+1); /* Connection ID */
|
||||
bcopy2(&zero,r->start+3); /* Packet number */
|
||||
bcopy2(&zero,r->start+5); /* Total packets */
|
||||
bcopy2(&rcvd,r->start+7); /* Received through */
|
||||
|
||||
tmp = ardp_snd_pkt(r,req);
|
||||
ardp_ptfree(r);
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
|
||||
114
prospero/lib/ardp/ardp_retriev.c
Normal file
114
prospero/lib/ardp/ardp_retriev.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>.
|
||||
*
|
||||
* Written by bcn 1/93 to check and/or wait for completion of request
|
||||
*/
|
||||
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef AIX
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include <ardp.h>
|
||||
#include <perrno.h>
|
||||
#include <pmachine.h>
|
||||
|
||||
extern RREQ ardp_activeQ; /* Info about active requests */
|
||||
extern RREQ ardp_completeQ;/* Info about completed reqs */
|
||||
extern int ardp_port; /* Opened UDP port */
|
||||
extern int pfs_debug; /* Debug level */
|
||||
|
||||
/*
|
||||
* ardp_retrieve - check and/or wait for completion of request
|
||||
*
|
||||
* ardp_retrieve takes a request and a time to wait. It will check to
|
||||
* see if the request is complete and if so, returns ARDP_SUCCESS.
|
||||
* If not complete, ardp_retrieve will wait up till the time to wait
|
||||
* before returning. If still incomplete it will return ARDP_PENDING.
|
||||
* A time to wait of -1 indicates that one should not return until
|
||||
* complete, or until a timeout occurs. On any failure (other than
|
||||
* still pending), an error code is returned.
|
||||
*
|
||||
* BUGS: Right now, only accepts ttwait values of 0 and -1. If
|
||||
* positive, it is currently treated as -1.
|
||||
*/
|
||||
int
|
||||
ardp_retrieve(req,ttwait)
|
||||
RREQ req; /* Request to wait for */
|
||||
int ttwait; /* Time to wait in microseconds */
|
||||
{
|
||||
fd_set readfds; /* Used for select */
|
||||
struct timeval *selwait; /* Time to wait for select */
|
||||
int tmp; /* Hold value returned by select */
|
||||
|
||||
/* XXX For now only support ttwait values of 0 and -1 */
|
||||
if(ttwait > 0) return(ARDP_FAILURE);
|
||||
|
||||
p_clear_errors();
|
||||
|
||||
if(req->status == ARDP_STATUS_FREE) {
|
||||
fprintf(stderr,"Attempt to retrieve free RREQ\n");
|
||||
abort();
|
||||
return(ARDP_BAD_REQ);
|
||||
}
|
||||
|
||||
if(req->status == ARDP_STATUS_NOSTART) {
|
||||
perrno = ARDP_BAD_REQ;
|
||||
return(perrno);
|
||||
}
|
||||
|
||||
check_for_more:
|
||||
|
||||
ardp_process_active();
|
||||
if((req->status == ARDP_STATUS_COMPLETE) || (req->status > 0)) {
|
||||
EXTRACT_ITEM(req,ardp_completeQ);
|
||||
if(pfs_debug >= 9) {
|
||||
PTEXT ptmp; /* debug-step through req->rcvd */
|
||||
if(req->status > 0) fprintf(stderr,"Request failed (error %d)!",
|
||||
req->status);
|
||||
else fprintf(stderr,"Packets received...");
|
||||
ptmp = req->rcvd;
|
||||
while(ptmp) {
|
||||
fprintf(stderr,"Packet %d:\n",ptmp->seq);
|
||||
ardp_showbuf(ptmp->start, ptmp->length, stderr);
|
||||
putc('\n', stderr);
|
||||
ptmp = ptmp->next;
|
||||
}
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
if(req->status == ARDP_STATUS_COMPLETE) return(ARDP_SUCCESS);
|
||||
else {
|
||||
perrno = req->status; /* Specific error */
|
||||
return(perrno);
|
||||
}
|
||||
}
|
||||
if(ttwait == 0) return(ARDP_PENDING);
|
||||
|
||||
/* Here we should figure out how long to wait, a minimum of */
|
||||
/* ttwait, or the first retry timer for any pending request */
|
||||
/* For the time being, we use the retry timer of the */
|
||||
/* current request. */
|
||||
|
||||
if (pfs_debug >= 6) fprintf(stderr,"Waiting for reply...");
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(ardp_port, &readfds);
|
||||
|
||||
selwait = &(req->timeout_adj);
|
||||
|
||||
/* select - either recv is ready, or timeout */
|
||||
/* see if timeout or error or wrong descriptor */
|
||||
tmp = select(ardp_port + 1, &readfds, (fd_set *)0, (fd_set *)0, selwait);
|
||||
|
||||
/* Packet received, or timeout - both handled by ardp_process_active */
|
||||
if(tmp >= 0) goto check_for_more;
|
||||
|
||||
if (pfs_debug) fprintf(stderr, "select failed: returned %d\n", tmp);
|
||||
perrno = ARDP_SELECT_FAILED;
|
||||
return(perrno);
|
||||
}
|
||||
240
prospero/lib/ardp/ardp_rqalloc.c
Normal file
240
prospero/lib/ardp/ardp_rqalloc.c
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>
|
||||
*
|
||||
* Written by bcn 1991 as part of the Prospero distribution
|
||||
* Modified by bcn 1/93 extended rreq structure
|
||||
* Modified by swa 11/93 multithreaded
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
#include <stdio.h>
|
||||
#include <ardp.h>
|
||||
#include <stdlib.h> /* malloc or free */
|
||||
#include <pmachine.h> /* for bzero() */
|
||||
#include <pfs.h> /* for pafree and stfree */
|
||||
|
||||
/* When debugging the ARDP window flow control stuff, use these definitions. */
|
||||
/* Defaults are set here. */
|
||||
#if 0
|
||||
#define ARDP_MY_WINDOW_SZ 2 /* Our window size;currently only implemented on
|
||||
the client. Here, the client asks for a
|
||||
window size of 2, for testing. */
|
||||
#undef ARDP_DEFAULT_WINDOW_SZ /* Peer window size the server will use for its
|
||||
default flow-control strategy. */ */
|
||||
#define ARDP_DEFAULT_WINDOW_SZ 1 /* for testing. */
|
||||
#endif
|
||||
|
||||
static ardp_default_timeout = ARDP_DEFAULT_TIMEOUT;
|
||||
static ardp_default_retry = ARDP_DEFAULT_RETRY;
|
||||
int ardp_priority = 0; /* Default priority */
|
||||
|
||||
static RREQ lfree = NOREQ;
|
||||
int rreq_count = 0;
|
||||
int rreq_max = 0;
|
||||
|
||||
#ifndef NDEBUG
|
||||
static int rreq_member_of_list(RREQ rr, RREQ list);
|
||||
#endif
|
||||
|
||||
extern RREQ ardp_pendingQ, ardp_runQ, ardp_doneQ;
|
||||
|
||||
|
||||
/*
|
||||
* rralloc - allocate and initialize an rreq structure
|
||||
*
|
||||
* ardp_rqalloc returns a pointer to an initialized structure of type
|
||||
* RREQ. If it is unable to allocate such a structure, it
|
||||
* returns NOREQ (NULL).
|
||||
*/
|
||||
RREQ
|
||||
ardp_rqalloc()
|
||||
{
|
||||
RREQ rq;
|
||||
|
||||
p_th_mutex_lock(p_th_mutexARDP_RQALLOC);
|
||||
if(lfree) {
|
||||
rq = lfree;
|
||||
lfree = lfree->next;
|
||||
}
|
||||
else {
|
||||
rq = (RREQ) malloc(sizeof(RREQ_ST));
|
||||
if (!rq) return(NOREQ);
|
||||
rreq_max++;
|
||||
}
|
||||
rreq_count++;
|
||||
p_th_mutex_unlock(p_th_mutexARDP_RQALLOC);
|
||||
|
||||
rq->status = ARDP_STATUS_NOSTART;
|
||||
#ifdef ARDP_MY_WINDOW_SZ
|
||||
rq->flags = ARDP_FLAG_SEND_MY_WINDOW_SIZE; /* used by clients. */
|
||||
#else
|
||||
rq->flags = 0;
|
||||
#endif
|
||||
rq->cid = 0;
|
||||
rq->priority = ardp_priority;
|
||||
rq->pf_priority = 0;
|
||||
rq->peer_ardp_version = 0;
|
||||
rq->inpkt = NOPKT;
|
||||
rq->rcvd_tot = 0;
|
||||
rq->rcvd = NOPKT;
|
||||
rq->rcvd_thru = 0;
|
||||
#ifdef ARDP_MY_WINDOW_SZ /* This sets the window size we'll ask for */
|
||||
rq->window_sz = ARDP_MY_WINDOW_SZ;
|
||||
#else
|
||||
rq->window_sz = 0;
|
||||
#endif
|
||||
rq->pwindow_sz = ARDP_DEFAULT_WINDOW_SZ; /* sets the window size we assume
|
||||
our peer will accept in the
|
||||
absence of an explicit
|
||||
request. */
|
||||
rq->comp_thru = NOPKT;
|
||||
rq->outpkt = NOPKT;
|
||||
rq->trns_tot = 0;
|
||||
rq->trns = NOPKT;
|
||||
rq->prcvd_thru = 0;
|
||||
bzero(&(rq->peer),sizeof(rq->peer));
|
||||
rq->rcvd_time.tv_sec = 0;
|
||||
rq->rcvd_time.tv_usec = 0;
|
||||
rq->svc_start_time.tv_sec = 0;
|
||||
rq->svc_start_time.tv_usec = 0;
|
||||
rq->svc_comp_time.tv_sec = 0;
|
||||
rq->svc_comp_time.tv_usec = 0;
|
||||
rq->timeout.tv_sec = ardp_default_timeout;
|
||||
rq->timeout.tv_usec = 0;
|
||||
rq->timeout_adj.tv_sec = ardp_default_timeout;
|
||||
rq->timeout_adj.tv_usec = 0;
|
||||
rq->wait_till.tv_sec = 0;
|
||||
rq->wait_till.tv_usec = 0;
|
||||
rq->retries = ardp_default_retry;
|
||||
rq->retries_rem = ardp_default_retry;
|
||||
rq->svc_rwait = 0;
|
||||
rq->svc_rwait_seq = 0;
|
||||
rq->inf_queue_pos = 0;
|
||||
rq->inf_sys_time = 0;
|
||||
#ifdef PROSPERO
|
||||
rq->auth_info = NULL;
|
||||
#endif /* PROSPERO */
|
||||
rq->client_name = NULL;
|
||||
rq->peer_sw_id = NULL;
|
||||
rq->cfunction = NULL;
|
||||
rq->cfunction_args = NULL;
|
||||
rq->previous = NOREQ;
|
||||
rq->next = NOREQ;
|
||||
return(rq);
|
||||
}
|
||||
|
||||
/*
|
||||
* ardp_rqfree - free a RREQ structure
|
||||
*
|
||||
* ardp_rqfree takes a pointer to a RREQ structure and adds it to
|
||||
* the free list for later reuse.
|
||||
*/
|
||||
void ardp_rqfree(rq)
|
||||
RREQ rq;
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
/* This is different from the way we do consistency checking in the PFS
|
||||
library, because here the status field is just sitting to be used. */
|
||||
assert(rq->status != ARDP_STATUS_FREE);
|
||||
rq->status = ARDP_STATUS_FREE;
|
||||
CHECK_OFFLIST(rq); /* MITRA macro; probably does the same as those
|
||||
listed below. Might never be defined. */
|
||||
assert(!rreq_member_of_list(rq, ardp_pendingQ));
|
||||
assert(!rreq_member_of_list(rq, ardp_runQ));
|
||||
assert(!rreq_member_of_list(rq, ardp_doneQ));
|
||||
#endif
|
||||
/* Don't free inpkt or comp_thru, already on rcvd */
|
||||
if(rq->rcvd) ardp_ptlfree(rq->rcvd);
|
||||
/* But outpkt has not been added to trns */
|
||||
if(rq->outpkt) ardp_ptlfree(rq->outpkt);
|
||||
if(rq->trns) ardp_ptlfree(rq->trns);
|
||||
#ifdef PROSPERO
|
||||
if (rq->auth_info) pafree(rq->auth_info);
|
||||
#endif /* PROSPERO */
|
||||
if (rq->client_name) stfree(rq->client_name);
|
||||
if (rq->peer_sw_id) stfree(rq->peer_sw_id);
|
||||
|
||||
p_th_mutex_lock(p_th_mutexARDP_RQALLOC);
|
||||
rq->next = lfree;
|
||||
rq->previous = NOREQ;
|
||||
lfree = rq;
|
||||
rreq_count--;
|
||||
p_th_mutex_unlock(p_th_mutexARDP_RQALLOC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Free just the fields that are needed only while processing the request
|
||||
but not the fields that will be used for a request that is on the ardp_doneQ
|
||||
so that the results can be retransmitted. This is only needed when
|
||||
debugging the server. It is used in ardp_respond() and is #ifdef'd NDEBUG.
|
||||
*/
|
||||
void
|
||||
ardp_rq_partialfree(RREQ rq)
|
||||
{
|
||||
#ifdef PROSPERO
|
||||
if (rq->auth_info) { pafree(rq->auth_info); rq->auth_info = NULL; }
|
||||
#endif /* PROSPERO */
|
||||
if (rq->client_name) { stfree(rq->client_name); rq->client_name = NULL; }
|
||||
if (rq->peer_sw_id) { stfree(rq->peer_sw_id); rq->peer_sw_id = NULL; }
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* ardp_rqlfree - free many RREQ structures
|
||||
*
|
||||
* ardp_rqlfree takes a pointer to a RREQ structure frees it and any linked
|
||||
* RREQ structures. It is used to free an entrie list of RREQ
|
||||
* structures.
|
||||
*/
|
||||
|
||||
void
|
||||
ardp_rqlfree(rq)
|
||||
RREQ rq;
|
||||
{
|
||||
RREQ nxt;
|
||||
|
||||
while(rq != NOREQ) {
|
||||
nxt = rq->next;
|
||||
ardp_rqfree(rq);
|
||||
rq = nxt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ardp_set_retry - change default values for timeout
|
||||
*
|
||||
* ardp_set_retry takes a value for timout in seconds and a count
|
||||
* of the number of retries to allow. It sets static variables in this
|
||||
* file used by pralloc to set the default values in request structures
|
||||
* it allocates.
|
||||
*/
|
||||
int
|
||||
ardp_set_retry(int to, int rt)
|
||||
{
|
||||
/* XXX This is a critical section, but it is safe as long as we are not on
|
||||
a multiprocessor and don't block. So no mutexes. */
|
||||
ardp_default_timeout = to;
|
||||
ardp_default_retry = rt;
|
||||
/*** XXX End Critical section */
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Return 1 if the RREQ rr is a member of the list LIST. */
|
||||
static int
|
||||
rreq_member_of_list(RREQ rr, RREQ list)
|
||||
{
|
||||
for ( ; list; list = list->next) {
|
||||
if (rr == list) return 1;
|
||||
}
|
||||
return 0; /* false */
|
||||
}
|
||||
#endif
|
||||
305
prospero/lib/ardp/ardp_send.c
Normal file
305
prospero/lib/ardp/ardp_send.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright (c) 1991-1993 by the University of Southern California
|
||||
*
|
||||
* Written by bcn 1989-92 as dirsend.c in the Prospero distribution
|
||||
* Modified by bcn 1/93 separate library and add support for asynchrony
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ardp.h>
|
||||
#include <perrno.h>
|
||||
#include <pmachine.h>
|
||||
|
||||
#define OLD_GETHOSTBYNAME /* do it the old way, since we're on the client
|
||||
*/
|
||||
#ifdef PROSPERO
|
||||
#include <pcompat.h>
|
||||
#else /* not PROSPERO */
|
||||
#define DISABLE_PFS_START()
|
||||
#define DISABLE_PFS_END()
|
||||
#endif /* not PROSPERO */
|
||||
|
||||
RREQ ardp_activeQ = NOREQ; /* Info about active requests */
|
||||
RREQ ardp_completeQ = NOREQ;/* Completed requests */
|
||||
static unsigned short ardp_def_port_no = 0; /* Default UDP port to use */
|
||||
int ardp_port = -1; /* Opened UDP port */
|
||||
|
||||
extern int pfs_debug; /* Debug level */
|
||||
|
||||
static ardp_init();
|
||||
static short ardp_next_cid();
|
||||
|
||||
/*
|
||||
* ardp_send - send a request and possibly wait for response
|
||||
*
|
||||
* ardp_send takes a pointer to a structure of type RREQ, an optional
|
||||
* hostname, an optional pointer to the desination address, and the time to
|
||||
* wait before returning in microseconds.
|
||||
*
|
||||
* If a destination address was specified, the address is inserted
|
||||
* into the RREQ structure. If not, but a hostname was specified, the
|
||||
* hostname is resolved, and its address inserted into the RREQ
|
||||
* structure. The hostname may be followed by a port number in
|
||||
* parentheses in which case the port field is filled in. If not
|
||||
* specified, the Prospero directory server port is used as the default.
|
||||
* If the host address is a non-null pointer to an empty address, then
|
||||
* the address is also filled in.
|
||||
*
|
||||
* ardp_send then sends the packets specified by the request structure
|
||||
* to the address in the request structure. If the time to wait is
|
||||
* -1, it waits until the complete response has been received and
|
||||
* returns PSUCCESS or PFAILURE depending on the outcome. Any
|
||||
* returned packets are left in the RREQ strucure. If the time to
|
||||
* wait is 0, ardp_send returns immediately. The prereq strucure will
|
||||
* be filled in as the response is received if calls are made to
|
||||
* ardp_check_messages (which may be called by an interrupt, or
|
||||
* explicitly at appropriate points in the application. If the time
|
||||
* to wait is positive, then ardp_send waits the specified lenght of
|
||||
* time before returning.
|
||||
*
|
||||
* If ardp_send returns before the complete response has been
|
||||
* received, it returns ARDP_PENDING (-1). This means that only
|
||||
* the status field in the RREQ structure may be used until the status
|
||||
* field indicates ARDP_STATUS_COMPLETE. In no event shall it be legal
|
||||
* for the application to modify fields in the RREQ structure while a
|
||||
* request is pending. If the request completes during the call to
|
||||
* ardp_send, it returns ARDP_SUCCESS (0). On error, a positive
|
||||
* return or status value indicates the error that occured.
|
||||
*
|
||||
* In attempting to obtain the response, the ARDP library will wait
|
||||
* for a response and retry an appropriate number of times as defined
|
||||
* by timeout and retries (both static variables). It will collect
|
||||
* however many packets form the reply, and return them in the
|
||||
* request structue.
|
||||
*
|
||||
* ARGS: req Request structure holding packets to send
|
||||
* and to receive the response
|
||||
* hname Hostname including optional port in parentheses
|
||||
* dest Pointer to destination address
|
||||
* ttwait Time to wait in microseconds
|
||||
*
|
||||
* MODIFIES: dest If pointer to empty address
|
||||
* req Fills in ->recv and frees ->trns
|
||||
*
|
||||
* NOTE: In preparing packets for transmission, the packets
|
||||
* are modified. Once the full response has been received,
|
||||
* the packets that were sent are freed.
|
||||
*/
|
||||
int
|
||||
ardp_send(RREQ req, /* Request structure to use (in, out) */
|
||||
char *dname, /* Hostname (and port) of destination */
|
||||
struct sockaddr_in *dest, /* Pointer to destination address */
|
||||
int ttwait) /* Time to wait in microseconds */
|
||||
{
|
||||
char hostnoport[400];/* Hostname without port */
|
||||
char *openparen; /* Start of port in dname */
|
||||
int req_udp_port; /* UDP port from hostname */
|
||||
#ifdef OLD_GETHOSTBYNAME /* unused */
|
||||
struct hostent *host; /* Host info from gethostbyname */
|
||||
#endif
|
||||
|
||||
PTEXT ptmp; /* Temporary packet pointer */
|
||||
int DpfStmp; /* Used when disabling prospero */
|
||||
int tmp; /* To temporarily hold return values */
|
||||
|
||||
p_clear_errors();
|
||||
|
||||
if((ardp_port < 0) && (tmp = ardp_init())) return(tmp);
|
||||
|
||||
if(req->status == ARDP_STATUS_FREE) {
|
||||
fprintf(stderr,"Attempt to send free RREQ\n");
|
||||
abort();
|
||||
return(perrno = ARDP_BAD_REQ);
|
||||
}
|
||||
|
||||
while(req->outpkt) {
|
||||
req->outpkt->seq = ++(req->trns_tot);
|
||||
ptmp = req->outpkt;
|
||||
EXTRACT_ITEM(ptmp,req->outpkt);
|
||||
APPEND_ITEM(ptmp,req->trns);
|
||||
}
|
||||
|
||||
if(pfs_debug >= 9) {
|
||||
fprintf(stderr, "In ardp_send - sending to %s\n", dname);
|
||||
ptmp = req->trns;
|
||||
while(ptmp) {
|
||||
fprintf(stderr,"Packet %d:\n",ptmp->seq);
|
||||
ardp_showbuf(ptmp->text, ptmp->length, stderr);
|
||||
putc('\n', stderr);
|
||||
ptmp = ptmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign connection ID */
|
||||
req->cid = ardp_next_cid();
|
||||
|
||||
/* Resolve the host name, address, and port arguments */
|
||||
|
||||
/* If we were given the host address, then use it. Otherwise */
|
||||
/* lookup the hostname. If we were passed a host address of */
|
||||
/* 0, we must lookup the host name, then replace the old value */
|
||||
if(!dest || (dest->sin_addr.s_addr == 0)) {
|
||||
/* I we have a null host name, return an error */
|
||||
if((dname == NULL) || (*dname == '\0')) {
|
||||
if (pfs_debug >= 1)
|
||||
fprintf(stderr, "ardp_send: Null hostname specified\n");
|
||||
return(perrno = ARDP_BAD_HOSTNAME);
|
||||
}
|
||||
/* If a port is included, save it away */
|
||||
if(openparen = strchr(dname,'(')) {
|
||||
sscanf(openparen+1,"%d",&req_udp_port);
|
||||
if(req_udp_port) req->peer_port = htons(req_udp_port);
|
||||
strncpy(hostnoport,dname,399);
|
||||
if((openparen - dname) < 400) {
|
||||
*(hostnoport + (openparen - dname)) = '\0';
|
||||
dname = hostnoport;
|
||||
}
|
||||
}
|
||||
#ifdef OLD_GETHOSTBYNAME
|
||||
DISABLE_PFS_START();
|
||||
assert(P_IS_THIS_THREAD_MASTER());
|
||||
if((host = gethostbyname(dname)) == NULL) {
|
||||
DISABLE_PFS_END();
|
||||
/* Check if a numeric address */
|
||||
req->peer.sin_family = AF_INET;
|
||||
req->peer_addr.s_addr = inet_addr(dname);
|
||||
if(req->peer_addr.s_addr == -1) {
|
||||
if (pfs_debug >= 1)
|
||||
fprintf(stderr, "ardp: Can't resolve host %s\n", dname);
|
||||
return(perrno = ARDP_BAD_HOSTNAME);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DISABLE_PFS_END();
|
||||
req->peer.sin_family = host->h_addrtype;
|
||||
bcopy(host->h_addr, (char *)&(req->peer_addr),
|
||||
host->h_length);
|
||||
}
|
||||
#else
|
||||
/* New way of doing things */
|
||||
if (ardp_hostname2addr(dname, &req->peer_addr))
|
||||
return perrno = ARDP_BAD_HOSTNAME;
|
||||
|
||||
#endif
|
||||
}
|
||||
else bcopy(dest, &(req->peer), S_AD_SZ);
|
||||
|
||||
/* If no port set, use default port */
|
||||
if(req->peer_port == 0) req->peer_port = ardp_def_port_no;
|
||||
|
||||
/* If dest was set, but zero, fill it in */
|
||||
if(dest && (dest->sin_addr.s_addr == 0))
|
||||
bcopy(&(req->peer), dest, S_AD_SZ);
|
||||
|
||||
if(tmp = ardp_headers(req)) return(tmp);
|
||||
|
||||
req->status = ARDP_STATUS_ACTIVE;
|
||||
APPEND_ITEM(req,ardp_activeQ);
|
||||
req->wait_till.tv_sec = time(NULL) + req->timeout_adj.tv_sec;
|
||||
ardp_xmit(req, req->pwindow_sz);
|
||||
return(ardp_retrieve(req,ttwait));
|
||||
}
|
||||
|
||||
/*
|
||||
* ardp_init - Open socket and bind port for network operations
|
||||
*
|
||||
* ardp_init attempts to determine the default destination port.
|
||||
* It then opens a socket for network operations and attempts
|
||||
* to bind it to an available privleged port. It tries to bind to a
|
||||
* privileged port so that its peer can tell it is communicating with
|
||||
* a "trusted" program. If it can not bind a priveleged port, then
|
||||
* it also returns successfully since the system will automatically
|
||||
* assign a non-priveleged port later, in which case the peer will
|
||||
* assume that it is communicating with a non-trusted program. It
|
||||
* is expected that in the normal case, we will fail to bind the
|
||||
* port since most applications calling this routine should NOT
|
||||
* be setuid.
|
||||
*/
|
||||
static int
|
||||
ardp_init()
|
||||
{
|
||||
struct servent *sp; /* Entry from services file */
|
||||
struct sockaddr_in us; /* Our address */
|
||||
int DpfStmp;/* Used when disabling prospero */
|
||||
int tmp; /* For stepping through ports */
|
||||
|
||||
/* Determine default udp port to use */
|
||||
DISABLE_PFS_START();
|
||||
assert(P_IS_THIS_THREAD_MASTER()); /*SOLARIS: getservbyname MT-Unsafe */
|
||||
if ((sp = getservbyname(ARDP_DEFAULT_PEER,"udp")) == 0) {
|
||||
if (pfs_debug >= 10)
|
||||
fprintf(stderr, "ardp: udp/%s unknown service - using %d\n",
|
||||
ARDP_DEFAULT_PEER, ARDP_DEFAULT_PORT);
|
||||
ardp_def_port_no = htons((u_short) ARDP_DEFAULT_PORT);
|
||||
}
|
||||
else ardp_def_port_no = sp->s_port;
|
||||
DISABLE_PFS_END();
|
||||
if (pfs_debug >= 10)
|
||||
fprintf(stderr,"default udp port is %d\n", ntohs(ardp_def_port_no));
|
||||
|
||||
|
||||
/* Open the local socket from which packets will be sent */
|
||||
errno=0;
|
||||
if((ardp_port = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
if (pfs_debug >= 1)
|
||||
fprintf(stderr,"ardp: Can't open socket - %s\n",
|
||||
unixerrstr());
|
||||
return(perrno = ARDP_UDP_CANT);
|
||||
}
|
||||
|
||||
#ifndef ARDP_NONPRIVED
|
||||
/* Try to bind it to a privileged port - loop through candidate */
|
||||
/* ports trying to bind. If failed, that's OK, we will let the */
|
||||
/* system assign a non-privileged port later */
|
||||
bzero((char *)&us, sizeof(us));
|
||||
us.sin_family = AF_INET;
|
||||
for(tmp = ARDP_FIRST_PRIVP; tmp < ARDP_FIRST_PRIVP+ARDP_NUM_PRIVP;tmp++) {
|
||||
us.sin_port = htons((u_short) tmp);
|
||||
if(bind(ardp_port, (struct sockaddr *)&us, sizeof(us)) == 0)
|
||||
return(ARDP_SUCCESS);
|
||||
if(errno != EADDRINUSE) return(ARDP_SUCCESS);
|
||||
}
|
||||
#endif /* ARDP_NONPRIVED */
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* ardp_next_cid - return next connection ID in network byte order
|
||||
*
|
||||
* ardp_next_cid returns the next connection ID to be used
|
||||
* after first converting it to network byte order.
|
||||
*/
|
||||
static short ardp_next_cid()
|
||||
{
|
||||
static unsigned short next_conn_id = 0; /* Next conn id to use */
|
||||
static int last_pid = 0; /* Reset after forks */
|
||||
int pid = getpid();
|
||||
|
||||
/* If we did a fork, reinitialize */
|
||||
if(last_pid != pid) {
|
||||
if(ardp_port >= 0) close(ardp_port);
|
||||
ardp_port = -1;
|
||||
next_conn_id = 0;
|
||||
ardp_init();
|
||||
}
|
||||
/* Find first connection ID */
|
||||
assert(P_IS_THIS_THREAD_MASTER()); /* rand and srand are unsafe */
|
||||
if(next_conn_id == 0) {
|
||||
srand(pid+time(0));
|
||||
next_conn_id = rand();
|
||||
last_pid = pid;
|
||||
}
|
||||
if(++next_conn_id == 0) ++next_conn_id;
|
||||
return(htons(next_conn_id));
|
||||
}
|
||||
61
prospero/lib/ardp/ardp_showbuf.c
Normal file
61
prospero/lib/ardp/ardp_showbuf.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern Calfornia
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static void showc(char c, FILE *outf);
|
||||
|
||||
/* Return non-zero if string ends in a newline. */
|
||||
/* Like fputs, but for bstrings. */
|
||||
void
|
||||
ardp_showbuf(const char *bst, int len, FILE *out)
|
||||
{
|
||||
while (len-- > 0) {
|
||||
showc(*bst++, out);
|
||||
}
|
||||
}
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
extern int pfs_debug;
|
||||
|
||||
static void
|
||||
showc(char c, FILE *outf)
|
||||
{
|
||||
if (c == '\\') {
|
||||
putc('\\', outf);
|
||||
putc('\\', outf);
|
||||
} else if (isprint(c)) {
|
||||
putc(c, outf);
|
||||
} else if ((c == '\n')) {
|
||||
if (pfs_debug >= 11) {
|
||||
putc('\\', outf);
|
||||
putc('n', outf);
|
||||
} else {
|
||||
putc('\n', outf);
|
||||
}
|
||||
} else if ((c == '\t')) {
|
||||
if (pfs_debug >= 11) {
|
||||
putc('\\', outf);
|
||||
putc('t', outf);
|
||||
} else {
|
||||
putc('\t', outf);
|
||||
}
|
||||
} else if ((c == '\r')) {
|
||||
if (pfs_debug >= 11) {
|
||||
putc('\\', outf);
|
||||
putc('r', outf);
|
||||
} else {
|
||||
putc('\r', outf);
|
||||
}
|
||||
} else {
|
||||
fprintf(outf, "\\%#03o", c);
|
||||
}
|
||||
}
|
||||
47
prospero/lib/ardp/ardp_snd_pkt.c
Normal file
47
prospero/lib/ardp/ardp_snd_pkt.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>.
|
||||
*
|
||||
* Written by bcn 1/93 to send a single packet to a peer
|
||||
*/
|
||||
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ardp.h>
|
||||
#include <plog.h>
|
||||
#include <errno.h>
|
||||
#include <perrno.h>
|
||||
|
||||
extern int ardp_srvport;
|
||||
extern int ardp_prvport;
|
||||
|
||||
/*
|
||||
* ardp_snd_pkt - transmits a single packet to address in req
|
||||
*
|
||||
* ardp_snd_pkt takes a pointer to a packet of type PTEXT to be
|
||||
* sent to a peer identified by req->peer. It then send the packet to
|
||||
* the peer. If the packet was sent successfully, ARDP_SUCCESS is
|
||||
* returned. Successful transmission of the packet does not provide
|
||||
* any assurance of receipt by the peer. If the attempt to send
|
||||
* the packet fails, ARDP_NOT_SENT is returned.
|
||||
*/
|
||||
int
|
||||
ardp_snd_pkt(pkt,req)
|
||||
PTEXT pkt;
|
||||
RREQ req;
|
||||
{
|
||||
int sent;
|
||||
|
||||
sent = sendto(((ardp_prvport != -1) ? ardp_prvport : ardp_srvport),
|
||||
pkt->start, pkt->length, 0, &(req->peer), S_AD_SZ);
|
||||
|
||||
if(sent == pkt->length) return(ARDP_SUCCESS);
|
||||
|
||||
plog(L_NET_ERR, req, "Attempt to send message failed (errno %d %s)",
|
||||
errno, unixerrstr(), 0);
|
||||
|
||||
return(ARDP_NOT_SENT);
|
||||
}
|
||||
107
prospero/lib/ardp/ardp_srv_ini.c
Normal file
107
prospero/lib/ardp/ardp_srv_ini.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 1991 by the University of Washington
|
||||
* Copyright (c) 1992, 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the files
|
||||
* <uw-copyright.h> and <usc-copyr.h>.
|
||||
*
|
||||
* Written by bcn 1991 as part of rdgram.c in Prospero distribution
|
||||
* Modified by bcn 1/93 modularized and incorporated into new ardp library
|
||||
*/
|
||||
|
||||
#include <uw-copyright.h>
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ardp.h>
|
||||
#include <plog.h>
|
||||
|
||||
int (*ardp_pri_func)() = NULL; /* Function to compare priorities */
|
||||
int ardp_pri_override = 0; /* If 1, then oveeride value in request */
|
||||
|
||||
int ardp_srvport = -1;
|
||||
int ardp_prvport = -1;
|
||||
|
||||
|
||||
/*
|
||||
* ardp_set_queueing_plicy - set function for queueing policy
|
||||
*
|
||||
* ardp_set_queuing_policy allows one to provide a function that will set
|
||||
* priorities for requests. When passed two req structures, r1 and r2, the
|
||||
* function should return a negative number if r1 should be executed first
|
||||
* (i.e. r1 has a lower numerical priority) and positive if r2 should be
|
||||
* executed first. If the function returns 0, it means the two have the
|
||||
* same priority and should be executed FCFS. If override is non-zero, then
|
||||
* the priority function is to be applied to all requests. If non-zero,
|
||||
* it is only applied to those with identical a priori priorities (as
|
||||
* specified in the datagram itself.
|
||||
*/
|
||||
int
|
||||
ardp_set_queuing_policy(pf,override)
|
||||
int (*pf)(); /* Function to compare priorities */
|
||||
int override; /* If 1, then oveeride value in request */
|
||||
{
|
||||
ardp_pri_func = pf;
|
||||
ardp_pri_override = override;
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
ardp_set_prvport(port)
|
||||
int port;
|
||||
{
|
||||
ardp_prvport = port;
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
ardp_bind_port(portname)
|
||||
char *portname;
|
||||
{
|
||||
struct sockaddr_in s_in = {AF_INET};
|
||||
struct servent *sp;
|
||||
int on = 1;
|
||||
int port_no = 0;
|
||||
|
||||
assert(P_IS_THIS_THREAD_MASTER()); /*getpwuid MT-Unsafe*/
|
||||
if(*portname == '#') {
|
||||
sscanf(portname+1,"%d",&port_no);
|
||||
if(port_no == 0) {
|
||||
fprintf(stderr, "ardp_bind_port: port number must follow #\n");
|
||||
exit(1);
|
||||
}
|
||||
s_in.sin_port = htons((ushort) port_no);
|
||||
}
|
||||
else if((sp = getservbyname(portname, "udp")) != NULL) {
|
||||
s_in.sin_port = sp->s_port;
|
||||
}
|
||||
else if(strcmp(portname,ARDP_DEFAULT_PEER) == 0) {
|
||||
fprintf(stderr, "ardp_bind_port: udp/%s unknown service - using %d\n",
|
||||
ARDP_DEFAULT_PEER, ARDP_DEFAULT_PORT);
|
||||
s_in.sin_port = htons((ushort) ARDP_DEFAULT_PORT);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "ardp_bind_port: udp/%s unknown service\n",portname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((ardp_srvport = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
plog(L_STATUS,NOREQ,"Startup - Can't open socket",0);
|
||||
fprintf(stderr, "ardp_bind_port: Can't open socket\n");
|
||||
exit(1);
|
||||
}
|
||||
if (setsockopt(ardp_srvport, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
|
||||
fprintf(stderr, "dirsrv: setsockopt (SO_REUSEADDR)\n");
|
||||
|
||||
if (bind(ardp_srvport, (struct sockaddr *) &s_in, S_AD_SZ) < 0) {
|
||||
plog(L_STATUS,NOREQ,"Startup - Can't bind socket",0);
|
||||
fprintf(stderr, "dirsrv: Can not bind socket\n");
|
||||
exit(1);
|
||||
}
|
||||
return(ntohs(s_in.sin_port));
|
||||
}
|
||||
|
||||
103
prospero/lib/ardp/ardp_xmit.c
Normal file
103
prospero/lib/ardp/ardp_xmit.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*
|
||||
* Written by bcn 1/93 to send a list of packets to a destination
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ardp.h>
|
||||
#include <pmachine.h> /* for bcopy() and select() */
|
||||
|
||||
extern int pfs_debug; /* Debug level */
|
||||
extern int ardp_port; /* Opened UDP port */
|
||||
|
||||
/*
|
||||
* ardp_xmit - transmits packets in req->trns
|
||||
*
|
||||
* ardp_xmit takes a pointer to a request structure of type RREQ and a
|
||||
* window size. It then sends the packet on the request structure
|
||||
* transmit queue to the peer address in the request structure starting after
|
||||
* the indicated peer rcvd_thru value, and up to the number of packets
|
||||
* specified by the window size. It returns ARDP_SUCCESS on success and
|
||||
* returns an error code on failure.
|
||||
*
|
||||
* This is called on both the client and server side, called respectively by
|
||||
* ardp_send() and ardp_pr_actv().
|
||||
*/
|
||||
|
||||
int
|
||||
ardp_xmit(RREQ req, /* Request structure with packets to send */
|
||||
int window) /* Max packets to send at once. Note that
|
||||
right now this is always identical to
|
||||
req->pwindow_sz.
|
||||
0 means infinite window size
|
||||
-1 means just send an ACK; don't send any
|
||||
data packets. */
|
||||
{
|
||||
PTEXT ptmp; /* Packet pointer for stepping through trns */
|
||||
unsigned short stmp; /* Temp short for conversions */
|
||||
int ns; /* Number of bytes actually sent */
|
||||
static PTEXT ack = NOPKT; /* Only an ack to be sent */
|
||||
|
||||
if(window < 0 || req->prcvd_thru >= req->trns_tot) {
|
||||
/* All our packets got through, send acks only */
|
||||
if(ack == NOPKT) {
|
||||
ack = ardp_ptalloc();
|
||||
/* Add header */
|
||||
ack->start -= 9;
|
||||
ack->length += 9;
|
||||
*(ack->start) = (char) 9;
|
||||
/* An unsequenced control packet */
|
||||
bzero4(ack->start+3);
|
||||
}
|
||||
/* Received Through */
|
||||
stmp = htons(req->rcvd_thru);
|
||||
bcopy2(&stmp,ack->start+7);
|
||||
/* Connection ID */
|
||||
bcopy2(&(req->cid),ack->start+1);
|
||||
ptmp = ack;
|
||||
}
|
||||
else ptmp = req->trns;
|
||||
|
||||
/* Note that we don't want to get rid of packts before the */
|
||||
/* peer received through since the peer might later tell */
|
||||
/* us it forgot them and ask us to send them again */
|
||||
/* XXX whether this is allowable should be an application */
|
||||
/* specific configration option. */
|
||||
while(ptmp) {
|
||||
if((window > 0) && (ptmp->seq > req->prcvd_thru + window)) break;
|
||||
if((ptmp->seq == 0) || (ptmp->seq > req->prcvd_thru)) {
|
||||
if (pfs_debug >= 6) {
|
||||
if (req->peer.sin_family == AF_INET)
|
||||
fprintf(stderr,
|
||||
"Sending message%s (cid=%d) (seq=%d) to %s(%d)...",
|
||||
(ptmp == ack) ? " (ACK only)" : "",
|
||||
ntohs(req->cid), ntohs(ptmp->seq),
|
||||
inet_ntoa(req->peer_addr), PEER_PORT(req));
|
||||
else fprintf(stderr,"Sending message...");
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
ns = sendto(ardp_port,(char *)(ptmp->start), ptmp->length, 0,
|
||||
&(req->peer), S_AD_SZ);
|
||||
if(ns != ptmp->length) {
|
||||
if (pfs_debug >= 1) {
|
||||
fprintf(stderr,"\nsent only %d/%d: ",ns, ptmp->length);
|
||||
perror("");
|
||||
}
|
||||
return(ARDP_NOT_SENT);
|
||||
}
|
||||
if (pfs_debug >= 6) fprintf(stderr,"Sent.\n");
|
||||
}
|
||||
ptmp = ptmp->next;
|
||||
}
|
||||
return(ARDP_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
0
prospero/lib/ardp/dependency.list
Normal file
0
prospero/lib/ardp/dependency.list
Normal file
72
prospero/lib/ardp/dnscache_alloc.c
Normal file
72
prospero/lib/ardp/dnscache_alloc.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/* Copyright (c) 1993, by Pandora Systems */
|
||||
/* Author: Mitra <mitra@path.net> */
|
||||
/* Allocation code copied and adapted from:
|
||||
prospero/alpha.5.2a+/lib/pfs/flalloc */
|
||||
|
||||
#include "dnscache_alloc.h"
|
||||
#include <pfs.h>
|
||||
#include <pfs_threads.h>
|
||||
#include <mitra_macros.h>
|
||||
|
||||
static DNSCACHE lfree = NULL; /* Free dnscaches */
|
||||
/* These are global variables which will be read by dirsrv.c
|
||||
Too bad C doesn't have better methods for structuring such global data. */
|
||||
|
||||
int dnscache_count = 0;
|
||||
int dnscache_max = 0;
|
||||
|
||||
|
||||
/************* Standard routines to alloc, free and copy *************/
|
||||
/*
|
||||
* dnscache_alloc - allocate and initialize DNSCACHE structure
|
||||
*
|
||||
* returns a pointer to an initialized structure of type
|
||||
* DNSCACHE. If it is unable to allocate such a structure, it
|
||||
* signals out_of_memory();
|
||||
*/
|
||||
|
||||
DNSCACHE
|
||||
dnscache_alloc()
|
||||
{
|
||||
DNSCACHE acache;
|
||||
|
||||
TH_STRUC_ALLOC(dnscache,DNSCACHE,acache);
|
||||
acache->name = NULL;
|
||||
acache->usecount = 0;
|
||||
bzero(&acache->sockad,sizeof(acache->sockad));
|
||||
return(acache);
|
||||
}
|
||||
|
||||
/*
|
||||
* dnscache_free - free a DNSCACHE structure
|
||||
*
|
||||
* dnscache_free takes a pointer to a DNSCACHE structure and adds it to
|
||||
* the free list for later reuse.
|
||||
*/
|
||||
void
|
||||
dnscache_free(DNSCACHE acache)
|
||||
{
|
||||
stfree(acache->name) ; acache->name = NULL;
|
||||
TH_STRUC_FREE(dnscache,DNSCACHE,acache);
|
||||
}
|
||||
|
||||
/*
|
||||
* dnscache_lfree - free a linked list of DNSCACHE structures.
|
||||
*
|
||||
* dnscache_lfree takes a pointer to a dnscache structure frees it and
|
||||
* any linked
|
||||
* DNSCACHE structures. It is used to free an entire list of WAISMSGBUFF
|
||||
* structures.
|
||||
*/
|
||||
void
|
||||
dnscache_lfree(acache)
|
||||
DNSCACHE acache;
|
||||
{
|
||||
TH_STRUC_LFREE(DNSCACHE,acache,dnscache_free);
|
||||
}
|
||||
|
||||
void
|
||||
dnscache_freespares()
|
||||
{
|
||||
TH_FREESPARES(dnscache,DNSCACHE);
|
||||
}
|
||||
33
prospero/lib/ardp/dnscache_alloc.h
Normal file
33
prospero/lib/ardp/dnscache_alloc.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef dnscache_alloc_h
|
||||
#define dnscache_alloc_h
|
||||
|
||||
#include <pfs.h>
|
||||
#include <pfs_threads.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
struct dnscache {
|
||||
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
||||
int consistency;
|
||||
#endif
|
||||
char *name;
|
||||
struct sockaddr_in sockad;
|
||||
int usecount; /* For determining size of cache */
|
||||
struct dnscache *next;
|
||||
struct dnscache *previous;
|
||||
};
|
||||
typedef struct dnscache *DNSCACHE;
|
||||
typedef struct dnscache DNSCACHE_ST;
|
||||
|
||||
extern DNSCACHE dnscache_alloc();
|
||||
extern void dnscache_free(DNSCACHE acache);
|
||||
extern void dnscache_lfree(DNSCACHE acache);
|
||||
extern void dnscache_freespares();
|
||||
extern int dnscache_count, dnscache_max;
|
||||
/*extern DNSCACHE dnscache_copy(DNSCACHE f, int r);*/
|
||||
|
||||
#ifdef PFS_THREADS
|
||||
extern p_th_mutex p_th_mutexDNSCACHE;
|
||||
extern p_th_mutex p_th_mutexALLDNSCACHE;
|
||||
#endif
|
||||
|
||||
#endif /*dnscache_alloc_h*/
|
||||
221
prospero/lib/ardp/flocks.c
Normal file
221
prospero/lib/ardp/flocks.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/* Copyright (c) 1993, by Pandora Systems */
|
||||
/* Author: Mitra <mitra@path.net> */
|
||||
/* Allocation code copied and adapted from:
|
||||
lib/pfs/flalloc.c in the Prospero Alpha.5.2a release. */
|
||||
|
||||
#include <pfs.h>
|
||||
#include <plog.h>
|
||||
#include "flocks.h"
|
||||
|
||||
#include "mitra_macros.h"
|
||||
#ifdef PFS_THREADS
|
||||
extern p_th_mutex p_th_mutexFILES;
|
||||
#endif
|
||||
|
||||
/* FileLocks are currently unused by dirsrv.c, and not linked into the ardp
|
||||
library. So dirsrv will not report on them in replies to a STATUS message.
|
||||
*/
|
||||
|
||||
static FILELOCK lfree = NULL; /* Free filelocks */
|
||||
/* These are global variables which will be read by dirsrv.c
|
||||
Too bad C doesn't have better methods for structuring such global data. */
|
||||
|
||||
int filelock_count = 0;
|
||||
int filelock_max = 0;
|
||||
int filelock_open = 0;
|
||||
int filelock_open_max = 0;
|
||||
int filelock_sepwaits = 0;
|
||||
int filelock_secwaits = 0;
|
||||
FILELOCK filelock_locked = NULL;
|
||||
|
||||
/************* Standard routines to alloc, free and copy *************/
|
||||
/*
|
||||
* filelock_alloc - allocate and initialize FILELOCK structure
|
||||
*
|
||||
* returns a pointer to an initialized structure of type
|
||||
* FILELOCK. If it is unable to allocate such a structure, it
|
||||
* signals out_of_memory();
|
||||
*/
|
||||
|
||||
FILELOCK
|
||||
filelock_alloc()
|
||||
{
|
||||
FILELOCK fl;
|
||||
|
||||
TH_STRUC_ALLOC(filelock,FILELOCK,fl);
|
||||
fl->name = NULL;
|
||||
fl->readers = 0;
|
||||
return(fl);
|
||||
}
|
||||
|
||||
/*
|
||||
* filelock_free - free a FILELOCK structure
|
||||
*
|
||||
* filelock_free takes a pointer to a FILELOCK structure and adds it to
|
||||
* the free list for later reuse.
|
||||
*/
|
||||
void
|
||||
filelock_free(FILELOCK fl)
|
||||
{
|
||||
stfree(fl->name); fl->name = NULL;
|
||||
fl->readers = 0;
|
||||
TH_STRUC_FREE(filelock, FILELOCK, fl);
|
||||
}
|
||||
|
||||
/*
|
||||
* filelock_lfree - free a linked list of FILELOCK structures.
|
||||
*
|
||||
* filelock_lfree takes a pointer to a filelock structure frees it and
|
||||
* any linked
|
||||
* FILELOCK structures. It is used to free an entire list of FILELOCK
|
||||
* structures.
|
||||
*/
|
||||
void
|
||||
filelock_lfree(fl)
|
||||
FILELOCK fl;
|
||||
{
|
||||
TH_STRUC_LFREE(FILELOCK,fl,filelock_free);
|
||||
}
|
||||
|
||||
static void
|
||||
filelock_unreaders(FILELOCK flock)
|
||||
{
|
||||
/* Assumes p_th_mutexFILES is locked already */
|
||||
assert(flock->readers > 0);
|
||||
if (!(--flock->readers)) {
|
||||
EXTRACT_ITEM(flock,filelock_locked);
|
||||
filelock_free(flock);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
filelock_unwriters(FILELOCK flock)
|
||||
{
|
||||
/* Assumes p_th_mutexFILES is locked already */
|
||||
assert(flock->readers == -1);
|
||||
EXTRACT_ITEM(flock, filelock_locked);
|
||||
filelock_free(flock);
|
||||
}
|
||||
|
||||
void
|
||||
filelock_freespares()
|
||||
/* This is used for filelocks to free up space in the child */
|
||||
{
|
||||
TH_FREESPARES(filelock,FILELOCK);
|
||||
}
|
||||
|
||||
void
|
||||
filelock_release(const char *filename, int readonly)
|
||||
{
|
||||
FILELOCK flock;
|
||||
p_th_mutex_lock(p_th_mutexFILES);
|
||||
flock = filelock_locked;
|
||||
FIND_FNCTN_LIST(flock, name, filename, stequal);
|
||||
assert(flock); /* it better be locked */
|
||||
if (readonly) {
|
||||
filelock_unreaders(flock); /* May destroy flock */
|
||||
} else {
|
||||
filelock_unwriters(flock); /* May destroy flock */
|
||||
}
|
||||
filelock_open--;
|
||||
p_th_mutex_unlock(p_th_mutexFILES);
|
||||
}
|
||||
|
||||
int
|
||||
locked_fclose_A(FILE *afile, const char *filename, int readonly)
|
||||
{
|
||||
int retval;
|
||||
/* Assumes already obtained filelock for filename */
|
||||
retval = fclose(afile);
|
||||
/* At least on solaris, this can return an error for no apparent reason */
|
||||
#if 0
|
||||
assert(!retval);
|
||||
#endif
|
||||
filelock_release(filename, readonly);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
void
|
||||
filelock_obtain(const char *filename, int readonly)
|
||||
{
|
||||
FILELOCK(flock);
|
||||
int haswaited = 0;
|
||||
for (;;) {
|
||||
p_th_mutex_lock(p_th_mutexFILES);
|
||||
flock = filelock_locked;
|
||||
FIND_FNCTN_LIST(flock, name, filename,stequal);
|
||||
if (!flock) { /* didnt find a matching lock */
|
||||
flock = filelock_alloc();
|
||||
flock->name = stcopy(filename);
|
||||
flock->readers = 0;
|
||||
APPEND_ITEM(flock,filelock_locked);
|
||||
}
|
||||
/* Found, or created a matching lock */
|
||||
if (readonly) {
|
||||
if (flock->readers >= 0) {
|
||||
flock->readers++;
|
||||
break;
|
||||
}
|
||||
/* Drops thru here, if we want it readonly, but someone else writing*/
|
||||
} else {
|
||||
if (flock->readers == 0) {
|
||||
flock->readers = -1; /* Special code for writer */
|
||||
break;
|
||||
}
|
||||
/* Drops thru here, if we want to write, but someone else
|
||||
is reading/writing */
|
||||
}
|
||||
/* At this point we cant lock it, so unlock mutex, wait, and try again*/
|
||||
p_th_mutex_unlock(p_th_mutexFILES);
|
||||
plog(L_QUEUE_INFO,NOREQ, "Waiting for filelock for %s", filename, 0);
|
||||
if (!haswaited) filelock_sepwaits++;
|
||||
filelock_secwaits++;
|
||||
sleep(1); /* Maybe too long */
|
||||
} /*for*/
|
||||
if (++filelock_open > filelock_open_max) {
|
||||
filelock_open_max = filelock_open;
|
||||
}
|
||||
/* break is always done with mutex locked */
|
||||
p_th_mutex_unlock(p_th_mutexFILES);
|
||||
}
|
||||
|
||||
|
||||
FILE *
|
||||
locked_fopen(const char *filename, const char *mode)
|
||||
{
|
||||
FILELOCK flock;
|
||||
FILE *retval;
|
||||
int readonly = stequal(mode,"r");
|
||||
filelock_obtain(filename,readonly); /* Will wait till available */
|
||||
if (!(retval = fopen(filename,mode))) {
|
||||
filelock_release(filename, readonly);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Suuitable sequence for creating a file via a temporary
|
||||
filelock_obtain(filename,FALSE);
|
||||
if (!(afile = locked_fopen(tmpfilename, "w")) )
|
||||
filelock_release(filename,FALSE);
|
||||
written stuff to the file - retval set if fails
|
||||
return(locked_fclose_and_rename(afile, tmpfilename, filenam,retvale));
|
||||
*/
|
||||
|
||||
int
|
||||
locked_fclose_and_rename(
|
||||
FILE *afile, /* Open "w" temporary file */
|
||||
const char *tmpfilename, /* Name of temp file */
|
||||
const char *filename, /* Name desired */
|
||||
int retval) /* FALSE if ok to rename, TRUE cleanup*/
|
||||
{
|
||||
|
||||
if (fflush(afile) || ferror(afile)) { retval = PFAILURE; }
|
||||
if (locked_fclose_A(afile, tmpfilename, FALSE)) { retval = PFAILURE; }
|
||||
if (!retval) { /* Dont attempt to rename if failed */
|
||||
if (rename(tmpfilename, filename)) { retval = PFAILURE; }
|
||||
}
|
||||
unlink(tmpfilename);
|
||||
filelock_release(filename,FALSE);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
28
prospero/lib/ardp/flocks.h
Normal file
28
prospero/lib/ardp/flocks.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef rmg_filelock_h
|
||||
#define rmg_filelock_h
|
||||
|
||||
#include <pfs.h>
|
||||
|
||||
struct filelock {
|
||||
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
||||
int consistency;
|
||||
#endif
|
||||
char *name;
|
||||
int readers; /* -1 for writing */
|
||||
/* Note we dont keep the fileno here since each locker opens seperately*/
|
||||
struct filelock *next;
|
||||
struct filelock *previous;
|
||||
};
|
||||
typedef struct filelock *FILELOCK;
|
||||
typedef struct filelock FILELOCK_ST;
|
||||
|
||||
extern FILELOCK filelock_alloc();
|
||||
extern void filelock_free(FILELOCK chan);
|
||||
extern void filelock_lfree(FILELOCK chan);
|
||||
extern void filelock_freespares();
|
||||
extern FILELOCK filelock_copy(FILELOCK f, int r);
|
||||
#ifdef PFS_THREADS
|
||||
extern p_th_mutex p_th_mutexFILELOCK;
|
||||
#endif
|
||||
|
||||
#endif /*rmg_filelock_h*/
|
||||
204
prospero/lib/ardp/hostname2adr.c
Normal file
204
prospero/lib/ardp/hostname2adr.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 1991-1994 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
#include <ardp.h>
|
||||
#include <perrno.h>
|
||||
|
||||
#include <sys/types.h> /* for gethostbyname() */
|
||||
#include <sys/socket.h> /* for gethostbyname */
|
||||
#include <netdb.h> /* for gethostbyname. */
|
||||
#include <netinet/in.h> /* for struct sockaddr_in */
|
||||
#include <pmachine.h> /* for bzero */
|
||||
#include <string_with_strcasecmp.h> /* for strcasecmp */
|
||||
|
||||
#ifdef PROSPERO
|
||||
#include <pserver.h> /* For DNSCACHE_MAX */
|
||||
#ifdef DNSCACHE_MAX
|
||||
#include "dnscache_alloc.h"
|
||||
#endif
|
||||
#include <pcompat.h>
|
||||
#else /* not PROSPERO */
|
||||
#define DISABLE_PFS_START()
|
||||
#define DISABLE_PFS_END()
|
||||
#endif /* not PROSPERO */
|
||||
|
||||
extern int stcaseequal(const char *s1,const char *s2);
|
||||
|
||||
/*
|
||||
* This function serves as a thread-safe version of gethostbyname(),
|
||||
* which is not a re-entrant function since it uses static data.
|
||||
*
|
||||
* It normally accepts a hostname and initializes the socket address
|
||||
* appropriately, then returns PSUCCESS. Also accepts numeric addresses.
|
||||
* Does not currently handle the port #, although that would be a useful future
|
||||
* extension.
|
||||
*
|
||||
* It returns ARDP_BAD_HOSTNAME if the hostname could not be resolved.
|
||||
* gethostbyname should not be called anywhere else in multi-threaded versions
|
||||
* of the Prospero code; to this end, an error define occurs for it in
|
||||
* pfs_threads.h
|
||||
*
|
||||
* Oh no there isn't a definition in pfs_threads.h - Mitra
|
||||
*
|
||||
* Note that gethostbyname() is not multi-threaded internally, and
|
||||
* does block, so we might block on name resolution as a bottleneck.
|
||||
* Probably want a multithreaded name resolver library. Release such a thing
|
||||
* as freeware?
|
||||
*
|
||||
* It also converts numeric addresses appropriately.
|
||||
*/
|
||||
/* If change this - uncomment/comment initialization in server/dirsrv.c */
|
||||
|
||||
#ifdef DNSCACHE_MAX
|
||||
#include "dnscache_alloc.h"
|
||||
#include <mitra_macros.h> /* FIND_FNCTN_LIST */
|
||||
#include <string.h> /* For strcmp */
|
||||
|
||||
DNSCACHE alldnscaches = NULL;
|
||||
int alldnscache_count = 0;
|
||||
|
||||
void
|
||||
sockaddr_copy(struct sockaddr_in *src, struct sockaddr_in *destn)
|
||||
{
|
||||
/* Nothing in a sockaddr_in is a pointer */
|
||||
memcpy(destn, src, sizeof(struct sockaddr_in));
|
||||
}
|
||||
#endif /*DNSCACHE_MAX*/
|
||||
|
||||
/* Caching has been added, to this - take care that it does what you
|
||||
want, I'm certainly open to changes if this isnt what we need.
|
||||
Currently it is called by something at a higher layer, with a
|
||||
hostname of the name to cache, and a hostaddr of NULL.
|
||||
Currently this is used to cache all the hostnames hard coded
|
||||
into include/* on the assumption that these are unlikely to move around
|
||||
while a server is running. Later, we may want to delete a cached
|
||||
entry periodically, or if it fails.
|
||||
|
||||
The first thing in alldnscaches is always a copy of the last thing
|
||||
found, to allow really quick returns on repeat requests.
|
||||
|
||||
Note - great care is taken here to
|
||||
a) avoid deadlock between GETHOSTBYNAME and DNSCACHE mutexes
|
||||
b) avoid requirement for GETHOSTBYNAME mutex, if found in cache
|
||||
This allows multiple cached results to be returned while a
|
||||
single thread calls gethostbyname
|
||||
*/
|
||||
|
||||
void
|
||||
ardp_hostname2addr_initcache()
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
dnscache_clean()
|
||||
{
|
||||
DNSCACHE dc, nextdc;
|
||||
if (alldnscache_count > DNSCACHE_MAX) {
|
||||
if (! p_th_mutex_trylock(p_th_mutexALLDNSCACHE)) {
|
||||
/* Since this is only optimisation, skip if its locked already */
|
||||
for (dc = alldnscaches; dc ; dc = nextdc) {
|
||||
nextdc = dc->next;
|
||||
if (!(--dc->usecount)) {
|
||||
EXTRACT_ITEM(dc,alldnscaches);
|
||||
dnscache_free(dc);
|
||||
alldnscache_count--;
|
||||
}
|
||||
}
|
||||
p_th_mutex_unlock(p_th_mutexALLDNSCACHE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ardp_hostname2addr(const char *hostname, struct sockaddr_in *hostaddr)
|
||||
{
|
||||
struct hostent *hp; /* Remote host we're connecting to. */
|
||||
int retval; /* Value to return */
|
||||
#define RETURN(rv) { retval = (rv); goto cleanup; }
|
||||
#ifdef PROSPERO
|
||||
int DpfStmp; /* for DISABLE_PFS_START() */
|
||||
#endif
|
||||
#ifdef DNSCACHE_MAX
|
||||
DNSCACHE acache = NULL;
|
||||
|
||||
acache = alldnscaches;
|
||||
|
||||
p_th_mutex_lock(p_th_mutexALLDNSCACHE);
|
||||
/* Cant use TH_FIND_FNCTN_LIST because must retain lock */
|
||||
FIND_FNCTN_LIST(acache, name, hostname, stcaseequal);
|
||||
if(acache) {
|
||||
acache->usecount++;
|
||||
if (hostaddr) {
|
||||
/* Note is is pointless, but not harmfull to call again
|
||||
for same hostaddr - may just want to rerun*/
|
||||
sockaddr_copy(&(acache->sockad),hostaddr);
|
||||
}
|
||||
p_th_mutex_unlock(p_th_mutexALLDNSCACHE); /* Also released below*/
|
||||
return(ARDP_SUCCESS); /* Dont free acache */
|
||||
}
|
||||
p_th_mutex_unlock(p_th_mutexALLDNSCACHE); /* Note also released above*/
|
||||
acache = dnscache_alloc(); /*locks DNSCACHE temporarily*/
|
||||
acache->name = stcopy(hostname);
|
||||
if (!hostaddr) { hostaddr = &(acache->sockad); }
|
||||
#endif /*DNSCACHE_MAX*/
|
||||
|
||||
DISABLE_PFS_START(); /* Turn off compatibility library if on */
|
||||
p_th_mutex_lock(p_th_mutexGETHOSTBYNAME);
|
||||
hp = gethostbyname((char *) hostname); /* cast to char * in case bad prototype.
|
||||
*/
|
||||
DISABLE_PFS_END(); /* Restore compat. lib. */
|
||||
if (hp == NULL) {
|
||||
p_th_mutex_unlock(p_th_mutexGETHOSTBYNAME);
|
||||
/* Try to see if it might be a numeric address. */
|
||||
/* Check if a numeric address */
|
||||
hostaddr->sin_family = AF_INET;
|
||||
hostaddr->sin_addr.s_addr = inet_addr(hostname);
|
||||
if(hostaddr->sin_addr.s_addr == -1) {
|
||||
p_clear_errors(); /* clear p_err_string if set. */
|
||||
RETURN(perrno = ARDP_BAD_HOSTNAME);
|
||||
}
|
||||
RETURN(ARDP_SUCCESS);
|
||||
}
|
||||
bzero((char *) hostaddr, sizeof *hostaddr);
|
||||
memcpy((char *)&hostaddr->sin_addr, hp->h_addr, hp->h_length);
|
||||
hostaddr->sin_family = hp->h_addrtype;
|
||||
/* Don't unlock the mutex until we're no longer reading from hp. */
|
||||
p_th_mutex_unlock(p_th_mutexGETHOSTBYNAME); /* Note can be unlocked above*/
|
||||
/* Copy last result into cache */
|
||||
#ifdef DNSCACHE_MAX
|
||||
if (alldnscaches == NULL)
|
||||
ardp_hostname2addr_initcache();
|
||||
sockaddr_copy(hostaddr,&(acache->sockad));
|
||||
/* Boost initially, to bias towards keeping recent*/
|
||||
acache->usecount = 5;
|
||||
p_th_mutex_lock(p_th_mutexALLDNSCACHE);
|
||||
APPEND_ITEM(acache,alldnscaches);
|
||||
alldnscache_count++;
|
||||
p_th_mutex_unlock(p_th_mutexALLDNSCACHE);
|
||||
dnscache_clean(); /* Only does anything if cache too big */
|
||||
#endif /*DNSCACHE_MAX*/
|
||||
return(ARDP_SUCCESS); /* Dont free acache */
|
||||
|
||||
cleanup:
|
||||
#ifdef DNSCACHE_MAX
|
||||
if (acache) dnscache_free(acache);
|
||||
#endif
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/* Prototype needs to go into here, not just in pfs.h. */
|
||||
int
|
||||
stcaseequal(const char *s1,const char *s2)
|
||||
{
|
||||
if (s1 == s2) /* test for case when both NULL*/
|
||||
return TRUE;
|
||||
if (!s1 || !s2) /* test for one NULL */
|
||||
return FALSE;
|
||||
return (strcasecmp(s1, s2) == 0);
|
||||
}
|
||||
|
||||
141
prospero/lib/ardp/p__th_self_num.c
Normal file
141
prospero/lib/ardp/p__th_self_num.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 1991-1994 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <pfs_threads.h>
|
||||
#include <ardp.h> /* for internal error stuff. */
|
||||
|
||||
/* This is the only section of code which calls the pthread_ routines directly.
|
||||
Everything else is through the interface in pfs_threads.h. */
|
||||
|
||||
#ifdef PFS_THREADS
|
||||
/* Don't compile this if !PFS_THREADS, because it overrides macro definitions
|
||||
*/
|
||||
static struct {
|
||||
p_th_t thread;
|
||||
int inuse;
|
||||
} thread_map[P_MAX_NUM_THREADS];
|
||||
|
||||
#ifdef PFS_THREADS_SOLARIS
|
||||
thread_key_t thread_map_key;
|
||||
#endif
|
||||
|
||||
int
|
||||
p__th_self_num(void)
|
||||
{
|
||||
#if defined(PFS_THREADS_FLORIDA) || !defined(NDEBUG)
|
||||
p_th_t self = p_th_self();
|
||||
#endif
|
||||
|
||||
#ifdef PFS_THREADS_FLORIDA
|
||||
int i;
|
||||
|
||||
for (i = 0; i < P_MAX_NUM_THREADS; ++i) {
|
||||
if (thread_map[i].inuse
|
||||
&& p_th_equal(thread_map[i].thread, self))
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
#ifdef PFS_THREADS_SOLARIS
|
||||
long val;
|
||||
|
||||
if (!thread_map_key) return 0; /* Assume not threading */
|
||||
if (!thr_getspecific(thread_map_key,(void *)&val)) {
|
||||
assert(p_th_equal(thread_map[val].thread, self));
|
||||
assert(val < P_MAX_NUM_THREADS); /* i.e. 0 .. MAX-1 */
|
||||
return val;
|
||||
}
|
||||
#endif /*PFS_THREADS_SOLARIS*/
|
||||
internal_error("p__th_self_num() called for a thread that didn't have its \
|
||||
number set with p__th_allocate_self_num() or p__th_set_self_master()");
|
||||
return -1 ; /* Keep Gcc happy */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
p__th_set_self_master(void)
|
||||
{
|
||||
assert(!thread_map[0].inuse);
|
||||
thread_map[0].inuse = 1;
|
||||
thread_map[0].thread = p_th_self();
|
||||
#ifdef PFS_THREADS_SOLARIS
|
||||
assert(!thread_map_key);
|
||||
thr_keycreate(&thread_map_key, NULL);
|
||||
thr_setspecific(thread_map_key, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This allocates a number to this thread.
|
||||
* It also does consistency checking to make sure the function is called
|
||||
* only on a thread that doesn't have a number already allocated.
|
||||
*/
|
||||
void
|
||||
p_th_allocate_self_num(void)
|
||||
{
|
||||
int allocated = 0;
|
||||
p_th_t self = p_th_self();
|
||||
int i;
|
||||
|
||||
CHECK_MEM();
|
||||
assert(thread_map_key); /* Better be initialized*/
|
||||
/* I think this needs mutexing */
|
||||
p_th_mutex_lock(p_th_mutexARDP_SELFNUM);
|
||||
for (i = 0; i < P_MAX_NUM_THREADS; ++i) {
|
||||
if (!thread_map[i].inuse) {
|
||||
if (!allocated) {
|
||||
thread_map[i].thread = self;
|
||||
thread_map[i].inuse = 1;
|
||||
++allocated;
|
||||
CHECK_MEM();
|
||||
#ifdef PFS_THREADS_SOLARIS
|
||||
thr_setspecific(thread_map_key,(void *)i);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if(p_th_equal(thread_map[i].thread, self)) {
|
||||
internal_error("Shouldn't allocate a number to a thread twice.");
|
||||
}
|
||||
}
|
||||
}
|
||||
p_th_mutex_unlock(p_th_mutexARDP_SELFNUM);
|
||||
}
|
||||
|
||||
void
|
||||
p_th_deallocate_self_num(void)
|
||||
{
|
||||
int i = p__th_self_num();
|
||||
thread_map[i].inuse = 0;
|
||||
}
|
||||
|
||||
extern p_th_mutex p_th_mutexFILES;
|
||||
|
||||
#ifndef NDEBUG
|
||||
char mutex_locked_msg[] = "Mutex %s locked\n";
|
||||
#endif
|
||||
|
||||
#ifdef PFS_THREADS_SOLARIS
|
||||
/* Return true if fails to lock - i.e was already locked */
|
||||
int
|
||||
p_th_mutex_islocked(mutex_t *mp)
|
||||
{
|
||||
int retval;
|
||||
if (retval = mutex_trylock(mp)) {
|
||||
return retval;
|
||||
} else {
|
||||
return mutex_unlock(mp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* PFS_THREADS_SOLARIS */
|
||||
|
||||
#endif /*PFS_THREADS*/
|
||||
|
||||
324
prospero/lib/ardp/restrict.c
Normal file
324
prospero/lib/ardp/restrict.c
Normal file
@@ -0,0 +1,324 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#if !defined(AIX) && !defined(SOLARIS)
|
||||
#include <vfork.h>
|
||||
#endif
|
||||
#include <malloc.h>
|
||||
#include <search.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include "typedef.h"
|
||||
#include "db_files.h"
|
||||
#include "host_db.h"
|
||||
#include "header.h"
|
||||
#include "error.h"
|
||||
#include "archie_strings.h"
|
||||
#include "files.h"
|
||||
#include "master.h"
|
||||
#include "protos.h"
|
||||
#include "db_ops.h"
|
||||
|
||||
/* This performs a simple ACL based on ip addresses */
|
||||
|
||||
typedef struct {
|
||||
int ip[4]; /* Composes the ip address a.b.c.d */
|
||||
} ip_t;
|
||||
|
||||
|
||||
#define DIRSRV_ACL_FILE "dirsrv.acl"
|
||||
#define DIRSRV_ACL_MESSAGE_FILE "dirsrv.acl.mesg"
|
||||
|
||||
#define DIRSRV_ACL_MESSAGE_DEFAULT "Access to this server is restricted"
|
||||
|
||||
static ip_t *acl_list = NULL;
|
||||
static int acl_list_num = 0;
|
||||
static int acl_list_max = 0;
|
||||
static int acl_not_present = 0;
|
||||
|
||||
static char acl_err_mesg[100];
|
||||
|
||||
|
||||
#define IP_STAR 257
|
||||
|
||||
extern int errno;
|
||||
|
||||
|
||||
|
||||
static int qcompare_ip(a,b)
|
||||
ip_t *a, *b;
|
||||
{
|
||||
if ( a->ip[0] != b->ip[0] )
|
||||
return a->ip[0]- b->ip[0];
|
||||
|
||||
if ( a->ip[1] != b->ip[1] )
|
||||
return a->ip[1]- b->ip[1];
|
||||
|
||||
if ( a->ip[2] != b->ip[2] )
|
||||
return a->ip[2]- b->ip[2];
|
||||
|
||||
return a->ip[3]- b->ip[3];
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int compare_ip(a,b) /* Assuming that can contain * */
|
||||
ip_t *a, *b;
|
||||
{
|
||||
if ( b->ip[0] == IP_STAR )
|
||||
return 0;
|
||||
|
||||
if ( a->ip[0] != b->ip[0] )
|
||||
return a->ip[0]- b->ip[0];
|
||||
|
||||
if ( b->ip[1] == IP_STAR )
|
||||
return 0;
|
||||
|
||||
if ( a->ip[1] != b->ip[1] )
|
||||
return a->ip[1]- b->ip[1];
|
||||
|
||||
if ( b->ip[2] == IP_STAR )
|
||||
return 0;
|
||||
|
||||
if ( a->ip[2] != b->ip[2] )
|
||||
return a->ip[2]- b->ip[2];
|
||||
|
||||
if ( b->ip[3] == IP_STAR )
|
||||
return 0;
|
||||
|
||||
return a->ip[3]- b->ip[3];
|
||||
|
||||
}
|
||||
|
||||
static int file_proc(ft,name,present)
|
||||
file_info_t *ft;
|
||||
char *name;
|
||||
int *present;
|
||||
{
|
||||
struct stat st;
|
||||
*present = 1;
|
||||
if ( ft == NULL ) {
|
||||
error(A_ERR,"file_proc", "Unable to create ft file pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sprintf(ft->filename,"%s/%s/%s",get_archie_home(),DEFAULT_ETC_DIR,name);
|
||||
if ( stat(ft->filename,&st) == -1 ) {
|
||||
if ( errno == ENOENT ) {
|
||||
*present = 0;
|
||||
return 0;
|
||||
}
|
||||
error(A_ERR,"file_proc","Error finding ft: %s, errno = %d",ft->filename,errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( open_file(ft, O_RDONLY) == ERROR ) {
|
||||
error(A_ERR,"file_proc", "Error opening acl file: %s",ft->filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void read_acl_message()
|
||||
{
|
||||
char buff[100];
|
||||
int i;
|
||||
|
||||
file_info_t *acl_mesg = create_finfo();
|
||||
|
||||
strcpy(acl_err_mesg, DIRSRV_ACL_MESSAGE_DEFAULT);
|
||||
|
||||
if ( file_proc(acl_mesg,DIRSRV_ACL_MESSAGE_FILE,&i) ) {
|
||||
if ( fgets(buff,99,acl_mesg->fp_or_dbm.fp) != NULL ) {
|
||||
*(strrchr(buff,'\n')) = '\0';
|
||||
strcpy(acl_err_mesg,buff);
|
||||
}
|
||||
close_file(acl_mesg);
|
||||
destroy_finfo(acl_mesg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int read_acl_file()
|
||||
{
|
||||
char buff[100];
|
||||
int i,j;
|
||||
char **av;
|
||||
file_info_t *acl_file = create_finfo();
|
||||
|
||||
if (! file_proc(acl_file,DIRSRV_ACL_FILE,&j) ) {
|
||||
if ( j == 0 ) {
|
||||
acl_not_present = 1;
|
||||
destroy_finfo(acl_file);
|
||||
return 1;
|
||||
}
|
||||
destroy_finfo(acl_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Count the number of items */
|
||||
fseek(acl_file->fp_or_dbm.fp, 0L ,0);
|
||||
i = 0;
|
||||
while (fgets(buff,99,acl_file->fp_or_dbm.fp) != NULL ) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if ( i == 0 ) {
|
||||
error(A_INFO,"read_acl_file","ACL file is empty");
|
||||
acl_not_present = 1;
|
||||
destroy_finfo(acl_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( acl_list_max == 0 ) { /* New */
|
||||
acl_list_max = i+10;
|
||||
acl_list = (ip_t*)malloc(sizeof(ip_t)*acl_list_max);
|
||||
if ( acl_list == NULL ) {
|
||||
error(A_ERR,"read_acl_file","Unable to allocate memory");
|
||||
destroy_finfo(acl_file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ip_t *tmp;
|
||||
if ( acl_list_max <= i ) {
|
||||
acl_list_max = i+10;
|
||||
tmp = (ip_t*)realloc(acl_list, sizeof(ip_t)*acl_list_max);
|
||||
if ( tmp == NULL ) {
|
||||
error(A_ERR,"read_acl_file", "Unable to expand allocated memory");
|
||||
}
|
||||
acl_list = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
acl_list_num = 0;
|
||||
|
||||
fseek(acl_file->fp_or_dbm.fp, 0L ,0);
|
||||
while (fgets(buff,99,acl_file->fp_or_dbm.fp) != NULL ) {
|
||||
av = str_sep(buff,'.');
|
||||
if ( av == NULL ) {
|
||||
error(A_ERR,"read_acl_file", "Unable to decompose string: %s",buff);
|
||||
}
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
if ( av[i] == NULL|| av[i][0] == '*' ) {
|
||||
break;
|
||||
}
|
||||
acl_list[acl_list_num].ip[i] = atoi(av[i]);
|
||||
}
|
||||
for ( ; i < 4; i++ ) {
|
||||
acl_list[acl_list_num].ip[i] = IP_STAR;
|
||||
}
|
||||
acl_list_num++;
|
||||
}
|
||||
|
||||
close_file(acl_file);
|
||||
|
||||
qsort(acl_list,acl_list_num, sizeof(ip_t),qcompare_ip);
|
||||
|
||||
read_acl_message();
|
||||
|
||||
destroy_finfo(acl_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int verify_acl_list(from)
|
||||
struct sockaddr_in *from;
|
||||
{
|
||||
ip_t ip;
|
||||
int i;
|
||||
char **av;
|
||||
char *ip_addr;
|
||||
|
||||
|
||||
if ( acl_not_present )
|
||||
return 1;
|
||||
|
||||
if ( acl_list == NULL ) {
|
||||
if (!read_acl_file() )
|
||||
return 0;
|
||||
if ( acl_not_present )
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
ip_addr = inet_ntoa(from->sin_addr);
|
||||
printf("%s\n",ip_addr);
|
||||
/* decompose address */
|
||||
av = str_sep(ip_addr,'.');
|
||||
if ( av == NULL ) {
|
||||
error(A_ERR,"verify_acl_list","Unable to decompsoe ip address: %s. Accepting",ip_addr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ip.ip[0] = atoi(av[0]);
|
||||
ip.ip[1] = atoi(av[1]);
|
||||
ip.ip[2] = atoi(av[2]);
|
||||
ip.ip[3] = atoi(av[3]);
|
||||
|
||||
|
||||
if ( ip.ip[0] == 127 && ip.ip[1] == 0 && ip.ip[2] == 0 && ip.ip[3] == 1 ) {
|
||||
free_opts(av);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
for ( i = 0; i < acl_list_num; i++ ) {
|
||||
int ret;
|
||||
|
||||
ret = compare_ip(&ip, &acl_list[i]);
|
||||
if ( ret == 0 ){
|
||||
free_opts(av);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( ret < 0 ) {
|
||||
free_opts(av);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
free_opts(av);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *acl_message()
|
||||
{
|
||||
return acl_err_mesg;
|
||||
}
|
||||
|
||||
#if 0
|
||||
char *prog;
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char buff[100];
|
||||
struct sockaddr_in from;
|
||||
|
||||
prog = argv[0];
|
||||
while ( fgets(buff,99,stdin) != NULL ) {
|
||||
*(strrchr(buff,'\n')) = '\0';
|
||||
printf("Checking %s, ",buff);
|
||||
|
||||
from.sin_addr.s_addr = inet_addr(buff);
|
||||
|
||||
if ( verify_acl_list(&from) )
|
||||
printf("Ok\n");
|
||||
else
|
||||
printf("No:%s\n",acl_message());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
41
prospero/lib/ardp/unixerrstr.c
Normal file
41
prospero/lib/ardp/unixerrstr.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 1991-1994 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
|
||||
#include <pmachine.h>
|
||||
#if defined(HAVESTRERROR)
|
||||
#include <errno.h>
|
||||
#include <string.h> /* For stringerr*/
|
||||
#else
|
||||
#include <errno.h> /* For sys_nerr and sys_errlist*/
|
||||
#ifndef SOLARIS
|
||||
/* definitely needed under SunOS; probably under almost everything right
|
||||
now. Solaris's <errno.h> declares these; others don't. */
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
#endif /* ndef SOLARIS */
|
||||
#undef HAVESTRERROR
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
unixerrstr(void)
|
||||
{
|
||||
#ifdef HAVESTRERROR
|
||||
/* sys_errlist is not in SOLARIS, replace with strerror()
|
||||
which may not be thread safe in some applications
|
||||
there doesnt appear to be a posix compliant equivalent */
|
||||
return strerror(errno);
|
||||
#else
|
||||
/* Would be nice to have the message include the error #. */
|
||||
return errno < sys_nerr ? sys_errlist[errno] : "Unprintable Error";
|
||||
#endif
|
||||
}
|
||||
|
||||
15
prospero/lib/ardp/usc_lic_str.c
Normal file
15
prospero/lib/ardp/usc_lic_str.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
/* This string is modified in ardp_xmit.c. That forces the C compiler to
|
||||
include it in the Prospero binaries. If you know a less kludgy way to
|
||||
force a fancy optimizing C compiler to include it in the binaries, please
|
||||
let us know.
|
||||
*/
|
||||
char *usc_license_string = "PROSPERO(TM) Copyright (c) 1991-1993 University of Southern California\nPROSPERO is a trademark of the University of Southern California\n";
|
||||
Reference in New Issue
Block a user