;;; -*- Mode:Lisp; Readtable:CL; Package:USER; Base:10; Patch-File:T -*-
;;; Patch file for System version 121.14
;;; Reason:
;;;  CHAOS bugs found when testing band transfer over Excelan:
;;;   -  If an RFC packet is retransmitted, the foreign hosts sets its send window to 65535.
;;;      Fix: don't clobber the PKT-ACK-NUM field of an RFC packet which is (undocumentedly) being used to
;;;           transmit the initial send window.  Also don't believe a received window > MAXIMUM-WINDOW-SIZE
;;;   -  RECEIPT was updating the send window before taking into account the packet numbers just acknowledged
;;;   -  (serious bug -- totally screws flow control) The first data word of a STS packet is supposed to contain
;;;      the highest packet number "successfully received".  In the context of this implementation, that means
;;;      the last packet read by the user.  We were setting it to the last packet received in order, whether the
;;;      user has read it or not.  We now set it to the last packet read by user, which protects us from being
;;;      flooded by old systems.   We also ignore the first data word of received STS packets, taking the
;;;      PKT-ACK-NUM instead, which keeps old systems from being flooded by us.
;;; Reason:
;;;  CHAOS bugs noted while trying to find why band transfer swamped system:
;;;  If an RFC packet is retransmitted, the undocumented usage of the PKT-ACK-NUM field as initial window is
;;;  broken -- it gets set to 65535.  This necessitates two changes: don't modify this field in an RFC on
;;;  transmission or retransmission, and if the received window is > MAXIMUM-WINDOW-SIZE, use a reasonable value.
;;;  Also, update SEND-PKT-ACKED field of CONN before recalculating foreign window.
;;; Written 28-Jan-87 12:53:47 by pld (Peter L. DeWolf) at site LMI Cambridge
;;; while running on Azathoth from band 3
;;; with Experimental System 121.13, Experimental Lambda-Diag 15.0, Experimental ZMail 70.2, Experimental KERMIT 32.0, Experimental Unix-Interface 10.0, Experimental Local-File 72.0, Experimental FILE-Server 21.0, Experimental Tape 13.0, Experimental Site Data Editor 4.0, microcode 1730, SDU Boot Tape 3.12, SDU ROM 102, the old ones.



; From modified file DJ: L.NETWORK.CHAOS; CHSNCP.LISP#372 at 28-Jan-87 12:54:50
#8R CHAOS#: #!:ZL
(COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "CHAOS")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; CHAOS; CHSNCP  "

(DEFUN TRANSMIT-PKT (PKT &OPTIONAL ACK-P)
  "Put the pkt on the transmit list, and create a phony transmitter interrupt
  if needed so that the interrupt level will start sending.
If the second arg is T, put an ACK aboard this PKT.
This is a very low level function, called mainly by the following 2 functions.
/(Also called by the retransmitter and forwarder.)"
    (AND (> (PKT-NBYTES PKT) MAX-DATA-BYTES-PER-PKT)
	 (FERROR "Attempt to transmit an invalid packet (~S).~%   ~
			The length ~O is greater than the maximum packet size (~O)."
		 PKT (PKT-NBYTES PKT) MAX-DATA-BYTES-PER-PKT))
    (WHEN (and ACK-P (not (= (pkt-opcode pkt) rfc-op)))
      (WITHOUT-INTERRUPTS
	(LET ((CONN (PKT-SOURCE-CONN PKT)))
	  (OR CONN (FERROR "~S has null connection." PKT))
	  (LET ((ACKN (PKT-NUM-READ CONN)))
	    (SETF (PKT-ACK-NUM PKT) ACKN)
	    (SETF (PKT-NUM-ACKED CONN) ACKN)))))
    (SETF (PKT-TIME-TRANSMITTED PKT) (TIME))
    (SETF (PKT-TIMES-TRANSMITTED PKT) (1+ (PKT-TIMES-TRANSMITTED PKT)))
    (TRANSMIT-INT-PKT (CONVERT-TO-INT-PKT PKT)) )

))

; From modified file DJ: L.NETWORK.CHAOS; CHSNCP.LISP#372 at 28-Jan-87 12:55:49
#8R CHAOS#: #!:ZL
(COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "CHAOS")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; CHAOS; CHSNCP  "

(DEFUN RFC-MEETS-LSN (CONN PKT)
  (SETF (FOREIGN-ADDRESS CONN) (PKT-SOURCE-ADDRESS PKT))
  (SETF (FOREIGN-INDEX-NUM CONN) (PKT-SOURCE-INDEX-NUM PKT))
  (SETF (FOREIGN-WINDOW-SIZE CONN) (if (> (PKT-ACK-NUM PKT) maximum-window-size) 0 (pkt-ack-num pkt)))
  (SETF (PKT-NUM-READ CONN) (PKT-NUM PKT))
  (SETF (PKT-NUM-RECEIVED CONN) (PKT-NUM PKT))
  (SETF (PKT-NUM-ACKED CONN) (PKT-NUM PKT))
  (SETF (STATE CONN) 'RFC-RECEIVED-STATE)
  (SETF (READ-PKTS CONN) PKT)
  (SETF (READ-PKTS-LAST CONN) PKT)
  (SETF (PKT-LINK PKT) NIL)
  (INTERRUPT-CONN :CHANGE-OF-STATE CONN 'RFC-RECEIVED-STATE)
  (INTERRUPT-CONN :INPUT CONN))

))

; From modified file DJ: L.NETWORK.CHAOS; CHSNCP.LISP#372 at 28-Jan-87 12:56:28
#8R CHAOS#: #!:ZL
(COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "CHAOS")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; CHAOS; CHSNCP  "

(DEFUN RECEIPT (CONN ACK-LEV)
 (WITHOUT-INTERRUPTS
  (LET ((SENDS (SEND-PKTS CONN))	;(Save array references...)
	(NEXT NIL)			;Prevent weird screw.
	(LENGTH (SEND-PKTS-LENGTH CONN)))
    (DO ((PKT SENDS NEXT))		;For each PKT not yet ACKed which this ACKs,
	((OR (NULL PKT) (PKTNUM-< ACK-LEV (PKT-NUM PKT))))
;     (SETQ NEXT (PKT-LINK PKT))
      (SETQ NEXT (SETQ SENDS (PKT-LINK PKT)))  ;Two variables only for "clairity"
      (FREE-PKT PKT)
      (SETQ LENGTH (1- LENGTH)))
    
    (SETF (SEND-PKTS CONN) SENDS)
    (SETF (SEND-PKTS-LENGTH CONN) LENGTH)
    (COND ((NULL SENDS) (SETF (SEND-PKTS-LAST CONN) NIL))))
  (cond ((PKTNUM-< (SEND-PKT-ACKED CONN) ack-lev)
	 (SETF (SEND-PKT-ACKED CONN) ack-lev)))
  (update-window-available conn)))

))

; From file DJ: L.NETWORK.CHAOS; CHSNCP.LISP#374 at 28-Jan-87 14:16:07
#8R CHAOS#: #!:ZL
(COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "CHAOS")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; CHAOS; CHSNCP  "

(DEFUN TRANSMIT-STS (CONN WHY &optional PKT)
  (SETF (AREF STS-WHY-ARRAY (ARRAY-LEADER STS-WHY-ARRAY 1)) WHY)
  (SETF (ARRAY-LEADER STS-WHY-ARRAY 1) (\ (1+ (ARRAY-LEADER STS-WHY-ARRAY 1)) #o100))
  (unless pkt
    (SETQ PKT (ALLOCATE-INT-PKT)))
  (SETF (PKT-OPCODE PKT) STS-OP)
  (SETF (PKT-NBYTES-on-write PKT) 4)
  ;;Set the first-data-word to the highest packet number successfully received
  ;;We set it to CONN-PKT-NUM-READ, which is also what goes into the PKT-ACK-NUM field,
  ;; because old CHAOS implementations use this field, rather than PKT-ACK-NUM, to
  ;; update the available send window.
  ;;(SETF (PKT-FIRST-DATA-WORD PKT) (PKT-NUM-RECEIVED CONN))
  (SETF (PKT-FIRST-DATA-WORD PKT) (PKT-NUM-READ CONN))
  (SETF (PKT-SECOND-DATA-WORD PKT) (LOCAL-WINDOW-SIZE CONN))
  (TRANSMIT-INT-PKT-FOR-CONN CONN PKT))

))

; From modified file DJ: L.NETWORK.CHAOS; CHSNCP.LISP#374 at 28-Jan-87 14:27:45
#8R CHAOS#: #!:ZL
(COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "CHAOS")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; CHAOS; CHSNCP  "

(DEFUN RECEIVE-STS (CONN INT-PKT)
  (SETF (FOREIGN-WINDOW-SIZE CONN) (PKT-SECOND-DATA-WORD INT-PKT))
  (RECEIPT CONN (PKT-ACK-NUM INT-PKT))
  (FREE-INT-PKT INT-PKT))

))
