From hhubner at common-lisp.net Fri Jan 20 22:35:08 2012 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Fri, 20 Jan 2012 14:35:08 -0800 Subject: [usocket-cvs] r679 - in usocket/trunk: . backend Message-ID: Author: hhubner Date: Fri Jan 20 14:35:07 2012 New Revision: 679 Log: :nodelay :if-supported patch from Anton Vodonosov Modified: usocket/trunk/backend/abcl.lisp usocket/trunk/backend/allegro.lisp usocket/trunk/backend/clisp.lisp usocket/trunk/backend/cmucl.lisp usocket/trunk/backend/lispworks.lisp usocket/trunk/backend/mcl.lisp usocket/trunk/backend/openmcl.lisp usocket/trunk/backend/sbcl.lisp usocket/trunk/backend/scl.lisp usocket/trunk/usocket.lisp Modified: usocket/trunk/backend/abcl.lisp ============================================================================== --- usocket/trunk/backend/abcl.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/backend/abcl.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -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/trunk/backend/allegro.lisp ============================================================================== --- usocket/trunk/backend/allegro.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/backend/allegro.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -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/trunk/backend/clisp.lisp ============================================================================== --- usocket/trunk/backend/clisp.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/backend/clisp.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -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/trunk/backend/cmucl.lisp ============================================================================== --- usocket/trunk/backend/cmucl.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/backend/cmucl.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -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/trunk/backend/lispworks.lisp ============================================================================== --- usocket/trunk/backend/lispworks.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/backend/lispworks.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -253,7 +253,6 @@ (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)) ;; What's the meaning of this keyword? (when deadline @@ -264,7 +263,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 Modified: usocket/trunk/backend/mcl.lisp ============================================================================== --- usocket/trunk/backend/mcl.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/backend/mcl.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -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/trunk/backend/openmcl.lisp ============================================================================== --- usocket/trunk/backend/openmcl.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/backend/openmcl.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -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/trunk/backend/sbcl.lisp ============================================================================== --- usocket/trunk/backend/sbcl.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/backend/sbcl.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -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/trunk/backend/scl.lisp ============================================================================== --- usocket/trunk/backend/scl.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/backend/scl.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -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/trunk/usocket.lisp ============================================================================== --- usocket/trunk/usocket.lisp Thu Nov 10 17:40:53 2011 (r678) +++ usocket/trunk/usocket.lisp Fri Jan 20 14:35:07 2012 (r679) @@ -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 form the +CL implementation (in most cases the 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 the Nagle's algorithm; signals an UNSUPPORTED + condition if the implementation does not support explicit + manipulation with that option. + NIL - Leave the 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 the Nagle's algorithm if the implementation + allows this, otherwises just ignore this option. + Returns a usocket object.") ;; Documentation for the function From hhubner at common-lisp.net Fri Jan 20 23:38:01 2012 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Fri, 20 Jan 2012 15:38:01 -0800 Subject: [usocket-cvs] r680 - usocket/trunk Message-ID: Author: hhubner Date: Fri Jan 20 15:38:00 2012 New Revision: 680 Log: Textual corrections for :nodelay :if-supported. Modified: usocket/trunk/usocket.lisp Modified: usocket/trunk/usocket.lisp ============================================================================== --- usocket/trunk/usocket.lisp Fri Jan 20 14:35:07 2012 (r679) +++ usocket/trunk/usocket.lisp Fri Jan 20 15:38:00 2012 (r680) @@ -540,17 +540,17 @@ 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 form the -CL implementation (in most cases the Nagle's algorithm is +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 the Nagle's algorithm; signals an UNSUPPORTED + T - Disable Nagle's algorithm; signals an UNSUPPORTED condition if the implementation does not support explicit manipulation with that option. - NIL - Leave the Nagle's algorithm enabled on the socket; + 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 the Nagle's algorithm if the implementation + :IF-SUPPORTED - Disables Nagle's algorithm if the implementation allows this, otherwises just ignore this option. Returns a usocket object.") From ctian at common-lisp.net Sat Jan 28 20:31:13 2012 From: ctian at common-lisp.net (ctian at common-lisp.net) Date: Sat, 28 Jan 2012 12:31:13 -0800 Subject: [usocket-cvs] r681 - in usocket/trunk: . backend Message-ID: Author: ctian Date: Sat Jan 28 12:31:12 2012 New Revision: 681 Log: [LispWorks] Fixed UDP support for LispWorks 6.1 (patch from Camille Troillard with minor fixes). Modified: usocket/trunk/CHANGES usocket/trunk/backend/lispworks.lisp Modified: usocket/trunk/CHANGES ============================================================================== --- usocket/trunk/CHANGES Fri Jan 20 15:38:00 2012 (r680) +++ usocket/trunk/CHANGES Sat Jan 28 12:31:12 2012 (r681) @@ -1,3 +1,10 @@ +0.6.0: + +* New feature: SOCKET-OPTION for seting and geting various socket options. +* Enhancement: SOCKET-CONNECT argument :nodelay can now set to :if-supported (patch from Anton Vodonosov). +* Bugfix: [LispWorks] Fixed UDP support for LispWorks 6.1 (patch from Camille Troillard). +* Bugfix: [LispWorks] Stop using hcl:add-special-free-action for reclaiming unused UDP socket fds to improve multi-threading stablity (suggested by Camille Troillard). + 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) @@ -51,10 +58,6 @@ * New feature: CLISP support some advanced TCP features which CLISP's SOCKET interface not provide * New feature: Macintosh Common Lisp (MCL) support Datagram sockets (UDP) -0.6.0: - -* New feature: SOCKET-OPTION for seting and geting various socket options. - [TODO for 0.6.x] * New feature: SOCKET-SHUTDOWN for TCP and UDP sockets Modified: usocket/trunk/backend/lispworks.lisp ============================================================================== --- usocket/trunk/backend/lispworks.lisp Fri Jan 20 15:38:00 2012 (r680) +++ usocket/trunk/backend/lispworks.lisp Sat Jan 28 12:31:12 2012 (r681) @@ -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,54 +241,51 @@ ;; 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) @@ -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) From ctian at common-lisp.net Sat Jan 28 20:49:31 2012 From: ctian at common-lisp.net (ctian at common-lisp.net) Date: Sat, 28 Jan 2012 12:49:31 -0800 Subject: [usocket-cvs] r682 - usocket/trunk Message-ID: Author: ctian Date: Sat Jan 28 12:49:31 2012 New Revision: 682 Log: Merge r678 from 0.5.x branch, this new feature is left for 0.6.0 Modified: usocket/trunk/CHANGES usocket/trunk/server.lisp Modified: usocket/trunk/CHANGES ============================================================================== --- usocket/trunk/CHANGES Sat Jan 28 12:31:12 2012 (r681) +++ usocket/trunk/CHANGES Sat Jan 28 12:49:31 2012 (r682) @@ -1,7 +1,8 @@ 0.6.0: * New feature: SOCKET-OPTION for seting and geting various socket options. -* Enhancement: SOCKET-CONNECT argument :nodelay can now set to :if-supported (patch from Anton Vodonosov). +* Enhancement: SOCKET-CONNECT argument :nodelay now support :if-supported as value (patch from Anton Vodonosov). +* Enhancement: Add *remote-host* *remote-port* to SOCKET-SERVER stream handler (suggested by Matthew Curry). * Bugfix: [LispWorks] Fixed UDP support for LispWorks 6.1 (patch from Camille Troillard). * Bugfix: [LispWorks] Stop using hcl:add-special-free-action for reclaiming unused UDP socket fds to improve multi-threading stablity (suggested by Camille Troillard). Modified: usocket/trunk/server.lisp ============================================================================== --- usocket/trunk/server.lisp Sat Jan 28 12:31:12 2012 (r681) +++ usocket/trunk/server.lisp Sat Jan 28 12:49:31 2012 (r682) @@ -80,7 +80,8 @@ &key element-type multi-threading) (let ((real-function #'(lambda (client-socket &rest arguments) (unwind-protect - (apply function (socket-stream client-socket) arguments) + (multiple-value-bind (*remote-host* *remote-port*) (get-peer-name client-socket) + (apply function (socket-stream client-socket) arguments)) (close (socket-stream client-socket)) (socket-close client-socket) nil))))