From: Didier Morandi [Didier.Morandi@Free.fr] Sent: Wednesday, April 10, 2002 5:16 PM To: Info-VAX@Mvb.Saic.Com Subject: Re: remote mailbox This procedure is a programming example on how to do DEcnet task to task communication via IP when DECnet routing is disabled. It sends "coucou" and receives "Coucou yourself". It does not do DECnet over IP, it does IP (on a system running DECnet-Plus). Version 1.2 has a test on f$getsyi("decnet_version") to change the way the timeouts are set up, but I don't have it at home. Lines should be 80c long. $!+ $! ipLEEnk.com $! $! This procedure does DECnet Task To Task communication with itself on its $! local or a remote node via DECnet. Should DECnet routing to the remote node $! not be available, the link is automatically established via an IP gateway $! (if available, of course). $! $! The author gratefully thanks his wife Pascale for the time he had to write $! all this, Peter LEE from a Bank in Zurich for his very valuable and $! powerful C programming of the two IP gateway tasks, Geoff KINGSMIL from $! Compaq for his valuable debugging support to make it work and Stephen Hoff $! HOFFMAN also from COMPAQ for so many reasons that I will not try to list $! here. See the OpenVMS FAQ :-) $! $! Prerequisites $! ============= $! $! To make it work (architecture Client <--> IP Gateway <--> Server) $! --------------- node_1 node_2 node_3 $! $! 1. build ipLEEnk_in and ipLEEnk_out executable images (see ipLEEnk.doc) $! 2. install ipLEEnk_out.(com|exe) on the local node $! 3. install ipLEEnk_in.(com|exe) on the Gateway node $! 4. copy ipLEEnk.com (this procedure) to the target remote node $! 5. enable ipLEEnk_in account proxy on remote node to remote ipLEEnk.com task $! $! Example: $! Assuming that the local user on NODE_1 is "ipLEEnk_user" and that the $! ipLEEnk.com procedure has been copied in the default directory of $! ipLEEnk_user on NODE_3, and that the ipLEEnk_in gateway task is on $! NODE_2, do $! $! NODE_3> uaf add/proxy NODE_2::ipLEEnk_in ipLEEnk_user $! $! $! P1: Message to send (between quotes if more than one word) $! P2: Remote node where the network task should be accessed $! P3: IP Gateway node (can be the same as P2) $! P4: "V" (or any other character) will trigger verbose mode. $! P5: Network timeout value in seconds on DECnet incoming and outgoing access $! P6: "I" will skip a DECnet connection attempt and force IP connection. $! P7: Name of the remote task to connect to (default is ipLEEnk.com) $! $! When the message has been successfully received by the remote task, it is $! returned to the local task with the (obscure) string " yourself!" appended. $! $! See diagram at the end of this file. $! $! $! none but display. $! $! $! none but two log files creation in both ipLEEnk.com default directories on $! local and remote node. Note that a logfile is also created by the gateway $! tasks in their default directories, and a NET$SERVER.LOG file too. $! $! Note that the DECnet session control outgoing timeout is set to 3 seconds $! within this procedure (default is 60) to avoid the user to wait too long $! before any error message dealing with outgoing DECnet access failure. Value $! is reset to default at end of procedure (generally 60 seconds, not checked). $! $! LEGAL $! ===== $! This procedure and all accompagnement software is (c) 2001 Didier Morandi $! MORANDI Consulting, Zurich, CH. http://Didier.Morandi.Free.fr/index_us.html $! $! Revision history $! $! Version Date Author action $! ------- ----------- ---------- --------------------------------------------- $! v1.0-0 23-nov-2001 D. Morandi creation (during off hours) $v="1.1-0"!28-nov-2001 DMo add messages formatting. $!- $ say = "write sys$output" $ we_should_try_IP = 0 !init flag $ we_use_DECnet = 0 !init flag $ we_use_IP = 0 !init flag $ fac = "ipLEEnk" !facility identification $ tmo_def = 3 !network timeout in sec. $ me = " ? " !not yet defined $ dbg = "!" !the Verbose magic trigger $! $ on warning then gosub ERROR $ on control then goto EXIT $ if p4 .nes. "" then dbg = "" !remove comment will enable msg $ tmo = "''p5'" !optional network timeout value $ if tmo .eqs. "" then tmo = tmo_def !default value in seconds $ if tmo .eq. 0 then tmo = tmo_def !idem $ 'dbg' say "" $ 'dbg' say fac,"-I-, entering ",f$env("procedure")," v",v $ pid = f$getjpi(0,"pid") $ logfile = "SYS$LOGIN:ipLEEnk_''f$getjpi(0,"pid")'.LOG" $ 'dbg' say fac,"-I-, creating logfile ",logfile $ 'dbg' log_flag = "/log" $ create'log_flag' 'logfile' $ logfile = f$search(logfile) !get full file spec. $ node = f$trnlnm("sys$node") - "::" $ msg = f$env("procedure") + " starting (" + f$mode() + ")" $ gosub LOG_IT $ msg = "setting NETSERVER$TIMEOUT to ""0 00:00:00""" $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ define/process/nolog netserver$timeout "0 00:00:00" $ s = "s" $ if tmo .eq. 1 then s = "" $ msg = "setting SESSION CONTROL OUTGOING TIMER to ''tmo' second''s'" $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ define/user sys$output nl: $ defile/user sys$error nl: $ mc ncl set session control outgoing timer 'tmo' $ if p7 .eqs. "" then p7 = "ipLEEnk.com" !default remote task to reach $ msg = "setting default remote task name to ''p7'" $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ goto 'f$mode()' $! $INTERACTIVE: $ me = " C: " ! "C" = Client $ on warning then gosub ERROR $ if p1 .eqs. "" then inq p1 "Enter message to send between quotes, =exit" $ if p1 .eqs. "" then exit $ if p2 .eqs. "" then inq p2 "Enter DECnet target system name [FRED]" $ if p2 .eqs. "" then p2 = "FRED" $ if p3 .eqs. "" then inq p3 "Enter ipLEEnk_in server name [FRED]" $ if p3 .eqs. "" then p3 = "FRED" $ p2 = p2 - "::" $ p3 = p3 - "::" $!+ $! Record some environment data $!- $ msg = "logfile is " + logfile $ gosub LOG_IT $ msg = "Network timeout is ''tmo' s." $ gosub LOG_IT $ if f$edit(p6,"upcase,collapse") .eqs. "I" then goto NO_LINK $!+ $! Open DECnet network link to remote task (if DECnet routing available) $!- $ close/nolog netlink $ say "" $ msg = "opening DECnet link from ''node' to remote task on node " + p2 $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ open/read/write netlink 'p2'"SYSTEM"::"TASK=''p7'" $ if we_should_try_IP !DECnet failed, backup. $ then $ msg="DECnet link to remote node unavailable, trying IP Gateway." $ say fac,"-W-, ",msg $ gosub LOG_IT $ goto NO_LINK $ endif $ msg = "link opened successfully" $ gosub LOG_IT $ param = "----OK" !we assume it. $ we_use_DECnet = 1 !flag $ goto GO_DECNET !and we skip the Gateway $!+ $! Open DECnet network link to local Gateway $!- $NO_LINK: $ close/nolog netlink $ say "" $ msg = "opening DECnet link to local outgoing IP Gateway on " + node $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ open/read/write netlink 0""::"task=gen_tcp_svr_out" $ msg = "link to GEN_TCP_SVR_OUT opened successfully" $ gosub LOG_IT $ we_use_IP = 1 !flag $!+ $! Send information needed to reach remote incoming gateway and network task. $!- $ msg = "sending remote incoming IP Gateway address and remote task data" $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ msg = "sending ''p3'|59051|''p2'""SYSTEM""::""TASK=''p7'""" $ gosub LOG_IT $ msg = msg - "sending " $ write netlink msg $ msg = "information sent successfully" $ gosub LOG_IT $!+ $! Send "request for ACK" message to remote incoming Gateway via local outgoing $! Gateway to allow it to receive its ACK message "----OK". Actually the $! request for ACK message is any string, which causes the partner to answer. $!- $ m1 = "HERE IS ''node'" !dummy msg $ msg = "sending request for ACK to remote incoming IP Gateway on " + p3 $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ write netlink m1 $ msg = "message sent successfully" $ gosub LOG_IT $!+ $! Then we read the ACK status (----OK) from the incoming Gateway task. $!- $ read/err=ERROR/time_out='tmo' netlink param $ msg = "READ completed successfully" $ gosub LOG_IT $!+ $! If ACK, let's send our message to our remote server. $!- $GO_DECNET: $ if param .eqs. "----OK" $ then $ msg = "remote server task return status is: " + param $ gosub LOG_IT $ if we_use_DECnet $ then $ m1 = "HERE IS ''node'" !dummy msg $ msg = "sending message ""''m1'"" to remote server task on " + p2 $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ write netlink m1 $ msg = "WRITE completed successfully" $ gosub LOG_IT msg = "sending ""''p1'"" from ''node' to ''p2' via DECnet" $ endif $ if we_use_IP then - msg = "sending ""''p1'"" from ''node' to ''p2' via ''p3' (IP Gateway)" $ say fac,"-I-, ",msg $ gosub LOG_IT $ write netlink "''p1'" $ msg = "WRITE completed successfully" $ gosub LOG_IT $! $ msg = "waiting to read answer from remote server task on ''p2'..." $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ read/err=ERROR/time_out='tmo' netlink param $ msg = "READ completed successfully" $ gosub LOG_IT $ msg = "message received from ''p2' is: " + param $ say fac,"-I-, ",msg $ gosub LOG_IT $! $ msg = "sending request to remote server task to close remote link" $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ write netlink "----CLOSE" $ msg = "WRITE completed successfully" $ gosub LOG_IT $! $ msg = "waiting to receive CLOSE ACK from remote server task on ''p2'..." $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ read/err=ERROR/time_out='tmo' netlink param $ msg = "READ completed successfully" $ gosub LOG_IT $ msg = "CLOSE ACK successfully received from ''p2'" $ gosub LOG_IT $ if param .eqs. "----CLOSE" $ then $ if we_use_DECnet then - msg = "remote server task closed communication" $ if we_use_IP then - msg = "remote Gateway task closed communication" $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ else $ if we_use_DECnet then - msg = "non-fatal error received from remote server task on close" $ if we_use_IP then - msg = "non-fatal error received from remote Gateway on close" $ say fac,"-E-, ",msg $ gosub LOG_IT $ msg = "error status is " + param $ say fac,"-E-, ",msg $ gosub LOG_IT $ endif $ else $! (we come here only in case of IP transport error) $ msg = - "trying to connect to ''p2', remote IP Gateway on ''p3' answered:" $ say fac,"-F-, ",msg $ gosub LOG_IT $ say param $ msg = param $ gosub LOG_IT $! let's extract the VMS completion status $ status = 'f$element(1,":",param)' $ msg = f$message(status) $ say "----ERROR ",msg $ gosub LOG_IT $ msg = - "DECnet TTT connection via IP between ''node' and ''p2' has failed." $ say fac,"-F-, ",msg $ gosub LOG_IT $ endif $ goto EXIT $! $BATCH: $OTHER: $NETWORK: $ on warning then gosub ERROR $ me = " S: " ! "S" = Server $ msg = "logfile is " + logfile $ gosub LOG_IT $ tmo = tmo_def $ msg = "network timeout is ''tmo'" $ gosub LOG_IT $ close/nolog netlink $ msg = "opening SYS$NET mailbox" $ gosub LOG_IT $ open/read/write netlink sys$net $ msg = "SYS$NET mailbox opened successfully" $ gosub LOG_IT $ msg = "waiting to read from SYS$NET mailbox..." $ gosub LOG_IT $ read/err=ERROR/time_out='tmo' netlink parameter !the ACK request $ msg = "READ successful, message received was """ + parameter + """" $ gosub LOG_IT $ msg = "entering READ loop" $ gosub LOG_IT $! $LOOP: $ msg = "waiting to read from SYS$NET mailbox within loop..." $ gosub LOG_IT $ read/err=ERROR/time_out='tmo' netlink parameter !the message $ msg = "READ successful, message received was """ + parameter + """" $ gosub LOG_IT $ if parameter .eqs. "----CLOSE" then goto NO_MORE !done $ msg = "sending (hard-coded) answer to SYS$NET mailbox" $ gosub LOG_IT $ write netlink "''parameter' yourself!" $ msg = "WRITE successful, message sent was ""''parameter' yourself!""" $ gosub LOG_IT $ goto LOOP !next message? $! $NO_MORE: $ msg = "CLOSE request received, sending ACK back to Client" $ gosub LOG_IT $ write netlink parameter !ie "----CLOSE" $ msg = "WRITE successful" $ gosub LOG_IT $ status = 1 !success $ goto EXIT $! $LOG_IT: $!+ $! This (stupid) open/close sequence flushes the messages into the logfile in $! case the procedure hangs. This allows the (courageous) debugger to have a $! bit more of information than the "starting (NETWORK)" message... $!- $ close/nolog log $ open/append/share log 'logfile' $ write log f$extract(12,8,f$time())," ",pid," ",node,me,msg $ close log $ return $! $ERROR: $ status=$status $ set noon $ if status .eqs. "%X100184C4" $ then $! occurs when DECnet is missing. $ msg = "501, DECnet not started on local node ''node'" $ goto FATAL_EXIT $ endif $ if status .eqs. "%X109110A2" $ then $! occurs when DECnet is no more available.. $ msg = "502, DECnet unavailable on local node ''p1'" $ goto FATAL_EXIT $ endif $ if status .eqs. "%X1001C002" $ then $! occurs when a PROXY is missing to access network task. $ msg = "503, No access from ''node' to DECnet network task" $! now, let's see if we try to reach ourselves or a remote system $ if p2 .eqs. node $ then $ goto FATAL_EXIT !cannot connect to me $ else $ we_should_try_IP = 1 !flag $ return $ endif $ endif $ if status .eqs. "%X0001C0F4" $ then $! occurs when DECnet link has gone. $ msg = "504, Read error from (disconnected?) DECnet link" $ goto FATAL_EXIT $ endif $ if status .eqs. "%X0001C114" $ then $! occurs when DECnet link has gone. $ msg = "505, Write error to (disconnected?) DECnet link" $ goto FATAL_EXIT $ endif $ if status .eqs. "%X0001827A" $ then $! occurs when remote Gateway service is disabled. $ msg = "506, Read error from DECnet link, EOF detected" $ goto FATAL_EXIT $ endif $ if status .eqs. "%X000181B0" $ then $! occurs when DECnet has been stopped or system unavailable. $ msg = "507, Timeout after ''tmo' s. on READ from DECnet link" $ goto FATAL_EXIT $ endif $ msg = "1. unexpected non fatal error:" $ gosub LOG_IT $ msg = "2. " + f$mess(status) $ gosub LOG_IT $ msg = "3. processing continuing" $ gosub LOG_IT $ on warning then gosub ERROR $ return $! $FATAL_EXIT: $ msg = msg + " (" + status + ")" $ say fac,"-F-, ",msg $ gosub LOG_IT $EXIT: $ msg = "closing network link" $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ close/nolog netlink $ msg = "resetting SESSION CONTROL OUTGOING TIMER to default value 60 s." $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ define/user sys$output nl: $ defile/user sys$error nl: $ mc ncl set session control outgoing timer 60 $ msg = "leaving " + f$env("procedure") $ 'dbg' say fac,"-I-, ",msg $ gosub LOG_IT $ say "" $ exit 'status' $! ################################################################################ Table 1 - ipLEEnk chronological links relationship NODE 1 ! NODE 2 ! NODE 3 ! ! Client ! IP Gateway ! Server +--------+ ! ! +--------+ No ! ! YES ! ! ! ! +--C6 C1_[READY?>________________________________________> S1 S6* * | ! ! ! ! ! ! * | ! C2 <____________________________________________ * * * * * * S3 ! * | ! ! ! ! ! ! * | ! C4_[CLOSE>_________________________________________> S4 ! * | ! ! ! ! ! ! * | ! C5 <____________________________________________OG1 OG2~[READY?>~~~IG1 IG2* * * * * * * * * * * * * * ! ! ! ! ! ! C2________IG4 ! ! ! ! ! ! ! ! C4_[CLOSE>_____0G7 OG8~[CLOSE>~~~~IG5 ! ! ! ! ! ! ! ! C5____ message IG = incoming IP Gateway task ___________ DECnet link for message transfer * * * * * * DECnet link for task to task traffic ~~~~~~~~~~~ IP link between gateway tasks _____ _____ ___\_ [#####]_[#####]_[####""> ___o___o___o___o___oo__oo____ TGV D. -- ---------------------------------------------------------------------- MORANDI Consultants - WEB: http://Didier.Morandi.Free.fr/index_us.html Pflanzschulstrasse 53, 8004 Zurich, Switzerland. GSM: +41 (0)79 705 4670 19, chemin de la Butte, 31400 Toulouse, France. GSM: +33 (0)6 7983 6418 Disaster Recovery Plans, Computer Security Audits, DEC OpenVMS Expertise On parle français Man spricht Deutsch se habla Castellano English spoken