[usocket-devel] Re: [usocket-cvs] r119 - in usocket/trunk: . backend doc notes
Erik Huelsmann
ehuels at gmail.com
Wed Oct 18 06:59:20 UTC 2006
Sorry. That was a bit more than Douglas submitted, I'll revert the
non-related part when I get back from work.
bye,
Erik.
On 10/18/06, ehuelsmann at common-lisp.net <ehuelsmann at common-lisp.net> wrote:
> Author: ehuelsmann
> Date: Wed Oct 18 02:56:33 2006
> New Revision: 119
>
> Added:
> usocket/trunk/backend/scl.lisp
> usocket/trunk/notes/accept-apis.txt
> Modified:
> usocket/trunk/condition.lisp
> usocket/trunk/doc/design.txt
> usocket/trunk/usocket.asd
> usocket/trunk/usocket.lisp
> Log:
> Add Scieneer support.
>
> Donated by Douglas Crosher <dtc at scieneer dot com>.
>
>
> Added: usocket/trunk/backend/scl.lisp
> ==============================================================================
> --- (empty file)
> +++ usocket/trunk/backend/scl.lisp Wed Oct 18 02:56:33 2006
> @@ -0,0 +1,101 @@
> +;;;; $Id: scl.lisp$
> +;;;; $URL: svn://common-lisp.net/project/usocket/svn/usocket/trunk/backend/scl.lisp $
> +
> +;;;; See LICENSE for licensing information.
> +
> +(in-package :usocket)
> +
> +(defparameter +scl-error-map+
> + (append +unix-errno-condition-map+
> + +unix-errno-error-map+))
> +
> +(defun scl-map-socket-error (err &key condition socket)
> + (let ((usock-err (cdr (assoc err +scl-error-map+ :test #'member))))
> + (cond (usock-err
> + (if (subtypep usock-err 'error)
> + (error usock-err :socket socket)
> + (signal usock-err :socket socket)))
> + (t
> + (error 'unknown-error
> + :socket socket
> + :real-error condition)))))
> +
> +(defun handle-condition (condition &optional (socket nil))
> + "Dispatch correct usocket condition."
> + (etypecase condition
> + (ext::socket-error
> + (format t "erron: ~D~%" (ext::socket-errno condition))
> + (scl-map-socket-error (ext::socket-errno condition)
> + :socket socket
> + :condition condition))
> + (error
> + (error 'unknown-error
> + :real-condition condition
> + :socket socket))))
> +
> +(defun socket-connect (host port)
> + (let* ((socket
> + (with-mapped-conditions (nil)
> + (ext:connect-to-inet-socket (host-to-hbo host) port :kind :stream)))
> + (stream (sys:make-fd-stream socket :input t :output t
> + :element-type 'character
> + :buffering :full)))
> + ;;###FIXME the above line probably needs an :external-format
> + (make-socket :socket socket :stream stream)))
> +
> +(defmethod socket-close ((usocket usocket))
> + "Close socket."
> + (with-mapped-conditions (usocket)
> + (ext:close-socket (socket usocket))))
> +
> +(defmethod get-local-name ((usocket usocket))
> + (multiple-value-bind (address port)
> + (with-mapped-conditions (usocket)
> + (ext:get-socket-host-and-port (socket usocket)))
> + (values (hbo-to-vector-quad address) port)))
> +
> +(defmethod get-peer-name ((usocket usocket))
> + (multiple-value-bind (address port)
> + (with-mapped-conditions (usocket)
> + (ext:get-peer-host-and-port (socket usocket)))
> + (values (hbo-to-vector-quad address) port)))
> +
> +(defmethod get-local-address ((usocket usocket))
> + (nth-value 0 (get-local-name usocket)))
> +
> +(defmethod get-peer-address ((usocket usocket))
> + (nth-value 0 (get-peer-name usocket)))
> +
> +(defmethod get-local-port ((usocket usocket))
> + (nth-value 1 (get-local-name usocket)))
> +
> +(defmethod get-peer-port ((usocket usocket))
> + (nth-value 1 (get-peer-name usocket)))
> +
> +
> +(defun get-host-by-address (address)
> + (multiple-value-bind (host errno)
> + (ext:lookup-host-entry (host-byte-order address))
> + (cond (host
> + (ext:host-entry-name host))
> + (t
> + (let ((condition (cdr (assoc errno +unix-ns-error-map+))))
> + (cond (condition
> + (error condition :host-or-ip address))
> + (t
> + (error 'ns-unknown-error :host-or-ip address
> + :real-error errno))))))))
> +
> +(defun get-hosts-by-name (name)
> + (multiple-value-bind (host errno)
> + (ext:lookup-host-entry name)
> + (cond (host
> + (mapcar #'hbo-to-vector-quad
> + (ext:host-entry-addr-list host)))
> + (t
> + (let ((condition (cdr (assoc errno +unix-ns-error-map+))))
> + (cond (condition
> + (error condition :host-or-ip name))
> + (t
> + (error 'ns-unknown-error :host-or-ip name
> + :real-error errno))))))))
>
> Modified: usocket/trunk/condition.lisp
> ==============================================================================
> --- usocket/trunk/condition.lisp (original)
> +++ usocket/trunk/condition.lisp Wed Oct 18 02:56:33 2006
> @@ -102,8 +102,8 @@
> ;; isn't really an error: there's just no data to return.
> ;; with lisp, we just return NIL (indicating no data) instead of
> ;; raising an exception...
> - (ns-host-not-found
> - ns-no-recovery)
> + (ns-host-not-found-error
> + ns-no-recovery-error)
> (ns-error))
>
> (define-condition ns-unknown-error (ns-error)
>
> Modified: usocket/trunk/doc/design.txt
> ==============================================================================
> --- usocket/trunk/doc/design.txt (original)
> +++ usocket/trunk/doc/design.txt Wed Oct 18 02:56:33 2006
> @@ -13,7 +13,7 @@
> * Motivation
> * Design goal
> * Functional requirements
> -
> + * Comments on the functional requirements
>
>
>
> @@ -83,6 +83,33 @@
> - OpenMCL
>
>
> +The lifetime of a socket can be described with these steps:
> +
> + 1. Socket creation (socket() function)
> + 2. Socket initializaiton (setsockopt(), bind() and listen()/connect() funcs)
> + 3. Socket use (accept() / recv[from], send[to])
> + 4. Socket termination (shutdown())
> + 5. Socket destruction (close())
> +
> +While for most applications steps 1-3 can be condensed into 1 (which most
> +implementations do), if the library wants to be extensible into other
> +domains than IP, a means should be provided to do socket initialization
> +without knowing what parameters to accept beforehand: other protocols
> +require parameters for setsockopt we will not know about in advance.
> +
> +There are several possibilities to address this issue:
> +
> + a. Force the 3 steps apart [hard to get done with the current status
> + for some implementations, as they are currently integrated in the
> + public interface].
> + b. Find a mechanism to pass options which we want setsockopt to
> + be called with. Problem: what to do with implementations which
> + don't support setting of all options *before* the bind() call?
> + Does it matter that some options may be set after the bind()
> + call? What if they're not set before connect() [buffer size changes
> + have to be set before connect()]?
> + c. ... ?
> +
> Comments on the design above
> ============================
>
>
> Added: usocket/trunk/notes/accept-apis.txt
> ==============================================================================
> --- (empty file)
> +++ usocket/trunk/notes/accept-apis.txt Wed Oct 18 02:56:33 2006
> @@ -0,0 +1,173 @@
> +
> + -*- text -*-
> +
> +Part of 'Step 3': Server/passive tcp socket interfaces supplied by
> +the different implementations in order to provide the same externally.
> +
> +
> +ABCL
> +====
> +
> + - ext:make-server-socket port
> + - ext:socket-accept socket
> + - ext:socket-close socket
> +
> +Allegro
> +=======
> +
> + - socket:make-socket :type :stream :connect :passive
> + :local-port <port> :reuse-address t :backlog <nr>
> + :local-host <host-ip>
> + - socket:accept-connection sock &key wait
> + - close
> +
> +
> +clisp
> +=====
> +
> + - socket:socket-server &optional port &key interface backlog
> + - socket:socket-server-close sock
> + - socket:socket-server-host sock
> + - socket:socket-server-port sock
> + - socket:socket-accept sock &key element-type external-format buffered timeout
> + - socket:socket-options sock &rest options
> +
> +... and ofcourse, there's the raw-sockets
> +
> +CMUCL
> +=====
> +
> + - ext:create-inet-listener port &optional kind
> + &key reuseaddress backlog interface
> + - ext:accept-tcp-connection socket
> +
> +
> +LispWorks
> +=========
> +
> + - comm::get-fd-from-socket (socket-os-fd lispworks-socket)
> + - comm::create-tcp-socket-for-service port
> + (may use comm::*use_so_reuseaddr* for that socket option)
> + misses the ability to specify an interface to bind to.
> + - comm::socket-close
> +
> +
> +OpenMCL
> +=======
> +
> + - openmcl-socket:accept-connection
> + - openmcl-socket:make-socket :local-host <if> :local-port port
> + :reuse-address t :type :stream :connect :passive
> + :backlog <nr>
> + - close
> +
> +
> +SBCL
> +====
> +
> + - make-instance 'inet-socket
> + - sb-bsd-sockets:sockopt-*
> + - sb-bsd-sockets:socket-bind
> + - sb-bsd-sockets:socket-listen
> + - sb-bsd-sockets:socket-accept
> +
> +
> +;;
> +;;
> +;; The above APIs are good enough to implement a simple
> +;; accept interface, but doesn't give access to specifying
> +;; socket options before the socket is bound to the interface
> +;; ==> This may only actually be required for SO_REUSEADDRESS?!???
> +;;
> +;; The other option would be to use lots of FFI - where needed -
> +;; and use the (mostly internal) glue routines from the implementations
> +
> +
> +ABCL
> +====
> +
> + With ABCL - lacking a good sockets API - it's still possible to implement
> + whatever we need to get good access...
> +
> +
> +Allegro
> +=======
> +
> + Hmm. The accept function in this implementation does not allow limiting
> + connections to a given host/ip, but it does allow to create sockets
> + with mostly the right options.
> +
> + Is that enough reason to do this entirely in ffi?!
> +
> + Also, doing this in FFI would require to reverse engineer the creation
> + of socket streams. Maybe Franz tech support could help there though.
> +
> + Need to investigate the IPC_* symbols an the sockets package:
> + there are lots of functions which look like they should be useable.
> +
> +
> +clisp
> +=====
> +
> + This implementation allows access to the full sockets as described
> + in http://clisp.cons.org/impnotes/rawsock.html.
> +
> +
> +CMUCL
> +=====
> +
> + Provides (in unix package):
> +
> + - unix-accept
> + - unix-bind
> + - unix-listen
> + - unix-socket
> +
> + Provides (in extentions):
> +
> + - inet-sockaddr
> + - get-socket-option
> + - set-socket-option
> + - create-inet-listener port &key host reuse-address backlog
> +
> +
> +LispWorks
> +=========
> +
> + The implementation provides a lot of undocumented functions the library
> + could tap into:
> +
> + - comm::socket
> + - comm::bind
> + - comm::accept
> + - comm::getsockopt
> + - comm::setsockopt
> + - comm::initialize-sockaddr_in (helper)
> + - comm::streams-from-fd (helper)
> +
> +
> +OpenMCL
> +=======
> +
> + - make-socket provides all options which we'll need to set,
> + it doesn't however provide access to [gs]etsockopt...
> +
> +
> +SBCL
> +====
> +
> + provides (in sb-bsd-sockets):
> + socket-bind
> + socket-accept
> + sokcet-listen
> +
> + provides (in sb-bsd-sockets-internal [sockint]):
> + getsockopt
> + setsockopt
> +
> + SO-* constants
> + TCP-* constant(s)
> + AF-* constants (and, since AF-* == IF-*, we don't need others)
> +
> +
> +
>
> Modified: usocket/trunk/usocket.asd
> ==============================================================================
> --- usocket/trunk/usocket.asd (original)
> +++ usocket/trunk/usocket.asd Wed Oct 18 02:56:33 2006
> @@ -28,6 +28,8 @@
> :depends-on ("condition"))
> #+cmu (:file "cmucl" :pathname "backend/cmucl"
> :depends-on ("condition"))
> + #+scl (:file "scl" :pathname "backend/scl"
> + :depends-on ("condition"))
> #+sbcl (:file "sbcl" :pathname "backend/sbcl"
> :depends-on ("condition"))
> #+lispworks (:file "lispworks" :pathname "backend/lispworks"
>
> Modified: usocket/trunk/usocket.lisp
> ==============================================================================
> --- usocket/trunk/usocket.lisp (original)
> +++ usocket/trunk/usocket.lisp Wed Oct 18 02:56:33 2006
> @@ -164,8 +164,8 @@
> (string (let ((ip (ignore-errors
> (dotted-quad-to-vector-quad host))))
> (if (and ip (= 4 (length ip)))
> - ip
> - (host-to-hbo (get-host-by-name host)))))
> + (host-byte-order ip)
> + (host-to-hbo (get-host-by-name host)))))
> ((vector t 4) (host-byte-order host))
> (integer host))))
>
> @@ -186,9 +186,19 @@
> ;;
>
> (setf (documentation 'socket-connect 'function)
> - "Connect to `host' on `port'. `host' is assumed to be a string of
> + "Connect to `host' on `port'. `host' is assumed to be a string or
> an IP address represented in vector notation, such as #(192 168 1 1).
> `port' is assumed to be an integer.
>
> Returns a usocket object.")
>
> +;; Documentation for the function
> +;;
> +;; (defun SOCKET-LISTEN (host port &key local-ip local-port
> +;; reuseaddress backlog) ..)
> +
> +
> +;; Documentation for the function
> +;;
> +;; (defun SOCKET-ACCEPT (socket &key element-type external-format
> +;; buffered timeout) ..)
> _______________________________________________
> usocket-cvs mailing list
> usocket-cvs at common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/usocket-cvs
>
More information about the usocket-devel
mailing list