Author: ctian Date: Mon Feb 27 06:49:55 2012 New Revision: 687
Log: Align with trunk (to r683), prepare for 0.5.5
Modified: usocket/branches/0.5.x/CHANGES usocket/branches/0.5.x/backend/abcl.lisp usocket/branches/0.5.x/backend/allegro.lisp usocket/branches/0.5.x/backend/clisp.lisp usocket/branches/0.5.x/backend/cmucl.lisp usocket/branches/0.5.x/backend/lispworks.lisp usocket/branches/0.5.x/backend/mcl.lisp usocket/branches/0.5.x/backend/openmcl.lisp usocket/branches/0.5.x/backend/sbcl.lisp usocket/branches/0.5.x/backend/scl.lisp usocket/branches/0.5.x/usocket.lisp
Modified: usocket/branches/0.5.x/CHANGES ============================================================================== --- usocket/branches/0.5.x/CHANGES Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/CHANGES Mon Feb 27 06:49:55 2012 (r687) @@ -1,3 +1,11 @@ +0.5.5: + +* Enhancement: SOCKET-CONNECT argument :nodelay can now set to :if-supported (patch from Anton Vodonosov). +* Enhancement: [server] adding *remote-host* *remote-port* to socket-server stream handler functions (suggested by Matthew Curry) +* Bugfix: [LispWorks] Fixed UDP support for LispWorks 6.1 (patch from Camille Troillard by Martin Simmons). +* Bugfix: [LispWorks] Stop using hcl:add-special-free-action for reclaiming unused UDP socket fds to improve multi-threading stablity (suggested by Camille Troillard). +* Bugfix: [LispWorks] Fixed SOCKET-CONNECT on Windows, now LOCAL-PORT never have *auto-port* (0) as default value. + 0.5.4:
* Bugfix: [ECL] Fixed for ECL's MAKE-BUILD by removing some unecessary code (reported by Juan Jose Garcia-Ripoll, the ECL maintainer)
Modified: usocket/branches/0.5.x/backend/abcl.lisp ============================================================================== --- usocket/branches/0.5.x/backend/abcl.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/backend/abcl.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -212,7 +212,8 @@ (setq stream (ext:get-socket-stream socket :element-type element-type) usocket (make-stream-socket :stream stream :socket socket)) (when nodelay-supplied-p - (jcall $@setTcpNoDelay/1 socket (if nodelay +java-true+ +java-false+))) + (jcall $@setTcpNoDelay/1 socket (if nodelay ;; both t and :if-supported mean +java-true+ + +java-true+ +java-false+))) (when timeout (jcall $@setSoTimeout/Socket/1 socket (truncate (* 1000 timeout)))))) (:datagram ; UDP
Modified: usocket/branches/0.5.x/backend/allegro.lisp ============================================================================== --- usocket/branches/0.5.x/backend/allegro.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/backend/allegro.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -55,6 +55,8 @@ local-host local-port) (when timeout (unsupported 'timeout 'socket-connect)) (when deadline (unsupported 'deadline 'socket-connect)) + (when (eq nodelay :if-supported) + (setf nodelay t))
(let ((socket)) (setf socket
Modified: usocket/branches/0.5.x/backend/clisp.lisp ============================================================================== --- usocket/branches/0.5.x/backend/clisp.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/backend/clisp.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -116,10 +116,11 @@ (defun socket-connect (host port &key (protocol :stream) (element-type 'character) timeout deadline (nodelay t nodelay-specified) local-host local-port) - (declare (ignore nodelay) - (ignorable timeout local-host local-port)) + (declare (ignorable timeout local-host local-port)) (when deadline (unsupported 'deadline 'socket-connect)) - (when nodelay-specified (unsupported 'nodelay 'socket-connect)) + (when (and nodelay-specified + (not (eq nodelay :if-supported))) + (unsupported 'nodelay 'socket-connect)) (case protocol (:stream (let ((socket)
Modified: usocket/branches/0.5.x/backend/cmucl.lisp ============================================================================== --- usocket/branches/0.5.x/backend/cmucl.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/backend/cmucl.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -56,10 +56,11 @@ (local-port nil local-port-p) &aux (local-bind-p (fboundp 'ext::bind-inet-socket))) - (declare (ignore nodelay)) (when timeout (unsupported 'timeout 'socket-connect)) (when deadline (unsupported 'deadline 'socket-connect)) - (when nodelay-specified (unsupported 'nodelay 'socket-connect)) + (when (and nodelay-specified + (not (eq nodelay :if-supported))) + (unsupported 'nodelay 'socket-connect)) (when (and local-host-p (not local-bind-p)) (unsupported 'local-host 'socket-connect :minimum "Snapshot 2008-08 (19E)")) (when (and local-port-p (not local-bind-p))
Modified: usocket/branches/0.5.x/backend/lispworks.lisp ============================================================================== --- usocket/branches/0.5.x/backend/lispworks.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/backend/lispworks.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -183,7 +183,47 @@ len) (float (/ (fli:dereference timeout) 1000))))
-(defun open-udp-socket (&key local-address local-port read-timeout) +(defun initialize-dynamic-sockaddr (hostname service protocol &aux (original-hostname hostname)) + (declare (ignorable original-hostname)) + #+(or lispworks4 lispworks5 lispworks6.0) + (let ((server-addr (fli:allocate-dynamic-foreign-object + :type '(:struct comm::sockaddr_in)))) + (values (comm::initialize-sockaddr_in + server-addr + comm::*socket_af_inet* + hostname + service protocol) + comm::*socket_af_inet* + server-addr + (fli:pointer-element-size server-addr))) + #-(or lispworks4 lispworks5 lispworks6.0) + (progn + (when (stringp hostname) + (setq hostname (comm:string-ip-address hostname)) + (unless hostname + (let ((resolved-hostname (comm:get-host-entry original-hostname :fields '(:address)))) + (unless resolved-hostname + (return-from initialize-dynamic-sockaddr :unknown-host)) + (setq hostname resolved-hostname)))) + (if (or (null hostname) + (integerp hostname) + (comm:ipv6-address-p hostname)) + (let ((server-addr (fli:allocate-dynamic-foreign-object + :type '(:struct comm::lw-sockaddr)))) + (multiple-value-bind (error family) + (comm::initialize-sockaddr_in + server-addr + hostname + service protocol) + (values error family + server-addr + (if (eql family comm::*socket_af_inet*) + (fli:size-of '(:struct comm::sockaddr_in)) + (fli:size-of '(:struct comm::sockaddr_in6)))))) + :bad-host))) + +(defun open-udp-socket (&key local-address local-port read-timeout + (address-family comm::*socket_af_inet*)) "Open a unconnected UDP socket. For binding on address ANY(*), just not set LOCAL-ADDRESS (NIL), for binding on random free unused port, set LOCAL-PORT to 0." @@ -201,59 +241,55 @@ ;; safe and it will be very fast after the first time. #+win32 (comm::ensure-sockets)
- (let ((socket-fd (comm::socket comm::*socket_af_inet* *socket_sock_dgram* *socket_ip_proto_udp*))) + (let ((socket-fd (comm::socket address-family *socket_sock_dgram* *socket_ip_proto_udp*))) (if socket-fd - (progn - (when read-timeout (set-socket-receive-timeout socket-fd read-timeout)) - (if local-port - (fli:with-dynamic-foreign-objects ((client-addr (:struct comm::sockaddr_in))) - (comm::initialize-sockaddr_in client-addr comm::*socket_af_inet* - local-address local-port "udp") - (if (comm::bind socket-fd - (fli:copy-pointer client-addr :type '(:struct comm::sockaddr)) - (fli:pointer-element-size client-addr)) - ;; success, return socket fd - socket-fd - (progn - (comm::close-socket socket-fd) - (error "cannot bind")))) + (progn + (when read-timeout (set-socket-receive-timeout socket-fd read-timeout)) + (if local-port + (fli:with-dynamic-foreign-objects () + (multiple-value-bind (error local-address-family + client-addr client-addr-length) + (initialize-dynamic-sockaddr local-address local-port "udp") + (if (or error (not (eql address-family local-address-family))) + (progn + (comm::close-socket socket-fd) + (error "cannot resolve hostname ~S, service ~S: ~A" + local-address local-port (or error "address family mismatch"))) + (if (comm::bind socket-fd client-addr client-addr-length) + ;; success, return socket fd + socket-fd + (progn + (comm::close-socket socket-fd) + (error "cannot bind")))))) socket-fd)) (error "cannot create socket"))))
(defun connect-to-udp-server (hostname service - &key local-address local-port read-timeout) + &key local-address local-port read-timeout) "Something like CONNECT-TO-TCP-SERVER" - (let ((socket-fd (open-udp-socket :local-address local-address - :local-port local-port - :read-timeout read-timeout))) - (if socket-fd - (fli:with-dynamic-foreign-objects ((server-addr (:struct comm::sockaddr_in))) - ;; connect to remote address/port - (comm::initialize-sockaddr_in server-addr comm::*socket_af_inet* hostname service "udp") - (if (comm::connect socket-fd - (fli:copy-pointer server-addr :type '(:struct comm::sockaddr)) - (fli:pointer-element-size server-addr)) - ;; success, return socket fd - socket-fd - ;; fail, close socket and return nil - (progn - (comm::close-socket socket-fd) - (error "cannot connect")))) - (error "cannot create socket")))) - -;; Register a special free action for closing datagram usocket when being GCed -(defun usocket-special-free-action (object) - (when (and (typep object 'datagram-usocket) - (%open-p object)) - (socket-close object))) - -(eval-when (:load-toplevel :execute) - (hcl:add-special-free-action 'usocket-special-free-action)) + (fli:with-dynamic-foreign-objects () + (multiple-value-bind (error address-family server-addr server-addr-length) + (initialize-dynamic-sockaddr hostname service "udp") + (when error + (error "cannot resolve hostname ~S, service ~S: ~A" + hostname service error)) + (let ((socket-fd (open-udp-socket :local-address local-address + :local-port local-port + :read-timeout read-timeout + :address-family address-family))) + (if socket-fd + (if (comm::connect socket-fd server-addr server-addr-length) + ;; success, return socket fd + socket-fd + ;; fail, close socket and return nil + (progn + (comm::close-socket socket-fd) + (error "cannot connect"))) + (error "cannot create socket"))))))
(defun socket-connect (host port &key (protocol :stream) (element-type 'base-char) timeout deadline (nodelay t nodelay-specified) - local-host (local-port #+win32 *auto-port* #-win32 nil)) - (declare (ignorable nodelay)) + local-host local-port)
;; What's the meaning of this keyword? (when deadline @@ -264,7 +300,8 @@ (unsupported 'timeout 'socket-connect :minimum "LispWorks 4.4.5"))
#+(or lispworks4 lispworks5.0) ; < 5.1 - (when nodelay-specified + (when (and nodelay-specified + (not (eq nodelay :if-supported))) (unsupported 'nodelay 'socket-connect :minimum "LispWorks 5.1"))
#+lispworks4 #+lispworks4 @@ -390,16 +427,19 @@ "Send message to a socket, using sendto()/send()" (declare (type integer socket-fd) (type sequence buffer)) - (fli:with-dynamic-foreign-objects ((client-addr (:struct comm::sockaddr_in))) - (fli:with-dynamic-lisp-array-pointer (ptr message :type '(:unsigned :byte)) - (replace message buffer :end2 length) - (if (and host service) - (progn - (comm::initialize-sockaddr_in client-addr comm::*socket_af_inet* host service "udp") + (fli:with-dynamic-lisp-array-pointer (ptr message :type '(:unsigned :byte)) + (replace message buffer :end2 length) + (if (and host service) + (fli:with-dynamic-foreign-objects () + (multiple-value-bind (error family client-addr client-addr-length) + (initialize-dynamic-sockaddr host service "udp") + (when error + (error "cannot resolve hostname ~S, service ~S: ~A" + host service error)) (%sendto socket-fd ptr (min length +max-datagram-packet-size+) 0 (fli:copy-pointer client-addr :type '(:struct comm::sockaddr)) - *length-of-sockaddr_in*)) - (comm::%send socket-fd ptr (min length +max-datagram-packet-size+) 0))))) + client-addr-length))) + (comm::%send socket-fd ptr (min length +max-datagram-packet-size+) 0))))
(defmethod socket-send ((socket datagram-usocket) buffer length &key host port) (send-message (socket socket)
Modified: usocket/branches/0.5.x/backend/mcl.lisp ============================================================================== --- usocket/branches/0.5.x/backend/mcl.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/backend/mcl.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -73,6 +73,8 @@
(defun socket-connect (host port &key (element-type 'character) timeout deadline nodelay local-host local-port (protocol :stream)) + (when (eq nodelay :if-supported) + (setf nodelay t)) (when (eq protocol :datagram) (unsupported '(protocol :datagram) 'socket-connect)) (with-mapped-conditions ()
Modified: usocket/branches/0.5.x/backend/openmcl.lisp ============================================================================== --- usocket/branches/0.5.x/backend/openmcl.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/backend/openmcl.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -85,6 +85,8 @@ (defun socket-connect (host port &key (protocol :stream) (element-type 'character) timeout deadline nodelay local-host local-port) + (when (eq nodelay :if-supported) + (setf nodelay t)) (with-mapped-conditions () (ecase protocol (:stream
Modified: usocket/branches/0.5.x/backend/sbcl.lisp ============================================================================== --- usocket/branches/0.5.x/backend/sbcl.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/backend/sbcl.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -261,8 +261,11 @@ ;; package today. There's no guarantee the functions ;; we need are available, but we can make sure not to ;; call them if they aren't + (not (eq nodelay :if-supported)) (not sockopt-tcp-nodelay-p)) (unsupported 'nodelay 'socket-connect)) + (when (eq nodelay :if-supported) + (setf nodelay t))
(let ((socket (make-instance 'sb-bsd-sockets:inet-socket :type protocol
Modified: usocket/branches/0.5.x/backend/scl.lisp ============================================================================== --- usocket/branches/0.5.x/backend/scl.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/backend/scl.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -34,8 +34,9 @@ (local-port nil local-port-p) &aux (patch-udp-p (fboundp 'ext::inet-socket-send-to))) - (declare (ignore nodelay)) - (when nodelay-specified (unsupported 'nodelay 'socket-connect)) + (when (and nodelay-specified + (not (eq nodelay :if-supported))) + (unsupported 'nodelay 'socket-connect)) (when deadline (unsupported 'deadline 'socket-connect)) (when timeout (unsupported 'timeout 'socket-connect)) (when (and local-host-p (not patch-udp-p))
Modified: usocket/branches/0.5.x/usocket.lisp ============================================================================== --- usocket/branches/0.5.x/usocket.lisp Sat Feb 4 09:48:27 2012 (r686) +++ usocket/branches/0.5.x/usocket.lisp Mon Feb 27 06:49:55 2012 (r687) @@ -529,7 +529,7 @@
;; Documentation for the function ;; -;; (defun SOCKET-CONNECT (host port &key element-type) ..) +;; (defun SOCKET-CONNECT (host port &key element-type nodelay some-other-keys...) ..) ;; (setf (documentation 'socket-connect 'function) "Connect to `host' on `port'. `host' is assumed to be a string or @@ -539,6 +539,20 @@ `element-type' specifies the element type to use when constructing the stream associated with the socket. The default is 'character.
+`nodelay' Allows to disable/enable Nagle's algorithm (http://en.wikipedia.org/wiki/Nagle%27s_algorithm). +If this parameter is omitted, the behaviour is inherited from the +CL implementation (in most cases, Nagle's algorithm is +enabled by default, but for example in ACL it is disabled). +If the parmeter is specified, one of these three values is possible: + T - Disable Nagle's algorithm; signals an UNSUPPORTED + condition if the implementation does not support explicit + manipulation with that option. + NIL - Leave Nagle's algorithm enabled on the socket; + signals an UNSUPPORTED condition if the implementation does + not support explicit manipulation with that option. + :IF-SUPPORTED - Disables Nagle's algorithm if the implementation + allows this, otherwises just ignore this option. + Returns a usocket object.")
;; Documentation for the function