[usocket-cvs] r617 - usocket/branches/0.5.x/backend
Chun Tian (binghe)
ctian at common-lisp.net
Wed Mar 30 18:25:06 UTC 2011
Author: ctian
Date: Wed Mar 30 14:25:06 2011
New Revision: 617
Log:
[CLISP] SOCKET-CONNECT / UDP now works on both RAWSOCK and FFI.
Modified:
usocket/branches/0.5.x/backend/clisp.lisp
Modified: usocket/branches/0.5.x/backend/clisp.lisp
==============================================================================
--- usocket/branches/0.5.x/backend/clisp.lisp (original)
+++ usocket/branches/0.5.x/backend/clisp.lisp Wed Mar 30 14:25:06 2011
@@ -97,13 +97,11 @@
(make-stream-socket :socket socket
:stream socket))) ;; the socket is a stream too
(:datagram
- #+rawsock
+ #+(or rawsock ffi)
(socket-create-datagram (or local-port *auto-port*)
:local-host (or local-host *wildcard-host*)
:remote-host host
:remote-port port)
- #+(and ffi (not rawsock))
- ()
#-(or rawsock ffi)
(unsupported '(protocol :datagram) 'socket-connect))))
@@ -342,6 +340,34 @@
#+win32 :stdc-stdcall)
(:return-type ffi:int))
+ (ffi:def-call-out %connect (:name "connect")
+ (:arguments (socket ffi:int)
+ (address (ffi:c-ptr sockaddr) :in)
+ (address_len socklen_t))
+ #+win32 (:library "WS2_32")
+ #-win32 (:library :default)
+ (:language #-win32 :stdc
+ #+win32 :stdc-stdcall)
+ (:return-type ffi:int))
+
+ (ffi:def-call-out %bind (:name "bind")
+ (:arguments (socket ffi:int)
+ (address (ffi:c-ptr sockaddr) :in)
+ (address_len socklen_t))
+ #+win32 (:library "WS2_32")
+ #-win32 (:library :default)
+ (:language #-win32 :stdc
+ #+win32 :stdc-stdcall)
+ (:return-type ffi:int))
+
+ (ffi:def-call-out %close (:name #-win32 "close" #+win32 "closesocket")
+ (:arguments (socket ffi:int))
+ #+win32 (:library "WS2_32")
+ #-win32 (:library :default)
+ (:language #-win32 :stdc
+ #+win32 :stdc-stdcall)
+ (:return-type ffi:int))
+
(ffi:def-call-out %getsockopt (:name "getsockopt")
(:arguments (sockfd ffi:int)
(level ffi:int)
@@ -366,18 +392,80 @@
#+win32 :stdc-stdcall)
(:return-type ffi:int))
+ (ffi:def-call-out %htonl (:name "htonl")
+ (:arguments (hostlong ffi:uint32))
+ #+win32 (:library "WS2_32")
+ #-win32 (:library :default)
+ (:language #-win32 :stdc
+ #+win32 :stdc-stdcall)
+ (:return-type ffi:uint32))
+
+ (ffi:def-call-out %htons (:name "htons")
+ (:arguments (hostshort ffi:uint16))
+ #+win32 (:library "WS2_32")
+ #-win32 (:library :default)
+ (:language #-win32 :stdc
+ #+win32 :stdc-stdcall)
+ (:return-type ffi:uint16))
+
+ (ffi:def-call-out %ntohl (:name "ntohl")
+ (:arguments (netlong ffi:uint32))
+ #+win32 (:library "WS2_32")
+ #-win32 (:library :default)
+ (:language #-win32 :stdc
+ #+win32 :stdc-stdcall)
+ (:return-type ffi:uint32))
+
+ (ffi:def-call-out %ntohs (:name "ntohs")
+ (:arguments (netshort ffi:uint16))
+ #+win32 (:library "WS2_32")
+ #-win32 (:library :default)
+ (:language #-win32 :stdc
+ #+win32 :stdc-stdcall)
+ (:return-type ffi:uint16))
+
;; socket constants
(defconstant +socket-af-inet+ 2)
- (defconstant +socket-pf-unspec+ 0)
(defconstant +socket-sock-dgram+ 2)
(defconstant +sockopt-so-rcvtimeo+ #-linux #x1006 #+linux 20 "Socket receive timeout")
- (defun open-udp-socket (&key local-address local-port read-timeout)
- "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."
- (let ((socket-fd (%socket +socket-af-inet+ +socket-sock-dgram+ +socket-pf-unspec+)))
- (if socket-fd
- (progn
- )
- (error "cannot create socket"))))
+ (defvar *length-of-sockaddr_in* (ffi:sizeof 'sockaddr_in))
+
+ (declaim (inline fill-sockaddr_in))
+ (defun fill-sockaddr_in (sockaddr host port)
+ (let ((hbo (host-to-hbo #(127 0 0 1))))
+ (setf (ffi:slot (ffi:foreign-value sockaddr) 'sin_len) *length-of-sockaddr_in*
+ (ffi:slot (ffi:foreign-value sockaddr) 'sin_family) +socket-af-inet+
+ (ffi:slot (ffi:foreign-value sockaddr) 'sin_port) (%htons port)
+ (ffi:slot (ffi:foreign-value sockaddr) 'sin_addr) (%htonl hbo))
+ sockaddr))
+
+ (defun socket-create-datagram (local-port
+ &key (local-host *wildcard-host*)
+ remote-host
+ remote-port)
+ (let ((sock (%socket +socket-af-inet+ +socket-sock-dgram+ 0))
+ (lsock_addr (fill-sockaddr_in (ffi:allocate-shallow 'sockaddr_in)
+ local-host local-port))
+ (rsock_addr (when remote-host
+ (fill-sockaddr_in (ffi:allocate-shallow 'sockaddr_in)
+ remote-host (or remote-port local-port)))))
+ (unwind-protect
+ (progn
+ (%bind sock (ffi:cast (ffi:foreign-value lsock_addr) 'sockaddr)
+ *length-of-sockaddr_in*)
+ (when rsock_addr
+ (%connect sock
+ (ffi:cast (ffi:foreign-value rsock_addr) 'sockaddr)
+ *length-of-sockaddr_in*)))
+ (ffi:foreign-free lsock_addr)
+ (when remote-host
+ (ffi:foreign-free rsock_addr)))
+ (make-datagram-socket sock :connected-p (if rsock_addr t nil))))
+
+ (defmethod socket-close ((usocket datagram-usocket))
+ (when (wait-list usocket)
+ (remove-waiter (wait-list usocket) usocket))
+ (zerop (%close (socket usocket))))
+
) ; progn
More information about the usocket-cvs
mailing list