Author: ctian Date: Sat Feb 4 07:56:00 2012 New Revision: 685
Log: [UDP] SOCKET-SEND now support an CCL-like OFFSET keyword for sending only parts of the whole buffer.
Modified: usocket/trunk/CHANGES 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/openmcl.lisp usocket/trunk/backend/sbcl.lisp usocket/trunk/backend/scl.lisp
Modified: usocket/trunk/CHANGES ============================================================================== --- usocket/trunk/CHANGES Sat Feb 4 02:35:44 2012 (r684) +++ usocket/trunk/CHANGES Sat Feb 4 07:56:00 2012 (r685) @@ -1,6 +1,7 @@ 0.6.0:
* New feature: SOCKET-OPTION and (setf SOCKET-OPTION) for seting and geting various socket options. +* New feature: [UDP] SOCKET-SEND now support an CCL-like OFFSET keyword for sending only parts of the whole buffer. * (on the way) New feature: SOCKET-SHUTDOWN for TCP and UDP sockets. * 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).
Modified: usocket/trunk/backend/abcl.lisp ============================================================================== --- usocket/trunk/backend/abcl.lisp Sat Feb 4 02:35:44 2012 (r684) +++ usocket/trunk/backend/abcl.lisp Sat Feb 4 07:56:00 2012 (r685) @@ -335,19 +335,17 @@ (code-char ub8) ub8)))
-(defmethod socket-send ((usocket datagram-usocket) buffer length &key host port) +(defmethod socket-send ((usocket datagram-usocket) buffer size &key host port (offset 0)) (let* ((socket (socket usocket)) - (real-length (or length (length buffer))) - (byte-array (jnew-array $*byte real-length)) + (byte-array (jnew-array $*byte size)) (packet (if (and host port) - (jnew $%DatagramPacket/5 byte-array 0 real-length (host-to-inet4 host) port) - (jnew $%DatagramPacket/3 byte-array 0 real-length)))) + (jnew $%DatagramPacket/5 byte-array 0 size (host-to-inet4 host) port) + (jnew $%DatagramPacket/3 byte-array 0 size)))) ;; prepare sending data - (loop for i from 0 below real-length + (loop for i from offset below (+ size offset) do (setf (jarray-ref byte-array i) (*->byte (aref buffer i)))) (with-mapped-conditions (usocket) - (jcall $@send/1 socket packet)) - real-length)) + (jcall $@send/1 socket packet))))
;;; TODO: return-host and return-port cannot be get ... (defmethod socket-receive ((usocket datagram-usocket) buffer length
Modified: usocket/trunk/backend/allegro.lisp ============================================================================== --- usocket/trunk/backend/allegro.lisp Sat Feb 4 02:35:44 2012 (r684) +++ usocket/trunk/backend/allegro.lisp Sat Feb 4 07:56:00 2012 (r685) @@ -151,10 +151,16 @@ (values (get-peer-address usocket) (get-peer-port usocket)))
-(defmethod socket-send ((socket datagram-usocket) buffer length &key host port) +(defmethod socket-send ((socket datagram-usocket) buffer size &key host port (offset 0)) (with-mapped-conditions (socket) (let ((s (socket socket))) - (socket:send-to s buffer length :remote-host host :remote-port port)))) + (socket:send-to s + (if (zerop offset) + buffer + (subseq buffer offset (+ offset size))) + size + :remote-host host + :remote-port port))))
(defmethod socket-receive ((socket datagram-usocket) buffer length &key) (declare (values (simple-array (unsigned-byte 8) (*)) ; buffer
Modified: usocket/trunk/backend/clisp.lisp ============================================================================== --- usocket/trunk/backend/clisp.lisp Sat Feb 4 02:35:44 2012 (r684) +++ usocket/trunk/backend/clisp.lisp Sat Feb 4 07:56:00 2012 (r685) @@ -93,10 +93,12 @@ "Dispatch correct usocket condition." (let (error-keyword error-string) (typecase condition + #+ffi ; because OS:ERRNO and OS:STRERROR is only present if FFI is present. (system::simple-os-error (let ((errno (car (simple-condition-format-arguments condition)))) (setq error-keyword (os:errno errno) error-string (os:strerror errno)))) + #+ffi ; because OS:ERRNO and OS:STRERROR is only present if FFI is present. (simple-error (let ((keyword (car (simple-condition-format-arguments condition)))) @@ -302,7 +304,7 @@ host port))))
- (defmethod socket-send ((socket datagram-usocket) buffer length &key host port) + (defmethod socket-send ((socket datagram-usocket) buffer size &key host port (offset 0)) "Returns the number of octets sent." (let* ((sock (socket socket)) (sockaddr (when (and host port) @@ -311,19 +313,19 @@ (make-sockaddr_in) (host-byte-order host) port)))) - (real-length (or length (length buffer))) + (real-size (min size +max-datagram-packet-size+)) (real-buffer (if (typep buffer '(simple-array (unsigned-byte 8) (*))) buffer - (make-array real-length + (make-array real-size :element-type '(unsigned-byte 8) - :initial-contents (subseq buffer 0 real-length)))) + :initial-contents (subseq buffer 0 real-size)))) (rv (if (and host port) (rawsock:sendto sock real-buffer sockaddr - :start 0 - :end real-length) + :start offset + :end (+ offset real-size)) (rawsock:send sock real-buffer - :start 0 - :end real-length)))) + :start offset + :end (+ offset real-size))))) rv))
(defmethod socket-close ((usocket datagram-usocket)) @@ -631,30 +633,31 @@ ;; in LispWorks. So, we allocate new foreign buffer for holding data (unknown sequence subtype) every time. ;; ;; I don't know if anyone is watching my coding work, but I think this design is reasonable for CLISP. - (defmethod socket-send ((usocket datagram-usocket) buffer length &key host port) + (defmethod socket-send ((usocket datagram-usocket) buffer size &key host port (offset 0)) (declare (type sequence buffer) - (type integer length)) - (let ((remote-address (when (and host port) - (fill-sockaddr_in (ffi:allocate-shallow 'sockaddr_in) host port))) - (send-buffer (let ((buffer-length (length buffer))) - (if (> buffer-length (* length 2)) - ;; if buffer is too big, then we copy out a subseq and only allocate as need - (ffi:allocate-deep 'ffi:uint8 (subseq buffer 0 length) :count length :read-only t) - ;; then we allocate the whole buffer directly, that should be faster. - (ffi:allocate-deep 'ffi:uint8 buffer :count (length buffer) :read-only t)))) - (real-length (min length +max-datagram-packet-size+)) + (type (integer 0 *) size offset)) + (let ((remote-address + (when (and host port) + (fill-sockaddr_in (ffi:allocate-shallow 'sockaddr_in) host port))) + (send-buffer + (ffi:allocate-deep 'ffi:uint8 + (if (zerop offset) + buffer + (subseq buffer offset (+ offset size))) + :count size :read-only t)) + (real-size (min size +max-datagram-packet-size+)) (nbytes 0)) (unwind-protect (let ((n (if remote-address (%sendto (socket usocket) (ffi:foreign-address send-buffer) - real-length + real-size 0 ; flags (ffi:cast (ffi:foreign-value remote-address) 'sockaddr) *length-of-sockaddr_in*) (%send (socket usocket) (ffi:foreign-address send-buffer) - real-length + real-size 0)))) (cond ((plusp n) (setq nbytes n))
Modified: usocket/trunk/backend/cmucl.lisp ============================================================================== --- usocket/trunk/backend/cmucl.lisp Sat Feb 4 02:35:44 2012 (r684) +++ usocket/trunk/backend/cmucl.lisp Sat Feb 4 07:56:00 2012 (r685) @@ -174,14 +174,17 @@ length flags))
-(defmethod socket-send ((usocket datagram-usocket) buffer length &key host port) +(defmethod socket-send ((usocket datagram-usocket) buffer size &key host port (offset 0) + &aux (real-buffer (if (zerop offset) + buffer + (subseq buffer offset (+ offset size))))) (with-mapped-conditions (usocket) (if (and host port) - (ext:inet-sendto (socket usocket) buffer length (host-to-hbo host) port) + (ext:inet-sendto (socket usocket) real-buffer size (host-to-hbo host) port) #-unicode - (unix:unix-send (socket usocket) buffer length 0) + (unix:unix-send (socket usocket) real-buffer size 0) #+unicode - (%unix-send (socket usocket) buffer length 0)))) + (%unix-send (socket usocket) real-buffer size 0))))
(defmethod socket-receive ((usocket datagram-usocket) buffer length &key) (declare (values (simple-array (unsigned-byte 8) (*)) ; buffer
Modified: usocket/trunk/backend/lispworks.lisp ============================================================================== --- usocket/trunk/backend/lispworks.lisp Sat Feb 4 02:35:44 2012 (r684) +++ usocket/trunk/backend/lispworks.lisp Sat Feb 4 07:56:00 2012 (r685) @@ -423,28 +423,27 @@ (defvar *length-of-sockaddr_in* (fli:size-of '(:struct comm::sockaddr_in)))
-(defun send-message (socket-fd message buffer &optional (length (length buffer)) host service) +(defmethod socket-send ((usocket datagram-usocket) buffer size &key host port (offset 0) + &aux (socket-fd (socket usocket)) + (message (slot-value usocket 'send-buffer))) "Send message to a socket, using sendto()/send()" (declare (type integer socket-fd) (type sequence buffer)) + (when host (setq host (host-to-hbo host))) (fli:with-dynamic-lisp-array-pointer (ptr message :type '(:unsigned :byte)) - (replace message buffer :end2 length) - (if (and host service) + (replace message buffer :start2 offset :end2 (+ offset size)) + (if (and host port) (fli:with-dynamic-foreign-objects () (multiple-value-bind (error family client-addr client-addr-length) - (initialize-dynamic-sockaddr host service "udp") + (initialize-dynamic-sockaddr host port "udp") + (declare (ignore family)) (when error - (error "cannot resolve hostname ~S, service ~S: ~A" - host service error)) - (%sendto socket-fd ptr (min length +max-datagram-packet-size+) 0 + (error "cannot resolve hostname ~S, port ~S: ~A" + host port error)) + (%sendto socket-fd ptr (min size +max-datagram-packet-size+) 0 (fli:copy-pointer client-addr :type '(:struct comm::sockaddr)) 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) - (slot-value socket 'send-buffer) - buffer length (and host (host-to-hbo host)) port)) + (comm::%send socket-fd ptr (min size +max-datagram-packet-size+) 0))))
(defun receive-message (socket-fd message &optional buffer (length (length buffer)) &key read-timeout (max-buffer-size +max-datagram-packet-size+))
Modified: usocket/trunk/backend/openmcl.lisp ============================================================================== --- usocket/trunk/backend/openmcl.lisp Sat Feb 4 02:35:44 2012 (r684) +++ usocket/trunk/backend/openmcl.lisp Sat Feb 4 07:56:00 2012 (r685) @@ -149,24 +149,25 @@ (with-mapped-conditions (usocket) (close (socket usocket))))
-(defmethod socket-send ((usocket datagram-usocket) buffer length &key host port offset) +(defmethod socket-send ((usocket datagram-usocket) buffer size &key host port (offset 0)) (with-mapped-conditions (usocket) (if (and host port) - (openmcl-socket:send-to (socket usocket) buffer length + (openmcl-socket:send-to (socket usocket) buffer size :remote-host (host-to-hbo host) - :remote-port port) + :remote-port port + :offset offset) ;; Clozure CL's socket function SEND-TO doesn't support operations on connected UDP sockets, ;; so we have to define our own. (let* ((socket (socket usocket)) (fd (ccl::socket-device socket))) (multiple-value-setq (buffer offset) - (ccl::verify-socket-buffer buffer offset length)) - (ccl::%stack-block ((bufptr length)) - (ccl::%copy-ivector-to-ptr buffer offset bufptr 0 length) + (ccl::verify-socket-buffer buffer offset size)) + (ccl::%stack-block ((bufptr size)) + (ccl::%copy-ivector-to-ptr buffer offset bufptr 0 size) (ccl::socket-call socket "send" (ccl::with-eagain fd :output (ccl::ignoring-eintr - (ccl::check-socket-error (#_send fd bufptr length 0)))))))))) + (ccl::check-socket-error (#_send fd bufptr size 0))))))))))
(defmethod socket-receive ((usocket datagram-usocket) buffer length &key) (with-mapped-conditions (usocket)
Modified: usocket/trunk/backend/sbcl.lisp ============================================================================== --- usocket/trunk/backend/sbcl.lisp Sat Feb 4 02:35:44 2012 (r684) +++ usocket/trunk/backend/sbcl.lisp Sat Feb 4 07:56:00 2012 (r685) @@ -398,11 +398,14 @@ (with-mapped-conditions (usocket) (close (socket-stream usocket))))
-(defmethod socket-send ((socket datagram-usocket) buffer length &key host port) +(defmethod socket-send ((usocket datagram-usocket) buffer size &key host port (offset 0)) (with-mapped-conditions (socket) - (let* ((s (socket socket)) - (dest (if (and host port) (list (host-to-vector-quad host) port) nil))) - (sb-bsd-sockets:socket-send s buffer length :address dest)))) + (let* ((s (socket usocket)) + (dest (if (and host port) (list (host-to-vector-quad host) port) nil)) + (real-buffer (if (zerop offset) + buffer + (subseq buffer offset (+ offset size))))) + (sb-bsd-sockets:socket-send s real-buffer size :address dest))))
(defmethod socket-receive ((socket datagram-usocket) buffer length &key (element-type '(unsigned-byte 8)))
Modified: usocket/trunk/backend/scl.lisp ============================================================================== --- usocket/trunk/backend/scl.lisp Sat Feb 4 02:35:44 2012 (r684) +++ usocket/trunk/backend/scl.lisp Sat Feb 4 07:56:00 2012 (r685) @@ -136,14 +136,17 @@ (defmethod socket-close :after ((socket datagram-usocket)) (setf (%open-p socket) nil))
-(defmethod socket-send ((socket datagram-usocket) buffer length &key host port) - (let ((s (socket socket)) - (host (if host (host-to-hbo host)))) +(defmethod socket-send ((usocket datagram-usocket) buffer size &key host port) + (let ((s (socket usocket)) + (host (if host (host-to-hbo host))) + (real-buffer (if (zerop offset) + buffer + (subseq buffer offset (+ offset size))))) (multiple-value-bind (result errno) - (ext:inet-socket-send-to s buffer length + (ext:inet-socket-send-to s real-buffer size :remote-host host :remote-port port) (or result - (scl-map-socket-error errno :socket socket))))) + (scl-map-socket-error errno :socket usocket)))))
(defmethod socket-receive ((socket datagram-usocket) buffer length &key) (declare (values (simple-array (unsigned-byte 8) (*)) ; buffer