From 9cbeb60c78389bde5a290e263335cffffbb5ced6 Mon Sep 17 00:00:00 2001 From: fredrik Date: Thu, 12 Apr 2007 01:01:38 +0000 Subject: [PATCH] Support version connect stanza in extension languages. git-svn-id: svn+ssh://svn.dolda2000.com/srv/svn/repos/src/doldaconnect@922 959494ce-11ee-0310-bf91-de5d638817bd --- lib/guile/dolcon-guile.c | 20 ++++++++++++++++++++ lib/guile/dolcon/ui.scm | 22 +++++++++++++--------- lib/python/dolcon/__init__.py | 12 +++++++----- lib/python/dolmod.c | 23 +++++++++++++++++++++++ 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/lib/guile/dolcon-guile.c b/lib/guile/dolcon-guile.c index 3ad21ff..e2de1ce 100644 --- a/lib/guile/dolcon-guile.c +++ b/lib/guile/dolcon-guile.c @@ -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); diff --git a/lib/guile/dolcon/ui.scm b/lib/guile/dolcon/ui.scm index d6b4354..f5a27fb 100644 --- a/lib/guile/dolcon/ui.scm +++ b/lib/guile/dolcon/ui.scm @@ -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") @@ -16,15 +16,19 @@ 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)) ) ) ) diff --git a/lib/python/dolcon/__init__.py b/lib/python/dolcon/__init__.py index 0cb26ba..c1611ac 100644 --- a/lib/python/dolcon/__init__.py +++ b/lib/python/dolcon/__init__.py @@ -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) diff --git a/lib/python/dolmod.c b/lib/python/dolmod.c index eb2c405..71623a6 100644 --- a/lib/python/dolmod.c +++ b/lib/python/dolmod.c @@ -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(); } -- 2.11.0