[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Notes on Setting up Dialnet at DREA (long)



Here is a little note on the problems and their solutions for setting up
Dialnet here at DREA.  Most of the problems were due to Dialnet in
general, and others were due to the Racal Vadic 3450 Modem code.  I hope
that the solutions presented here get incorporated by Symbolics, and aid
others in setting up their site to operate dialnet.  The complete
private dialnet registry is available from Mark Grover,
(Grover@ADS-DC.Dialnet.Symbolics.Com or Grover@AIDS-UNIX.ARPA)

	- Peter



================================================================================
Notes on Dialnet, in General, and its use with a Racal Vadic 3451 Modem 

				   by
				    
			    Peter J. Gergely
================================================================================

	Somewhere around the last week of May, it was decided that the
six Lispm's here at DREA should have dialnet access.  As all six
machines are running the Store and Forward Mailer (SFM), it should have
been easy.
	Unfortunately, setting up dialnet here encountered many problems
that had to be resolved.  This note attempts to explain the problems and
how they were fixed to aid others in getting on Dialnet.
	First, let me say that I think Dialnet is an excellent idea, and
support for the product should be continued.  It is a valuable resource
allowing communication with others when you have no connection to
Arpanet, Usenet, etc.

	The first problem encountered was what to do about dialing out.
DREA is on a government centrex which allows any calls in Canada to be
made by dialing direct, and all others must be done by getting out of
the government centrex.  To do so, a "9" must be dialed, and you need to
wait approx. 5 seconds for a new dial tone to appear.  If and only if
you get this new dial tone can you dial the number as you normally would
for any long distance service.
	Another problem surfaced immediately.  The modem would hang up
before a connection could be established with the remote site.  This and
the 5 sec delay for a dial tone could easily be remidied on the RV3451
modem by adding a "K" (which symbolizes a 5-sec delay) to the number to
be dialed at the right location.  After some research, it was noted that
a 10-sec delay at the end of dialing the number would be enough to reach
all the sites we were interested in.
	Therefore, our dialing subnet information became as follows:

================================================================================
;;; Code for dialing from any 1-902-426 government exchange
(:SUBNET "1902426ssss>1204xxxdddd" :DIAL "1204xxxddddKK" :COST "1")	;Manitoba
(:SUBNET "1902426ssss>1306xxxdddd" :DIAL "1306xxxddddKK" :COST "1")	;Saskatchewan
(:SUBNET "1902426ssss>1403xxxdddd" :DIAL "1403xxxddddKK" :COST "1")	;Alberta & Yukon 
(:SUBNET "1902426ssss>1403xxxdddd" :DIAL "1403xxxddddKK" :COST "1")	;Northwest Terr
(:SUBNET "1902426ssss>1416xxxdddd" :DIAL "1416xxxddddKK" :COST "1")	;Ontario
(:SUBNET "1902426ssss>1418xxxdddd" :DIAL "1418xxxddddKK" :COST "1")	;Quebec
(:SUBNET "1902426ssss>1506xxxdddd" :DIAL "1506xxxddddKK" :COST "1")	;New Brunswick
(:SUBNET "1902426ssss>1514xxxdddd" :DIAL "1514xxxddddKK" :COST "1")	;Quebec
(:SUBNET "1902426ssss>1519xxxdddd" :DIAL "1519xxxddddKK" :COST "1")	;Ontario
(:SUBNET "1902426ssss>1604xxxdddd" :DIAL "1604xxxddddKK" :COST "1")	;British Columbia
(:SUBNET "1902426ssss>1613xxxdddd" :DIAL "1613xxxddddKK" :COST "1")	;Ontario
(:SUBNET "1902426ssss>1705xxxdddd" :DIAL "1705xxxddddKK" :COST "1")	;Ontario
(:SUBNET "1902426ssss>1709xxxdddd" :DIAL "1709xxxddddKK" :COST "1")	;Newfoundland
(:SUBNET "1902426ssss>1807xxxdddd" :DIAL "1807xxxddddKK" :COST "1")	;Ontario
(:SUBNET "1902426ssss>1819xxxdddd" :DIAL "1819xxxddddKK" :COST "1")	;Quebec
(:SUBNET "1902426ssss>1902426dddd" :DIAL "6dddd" :COST "0")
(:SUBNET "1902426ssss>1902xxxdddd" :DIAL "9Kxxxdddd" :COST "0")
(:SUBNET "1902426ssss>1aaaxxxdddd" :DIAL "9K1aaaxxxddddKK" :COST "2")	;Long Delay for others
================================================================================

This presented the first major problem, and that was to get the dialnet
registry to recognize the letter "K" in the dial portion.  With many
thanks to Jim Dumoulin (Dumoulin@NASA-KSC.Dialnet.Symbolics.Com), who
kindly supplied a patch to allow for this.  Modifying the code in
SYS:DIALNET;NETWORK.LISP for the function NUMBER-TO-DIAL achieved the
desired result.  The patched code is:

================================================================================
;;; Allow UPPERCASE delays in the DIAL portion

;;; Figure out the number to dial from LOCAL-NUMBER to FOREIGN-NUMBER.  The SUBNET
;;; attributes of the dial network encode the prefixes.  Each "subnet" represents a
;;; phone company connection between the two exchanges.  The DIAL attribute of the
;;; subnet property gives the prefixes and the COST attribute some relative measure of
;;; how expensive the call is.

;;; Some typical patterns might be:
;;;  SUBNET 1xxxyyyyyyy>1zzzwwwwwww DIAL 1zzzwwwwwww COST 5
;;;  SUBNET 1xxxyyyyyyy>1xxxzzzzzzz DIAL zzzzzzz COST 0
;;;  SUBNET 1212xxxxxxx>1yyyzzzzzzz DIAL yyyzzzzzzz COST 5
;;;  SUBNET 1617864xxxx>1617774yyyy DIAL 1774yyyy COST 3
;;;  SUBNET 1617253xxxx>1617yyyyyyy DIAL 9yyyyyyy COST 0
;;;  SUBNET 1xxxyyyyyyy>1800zzzzzzz DIAL 1800zzzzzzz COST 1
;;; meaning (1) dial 1+area code outside of your area code, (2) dial just number
;;; within same area code, (3) no prefix 1 in new york, (4) dial 1+number to call
;;; Eastie from Cambridge, (5) dial 9 to get out of MIT, (6) free to call an 800 number.
;;; Letters represent variables, numbers constants.  The pattern with the fewest variables
;;; is the one used.
DIAL::(DEFUN NUMBER-TO-DIAL (LOCAL-NUMBER FOREIGN-NUMBER PATTERNS)
  (LET ((BEST-PATTERN NIL)
	(BEST-PATTERN-BINDINGS NIL))
    (LET* ((PATTERN-TO-MATCH (STRING-APPEND LOCAL-NUMBER #/> FOREIGN-NUMBER))
	   (PATTERN-LENGTH (STRING-LENGTH PATTERN-TO-MATCH)))
      (LOOP FOR FULL-PATTERN IN PATTERNS
	    AS (PATTERN) = FULL-PATTERN
	    DO (WHEN (= (STRING-LENGTH PATTERN) PATTERN-LENGTH)
		 (LET ((BINDINGS NIL)
		       (INDEX 0))
		   (BLOCK FAILED
		     (LOOP WHILE (< INDEX PATTERN-LENGTH) DOING
		       (LET ((PCHAR (AREF PATTERN INDEX))
			     (MCHAR (AREF PATTERN-TO-MATCH INDEX)))
			 (IF (= PCHAR MCHAR)
			     (INCF INDEX)
			   (WHEN ( #/0 PCHAR #/9)
			     (RETURN-FROM FAILED NIL))
			   (LET ((SUB-PATTERN-LENGTH (LOOP FOR I FROM INDEX
							     BELOW PATTERN-LENGTH
							   WHILE (= (AREF PATTERN I) PCHAR)
							     COUNT 1))
				 (BINDING (ASSQ PCHAR BINDINGS)))
			     (IF (NULL BINDING)
				 (PUSH (CONS PCHAR
					     (SUBSTRING PATTERN-TO-MATCH INDEX
							(INCF INDEX SUB-PATTERN-LENGTH)))
				       BINDINGS)
			       (SETQ BINDING (CDR BINDING))
			       (UNLESS (= (STRING-LENGTH BINDING) SUB-PATTERN-LENGTH)
				 (FERROR
				 "The subpattern ~A occurs with two different lengths in ~A"
				   BINDING PATTERN))
			       (LOOP FOR SINDEX BELOW SUB-PATTERN-LENGTH
				     DOING (UNLESS (= (AREF BINDING SINDEX)
						      (AREF PATTERN-TO-MATCH INDEX))
					     (RETURN-FROM FAILED NIL))
				     (INCF INDEX)))))))
		     (WHEN (OR (NULL BEST-PATTERN)
			       (< (LENGTH BINDINGS) (LENGTH BEST-PATTERN-BINDINGS)))
		       (SETQ BEST-PATTERN FULL-PATTERN
			     BEST-PATTERN-BINDINGS BINDINGS)))))))
    (IF (NULL BEST-PATTERN)
	FOREIGN-NUMBER
      (LET ((FILL-IN (SECOND (ASSQ ':DIAL (SECOND BEST-PATTERN)))))
	(IF (NULL FILL-IN)
	    FOREIGN-NUMBER
	  (LET* ((LENGTH (STRING-LENGTH FILL-IN))
		 (RESULT (MAKE-ARRAY LENGTH ':TYPE 'ART-STRING)))
	    (LET ((INDEX 0))
	      (LOOP WHILE (< INDEX LENGTH)
		    DOING (LET ((FCHAR (AREF FILL-IN INDEX)))
;;; Replace the original line here with the following
			    (IF (OR ( #/0 FCHAR #/9) ( #/A FCHAR #/Z))
				(SETF (AREF RESULT (PROG1 INDEX (INCF INDEX))) FCHAR)
			      (LET ((BINDING (ASSQ FCHAR BEST-PATTERN-BINDINGS)))
				(WHEN (NULL BINDING)
				  (FERROR "Result pattern ~A refers to binding ~C in ~S."
					  FILL-IN FCHAR BEST-PATTERN))
				(LOOP FOR CHAR BEING THE ARRAY-ELEMENTS OF (CDR BINDING)
				      DO (ASET CHAR RESULT INDEX)
					 (INCF INDEX)))))))
	    (VALUES RESULT
		    (LET ((COST (SECOND (ASSQ ':COST (SECOND BEST-PATTERN)))))
		      (AND COST (PARSE-NUMBER COST))))))))))
================================================================================

	With this patch in place, and our subnet dialing sequences, I
thought it was solved.  After much investigation, it turns out that our
subnet dialing sequences did not replace those in
SYS:SITE;PUBLIC-DIALNET-REGISTRY.LISP and the three lines below had to
be commented out.
================================================================================
;;; Call prefix information.
;;; Common situations; may be overridden by user's group or private registries.
#||
(:SUBNET "1xxxyyyyyyy>1zzzwwwwwww" :DIAL "1zzzwwwwwww" :COST "5")
(:SUBNET "1xxxyyyyyyy>1800zzzzzzz" :DIAL "1800zzzzzzz" :COST "1")
(:SUBNET "1xxxyyyyyyy>1xxxzzzzzzz" :DIAL "zzzzzzz" :COST "0")
||#
================================================================================
This had to be done because the first line has less variables than our
own, and by the definition of the code, the one with the least number of
variables is the one chosen.

	FINALLY, it appeared that everything would work.  Not quite,
with the additional delays introduced by the "K"'s it was necessary to
increase the dialing timeout for the RV3451 modem.  This was easy, and
the following patch was introduced:
================================================================================
;;; The dialing sequence involves the following intervals:
;;;     5 seconds to wait for a dial tone
;;;    60 seconds (approx) to dial the number
;;;    24 seconds to wait for the other side to answer
;;;   120 seconds to return to the idle state
DIAL::(DEFCONST va3450-dialing-timeout (* (+ 5. 60. 24. 120.) 60.))	;Longer timeout
================================================================================


	Well, a brand new problem with the RV3451 modem code became
apparent.  Every once in a while the modem would respond with INVALID
when the dialing sequence was given to it.  This would crash the mailer
when it was probing a DEFERRED-RECEIPT-HOST site (Book 6, pg 114) for
any mail for us, or just say an invalid response was received when we
were probing to send mail.  The solution required rewriting the :OPEN
method for the RV3450 Modem code (found in SYS:DIALNET;MODEMS.LISP), and is
included here for all interested parties.

================================================================================
DIAL::(defwhopper (va3450-modem :open) ()
  (error-restart (error "Redial call to ~A." host)
    (unless (eq (va3450-state-state va3450-state) 'idle)
      (let ((elapsed (time-difference (time) (va3450-state-clock va3450-state))))      
	(selectq (va3450-state-state va3450-state)	;compute current va3450-modem state
	  (hangup (when (< elapsed va3450-line-timeout)
		    (process-sleep (- va3450-line-timeout elapsed) "Hangup"))
		  (va3450-modem-set-state 'idle))
	  ((dialing ringing) (when (> elapsed va3450-dialing-timeout)
			       (va3450-modem-set-state 'idle)))
	  ((autodial ready number confirm busy voice no-dial-tone)
	   (cond ((> elapsed va3450-upper-timeout)
		  (va3450-modem-set-state 'idle))
		 ((> elapsed va3450-lower-timeout)
		  (va3450-modem-set-state 'autodial)))))
	
	;; Get into the IDLE, READY, NUMBER, or CONFIRM state.
	(selectq (va3450-state-state va3450-state)
	  (autodial
	   (process-sleep (- va3450-upper-timeout elapsed) "Timeout")
	   (va3450-modem-set-state 'idle))
	  (dialing
	   (process-sleep (- va3450-dialing-timeout elapsed) "Timeout")
	   (va3450-modem-set-state 'idle)))))
    
    ;; It is now safe to assert DTR, since we have waited long enough to hang up the phone.
    ;; Be sure not to do any I/O to the va3450-modem before this point.
    (let ((user-parameters (copylist si:parameters)))
      (unwind-protect
	(progn
	  (send self :put :mode :asynchronous :parity :even :number-of-data-bits 7
		:number-of-stop-bits 1 :check-parity-errors nil :receive-enable t
		:transmit-enable t)
	  (continue-whopper)
	  
	  ;; Get into the READY or NUMBER state.
	  (selectq (va3450-state-state va3450-state)
	    (idle
	     (va3450-modem-line-out "")
	     (va3450-modem-response "Ready"
				    '("
*" ready)
				    '("HELLO: I'M READY
*" ready)
				    '("
HELLO: I'M READY
*" ready)
				    '("
HELLO:I'M READY
*" ready)
				    '("
INVALID
*" ready)))
	    (confirm
	     (va3450-modem-line-out "X")
	     (va3450-modem-response "Ready"
				    '("
*" ready)
				    '("
INVALID
*" ready))))
	  ;; Get into the NUMBER state.
	  (LOOP REPEAT 4
		WHILE (eq (va3450-state-state va3450-state) 'ready)
		DO (va3450-modem-line-out "D")
		   (va3450-modem-response "Number"
					  '("NUMBER?
" number)
					  '("D
NUMBER? 
" number)
					  '("
*" ready)
					  '("
INVALID
*" ready))
		   (when (eq (va3450-state-state va3450-state) 'ready)
		     (PROCESS-SLEEP 10. "Stabilizing"))	;Let things settle a little bit
		   )				;End of loop from counter 1 to 4
	  (when (eq (va3450-state-state va3450-state) 'ready)	;Check a last time
	    (va3450-modem-line-out "D")
	    (va3450-modem-response "Number"
			    '("NUMBER?
" number)
			    '("D
NUMBER? 
" number)))	;If it fails again then make sure
						;we report the INVALID response
	  (WHEN (EQ (VA3450-STATE-STATE VA3450-STATE) 'NUMBER)
	    (va3450-modem-line-out phone-number)
	    (va3450-modem-response "Confirm"
				   `(,(string-append phone-number "
") confirm)
				   '("
*" ready)
				   '("
INVALID
*" ready)))
	  (WHEN (EQ (VA3450-STATE-STATE VA3450-STATE) 'CONFIRM)
	    (va3450-modem-line-out "")
	    (va3450-modem-response "Dial Tone"
				   '("DIALING:  " dialing)
				   `(,(string-append phone-number "

NO DIAL TONE!") no-dial-tone)
				   `(,(string-append phone-number "

DIALING...
") dialing)
				   '("
*" ready)
				   '("
INVALID
*" ready)))
	  (when (eq (va3450-state-state va3450-state) 'no-dial-tone)
	    (error 'modem-no-dial-tone))
	  (loop while (memq (va3450-state-state va3450-state) '(dialing ringing))
		doing
		(send self :input-wait
		      (format nil "~@(~A~) ~A" (va3450-state-state va3450-state) host))
		(va3450-modem-response "Dialed"
				'("ON LINE
" online)
				'("FAILED CALL
*" ready)
				'("ANSWER TONE
ON LINE 
" online)
				'("BUSY!
" busy)
				'("VOICE!
" voice)
				'("RINGING...
" ringing)
				'("FAILED CALL

*" ready)))
	  (selectq (va3450-state-state va3450-state)
	    (ready (error 'modem-call-failed :foreign-host host :connection self))
	    (busy (error 'modem-call-refused
			 :foreign-host host :connection self :reason "Phone is busy."))
	    (voice (error 'modem-call-refused
			  :foreign-host host :connection self :reason "Voice answered."))))
	
	(progn
	  (setq si:parameters user-parameters)
	  (if (neq (va3450-state-state va3450-state) 'online)
	      (send self :close :abort)
	      (send self :put :data-terminal-ready t :request-to-send t)))))))
================================================================================


Finally, after much effort and many thanks to several people (especially
Mark Grover, Grover@ADS-DC.Dialnet.Symbolics.Com) Dialnet mail was
flowing.  

	As we have two modems, and six sites, I wanted to have two
servers handling Dialnet.  This cannot be done as the registry only
keeps one slot per domain server.  Two machines may dial out, but only
one will be able to receive mail, if it is to be the server for all the
domains.  As a result, if you wish to contact me via dialnet the
following lines should be in the file
SYS:SITE;PRIVATE-DIALNET-REGISTRY.LISP

================================================================================
;;; Peter Gergely: (902) 426-3100 x 215 (Peter@DREA-XX.ARPA or GERGELY@DREA-XX.ARPA) AST
;;; Defence Research Establishment Atlantic; P.O. Box 1012, Dartmouth, Nova Scotia, Canada
;;; Postmaster's address: Postmaster@DREA.Dialnet.Symbolics.Com
(:HOST "DREA-GRIFFIN" :ADDRESS "19024262727")
(:HOST "DREA-PEGASUS" :ADDRESS "19024266813")
(:DOMAIN "DREA.Dialnet.Symbolics.Com" :HOST "DREA-PEGASUS")
(:DOMAIN "DREA-XX.Dialnet.Symbolics.Com" :HOST "DREA-PEGASUS")
;;; The .ARPA ones should only be used if you are not on the ARPANET
(:DOMAIN "Drea.ARPA" :HOST "DREA-PEGASUS")
(:DOMAIN "Drea-XX.ARPA" :HOST "DREA-PEGASUS")

#||
;;; dial|drea-pegasus will run a store-and-forward mailer servicing the domains named
;;; drea.dialnet.canada.mil, drea.drenet, drea.arpa, etc.  These may prove usefull
;;; sometime in the near future
(:DOMAIN "Drea.DreNet" :HOST "DREA-PEGASUS")
(:DOMAIN "Drea.DialNet.Canada.MIL" :HOST "DREA-PEGASUS")
(:DOMAIN "Drea-XX.DreNet" :HOST "DREA-PEGASUS")
(:DOMAIN "Drea-XX.DialNet.Canada.MIL" :HOST "DREA-PEGASUS")
||#
================================================================================

	In summary, with all of the above patches and fixes installed,
our machines now have dialnet service, both in sending and in receiving
mail.
	One last note that may help in debugging mailer problems is
setting the variable MAILER:DEBUG to T in your >MAIL>STATIC>OPTIONS.LISP
file.

NOTE:  The NUMBER-TO-DIAL patch was done by Jim Dumoulin, while the
others were done by myself.  The code itself is proprietary to
Symbolics, Inc.

Peter J. Gergely

ARPA:		GERGELY@DREA-XX.Arpa
Dialnet:	Peter@DREA-Griffin.DREA.Dialnet.Symbolics.Com
-------