[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Tue Mar 28 11:20:03 UTC 2017


The branch, master has been updated
       via  0837d0b python: Provide Python bindings for messaging.idl
       via  a3c9ad5 messaging: Declare well known server name auth_events as AUTH_EVENT_NAME in IDL
       via  6e87aa3 messaging.idl: Register a message type for authentication log messages
       via  16e9448 pymessaging: add single element tupple form of the server_id
       via  8c75d9f pymessaging: Add a hook to run the event loop, make callbacks practical
       via  e92a207 server_id_db: Protect against non-0-terminated data records
       via  0c25c40 selftest: Test server_id database add and removal
       via  e77c180 pymessaging: Add irpc_remove_name
       via  3bd9e5f pymessaging: Add support for irpc_add_name
       via  a47a8e4 samba-tool: Ensure that samba-tool processes --name=not-existing does not error
       via  f21c17c selftest: Add more tests for "samba-tool processes"
      from  782172a s3: Test for CVE-2017-2619 regression with "follow symlinks = no".

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 0837d0b9dca5efe8f9cade28fc2ed8b695d6f4c2
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Mar 14 13:09:02 2017 +1300

    python: Provide Python bindings for messaging.idl
    
    This will allow AUTH_EVENT_NAME and MSG_AUTH_LOG to be accessed from python
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Tue Mar 28 13:19:03 CEST 2017 on sn-devel-144

commit a3c9ad53a2543525092e78697af9816b94281960
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Mar 14 12:37:15 2017 +1300

    messaging: Declare well known server name auth_events as AUTH_EVENT_NAME in IDL
    
    This makes it easy to ensure we use the same name in the python and the C
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>

commit 6e87aa38c4daf40f089915fd5e40e97076d35aa2
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Mar 7 15:09:38 2017 +1300

    messaging.idl: Register a message type for authentication log messages
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Pair-Programmed-by: Gary Lockyer <gary at catalyst.net.nz>
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>

commit 16e9448174a7cb7ece90a7a68b7f0fd8ffa4de91
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Thu Mar 16 16:26:01 2017 +1300

    pymessaging: add single element tupple form of the server_id
    
    This avoids the python code needing to call getpid() internally,
    while declaring a stable task_id.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>

commit 8c75d9fc73614fad29a998d08c4b11034ab2aebb
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Mar 14 12:39:13 2017 +1300

    pymessaging: Add a hook to run the event loop, make callbacks practical
    
    These change allow us to write a messaging server in python.
    
    The previous ping_speed test did not actually test anything, so
    we use .loop_once() to make it actually work.  To enable practial use
    a context is supplied in the tuple with the callback, and the server_id
    for the reply is not placed inside an additional tuple.
    
    In order to get at the internal event context on which to loop, we
    expose imessaging_context in messaging_internal.h and allow the python
    bindings to use that header.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>

commit e92a20781ca45b8696397cdef424fe8b92bee66b
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Mar 23 15:48:25 2017 +0100

    server_id_db: Protect against non-0-terminated data records
    
    Remove the failing test from knownfail.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12705

commit 0c25c40315a8255362780486d2f2e27ea0dbbff4
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Mar 14 16:07:46 2017 +1300

    selftest: Test server_id database add and removal
    
    This tests indirectly server_id_db_lookup() and
    server_id_db_prune_name(), as well as the imessaging
    and the imessaging python bindings.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12705

commit e77c18019aef9c98caa0b66cb2e9da5a6f58e600
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Mar 14 13:39:00 2017 +1300

    pymessaging: Add irpc_remove_name
    
    This allows tests to be indirectly added for server_id_db_lookup()
    and server_id_db_prune_name()
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12705

commit 3bd9e5f4ed2362f5006144433295cde2276272c5
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Mar 8 14:53:26 2017 +1300

    pymessaging: Add support for irpc_add_name
    
    This allows tests to be indirectly added for server_id_db_lookup()
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Pair-Programmed-by: Gary Lockyer <gary at catalyst.net.nz>
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12705

commit a47a8e41bd3acc20d40ba78449d89775bcdd73ed
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 24 13:07:06 2017 +1300

    samba-tool: Ensure that samba-tool processes --name=not-existing does not error
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12705

commit f21c17c6d0bfa304c54d80aaceb91aad1a3a6bb1
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 24 13:07:23 2017 +1300

    selftest: Add more tests for "samba-tool processes"
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12705

-----------------------------------------------------------------------

Summary of changes:
 lib/util/server_id_db.c                            |  22 +++-
 librpc/idl/messaging.idl                           |   6 +
 librpc/idl/wscript_build                           |   7 +-
 python/samba/netcmd/processes.py                   |   6 +-
 python/samba/tests/messaging.py                    | 113 ++++++++++++++--
 python/samba/tests/samba_tool/processes.py         |   6 +
 source4/lib/messaging/messaging.c                  |  17 +--
 .../lib/messaging/messaging_internal.h             |  21 ++-
 source4/lib/messaging/pymessaging.c                | 143 +++++++++++++++++++--
 source4/librpc/wscript_build                       |   6 +
 10 files changed, 292 insertions(+), 55 deletions(-)
 copy libcli/auth/schannel.h => source4/lib/messaging/messaging_internal.h (62%)


Changeset truncated at 500 lines:

diff --git a/lib/util/server_id_db.c b/lib/util/server_id_db.c
index e0b8476..e190f45 100644
--- a/lib/util/server_id_db.c
+++ b/lib/util/server_id_db.c
@@ -138,6 +138,7 @@ int server_id_db_prune_name(struct server_id_db *db, const char *name,
 	char idbuf[idbuf_len];
 	TDB_DATA key;
 	uint8_t *data;
+	size_t datalen;
 	char *ids, *id;
 	int ret;
 
@@ -156,6 +157,13 @@ int server_id_db_prune_name(struct server_id_db *db, const char *name,
 		return ret;
 	}
 
+	datalen = talloc_get_size(data);
+	if ((datalen == 0) || (data[datalen-1] != '\0')) {
+		tdb_chainunlock(tdb, key);
+		TALLOC_FREE(data);
+		return EINVAL;
+	}
+
 	ids = (char *)data;
 
 	id = strv_find(ids, idbuf);
@@ -166,7 +174,12 @@ int server_id_db_prune_name(struct server_id_db *db, const char *name,
 	}
 
 	strv_delete(&ids, id);
-	ret = tdb_store(tdb, key, talloc_tdb_data(ids), TDB_MODIFY);
+
+	if (talloc_get_size(ids) == 0) {
+		ret = tdb_delete(tdb, key);
+	} else {
+		ret = tdb_store(tdb, key, talloc_tdb_data(ids), TDB_MODIFY);
+	}
 	TALLOC_FREE(data);
 
 	tdb_chainunlock(tdb, key);
@@ -200,6 +213,7 @@ int server_id_db_lookup(struct server_id_db *db, const char *name,
 	struct tdb_context *tdb = db->tdb->tdb;
 	TDB_DATA key;
 	uint8_t *data;
+	size_t datalen;
 	char *ids, *id;
 	unsigned num_servers;
 	struct server_id *servers;
@@ -212,6 +226,12 @@ int server_id_db_lookup(struct server_id_db *db, const char *name,
 		return ret;
 	}
 
+	datalen = talloc_get_size(data);
+	if ((datalen == 0) || (data[datalen-1] != '\0')) {
+		TALLOC_FREE(data);
+		return EINVAL;
+	}
+
 	ids = (char *)data;
 	num_servers = strv_count(ids);
 
diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl
index 032f95e..b962ab1 100644
--- a/librpc/idl/messaging.idl
+++ b/librpc/idl/messaging.idl
@@ -139,6 +139,9 @@ interface messaging
 		MSG_NTVFS_OPLOCK_BREAK          = 0x0703,
 		MSG_DREPL_ALLOCATE_RID          = 0x0704,
 
+		/* Called during authentication and authorization to allow out-of- */
+		MSG_AUTH_LOG                    = 0x0800,
+
 		/* dbwrap messages 4001-4999 (0x0FA0 - 0x1387) */
 		/* MSG_DBWRAP_TDB2_CHANGES		= 4001, */
 		/* MSG_DBWRAP_G_LOCK_RETRY		= 4002, */
@@ -170,4 +173,7 @@ interface messaging
 		uint32 num_recs;
 		messaging_rec *recs[num_recs];
 	} messaging_reclog;
+
+        /* This allows this well known service name to be referenced in python and C */
+        const string AUTH_EVENT_NAME = "auth_event";
 }
diff --git a/librpc/idl/wscript_build b/librpc/idl/wscript_build
index 1f09ae0..899708c 100644
--- a/librpc/idl/wscript_build
+++ b/librpc/idl/wscript_build
@@ -24,16 +24,11 @@ bld.SAMBA_PIDL_LIST('PIDL',
                     output_dir='../gen_ndr')
 
 bld.SAMBA_PIDL_LIST('PIDL',
-                    'idmap.idl',
+                    'idmap.idl messaging.idl',
                     options='--header --ndr-parser --client --python',
                     output_dir='../gen_ndr')
 
 bld.SAMBA_PIDL_LIST('PIDL',
-                    'messaging.idl',
-                    options='--header --ndr-parser',
-                    output_dir='../gen_ndr')
-
-bld.SAMBA_PIDL_LIST('PIDL',
                     '''
                     rap.idl
                     ntprinting.idl
diff --git a/python/samba/netcmd/processes.py b/python/samba/netcmd/processes.py
index b25a2e4..c8000b7 100644
--- a/python/samba/netcmd/processes.py
+++ b/python/samba/netcmd/processes.py
@@ -60,7 +60,11 @@ class cmd_processes(Command):
         msg_ctx = Messaging()
 
         if name is not None:
-            ids = msg_ctx.irpc_servers_byname(name)
+            try:
+                ids = msg_ctx.irpc_servers_byname(name)
+            except KeyError:
+                ids = []
+
             for server_id in ids:
                 self.outf.write("%d\n" % server_id.pid)
         elif pid is not None:
diff --git a/python/samba/tests/messaging.py b/python/samba/tests/messaging.py
index 5d32d60..41834c1 100644
--- a/python/samba/tests/messaging.py
+++ b/python/samba/tests/messaging.py
@@ -21,7 +21,11 @@
 import samba
 from samba.messaging import Messaging
 from samba.tests import TestCase
-from samba.dcerpc.server_id import server_id
+import time
+from samba.ndr import ndr_print
+from samba.dcerpc import server_id
+import random
+import os
 
 class MessagingTests(TestCase):
 
@@ -33,7 +37,8 @@ class MessagingTests(TestCase):
         x = self.get_context()
         def callback():
             pass
-        msg_type = x.register(callback)
+        msg_type = x.register((callback, None))
+        self.assertTrue(isinstance(msg_type, long))
         x.deregister(callback, msg_type)
 
     def test_all_servers(self):
@@ -45,24 +50,104 @@ class MessagingTests(TestCase):
         for name in x.irpc_all_servers():
             self.assertTrue(isinstance(x.irpc_servers_byname(name.name), list))
 
+    def test_unknown_name(self):
+        x = self.get_context()
+        self.assertRaises(KeyError,
+                          x.irpc_servers_byname, "samba.messaging test NONEXISTING")
+
     def test_assign_server_id(self):
         x = self.get_context()
-        self.assertTrue(isinstance(x.server_id, server_id))
+        self.assertTrue(isinstance(x.server_id, server_id.server_id))
+
+    def test_add_remove_name(self):
+        x = self.get_context()
+        name = "samba.messaging test-%d" % random.randint(1, 1000000)
+        x.irpc_add_name(name)
+        name_list = x.irpc_servers_byname(name)
+        self.assertEqual(len(name_list), 1)
+        self.assertEqual(ndr_print(x.server_id),
+                         ndr_print(name_list[0]))
+        x.irpc_remove_name(name)
+        self.assertRaises(KeyError,
+                          x.irpc_servers_byname, name)
 
     def test_ping_speed(self):
+        got_ping = {"count": 0}
+        got_pong = {"count": 0}
+        timeout = False
+
+        msg_pong = 0
+        msg_ping = 0
+
         server_ctx = self.get_context((0, 1))
-        def ping_callback(src, data):
-                server_ctx.send(src, data)
-        def exit_callback():
-                print "received exit"
-        msg_ping = server_ctx.register(ping_callback)
-        msg_exit = server_ctx.register(exit_callback)
-
-        def pong_callback():
-                print "received pong"
+        def ping_callback(got_ping, msg_type, src, data):
+            got_ping["count"] += 1
+            server_ctx.send(src, msg_pong, data)
+
+        msg_ping = server_ctx.register((ping_callback, got_ping))
+
+        def pong_callback(got_pong, msg_type, src, data):
+            got_pong["count"] += 1
+
         client_ctx = self.get_context((0, 2))
-        msg_pong = client_ctx.register(pong_callback)
+        msg_pong = client_ctx.register((pong_callback, got_pong))
 
+        # Try both server_id forms (structure and tuple)
         client_ctx.send((0, 1), msg_ping, "testing")
-        client_ctx.send((0, 1), msg_ping, "")
 
+        client_ctx.send((0, 1), msg_ping, "testing2")
+
+        start_time = time.time()
+
+        # NOTE WELL: If debugging this with GDB, then the timeout will
+        # fire while you are trying to understand it.
+
+        while (got_ping["count"] < 2 or got_pong["count"] < 2) and not timeout:
+            client_ctx.loop_once(0.1)
+            server_ctx.loop_once(0.1)
+            if time.time() - start_time > 1:
+                timeout = True
+
+        self.assertEqual(got_ping["count"], 2)
+        self.assertEqual(got_pong["count"], 2)
+
+    def test_pid_defaulting(self):
+        got_ping = {"count": 0}
+        got_pong = {"count": 0}
+        timeout = False
+
+        msg_pong = 0
+        msg_ping = 0
+
+        pid = os.getpid()
+        server_ctx = self.get_context((pid, 1))
+        def ping_callback(got_ping, msg_type, src, data):
+            got_ping["count"] += 1
+            server_ctx.send(src, msg_pong, data)
+
+        msg_ping = server_ctx.register((ping_callback, got_ping))
+
+        def pong_callback(got_pong, msg_type, src, data):
+            got_pong["count"] += 1
+
+        client_ctx = self.get_context((2,))
+        msg_pong = client_ctx.register((pong_callback, got_pong))
+
+        # Try one and two element tuple forms
+        client_ctx.send((pid, 1), msg_ping, "testing")
+
+        client_ctx.send((1,), msg_ping, "testing2")
+
+        start_time = time.time()
+
+        # NOTE WELL: If debugging this with GDB, then the timeout will
+        # fire while you are trying to understand it.
+
+        while (got_ping["count"] < 2 or got_pong["count"] < 2) and not timeout:
+            client_ctx.loop_once(0.1)
+            server_ctx.loop_once(0.1)
+            if time.time() - start_time > 1:
+                timeout = True
+
+        self.assertEqual(got_ping["count"], 2)
+        self.assertEqual(got_pong["count"], 2)
diff --git a/python/samba/tests/samba_tool/processes.py b/python/samba/tests/samba_tool/processes.py
index 5b8f502..cff9cad 100644
--- a/python/samba/tests/samba_tool/processes.py
+++ b/python/samba/tests/samba_tool/processes.py
@@ -29,6 +29,12 @@ class ProcessCmdTestCase(SambaToolCmdTest):
         (result, out, err) = self.runcmd("processes", "--name", "samba")
         self.assertCmdSuccess(result, out, err, "Ensuring processes ran successfully")
 
+    def test_unknown_name(self):
+        """Run processes command with an not-existing --name"""
+        (result, out, err) = self.runcmd("processes", "--name", "not-existing-samba")
+        self.assertCmdSuccess(result, out, err, "Ensuring processes ran successfully")
+        self.assertEqual(out, "")
+
     def test_all(self):
         """Run processes command"""
         (result, out, err) = self.runcmd("processes")
diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c
index 84df934..4d75f09 100644
--- a/source4/lib/messaging/messaging.c
+++ b/source4/lib/messaging/messaging.c
@@ -24,6 +24,7 @@
 #include "lib/util/server_id.h"
 #include "system/filesys.h"
 #include "messaging/messaging.h"
+#include "messaging/messaging_internal.h"
 #include "../lib/util/dlinklist.h"
 #include "lib/socket/socket.h"
 #include "librpc/gen_ndr/ndr_irpc.h"
@@ -55,22 +56,6 @@ struct irpc_request {
 	} incoming;
 };
 
-struct imessaging_context {
-	struct imessaging_context *prev, *next;
-	struct tevent_context *ev;
-	struct server_id server_id;
-	const char *sock_dir;
-	const char *lock_dir;
-	struct dispatch_fn **dispatch;
-	uint32_t num_types;
-	struct idr_context *dispatch_tree;
-	struct irpc_list *irpc;
-	struct idr_context *idr;
-	struct server_id_db *names;
-	struct timeval start_time;
-	void *msg_dgm_ref;
-};
-
 /* we have a linked list of dispatch handlers for each msg_type that
    this messaging server can deal with */
 struct dispatch_fn {
diff --git a/libcli/auth/schannel.h b/source4/lib/messaging/messaging_internal.h
similarity index 62%
copy from libcli/auth/schannel.h
copy to source4/lib/messaging/messaging_internal.h
index c53d68e..93c5c4b 100644
--- a/libcli/auth/schannel.h
+++ b/source4/lib/messaging/messaging_internal.h
@@ -1,10 +1,9 @@
 /*
    Unix SMB/CIFS implementation.
 
-   dcerpc schannel operations
+   Samba internal messaging functions
 
    Copyright (C) Andrew Tridgell 2004
-   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2004-2005
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -20,6 +19,18 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "libcli/auth/libcli_auth.h"
-#include "libcli/auth/schannel_state.h"
-#include "libcli/auth/schannel_proto.h"
+struct imessaging_context {
+	struct imessaging_context *prev, *next;
+	struct tevent_context *ev;
+	struct server_id server_id;
+	const char *sock_dir;
+	const char *lock_dir;
+	struct dispatch_fn **dispatch;
+	uint32_t num_types;
+	struct idr_context *dispatch_tree;
+	struct irpc_list *irpc;
+	struct idr_context *idr;
+	struct server_id_db *names;
+	struct timeval start_time;
+	void *msg_dgm_ref;
+};
diff --git a/source4/lib/messaging/pymessaging.c b/source4/lib/messaging/pymessaging.c
index f62354b..d83f5e6 100644
--- a/source4/lib/messaging/pymessaging.c
+++ b/source4/lib/messaging/pymessaging.c
@@ -34,6 +34,7 @@
 #include "librpc/rpc/dcerpc.h"
 #include "librpc/gen_ndr/server_id.h"
 #include <pytalloc.h>
+#include "messaging_internal.h"
 
 void initmessaging(void);
 
@@ -61,13 +62,20 @@ static bool server_id_from_py(PyObject *object, struct server_id *server_id)
 		server_id->task_id = task_id;
 		server_id->vnn = vnn;
 		return true;
-	} else {
+	} else if (PyTuple_Size(object) == 2) {
 		unsigned long long pid;
 		int task_id;
 		if (!PyArg_ParseTuple(object, "KI", &pid, &task_id))
 			return false;
 		*server_id = cluster_id(pid, task_id);
 		return true;
+	} else {
+		unsigned long long pid = getpid();
+		int task_id;
+		if (!PyArg_ParseTuple(object, "I", &task_id))
+			return false;
+		*server_id = cluster_id(pid, task_id);
+		return true;
 	}
 }
 
@@ -173,7 +181,8 @@ static void py_msg_callback_wrapper(struct imessaging_context *msg, void *privat
 			       uint32_t msg_type, 
 			       struct server_id server_id, DATA_BLOB *data)
 {
-	PyObject *py_server_id, *callback = (PyObject *)private_data;
+	PyObject *py_server_id, *callback_and_tuple = (PyObject *)private_data;
+	PyObject *callback, *py_private;
 
 	struct server_id *p_server_id = talloc(NULL, struct server_id);
 	if (!p_server_id) {
@@ -182,10 +191,18 @@ static void py_msg_callback_wrapper(struct imessaging_context *msg, void *privat
 	}
 	*p_server_id = server_id;
 
+	if (!PyArg_ParseTuple(callback_and_tuple, "OO",
+			      &callback,
+			      &py_private)) {
+		return;
+	}
+
 	py_server_id = py_return_ndr_struct("samba.dcerpc.server_id", "server_id", p_server_id, p_server_id);
 	talloc_unlink(NULL, p_server_id);
 
-	PyObject_CallFunction(callback, discard_const_p(char, "i(O)s#"), msg_type,
+	PyObject_CallFunction(callback, discard_const_p(char, "OiOs#"),
+			      py_private,
+			      msg_type,
 			      py_server_id,
 			      data->data, data->length);
 }
@@ -194,24 +211,30 @@ static PyObject *py_imessaging_register(PyObject *self, PyObject *args, PyObject
 {
 	imessaging_Object *iface = (imessaging_Object *)self;
 	int msg_type = -1;
-	PyObject *callback;
+	PyObject *callback_and_context;
 	NTSTATUS status;
-	const char *kwnames[] = { "callback", "msg_type", NULL };
+	const char *kwnames[] = { "callback_and_context", "msg_type", NULL };
 	
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:register", 
-		discard_const_p(char *, kwnames), &callback, &msg_type)) {
+		discard_const_p(char *, kwnames),
+					 &callback_and_context, &msg_type)) {
+		return NULL;
+	}
+	if (!PyTuple_Check(callback_and_context)
+	    || PyTuple_Size(callback_and_context) != 2) {
+		PyErr_SetString(PyExc_ValueError, "Expected of size 2 for callback_and_context");
 		return NULL;
 	}
 
-	Py_INCREF(callback);
+	Py_INCREF(callback_and_context);
 
 	if (msg_type == -1) {
 		uint32_t msg_type32 = msg_type;
-		status = imessaging_register_tmp(iface->msg_ctx, callback,
+		status = imessaging_register_tmp(iface->msg_ctx, callback_and_context,
 						py_msg_callback_wrapper, &msg_type32);
 		msg_type = msg_type32;
 	} else {
-		status = imessaging_register(iface->msg_ctx, callback,
+		status = imessaging_register(iface->msg_ctx, callback_and_context,
 				    msg_type, py_msg_callback_wrapper);
 	}
 	if (NT_STATUS_IS_ERR(status)) {
@@ -241,6 +264,85 @@ static PyObject *py_imessaging_deregister(PyObject *self, PyObject *args, PyObje
 	Py_RETURN_NONE;
 }
 
+static void simple_timer_handler(struct tevent_context *ev,
+				 struct tevent_timer *te,
+				 struct timeval current_time,
+				 void *private_data)
+{
+	return;
+}
+
+static PyObject *py_imessaging_loop_once(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+	imessaging_Object *iface = (imessaging_Object *)self;
+	double offset;
+	int seconds;
+	struct timeval next_event;
+	struct tevent_timer *timer = NULL;
+	const char *kwnames[] = { "timeout", NULL };
+
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d",
+					 discard_const_p(char *, kwnames), &offset)) {
+		TALLOC_FREE(frame);
+		return NULL;
+	}
+
+	if (offset != 0.0) {
+		seconds = offset;
+		offset -= seconds;
+		next_event = tevent_timeval_current_ofs(seconds, (int)(offset*1000000));
+
+		timer = tevent_add_timer(iface->msg_ctx->ev, frame, next_event, simple_timer_handler,
+					 NULL);
+		if (timer == NULL) {
+			PyErr_NoMemory();
+			TALLOC_FREE(frame);
+			return NULL;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list