;;; -*- Mode:Lisp; Readtable:CL; Package:USER; Base:10; Patch-File:T -*-
;;; Patch file for System version 123.39
;;; Reason:
;;;  If an FTP connection is interrupted for a long time (e.g. you are loading a file which
;;;  causes other files to be loaded), the remote end can time out and send a RST.
;;;  Two problems, two cures:
;;;    - FTP data connection now requests pessimistic window -- when no read buffers
;;;      available, the remote end will get a zero window, which it must (per TCP spec)
;;;      be patient about.
;;;    - TCP-STREAM now has a cerror for :reset and :close messages (remote and local
;;;      aborts), allowing you to treat them as end-of-file, but not assuming that
;;;      that is what you want to do.
;;; Written 7-Oct-87 16:50:42 by pld at site LMI Cambridge
;;; while running on Jack Flanders from band 2
;;; with Experimental System 123.38, Experimental Local-File 73.0, Experimental FILE-Server 22.0, Experimental Unix-Interface 11.0, Experimental Tape 18.0, Experimental KERMIT 34.0, Experimental ZMail 71.0, Experimental Lambda-Diag 15.0, microcode 1754, SDU Boot Tape 3.12, SDU ROM 8.



; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; TCP-STREAM.LISP#39 at 7-Oct-87 16:50:43
#10R TCP#: 
(COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TCP")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; TCP-STREAM  "

(defmethod (tcp-stream-mixin :handle-replies) (&optional no-hang-p)
  (loop
    (cond ((send socket :listen)					;Activity on the socket
	   (let ((item (send socket :read-data)))
	     (case (first item)
	       (:open
		(send self :build-buffers)
		(return :open))
	       (:write-reply
		(send self :write-reply (second item))
		(return :write-reply))
	       (:data
		(send self :read-reply (second item))
		(when (eq (third item) :eof)
		  (setq closing t))
		(return :read-reply))
	       (:closing						;Remote side has closed
		(setq closing t)
		(return :remote-close))
	       (:reset
		(setq closing t)
		(setq open nil)
		;;(cerror "Continue, treating as end-of-file" "Connection reset remotely")
		(return :reset))
	       (:close							;Socket closed out from under us
		(setq closing t)
		(setq open nil)
		;;(cerror "Continue, treating as end-of-file" "Connection reset locally")
		(return :local-close))
	       ((:network-unreachable :host-unreachable :protocol-unreachable :port-unreachable)
		(setq closing t)
		(setq open nil)
		(send socket :abort)
		(return :unreachable))
	       (:timeout
		(return :timeout))
	       (otherwise
		;;Ignore it
		))))
	  (no-hang-p							;No activity and no-hang
	   (return nil))
	  (t								;No activity -- wait
	   (wait-for-reply socket)))))

))

; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#25 at 7-Oct-87 16:50:54
#10R FTP#: 
(COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  "

(defun initconn (direction)
  (when *data*
    (close *data*)
    (setq *data* nil))
  (let ((addr nil)
	(port nil)
	(result nil))
    (setq *data* (open (format nil
			     "TCP-HOST:~D.FTP-DATA~:[#~D~;~]"
			     (send *cin* :remote-address)
			     *sendport*
			     (send *cin* :local-port))
		     :direction direction
		     :input-buffers 16
		     :output-buffers 16
		     :optimistic nil
		     :keyword "FTP Data Connection"
		     :connect nil))
    (when *sendport*
      (setq addr (send *data* :local-address))
      (setq port (send *data* :local-port))
      (setq result (command "PORT ~D,~D,~D,~D,~D,~D"
			    (ldb (byte 8 24) addr)
			    (ldb (byte 8 16) addr)
			    (ldb (byte 8 8) addr)
			    (ldb (byte 8 0) addr)
			    (ldb (byte 8 8) port)
			    (ldb (byte 8 0) port)))
	(if (= result (sym error))
	    (let ((*sendport* nil))
	      (initconn direction))
	  (not (= result (sym complete)))))))

))
