Support version connect stanza in extension languages.
authorfredrik <fredrik@959494ce-11ee-0310-bf91-de5d638817bd>
Thu, 12 Apr 2007 01:01:38 +0000 (01:01 +0000)
committerfredrik <fredrik@959494ce-11ee-0310-bf91-de5d638817bd>
Thu, 12 Apr 2007 01:01:38 +0000 (01:01 +0000)
git-svn-id: svn+ssh://svn.dolda2000.com/srv/svn/repos/src/doldaconnect@922 959494ce-11ee-0310-bf91-de5d638817bd

lib/guile/dolcon-guile.c
lib/guile/dolcon/ui.scm
lib/python/dolcon/__init__.py
lib/python/dolmod.c

index 3ad21ff..e2de1ce 100644 (file)
@@ -294,6 +294,24 @@ static SCM scm_dc_lexsexpr(SCM sexpr)
     return(scm_reverse(ret));
 }
 
+static SCM scm_dc_checkproto(SCM resp, SCM version)
+{
+    int ver;
+    
+    SCM_ASSERT(SCM_SMOB_PREDICATE(resptype, resp), resp, SCM_ARG1, "dc-checkproto");
+    if(version == SCM_UNDEFINED)
+    {
+       ver = DC_LATEST;
+    } else {
+       SCM_ASSERT(SCM_INUMP(version), version, SCM_ARG2, "dc-checkproto");
+       ver = SCM_INUM(version);
+    }
+    if(dc_checkprotocol(((struct respsmob *)SCM_SMOB_DATA(resp))->resp, ver))
+       return(SCM_BOOL_F);
+    else
+       return(SCM_BOOL_T);
+}
+
 static size_t resp_free(SCM respsmob)
 {
     struct respsmob *data;
@@ -331,6 +349,8 @@ void init_guiledc(void)
     scm_c_define_gsubr("dc-qcmd", 1, 1, 0, scm_dc_qcmd);
     scm_c_define_gsubr("dc-loginasync", 2, 1, 0, scm_dc_loginasync);
     scm_c_define_gsubr("dc-lexsexpr", 1, 0, 0, scm_dc_lexsexpr);
+    scm_c_define_gsubr("dc-checkproto", 1, 1, 0, scm_dc_checkproto);
+    scm_c_define("dc-latest", SCM_MAKINUM(DC_LATEST));
     resptype = scm_make_smob_type("dc-resp", sizeof(struct respsmob));
     scm_set_smob_free(resptype, resp_free);
     scm_set_smob_print(resptype, resp_print);
index d6b4354..f5a27fb 100644 (file)
@@ -1,6 +1,6 @@
 (define-module (dolcon ui))
 
-(export dc-connect dc-disconnect dc-connected dc-select dc-getresp dc-extract dc-intresp dc-qcmd dc-loginasync dc-lexsexpr)
+(export dc-connect dc-disconnect dc-connected dc-select dc-getresp dc-extract dc-intresp dc-qcmd dc-loginasync dc-lexsexpr dc-checkproto)
 
 (load-extension "libdolcon-guile" "init_guiledc")
 
       errsym)))
 
 (define-public dc-must-connect
-  (lambda args
-    (let* ((fd (apply dc-connect args)) (resp (dc-extract (do ((resp (dc-getresp) (dc-getresp)))
-                               ((and resp
-                                     (equal? (cdr (assoc 'cmd (dc-extract resp))) ".connect"))
-                                resp)
-                             (dc-select)))))
-      (if (= (cdr (assoc 'code resp)) 200)
-         fd
+  (lambda (host . version)
+    (let* ((fd (dc-connect host))
+          (ores (do ((resp (dc-getresp) (dc-getresp)))
+                    ((and resp
+                          (equal? (cdr (assoc 'cmd (dc-extract resp))) ".connect"))
+                     resp)
+                  (dc-select)))
+          (resp (dc-extract ores)))
+      (if (not (= (cdr (assoc 'code resp)) 201))
          (throw 'bad-return (cdr (assoc 'code resp)) (cadr (assoc 'resp resp)))
+         (if (dc-checkproto ores (if (pair? version) (car version) dc-latest))
+             fd
+             (throw 'bad-protocol ores))
          )
       )
     )
index 0cb26ba..c1611ac 100644 (file)
@@ -25,7 +25,7 @@ def login(useauthless = True, **kw):
         select()
     return result[0]
 
-def mustconnect(host, port = -1):
+def mustconnect(host, revision = latest):
     """A convenience function for connect.
 
     This function will connect to the given host, perform a select
@@ -33,17 +33,19 @@ def mustconnect(host, port = -1):
     any of these steps fail, an exception is raised. If successful,
     the file descriptor for the server connection is returned.
     """
-    fd = connect(host, port)
+    fd = connect(host)
     while True:
         resp = getresp()
         if resp is not None and resp.getcmd() == u".connect":
             break
         select()
-    if resp.getcode() != 200:
+    if resp.getcode() != 201:
         raise RuntimeError, resp.intresp()[0][0]
+    if not checkproto(resp, revision):
+        raise RuntimeError, resp
     return fd
 
-def cnl(host = None, port = -1, useauthless = True, **kw):
+def cnl(host = None, useauthless = True, revision = latest, **kw):
     """A convenience function for connect and loginasync.
 
     This function will connect to the given server, or the server in
@@ -55,7 +57,7 @@ def cnl(host = None, port = -1, useauthless = True, **kw):
         host = os.getenv("DCSERVER")
     if host is None:
         host = "localhost"
-    fd = mustconnect(host, port)
+    fd = mustconnect(host, revision)
     err, reason = login(useauthless, **kw)
     if err != "success":
         raise RuntimeError, (err, reason)
index eb2c405..71623a6 100644 (file)
@@ -389,6 +389,26 @@ static PyObject *mod_wantwrite(PyObject *self)
        Py_RETURN_FALSE;
 }
 
+static PyObject *mod_checkproto(PyObject *self, PyObject *args)
+{
+    PyObject *tmp;
+    struct respobj *resp;
+    int version;
+    
+    version = DC_LATEST;
+    if(!PyArg_ParseTuple(args, "O|i", &tmp, &version))
+       return(NULL);
+    if(!PyObject_TypeCheck(tmp, &resptype)) {
+       PyErr_SetString(PyExc_TypeError, "first argument must be a response object");
+       return(NULL);
+    }
+    resp = tmp;
+    if(dc_checkprotocol(resp->resp, version))
+       Py_RETURN_FALSE;
+    else
+       Py_RETURN_TRUE;
+}
+
 static PyMethodDef methods[] = {
     {"connect", mod_connect, METH_VARARGS,
      "Connect to a Dolda Connect server"},
@@ -408,6 +428,8 @@ static PyMethodDef methods[] = {
      "Use a standard algorithm to lex a search expression"},
     {"wantwrite", (PyCFunction)mod_wantwrite, METH_NOARGS,
      "Return a boolean indicating whether there is output to be fed to the server"},
+    {"checkproto", (PyCFunction)mod_checkproto, METH_VARARGS,
+     "Check so that the connect stanza returned by the server indicates support for the correct revision of the protocol"},
     {NULL, NULL, 0, NULL}
 };
 
@@ -420,5 +442,6 @@ PyMODINIT_FUNC initdolmod(void)
     m = Py_InitModule("dolmod", methods);
     Py_INCREF(&resptype);
     PyModule_AddObject(m, "Response", (PyObject *)&resptype);
+    PyModule_AddObject(m, "latest", Py_BuildValue("i", DC_LATEST));
     dc_init();
 }