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));
 }
 
     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;
 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-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);
     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))
 
 (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")
 
 
 (load-extension "libdolcon-guile" "init_guiledc")
 
       errsym)))
 
 (define-public dc-must-connect
       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)))
          (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]
 
         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
     """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.
     """
     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()
     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]
         raise RuntimeError, resp.intresp()[0][0]
+    if not checkproto(resp, revision):
+        raise RuntimeError, resp
     return fd
 
     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
     """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"
         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)
     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;
 }
 
        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"},
 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"},
      "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}
 };
 
     {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);
     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();
 }
     dc_init();
 }