[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