;;; -*- Mode:LISP; Package:SUN; Base:10; Readtable:CL -*- ;;; (c) LISP Machine, Inc. 1986 ;;; All Rights Reserved ;;; See filename "copyright.text" for ;;; further information. ;;; (C) Copyright 1987, LISP MACHINE INC ;;; See filename "Copyright.Text" for more information. ;;; ********************************************************* ;;; ********************************************************* ;;; *** NOTE: This is an EXAMPLE, not LMI supported code. *** ;;; *** information contained in this example is subject *** ;;; *** to change without notice. The ways of doing *** ;;; *** the things contained in the example may change *** ;;; *** between system releases. Some techniques which *** ;;; *** are mere examples in one release may become built *** ;;; *** in system features in the next release. Use good *** ;;; *** judgement when copying these techniques. Most *** ;;; *** examples have been motivated by specific customer *** ;;; *** requests, and may not be the best engineered *** ;;; *** or most efficient solution for someone else. *** ;;; ********************************************************* ;;; ********************************************************* (defun on-udp-socket (f &optional local-port &aux socket) (unwind-protect (progn (setq socket (tcp:open-socket :type 'tcp:sock-dgram :address (cond (local-port (tcp:make-socket-address :port local-port)) ('else :unspecified)))) (funcall f socket)) (and socket (tcp:close-socket socket)))) (defun run-port-mapper () (on-udp-socket 'port-mapper-toplevel *port-mapper-port*)) (defun port-mapper-toplevel (socket) (let ((from (tcp:make-socket-address)) (data (make-string tcp:bsize))) (do-forever (multiple-value-bind (reply-data reply-length) (port-mapper-1 data (tcp:udp-socket-read socket data from)) (when reply-length (tcp:udp-socket-write socket reply-data from reply-length)))))) (defun port-mapper-1 (array length) (let ((receive-xdrs (xdrmem_create :decode array 0 length)) (transmit-xdrs (xdrmem_create :encode array))) (let ((message (xdr_receive receive-xdrs 'rpc:rpc_msg))) (let ((body (descriminated-value (xdr_structure_ref message 'rpc:body)))) (let ((item (ass #'equal (list (xdr_structure_ref body 'rpc:proc) (xdr_structure_ref body 'rpc:vers)) *port-mapper*))) (cond ((and item (get (cadr item) 'service-procedure)) (let* ((args (mapcar #'(lambda (argtype) (xdr_receive receive-xdrs argtype)) (caddr item))) (values (apply (get (cadr item) 'service-procedure) args))) ;; need to handle error conditions too. (fill array 0) (xdr_transmit transmit-xdrs (make-accepted-msg (xdr_structure_ref message 'rpc:xid) 'rpc:success) 'rpc:rpc_msg) (mapc #'(lambda (val type) (xdr_transmit transmit-xdrs val type)) values (cadddr item)) (values array (xdr_getpos transmit-xdrs)))) ('else (fill array 0) (xdr_transmit transmit-xdrs (make-accepted-msg (xdr_structure_ref message 'rpc:xid) 'rpc:proc_unavail) 'rpc:rpc_msg) (values array (xdr_getpos transmit-xdrs))))))))) (defun make-accepted-msg (xid accept_stat) (xdr_make_structure 'rpc:rpc_msg 'rpc:xid xid 'rpc:body (xdr_make_descrimination 'rpc:reply (xdr_make_descrimination 'rpc:msg_accepted (xdr_make_structure 'rpc:accepted_reply 'rpc:verf rpc:*null-auth* 'rpc:result (xdr_make_descrimination accept_stat ())))))) (defvar *port-mapper* '(((0 2) pmapproc_null () ()) ((1 2) pmapproc_set (u_int u_int protocol u_int) (boole)) ((2 2) pmapproc_unset (u_int u_int protocol u_int) (boole)) ((3 2) pmapproc_getport (u_int u_int protocol u_int) (u_int)) ((4 2) pmapproc_dump () ((list port-mapping))) ((5 2) pmapproc_callit (u_int u_int u_int string) (u_int string)))) (defun (pmapproc_null service-procedure) () ()) (defvar *port-mappings* nil) (defun lookup-port-mapping (prog vers prot) (car (mem #'(lambda (ignore x) (and (eq (xdr_structure_ref x 'prog) prog) (eq (xdr_structure_ref x 'vers) vers) (eq (xdr_structure_ref x 'prot) prot))) () *port-mappings*))) (defun set-port-mapping (prog vers prot port) (with-lock ((get '*port-mappings* 'lock)) (setq *port-mappings* (append (remq (lookup-port-mapping prog vers prot) *port-mappings*) (list (xdr_make_structure 'port-mapping 'prog prog 'vers vers 'prot prot 'port port)))))) (defun (pmapproc_set service-procedure) (prog vers prot port) (set-port-mapping prog vers prot port) '(t)) (defun (pmapproc_unset service-procedure) (prog vers ignore ignore) (with-lock ((get '*port-mappings* 'lock)) (do ((item)) ((not (setq item (car (mem #'(lambda (ignore x) (and (eq (xdr_structure_ref x 'prog) prog) (eq (xdr_structure_ref x 'vers) vers))) () *port-mappings*))))) (setq *port-mappings* (remq item *port-mappings*)))) '(t)) (defun (pmapproc_getport service-procedure) (prog vers prot ignore) (let ((map (lookup-port-mapping prog vers prot))) (cond ((not map) (list 0)) ('else (list (xdr_structure_ref map 'port)))))) (defun (pmapproc_dump service-procedure) () (list *port-mappings*))