[usocket-cvs] r119 - in usocket/trunk: . backend doc notes

ehuelsmann at common-lisp.net ehuelsmann at common-lisp.net
Wed Oct 18 06:56:34 UTC 2006


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) ..)



More information about the usocket-cvs mailing list