Author: ctian Date: Fri Oct 3 08:49:40 2008 New Revision: 426
Added: usocket/branches/experimental-udp/rtt-client.lisp (contents, props changed) usocket/branches/experimental-udp/rtt.lisp (contents, props changed) usocket/branches/experimental-udp/server.lisp (contents, props changed) Modified: usocket/branches/experimental-udp/backend/allegro.lisp usocket/branches/experimental-udp/backend/cmucl.lisp usocket/branches/experimental-udp/backend/lispworks.lisp usocket/branches/experimental-udp/backend/openmcl.lisp usocket/branches/experimental-udp/backend/sbcl.lisp usocket/branches/experimental-udp/condition.lisp usocket/branches/experimental-udp/package.lisp usocket/branches/experimental-udp/usocket.asd usocket/branches/experimental-udp/usocket.lisp Log: [experimental-udp] initial commit, no support on scl/clisp/armedbear, buggy on others.
Modified: usocket/branches/experimental-udp/backend/allegro.lisp ============================================================================== --- usocket/branches/experimental-udp/backend/allegro.lisp (original) +++ usocket/branches/experimental-udp/backend/allegro.lisp Fri Oct 3 08:49:40 2008 @@ -49,7 +49,7 @@ :text :binary))
-(defun socket-connect (host port &key (element-type 'character) +(defun socket-connect (host port &key (protocol :tcp) (element-type 'character) timeout deadline (nodelay t) ;; nodelay == t is the ACL default local-host local-port) @@ -59,22 +59,38 @@ (let ((socket)) (setf socket (with-mapped-conditions (socket) - (if timeout - (mp:with-timeout (timeout nil) - (socket:make-socket :remote-host (host-to-hostname host) - :remote-port port - :local-host (when local-host (host-to-hostname local-host)) - :local-port local-port - :format (to-format element-type) - :nodelay nodelay)) - (socket:make-socket :remote-host (host-to-hostname host) - :remote-port port - :local-host local-host - :local-port local-port - :format (to-format element-type) - :nodelay nodelay)))) - (make-stream-socket :socket socket :stream socket))) - + (ecase protocol + (:tcp (if timeout + (mp:with-timeout (timeout nil) + (socket:make-socket :remote-host (host-to-hostname host) + :remote-port port + :local-host (when local-host (host-to-hostname local-host)) + :local-port local-port + :format (to-format element-type) + :nodelay nodelay)) + (socket:make-socket :remote-host (host-to-hostname host) + :remote-port port + :local-host (when local-host (host-to-hostname local-host)) + :local-port local-port + :format (to-format element-type) + :nodelay nodelay))) + (:udp (if (and host port) + (socket:make-socket :type :datagram + :address-family :internet + :connect :active + :remote-host (host-to-hostname host) + :remote-port port + :local-host (when local-host (host-to-hostname local-host)) + :local-port local-port + :format (to-format element-type)) + (socket:make-socket :type :datagram + :address-family :internet + :local-host local-host + :local-port (when local-host (host-to-hostname local-host)) + :format (to-format element-type))))))) + (ecase protocol + (:tcp (make-stream-socket :socket socket :stream socket)) + (:udp (make-datagram-socket socket)))))
;; One socket close method is sufficient, ;; because socket-streams are also sockets. @@ -113,6 +129,16 @@ (socket:accept-connection (socket socket))))) (make-stream-socket :socket stream-sock :stream stream-sock)))
+(defmethod socket-send ((socket datagram-usocket) buffer length &key address port) + (with-mapped-conditions (socket) + (let ((s (socket socket))) + (socket:send-to s buffer length :remote-host address :remote-port port)))) + +(defmethod socket-receive ((socket datagram-usocket) buffer length) + (with-mapped-conditions (socket) + (let ((s (socket socket))) + (socket:receive-from s length :buffer buffer :extract t)))) + (defmethod get-local-address ((usocket usocket)) (hbo-to-vector-quad (socket:local-host (socket usocket))))
Modified: usocket/branches/experimental-udp/backend/cmucl.lisp ============================================================================== --- usocket/branches/experimental-udp/backend/cmucl.lisp (original) +++ usocket/branches/experimental-udp/backend/cmucl.lisp Fri Oct 3 08:49:40 2008 @@ -50,7 +50,7 @@ :socket socket :condition condition))))
-(defun socket-connect (host port &key (element-type 'character) +(defun socket-connect (host port &key (protocol :tcp) (element-type 'character) timeout deadline (nodelay t nodelay-specified) local-host local-port) (declare (ignore nodelay)) @@ -61,20 +61,43 @@ (unsupported 'local-host 'socket-connect) (unsupported 'local-port 'socket-connect))
- (let* ((socket)) - (setf socket - (with-mapped-conditions (socket) - (ext:connect-to-inet-socket (host-to-hbo host) port :stream))) - (if socket - (let* ((stream (sys:make-fd-stream socket :input t :output t - :element-type element-type - :buffering :full)) - ;;###FIXME the above line probably needs an :external-format - (usocket (make-stream-socket :socket socket - :stream stream))) - usocket) - (let ((err (unix:unix-errno))) - (when err (cmucl-map-socket-error err)))))) + (let ((socket)) + (ecase protocol + (:tcp (progn + (setf socket + (with-mapped-conditions (socket) + (ext:connect-to-inet-socket (host-to-hbo host) port + (cdr (assoc protocol +protocol-map+)) + :local-host (if local-host + (host-to-hbo local-host)) + :local-port local-port))) + (if socket + (let* ((stream (sys:make-fd-stream socket :input t :output t + :element-type element-type + :buffering :full)) + ;;###FIXME the above line probably needs an :external-format + (usocket (make-stream-socket :socket socket + :stream stream))) + usocket) + (let ((err (unix:unix-errno))) + (when err (cmucl-map-socket-error err)))))) + (:udp (progn + (if (and host port) + (setf socket (with-mapped-conditions (socket) + (ext:connect-to-inet-socket (host-to-hbo host) port :datagram + :local-host (if local-host + (host-to-hbo local-host)) + :local-port local-port))) + (progn + (setf socket (with-mapped-conditions (socket) + (ext:create-inet-socket :datagram))) + (when (and local-host local-port) + (with-mapped-conditions (socket) + (ext:bind-inet-socket socket local-host local-port))))) + (let ((usocket (make-datagram-socket socket))) + (ext:finalize usocket #'(lambda () (unless (%closed-p usocket) + (ext:close-socket socket)))) + usocket))))))
(defun socket-listen (host port &key reuseaddress @@ -119,6 +142,24 @@ (with-mapped-conditions (usocket) (ext:close-socket (socket usocket))))
+(defmethod socket-close :after ((socket datagram-usocket)) + (setf (%closed-p socket) t)) + +(defmethod socket-send ((usocket datagram-usocket) buffer length &key address port) + (with-mapped-conditions (usocket) + (ext:inet-sendto (socket usocket) buffer length (if address (host-to-hbo address)) port))) + +(defmethod socket-receive ((usocket datagram-usocket) buffer length) + (let ((real-buffer (or buffer + (make-array length :element-type '(unsigned-byte 8)))) + (real-length (or length + (length buffer)))) + (multiple-value-bind (nbytes remote-host remote-port) + (with-mapped-conditions (usocket) + (ext:inet-recvfrom (socket usocket) real-buffer real-length)) + (when (plusp nbytes) + (values real-buffer nbytes remote-host remote-port))))) + (defmethod get-local-name ((usocket usocket)) (multiple-value-bind (address port)
Modified: usocket/branches/experimental-udp/backend/lispworks.lisp ============================================================================== --- usocket/branches/experimental-udp/backend/lispworks.lisp (original) +++ usocket/branches/experimental-udp/backend/lispworks.lisp Fri Oct 3 08:49:40 2008 @@ -73,7 +73,7 @@ (declare (ignore host port err-msg)) (raise-usock-err errno socket condition)))))
-(defun socket-connect (host port &key (element-type 'base-char) +(defun socket-connect (host port &key (protocol :tcp) (element-type 'base-char) timeout deadline (nodelay t nodelay-specified) local-host local-port) (declare (ignorable nodelay)) @@ -87,23 +87,36 @@ (unsupported 'local-host 'socket-connect :minimum "LispWorks 5.0+ (verified)") (unsupported 'local-port 'socket-connect :minimum "LispWorks 5.0+ (verified)"))
- (let ((hostname (host-to-hostname host)) - (stream)) - (setf stream - (with-mapped-conditions () - (comm:open-tcp-stream hostname port - :element-type element-type - #-lispworks4 #-lispworks4 - #-lispworks4 #-lispworks4 - :local-address (when local-host (host-to-hostname local-host)) - :local-port local-port - #+(and (not lispworks4) (not lispworks5.0)) - #+(and (not lispworks4) (not lispworks5.0)) - :nodelay nodelay))) - (if stream - (make-stream-socket :socket (comm:socket-stream-socket stream) - :stream stream) - (error 'unknown-error)))) + (ecase protocol + (:tcp (let ((hostname (host-to-hostname host)) + (stream)) + (setf stream + (with-mapped-conditions () + (comm:open-tcp-stream hostname port + :element-type element-type + #-lispworks4 #-lispworks4 + #-lispworks4 #-lispworks4 + :local-address (when local-host (host-to-hostname local-host)) + :local-port local-port + #+(and (not lispworks4) (not lispworks5.0)) + #+(and (not lispworks4) (not lispworks5.0)) + :nodelay nodelay))) + (if stream + (make-stream-socket :socket (comm:socket-stream-socket stream) + :stream stream) + (error 'unknown-error)))) + (:udp (let ((usocket (make-datagram-socket + (if (and host port) + (comm:connect-to-udp-server host port + :errorp t + :local-address local-host + :local-port local-port) + (comm:open-udp-socket :errorp t + :local-address local-host + :local-port local-port)) + :connected-p t))) + (hcl:flag-special-free-action usocket) + usocket))))
(defun socket-listen (host port &key reuseaddress @@ -152,6 +165,27 @@ (with-mapped-conditions (usocket) (comm::close-socket (socket usocket))))
+(defmethod socket-close :after ((socket datagram-usocket)) + "Additional socket-close method for datagram-usocket" + (setf (%closed-p socket) t)) + +;; Register a special free action for closing datagram usocket when being GCed +(defun usocket-special-free-action (object) + (when (and (typep object 'datagram-usocket) + (not (closed-p object))) + (socket-close object))) + +(eval-when (:load-toplevel :execute) + (hcl:add-special-free-action 'usocket-special-free-action)) + +(defmethod socket-send ((socket datagram-usocket) buffer length &key address port) + (let ((s (socket socket))) + (comm:send-message s buffer length address port))) + +(defmethod socket-receive ((socket datagram-usocket) buffer length) + (let ((s (socket socket))) + (comm:receive-message s buffer length))) + (defmethod get-local-name ((usocket usocket)) (multiple-value-bind (address port)
Modified: usocket/branches/experimental-udp/backend/openmcl.lisp ============================================================================== --- usocket/branches/experimental-udp/backend/openmcl.lisp (original) +++ usocket/branches/experimental-udp/backend/openmcl.lisp Fri Oct 3 08:49:40 2008 @@ -74,21 +74,36 @@ :text :binary))
-(defun socket-connect (host port &key (element-type 'character) timeout deadline nodelay +(defun socket-connect (host port &key (protocol :tcp) (element-type 'character) + timeout deadline nodelay local-host local-port) (with-mapped-conditions () - (let ((mcl-sock - (openmcl-socket:make-socket :remote-host (host-to-hostname host) - :remote-port port - :local-host (when local-host (host-to-hostname local-host)) - :local-port local-port - :format (to-format element-type) - :deadline deadline - :nodelay nodelay - :connect-timeout (and timeout - (* timeout internal-time-units-per-second))))) - (openmcl-socket:socket-connect mcl-sock) - (make-stream-socket :stream mcl-sock :socket mcl-sock)))) + (ecase protocol + (:tcp + (let ((mcl-sock + (openmcl-socket:make-socket :remote-host (host-to-hostname host) + :remote-port port + :local-host (when local-host (host-to-hostname local-host)) + :local-port local-port + :format (to-format element-type) + :deadline deadline + :nodelay nodelay + :connect-timeout (and timeout + (* timeout internal-time-units-per-second))))) + (openmcl-socket:socket-connect mcl-sock) + (make-stream-socket :stream mcl-sock :socket mcl-sock))) + (:udp + (let ((mcl-sock + (openmcl-socket:make-socket :address-family :internet + :type :datagram + :local-host (if local-host + (host-to-hbo local-host)) + :local-port local-port))) + (when (and host port) + (ccl::inet-connect (ccl::socket-device mcl-sock) + (ccl::host-as-inet-host host) + (ccl::port-as-inet-port port "udp"))) + (make-datagram-socket mcl-sock))))))
(defun socket-listen (host port &key reuseaddress @@ -122,6 +137,16 @@ (with-mapped-conditions (usocket) (close (socket usocket))))
+(defmethod socket-send ((usocket datagram-usocket) buffer length &key address port) + (with-mapped-conditions (usocket) + (openmcl-socket:send-to (socket usocket) buffer length + :remote-host (if address (host-to-hbo address)) + :remote-port port))) + +(defmethod socket-receive ((usocket datagram-usocket) buffer length) + (with-mapped-conditions (usocket) + (openmcl-socket:receive-from (socket usocket) length :buffer buffer))) + (defmethod get-local-address ((usocket usocket)) (hbo-to-vector-quad (openmcl-socket:local-host (socket usocket))))
Modified: usocket/branches/experimental-udp/backend/sbcl.lisp ============================================================================== --- usocket/branches/experimental-udp/backend/sbcl.lisp (original) +++ usocket/branches/experimental-udp/backend/sbcl.lisp Fri Oct 3 08:49:40 2008 @@ -199,8 +199,7 @@ (if usock-cond (signal usock-cond :socket socket))))))
- -(defun socket-connect (host port &key (element-type 'character) +(defun socket-connect (host port &key (protocol :tcp) (element-type 'character) timeout deadline (nodelay t nodelay-specified) local-host local-port) (when deadline (unsupported 'deadline 'socket-connect)) @@ -214,28 +213,38 @@ (unsupported 'nodelay 'socket-connect))
(let ((socket (make-instance 'sb-bsd-sockets:inet-socket - :type :stream :protocol :tcp))) + :type (cdr (assoc protocol +protocol-map+)) + :protocol protocol))) (handler-case - (let* ((stream - (sb-bsd-sockets:socket-make-stream socket - :input t - :output t - :buffering :full - :element-type element-type)) - ;;###FIXME: The above line probably needs an :external-format - (usocket (make-stream-socket :stream stream :socket socket)) - (ip (host-to-vector-quad host))) - (when (and nodelay-specified - (fboundp 'sb-bsd-sockets::sockopt-tcp-nodelay)) - (setf (sb-bsd-sockets:sockopt-tcp-nodelay socket) nodelay)) - (when (or local-host local-port) - (sb-bsd-sockets:socket-bind socket - (host-to-vector-quad - (or local-host *wildcard-host*)) - (or local-port *auto-port*))) - (with-mapped-conditions (usocket) - (sb-bsd-sockets:socket-connect socket ip port)) - usocket) + (ecase protocol + (:tcp (let* ((stream + (sb-bsd-sockets:socket-make-stream socket + :input t + :output t + :buffering :full + :element-type element-type)) + ;;###FIXME: The above line probably needs an :external-format + (usocket (make-stream-socket :stream stream :socket socket)) + (ip (host-to-vector-quad host))) + (when (and nodelay-specified + (fboundp 'sb-bsd-sockets::sockopt-tcp-nodelay)) + (setf (sb-bsd-sockets:sockopt-tcp-nodelay socket) nodelay)) + (when (or local-host local-port) + (sb-bsd-sockets:socket-bind socket + (host-to-vector-quad + (or local-host *wildcard-host*)) + (or local-port *auto-port*))) + (with-mapped-conditions (usocket) + (sb-bsd-sockets:socket-connect socket ip port)) + usocket)) + (:udp (progn + (when (and local-host local-port) + (sb-bsd-sockets:socket-bind socket + (host-to-vector-quad local-host) + local-port)) + (when (and host port) + (sb-bsd-sockets:socket-connect socket (host-to-hbo host) port)) + (make-datagram-socket socket)))) (t (c) ;; Make sure we don't leak filedescriptors (sb-bsd-sockets:socket-close socket) @@ -287,6 +296,18 @@ (with-mapped-conditions (usocket) (close (socket-stream usocket))))
+(defmethod socket-send ((socket datagram-usocket) buffer length &key address port) + (with-mapped-conditions (socket) + (let* ((s (socket socket)) + (dest (if (and address port) (list (host-to-vector-quad address) port) nil))) + (sb-bsd-sockets:socket-send s buffer length :address dest)))) + +(defmethod socket-receive ((socket datagram-usocket) buffer length + &key (element-type '(unsigned-byte 8))) + (with-mapped-conditions (socket) + (let ((s (socket socket))) + (sb-bsd-sockets:socket-receive s buffer length :element-type element-type)))) + (defmethod get-local-name ((usocket usocket)) (sb-bsd-sockets:socket-name (socket usocket)))
Modified: usocket/branches/experimental-udp/condition.lisp ============================================================================== --- usocket/branches/experimental-udp/condition.lisp (original) +++ usocket/branches/experimental-udp/condition.lisp Fri Oct 3 08:49:40 2008 @@ -197,4 +197,44 @@ :context ,context :minimum ,minimum))
(defmacro unimplemented (feature context) - `(signal 'unimplemented :feature ,feature :context ,context)) \ No newline at end of file + `(signal 'unimplemented :feature ,feature :context ,context)) + +;;; binghe: socket-warning for UDP retransmit support + +(define-condition socket-warning (socket-condition warning) + () ;; no slots (yet) + (:documentation "Parent warning for all socket related warnings")) + +(define-condition rtt-timeout-warning (socket-warning) + ((old-rto :type short-float + :reader old-rto-of + :initarg :old-rto) + (new-rto :type short-float + :reader new-rto-of + :initarg :new-rto)) + (:report (lambda (condition stream) + (format stream "Receive timeout (~As), next: ~As.~%" + (old-rto-of condition) + (new-rto-of condition)))) + (:documentation "RTT timeout warning")) + +(define-condition rtt-seq-mismatch-warning (socket-warning) + ((send-seq :type integer + :reader send-seq-of + :initarg :send-seq) + (recv-seq :type integer + :reader recv-seq-of + :initarg :recv-seq)) + (:report (lambda (condition stream) + (format stream "Sequence number mismatch (~A -> ~A), try read again.~%" + (send-seq-of condition) + (recv-seq-of condition)))) + (:documentation "RTT sequence mismatch warning")) + +(define-condition rtt-timeout-error (socket-error) + () + (:report (lambda (condition stream) + (declare (ignore condition)) + (format stream "Max retransmit times (~A) reached, give up.~%" + *rtt-maxnrexmt*))) + (:documentation "RTT timeout error"))
Modified: usocket/branches/experimental-udp/package.lisp ============================================================================== --- usocket/branches/experimental-udp/package.lisp (original) +++ usocket/branches/experimental-udp/package.lisp Fri Oct 3 08:49:40 2008 @@ -11,6 +11,9 @@ (:export #:*wildcard-host* #:*auto-port*
+ #:*remote-host* ; special variables (udp) + #:*remote-port* + #:socket-connect ; socket constructors and methods #:socket-listen #:socket-accept @@ -22,6 +25,11 @@ #:get-local-name #:get-peer-name
+ #:socket-send ; udp function (send) + #:socket-receive ; udp function (receive) + #:socket-sync ; udp client (high-level) + #:socket-server ; udp server + #:wait-for-input ; waiting for input-ready state (select() like) #:make-wait-list #:add-waiter @@ -65,6 +73,7 @@ #:ns-unknown-condition #:unknown-error #:ns-unknown-error + #:socket-warning ; warnings (udp)
#:insufficient-implementation ; conditions regarding usocket support level #:unsupported
Added: usocket/branches/experimental-udp/rtt-client.lisp ============================================================================== --- (empty file) +++ usocket/branches/experimental-udp/rtt-client.lisp Fri Oct 3 08:49:40 2008 @@ -0,0 +1,50 @@ +;;;; $Id$ +;;;; $URL$ + +(in-package :usocket) + +(defun default-rtt-function (message) (values message 0)) + +(defmethod socket-sync ((socket datagram-usocket) message &key address port + (max-receive-length +max-datagram-packet-size+) + (encode-function #'default-rtt-function) + (decode-function #'default-rtt-function)) + (rtt-newpack socket) + (multiple-value-bind (data send-seq) (funcall encode-function message) + (let ((data-length (length data))) + (loop + with send-ts = (rtt-ts socket) + and recv-message = nil + and recv-seq = -1 + and continue-p = t + do (progn + (socket-send socket data data-length :address address :port port) + (multiple-value-bind (sockets real-time) + (wait-for-input socket :timeout (rtt-start socket)) + (declare (ignore sockets)) + (if real-time + ;; message received + (loop + do (multiple-value-setq (recv-message recv-seq) + (funcall decode-function + (socket-receive socket nil max-receive-length))) + until (or (= recv-seq send-seq) + (warn 'rtt-seq-mismatch-warning + :socket socket + :send-seq send-seq + :recv-seq recv-seq)) + finally (let ((recv-ts (rtt-ts socket))) + (rtt-stop socket (- recv-ts send-ts)) + (return nil))) + ;; message not received + (let ((old-rto (slot-value socket 'rto))) + (setf continue-p (rtt-timeout socket)) + (warn 'rtt-timeout-warning + :socket socket + :old-rto old-rto + :new-rto (slot-value socket 'rto)) + (unless continue-p + (error 'rtt-timeout-error) + (rtt-init socket)))))) + until (or recv-message (not continue-p)) + finally (return recv-message)))))
Added: usocket/branches/experimental-udp/rtt.lisp ============================================================================== --- (empty file) +++ usocket/branches/experimental-udp/rtt.lisp Fri Oct 3 08:49:40 2008 @@ -0,0 +1,80 @@ +;;;; $Id$ +;;;; $URL$ + +;;;; UDP retransmit support by Chun Tian (binghe) +;;;; See the LICENSE file for licensing information. + +(in-package :usocket) + +;;; UNIX Network Programming v1 - Networking APIs: Sockets and XTI +;;; Chapter 20: Advance UDP Sockets +;;; Adding Reliability to a UDP Application + +(defclass rtt-info-mixin () + ((rtt :type short-float + :documentation "most recent measured RTT, seconds") + (srtt :type short-float + :documentation "smoothed RTT estimator, seconds") + (rttvar :type short-float + :documentation "smoothed mean deviation, seconds") + (rto :type short-float + :documentation "current RTO to use, seconds") + (nrexmt :type fixnum + :documentation "#times retransmitted: 0, 1, 2, ...") + (base :type integer + :documentation "#sec since 1/1/1970 at start, but we use Lisp time here")) + (:documentation "RTT Info Class")) + +(defvar *rtt-rxtmin* 2.0 "min retransmit timeout value, seconds") +(defvar *rtt-rxtmax* 60.0 "max retransmit timeout value, seconds") +(defvar *rtt-maxnrexmt* 3 "max #times to retransmit") + +(defmethod rtt-rtocalc ((instance rtt-info-mixin)) + "Calculate the RTO value based on current estimators: + smoothed RTT plus four times the deviation." + (with-slots (srtt rttvar) instance + (+ srtt (* 4.0 rttvar)))) + +(defun rtt-minmax (rto) + "rtt-minmax makes certain that the RTO is between the upper and lower limits." + (declare (type short-float rto)) + (cond ((< rto *rtt-rxtmin*) *rtt-rxtmin*) + ((> rto *rtt-rxtmax*) *rtt-rxtmax*) + (t rto))) + +(defmethod initialize-instance :after ((instance rtt-info-mixin) &rest initargs + &key &allow-other-keys) + (declare (ignore initargs)) + (rtt-init instance)) + +(defmethod rtt-init ((instance rtt-info-mixin)) + (with-slots (base rtt srtt rttvar rto) instance + (setf base (get-internal-real-time) + rtt 0.0 + srtt 0.0 + rttvar 0.75 + rto (rtt-minmax (rtt-rtocalc instance))))) + +(defmethod rtt-ts ((instance rtt-info-mixin)) + (* (- (get-internal-real-time) (slot-value instance 'base)) + #.(/ 1000 internal-time-units-per-second))) + +(defmethod rtt-start ((instance rtt-info-mixin)) + "return value can be used as: alarm(rtt_start(&foo))" + (round (slot-value instance 'rto))) + +(defmethod rtt-stop ((instance rtt-info-mixin) (ms number)) + (with-slots (rtt srtt rttvar rto) instance + (setf rtt (/ ms 1000.0)) + (let ((delta (- rtt srtt))) + (incf srtt (/ delta 8.0)) + (incf rttvar (/ (- (abs delta) rttvar) 4.0))) + (setf rto (rtt-minmax (rtt-rtocalc instance))))) + +(defmethod rtt-timeout ((instance rtt-info-mixin)) + (with-slots (rto nrexmt) instance + (setf rto (* rto 2.0)) + (< (incf nrexmt) *rtt-maxnrexmt*))) + +(defmethod rtt-newpack ((instance rtt-info-mixin)) + (setf (slot-value instance 'nrexmt) 0))
Added: usocket/branches/experimental-udp/server.lisp ============================================================================== --- (empty file) +++ usocket/branches/experimental-udp/server.lisp Fri Oct 3 08:49:40 2008 @@ -0,0 +1,43 @@ +;;;; $Id$ +;;;; $URL$ + +(in-package :usocket) + +(defvar *remote-host*) +(defvar *remote-port*) + +(defun socket-server (host port function &optional arguments + &key (element-type '(unsigned-byte 8)) (timeout 1) + (max-buffer-size +max-datagram-packet-size+)) + (let ((socket (socket-connect nil nil + :protocol :udp + :local-host host + :local-port port + :element-type element-type)) + (buffer (make-array max-buffer-size + :element-type '(unsigned-byte 8) + :initial-element 0))) + (unwind-protect + (loop (progn + (multiple-value-bind (sockets real-time) + (wait-for-input socket :timeout timeout) + (declare (ignore sockets)) + (when real-time + (multiple-value-bind (recv n *remote-host* *remote-port*) + (socket-receive socket buffer max-buffer-size) + (declare (ignore recv)) + (if (plusp n) + (progn + (let ((reply + (apply function + (cons (subseq buffer 0 n) arguments)))) + (when reply + (replace buffer reply) + (let ((n (socket-send socket buffer (length reply) + :address *remote-host* + :port *remote-port*))) + (when (minusp n) + (error "send error: ~A~%" n)))))) + (error "receive error: ~A" n)))) + #+(and cmu mp) (mp:process-yield)))) + (socket-close socket))))
Modified: usocket/branches/experimental-udp/usocket.asd ============================================================================== --- usocket/branches/experimental-udp/usocket.asd (original) +++ usocket/branches/experimental-udp/usocket.asd Fri Oct 3 08:49:40 2008 @@ -1,4 +1,4 @@ - +;;;; -*- Mode: Lisp -*- ;;;; $Id$ ;;;; $URL$
@@ -18,26 +18,26 @@ :licence "MIT" :description "Universal socket library for Common Lisp" :depends-on (:split-sequence - #+sbcl :sb-bsd-sockets) + #+sbcl :sb-bsd-sockets + #+lispworks :lispworks-udp) :components ((:file "package") + (:file "rtt" + :depends-on ("package")) (:file "usocket" - :depends-on ("package")) + :depends-on ("package" "rtt")) (:file "condition" - :depends-on ("usocket")) - #+clisp (:file "clisp" :pathname "backend/clisp" - :depends-on ("condition")) - #+cmu (:file "cmucl" :pathname "backend/cmucl" - :depends-on ("condition")) - #+scl (:file "scl" :pathname "backend/scl" - :depends-on ("condition")) - #+(or sbcl ecl) (:file "sbcl" :pathname "backend/sbcl" - :depends-on ("condition")) - #+lispworks (:file "lispworks" :pathname "backend/lispworks" - :depends-on ("condition")) - #+openmcl (:file "openmcl" :pathname "backend/openmcl" - :depends-on ("condition")) - #+allegro (:file "allegro" :pathname "backend/allegro" - :depends-on ("condition")) - #+armedbear (:file "armedbear" :pathname "backend/armedbear" - :depends-on ("condition")) - )) + :depends-on ("usocket" "rtt")) + (:module "backend" + :components (#+clisp (:file "clisp") + #+cmu (:file "cmucl") + #+scl (:file "scl") + #+(or sbcl ecl) (:file "sbcl") + #+lispworks (:file "lispworks") + #+openmcl (:file "openmcl") + #+allegro (:file "allegro") + #+armedbear (:file "armedbear")) + :depends-on ("condition")) + (:file "rtt-client" + :depends-on ("rtt" "backend" "condition")) + (:file "server" + :depends-on ("backend"))))
Modified: usocket/branches/experimental-udp/usocket.lisp ============================================================================== --- usocket/branches/experimental-udp/usocket.lisp (original) +++ usocket/branches/experimental-udp/usocket.lisp Fri Oct 3 08:49:40 2008 @@ -11,6 +11,9 @@ (defparameter *auto-port* 0 "Port number to pass when an auto-assigned port number is wanted.")
+(defconstant +max-datagram-packet-size+ 65536) +(defconstant +protocol-map+ '((:tcp . :stream) (:udp . :datagram))) + (defclass usocket () ((socket :initarg :socket @@ -82,10 +85,17 @@ (:documentation "Socket which listens for stream connections to be initiated from remote sockets."))
-(defclass datagram-usocket (usocket) - ((connected-p :initarg :connected-p :accessor connected-p)) -;; ###FIXME: documentation to be added. - (:documentation "")) +(defclass datagram-usocket (usocket rtt-info-mixin) + ((connected-p :type boolean + :accessor connected-p + :initarg :connected-p) + #+(or cmu lispworks) + (%closed-p :type boolean + :accessor %closed-p + :initform nil + :documentation "Flag to indicate if this usocket is closed, +for GC on LispWorks/CMUCL")) + (:documentation "UDP (inet-datagram) socket"))
(defun usocket-p (socket) (typep socket 'usocket))