(FILECREATED "30-Jun-86 17:01:43" {PHYLUM}<LANNING>RPC>RPC.;1 86456 changes to: (FNS \MarshalString) (MACROS FILLPUPSOURCE PUPDEBUGGING) (RECORDS Connection Conversation ConversationID DispDetails ExportTableEntry ImportInstance InterfaceName PktConversationID RPCBinderArgs RPCHandle RPCPup RPCPupContents RPCRFAResponse RPCRFARequest VersionRange) previous date: "10-Jan-86 18:37:17" {ERIS}<LISPUSERS>KOTO>RPC.;7) (* Copyright (c) 1984, 1985, 1986 by Xerox Corporation. All rights reserved.) (PRETTYCOMPRINT RPCCOMS) (RPAQQ RPCCOMS ((* Top Level functions) (FNS InitRPC StopRPC) (* Client functions) (FNS ImportInterface RemoteBind UnimportInterface) (* Server functions) (FNS Binder NewExportTableEntry ExportInterface UnexportInterface) (* Conversations) (FNS \Authenticate StartConversation) (* Basic protocol operation) (FNS \RPCTopProc \RPCServerProc \RoutePup \ExchangePackets \DoSignal) (* Call management) (FNS \StartCall \Call \AbortRemote CantCatchHere \StartSignal \StartReturn) (* Local id maintenance) (FNS \SetWanting \ClearWanting \Wanting \NewHandleCnt \NewProcess \FindHandle \KillHandle) (* encryption utilities) (FNS \EncryptPup \DecryptPup) (* Utilities) (FNS \RPCOpenClosest \SetupResponse \ReceiveExtra \SendExtra CheapHopsToNet \CheckRPC \RPCNotAliveErr \ServerError \InitRPCVars) (DECLARE: DONTCOPY (MACROS FILLPUPSOURCE)) (* Authentication) (FNS \ReplyToRFA \GetConnectionState) (* Misc. constants) (DECLARE: DONTCOPY (CONSTANTS (\RPCLupineArgStart 11) (\RPCPupWordOvLen 10) (\RPCPupByteOvLen 20) (\RPCMaxDataOffset 264) (\RPCMaxPupLength 550) (\RPCRetransTimeout 1000) (\RPCPingTimeout 5000) (\RPCMaxPingTimeout 60000) (\RPCMaxTransCount 14) (\RPCTransTimeoutIncr 100) (\RPCDelayPerHop 500) (\NonceIdOffset 6) (\RPCPktIDOffset 2) (\RPCRFAcallerIDOffset 12) (\PT.ECHOME 1) (\PT.IAMECHO 2) (\PUPOVLEN 22) (\RPCStringHeaderLength 2) (\RPCCheckLength 2) (\RPCClearHeaderLength 2) (\RPCRespCKBlocks 3)) (* State constants for \ExchangePackets) (CONSTANTS (\stReceiving (QUOTE receiving)) (\stSending (QUOTE sending)) (\stCall (QUOTE call)) (\stEndCall (QUOTE endCall)) (\stAuthReq (QUOTE authReq))) (* constants for result field of pups) (CONSTANTS (\rcResult 0) (\rcUnbound 1) (\rcSignal 2) (\rcUnwind 3) (\rcProtocol 4)) (* constants for type field of pups) (CONSTANTS (\clCall 0) (\clData 1) (\clAck 2) (\clRFA 4)) (* RPC internal error codes) (CONSTANTS (\ecUnbound (QUOTE unbound)) (\ecTimeout (QUOTE timeout))) (* Authentication constants) (CONSTANTS (\RPCAuthKyPos 0) (\RPCAuthConvKeyPos 8) (\RPCAuthTimePos 16) (\RPCAuthNamePos 18) (\RPCAuthFixedLength 18) (\RPCAuthenticatorOffset 24))) (* Global parameters) (INITVARS (\RPCNullSeed (ARRAY 8 (QUOTE (BITS 8)) 0 0)) (\HandleCnt 0) (\HandleOverflow) (\ConnectionTimeout 6) (\CheckConnectionsInterval 60000) (\RPCConnections) (\RPCConversations) (\RPCLastConversation) (\RPCHandles) (\RPCWanting) (\RPCDefaultSocket 30) (\BinderDisp) (\RPCConvID) (\RPCDontBotherWithRFA) (\RPCDebugWaitForever) (\RPCNumberOfServers 0) (\RPCMaxServers 5) (\RPCMaxIdlers 3) (\RPCIdlers) (\RPCDebugServers) (\RPCServerErrors) (\RPCMaxServerErrors 25)) (RESOURCES \RPCScratchStream) (GLOBALVARS \RPCNullSeed \HandleCnt \HandleOverflow \RPCConnections \RPCConversations \RPCLastConversation \RPCHandles \RPCWanting \RPCDefaultSocket \BinderDisp \CallCnt \RPCConvID \RPCDontBotherWithRFA \RPCDebugWaitForever \RPCNumberOfServers \RPCMaxServers \RPCMaxIdlers \RPCIdlers \ConnectionTimeout \CheckConnectionsInterval \RPCDebugServers \RPCServerErrors \RPCMaxServerErrors) (GLOBALVARS ExportTable \RPCTopProc \RPCSocket \RPCSocketNumber ExportCount) (* The block records here reflect Andrew's layout of the transport mechanism in {INDIGO}<CEDAR>RPC>RPCPkt.mesa and should track any changes made there) (DECLARE: DONTCOPY (RECORDS Connection Conversation ConversationID DispDetails ExportTableEntry ImportInstance InterfaceName PktConversationID RPCBinderArgs RPCHandle RPCPup RPCPupContents RPCRFAResponse RPCRFARequest VersionRange)) (VARS (\NoDispatcher 0) (\MatchAnyVersion) (\NoDispDetails)) (P (\InitRPCVars)) (GLOBALVARS \NoDispatcher \MatchAnyVersion \NoDispDetails) (* adding stuff to pups) (FNS \PutBinderString \AddRPCDispDetails \AddRPCVersion \AddPupDblWord \AddPupWord \AddPupEnum \AddPupSmallp \AddPupBoolean \MarshalStream \MarshalArb \MarshalString \MarshalAtom \MoveToPup \MoveToMultPups) (* Picking stuff out of pups) (FNS \GetBinderString \GetArgDisp \GetArgVersion \GetArgDblWord \GetArgWord \GetArgEnum \GetArgBool \GetArgSmallp \UnmarshalString \UnmarshalStream \UnmarshalArb \UnmarshalAtom \MoveFromPup \MoveFromMultPups \IncrDataOffset \IncrPupLength \CurrentPupBase \CurrentPupPosition \CheckPupOverflow \CheckPupExhausted \SkipBytesOut \SkipWordsIn) (* to control how much PUPTRACEFLG shows) (ALISTS (PUPPRINTMACROS 96 97 98 104 105 106 120 100 108 121)) [VARS RPCPUPTYPES [PUPTYPES (UNION RPCPUPTYPES (LISTP (EVALV (QUOTE PUPTYPES] (PUPONLYTYPES (UNION PUPONLYTYPES (MAPCAR RPCPUPTYPES (FUNCTION CADR] (DECLARE: DONTCOPY (MACROS PUPDEBUGGING)) (DECLARE: DONTCOPY EVAL@COMPILE (P (RESETSAVE DWIMIFYCOMPFLG T))) (FILES GRAPEVINE SIGNAL CRYPT) (DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY (FILES (LOADCOMP) CRYPT SIGNAL NOBOX ETHERRECORDS (IMPORT) LLCHAR LLARRAYELT)))) (* Top Level functions) (DEFINEQ (InitRPC [LAMBDA (socket) (* ht: "27-Sep-84 08:56") (* Start listening and initialise state of RPC world) (PROG NIL (if (THIS.PROCESS)=NIL then (printout T T "Please enable processes by typing (PROCESSWORLD) and try again" T) (RETURN)) (\RPCSocketNumber←(OR socket \RPCDefaultSocket)) (if (OR \RPCSocket←(OPENPUPSOCKET \RPCSocketNumber 'FAIL)=NIL (FIND.PROCESS \RPCTopProc)) then (\RPCSocket←(OPENPUPSOCKET \RPCSocketNumber 'ACCEPT)) (SELECTQ (ASKUSER DWIMWAIT 'Y "OK to Reinitialize? ") (Y (StopRPC) \RPCSocket← (OPENPUPSOCKET \RPCSocketNumber)) (N (RETURN)) (SHOULDNT))) [\RPCTopProc←(PROCESS.NAME (ADD.PROCESS '(\RPCTopProc)] (ExportTable←NIL) (ExportCount←-1) (\RPCConnections←NIL) (\RPCConversations←NIL) [\RPCLastConversation←(create ConversationID originatorC ←(ETHERHOSTNUMBER) count ←(IBOX (CLOCK 0] (* * cheat to make sure that bit is 0 for later use as PktConversationID) (\RPCLastConversation:count:originatorP←0) (\RPCHandles←NIL) (\RPCWanting←NIL) (\RPCIdlers←NIL) (\HandleCnt←0) (\HandleOverflow←NIL) (\CallCnt←0) (for i from 1 to \RPCMaxIdlers do (ADD.PROCESS '(\RPCServerProc)) (BLOCK)) (\RPCNumberOfServers←\RPCMaxIdlers) (\RPCConvID←(LOGAND -32769 (CLOCK))) (* mask out the "caller" bit) (NewExportTableEntry (FUNCTION Binder) (create InterfaceName type ← "Binder")) (ExportTable:1:dispId←\NoDispatcher+1) (* all of this adds up to the binder having hint 0 and id 1) (\BinderDisp←(create DispDetails dId ←(\NoDispatcher+1))) (RETURN T]) (StopRPC [LAMBDA NIL (* ht: " 4-SEP-83 17:52") \BinderDisp←NIL (* so we can tell if we're alive or dead) (if (FIND.PROCESS \RPCTopProc) then (DEL.PROCESS \RPCTopProc)) (NLSETQ (CLOSEPUPSOCKET \RPCSocket)) (MAP.PROCESSES (FUNCTION (LAMBDA (p n f) (if f:1=(QUOTE \RPCServerProc) then (DEL.PROCESS p]) ) (* Client functions) (DEFINEQ (ImportInterface [LAMBDA (type instance version stubProt) (* ht: " 3-Jan-85 13:37") (* = RPCBinding.ImportInterface, .TryBinding) (\CheckRPC) (PROG (host socket) (if (AND instance instance~= 'BROADCAST) then (if (STRPOS "." instance) then (* an rName) (if ~(STRINGP host←(GV.READCONNECT instance)) then (Signal 'ImportFailed 'BadRName)) elseif host←(ETHERPORT instance) else (Signal 'ImportFailed 'BadInstance)) socket←(ETHERPORT host) elseif socket←(\RPCOpenClosest (if instance= 'BROADCAST then (ETHERPORT 0 T T) elseif (STRPOS "." type) then (* an rName of a group, we hope) (LOCATESOCKETS type T) elseif (ETHERPORT type T T) else (Signal 'ImportFailed 'BadType)) type) else (SHOULDNT)) (RETURN (create ImportInstance host ← socket dispDetails ← (enable CallFailed => (goto die) (RemoteBind socket type (if instance= 'BROADCAST then NIL else instance) (OR stubProt \MatchAnyVersion) (OR version \MatchAnyVersion)) die -> (Signal 'ImportFailed 'communications))]) (RemoteBind [LAMBDA (socket type instance stubProt version) (* ht: " 1-Aug-85 08:56") (PROG (l..cPup contents expStubProt expVersion disp) (DECLARE (SPECVARS l..cPup)) (l..cPup←(\StartCall socket \BinderDisp)) (contents←l..cPup:PUPCONTENTS) (contents:request←0) (add l..cPup:PUPLENGTH 6) (contents:bindType←(LRSH l..cPup:PUPLENGTH-\RPCPupByteOvLen-\PUPOVLEN 1)) (contents:bindInstance←(\PutBinderString l..cPup type)) (\PutBinderString l..cPup instance) (l..cPup←(\Call l..cPup)) (expStubProt←(\GetArgVersion l..cPup)) (expVersion←(\GetArgVersion l..cPup)) (disp←(\GetArgDisp l..cPup)) (if disp:dId=\NoDispatcher then (Signal 'ImportFailed 'unbound)) (if (AND (NOT (EQUAL stubProt \MatchAnyVersion)) (NOT (EQUAL expStubProt \MatchAnyVersion)) (OR (IGREATERP stubProt:first expStubProt:last) (ILESSP stubProt:last expStubProt:first))) then (Signal 'ImportFailed 'stubProtocol)) (if (AND (NOT (EQUAL version \MatchAnyVersion)) (IGREATERP version:first version:last)) then (Signal 'ImportFailed 'badVersion)) (if (AND (NOT (EQUAL version \MatchAnyVersion)) (NOT (EQUAL expVersion \MatchAnyVersion)) (OR (IGREATERP version:first expVersion:last) (ILESSP version:last expVersion:first))) then (Signal 'ImportFailed 'wrongVersion)) (RELEASE.PUP l..cPup) (RETURN disp]) (UnimportInterface [LAMBDA (interface) (* ht: "13-JAN-83 10:52") (* ht: "13-JAN-83 09:46") ]) ) (* Server functions) (DEFINEQ (Binder [LAMBDA (pup) (* ht: "11-Feb-84 10:44") (if pup:PUPCONTENTS:request=0 then (PROG ((contents (pup:PUPCONTENTS)) type instance ete (stubProt \MatchAnyVersion) (version \MatchAnyVersion) (dispatcher \NoDispDetails)) (type←(\GetBinderString contents contents:bindType contents:bindInstance)) (instance←(\GetBinderString contents contents:bindInstance (LRSH pup:PUPLENGTH-\RPCPupByteOvLen-\PUPOVLEN 1))) (if ete←[for e in ExportTable unless e:dispId=\NoDispatcher thereis (AND (OR type=NIL (STREQUAL type e:intName:type)) (OR instance=NIL (STREQUAL instance e:intName:instance] then (stubProt←ete:stubProt) (version←ete:intName:version) (dispatcher←(create DispDetails dMds ← ete:mds dId ← ete:dispId hint ← ete:dispHint))) (* set up response packet) (pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen)) (\AddRPCVersion pup stubProt) (\AddRPCVersion pup version) (\AddRPCDispDetails pup dispatcher) (RETURN pup)) elseif pup:PUPCONTENTS:request=1 then (* client wishes to abort a server process) (PROG ((sourcePSB (\GetArgSmallp pup)) (localId (\GetArgSmallp pup)) (convId (\GetArgDblWord pup)) (callCnt (\GetArgDblWord pup)) handle) (if (AND handle←(ASSOC localId \RPCHandles) (CAR (PROCESSPROP handle:process (QUOTE FORM)))=(QUOTE \RPCServerProc)) then (PROCESS.APPLY handle:process (FUNCTION Signal) <(QUOTE RPCAbortMe?) < pup:SOURCE sourcePSB convId callCnt>>)) (\StartReturn pup) (RETURN pup)) else (ERROR "wrong request to binder" pup:PUPCONTENTS:request]) (NewExportTableEntry [LAMBDA (dispatcher intName stubProt mds) (* ht: " 1-SEP-83 16:02") (CAR (push ExportTable (create ExportTableEntry dispHint ←(do (OR (SMALLP (add ExportCount 1)) ExportCount←1) repeatwhile (ASSOC ExportCount ExportTable) finally (RETURN ExportCount)) dispId ←(CLOCK) dispatcher ← dispatcher mds ←(OR mds 0) intName ←(create InterfaceName type ←(MKSTRING intName:type) instance ←(MKSTRING intName:instance) version ← intName:version) stubProt ←(OR stubProt \MatchAnyVersion]) (ExportInterface [LAMBDA (name pw type instance version dispatcher stubProt) (* bvm: "19-Jul-85 18:00") (\CheckRPC) (MakeErrorsSignals) [PROG ((me (ETHERHOSTNUMBER)) current res) (* interface.instance had better name us one way or another) [COND [(STRPOS "." instance) (* an rName) [COND ([NOT (STRINGP (SETQ current (GV.READCONNECT instance] (Signal (QUOTE ExportFailed) (QUOTE BadRName] (COND ((NEQ me (CAR (ETHERPORT current))) (SELECTQ (GV.CHANGECONNECT instance (PORTSTRING me) (OR name T) pw) (T) (Signal (QUOTE ExportFailed) (QUOTE BadInstance] ((NEQ (CAR (ETHERPORT instance)) me) (Signal (QUOTE ExportFailed) (QUOTE WrongInstance] (COND ((STRPOS "." type) (* an rName - we should be among the members) (COND ((NOT (for m in [CDR (OR (LISTP (SETQ res (GV.READMEMBERS type))) (Signal (QUOTE ExportFailed) (QUOTE BadRName] thereis (STREQUAL instance m))) (COND ((NEQ (SETQ res (GV.ADDMEMBER type instance)) T) (Signal (QUOTE ExportFailed) res] (NewExportTableEntry dispatcher (create InterfaceName type ← type instance ← instance version ←(OR version \MatchAnyVersion)) stubProt]) (UnexportInterface [LAMBDA (etEntry) (* ht: "22-JAN-83 14:30") (SETQ ExportTable (DREMOVE etEntry ExportTable]) ) (* Conversations) (DEFINEQ (\Authenticate [LAMBDA (caller key callee) (* ht: "26-Sep-84 19:53") (* key must either be a key already, or a LISP-locally encrypted password, e.g. the result of a call to \INTERNAL/GETPASSWORD) ([LAMBDA (res) (if res~=T then (Signal 'AuthenticateFailed <caller key res>] (GV.AUTHENTICATE caller key)) ([LAMBDA (res) (if ~(TYPENAMEP res 'TIMESTAMP) then (Signal 'AuthenticateFailed <callee res>] (GV.CHECKSTAMP callee)) (PROG ((nameLen (((NCHARS caller)+ 1)/2)) (iv (GetRandomIV)) (kb (CorrectParity (COPYARRAY DESNullKey))) (ky (GetRandomCryptKey)) (convKey (GetRandomCryptKey)) nBlks auth) (nBlks←(\RPCAuthFixedLength+\RPCStringHeaderLength+nameLen+\DESBlockSize-1)/\DESBlockSize) (auth←(ARRAY nBlks*\DESBlockSize '(BITS 16) 0 0)) (\BLT (\ADDBASE auth:ARRAYP.BASE \RPCAuthKyPos) ky:ARRAYP.BASE 4) (\BLT (\ADDBASE auth:ARRAYP.BASE \RPCAuthConvKeyPos) convKey:ARRAYP.BASE 4) (* * time is already 0) ((ELT auth \RPCAuthNamePos)←(NCHARS caller)) (\PUTBASESTRING auth:ARRAYP.BASE (CONSTANT (LLSH \RPCAuthNamePos+\RPCStringHeaderLength 1)) caller) (EncryptBlock kb (\ADDBASE auth:ARRAYP.BASE \RPCAuthConvKeyPos) (\ADDBASE auth:ARRAYP.BASE \RPCAuthConvKeyPos)) (CryptData ky nBlks-2 (\ADDBASE auth:ARRAYP.BASE \RPCAuthConvKeyPos) (\ADDBASE auth:ARRAYP.BASE \RPCAuthConvKeyPos) 'encrypt 'cbcCheck \RPCNullSeed) (EncryptBlock kb (\ADDBASE auth:ARRAYP.BASE \RPCAuthKyPos) (\ADDBASE auth:ARRAYP.BASE \RPCAuthKyPos)) (RETURN (create Conversation authenticator ← auth convKey ← convKey iv ← iv]) (StartConversation [LAMBDA (caller key callee level) (* ht: " 3-Jan-85 13:32") (* key must either be a key already, or a LISP-locally encrypted password, e.g. the result of a call to \INTERNAL/GETPASSWORD) (if level~=%'CBCCheck then (Signal 'NotImplemented level)) (PROG ((conv (\Authenticate caller key callee))) (conv:caller←caller) (conv:callee←callee) (conv:level←level) (add \RPCLastConversation:count:ls 1) (if (IEQP \RPCLastConversation:count:ls 0) then (add \RPCLastConversation:count:ms 1)) (conv:cId←(create ConversationID count ←(IBOX \RPCLastConversation:count) originatorC ← \RPCLastConversation:originatorC)) (push \RPCConversations conv) (RETURN conv]) ) (* Basic protocol operation) (DEFINEQ (\RPCTopProc [LAMBDA NIL (* ht: "27-Sep-84 08:17") (* the root process in a server. Handles EchoMe pups for establishing connections, and also dispatches RPC pups to the appropriate process. Note that pup is shared among all processes, so they have to be careful with it. Also checks periodically to age idle connections and kill them if they get too old.) (PROG (pup timer tString) (while pup←(GETPUP \RPCSocket) do (RELEASE.PUP pup)) (timer←(SETUPTIMER \CheckConnectionsInterval)) (* NO LONGER NEEDED (OR (if \RPCPupQueue then (pup←\RPCPupQueue) (\RPCPupQueue←pup:ETHERPACKET.EPLINK ) (pup:ETHERPACKET.EPLINK←NIL) T))) LP (if pup←(GETPUP \RPCSocket (LRSH \CheckConnectionsInterval 4)) then (SELECTC (fetch PUPTYPE of pup) (\PT.ECHOME (SETQ tString (GETPUPSTRING pup 0)) (if [for e in ExportTable unless (EQ (fetch dispId of e) \NoDispatcher) thereis (STREQUAL tString (fetch type of (fetch intName of e] then (SETUPPUP pup (fetch SOURCE of pup) (fetch SOURCESKT of pup) \PT.IAMECHO (fetch PUPID of pup) \RPCSocket) (FILLPUPSOURCE pup) (SENDPUP \RPCSocket pup)) (RELEASE.PUP pup)) (if (fetch RPCP of pup) then (\RoutePup pup) else (PUPDEBUGGING T "ignoring non-RPC pup") (RELEASE.PUP pup))) elseif (TIMEREXPIRED? timer) then (* check the vacant connections for moribund ones) (SETQ \RPCConnections (for c in \RPCConnections when (AND (add (fetch age of c) 1) (ILEQ (fetch age of c) \ConnectionTimeout)) collect c)) (\RPCHandles←(for h in \RPCHandles when (PROCESSP h:process) collect h)) (timer←(SETUPTIMER \CheckConnectionsInterval timer))) (GO LP]) (\RPCServerProc [LAMBDA (pup) (* ht: " 2-Aug-85 09:38") (* At least one of these is running for each connection being supported by a server) (PROG (handle localId event) (handle←(\NewProcess T)) (localId←handle:localId) (event←handle:event) (* * this prog here just to protect the server) TopLp (NLSETQ (PROG (expInst RPCConnection RPCCallCount conv decrypted) (if (NOT pup) then (GO WAIT)) TOPLP (decrypted←NIL) (if RPCConnection←(for c in \RPCConnections thereis (* note that the first term of the AND means we will never find a conv. we started - packets for them had better be being waited for) (AND c:remoteHost=pup:SOURCE c:activity=pup:sourcePSB (IEQP c:convId pup:PUPCONTENTS:conversationID))) then (if conv←RPCConnection:conv then (if (NOT (\DecryptPup pup conv)) then (PUPDEBUGGING T "decryption failed") (GO BAD))) (decrypted←T) (if pup:PUPCONTENTS:callAgent~=pup:sourcePSB then (* phooey) (PUPDEBUGGING T "source/callAgent mismatch") (GO BAD)) (if (AND pup:class=\clCall (IGREATERP pup:PUPCONTENTS:callCount RPCConnection:callCnt)) then (if pup:PUPCONTENTS:packetSeq~=1 then (PUPDEBUGGING T "non-1 packetSeq") (GO BAD)) (* genuine new call) else (GO OLD)) elseif pup:class=\clCall then (* need a new RPCConnection) (if conv← (enable CallFailed => (PUPDEBUGGING T "can't get Conn state") (exit) (\GetConnectionState pup)) then (if conv=T then conv←NIL) (* GCS will have done any necessary decryption) (push \RPCConnections (RPCConnection←(create Connection conv ← conv convId ← pup:PUPCONTENTS:conversationID remoteHost ← pup:SOURCE activity ← pup:PUPCONTENTS:callAgent callCnt ← -1))) else (GO BAD)) else (GO OLD)) LP (RPCConnection:age←0) (RPCConnection:processId←localId) (RPCConnection:callCnt←RPCCallCount←pup:PUPCONTENTS:callCount) (* turn the pup around) (\SetupResponse pup) (if pup:EOM then (pup:PUPCONTENTS:MDSBase←\rcResult) (* note we overwrite the MDSBase hint here, but as we don%'t use it it doesn%'t matter)) (if (AND expInst←(ASSOC pup:PUPCONTENTS:dispatcherHint ExportTable) (IEQP expInst:dispId pup:PUPCONTENTS:dispatcherId)) then (pup:dataOffset←\RPCLupineArgStart) (enable unwindRequested => (goto uw) CallFailed => (PUPDEBUGGING T "Call Failed " arg) (goto lp) LispError => (if \RPCDebugServers then (reject) else (\ServerError arg RPCConnection) (goto lp)) RPCAbortMe? => (if (AND RPCConnection:remoteHost=arg:1 RPCConnection:activity=arg:2 (IEQP RPCConnection:convId arg:3) (IEQP RPCCallCount arg:4)) then (goto lp) else (sresume T)) (pup←(APPLY* expInst:dispatcher pup pup:PUPCONTENTS:request conv)) uw -> (pup←$SignalArg$) (\SetupResponse pup) (pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen)) (pup:PUPCONTENTS:MDSBase←\rcResult) lp -> (pup←NIL)) else (pup:PUPCONTENTS:MDSBase←\rcUnbound) (pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen))) (if pup then pup← (enable LispError => (if \RPCDebugServers then (reject) else (\ServerError arg \RPCConnections) (exit)) CallFailed => (* NIL into pup) (exit) (\ExchangePackets pup \stEndCall NIL conv))) (if pup then (GO LP)) WAIT (* Exchange left us nothing to go on with) (handle←(\FindHandle (THIS.PROCESS))) (\ClearWanting handle) (* just in case) (if (ILESSP (LENGTH \RPCIdlers) \RPCMaxIdlers) then (push \RPCIdlers handle) (until pup←handle:newPup do (AWAIT.EVENT event)) (* wait to be pressed into service again) (handle:newPup←NIL) (GO TOPLP) else (add \RPCNumberOfServers -1) (\KillHandle handle) (PROCESS.RETURN)) OLD (* old - actually other cases exist - should be checked and errors raised) (if (AND RPCConnection pup:destPSB~=0 pup:destPSB~=RPCConnection:processId) then (* genuine bad hint) (if ~decrypted then (SHOULDNT "not decrypted OLD??") elseif conv then (\EncryptPup pup conv) (* !)) (\RoutePup pup T) (pup←NIL) (GO WAIT)) (if [AND pup:EOM pup:ack (OR pup:class=\clData (if handle←(ASSOC pup:destPSB \RPCHandles) then (AND (NOT (\Wanting pup:destPSB)) (NOT (FMEMB handle:process \RPCIdlers)) handle:process~=(THIS.PROCESS)) elseif (AND pup:destPSB=0 RPCConnection) then (pup:destPSB←RPCConnection:processId) (if ~decrypted then (SHOULDNT "not decrypted OLD??2") elseif conv then (\EncryptPup pup conv) (* !)) (\RoutePup pup) (pup←NIL) (GO WAIT] then (\SetupResponse pup) (pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen)) (pup:sourcePSB←(if handle then handle:localId else 0)) (FILLPUPSOURCE pup) (pup:class←\clAck) (pup:EOM←T) (pup:ack←NIL) (if (AND decrypted conv) then (\EncryptPup pup conv)) (SENDPUP \RPCSocket pup) else (PUPDEBUGGING T "throwing away stale packet")) BAD (RELEASE.PUP pup) (pup←NIL) (GO WAIT))) (pup←NIL) (GO TopLp]) (\RoutePup [LAMBDA (pup badHint) (* ht: "27-Sep-84 09:11") (PROG (handle) (if (AND ~badHint handle←(\Wanting pup:destPSB)) then (* try the hint) (\ClearWanting handle) (handle:newPup←pup) (NOTIFY.EVENT handle:event T) else (if badHint then (pup:destPSB←0)) (if handle←(pop \RPCIdlers) then (handle:newPup←pup) (NOTIFY.EVENT handle:event T) elseif (ILESSP \RPCNumberOfServers \RPCMaxServers) then (add \RPCNumberOfServers 1) (ADD.PROCESS < '\RPCServerProc pup>) else (RELEASE.PUP pup) (PUPDEBUGGING T "No room for new server - ignoring call") (RETURN)) (BLOCK) (* Let it get started)]) (\ExchangePackets [LAMBDA (pup state signalDispatcher conv) (* ht: "28-Sep-84 02:25") (* = RPCPktIO.PktExchange) (PROG (newPup acked (handle (\FindHandle (THIS.PROCESS))) transCount transTimeout pingTimeout callCount pktSeq callAgent) RLP (pingTimeout←\RPCPingTimeout) (transCount←0) (transTimeout←\RPCRetransTimeout+\RPCDelayPerHop*(CheapHopsToNet pup:DESTNET)) (FILLPUPSOURCE pup) (pup:sourcePSB←handle:localId) (if pup:PUPCONTENTS:packetSeq=0 then (* new call) (SELECTC state (\stCall (PUPDEBUGGING ",20a") (replace class of pup with \clCall) (replace EOM of pup with T) (replace ack of pup with NIL)) (\stSending (PUPDEBUGGING ",20b") (replace class of pup with \clCall) (replace EOM of pup with NIL) (replace ack of pup with T)) (\stAuthReq (PUPDEBUGGING ",20c") (replace class of pup with \clRFA) (replace EOM of pup with T) (replace ack of pup with NIL)) (SHOULDNT '1a)) (pup:PUPCONTENTS:callCount←(add \CallCnt 1)) (pup:PUPCONTENTS:packetSeq←1) else (SELECTC state (\stEndCall (* (PUPDEBUGGING "," 11)) (replace class of pup with \clData) (replace EOM of pup with T) (replace ack of pup with NIL)) (\stReceiving (replace class of pup with \clAck) (PUPDEBUGGING ",11a") (replace EOM of pup with T) (replace ack of pup with NIL) (SETQ acked T)) (\stCall (PUPDEBUGGING ",11b") (replace class of pup with \clData) (replace EOM of pup with T) (replace ack of pup with NIL)) (\stSending (PUPDEBUGGING ",11c") (replace class of pup with \clData) (replace EOM of pup with NIL) (replace ack of pup with T)) (SHOULDNT 1)) (if state~=\stReceiving then (add pup:PUPCONTENTS:packetSeq 1))) (callCount←pup:PUPCONTENTS:callCount) (pktSeq←pup:PUPCONTENTS:packetSeq) (callAgent←pup:PUPCONTENTS:callAgent) (\SetWanting handle) PingTrans (if conv then (\EncryptPup pup conv)) Retrans (SENDPUP \RPCSocket pup) LP (if newPup←handle:newPup elseif (AWAIT.EVENT handle:event (if acked then pingTimeout else transTimeout))=PSTAT.TIMEDOUT then (if \RPCDebugWaitForever then (GO LP) else (if acked then (pup:class←\clAck) (pup:ack←T) (pup:EOM←T) (pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen)) (pingTimeout←(MIN \RPCMaxPingTimeout (LLSH pingTimeout 1))) (acked←NIL) (GO PingTrans) else (pup:ack←T) (if (IGREATERP (add transCount 1) \RPCMaxTransCount) then (RELEASE.PUP pup) (Signal 'CallFailed \ecTimeout)) (transTimeout←transTimeout+\RPCTransTimeoutIncr) (GO Retrans) (* wait for someone to give us a pup))) else (GO LP)) (handle:newPup←NIL) (if newPup:class=\clRFA then (\ReplyToRFA pup newPup conv callAgent callCount) (\SetWanting handle) (GO LP)) (if (AND conv (IEQP pup:PUPCONTENTS:conversationID newPup:PUPCONTENTS:conversationID) newPup:SOURCE=pup:DEST) then (* * we don%'t check for success, as e.g. ack packets will not have correct checksum) (\DecryptPup newPup conv)) (if (AND (IEQP pup:PUPCONTENTS:conversationID newPup:PUPCONTENTS:conversationID) newPup:SOURCE=pup:DEST newPup:PUPCONTENTS:callAgent=callAgent) then (* (PUPDEBUGGING "," 4)) (* related to us) (if (IEQP newPup:PUPCONTENTS:callCount callCount) then (PUPDEBUGGING "," "5") (* our call) (if pktSeq+1=newPup:PUPCONTENTS:packetSeq then (PUPDEBUGGING "," "6") (* next in line) (SELECTC state ((LIST \stSending \stEndCall) (SHOULDNT 2)) ((LIST \stCall \stReceiving \stAuthReq) (PUPDEBUGGING "," "12") (SELECTC (fetch class of newPup) (\clData (PUPDEBUGGING "," "14")) (\clAck (SETQ acked T) (RELEASE.PUP newPup) (\SetWanting handle) (GO LP)) ((LIST \clCall \clRFA) (PUPDEBUGGING "," "15") (SHOULDNT 3)) (SHOULDNT 4))) (SHOULDNT 6)) elseif pktSeq=newPup:PUPCONTENTS:packetSeq then (PUPDEBUGGING "," "7") (* same as us) (SELECTC (fetch class of newPup) [\clAck (PUPDEBUGGING "," "16") (if (EQ (fetch class of pup) \clCall) then (replace destPSB of pup with (fetch sourcePSB of newPup)) (* update hint as this pup gets reused in multipkt calls) ) (SETQ acked T) (SELECTC state ((LIST \stSending \stEndCall) (PUPDEBUGGING "," "16a") (RELEASE.PUP newPup) (SETQ newPup) (* fall out empty-handed) ) (PROGN (PUPDEBUGGING ",16b") (* call, authReq, or receiving - just discard and wait, someone else is working on it) (RELEASE.PUP newPup) (\SetWanting handle) (GO LP] ((LIST \clData \clCall) (* retransmission) (PUPDEBUGGING ",7a") (SELECTC state (\stReceiving (PUPDEBUGGING ",7a1") (if (fetch ack of newPup) then (PUPDEBUGGING ",7a1a") (RELEASE.PUP newPup) (\SetWanting handle) (GO Retrans) else (PUPDEBUGGING ",7a1b") (RELEASE.PUP newPup) (\SetWanting handle) (GO LP))) (SHOULDNT 8))) (\clRFA (SHOULDNT 9)) (SHOULDNT 10)) elseif (ILESSP newPup:PUPCONTENTS:packetSeq pktSeq) then (PUPDEBUGGING "," "8") (* earlier, discard) (RELEASE.PUP newPup) (\SetWanting handle) (GO LP) else (PUPDEBUGGING "," "1") (* future) (SHOULDNT 11)) elseif (AND (IGREATERP newPup:PUPCONTENTS:callCount callCount) state=\stEndCall) then (* (PUPDEBUGGING "," 9)) (if newPup:class~=\clCall then (PUPDEBUGGING "," "10") (SHOULDNT 12)) else (PUPDEBUGGING "," "2") (* shouldn%'t have come to us - wrong call) (\RoutePup newPup T) (\SetWanting handle) (GO LP)) else (PUPDEBUGGING "," "3") (* shouldn%'t have come to us - wrong conversation or remoteId) (\RoutePup newPup T) (\SetWanting handle) (GO LP)) (if newPup then (RELEASE.PUP pup) (* this is right for \stSending, not sure about \endCall) (if (AND newPup:PUPCONTENTS:MDSBase=\rcSignal state=\stCall signalDispatcher) then (pup←(\DoSignal signalDispatcher newPup conv)) (GO RLP)) (RETURN newPup) else (if conv then (* better fix up pup in case it gets reused - e.g. in \SendExtra) (pup:PUPCONTENTS:callCount←callCount) (pup:PUPCONTENTS:packetSeq←pktSeq) (pup:PUPCONTENTS:callAgent←callAgent)) (RETURN]) (\DoSignal [LAMBDA (disp pup conv) (* ht: "27-Sep-84 22:47") (* to allow us to be pinged if nec.) (\SetupResponse pup) (if pup:EOM then (pup:PUPCONTENTS:MDSBase←\rcResult)) pup:dataOffset←\RPCPupWordOvLen (enable unwindRequested => (* not at all sure about this) (exit) (pup←(APPLY* disp pup conv)) unwind -> (pup:PUPCONTENTS:MDSBase←\rcUnwind) (pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen)) (pup←(\ExchangePackets pup \stCall (FUNCTION CantCatchHere) conv)) (SELECTC (fetch MDSBase of (fetch PUPCONTENTS of pup)) (\rcResult) (\rcSignal (SHOULDNT 21)) (SHOULDNT 22))) pup]) ) (* Call management) (DEFINEQ (\StartCall [LAMBDA (socket disp conv) (* ht: "27-Jul-85 14:45") (\CheckRPC) (if (NOT socket) then (Signal 'CallFailed 'Unimported)) (PROG ((pup (ALLOCATE.PUP)) (handle (\NewProcess)) id) (SETUPPUP pup socket \RPCSocketNumber 96 0 \RPCSocket) (\SetupResponse pup (if conv then (id←conv:cId) (if (IEQP id:originatorC (ETHERHOSTNUMBER)) then (* cheat for efficiency - set originatorP bit to 0) (LOGAND id:count (CONSTANT (LOGXOR -1 32768))) elseif (IEQP id:originatorC handle:remoteId) then (* cheat for efficiency - set originatorP bit to 1) (LOGOR id:count (CONSTANT 32768)) else (Signal 'MisusedConversation)) else \RPCConvID) handle:localId handle:remoteId) (pup:PUPCONTENTS:packetSeq←0) (pup:PUPCONTENTS:MDSBase←disp:dMds) (pup:PUPCONTENTS:dispatcherHint←disp:hint) (pup:PUPCONTENTS:dispatcherId←disp:dId) (pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen)) (RETURN pup]) (\Call [LAMBDA (pup signalDispatcher conv) (* ht: " 8-Apr-85 07:58") pup← (enable AbortRemote => (\AbortRemote pup:DEST pup:sourcePSB pup:PUPCONTENTS:conversationID [if pup:destPSB~=0 then pup:destPSB else (fetch remoteId of (\FindHandle (THIS.PROCESS] pup:PUPCONTENTS:callCount conv) (\RELEASE.PUP pup) (goto aborted) (\ExchangePackets pup \stCall signalDispatcher conv) aborted -> (ERROR!)) (replace remoteId of (\FindHandle (THIS.PROCESS)) with pup:sourcePSB) (\SetupResponse pup) (SELECTC (fetch MDSBase of (fetch PUPCONTENTS of pup)) (\rcResult (replace dataOffset of pup with \RPCPupWordOvLen) pup) (\rcUnwind (Signal 'unwindRequested pup)) (\rcUnbound (Signal 'CallFailed \ecUnbound)) (SHOULDNT]) (\AbortRemote [LAMBDA (host src id remid callCnt conv) (* ht: " 8-Apr-85 07:16") (PROG (pup) (pup←(\StartCall host \BinderDisp conv)) (\AddPupWord pup 1) (* remote abort call index) (\AddPupSmallp pup src) (\AddPupSmallp pup remid) (\AddPupDblWord pup id) (\AddPupDblWord pup callCnt) (enable CallFailed => (printout T T "Attempt to abort remote process failed" T) (exit) (\RELEASE.PUP (\Call pup (FUNCTION CantCatchHere) conv)))]) (CantCatchHere [LAMBDA (l..cPup) (* ht: " 1-Aug-85 08:56") (HELP]) (\StartSignal [LAMBDA (pup) (* ht: " 5-SEP-83 14:37") pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen) pup:PUPCONTENTS:MDSBase←\rcSignal]) (\StartReturn [LAMBDA (pup) (* ht: " 4-SEP-83 18:23") (* Should really be a macro, but the stubs won't have access to the PUP record) pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen]) ) (* Local id maintenance) (DEFINEQ (\SetWanting [LAMBDA (handle) (* ht: " 5-SEP-83 08:07") (push \RPCWanting handle]) (\ClearWanting [LAMBDA (handle) (* ht: " 5-SEP-83 08:07") \RPCWanting←(DREMOVE handle \RPCWanting]) (\Wanting [LAMBDA (hint) (* ht: " 5-SEP-83 08:08") (FASSOC hint \RPCWanting]) (\NewHandleCnt [LAMBDA NIL (* ht: " 1-SEP-83 16:30") (do (if ~(SMALLP (add \HandleCnt 1)) then (\HandleCnt←1) (\HandleOverflow←T)) repeatwhile (AND \HandleOverflow (ASSOC \HandleCnt \RPCHandles))) \HandleCnt]) (\NewProcess [LAMBDA (newFlg) (* ht: "27-Sep-84 09:32") (PROG (process) (process←(THIS.PROCESS)) (RETURN (if (AND ~newFlg (\FindHandle process)) else (CAR (push \RPCHandles (create RPCHandle localId ←(\NewHandleCnt) event ←(CREATE.EVENT (PACK* 'Server \HandleCnt)) remoteId ← 0 process ← process]) (\FindHandle [LAMBDA (process) (* ht: " 4-SEP-83 18:45") (thereis h in \RPCHandles suchthat (EQ (fetch process of h) process]) (\KillHandle [LAMBDA (h) (* ht: " 8-Apr-85 09:00") (if h then \RPCHandles←(DREMOVE h \RPCHandles]) ) (* encryption utilities) (DEFINEQ (\EncryptPup [LAMBDA (pup conv) (* ht: "28-Sep-84 01:13") (* if we ever get here with an odd PUPLENGTH, disaster!) (PROG ((words ((LRSH pup:PUPLENGTH-\PUPOVLEN 1)+(CONSTANT \RPCCheckLength-\RPCClearHeaderLength))) nBlks check (cryptBase (\ADDBASE pup:PUPCONTENTS \RPCClearHeaderLength)) (end (LRSH pup:PUPLENGTH-\PUPOVLEN 1))) (nBlks←(words+\DESBlockSize-1)/\DESBlockSize) (check←nBlks*\DESBlockSize-words) (* checksum is number of rounding words) (RPTQ check (PROGN (PUTPUPWORD pup end 0) (add end 1))) (PUTPUPWORD pup end (\LONUM check)) (PUTPUPWORD pup end+1 (\HINUM check)) (add pup:PUPLENGTH (LLSH check+2 1)) (SELECTQ conv:level (CBCCheck (CryptData conv:convKey nBlks cryptBase cryptBase 'encrypt 'cbcCheck conv:iv)) ((ECB CBC) (Signal 'NotImplementedYet conv:level)) (SHOULDNT]) (\DecryptPup [LAMBDA (pup conv) (* ht: "26-Sep-84 18:19") (PROG ((nBlks (((LRSH pup:PUPLENGTH-\PUPOVLEN 1) -\RPCClearHeaderLength)/\DESBlockSize)) (cryptBase (\ADDBASE pup:PUPCONTENTS \RPCClearHeaderLength)) (checkAddr ((LRSH pup:PUPLENGTH-\PUPOVLEN 1) -\RPCCheckLength)) check) (SELECTQ conv:level (CBCCheck (CryptData conv:convKey nBlks cryptBase cryptBase 'decrypt 'cbcCheck conv:iv)) ((ECB CBC) (Signal 'NotImplementedYet conv:level)) (SHOULDNT)) (check←(\MAKENUMBER (GETPUPWORD pup checkAddr+1) (GETPUPWORD pup checkAddr))) (RETURN (AND (IGREATERP check -1) (ILESSP check \DESBlockSize]) ) (* Utilities) (DEFINEQ (\RPCOpenClosest [LAMBDA (PORTLIST type) (* ht: " 8-Apr-85 09:46") (* FIND THE "closest" respondant on portList. EchoMe polling to determine responsiveness is to pollSoc, connection will go to connSoc. We poll in order from nearest to farest by hop order, use broadcast on local net if appropriate, and hope not to engage too many folks before the real thing comes along. The basic structure of this is owed to Taft) (PROG (PUP SOC CNTIME BETWEENPROBE NEXTPORT PORT VAL LOCALFLG (MYNET ((ETHERHOSTNUMBER):PUPNET#))) (if PORTLIST←(for PORT in PORTLIST collect PORT unless (if PORT:1:PUPNET#=MYNET then LOCALFLG←T)) then PORTLIST←(SORT.PUPHOSTS.BY.DISTANCE PORTLIST)) (if LOCALFLG then (* if there were some local hosts on the list, remove them and add a broadcast port) (push PORTLIST (<(create PUPADDRESS PUPNET# ← MYNET PUPHOST# ← 0) >)) elseif PORTLIST=NIL then (RETURN)) (SOC←(\GETMISCSOCKET)) (CNTIME←(SETUPTIMER \CONNECTTIMEOUT)) (NEXTPORT←PORTLIST) (DISCARDPUPS SOC) (* clear out anything left over from other activities) (RETURN (do (if (OR BETWEENPROBE=NIL (TIMEREXPIRED? BETWEENPROBE)) then (PORT←(PROG1 NEXTPORT:1 NEXTPORT←(OR NEXTPORT::1 PORTLIST))) (PUP←(ALLOCATE.PUP)) (SETUPPUP PUP PORT:1 \RPCDefaultSocket \PT.ECHOME NIL SOC 'FREE) (PUTPUPSTRING PUP type) (SENDPUP SOC PUP) (BETWEENPROBE←(SETUPTIMER \BETWEENPROBEDELAY BETWEENPROBE))) (BLOCK) (if (AND (SETQ PUP (GETPUP SOC)) PUP:PUPTYPE=\PT.IAMECHO) then (RETURN <PUP:PUPSOURCE ! PUP:PUPSOURCESOCKET>)) repeatuntil (TIMEREXPIRED? CNTIME]) (\SetupResponse [LAMBDA (pup conv id dest) (* ht: " 4-SEP-83 18:23") (if conv then (pup:destPSB←dest) (pup:PUPCONTENTS:conversationID←conv) (pup:PUPCONTENTS:callAgent←id) else (* better be a pup from our interlocutor) (pup:destPSB←pup:sourcePSB) (pup:DEST←pup:SOURCE)) pup:DESTSKT←\RPCSocketNumber]) (\ReceiveExtra [LAMBDA (pup conv) (* ht: "28-Sep-84 01:27") pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen) pup←(\ExchangePackets pup \stReceiving (FUNCTION CantCatchHere) conv) (\SetupResponse pup) (if pup:EOM then (pup:PUPCONTENTS:MDSBase←\rcResult) (* note we overwrite the MDSBase hint here, but as we don%'t use it it doesn%'t matter)) pup:dataOffset←\RPCPupWordOvLen pup]) (\SendExtra [LAMBDA (pup conv) (* ht: "27-Jul-85 14:45") (if (\ExchangePackets pup \stSending (FUNCTION CantCatchHere) conv) then (HELP "shouldn't get an answer") else (pup:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen]) (CheapHopsToNet [LAMBDA (net) (* ht: " 2-SEP-83 15:13") (* don't do any work - fake it if not here) (PROG (e) (RETURN (if e←(FASSOC net \PUP.ROUTING.TABLE) then e:2 else (* guess high) 5]) (\CheckRPC [LAMBDA NIL (* ht: "22-JAN-83 14:40") (if ~(AND \BinderDisp (PROCESSP (FIND.PROCESS \RPCTopProc))) then (\RPCNotAliveErr]) (\RPCNotAliveErr [LAMBDA NIL (* ht: "10-JUN-83 10:20") (Signal (QUOTE RPCDead) "Please do InitRPC() and try again"]) (\ServerError [LAMBDA (arg handle) (* ht: "27-Sep-84 18:30") (printout T "Lisp error in server: " # (ERRORMESS arg:eMess) "saving arg and carrying on" T) (if (ILESSP (LENGTH \RPCServerErrors) \RPCMaxServerErrors) then \RPCServerErrors← < !! \RPCServerErrors <(GDATE) arg < ! handle>>>) (RELSTK arg:ePos]) (\InitRPCVars [LAMBDA NIL (* ht: " 3-Jan-85 13:23") \MatchAnyVersion←(create VersionRange) \NoDispDetails←(create DispDetails]) ) (DECLARE: DONTCOPY (DECLARE: EVAL@COMPILE [PUTPROPS FILLPUPSOURCE MACRO ((pup) (PROGN (* zero causes SENDPUP to do it) (replace PUPSOURCESOCKET of pup with 0) (replace PUPSOURCE of pup with 0] ) ) (* Authentication) (DEFINEQ (\ReplyToRFA [LAMBDA (call request conv activity callCount) (* ht: "26-Sep-84 19:54") (* = RPCSecurity.ReplyToRFA) (PROG (nonceID) (if [OR ~(IEQP request:PUPCONTENTS:callerConv call:PUPCONTENTS:conversationID) ~(for o from 0 to 3 always (* check the packet ID) (IEQP (\GETBASE request:PUPCONTENTS o+\RPCRFAcallerIDOffset) (\GETBASE call:PUPCONTENTS o+\RPCPktIDOffset] then (RELEASE.PUP request) (RETURN)) (request:dataOffset←(CONSTANT \RPCPupWordOvLen+\NonceIdOffset)) (nonceID←(\GetArgDblWord request)) (* turn the pup around) (\SetupResponse request) (FILLPUPSOURCE request) (request:sourcePSB←0) (request:PUPLENGTH←(CONSTANT \PUPOVLEN+\RPCPupByteOvLen)) (\AddPupDblWord request 0) (* the iv) (\AddPupDblWord request 0) (request:PUPCONTENTS:trueConv←call:PUPCONTENTS:conversationID) (add request:PUPLENGTH 4) (\AddPupWord request call:SOURCE) (\AddPupWord request activity) (\AddPupDblWord request callCount) (\AddPupDblWord request nonceID+1) (if (IEQP call:PUPCONTENTS:conversationID \RPCConvID) then (* we started this, in the clear) (\AddPupWord request 0) (\AddPupWord request 0) (* auth. lenght - needed to get pup length right) (* level = none) else (* encrypted - oh boy) (if call:PUPCONTENTS:conversationID:originatorP=1 then (Signal 'NotMeBoss)) (\AddPupWord request 4) (* cheat - this is CBCCheck, the only thing we know) (\BLT (\ADDBASE request:PUPCONTENTS \RPCPupWordOvLen) conv:iv:ARRAYP.BASE 4) (CryptData conv:convKey \RPCRespCKBlocks (\ADDBASE request:PUPCONTENTS \RPCPupWordOvLen) (\ADDBASE request:PUPCONTENTS \RPCPupWordOvLen) 'encrypt 'cbcCheck \RPCNullSeed) (\AddPupWord request (ARRAYSIZE conv:authenticator)) (for i from 0 to (ARRAYSIZE conv:authenticator)+-1 do (\AddPupWord request (ELT conv:authenticator i))) (\PutBinderString request conv:caller)) (request:class←\clData) (request:EOM←T) (request:ack←NIL) (add request:PUPCONTENTS:packetSeq 1) (SENDPUP \RPCSocket request) (RELEASE.PUP request) (RETURN T]) (\GetConnectionState [LAMBDA (pup) (* ht: "27-Sep-84 18:49") (if \RPCDontBotherWithRFA then T else (PROG ((rfa (ALLOCATE.PUP)) (nonceId (CLOCK)) response level conv) (SETUPPUP rfa pup:SOURCE \RPCSocketNumber 96 0 \RPCSocket) (rfa:PUPCONTENTS:callerConv←pup:PUPCONTENTS:conversationID) (for o from 0 to 3 do (\PUTBASE rfa:PUPCONTENTS o+\RPCRFAcallerIDOffset (\GETBASE pup:PUPCONTENTS o+\RPCPktIDOffset))) (rfa:PUPLENGTH←(CONSTANT \RPCPupByteOvLen+\PUPOVLEN+(LLSH \NonceIdOffset 1))) (\AddPupDblWord rfa nonceId) (\SetupResponse rfa \RPCConvID 0 pup:sourcePSB) (rfa:PUPCONTENTS:packetSeq←0) (response←(\ExchangePackets rfa \stAuthReq)) (if (ILESSP response:PUPLENGTH-\PUPOVLEN 26) then (PUPDEBUGGING T "too small") (RETURN)) (SELECTQ (level←(GETPUPWORD response (CONSTANT \RPCPupWordOvLen+12))) (0 (* no encryption - fine) NIL) ((1 2 3) (HELP "level not implemented yet" level)) [4 (* CBCCheck encryption - we can do it) (PROG ((kb (CorrectParity (COPYARRAY DESNullKey))) (tempKey (ARRAY 8 '(BITS 8) 0 0)) iv) (DecryptBlock kb (\ADDBASE response:PUPCONTENTS (CONSTANT \RPCAuthenticatorOffset+\RPCAuthKyPos)) (\ADDBASE response:PUPCONTENTS (CONSTANT \RPCAuthenticatorOffset+\RPCAuthKyPos))) (\BLT tempKey:ARRAYP.BASE (\ADDBASE response:PUPCONTENTS (CONSTANT \RPCAuthenticatorOffset+\RPCAuthKyPos)) 4) (CryptData tempKey (GETPUPWORD response (CONSTANT \RPCPupWordOvLen+13)) /\DESBlockSize-2 (\ADDBASE response:PUPCONTENTS (CONSTANT \RPCAuthenticatorOffset+\RPCAuthConvKeyPos)) (\ADDBASE response:PUPCONTENTS (CONSTANT \RPCAuthenticatorOffset+\RPCAuthConvKeyPos)) 'decrypt 'cbcCheck \RPCNullSeed) (DecryptBlock kb (\ADDBASE response:PUPCONTENTS (CONSTANT \RPCAuthenticatorOffset+\RPCAuthConvKeyPos)) (\ADDBASE response:PUPCONTENTS (CONSTANT \RPCAuthenticatorOffset+\RPCAuthConvKeyPos))) (\BLT tempKey:ARRAYP.BASE (\ADDBASE response:PUPCONTENTS (CONSTANT \RPCAuthenticatorOffset+\RPCAuthConvKeyPos)) 4) (CryptData tempKey \RPCRespCKBlocks (\ADDBASE response:PUPCONTENTS \RPCPupWordOvLen) (\ADDBASE response:PUPCONTENTS \RPCPupWordOvLen) 'decrypt 'cbcCheck \RPCNullSeed) (conv←(create Conversation cId ←(create ConversationID originatorC ←(if response:PUPCONTENTS:trueConv:originatorP=0 then (GETPUPWORD response (CONSTANT \RPCPupWordOvLen+6)) else (ETHERHOSTNUMBER)) count ←(LOGAND response:PUPCONTENTS:trueConv -32769)) level ← 'CBCCheck iv ←(PROG1 iv←(ARRAY 8 '(BITS 8) 0 0) (\BLT iv:ARRAYP.BASE (\ADDBASE response:PUPCONTENTS \RPCPupWordOvLen) 4)) caller ←(\GETBASESTRING response:PUPCONTENTS (CONSTANT (LLSH \RPCAuthenticatorOffset+\RPCAuthNamePos+\RPCStringHeaderLength 1)) (GETPUPWORD response (CONSTANT \RPCAuthenticatorOffset+\RPCAuthNamePos))) convKey ←(COPYARRAY tempKey))) (OR (\DecryptPup pup conv) (PUPDEBUGGING T "didn't decrypt") (RETURN] (SHOULDNT)) (if ~[IEQP nonceId+1 (\MAKENUMBER (GETPUPWORD response (CONSTANT \RPCPupWordOvLen+10+1)) (GETPUPWORD response (CONSTANT \RPCPupWordOvLen+10] then (PUPDEBUGGING T "nonceID#") (RETURN)) (if ~(AND (IEQP response:PUPCONTENTS:trueConv pup:PUPCONTENTS:conversationID) pup:SOURCE=(GETPUPWORD response (CONSTANT \RPCPupWordOvLen+6)) pup:PUPCONTENTS:callAgent=(GETPUPWORD response (CONSTANT \RPCPupWordOvLen+7))) then (PUPDEBUGGING T "connection wrong") (RETURN)) (if ~[IEQP pup:PUPCONTENTS:callCount (\MAKENUMBER (GETPUPWORD response (CONSTANT \RPCPupWordOvLen+9)) (GETPUPWORD response (CONSTANT \RPCPupWordOvLen+8] then (PUPDEBUGGING T "callCount wrong") (RETURN)) (RETURN (OR conv T]) ) (* Misc. constants) (DECLARE: DONTCOPY (DECLARE: EVAL@COMPILE (RPAQQ \RPCLupineArgStart 11) (RPAQQ \RPCPupWordOvLen 10) (RPAQQ \RPCPupByteOvLen 20) (RPAQQ \RPCMaxDataOffset 264) (RPAQQ \RPCMaxPupLength 550) (RPAQQ \RPCRetransTimeout 1000) (RPAQQ \RPCPingTimeout 5000) (RPAQQ \RPCMaxPingTimeout 60000) (RPAQQ \RPCMaxTransCount 14) (RPAQQ \RPCTransTimeoutIncr 100) (RPAQQ \RPCDelayPerHop 500) (RPAQQ \NonceIdOffset 6) (RPAQQ \RPCPktIDOffset 2) (RPAQQ \RPCRFAcallerIDOffset 12) (RPAQQ \PT.ECHOME 1) (RPAQQ \PT.IAMECHO 2) (RPAQQ \PUPOVLEN 22) (RPAQQ \RPCStringHeaderLength 2) (RPAQQ \RPCCheckLength 2) (RPAQQ \RPCClearHeaderLength 2) (RPAQQ \RPCRespCKBlocks 3) (CONSTANTS (\RPCLupineArgStart 11) (\RPCPupWordOvLen 10) (\RPCPupByteOvLen 20) (\RPCMaxDataOffset 264) (\RPCMaxPupLength 550) (\RPCRetransTimeout 1000) (\RPCPingTimeout 5000) (\RPCMaxPingTimeout 60000) (\RPCMaxTransCount 14) (\RPCTransTimeoutIncr 100) (\RPCDelayPerHop 500) (\NonceIdOffset 6) (\RPCPktIDOffset 2) (\RPCRFAcallerIDOffset 12) (\PT.ECHOME 1) (\PT.IAMECHO 2) (\PUPOVLEN 22) (\RPCStringHeaderLength 2) (\RPCCheckLength 2) (\RPCClearHeaderLength 2) (\RPCRespCKBlocks 3)) ) (DECLARE: EVAL@COMPILE (RPAQQ \stReceiving receiving) (RPAQQ \stSending sending) (RPAQQ \stCall call) (RPAQQ \stEndCall endCall) (RPAQQ \stAuthReq authReq) (CONSTANTS (\stReceiving (QUOTE receiving)) (\stSending (QUOTE sending)) (\stCall (QUOTE call)) (\stEndCall (QUOTE endCall)) (\stAuthReq (QUOTE authReq))) ) (DECLARE: EVAL@COMPILE (RPAQQ \rcResult 0) (RPAQQ \rcUnbound 1) (RPAQQ \rcSignal 2) (RPAQQ \rcUnwind 3) (RPAQQ \rcProtocol 4) (CONSTANTS (\rcResult 0) (\rcUnbound 1) (\rcSignal 2) (\rcUnwind 3) (\rcProtocol 4)) ) (DECLARE: EVAL@COMPILE (RPAQQ \clCall 0) (RPAQQ \clData 1) (RPAQQ \clAck 2) (RPAQQ \clRFA 4) (CONSTANTS (\clCall 0) (\clData 1) (\clAck 2) (\clRFA 4)) ) (DECLARE: EVAL@COMPILE (RPAQQ \ecUnbound unbound) (RPAQQ \ecTimeout timeout) (CONSTANTS (\ecUnbound (QUOTE unbound)) (\ecTimeout (QUOTE timeout))) ) (DECLARE: EVAL@COMPILE (RPAQQ \RPCAuthKyPos 0) (RPAQQ \RPCAuthConvKeyPos 8) (RPAQQ \RPCAuthTimePos 16) (RPAQQ \RPCAuthNamePos 18) (RPAQQ \RPCAuthFixedLength 18) (RPAQQ \RPCAuthenticatorOffset 24) (CONSTANTS (\RPCAuthKyPos 0) (\RPCAuthConvKeyPos 8) (\RPCAuthTimePos 16) (\RPCAuthNamePos 18) (\RPCAuthFixedLength 18) (\RPCAuthenticatorOffset 24)) ) ) (* Global parameters) (RPAQ? \RPCNullSeed (ARRAY 8 (QUOTE (BITS 8)) 0 0)) (RPAQ? \HandleCnt 0) (RPAQ? \HandleOverflow ) (RPAQ? \ConnectionTimeout 6) (RPAQ? \CheckConnectionsInterval 60000) (RPAQ? \RPCConnections ) (RPAQ? \RPCConversations ) (RPAQ? \RPCLastConversation ) (RPAQ? \RPCHandles ) (RPAQ? \RPCWanting ) (RPAQ? \RPCDefaultSocket 30) (RPAQ? \BinderDisp ) (RPAQ? \RPCConvID ) (RPAQ? \RPCDontBotherWithRFA ) (RPAQ? \RPCDebugWaitForever ) (RPAQ? \RPCNumberOfServers 0) (RPAQ? \RPCMaxServers 5) (RPAQ? \RPCMaxIdlers 3) (RPAQ? \RPCIdlers ) (RPAQ? \RPCDebugServers ) (RPAQ? \RPCServerErrors ) (RPAQ? \RPCMaxServerErrors 25) (DECLARE: EVAL@COMPILE [PUTDEF (QUOTE \RPCScratchStream) (QUOTE RESOURCES) (QUOTE (NEW (OPENSTREAM (QUOTE {NODIRCORE}) (QUOTE BOTH) (QUOTE NEW)) FREE (SETFILEPTR (SETQ \\RPCScratchStream.GLOBALRESOURCE (PROGN . ARGS)) 0] ) (DECLARE: DOEVAL@COMPILE DONTCOPY (GLOBALVARS \RPCNullSeed \HandleCnt \HandleOverflow \RPCConnections \RPCConversations \RPCLastConversation \RPCHandles \RPCWanting \RPCDefaultSocket \BinderDisp \CallCnt \RPCConvID \RPCDontBotherWithRFA \RPCDebugWaitForever \RPCNumberOfServers \RPCMaxServers \RPCMaxIdlers \RPCIdlers \ConnectionTimeout \CheckConnectionsInterval \RPCDebugServers \RPCServerErrors \RPCMaxServerErrors) ) (DECLARE: DOEVAL@COMPILE DONTCOPY (GLOBALVARS ExportTable \RPCTopProc \RPCSocket \RPCSocketNumber ExportCount) ) (* The block records here reflect Andrew's layout of the transport mechanism in {INDIGO}<CEDAR>RPC>RPCPkt.mesa and should track any changes made there) (DECLARE: DONTCOPY [DECLARE: EVAL@COMPILE (RECORD Connection (((conv . convId) remoteHost . callCnt) processId activity . age)) (RECORD Conversation (((authenticator . cId) convKey . iv) level callee . caller)) (RECORD ConversationID (originatorC . count)) (RECORD DispDetails (dId dMds hint) dMds ← 0 dId ← \NoDispatcher hint ← 0) (RECORD ExportTableEntry (dispHint dispId mds dispatcher intName stubProt) mds ← 0 stubProt ← \MatchAnyVersion) (RECORD ImportInstance (host . dispDetails)) (RECORD InterfaceName (type instance version) version ← \MatchAnyVersion) (BLOCKRECORD PktConversationID ((ls BITS 16) (originatorP BITS 1) (ms BITS 15))) (BLOCKRECORD RPCBinderArgs ((NIL FIXP) (NIL FIXP) (NIL FIXP) (NIL FIXP) (NIL FIXP) (request WORD) (bindType WORD) (bindInstance WORD))) (RECORD RPCHandle (localId (remoteId . newPup) event . process)) (BLOCKRECORD RPCPup ((NIL 32 WORD) (destPSB WORD) (sourcePSB WORD)) [ACCESSFNS RPCPup ([RPCP (EQ (LOGAND (fetch (PUP PUPTYPE) of DATUM) 224) 96) (LAMBDA (D N) (COND (N (change (fetch (PUP PUPTYPE) of D) (LOGOR DATUM 96] [EOM (NEQ (LOGAND (fetch (PUP PUPTYPE) of DATUM) 16) 16) (LAMBDA (D N) (change (fetch (PUP PUPTYPE) of D) (COND [N (LOGAND DATUM (CONSTANT (LOGXOR 255 16] (T (LOGOR DATUM 16] [ack (EQ (LOGAND (fetch (PUP PUPTYPE) of DATUM) 8) 8) (LAMBDA (D N) (change (fetch (PUP PUPTYPE) of D) (COND (N (LOGOR DATUM 8)) (T (LOGAND DATUM (CONSTANT (LOGXOR 255 8] [class (LOGAND (fetch (PUP PUPTYPE) of DATUM) 7) (LAMBDA (D N) (change (fetch (PUP PUPTYPE) of D) (LOGOR (LOGAND DATUM (CONSTANT (LOGXOR 255 7))) N] (dataOffset (fetch (ETHERPACKET EPUSERFIELD) of DATUM) (replace (ETHERPACKET EPUSERFIELD) of DATUM with NEWVALUE]) (BLOCKRECORD RPCPupContents ((conversationID FIXP) (callAgent WORD) (callCountLo WORD) (callCountHi WORD) (packetSeq WORD) (MDSBase WORD) (dispatcherIdLo WORD) (dispatcherIdHi WORD) (dispatcherHint WORD)) [ACCESSFNS RPCPupContents ([dispatcherId [LAMBDA (D) (\MAKENUMBER (fetch dispatcherIdHi of D) (fetch dispatcherIdLo of D] (LAMBDA (D N) (replace dispatcherIdHi of D with (\HINUM N)) (replace dispatcherIdLo of D with (\LONUM N] (callCount [LAMBDA (D) (\MAKENUMBER (fetch callCountHi of D) (fetch callCountLo of D] (LAMBDA (D N) (replace callCountHi of D with (\HINUM N)) (replace callCountLo of D with (\LONUM N]) (BLOCKRECORD RPCRFAResponse ((NIL FIXP) (NIL FIXP) (NIL FIXP) (NIL FIXP) (NIL FIXP) (NIL FIXP) (NIL FIXP) (trueConv FIXP))) (BLOCKRECORD RPCRFARequest ((NIL FIXP) (NIL FIXP) (NIL FIXP) (NIL FIXP) (NIL FIXP) (callerConv FIXP))) (RECORD VersionRange (first . last) first ← 1 last ← 0) ] ) (RPAQQ \NoDispatcher 0) (RPAQQ \MatchAnyVersion NIL) (RPAQQ \NoDispDetails NIL) (\InitRPCVars) (DECLARE: DOEVAL@COMPILE DONTCOPY (GLOBALVARS \NoDispatcher \MatchAnyVersion \NoDispDetails) ) (* adding stuff to pups) (DEFINEQ (\PutBinderString [LAMBDA (pup string) (* ht: "13-JAN-83 15:32") (if string then (\AddPupWord pup (NCHARS string)) (\AddPupWord pup (NCHARS string)) (\PUTPUPSTRING pup string) (if (ODDP pup:PUPLENGTH) then (add pup:PUPLENGTH 1)) (LRSH pup:PUPLENGTH-\RPCPupByteOvLen-\PUPOVLEN 1) else 0]) (\AddRPCDispDetails [LAMBDA (pup disp) (* ht: "27-Sep-84 22:52") (\AddPupWord pup disp:dMds) (\AddPupDblWord pup disp:dId) (\AddPupWord pup disp:hint]) (\AddRPCVersion [LAMBDA (pup version) (* ht: "10-SEP-82 22:26") (\AddPupWord pup version:first) (\AddPupWord pup version:last]) (\AddPupDblWord [LAMBDA (pup dblWord conv) (* ht: "27-Sep-84 22:53") (* ********** Note Inversion!!!!! ***********) (\AddPupWord pup (\LONUM dblWord) conv) (\AddPupWord pup (\HINUM dblWord) conv]) (\AddPupWord [LAMBDA (pup word conv) (* ht: "27-Jul-85 15:11") (if (IGEQ pup:PUPLENGTH \RPCMaxPupLength) then (\SendExtra pup conv)) (PUTPUPWORD pup (LRSH pup:PUPLENGTH-\PUPOVLEN 1) word) (add pup:PUPLENGTH 2]) (\AddPupEnum [LAMBDA (pup type val conv) (* ht: "27-Sep-84 22:59") (\AddPupWord pup (for i from 0 as t in type do (if t=val then (RETURN i)) finally (Signal 'BoundsCheck <val ! type>)) conv]) (\AddPupSmallp [LAMBDA (pup n conv) (* ht: "27-Sep-84 22:59") (\AddPupWord pup (if (ILESSP n 0) then n+65536 else n) conv]) (\AddPupBoolean [LAMBDA (pup bool conv) (* ht: "27-Sep-84 22:59") (\AddPupWord pup (if bool then 1 else 0) conv]) (\MarshalStream [LAMBDA (pup parm stream conv) (* ht: "27-Jul-85 15:11") (* Note that the parm argument is ignored - only needed for output) (if (STRINGP stream) then (\MarshalString pup stream conv) else (if (IGREATERP pup:PUPLENGTH+4 \RPCMaxPupLength) then (* in next pup) (\SendExtra pup conv)) (if stream then (if (NOT (TYPENAMEP stream 'STREAM)) then stream←(GETSTREAM stream)) (SETFILEPTR stream 0) (\AddPupBoolean pup NIL conv) (PROG ((length (GETEOFPTR stream))) (\AddPupWord pup length conv) (if length~=0 then (\MoveToPup pup length stream 0 conv)) (RETURN stream)) else (* ni lstream) (\AddPupBoolean pup T) (\AddPupWord pup 0]) (\MarshalArb [LAMBDA (pup datum conv) (* ht: "30-Dec-85 16:18") (DECLARE (GLOBALVARS \\RPCScratchStream.GLOBALRESOURCE)) (* * this is a manually expanded WITH-RESOURCE because of some weird INTERMEZZO bug - ht) ([LAMBDA (\RPCScratchStream) (LET ((stream \RPCScratchStream:1)) (PROG1 (PROGN (PRIN4 datum stream) (\SETEOFPTR stream (GETFILEPTR stream)) (\MarshalStream pup NIL stream conv)) (SETFILEPTR stream 0) (push \\RPCScratchStream.GLOBALRESOURCE \RPCScratchStream] (if \\RPCScratchStream.GLOBALRESOURCE then (pop \\RPCScratchStream.GLOBALRESOURCE) else (CONS (OPENSTREAM '{NODIRCORE} 'BOTH 'NEW]) (\MarshalString [LAMBDA (pup string conv) (* jtm: "12-Mar-86 09:36") (* jtm: bug fix: string:STRINGP.FATSTRINGP dies if string is NIL. \MarshalAtom passes NIL, so added a test to make sure string was non-NIL.) (if (AND string string:STRINGP.FATSTRINGP) then (Signal 'NoFatStringsAllowedYet string) else (if (IGREATERP pup:PUPLENGTH+4 \RPCMaxPupLength) then (* in next pup) (\SendExtra pup conv)) (if string then (\AddPupBoolean pup NIL conv) (if (NOT (STRINGP string)) then string←(MKSTRING string)) (PROG ((length (NCHARS string))) (\AddPupWord pup length conv) (if length~=0 then (\MoveToPup pup length string:STRINGP.BASE string:STRINGP.OFFST conv)) (RETURN string)) else (* ni lstring) (\AddPupBoolean pup T) (\AddPupWord pup 0]) (\MarshalAtom [LAMBDA (pup atom conv) (* jtm: "10-Jan-86 14:23") (\MarshalString pup (if atom then (MKSTRING atom)) conv]) (\MoveToPup [LAMBDA (pup #bytes source offset conv) (* ht: "27-Jul-85 15:11") (if (IGREATERP #bytes+pup:PUPLENGTH \RPCMaxPupLength) then (\MoveToMultPups pup #bytes source offset conv) else (if (TYPENAMEP source 'STREAM) then (\BINS source pup:PUPCONTENTS pup:PUPLENGTH-\PUPOVLEN #bytes) else (\MOVEBYTES source offset pup:PUPCONTENTS pup:PUPLENGTH-\PUPOVLEN #bytes)) (add pup:PUPLENGTH (if (ODDP #bytes) then #bytes+1 else #bytes]) (\MoveToMultPups [LAMBDA (pup #bytes source offset conv) (* ht: "27-Jul-85 15:11") (PROG ((initBytes (\RPCMaxPupLength-pup:PUPLENGTH)) pcb) (pcb←(CONSTANT \RPCMaxPupLength-(\RPCPupByteOvLen+\PUPOVLEN))) (if (TYPENAMEP source 'STREAM) then (\BINS source pup:PUPCONTENTS pup:PUPLENGTH-\PUPOVLEN initBytes) else (\MOVEBYTES source offset pup:PUPCONTENTS pup:PUPLENGTH-\PUPOVLEN initBytes)) (add pup:PUPLENGTH initBytes) (bind mvd for bytesMoved from initBytes to #bytes by pcb do (\SendExtra pup conv) (mvd←(MIN #bytes-bytesMoved pcb)) (if (TYPENAMEP source 'STREAM) then (\BINS source pup:PUPCONTENTS pup:PUPLENGTH-\PUPOVLEN mvd) else (\MOVEBYTES source offset+bytesMoved pup:PUPCONTENTS pup:PUPLENGTH-\PUPOVLEN mvd)) (add pup:PUPLENGTH mvd)) (if (ODDP #bytes) then (add pup:PUPLENGTH 1]) ) (* Picking stuff out of pups) (DEFINEQ (\GetBinderString [LAMBDA (contents offset nextOffset) (* ht: "10-JUN-83 09:05") (* mesa strings are a word of length, an ignored word of maxLength and the bytes) (if offset~=nextOffset then (\GETBASESTRING contents \RPCPupByteOvLen+(LLSH offset 1)+ 4 (\GETBASE contents offset+\RPCPupWordOvLen]) (\GetArgDisp [LAMBDA (pup) (* ht: " 7-JAN-83 16:39") (create DispDetails dMds ←(\GetArgWord pup) dId ←(\GetArgDblWord pup) hint ←(\GetArgWord pup]) (\GetArgVersion [LAMBDA (pup) (* ht: " 7-JAN-83 16:30") (create VersionRange first ←(\GetArgWord pup) last ←(\GetArgWord pup]) (\GetArgDblWord [LAMBDA (pup conv) (* ht: "27-Sep-84 23:04") (* ******** Note Inversion *********) ([LAMBDA (loWord) (\MAKENUMBER (\GetArgWord pup conv) loWord] (\GetArgWord pup conv]) (\GetArgWord [LAMBDA (pup conv) (* ht: " 1-Aug-85 08:56") (if (IGEQ pup:dataOffset \RPCMaxDataOffset) then (* need another pup) (pup←l..cPup←(\ReceiveExtra pup conv))) (GETPUPWORD pup (PROG1 pup:dataOffset (add pup:dataOffset 1]) (\GetArgEnum [LAMBDA (pup type conv) (* ht: "27-Sep-84 23:03") (CAR (NTH type (\GetArgWord pup conv)+ 1]) (\GetArgBool (LAMBDA (pup conv) (* lmm "30-Apr-85 13:23") (NEQ (\GetArgWord pup conv) 0))) (\GetArgSmallp [LAMBDA (pup conv) (* ht: "27-Sep-84 23:02") (PROG (n) (RETURN (if (IGREATERP n←(\GetArgWord pup conv) 32767) then n-65536 else n]) (\UnmarshalString [LAMBDA (pup conv) (* jtm: "10-Jan-86 14:15") [if (IGREATERP (PLUS (fetch dataOffset of pup) 2) \RPCMaxDataOffset) then (* in next pup) (SETQ l..cPup (SETQ pup (\ReceiveExtra pup conv] (if (\GetArgBool pup conv) then (* ni lstring) (\GetArgWord pup conv) NIL else (PROG ((length (\GetArgWord pup conv)) str) (SETQ str (ALLOCSTRING length)) (if (NEQ length 0) then (\MoveFromPup pup (LRSH (PLUS length 1) 1) (fetch (STRINGP BASE) of str) conv)) (RETURN str]) (\UnmarshalStream [LAMBDA (pup stream conv) (* jtm: "10-Jan-86 14:23") (if (IGREATERP pup:dataOffset+2 \RPCMaxDataOffset) then (* in next pup) (l..cPup←pup←(\ReceiveExtra pup conv))) (if (\GetArgBool pup conv) then (* empty string) (\GetArgWord pup conv) NIL else (PROG (length (stream (stream:1))) (length←(\GetArgWord pup conv)) (OR (STREAMP stream) stream←(OPENSTREAM stream 'BOTH 'NEW)) (if length~=0 then (\MoveFromPup pup (LRSH length+1 1) stream conv)) (SETFILEPTR stream 0) (\SETEOFPTR stream length) (RETURN stream]) (\UnmarshalArb [LAMBDA (pup conv) (* ht: "30-Dec-85 16:13") (DECLARE (GLOBALVARS \\RPCScratchStream.GLOBALRESOURCE)) (* * this is a manually expanded WITH-RESOURCE because of some weird INTERMEZZO bug - ht) ([LAMBDA (\RPCScratchStream) (PROG1 (READ (\UnmarshalStream pup \RPCScratchStream conv)) (SETFILEPTR \RPCScratchStream:1 0) (push \\RPCScratchStream.GLOBALRESOURCE \RPCScratchStream] (if \\RPCScratchStream.GLOBALRESOURCE then (pop \\RPCScratchStream.GLOBALRESOURCE) else (CONS (OPENSTREAM '{NODIRCORE} 'BOTH 'NEW]) (\UnmarshalAtom [LAMBDA (pup conv) (* ht: "27-Sep-84 23:01") (MKATOM (\UnmarshalString pup conv]) (\MoveFromPup [LAMBDA (pup #words dest conv) (* ht: "27-Jul-85 15:11") (if (IGREATERP #words+pup:dataOffset \RPCMaxDataOffset) then (\MoveFromMultPups pup #words dest conv) else (if (TYPENAMEP dest 'STREAM) then (\BOUTS dest pup:PUPCONTENTS (LLSH pup:dataOffset 1) (LLSH #words 1)) else (\BLT dest (\ADDBASE pup:PUPCONTENTS pup:dataOffset) #words)) (add pup:dataOffset #words]) (\MoveFromMultPups [LAMBDA (pup #words dest conv) (* ht: " 1-Aug-85 08:56") (PROG ((initWords (\RPCMaxDataOffset-pup:dataOffset)) pcw) (pcw←\RPCMaxDataOffset-\RPCPupWordOvLen) (if (TYPENAMEP dest 'STREAM) then (\BOUTS dest pup:PUPCONTENTS (LLSH pup:dataOffset 1) (LLSH initWords 1)) else (\BLT dest (\ADDBASE pup:PUPCONTENTS pup:dataOffset) initWords)) (bind mvd for wordsMoved from initWords to #words by pcw do (pup←(\ReceiveExtra pup conv)) (if (TYPENAMEP dest 'STREAM) then (\BOUTS dest pup:PUPCONTENTS (LLSH pup:dataOffset 1) (LLSH mvd←(MIN #words-wordsMoved pcw) 1)) else (\BLT (\ADDBASE dest wordsMoved) (\ADDBASE pup:PUPCONTENTS pup:dataOffset) mvd←(MIN #words-wordsMoved pcw))) finally (add pup:dataOffset mvd)) (l..cPup←pup]) (\IncrDataOffset [LAMBDA (pup incr) (* ht: "25-Jul-85 18:07") (add pup:dataOffset incr]) (\IncrPupLength [LAMBDA (pup incr) (* ht: "26-Jul-85 14:51") (add pup:PUPLENGTH incr]) (\CurrentPupBase [LAMBDA (pup) (* ht: "25-Jul-85 18:06") (\ADDBASE pup:PUPCONTENTS pup:dataOffset]) (\CurrentPupPosition [LAMBDA (pup) (* ht: "26-Jul-85 14:54") (\ADDBASE pup:PUPCONTENTS (LRSH (IDIFFERENCE pup:PUPLENGTH \PUPOVLEN) 1]) (\CheckPupOverflow [LAMBDA (pup need) (* ht: " 1-Aug-85 09:23") (if (IGREATERP (IPLUS pup:PUPLENGTH need) \RPCMaxPupLength) then (\SendExtra pup l..conv]) (\CheckPupExhausted [LAMBDA (pup need) (* ht: " 1-Aug-85 09:22") (if (IGREATERP (IPLUS pup:dataOffset need) \RPCMaxDataOffset) then l..cPup←(\ReceiveExtra pup l..conv) else pup]) (\SkipBytesOut [LAMBDA (pup nBytes) (* ht: " 1-Aug-85 09:22") (until (ILEQ pup:PUPLENGTH+nBytes \RPCMaxPupLength) do (nBytes←nBytes-(\RPCMaxPupLength-pup:PUPLENGTH)) (pup:PUPLENGTH←\RPCMaxPupLength) (\SendExtra pup l..conv) finally (add pup:PUPLENGTH nBytes]) (\SkipWordsIn [LAMBDA (pup nWords) (* ht: " 1-Aug-85 09:23") (until (ILEQ pup:dataOffset+nWords \RPCMaxDataOffset) do (nWords←nWords-(\RPCMaxDataOffset-pup:dataOffset)) (pup:dataOffset←\RPCMaxDataOffset) (pup←l..cPup←(\ReceiveExtra pup l..conv)) finally (add pup:dataOffset nWords)) pup]) ) (* to control how much PUPTRACEFLG shows) (ADDTOVAR PUPPRINTMACROS (96 INTEGER 4 WORDS 42 ...) (97 INTEGER 4 WORDS 42 ...) (98 INTEGER 4 WORDS 16 ...) (104 INTEGER 4 WORDS 42 ...) (105 INTEGER 4 WORDS 42 ...) (106 INTEGER 4 WORDS 16 ...) (120 INTEGER 4 WORDS 42 ...) (100 INTEGER 4 WORDS 42) (108 INTEGER 4 WORDS 42) (121 INTEGER 4 WORDS 42 ...)) (RPAQQ RPCPUPTYPES ((\RPC.ACK 98) (\RPC.DATA! 105) (\RPC.PING 106) (\RPC.CALL 96) (\RPC.CALL! 104) (\RPC.DATA 97) (\RPC.CALL-! 120) (\RPC.RFA 100) (\RPC.RFA! 108) (\RPC.DATA-! 121))) (RPAQ PUPTYPES [UNION RPCPUPTYPES (LISTP (EVALV (QUOTE PUPTYPES]) (RPAQ PUPONLYTYPES (UNION PUPONLYTYPES (MAPCAR RPCPUPTYPES (FUNCTION CADR)))) (DECLARE: DONTCOPY (DECLARE: EVAL@COMPILE [PUTPROPS PUPDEBUGGING MACRO ((X . Y) (COND (PUPTRACEFLG (printout PUPTRACEFILE X . Y] ) ) (DECLARE: DONTCOPY EVAL@COMPILE (RESETSAVE DWIMIFYCOMPFLG T) ) (FILESLOAD GRAPEVINE SIGNAL CRYPT) (DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY (FILESLOAD (LOADCOMP) CRYPT SIGNAL NOBOX ETHERRECORDS (IMPORT) LLCHAR LLARRAYELT) ) (PUTPROPS RPC COPYRIGHT ("Xerox Corporation" 1984 1985 1986)) (DECLARE: DONTCOPY (FILEMAP (NIL (6008 8619 (InitRPC 6018 . 8167) (StopRPC 8169 . 8617)) (8649 12271 (ImportInterface 8659 . 10308) (RemoteBind 10310 . 12056) (UnimportInterface 12058 . 12269)) (12301 16895 (Binder 12311 . 14343) (NewExportTableEntry 14345 . 14995) (ExportInterface 14997 . 16725) (UnexportInterface 16727 . 16893)) (16922 19924 (\Authenticate 16932 . 18953) (StartConversation 18955 . 19922)) (19962 40773 (\RPCTopProc 19972 . 22238) (\RPCServerProc 22240 . 30056) (\RoutePup 30058 . 30967) (\ExchangePackets 30969 . 39870) (\DoSignal 39872 . 40771)) (40802 44409 (\StartCall 40812 . 42086) (\Call 42088 . 43075) (\AbortRemote 43077 . 43745) (CantCatchHere 43747 . 43872) (\StartSignal 43874 . 44078) ( \StartReturn 44080 . 44407)) (44443 46062 (\SetWanting 44453 . 44595) (\ClearWanting 44597 . 44752) ( \Wanting 44754 . 44889) (\NewHandleCnt 44891 . 45200) (\NewProcess 45202 . 45675) (\FindHandle 45677 . 45886) (\KillHandle 45888 . 46060)) (46096 48076 (\EncryptPup 46106 . 47251) (\DecryptPup 47253 . 48074)) (48099 52921 (\RPCOpenClosest 48109 . 50211) (\SetupResponse 50213 . 50655) (\ReceiveExtra 50657 . 51176) (\SendExtra 51178 . 51493) (CheapHopsToNet 51495 . 51903) (\CheckRPC 51905 . 52112) ( \RPCNotAliveErr 52114 . 52296) (\ServerError 52298 . 52717) (\InitRPCVars 52719 . 52919)) (53160 61289 (\ReplyToRFA 53170 . 56157) (\GetConnectionState 56159 . 61287)) (69890 76965 (\PutBinderString 69900 . 70305) (\AddRPCDispDetails 70307 . 70532) (\AddRPCVersion 70534 . 70724) (\AddPupDblWord 70726 . 71059) (\AddPupWord 71061 . 71359) (\AddPupEnum 71361 . 71665) (\AddPupSmallp 71667 . 71878) ( \AddPupBoolean 71880 . 72074) (\MarshalStream 72076 . 73155) (\MarshalArb 73157 . 73969) ( \MarshalString 73971 . 75155) (\MarshalAtom 75157 . 75361) (\MoveToPup 75363 . 75927) (\MoveToMultPups 75929 . 76963)) (77004 85165 (\GetBinderString 77014 . 77448) (\GetArgDisp 77450 . 77687) ( \GetArgVersion 77689 . 77896) (\GetArgDblWord 77898 . 78227) (\GetArgWord 78229 . 78603) (\GetArgEnum 78605 . 78771) (\GetArgBool 78773 . 78867) (\GetArgSmallp 78869 . 79126) (\UnmarshalString 79128 . 79980) (\UnmarshalStream 79982 . 80838) (\UnmarshalArb 80840 . 81530) (\UnmarshalAtom 81532 . 81691) ( \MoveFromPup 81693 . 82207) (\MoveFromMultPups 82209 . 83237) (\IncrDataOffset 83239 . 83385) ( \IncrPupLength 83387 . 83531) (\CurrentPupBase 83533 . 83695) (\CurrentPupPosition 83697 . 83910) ( \CheckPupOverflow 83912 . 84146) (\CheckPupExhausted 84148 . 84416) (\SkipBytesOut 84418 . 84773) ( \SkipWordsIn 84775 . 85163))))) STOP