rpms/nspluginwrapper/devel nspluginwrapper-1.1.0-concurrent-rpc_method_invoke_rediff.patch, NONE, 1.1 nspluginwrapper-1.1.0-visual-id.patch, 1.3, 1.4 nspluginwrapper.spec, 1.60, 1.61

Warren Togami 砥上勇 wtogami at fedoraproject.org
Mon Oct 6 21:33:35 UTC 2008


Author: wtogami

Update of /cvs/pkgs/rpms/nspluginwrapper/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv3877

Modified Files:
	nspluginwrapper-1.1.0-visual-id.patch nspluginwrapper.spec 
Added Files:
	nspluginwrapper-1.1.0-concurrent-rpc_method_invoke_rediff.patch 
Log Message:
- Unrevert patch from -7 because Warren was wrong
- Concurrent rpc_method_invoke() patch


nspluginwrapper-1.1.0-concurrent-rpc_method_invoke_rediff.patch:

--- NEW FILE nspluginwrapper-1.1.0-concurrent-rpc_method_invoke_rediff.patch ---
Rediff against fedora's .src.rpm

diff -urN nspluginwrapper-1.1.0.orig/Makefile nspluginwrapper-1.1.0/Makefile
--- nspluginwrapper-1.1.0.orig/Makefile	2008-10-06 14:45:47.000000000 -0400
+++ nspluginwrapper-1.1.0/Makefile	2008-10-06 14:46:15.000000000 -0400
@@ -137,6 +137,18 @@
 nploader_RAWSRCS = npw-viewer.sh
 nploader_SOURCES = $(nploader_RAWSRCS:%.sh=$(SRC_PATH)/src/%.sh)
 
+test_rpc_RAWSRCS		 = test-rpc-common.c debug.c rpc.c
+test_rpc_client_OBJECTS	 = $(test_rpc_RAWSRCS:%.c=%-client.o)
+test_rpc_server_OBJECTS	 = $(test_rpc_RAWSRCS:%.c=%-server.o)
+test_rpc_client_CPPFLAGS = $(CPPFLAGS) -I$(SRC_PATH)/src -DBUILD_CLIENT -DNPW_COMPONENT_NAME="\"Client\""
+test_rpc_server_CPPFLAGS = $(CPPFLAGS) -I$(SRC_PATH)/src -DBUILD_SERVER -DNPW_COMPONENT_NAME="\"Server\""
+test_rpc_CFLAGS			 = -I$(SRC_PATH)/src $(GLIB_CFLAGS)
+test_rpc_LDFLAGS		 = $(GLIB_LDFLAGS) $(libpthread_LDFLAGS)
+test_rpc_RAWPROGS		 = test-rpc-types test-rpc-nested test-rpc-concurrent
+test_rpc_PROGRAMS		 = \
+	$(test_rpc_RAWPROGS:%=%-client) \
+	$(test_rpc_RAWPROGS:%=%-server)
+
 CPPFLAGS	= -I. -I$(SRC_PATH)
 TARGETS		= $(npconfig_PROGRAM)
 TARGETS		+= $(nploader_PROGRAM)
@@ -146,6 +158,7 @@
 ifeq ($(build_player),yes)
 TARGETS		+= $(npplayer_PROGRAM)
 endif
+TARGETS		+= $(test_rpc_PROGRAMS)
 
 archivedir	= files/
 SRCARCHIVE	= $(PACKAGE)-$(VERSION)$(VERSION_SUFFIX).tar
@@ -336,3 +349,16 @@
 	$(CC) $(LDFLAGS) -nostdlib $(DSO_LDFLAGS) $< -o $@ \
 		-Wl,--version-script,$(patsubst $(LSB_OBJ_DIR)/%.o,$(LSB_SRC_DIR)/%.Version,$<) \
 		-Wl,-soname,`grep "$(patsubst $(LSB_OBJ_DIR)/%.o,%,$<) " $(LSB_SRC_DIR)/LibNameMap.txt | cut -f2 -d' '`
+
+test-rpc-%-client: test-rpc-%-client.o $(test_rpc_client_OBJECTS)
+	$(CC) -o $@ $< $(test_rpc_client_OBJECTS) $(test_rpc_LDFLAGS)
+test-rpc-%-client.o: $(SRC_PATH)/tests/test-rpc-%.c
+	$(CC) -o $@ -c $< $(test_rpc_client_CPPFLAGS) $(test_rpc_CFLAGS)
+%-client.o: $(SRC_PATH)/src/%.c
+	$(CC) -o $@ -c $< $(test_rpc_client_CPPFLAGS) $(test_rpc_CFLAGS)
+test-rpc-%-server: test-rpc-%-server.o $(test_rpc_server_OBJECTS)
+	$(CC) -o $@ $< $(test_rpc_server_OBJECTS) $(test_rpc_LDFLAGS)
+test-rpc-%-server.o: $(SRC_PATH)/tests/test-rpc-%.c
+	$(CC) -o $@ -c $< $(test_rpc_server_CPPFLAGS) $(test_rpc_CFLAGS)
+%-server.o: $(SRC_PATH)/src/%.c
+	$(CC) -o $@ -c $< $(test_rpc_server_CPPFLAGS) $(test_rpc_CFLAGS)
diff -urN nspluginwrapper-1.1.0.orig/src/npruntime.c nspluginwrapper-1.1.0/src/npruntime.c
--- nspluginwrapper-1.1.0.orig/src/npruntime.c	2008-10-06 14:45:47.000000000 -0400
+++ nspluginwrapper-1.1.0/src/npruntime.c	2008-10-06 14:46:15.000000000 -0400
@@ -86,7 +86,7 @@
 	D(bug(" done\n"));
   }
 
-  return RPC_ERROR_NO_ERROR;
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
 }
 
 void npclass_invoke_Invalidate(NPObject *npobj)
diff -urN nspluginwrapper-1.1.0.orig/src/npw-viewer.c nspluginwrapper-1.1.0/src/npw-viewer.c
--- nspluginwrapper-1.1.0.orig/src/npw-viewer.c	2008-10-06 14:45:47.000000000 -0400
+++ nspluginwrapper-1.1.0/src/npw-viewer.c	2008-10-06 14:46:15.000000000 -0400
@@ -2389,6 +2389,12 @@
 {
   D(bug("handle_NP_GetMIMEDescription\n"));
 
+  int error = rpc_method_get_args(connection, RPC_TYPE_INVALID);
+  if (error != RPC_ERROR_NO_ERROR) {
+	npw_perror("NP_GetMIMEDescription() get args", error);
+	return error;
+  }
+
   char *str = g_NP_GetMIMEDescription();
   return rpc_method_send_reply(connection, RPC_TYPE_STRING, str, RPC_TYPE_INVALID);
 }
@@ -2555,6 +2561,12 @@
 {
   D(bug("handle_NP_Shutdown\n"));
 
+  int error = rpc_method_get_args(connection, RPC_TYPE_INVALID);
+  if (error != RPC_ERROR_NO_ERROR) {
+	npw_perror("NP_Shutdown() get args", error);
+	return error;
+  }
+
   NPError ret = g_NP_Shutdown();
   return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_INVALID);
 }
@@ -2872,7 +2884,7 @@
   if (url)
 	free(url);
 
-  return RPC_ERROR_NO_ERROR;
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
 }
 
 // NPP_NewStream
@@ -3121,7 +3133,7 @@
   if (fname)
 	free(fname);
 
-  return RPC_ERROR_NO_ERROR;
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
 }
 
 // NPP_Print
@@ -3139,7 +3151,8 @@
   D(bug(" done\n"));
 }
 
-static void invoke_NPN_PrintData(PluginInstance *plugin, uint32_t platform_print_id, NPPrintData *printData)
+static void
+invoke_NPN_PrintData(PluginInstance *plugin, uint32_t platform_print_id, NPPrintData *printData)
 {
   if (printData == NULL)
 	return;
diff -urN nspluginwrapper-1.1.0.orig/src/npw-wrapper.c nspluginwrapper-1.1.0/src/npw-wrapper.c
--- nspluginwrapper-1.1.0.orig/src/npw-wrapper.c	2008-10-06 14:45:47.000000000 -0400
+++ nspluginwrapper-1.1.0/src/npw-wrapper.c	2008-10-06 14:46:15.000000000 -0400
@@ -246,6 +246,12 @@
 {
   D(bug("handle_NPN_UserAgent\n"));
 
+  int error = rpc_method_get_args(connection, RPC_TYPE_INVALID);
+  if (error != RPC_ERROR_NO_ERROR) {
+	npw_perror("NPN_UserAgent() get args", error);
+	return error;
+  }
+
   const char *user_agent = g_NPN_UserAgent(NULL);
   return rpc_method_send_reply(connection, RPC_TYPE_STRING, user_agent, RPC_TYPE_INVALID);
 }
@@ -273,7 +279,7 @@
 	mozilla_funcs.status(instance, message);
   if (message)
 	free(message);
-  return RPC_ERROR_NO_ERROR;
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
 }
 
 // NPN_GetValue
@@ -394,7 +400,7 @@
 
   g_NPN_InvalidateRect(instance, &invalidRect);
 
-  return RPC_ERROR_NO_ERROR;
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
 }
 
 // NPN_GetURL
@@ -595,7 +601,7 @@
   if (fwrite(printData.data, printData.size, 1, platformPrint->fp) != 1)
 	return RPC_ERROR_ERRNO_SET;
 
-  return RPC_ERROR_NO_ERROR;
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
 }
 
 // NPN_RequestRead
@@ -835,7 +841,7 @@
 
   g_NPN_PushPopupsEnabledState(instance, enabled);
 
-  return RPC_ERROR_NO_ERROR;
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
 }
 
 // NPN_PopPopupsEnabledState
@@ -865,7 +871,7 @@
 
   g_NPN_PopPopupsEnabledState(instance);
 
-  return RPC_ERROR_NO_ERROR;
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
 }
 
 // NPN_CreateObject
@@ -1175,7 +1181,7 @@
 
   // XXX memory leak (message)
 
-  return RPC_ERROR_NO_ERROR;
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
 }
 
 // NPN_GetStringIdentifier
diff -urN nspluginwrapper-1.1.0.orig/src/rpc.c nspluginwrapper-1.1.0/src/rpc.c
--- nspluginwrapper-1.1.0.orig/src/rpc.c	2008-10-06 14:45:47.000000000 -0400
+++ nspluginwrapper-1.1.0/src/rpc.c	2008-10-06 14:46:15.000000000 -0400
@@ -516,6 +516,16 @@
   return error;
 }
 
+#if DEBUG
+static inline int rpc_error_debug(rpc_connection_t *connection, int error, const char *filename, int line)
+{
+  npw_printf("ERROR: RPC error %d caught at %s:%d\n", error, filename, line);
+  return rpc_error(connection, error);
+}
+#define rpc_error(connection, error) \
+		rpc_error_debug(connection, error, __FILE__, __LINE__)
+#endif
+
 // Returns socket fd or -1 if invalid connection
 int rpc_socket(rpc_connection_t *connection)
 {
@@ -1472,7 +1482,7 @@
 // Dispatch message received in the server loop
 static int _rpc_dispatch(rpc_connection_t *connection, rpc_message_t *message)
 {
-  // wait: <invoke> (body: <method-id> MESSAGE_END
+  // recv: <invoke> (body: <method-id> MESSAGE_END
   D(bug("receiving message\n"));
   int32_t method;
   int error = rpc_message_recv_int32(message, &method);
@@ -1486,14 +1496,6 @@
 	return RPC_ERROR_MESSAGE_TYPE_INVALID;
   D(bug("  -- message received [%d]\n", method));
 
-  // send: MESSAGE_ACK
-  error = rpc_message_send_int32(message, RPC_MESSAGE_ACK);
-  if (error != RPC_ERROR_NO_ERROR)
-	return error;
-  error = rpc_message_flush(message);
-  if (error != RPC_ERROR_NO_ERROR)
-	return error;
-
   // call: <method>
   rpc_method_callback_t callback = rpc_lookup_callback(connection, method);
   if (callback)
@@ -1503,37 +1505,35 @@
   if (error != RPC_ERROR_NO_ERROR) {
 	int error_code = error;
 
-	// send: MESSAGE_FAILURE <error-code>
-	error = rpc_message_send_int32(message, RPC_MESSAGE_FAILURE);
-	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
-	error = rpc_message_send_int32(message, error_code);
-	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
-	error = rpc_message_flush(message);
-	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	// send: MESSAGE_FAILURE <error-code> ("high-level" error codes only)
+	switch (error) {
+	case RPC_ERROR_GENERIC:
+	case RPC_ERROR_ERRNO_SET:
+	case RPC_ERROR_NO_MEMORY:
+	  error = rpc_message_send_int32(message, RPC_MESSAGE_FAILURE);
+	  if (error != RPC_ERROR_NO_ERROR)
+		return error;
+	  error = rpc_message_send_int32(message, error_code);
+	  if (error != RPC_ERROR_NO_ERROR)
+		return error;
+	  error = rpc_message_flush(message);
+	  if (error != RPC_ERROR_NO_ERROR)
+		return error;
+	  break;
+	}
 	return error_code;
   }
 
-  // send: MESSAGE_ACK
-  error = rpc_message_send_int32(message, RPC_MESSAGE_ACK);
-  if (error != RPC_ERROR_NO_ERROR)
-	return error;
-  error = rpc_message_flush(message);
-  if (error != RPC_ERROR_NO_ERROR)
-	return error;
-
   return method;
 }
 
 int rpc_dispatch(rpc_connection_t *connection)
 {
+  int32_t msg_tag;
   rpc_message_t message;
   rpc_message_init(&message, connection);
 
-  // wait: <invoke> (header: MESSAGE_START)
-  int32_t msg_tag;
+  // recv: <invoke> (header: MESSAGE_START)
   int error = rpc_message_recv_int32(&message, &msg_tag);
   if (error != RPC_ERROR_NO_ERROR)
 	return rpc_error(connection, error);
@@ -1546,6 +1546,35 @@
   return method;
 }
 
+// Dispatch pending remote calls until we get MSG_TAG
+static int _rpc_dispatch_until(rpc_connection_t *connection, rpc_message_t *message, int32_t expected_msg_tag)
+{
+  if (expected_msg_tag) {
+	for (;;) {
+	  int32_t msg_tag;
+	  int error = rpc_message_recv_int32(message, &msg_tag);
+	  if (error != RPC_ERROR_NO_ERROR)
+		return error;
+	  if (msg_tag == expected_msg_tag)
+		break;
+	  if (msg_tag != RPC_MESSAGE_START)
+		return RPC_ERROR_MESSAGE_TYPE_INVALID;
+	  if ((error = _rpc_dispatch(connection, message)) < 0)
+		return error;
+	}
+  }
+  else {
+	for (;;) {
+	  int ret = _rpc_wait_dispatch(connection, 0);
+	  if (ret == 0)
+		break;
+	  if (ret < 0 || (ret = rpc_dispatch(connection)) < 0)
+		return ret;
+	}
+  }
+  return RPC_ERROR_NO_ERROR;
+}
+
 
 /* ====================================================================== */
 /* === Method Callbacks Handling                                      === */
@@ -1634,16 +1663,12 @@
   rpc_message_init(&message, connection);
 
   // call: rpc_dispatch() (pending remote calls)
-  for (;;) {
-	int ret = _rpc_wait_dispatch(connection, 0);
-	if (ret == 0)
-	  break;
-	if (ret < 0 || (ret = rpc_dispatch(connection)) < 0)
-	  return ret;
-  }
+  int error = _rpc_dispatch_until(connection, &message, 0);
+  if (error != RPC_ERROR_NO_ERROR)
+	return rpc_error(connection, error);
 
   // send: <invoke> = MESSAGE_START <method-id> MESSAGE_END
-  int error = rpc_message_send_int32(&message, RPC_MESSAGE_START);
+  error = rpc_message_send_int32(&message, RPC_MESSAGE_START);
   if (error != RPC_ERROR_NO_ERROR)
 	return rpc_error(connection, error);
   error = rpc_message_send_int32(&message, method);
@@ -1656,14 +1681,6 @@
   if (error != RPC_ERROR_NO_ERROR)
 	return rpc_error(connection, error);
 
-  // wait: MESSAGE_ACK
-  int32_t msg_tag;
-  error = rpc_message_recv_int32(&message, &msg_tag);
-  if (error != RPC_ERROR_NO_ERROR)
-	return rpc_error(connection, error);
-  if (msg_tag != RPC_MESSAGE_ACK)
-	return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
-
   // send optional arguments
   va_list args;
   va_start(args, method);
@@ -1680,15 +1697,15 @@
 	error = rpc_message_flush(&message);
 	if (error != RPC_ERROR_NO_ERROR)
 	  return rpc_error(connection, error);
-
-	// wait: MESSAGE_ACK
-	error = rpc_message_recv_int32(&message, &msg_tag);
-	if (error != RPC_ERROR_NO_ERROR)
-	  return rpc_error(connection, error);
-	if (msg_tag != RPC_MESSAGE_ACK)
-	  return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
   }
 
+  // wait: MESSAGE_ACK
+  error = _rpc_dispatch_until(connection, &message, RPC_MESSAGE_ACK);
+  if (error == RPC_ERROR_ERRNO_SET)
+	perror("rpc_method_invoke");
+  if (error != RPC_ERROR_NO_ERROR)
+	return rpc_error(connection, error);
+
   return RPC_ERROR_NO_ERROR;
 }
 
@@ -1705,7 +1722,11 @@
   rpc_message_t message;
   rpc_message_init(&message, connection);
 
-  // wait: <method-args>
+  // we can't have pending calls here because the method invocation
+  // message and its arguments are atomic (i.e. they are sent right
+  // away, no wait for ACK)
+
+  // recv: <method-args>
   va_list args;
   va_start(args, connection);
   int error = rpc_message_recv_args(&message, args);
@@ -1735,76 +1756,42 @@
 	return RPC_ERROR_CONNECTION_CLOSED;
 
   int error;
+  int32_t msg_tag;
   rpc_message_t message;
   rpc_message_init(&message, connection);
 
   // call: rpc_dispatch() (pending remote calls)
-  int32_t msg_tag;
-  bool done = false;
-  while (!done) {
-	error = rpc_message_recv_int32(&message, &msg_tag);
-	if (error != RPC_ERROR_NO_ERROR)
-	  return rpc_error(connection, error);
-	switch (msg_tag) {
-	case RPC_MESSAGE_START:
-	  if ((error = _rpc_dispatch(connection, &message)) < 0)
-		return rpc_error(connection, error);
-	  break;
-	case RPC_MESSAGE_REPLY:
-	case RPC_MESSAGE_ACK:
-	  done = true;
-	  break;
-	case RPC_MESSAGE_FAILURE:
-	  {
-		// wait: <error-code>
-		int32_t error_code;
-		error = rpc_message_recv_int32(&message, &error_code);
-		if (error != RPC_ERROR_NO_ERROR)
-		  return rpc_error(connection, error);
-		// return other-side error code
-		return rpc_error(connection, error_code);
-	  }
-	default:
-	  return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
-	}
-  }
+  // recv: MESSAGE_REPLY
+  error = _rpc_dispatch_until(connection, &message, RPC_MESSAGE_REPLY);
+  if (error != RPC_ERROR_NO_ERROR)
+	return rpc_error(connection, error);
 
+  // receive optional arguments
   va_list args;
   va_start(args, connection);
   int type = va_arg(args, int);
   va_end(args);
-
   if (type != RPC_TYPE_INVALID) {
 
-	// wait: <reply>
-	if (msg_tag != RPC_MESSAGE_REPLY)
-	  return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
+	// recv: [ <method-args> ]
 	va_start(args, connection);
 	error = rpc_message_recv_args(&message, args);
 	va_end(args);
 	if (error != RPC_ERROR_NO_ERROR)
 	  return rpc_error(connection, error);
-	error = rpc_message_recv_int32(&message, &msg_tag);
-	if (error != RPC_ERROR_NO_ERROR)
-	  return rpc_error(connection, error);
-	if (msg_tag != RPC_MESSAGE_END)
-	  return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
-
-	// send: MESSAGE_ACK
-	error = rpc_message_send_int32(&message, RPC_MESSAGE_ACK);
-	if (error != RPC_ERROR_NO_ERROR)
-	  return rpc_error(connection, error);
-	error = rpc_message_flush(&message);
-	if (error != RPC_ERROR_NO_ERROR)
-	  return rpc_error(connection, error);
-
-	// wait: MESSAGE_ACK (prepare for final ACK)
-	error = rpc_message_recv_int32(&message, &msg_tag);
-	if (error != RPC_ERROR_NO_ERROR)
-	  return rpc_error(connection, error);
   }
 
+  // recv: MESSAGE_END
+  error = rpc_message_recv_int32(&message, &msg_tag);
+  if (error != RPC_ERROR_NO_ERROR)
+	return rpc_error(connection, error);
+  if (msg_tag != RPC_MESSAGE_END)
+	return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
+
   // wait: MESSAGE_ACK
+  error = rpc_message_recv_int32(&message, &msg_tag);
+  if (error != RPC_ERROR_NO_ERROR)
+	return rpc_error(connection, error);
   if (msg_tag != RPC_MESSAGE_ACK)
 	return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
   
@@ -1841,13 +1828,13 @@
   if (error != RPC_ERROR_NO_ERROR)
 	return rpc_error(connection, error);
 
-  // wait: MESSAGE_ACK
-  int32_t msg_tag;
-  error = rpc_message_recv_int32(&message, &msg_tag);
+  // send: MESSAGE_ACK
+  error = rpc_message_send_int32(&message, RPC_MESSAGE_ACK);
+  if (error != RPC_ERROR_NO_ERROR)
+	return rpc_error(connection, error);
+  error = rpc_message_flush(&message);
   if (error != RPC_ERROR_NO_ERROR)
 	return rpc_error(connection, error);
-  if (msg_tag != RPC_MESSAGE_ACK)
-	return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
 
   return RPC_ERROR_NO_ERROR;
 }
diff -urN nspluginwrapper-1.1.0.orig/tests/test-rpc-common.c nspluginwrapper-1.1.0/tests/test-rpc-common.c
--- nspluginwrapper-1.1.0.orig/tests/test-rpc-common.c	1969-12-31 19:00:00.000000000 -0500
+++ nspluginwrapper-1.1.0/tests/test-rpc-common.c	2008-10-06 14:46:15.000000000 -0400
@@ -0,0 +1,318 @@
+/*
+ *  test-rpc-common.c - Common RPC test code
+ *
+ *  nspluginwrapper (C) 2005-2008 Gwenole Beauchesne
+ *
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "sysdeps.h"
+#include "test-rpc-common.h"
+#include <signal.h>
+
+#define DEBUG 1
+#include "debug.h"
+
+#ifdef  BUILD_WRAPPER
+#define BUILD_CLIENT 1
+#endif
+
+#ifdef  BUILD_VIEWER
+#define BUILD_SERVER 1
+#endif
+
+typedef struct _RPCTest RPCTest;
+struct _RPCTest
+{
+  RPCTestFuncs funcs;
+  gpointer     user_data;
+};
+
+static RPCTest           g_test;
+static rpc_connection_t *g_connection;
+static const gchar      *g_connection_path;
+static GMainLoop        *g_main_loop;
+static GPid              g_child_pid;
+static guint             g_child_watch_id;
+static guint             g_source_id;
+static gint              g_exit_status;
+
+void
+rpc_test_set_funcs (const RPCTestFuncs *funcs, gpointer user_data)
+{
+  g_test.user_data = user_data;
+  if (funcs && funcs->pre_dispatch_hook)
+	g_test.funcs.pre_dispatch_hook = funcs->pre_dispatch_hook;
+  if (funcs && funcs->post_dispatch_hook)
+	g_test.funcs.post_dispatch_hook = funcs->post_dispatch_hook;
+}
+
+rpc_connection_t *
+rpc_test_get_connection (void)
+{
+  return g_connection;
+}
+
+#ifdef BUILD_CLIENT
+static void
+child_exited_cb (GPid pid, gint status, gpointer user_data)
+{
+  g_print ("child_exited_cb(), pid %d, status %d\n", pid, status);
+  if (status)
+	g_exit_status = status;
+  g_main_loop_quit (g_main_loop);
+  if (g_child_watch_id)
+	g_source_remove (g_child_watch_id);
+  g_spawn_close_pid (pid);
+}
+
+static void
+kill_child_now (void)
+{
+  if (g_child_watch_id)
+	g_source_remove (g_child_watch_id);
+  if (g_child_pid)
+	{
+	  g_spawn_close_pid (g_child_pid);
+	  kill (g_child_pid, SIGTERM);
+	}
+}
+
+static void
+urgent_exit_sig (int sig)
+{
+  kill_child_now ();
+}
+#endif
+
+#ifdef BUILD_SERVER
+static gboolean
+rpc_event_prepare (GSource *source, gint *timeout)
+{
+  *timeout = -1;
+  return FALSE;
+}
+
+static gboolean
+rpc_event_check (GSource *source)
+{
+  return rpc_wait_dispatch (g_connection, 0) > 0;
+}
+
+static gboolean
+rpc_event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
+{
+  gint rc;
+
+  if (g_test.funcs.pre_dispatch_hook)
+	{
+	  if (!g_test.funcs.pre_dispatch_hook (g_test.user_data))
+		return TRUE;
+	}
+
+  rc = rpc_dispatch (g_connection);
+
+  if (g_test.funcs.post_dispatch_hook)
+	g_test.funcs.post_dispatch_hook (g_test.user_data);
+
+  return rc != RPC_ERROR_CONNECTION_CLOSED;
+}
+
+typedef gboolean (*GSourcePrepare)      (GSource *, gint *);
+typedef gboolean (*GSourceCheckFunc)    (GSource *);
+typedef gboolean (*GSourceDispatchFunc) (GSource *, GSourceFunc, gpointer);
+typedef void     (*GSourceFinalizeFunc) (GSource *);
+
+static GSourceFuncs rpc_event_funcs =
+  {
+	rpc_event_prepare,
+	rpc_event_check,
+	rpc_event_dispatch,
+	(GSourceFinalizeFunc)g_free,
+	(GSourceFunc)NULL,
+	(GSourceDummyMarshal)NULL
+  };
+#endif
+
+static gboolean
+rpc_test_execute_cb (gpointer user_data)
+{
+  int rc = RPC_TEST_EXECUTE_SUCCESS;
+
+  if (rpc_test_execute)
+	rc = rpc_test_execute (g_test.user_data);
+  g_assert ((rc & ~RPC_TEST_EXECUTE_DONT_QUIT) == RPC_TEST_EXECUTE_SUCCESS);
+
+#ifdef BUILD_CLIENT
+  if ((rc & RPC_TEST_EXECUTE_DONT_QUIT) == 0)
+	rpc_test_exit_full (0);
+#endif
+  return FALSE;
+}
+
+static gchar **
+clone_args (gchar **args)
+{
+  gchar **new_args;
+  gint    i, n, rc = 0;
+
+  if ((new_args = g_strdupv (args)) == NULL)
+	g_error ("could not duplicate the program arguments");
+  n = g_strv_length (new_args);
+
+#ifdef BUILD_CLIENT
+  /* first arg was path to server program, skip it */
+  g_assert (n >= 2);
+  g_free (new_args[1]);
+  for (i = 1; i < n - 1; i++)
+	new_args[i] = new_args[i + 1];
+  new_args[i] = NULL;
+#endif
+
+  return new_args;
+}
+
+static void
+rpc_test_init_invoke (gchar **program_args)
+{
+  gchar **args  = NULL;
+  gint    n, rc = 0;
+
+  if ((args = clone_args (program_args)) == NULL)
+	g_error ("could not clone program arguments");
+  n = g_strv_length (args);
+
+  if (rpc_test_init)
+	rc = rpc_test_init (n, args);
+  g_strfreev (args);
+  g_assert (rc == 0);
+
+  g_timeout_add (0, rpc_test_execute_cb, NULL);
+}
+
+void
+rpc_test_exit (int status)
+{
+  if (status)
+	g_exit_status = status;
+  if (g_source_id)
+	g_source_remove (g_source_id);
+  if (g_connection)
+	rpc_exit (g_connection);
+  g_main_loop_quit (g_main_loop);
+}
+
+void
+rpc_test_exit_full (int status)
+{
+#ifdef BUILD_CLIENT
+  /* Tell server to quit, don't expect any reply from him */
+  rpc_method_invoke (g_connection,
+					 RPC_TEST_METHOD_EXIT,
+					 RPC_TYPE_INT32, status,
+					 RPC_TYPE_INVALID);
+#endif
+
+  rpc_test_exit (status);
+}
+
+static int
+handle_rpc_test_exit (rpc_connection_t *connection)
+{
+  int    error;
+  gint32 status;
+
+  error = rpc_method_get_args (connection,
+							   RPC_TYPE_INT32, &status,
+							   RPC_TYPE_INVALID);
+
+  if (error == RPC_ERROR_NO_ERROR)
+	rpc_test_exit (status);
+
+  return error;
+}
+
+int
+main (int argc, char *argv[])
+{
+  if (rpc_test_get_connection_path)
+	g_connection_path = rpc_test_get_connection_path ();
+  else
+	g_connection_path = NPW_CONNECTION_PATH "/Test.RPC";
+
+#ifdef BUILD_CLIENT
+  gchar **child_args;
+
+  if (argc < 2)
+	g_error ("no server program provided on command line");
+
+  signal (SIGSEGV, urgent_exit_sig);
+  signal (SIGBUS,  urgent_exit_sig);
+  signal (SIGINT,  urgent_exit_sig);
+  signal (SIGABRT, urgent_exit_sig);
+
+  if ((child_args = clone_args (argv)) == NULL)
+	g_error ("could not create server program arguments\n");
+  g_free (child_args[0]);
+  child_args[0] = g_strdup (argv[1]);
+
+  if (!g_spawn_async (NULL,
+					  child_args,
+					  NULL,
+					  G_SPAWN_DO_NOT_REAP_CHILD,
+					  NULL,
+					  NULL,
+					  &g_child_pid,
+					  NULL))
+	g_error ("could not start server program '%s'", child_args[0]);
+
+  g_strfreev (child_args);
+
+  if ((g_connection = rpc_init_client (g_connection_path)) == NULL)
+	g_error ("failed to initialize RPC client connection");
+#endif
+
+#ifdef BUILD_SERVER
+  if ((g_connection = rpc_init_server (g_connection_path)) == NULL)
+	g_error ("failed to initialize RPC server connection");
+
+  GSource   *rpc_source;
+  GPollFD    rpc_event_poll_fd;
+
+  if ((rpc_source = g_source_new (&rpc_event_funcs, sizeof (GSource))) == NULL)
+	g_error ("failed to initialize RPC source");
+
+  g_source_id = g_source_attach (rpc_source, NULL);
+  memset (&rpc_event_poll_fd, 0, sizeof (rpc_event_poll_fd));
+  rpc_event_poll_fd.fd      = rpc_listen_socket (g_connection);
+  rpc_event_poll_fd.events  = G_IO_IN;
+  rpc_event_poll_fd.revents = 0;
+  g_source_add_poll (rpc_source, &rpc_event_poll_fd);
+#endif
+
+  static const rpc_method_descriptor_t vtable[] = {
+	{ RPC_TEST_METHOD_EXIT, handle_rpc_test_exit }
+  };
+  if (rpc_connection_add_method_descriptor (g_connection, &vtable[0]) < 0)
+	g_error ("could not add method descriptor for TEST_RPC_METHOD_EXIT");
+
+  g_main_loop = g_main_loop_new (NULL, TRUE);
+#ifdef BUILD_CLIENT
+  g_child_watch_id = g_child_watch_add (g_child_pid, child_exited_cb, NULL);
+#endif
+  rpc_test_init_invoke (argv);
+  g_main_loop_run (g_main_loop);
+  return g_exit_status;
+}
diff -urN nspluginwrapper-1.1.0.orig/tests/test-rpc-common.h nspluginwrapper-1.1.0/tests/test-rpc-common.h
--- nspluginwrapper-1.1.0.orig/tests/test-rpc-common.h	1969-12-31 19:00:00.000000000 -0500
+++ nspluginwrapper-1.1.0/tests/test-rpc-common.h	2008-10-06 14:46:15.000000000 -0400
@@ -0,0 +1,74 @@
+/*
+ *  test-rpc-common.h - Common RPC test code
+ *
+ *  nspluginwrapper (C) 2005-2008 Gwenole Beauchesne
+ *
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TEST_RPC_COMMON_H
+#define TEST_RPC_COMMON_H
+
+#include "rpc.h"
+#include <glib.h>
+
+enum
+  {
+	/* void rpc_test_exit (int status); */
+	RPC_TEST_METHOD_EXIT = 0,
+  };
+
+enum
+  {
+	RPC_TEST_EXECUTE_SUCCESS   = 0,
+	RPC_TEST_EXECUTE_FAILURE   = 1,
+	RPC_TEST_EXECUTE_DONT_QUIT = 0x8000,
+  };
+
+typedef struct _RPCTestFuncs RPCTestFuncs;
+struct _RPCTestFuncs
+{
+  gboolean (*pre_dispatch_hook)  (gpointer user_data);
+  void     (*post_dispatch_hook) (gpointer user_data);
+};
+
+void
+rpc_test_set_funcs (const RPCTestFuncs *funcs, gpointer user_data);
+
+rpc_connection_t *
+rpc_test_get_connection (void);
+
+/* IMPLEMENT: default is NPW_CONNECTION_PATH "/Test.RPC"; */
+const gchar *
+rpc_test_get_connection_path (void)
+  __attribute__((__weak__));
+
+/* IMPLEMENT: default is return 0; */
+int
+rpc_test_init (int argc, char *argv[])
+  __attribute__((__weak__));
+
+/* IMPLEMENT: default is return 0; */
+int
+rpc_test_execute (gpointer user_data)
+  __attribute__((__weak__));
+
+void
+rpc_test_exit (int status);
+
+void
+rpc_test_exit_full (int status);
+
+#endif /* TEST_RPC_COMMON_H */
diff -urN nspluginwrapper-1.1.0.orig/tests/test-rpc-concurrent.c nspluginwrapper-1.1.0/tests/test-rpc-concurrent.c
--- nspluginwrapper-1.1.0.orig/tests/test-rpc-concurrent.c	1969-12-31 19:00:00.000000000 -0500
+++ nspluginwrapper-1.1.0/tests/test-rpc-concurrent.c	2008-10-06 14:46:15.000000000 -0400
@@ -0,0 +1,163 @@
+/*
+ *  test-rpc-concurrent.c - Test concurrent RPC invoke
+ *
+ *  nspluginwrapper (C) 2005-2008 Gwenole Beauchesne
+ *
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "sysdeps.h"
+#include "test-rpc-common.h"
+#include <string.h>
+
+#define DEBUG 1
+#include "debug.h"
+
+#define RPC_TEST_USE_IDLE   TRUE
+
+enum
+  {
+	RPC_TEST_METHOD_PRINT = 1
+  };
+
+static gboolean g_is_silent   = TRUE;
+static gint     g_print_count = 5000;
+
+static void
+invoke_print (const gchar *str)
+{
+  rpc_connection_t *connection;
+  int               error;
+
+  connection = rpc_test_get_connection ();
+  g_assert (connection != NULL);
+
+  error = rpc_method_invoke (connection,
+							 RPC_TEST_METHOD_PRINT,
+							 RPC_TYPE_STRING, str,
+							 RPC_TYPE_INVALID);
+  /* Error out early for invalid messages types.
+
+	 The problem we are looking at is rpc_method_invoke() waiting for
+	 the other side MSG_ACK prior to sending the arguments. Sometimes,
+	 the other side sends a new message first (MSG_START). So, we get
+	 a mismatch. */
+  g_assert (error != RPC_ERROR_MESSAGE_TYPE_INVALID);
+  g_assert (error == RPC_ERROR_NO_ERROR);
+
+  error = rpc_method_wait_for_reply (connection, RPC_TYPE_INVALID);
+  g_assert (error == RPC_ERROR_NO_ERROR);
+}
+
+static int
+handle_print (rpc_connection_t *connection)
+{
+  char *str;
+  int   error;
+
+  error = rpc_method_get_args (connection,
+							   RPC_TYPE_STRING, &str,
+							   RPC_TYPE_INVALID);
+  g_assert (error == RPC_ERROR_NO_ERROR);
+  g_assert (str != NULL);
+
+  if (!g_is_silent)
+	npw_printf ("Got message from the other end: '%s'\n", str);
+  free (str);
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static inline void
+print_msg (void)
+{
+  invoke_print ("Hello from " NPW_COMPONENT_NAME);
+}
+
+static gboolean
+invoke_print_cb (gpointer user_data)
+{
+  print_msg ();
+
+  --g_print_count;
+#ifdef BUILD_CLIENT
+  if (g_print_count == 0)
+	rpc_test_exit_full (0);
+#endif
+  return g_print_count > 0;
+}
+
+int
+rpc_test_init (int argc, char *argv[])
+{
+  rpc_connection_t *connection;
+
+  for (int i = 1; i < argc; i++)
+	{
+	  const gchar *arg = argv[i];
+	  if (strcmp (arg, "--silent") == 0 || strcmp (arg, "-q") == 0)
+		g_is_silent = TRUE;
+	  else if (strcmp (arg, "--verbose") == 0 || strcmp (arg, "-v") == 0)
+		g_is_silent = FALSE;
+	  else if (strcmp (arg, "--count") == 0)
+		{
+		  if (++i < argc)
+			{
+			  unsigned long v = strtoul (argv[i], NULL, 10);
+			  if (v > 0)
+				g_print_count = v;
+			}
+		}
+	  else if (strcmp (arg, "--help") == 0)
+		{
+		  g_print ("Usage: %s [--silent|--verbose] [--count COUNT]\n", argv[0]);
+		  rpc_test_exit (0);
+		}
+	}
+
+  connection = rpc_test_get_connection ();
+  g_assert (connection != NULL);
+
+  static const rpc_method_descriptor_t vtable[] = {
+	{ RPC_TEST_METHOD_PRINT, handle_print },
+  };
+
+  if (rpc_connection_add_method_descriptor (connection, &vtable[0]) < 0)
+	g_error ("could not add method descriptors");
+
+  if (RPC_TEST_USE_IDLE)
+	{
+	  /* XXX: we hope to trigger concurrent rpc_method_invoke() */
+	  /* XXX: add a barrier to synchronize both processes? */
+	  //g_idle_add (invoke_print_cb, NULL);
+	  g_timeout_add (0, invoke_print_cb, NULL);
+	}
+  else
+	{
+	  while (--g_print_count >= 0)
+		print_msg ();
+	}
+  return 0;
+}
+
+int
+rpc_test_execute (gpointer user_data)
+{
+#ifdef BUILD_CLIENT
+  if (RPC_TEST_USE_IDLE)
+	return RPC_TEST_EXECUTE_SUCCESS|RPC_TEST_EXECUTE_DONT_QUIT;
+#endif
+  return RPC_TEST_EXECUTE_SUCCESS;
+}
diff -urN nspluginwrapper-1.1.0.orig/tests/test-rpc-nested.c nspluginwrapper-1.1.0/tests/test-rpc-nested.c
--- nspluginwrapper-1.1.0.orig/tests/test-rpc-nested.c	1969-12-31 19:00:00.000000000 -0500
+++ nspluginwrapper-1.1.0/tests/test-rpc-nested.c	2008-10-06 14:46:15.000000000 -0400
@@ -0,0 +1,116 @@
+/*
+ *  test-rpc-nested.c - Test nested RPC invoke
+ *
+ *  nspluginwrapper (C) 2005-2008 Gwenole Beauchesne
+ *
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "sysdeps.h"
+#include "test-rpc-common.h"
+#include <unistd.h>
+
+#define DEBUG 1
+#include "debug.h"
+
+enum
+  {
+	RPC_TEST_METHOD_GET_PID = 1
+  };
+
+static gint
+get_remote_pid (void)
+{
+  rpc_connection_t *connection;
+  int               error;
+  gint32            pid;
+
+  connection = rpc_test_get_connection ();
+  g_assert (connection != NULL);
+
+  error = rpc_method_invoke (connection,
+							 RPC_TEST_METHOD_GET_PID,
+							 RPC_TYPE_INVALID);
+  g_assert (error == RPC_ERROR_NO_ERROR);
+
+  error = rpc_method_wait_for_reply (connection,
+									 RPC_TYPE_INT32, &pid,
+									 RPC_TYPE_INVALID);
+  g_assert (error == RPC_ERROR_NO_ERROR);
+
+  return pid;
+}
+
+static inline gint
+get_local_pid (void)
+{
+  return getpid ();
+}
+
+static inline gint
+get_client_pid (void)
+{
+#ifdef BUILD_CLIENT
+  return get_local_pid ();
+#endif
+#ifdef BUILD_SERVER
+  return get_remote_pid ();
+#endif
+  return -1;
+}
+
+static int
+handle_get_pid (rpc_connection_t *connection)
+{
+  gint pid;
+  int  error;
+
+  error = rpc_method_get_args (connection, RPC_TYPE_INVALID);
+  g_assert (error == RPC_ERROR_NO_ERROR);
+
+  pid = get_client_pid ();
+
+  return rpc_method_send_reply (connection,
+								RPC_TYPE_INT32, pid,
+								RPC_TYPE_INVALID);
+}
+
+int
+rpc_test_init (int argc, char *argv[])
+{
+  rpc_connection_t *connection;
+
+  connection = rpc_test_get_connection ();
+  g_assert (connection != NULL);
+
+  static const rpc_method_descriptor_t vtable[] = {
+	{ RPC_TEST_METHOD_GET_PID, handle_get_pid },
+  };
+
+  if (rpc_connection_add_method_descriptor (connection, &vtable[0]) < 0)
+	g_error ("could not add method descriptors");
+
+  return 0;
+}
+
+int
+rpc_test_execute (gpointer user_data)
+{
+#ifdef BUILD_CLIENT
+  gint pid = get_remote_pid ();
+  g_assert (pid == get_local_pid ());
+#endif
+  return RPC_TEST_EXECUTE_SUCCESS;
+}
diff -urN nspluginwrapper-1.1.0.orig/tests/test-rpc-types.c nspluginwrapper-1.1.0/tests/test-rpc-types.c
--- nspluginwrapper-1.1.0.orig/tests/test-rpc-types.c	1969-12-31 19:00:00.000000000 -0500
+++ nspluginwrapper-1.1.0/tests/test-rpc-types.c	2008-10-06 14:46:15.000000000 -0400
@@ -0,0 +1,504 @@
+/*
+ *  test-rpc-types.c - Test marshaling of common data types
+ *
+ *  nspluginwrapper (C) 2005-2008 Gwenole Beauchesne
+ *
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "sysdeps.h"
+#include "test-rpc-common.h"
+#include "utils.h"
+#include <stdarg.h>
+
+#define DEBUG 1
+#include "debug.h"
+
+#define RPC_TEST_MAX_ARGS 32
+
+enum
+  {
+	RPC_TEST_METHOD_VOID__VOID = 1,
+	RPC_TEST_METHOD_VOID__CHAR,
+	RPC_TEST_METHOD_VOID__CHARx10,
+	RPC_TEST_METHOD_VOID__BOOL, 
+	RPC_TEST_METHOD_VOID__BOOLx10,
+	RPC_TEST_METHOD_VOID__INT32x10,
+	RPC_TEST_METHOD_VOID__UINT32x10,
+	RPC_TEST_METHOD_VOID__UINT64x10,
+	RPC_TEST_METHOD_VOID__DOUBLEx5,
+	RPC_TEST_METHOD_VOID__STRINGx3,
+ };
+
+const gchar *
+rpc_test_get_connection_path (void)
+{
+  return NPW_CONNECTION_PATH "/Test.RPC.Types";
+}
+
+static void
+rpc_test_signature (gboolean is_invoke, ...)
+{
+  va_list  args;
+  gint     type, n_args;
+  gboolean was_array;
+  GString *str;
+
+  if ((str = g_string_new (NULL)) == NULL)
+	return;
+  n_args = 0;
+  was_array = FALSE;
+  va_start (args, is_invoke);
+  while ((type = va_arg (args, gint)) != RPC_TYPE_INVALID)
+	{
+	  if (++n_args > 1 && !was_array)
+		g_string_append (str, ", ");
+	  was_array = FALSE;
+	  switch (type)
+		{
+		case RPC_TYPE_CHAR:
+		  g_string_append (str, "char");
+		  if (is_invoke)
+			va_arg (args, int);
+		  break;
+		case RPC_TYPE_BOOLEAN:
+		  g_string_append (str, "bool");
+		  if (is_invoke)
+			va_arg (args, int);
+		  break;
+		case RPC_TYPE_INT32:
+		  g_string_append (str, "int32");
+		  if (is_invoke)
+			va_arg (args, gint32);
+		  break;
+		case RPC_TYPE_UINT32:
+		  g_string_append (str, "uint32");
+		  if (is_invoke)
+			va_arg (args, guint32);
+		  break;
+		case RPC_TYPE_UINT64:
+		  g_string_append (str, "uint64");
+		  if (is_invoke)
+			va_arg (args, guint64);
+		  break;
+		case RPC_TYPE_DOUBLE:
+		  g_string_append (str, "double");
+		  if (is_invoke)
+			va_arg (args, gdouble);
+		  break;
+		case RPC_TYPE_STRING:
+		  g_string_append (str, "string");
+		  if (is_invoke)
+			va_arg (args, gchar *);
+		  break;
+		case RPC_TYPE_ARRAY:
+		  g_string_append (str, "array of");
+		  was_array = TRUE;
+		  break;
+		}
+	  if (!is_invoke && type != RPC_TYPE_ARRAY)
+		va_arg (args, gpointer);
+	}
+  va_end (args);
+  if (n_args == 0)
+	g_string_append (str, "void");
+  g_print ("void f (%s)\n", str->str);
+  g_string_free (str, TRUE);
+}
+
+#define rpc_test_invoke(method, ...) do {							\
+  int error;														\
+  rpc_connection_t *connection;										\
+  connection = rpc_test_get_connection ();							\
+  rpc_test_signature (TRUE, __VA_ARGS__);							\
+  error = rpc_method_invoke (connection, method, __VA_ARGS__);		\
+  g_assert (error == RPC_ERROR_NO_ERROR);							\
+  error = rpc_method_wait_for_reply (connection, RPC_TYPE_INVALID); \
+  g_assert (error == RPC_ERROR_NO_ERROR);							\
+} while (0)
+
+#define rpc_test_get_args(connection, ...) do {						\
+  int error;														\
+  rpc_test_signature (FALSE, __VA_ARGS__);							\
+  error = rpc_method_get_args (connection, __VA_ARGS__);			\
+  g_assert (error == RPC_ERROR_NO_ERROR);							\
+} while (0)
+
+#ifdef BUILD_SERVER
+typedef union _RPCTestArg RPCTestArg;
+
+union _RPCTestArg
+{
+  gchar   c;
+  guint   b;
+  gint32  i;
+  guint32 u;
+  guint64 j;
+  gdouble d;
+  gchar  *s;
+};
+
+static RPCTestArg g_args[RPC_TEST_MAX_ARGS];
+
+static int
+handle_VOID__VOID (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_INVALID);
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static int
+handle_VOID__CHAR (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_CHAR, &g_args[0].c,
+					 RPC_TYPE_INVALID);
+
+  g_assert (g_args[0].c == 'a');
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static int
+handle_VOID__CHARx10 (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_CHAR, &g_args[0].c,
+					 RPC_TYPE_CHAR, &g_args[1].c,
+					 RPC_TYPE_CHAR, &g_args[2].c,
+					 RPC_TYPE_CHAR, &g_args[3].c,
+					 RPC_TYPE_CHAR, &g_args[4].c,
+					 RPC_TYPE_CHAR, &g_args[5].c,
+					 RPC_TYPE_CHAR, &g_args[6].c,
+					 RPC_TYPE_CHAR, &g_args[7].c,
+					 RPC_TYPE_CHAR, &g_args[8].c,
+					 RPC_TYPE_CHAR, &g_args[9].c,
+					 RPC_TYPE_INVALID);
+
+  g_assert (g_args[0].c == 'a');
+  g_assert (g_args[1].c == 'b');
+  g_assert (g_args[2].c == 'c');
+  g_assert (g_args[3].c == 'd');
+  g_assert (g_args[4].c == 'e');
+  g_assert (g_args[5].c == '1');
+  g_assert (g_args[6].c == '2');
+  g_assert (g_args[7].c == '3');
+  g_assert (g_args[8].c == '4');
+  g_assert (g_args[9].c == '5');
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static int
+handle_VOID__BOOL (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_BOOLEAN, &g_args[0].b,
+					 RPC_TYPE_INVALID);
+
+  g_assert (g_args[0].b == TRUE);
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static int
+handle_VOID__BOOLx10 (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_BOOLEAN, &g_args[0].b,
+					 RPC_TYPE_BOOLEAN, &g_args[1].b,
+					 RPC_TYPE_BOOLEAN, &g_args[2].b,
+					 RPC_TYPE_BOOLEAN, &g_args[3].b,
+					 RPC_TYPE_BOOLEAN, &g_args[4].b,
+					 RPC_TYPE_BOOLEAN, &g_args[5].b,
+					 RPC_TYPE_BOOLEAN, &g_args[6].b,
+					 RPC_TYPE_BOOLEAN, &g_args[7].b,
+					 RPC_TYPE_BOOLEAN, &g_args[8].b,
+					 RPC_TYPE_BOOLEAN, &g_args[9].b,
+					 RPC_TYPE_INVALID);
+
+  g_assert (g_args[0].b == TRUE);
+  g_assert (g_args[1].b == FALSE);
+  g_assert (g_args[2].b == TRUE);
+  g_assert (g_args[3].b == FALSE);
+  g_assert (g_args[4].b == TRUE);
+  g_assert (g_args[5].b == FALSE);
+  g_assert (g_args[6].b == TRUE);
+  g_assert (g_args[7].b == FALSE);
+  g_assert (g_args[8].b == TRUE);
+  g_assert (g_args[9].b == FALSE);
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static int
+handle_VOID__INT32x10 (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_INT32, &g_args[0].i,
+					 RPC_TYPE_INT32, &g_args[1].i,
+					 RPC_TYPE_INT32, &g_args[2].i,
+					 RPC_TYPE_INT32, &g_args[3].i,
+					 RPC_TYPE_INT32, &g_args[4].i,
+					 RPC_TYPE_INT32, &g_args[5].i,
+					 RPC_TYPE_INT32, &g_args[6].i,
+					 RPC_TYPE_INT32, &g_args[7].i,
+					 RPC_TYPE_INT32, &g_args[8].i,
+					 RPC_TYPE_INT32, &g_args[9].i,
+					 RPC_TYPE_INVALID);
+
+  g_assert (g_args[0].i == 0);
+  g_assert (g_args[1].i == 1);
+  g_assert (g_args[2].i == -1);
+  g_assert (g_args[3].i == 2);
+  g_assert (g_args[4].i == -2);
+  g_assert (g_args[5].i == G_MAXINT32);
+  g_assert (g_args[6].i == G_MININT32);
+  g_assert (g_args[7].i == G_MAXINT32 - 1);
+  g_assert (g_args[8].i == G_MININT32 + 1);
+  g_assert (g_args[9].i == 0);
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static int
+handle_VOID__UINT32x10 (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_UINT32, &g_args[0].u,
+					 RPC_TYPE_UINT32, &g_args[1].u,
+					 RPC_TYPE_UINT32, &g_args[2].u,
+					 RPC_TYPE_UINT32, &g_args[3].u,
+					 RPC_TYPE_UINT32, &g_args[4].u,
+					 RPC_TYPE_UINT32, &g_args[5].u,
+					 RPC_TYPE_UINT32, &g_args[6].u,
+					 RPC_TYPE_UINT32, &g_args[7].u,
+					 RPC_TYPE_UINT32, &g_args[8].u,
+					 RPC_TYPE_UINT32, &g_args[9].u,
+					 RPC_TYPE_INVALID);
+
+  g_assert (g_args[0].u == 0);
+  g_assert (g_args[1].u == 1);
+  g_assert (g_args[2].u == 0xffffffff);
+  g_assert (g_args[3].u == 2);
+  g_assert (g_args[4].u == 0xfffffffe);
+  g_assert (g_args[5].u == G_MAXUINT32);
+  g_assert (g_args[6].u == G_MAXUINT32 - 1);
+  g_assert (g_args[7].u == 0x80000000);
+  g_assert (g_args[8].u == 0x80000001);
+  g_assert (g_args[9].u == 0);
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static int
+handle_VOID__UINT64x10 (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_UINT64, &g_args[0].j,
+					 RPC_TYPE_UINT64, &g_args[1].j,
+					 RPC_TYPE_UINT64, &g_args[2].j,
+					 RPC_TYPE_UINT64, &g_args[3].j,
+					 RPC_TYPE_UINT64, &g_args[4].j,
+					 RPC_TYPE_UINT64, &g_args[5].j,
+					 RPC_TYPE_UINT64, &g_args[6].j,
+					 RPC_TYPE_UINT64, &g_args[7].j,
+					 RPC_TYPE_UINT64, &g_args[8].j,
+					 RPC_TYPE_UINT64, &g_args[9].j,
+					 RPC_TYPE_INVALID);
+
+  g_assert (g_args[0].j == 0);
+  g_assert (g_args[1].j == G_GINT64_CONSTANT (0x00000000000000ffU));
+  g_assert (g_args[2].j == G_GINT64_CONSTANT (0x000000000000ff00U));
+  g_assert (g_args[3].j == G_GINT64_CONSTANT (0x0000000000ff0000U));
+  g_assert (g_args[4].j == G_GINT64_CONSTANT (0x00000000ff000000U));
+  g_assert (g_args[5].j == G_GINT64_CONSTANT (0x000000ff00000000U));
+  g_assert (g_args[6].j == G_GINT64_CONSTANT (0x0000ff0000000000U));
+  g_assert (g_args[7].j == G_GINT64_CONSTANT (0x00ff000000000000U));
+  g_assert (g_args[8].j == G_GINT64_CONSTANT (0xff00000000000000U));
+  g_assert (g_args[9].j == G_GINT64_CONSTANT (0x0123456789abcdefU));
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static int
+handle_VOID__DOUBLEx5 (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_DOUBLE, &g_args[0].d,
+					 RPC_TYPE_DOUBLE, &g_args[1].d,
+					 RPC_TYPE_DOUBLE, &g_args[2].d,
+					 RPC_TYPE_DOUBLE, &g_args[3].d,
+					 RPC_TYPE_DOUBLE, &g_args[4].d,
+					 RPC_TYPE_INVALID);
+
+  g_assert (g_args[0].d == 0.0);
+  g_assert (g_args[1].d == 1.0);
+  g_assert (g_args[2].d == -1.0);
+  g_assert (g_args[3].d == 2.0);
+  g_assert (g_args[4].d == -2.0);
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+
+static int
+handle_VOID__STRINGx3 (rpc_connection_t *connection)
+{
+  rpc_test_get_args (connection,
+					 RPC_TYPE_STRING, &g_args[0].s,
+					 RPC_TYPE_STRING, &g_args[1].s,
+					 RPC_TYPE_STRING, &g_args[2].s,
+					 RPC_TYPE_INVALID);
+
+  g_assert (g_args[0].s && strcmp (g_args[0].s, "") == 0);
+  free (g_args[0].s);
+  g_assert (g_args[1].s && strcmp (g_args[1].s, "one") == 0);
+  free (g_args[1].s);
+  g_assert (g_args[2].s == NULL);
+
+  return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
+}
+#endif
+
+int
+rpc_test_init (int argc, char *argv[])
+{
+#ifdef BUILD_SERVER
+  rpc_connection_t *connection;
+
+  static const rpc_method_descriptor_t vtable[] =
+	{
+	  { RPC_TEST_METHOD_VOID__VOID,			handle_VOID__VOID			},
+	  { RPC_TEST_METHOD_VOID__CHAR,			handle_VOID__CHAR			},
+	  { RPC_TEST_METHOD_VOID__CHARx10,		handle_VOID__CHARx10		},
+	  { RPC_TEST_METHOD_VOID__BOOL,			handle_VOID__BOOL			},
+	  { RPC_TEST_METHOD_VOID__BOOLx10,		handle_VOID__BOOLx10		},
+	  { RPC_TEST_METHOD_VOID__INT32x10,		handle_VOID__INT32x10		},
+	  { RPC_TEST_METHOD_VOID__UINT32x10,	handle_VOID__UINT32x10		},
+	  { RPC_TEST_METHOD_VOID__UINT64x10,	handle_VOID__UINT64x10		},
+	  { RPC_TEST_METHOD_VOID__DOUBLEx5,		handle_VOID__DOUBLEx5		},
+	  { RPC_TEST_METHOD_VOID__STRINGx3,		handle_VOID__STRINGx3		},
+	};
+
+  connection = rpc_test_get_connection ();
+  g_assert (connection != NULL);
+
+  if (rpc_connection_add_method_descriptors(connection,
+											vtable,
+											G_N_ELEMENTS (vtable)) < 0)
+	g_error ("could not add method descriptors");
+#endif
+
+  return 0;
+}
+
+int
+rpc_test_execute (gpointer user_data)
+{
+#ifdef BUILD_CLIENT
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__VOID,
+				   RPC_TYPE_INVALID);
+
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__CHAR,
+				   RPC_TYPE_CHAR, 'a',
+				   RPC_TYPE_INVALID);
+
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__CHARx10,
+				   RPC_TYPE_CHAR, 'a',
+				   RPC_TYPE_CHAR, 'b',
+				   RPC_TYPE_CHAR, 'c',
+				   RPC_TYPE_CHAR, 'd',
+				   RPC_TYPE_CHAR, 'e',
+				   RPC_TYPE_CHAR, '1',
+				   RPC_TYPE_CHAR, '2',
+				   RPC_TYPE_CHAR, '3',
+				   RPC_TYPE_CHAR, '4',
+				   RPC_TYPE_CHAR, '5',
+				   RPC_TYPE_INVALID);
+
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__BOOL,
+				   RPC_TYPE_BOOLEAN, TRUE,
+				   RPC_TYPE_INVALID);
+
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__BOOLx10,
+				   RPC_TYPE_BOOLEAN, TRUE,
+				   RPC_TYPE_BOOLEAN, FALSE,
+				   RPC_TYPE_BOOLEAN, TRUE,
+				   RPC_TYPE_BOOLEAN, FALSE,
+				   RPC_TYPE_BOOLEAN, TRUE,
+				   RPC_TYPE_BOOLEAN, FALSE,
+				   RPC_TYPE_BOOLEAN, TRUE,
+				   RPC_TYPE_BOOLEAN, FALSE,
+				   RPC_TYPE_BOOLEAN, TRUE,
+				   RPC_TYPE_BOOLEAN, FALSE,
+				   RPC_TYPE_INVALID);
+
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__INT32x10,
+				   RPC_TYPE_INT32, 0,
+				   RPC_TYPE_INT32, 1,
+				   RPC_TYPE_INT32, -1,
+				   RPC_TYPE_INT32, 2,
+				   RPC_TYPE_INT32, -2,
+				   RPC_TYPE_INT32, G_MAXINT32,
+				   RPC_TYPE_INT32, G_MININT32,
+				   RPC_TYPE_INT32, G_MAXINT32 - 1,
+				   RPC_TYPE_INT32, G_MININT32 + 1,
+				   RPC_TYPE_INT32, 0,
+				   RPC_TYPE_INVALID);
+
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__UINT32x10,
+				   RPC_TYPE_UINT32, 0,
+				   RPC_TYPE_UINT32, 1,
+				   RPC_TYPE_UINT32, 0xffffffff,
+				   RPC_TYPE_UINT32, 2,
+				   RPC_TYPE_UINT32, 0xfffffffe,
+				   RPC_TYPE_UINT32, G_MAXUINT32,
+				   RPC_TYPE_UINT32, G_MAXUINT32 - 1,
+				   RPC_TYPE_UINT32, 0x80000000,
+				   RPC_TYPE_UINT32, 0x80000001,
+				   RPC_TYPE_UINT32, 0,
+				   RPC_TYPE_INVALID);
+
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__UINT64x10,
+				   RPC_TYPE_UINT64, 0,
+				   RPC_TYPE_UINT64, G_GINT64_CONSTANT (0x00000000000000ffU),
+				   RPC_TYPE_UINT64, G_GINT64_CONSTANT (0x000000000000ff00U),
+				   RPC_TYPE_UINT64, G_GINT64_CONSTANT (0x0000000000ff0000U),
+				   RPC_TYPE_UINT64, G_GINT64_CONSTANT (0x00000000ff000000U),
+				   RPC_TYPE_UINT64, G_GINT64_CONSTANT (0x000000ff00000000U),
+				   RPC_TYPE_UINT64, G_GINT64_CONSTANT (0x0000ff0000000000U),
+				   RPC_TYPE_UINT64, G_GINT64_CONSTANT (0x00ff000000000000U),
+				   RPC_TYPE_UINT64, G_GINT64_CONSTANT (0xff00000000000000U),
+				   RPC_TYPE_UINT64, G_GINT64_CONSTANT (0x0123456789abcdefU),
+				   RPC_TYPE_INVALID);
+
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__DOUBLEx5,
+				   RPC_TYPE_DOUBLE, 0.0,
+				   RPC_TYPE_DOUBLE, 1.0,
+				   RPC_TYPE_DOUBLE, -1.0,
+				   RPC_TYPE_DOUBLE, 2.0,
+				   RPC_TYPE_DOUBLE, -2.0,
+				   RPC_TYPE_INVALID);
+
+  rpc_test_invoke (RPC_TEST_METHOD_VOID__STRINGx3,
+				   RPC_TYPE_STRING, "",
+				   RPC_TYPE_STRING, "one",
+				   RPC_TYPE_STRING, NULL,
+				   RPC_TYPE_INVALID);
+#endif
+  return RPC_TEST_EXECUTE_SUCCESS;
+}
diff -urN nspluginwrapper-1.1.0.orig/TODO nspluginwrapper-1.1.0/TODO
--- nspluginwrapper-1.1.0.orig/TODO	2008-07-06 16:50:10.000000000 -0400
+++ nspluginwrapper-1.1.0/TODO	2008-10-06 14:46:15.000000000 -0400
@@ -19,6 +19,7 @@
   * Split toolkit specific code (npviewer-{x11,gtk,win}.c)
   * Use winelib + override win32 socket to support AF_UNIX (Linux "native")
 - RPC
+  * RPC_MESSAGE_FAILURE handling is broken
   * Need a way to differenciate array of pointers or array of values
     => RPC_TYPE_DYNAMIC (allocate space), RPC_TYPE_STATIC (assumes data alloc'ed?)
     => Rearrange RPC message type descriptors

nspluginwrapper-1.1.0-visual-id.patch:

Index: nspluginwrapper-1.1.0-visual-id.patch
===================================================================
RCS file: /cvs/pkgs/rpms/nspluginwrapper/devel/nspluginwrapper-1.1.0-visual-id.patch,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- nspluginwrapper-1.1.0-visual-id.patch	3 Oct 2008 22:23:55 -0000	1.3
+++ nspluginwrapper-1.1.0-visual-id.patch	6 Oct 2008 21:33:35 -0000	1.4
@@ -1,13 +1,37 @@
-diff -up nspluginwrapper-1.1.0/src/npw-rpc.c.old nspluginwrapper-1.1.0/src/npw-rpc.c
---- nspluginwrapper-1.1.0/src/npw-rpc.c.old	2008-07-06 17:33:14.000000000 +0200
-+++ nspluginwrapper-1.1.0/src/npw-rpc.c	2008-08-01 20:45:33.000000000 +0200
-@@ -381,7 +381,8 @@ static int do_send_NPSetWindowCallbackSt
+2008-09-30  Gwenole Beauchesne  <gb.public at free.fr>
+
+	* src/npw-rpc (do_send_NPSetWindowCallbackStruct): Check for
+	NULL visual.
+	* src/npw-viewer.c (create_window_attributes): Get system
+	visual when we are passed a 0 visual ID.
+
+Index: src/npw-viewer.c
+===================================================================
+--- src/npw-viewer.c	(revision 645)
++++ src/npw-viewer.c	(revision 646)
+@@ -358,7 +358,11 @@
+ {
+   if (ws_info == NULL)
+ 	return -1;
+-  GdkVisual *gdk_visual = gdkx_visual_get((uintptr_t)ws_info->visual);
++  GdkVisual *gdk_visual;
++  if (ws_info->visual)
++	gdk_visual = gdkx_visual_get((uintptr_t)ws_info->visual);
++  else
++	gdk_visual = gdk_visual_get_system();
+   if (gdk_visual == NULL) {
+ 	npw_printf("ERROR: could not reconstruct XVisual from visualID\n");
+ 	return -2;
+Index: src/npw-rpc.c
+===================================================================
+--- src/npw-rpc.c	(revision 645)
++++ src/npw-rpc.c	(revision 646)
+@@ -381,7 +381,7 @@
  	  return error;
  	if ((error = rpc_message_send_int32(message, ws_info->type)) < 0)
  	  return error;
 -	if ((error = rpc_message_send_uint32(message, XVisualIDFromVisual(ws_info->visual))) < 0)
-+	uint32_t visual_id = ws_info->visual != NULL ? XVisualIDFromVisual(ws_info->visual) : 0;
-+	if ((error = rpc_message_send_uint32(message, visual_id)) < 0)
++	if ((error = rpc_message_send_uint32(message, ws_info->visual ? XVisualIDFromVisual(ws_info->visual) : 0)) < 0)
  	  return error;
  	if ((error = rpc_message_send_uint32(message, ws_info->colormap)) < 0)
  	  return error;


Index: nspluginwrapper.spec
===================================================================
RCS file: /cvs/pkgs/rpms/nspluginwrapper/devel/nspluginwrapper.spec,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -r1.60 -r1.61
--- nspluginwrapper.spec	5 Oct 2008 14:31:24 -0000	1.60
+++ nspluginwrapper.spec	6 Oct 2008 21:33:35 -0000	1.61
@@ -70,7 +70,7 @@
 Summary:	A compatibility layer for Netscape 4 plugins
 Name:		nspluginwrapper
 Version:	1.1.0
-Release:	10%{?dist}
+Release:	11%{?dist}
 Source0:	%{name}-%{version}%{?svndate:-%{svndate}}.tar.bz2
 Source1:        %{plugin_config_name}.tar.gz 
 Source2:        plugin-config.sh.in
@@ -81,6 +81,7 @@
 Patch4:         nspluginwrapper-0.9.91.5-shutdown.patch
 Patch5:         nspluginwrapper-0.9.91.5-sleep.patch
 Patch6:         nspluginwrapper-1.1.0-visual-id.patch
+Patch7:         nspluginwrapper-1.1.0-concurrent-rpc_method_invoke_rediff.patch
 Patch100:       plugin-config-setuid.patch
 License:	GPLv2+
 Group:		Networking/WWW
@@ -110,7 +111,8 @@
 %patch3 -p1 -b .fork
 %patch4 -p1 -b .shutdown
 %patch5 -p1 -b .sleep
-%patch6 -p1 -b .visual_id
+%patch6 -p0 -b .visual_id
+%patch7 -p1 -b .concurrent_rpc_method_invoke
 
 pushd %plugin_config_name
 %patch100 -p2
@@ -241,6 +243,10 @@
 %config %{_sysconfdir}/sysconfig/%{name}
 
 %changelog
+* Mon Oct 06 2008 Warren Togami <wtogami at redhat.com> 1.1.0-11
+- Unrevert patch from -7 because Warren was wrong
+- Concurrent rpc_method_invoke() patch
+
 * Fri Oct 03 2008 Warren Togami <wtogami at redhat.com> 1.1.0-10
 - Revert libcurl requires because it was done in an incorrect way
 - Revert patch from -7 because it made things worse




More information about the scm-commits mailing list