nspluginwrapper-1.1.10
Taken from Ubuntu orig.tar.gz file.
This commit is contained in:
parent
dec6139d44
commit
1f0ad8eb29
522
ChangeLog
522
ChangeLog
|
@ -1,3 +1,525 @@
|
|||
2008-12-07 22:35 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Destroy plugin window only if PluginInstance
|
||||
is finalize'd. This is because an NPPVpluginScriptableNPObject
|
||||
can still hold a reference to it (and a call to
|
||||
NPClass::Invalidate() would fail in that case).
|
||||
|
||||
2008-12-07 22:30 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime-impl.h, src/npruntime.c: Use NPW memory allocator
|
||||
for NPObjectInfo objects. Reference count PluginInstance bound
|
||||
to an NPObject if it is known at NPClass::allocate() time.
|
||||
|
||||
2008-12-07 22:02 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c, src/npw-wrapper.c: Re-add refcount debugging
|
||||
info for NPN_{Create,Retain,Release}Object().
|
||||
|
||||
2008-12-07 21:48 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Remove delayed NPN_InvalidateRect() code as
|
||||
it's no longer necessary with RPC synchronous messaging.
|
||||
|
||||
2008-12-07 19:25 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Make NPN_ReleaseObject() use
|
||||
rpc_method_invoke_possible() to check whether we can send it
|
||||
immediately. This detects the case where a call is made after
|
||||
rpc_method_send_reply() but before we return from the
|
||||
rpc_dispatch() handler.
|
||||
|
||||
2008-12-07 19:22 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/rpc.c, src/rpc.h: Implement synchronous messaging. aka turns
|
||||
an async call (i.e. an rpc_method_invoke() with a connection in
|
||||
server mode) into a synchronous one. That way, the browser is
|
||||
notified that the plugin wants to make a call and then puts self
|
||||
into condition to receive the message (normal rpc_dispatch() or
|
||||
at the end of a toplevel NPP_*() function).
|
||||
|
||||
This makes it RPC protocol v2.6.
|
||||
|
||||
2008-12-07 15:30 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* tests/test-rpc-concurrent.c: Improve concurrent test to check we
|
||||
get the right answers (in case nested handling got wrong).
|
||||
Besides, make sure the client waits for all server's incoming
|
||||
calls prior to rpc_test_exit()'ing.
|
||||
|
||||
2008-12-07 15:24 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* tests/test-rpc-common.c: Make sure to handle RPC on both ends,
|
||||
including the client's side.
|
||||
|
||||
2008-12-07 08:12 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Fix NPP_HandleEvent() return value on error.
|
||||
|
||||
2008-12-07 08:10 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c, src/npw-viewer.c, src/npw-wrapper.c: Add checks
|
||||
for all rpc_method_invoke() functions.
|
||||
|
||||
2008-12-07 08:06 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/debug.h: Add npw_return_if_fail() and
|
||||
npw_return_val_if_fail() helpers.
|
||||
|
||||
2008-12-07 07:16 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/rpc.c, src/rpc.h, tests/test-rpc-nested-2.c: Add
|
||||
rpc_method_invoke_possible() interface to check whether we are
|
||||
ready to call rpc_method_invoke() or not. i.e. in particular, if
|
||||
we are not trying to invoke functions after
|
||||
rpc_method_send_reply() and before we return from an RPC method
|
||||
handler.
|
||||
|
||||
2008-12-06 18:21 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* tests/test-rpc-common.c, tests/test-rpc-concurrent.c,
|
||||
tests/test-rpc-nested-1.c, tests/test-rpc-types.c: Use helpers.
|
||||
In particular, don't use g_assert() but rather RPC_TEST_ENSURE()
|
||||
or RPC_TEST_ENSURE_NO_ERROR() which always evaluate.
|
||||
|
||||
2008-12-06 18:13 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* Makefile, tests/test-rpc-nested-2.c: Add another testcase for
|
||||
nested rpc_method_invoke(). This time, we are also emitting a
|
||||
call just after an rpc_method_send_reply(). Note: this is not
|
||||
fixed yet.
|
||||
|
||||
2008-12-06 18:11 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* tests/test-rpc-common.h: Add helpers.
|
||||
|
||||
2008-12-06 18:10 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* Makefile, tests/test-rpc-nested-1.c, tests/test-rpc-nested.c:
|
||||
Rename.
|
||||
|
||||
2008-12-06 09:08 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Rework the XEMBED hack. Don't let the browser
|
||||
cause Gtk to kill our window. i.e. don't process WM_DELETE_EVENT
|
||||
sent by the browser GtkSocket. That way, we will kill the window
|
||||
ourselves in NPP_Destroy().
|
||||
|
||||
2008-12-04 21:31 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Process delayed calls in NPP_Destroy() only if
|
||||
PluginInstances match. Besides, don't care about pending
|
||||
NPN_InvalidateRect() requests if we already know the instance
|
||||
will pass away soon (i.e. we are in NPP_Destroy()).
|
||||
|
||||
2008-12-03 22:56 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Delay all NPN_InvalidateRect() messages. An
|
||||
intermediate solution may be to delay the messages only if there
|
||||
is actually incoming RPC. Postpone this optimization for a
|
||||
future version (and smarter strategy to "compress" the
|
||||
region/requests).
|
||||
|
||||
2008-12-03 20:51 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime-impl.h, src/npruntime.c: Add debug messages for
|
||||
NPClass::invoke_*() functions.
|
||||
|
||||
2008-12-02 21:49 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c, src/npw-wrapper.c: Fix invalid RPC beyond
|
||||
NPP_Destroy(). This fixes the following scenario:
|
||||
|
||||
Browser: NPP_Destroy()
|
||||
-> rpc_method_invoke()
|
||||
Viewer: NPN_InvalidateRect()
|
||||
-> rpc_method_invoke()
|
||||
-> rpc_dispatch() pending messages
|
||||
-> handle_NPP_Destroy()
|
||||
-> PluginInstance is killed
|
||||
-> send PluginInstance but it was killed...
|
||||
|
||||
Now, with the help of reference counting, we can hold the
|
||||
PluginInstance. Besides, NPP_Destroy() will reset instance_id,
|
||||
thus RPC won't be sending a "valid" PluginInstance to the other
|
||||
side, thus reducing the other side call to a no-op. i.e. don't
|
||||
try to do anything with the browser NPP instance that was killed
|
||||
previously (the NPP_Destroy() call would have completed by the
|
||||
time the browser-side needs to handle incoming RPC).
|
||||
|
||||
2008-12-02 21:00 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Preserve PluginInstance objects during
|
||||
invoke_NPN_*() function calls. This is because
|
||||
rpc_method_invoke() can handle pending messages, among which an
|
||||
NPP_Destroy() is possible. Since the latter unref the
|
||||
PluginInstance, we could arrive in a situation where we are
|
||||
dereferencing deallocated data.
|
||||
|
||||
2008-12-02 20:44 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-common.h, src/npw-viewer.c, src/npw-wrapper.c: Replace
|
||||
all RPC_TYPE_NPP with RPC_TYPE_NPW_PLUGIN_INSTANCE.
|
||||
|
||||
2008-12-02 20:15 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-rpc.c, src/npw-rpc.h: Add RPC_TYPE_NPW_PLUGIN_INSTANCE
|
||||
to marshal PluginInstance objects.
|
||||
|
||||
2008-12-01 23:01 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Pass PluginInstance to invoke_NP*() functions.
|
||||
The next step is to replace RPC_TYPE_NPP with
|
||||
RPC_TYPE_NPW_PLUGIN_INSTANCE.
|
||||
|
||||
2008-12-01 21:55 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c, src/npw-wrapper.c: Minor cleanups. Make sure
|
||||
plugin->instance is NULL on exit from NPP_Destroy().
|
||||
|
||||
2008-12-01 21:47 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-common.h: Remove extraneous "extern" linkage keyword,
|
||||
this is default behaviour.
|
||||
|
||||
2008-12-01 21:46 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-common.c, src/npw-common.h, src/npw-viewer.c,
|
||||
src/npw-wrapper.c: Add infrastructure to refcount PlugInstances.
|
||||
|
||||
2008-12-01 20:28 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* configure, src/npruntime.c, src/npw-viewer.c: Disable PID check,
|
||||
this is not really useful unless a plugin does fork() without
|
||||
exec(). This could be reactivated with --enable-pid-check though.
|
||||
|
||||
2008-12-01 20:06 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Fix pid_check() for USE_PID_CHECK == 0 (thanks
|
||||
Martin Stransky).
|
||||
|
||||
2008-12-01 20:03 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* nspluginwrapper.spec: Bump release for development.
|
||||
|
||||
2008-11-30 23:03 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* ChangeLog: Generated by svn2cl.
|
||||
|
||||
2008-11-30 23:00 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Drop use of "extern inline" as some (older)
|
||||
compilers don't support ISO C semantics.
|
||||
|
||||
2008-11-30 22:54 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* NEWS, nspluginwrapper.spec: Updates for 1.1.8.
|
||||
|
||||
2008-11-30 22:39 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Process all pending calls in NPP_Destroy() as
|
||||
the data could become junk afterwards.
|
||||
|
||||
2008-11-30 22:34 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Don't delay call to NPN_ReleaseObject() if we
|
||||
can handle it now.
|
||||
|
||||
2008-11-30 21:52 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/rpc.c: Add rpc_method_*_valist() variants, internal only for
|
||||
now.
|
||||
|
||||
2008-11-30 21:24 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Slightly improved delayed call mechanism. This
|
||||
is not fully satisfying yet as I believe a pipe should be better
|
||||
(glib GSource creation is slow). Fortunately, there doesn't seem
|
||||
to be that many calls to NPN_ReleaseObject().
|
||||
|
||||
2008-11-30 21:07 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-malloc.h: Fix typo.
|
||||
|
||||
2008-11-30 20:47 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c, src/npw-viewer.c: Delay calls to
|
||||
NPN_ReleaseObject. Revert:
|
||||
|
||||
2008-11-22 10:43 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Fix NPN_ReleaseObject() reply, i.e. don't
|
||||
dereference npobj after the real call to NPN handler as it could
|
||||
be deallocated.
|
||||
|
||||
2008-11-30 17:38 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c, src/npw-viewer.c, src/npw-wrapper.c: Add
|
||||
missing debugging messages.
|
||||
|
||||
2008-11-30 17:21 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c: Fix pid_check() for the browser-side
|
||||
implementation.
|
||||
|
||||
2008-11-30 17:14 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c, src/npw-viewer.c: Extend PID check to npruntime
|
||||
bridge.
|
||||
|
||||
2008-11-30 15:52 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* lsb-build/stub_libs/libc_main.c: Add dirfd() for
|
||||
npw_close_all_open_files().
|
||||
|
||||
2008-11-30 15:47 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Check that processes fork()'ed off
|
||||
npviewer.bin don't issue RPC calls. Initial patch by Martin
|
||||
Stransky.
|
||||
|
||||
2008-11-30 14:56 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c: Rename is_npclass_valid() to
|
||||
is_valid_npobject_class().
|
||||
|
||||
2008-11-30 14:50 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c, src/npw-wrapper.c: Remove wrong comment. The
|
||||
errors previously noticed were due to the fact that NPObjects
|
||||
were looked up in the wrong (previously deallocated) hash table.
|
||||
We now preserve that hash table.
|
||||
|
||||
2008-11-30 14:33 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Likewise for npobject_bridge_destroy().
|
||||
|
||||
2008-11-30 14:18 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Move id_init() into NP_Initialize(), likewise
|
||||
for id_kill() into NP_Shutdown(). Those functions are guaranteed
|
||||
to be called only once. g_NP_Initialize() and g_NP_Shutdown()
|
||||
could be called several times for the restart machinery but we
|
||||
don't want to clobber with IDs generated previously.
|
||||
|
||||
2008-11-30 13:17 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Kill viewer if the parent browser died (Martin
|
||||
Stransky).
|
||||
|
||||
2008-11-30 13:08 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c, src/npw-wrapper.c: Use
|
||||
rpc_connection_set_error_callback() to detect and handle an RPC
|
||||
connection loss (Martin Stransky). In that case, all NPObjects
|
||||
are invalidated. XXX: this is too global.
|
||||
|
||||
2008-11-30 12:10 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime-impl.h, src/npruntime.c: Add a mechanism to stop
|
||||
calls to NPClass functions if the other end died. We get
|
||||
notified of this situation through npruntime_deactivate().
|
||||
Initial patch by Martin Stransky.
|
||||
|
||||
2008-11-30 11:09 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/rpc.c, src/rpc.h: Introduce
|
||||
rpc_connection_set_error_callback() to register a callback for
|
||||
RPC errors (Martin Stransky).
|
||||
|
||||
2008-11-30 10:41 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Warn out when we explicitly don't support
|
||||
specific variables for XPCOM in NPN_GetValue() (Martin Stransky).
|
||||
|
||||
2008-11-30 09:18 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/rpc.c: Add SOCK_CLOEXEC to socket() flags. This is a Linux
|
||||
>= 2.6.27 extension.
|
||||
|
||||
2008-11-30 09:01 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c, src/utils.c, src/utils.h: Close all open
|
||||
files on fork(). Initial patch by Dan Walsh.
|
||||
|
||||
2008-11-29 14:49 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* utils/npw-shadow.c: Nuke dead file.
|
||||
|
||||
2008-11-29 14:47 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Make it possible to execute native plugins
|
||||
directly (i.e. without npviewer.bin) if either "NPW_DIRECT_EXEC"
|
||||
or "NPW_DIRECT_EXECUTION" environment variable is set.
|
||||
|
||||
2008-11-29 14:03 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/utils.c: Fix id_init() to create a new hash if it does not
|
||||
exist already.
|
||||
|
||||
2008-11-25 22:11 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.sh: Make `which' failures silent for
|
||||
soudwrappers. It's also correct to work without a soundwrapper
|
||||
if the audio device is correctly multiplexed (Stanislav Brabec).
|
||||
|
||||
2008-11-25 21:20 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* nspluginwrapper.spec: Bump release for development.
|
||||
|
||||
2008-11-24 18:35 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* NEWS: Fix typo.
|
||||
|
||||
2008-11-23 21:57 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* ChangeLog: Generated by svn2cl.
|
||||
|
||||
2008-11-23 06:43 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Fix a warning (enumeration value not handled
|
||||
in switch).
|
||||
|
||||
2008-11-23 06:39 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* NEWS, nspluginwrapper.spec: Updates for 1.1.6.
|
||||
* README: Fix typos and mention trademark as there are commercial
|
||||
interests (and be on the safe side).
|
||||
|
||||
2008-11-22 15:33 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* ChangeLog: Generated by svn2cl.
|
||||
|
||||
2008-11-22 15:20 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c: Fix string_of_NPVariant() for NULL arguments.
|
||||
|
||||
2008-11-22 15:04 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c: Release args variants prior to calling
|
||||
rpc_method_send_reply().
|
||||
|
||||
2008-11-22 13:49 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c, src/npw-wrapper.c, src/utils.c, src/utils.h:
|
||||
Improve debug info for NP[PN]_[SG]etValue().
|
||||
|
||||
2008-11-22 13:23 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Fix debug message in NPN_Write().
|
||||
|
||||
2008-11-22 10:52 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Fix memory leak in NPN_GetStringIdentifiers()
|
||||
RPC handler.
|
||||
|
||||
2008-11-22 10:50 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-malloc.h: Add NPW_MemNew() and NPW_MemNew0() helpers.
|
||||
|
||||
2008-11-22 10:43 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Fix NPN_ReleaseObject() reply, i.e. don't
|
||||
dereference npobj after the real call to NPN handler as it could
|
||||
be deallocated.
|
||||
|
||||
2008-11-22 10:01 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/debug.c, src/debug.h, src/npruntime.c, src/npw-viewer.c,
|
||||
src/npw-wrapper.c: Indent debugging messages.
|
||||
|
||||
2008-11-22 08:54 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c, src/npw-viewer.c, src/npw-wrapper.c: Improve
|
||||
debugging messages. Nested invocations could confuse what the
|
||||
return value actually refers to.
|
||||
|
||||
2008-11-22 07:54 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-rpc.c: Don't make the sync message a WARNING.
|
||||
|
||||
2008-11-22 07:52 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-rpc.c: Always synchronize NPObject::referenceCount in
|
||||
case the plugin wants to inspect that. Synchronization through
|
||||
NPN_RetainObject()/NPN_ReleaseObject() should be enough though.
|
||||
|
||||
2008-11-22 07:37 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Fix plugin window resize in XEMBED hack mode.
|
||||
|
||||
2008-11-17 21:55 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* tests/test-plugins.html: Newer demo for the SqueakVM plugin.
|
||||
|
||||
2008-11-17 21:40 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c, src/npw-wrapper.c: Lower priority of RPC
|
||||
handlers.
|
||||
|
||||
2008-11-15 21:50 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-player.c: Fix for "javascript:" requests. Don't make
|
||||
them fail because we are starting those streams manually.
|
||||
|
||||
2008-11-15 21:45 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-common.h: Fix npw_get_stream_instance().
|
||||
|
||||
2008-11-09 17:02 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Update NPP_Write() comment for negative array
|
||||
lengths.
|
||||
|
||||
2008-11-09 16:56 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Propagate NPP_Write() with negative lengths
|
||||
since the plugin may want to handle that case (e.g. close a
|
||||
stream?). In practise, this doesn't make much sense either.
|
||||
NPAPI specs need to be updated to mean "close the stream" if
|
||||
NPP_WriteReady() returns a negative value.
|
||||
|
||||
2008-11-09 16:46 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/rpc.c, tests/test-rpc-types.c: Actually, since an array of
|
||||
negative size doesn't make sense, let it be the responsibility
|
||||
of the caller to check for bounds.
|
||||
|
||||
2008-11-09 16:38 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/rpc.c, tests/test-rpc-types.c: Size of the array to
|
||||
RPC_TYPE_ARRAY argument is now an int32. Allow for NULL arrays
|
||||
or arrays of negative length. In that case, the returned array
|
||||
pointer in the other size is NULL.
|
||||
|
||||
2008-11-09 15:26 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* tests/test-rpc-types.c: Add tests for arrays. Fix
|
||||
rpc_test_signature() for arrays.
|
||||
|
||||
2008-11-09 15:24 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/rpc.c: Allow arrays of uint64 or double.
|
||||
|
||||
2008-11-09 14:29 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* tests/test-rpc-common.c, tests/test-rpc-common.h,
|
||||
tests/test-rpc-concurrent.c, tests/test-rpc-nested.c,
|
||||
tests/test-rpc-types.c: Fix indentation (8-char tabs, not 4).
|
||||
|
||||
2008-11-09 14:18 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* configure: Enable glib memory hooks by default if not
|
||||
configuring with --enable-generic.
|
||||
|
||||
2008-11-09 14:13 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* nspluginwrapper.spec: Bump version for development.
|
||||
|
||||
2008-11-06 22:36 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* ChangeLog: Generated by svn2cl.
|
||||
|
||||
2008-11-06 22:28 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* NEWS, README, nspluginwrapper.spec: Updates for 1.1.4.
|
||||
|
|
6
Makefile
6
Makefile
|
@ -193,7 +193,11 @@ test_rpc_client_CPPFLAGS = $(CPPFLAGS) -I$(SRC_PATH)/src -DBUILD_CLIENT -DNPW_CO
|
|||
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) $(libsocket_LDFLAGS)
|
||||
test_rpc_RAWPROGS = test-rpc-types test-rpc-nested test-rpc-concurrent
|
||||
test_rpc_RAWPROGS = \
|
||||
test-rpc-types \
|
||||
test-rpc-nested-1 \
|
||||
test-rpc-nested-2 \
|
||||
test-rpc-concurrent
|
||||
test_rpc_PROGRAMS = \
|
||||
$(test_rpc_RAWPROGS:%=%-client) \
|
||||
$(test_rpc_RAWPROGS:%=%-server)
|
||||
|
|
29
NEWS
29
NEWS
|
@ -1,6 +1,33 @@
|
|||
nspluginwrapper NEWS -- history of user-visible changes. 2008-11-07
|
||||
nspluginwrapper NEWS -- history of user-visible changes. 2008-12-08
|
||||
Copyright (C) 2005-2008 Gwenole Beauchesne
|
||||
|
||||
Version 1.1.10 (BETA) - 08.Dec.2008
|
||||
* Fix NPPVpluginScriptableNPObject::Invalidate()
|
||||
* Fix condition for delayed NPN_ReleaseObject() call
|
||||
* Fix XEMBED (rework for lost events/focus regressions)
|
||||
* Fix RPC for calls initiated by the plugin (SYNC mode)
|
||||
* Fix invalid RPC after the plugin was NPP_Destroy()'ed
|
||||
|
||||
Version 1.1.8 (BETA) - 01.Dec.2008
|
||||
* Delay NPN_ReleaseObject() if there is incoming RPC
|
||||
* Improve plugins restart machinery (Martin Stransky)
|
||||
* Close npviewer.bin sockets on exec()
|
||||
* Close all open files on fork() (initial patch by Dan Walsh)
|
||||
* Make `which` failures silent for soundwrappers (Stanislav Brabec)
|
||||
* Allow direct execution of native plugins if NPW_DIRECT_EXEC is set
|
||||
|
||||
Version 1.1.6 (BETA) - 23.Nov.2008
|
||||
* Enable glib memory hooks by default
|
||||
* Lower priority of RPC events so that timeouts are triggered first
|
||||
* Fix string_of_NPVariant() that could make some plugins crash
|
||||
* Fix NPClass::Invoke(|Default)() args release
|
||||
* Fix memory leak in NPN_GetStringIdentifiers()
|
||||
* Fix NPN_ReleaseObject() that could dereference a deallocated NPObject
|
||||
* Fix (sync) NPObject referenceCount when the object is passed to the plugin
|
||||
* Fix plugin window resize in XEMBED hack mode
|
||||
* Fix "javascript:" streams requests in standalone player
|
||||
* Fix NPP_Write() and propagate negative lengths too (DiamondX plugin)
|
||||
|
||||
Version 1.1.4 (BETA) - 07.Nov.2008
|
||||
* Fix memory leaks in NPRuntime bridge
|
||||
* Fix XEMBED support (workaround Gtk2 and Firefox bugs)
|
||||
|
|
11
README
11
README
|
@ -11,6 +11,8 @@ License
|
|||
nspluginwrapper is available under the terms of the GNU General Public License.
|
||||
See the file "COPYING" that is included in the distribution for details.
|
||||
|
||||
nspluginwrapper is a trademark of Gwenole Beauchesne.
|
||||
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
@ -21,7 +23,7 @@ like Adobe Flash Player on other platforms like Linux/x86_64, *BSD and
|
|||
even Linux/ppc.
|
||||
|
||||
nspluginwrapper also provides a standalone plugins player. This
|
||||
programs makes it possible to execute plugins without an actual
|
||||
program makes it possible to execute plugins without an actual
|
||||
browser.
|
||||
|
||||
|
||||
|
@ -39,10 +41,11 @@ $ make
|
|||
Or, if you prefer from a source package:
|
||||
$ rpm --rebuild nspluginwrapper.src.rpm
|
||||
|
||||
NOTE: if you are building the Linux viewer to use on a non-Linux
|
||||
NOTE: if you are building the Linux viewer for use on a non-Linux
|
||||
system (e.g. NetBSD, FreeBSD), you will have to configure the Linux
|
||||
build with the --enable-generic option. That way, named sockets will be
|
||||
used and work under the Linux emulation on those operating systems.
|
||||
build with the --enable-generic option. That way, named sockets will
|
||||
be used and work under the Linux emulation layer on those operating
|
||||
systems.
|
||||
|
||||
|
||||
Requirements and Installation
|
||||
|
|
|
@ -36,7 +36,8 @@ host_cpu=`uname -m`
|
|||
target_os="linux"
|
||||
target_cpu="i386"
|
||||
rpc_init_timeout=5
|
||||
malloc_hooks="libc,glib"
|
||||
malloc_hooks="glib,libc"
|
||||
use_pid_check="no"
|
||||
case "$host_cpu" in
|
||||
arm*)
|
||||
host_cpu="arm"
|
||||
|
@ -124,6 +125,12 @@ case "$opt" in
|
|||
--disable-player)
|
||||
build_player="no"
|
||||
;;
|
||||
--enable-pid-check)
|
||||
use_pid_check="yes"
|
||||
;;
|
||||
--disable-pid-check)
|
||||
use_pid_check="no"
|
||||
;;
|
||||
--with-lib32=*)
|
||||
lib32=`echo "$opt" | cut -d '=' -f 2`
|
||||
;;
|
||||
|
@ -139,12 +146,12 @@ case "$opt" in
|
|||
--with-cxx=*)
|
||||
cxx=`echo "$opt" | cut -d '=' -f 2`
|
||||
;;
|
||||
--with-malloc=*)
|
||||
malloc_hooks=`echo "$opt" | cut -d '=' -f 2`
|
||||
;;
|
||||
--rpc-init-timeout=*)
|
||||
rpc_init_timeout=`echo "$opt" | cut -d '=' -f 2`
|
||||
;;
|
||||
--with-malloc=*)
|
||||
malloc_hooks=`echo "$opt" | cut -d '=' -f 2`
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
@ -580,10 +587,12 @@ for mh in $malloc_hooks_list; do
|
|||
is_ok="yes"
|
||||
;;
|
||||
glib)
|
||||
if $pkgconfig --atleast-version=2.10 glib-2.0; then
|
||||
is_ok="yes"
|
||||
else
|
||||
if test "x$linux_only" = "xno"; then
|
||||
echo "WARNING: disabling glib memory hooks with --enable-generic"
|
||||
elif ! $pkgconfig --atleast-version=2.10 glib-2.0; then
|
||||
echo "WARNING: disabling glib memory hooks that require glib >= 2.10 (system is $GLIB_VERSION)"
|
||||
else
|
||||
is_ok="yes"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
@ -596,6 +605,10 @@ for mh in $malloc_hooks_list; do
|
|||
fi
|
||||
fi
|
||||
done
|
||||
if test -z "$malloc_hooks"; then
|
||||
malloc_hook_default="libc"
|
||||
malloc_hooks="$malloc_hook_default"
|
||||
fi
|
||||
|
||||
# print configure help
|
||||
if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
|
||||
|
@ -619,13 +632,14 @@ echo " --source-path=PATH path of source code [$source_path]"
|
|||
echo " --enable-strip strip resulting binaries and libraries [$strip]"
|
||||
echo " --enable-generic don't use system-specific additions"
|
||||
echo " --enable-biarch build both 32-bit and 64-bit components at once"
|
||||
echo " --enable-pid-check enable PID check (DEBUG) [$use_pid_check]"
|
||||
echo " --with-lib32=NAME use NAME as the 32-bit library dir name [$lib32]"
|
||||
echo " --with-lib64=NAME use NAME as the 64-bit library dir name [$lib64]"
|
||||
echo " --with-x11-prefix=PREFIX use PREFIX as the X11 base dir [autodetect]"
|
||||
echo " --with-cc=CC use C compiler CC [$cc]"
|
||||
echo " --with-cxx=CXX use C++ compiler CXX [$cxx]"
|
||||
echo " --rpc-init-timeout=VALUE wait VALUE seconds for the plugin to connect [$rpc_init_timeout]"
|
||||
echo " --with-malloc=MALLOC use MALLOC for memory allocation hooks [$malloc_hooks]"
|
||||
echo " --rpc-init-timeout=VALUE wait VALUE seconds for the plugin to connect [$rpc_init_timeout]"
|
||||
echo ""
|
||||
echo "NOTE: The object files are built at the place where configure is launched"
|
||||
exit 1
|
||||
|
@ -643,13 +657,14 @@ echo "64-bit library dir name $lib64"
|
|||
echo "Source path $source_path"
|
||||
echo "C compiler $cc"
|
||||
echo "C++ compiler $cxx"
|
||||
echo "host OS $host_os"
|
||||
echo "host CPU $host_cpu"
|
||||
echo "host big endian $bigendian"
|
||||
echo "target OS $target_os"
|
||||
echo "target CPU $target_cpu"
|
||||
echo "rpc init timeout $rpc_init_timeout secs"
|
||||
echo "Host OS $host_os"
|
||||
echo "Host CPU $host_cpu"
|
||||
echo "Host big endian $bigendian"
|
||||
echo "Target OS $target_os"
|
||||
echo "Target CPU $target_cpu"
|
||||
echo "RPC init timeout $rpc_init_timeout secs"
|
||||
echo "Memory allocation hooks $malloc_hooks"
|
||||
echo "Use PID check (DEBUG) $use_pid_check"
|
||||
|
||||
config_mak="config-host.mak"
|
||||
echo "# Automatically generated by configure - do not modify" > $config_mak
|
||||
|
@ -808,6 +823,11 @@ if test "$libc_provides_ssp" = "yes"; then
|
|||
else
|
||||
echo "#undef TARGET_LIBC_PROVIDES_SSP" >> $config_h
|
||||
fi
|
||||
if test "$use_pid_check" = "yes"; then
|
||||
echo "#define USE_PID_CHECK 1" >> $config_h
|
||||
else
|
||||
echo "#define USE_PID_CHECK 0" >> $config_h
|
||||
fi
|
||||
|
||||
config_mak="config.mak"
|
||||
echo "# Automatically generated by configure - do not modify" > $config_mak
|
||||
|
|
|
@ -130,6 +130,7 @@ void dcgettext() {} ;
|
|||
void dcngettext() {} ;
|
||||
void dgettext() {} ;
|
||||
void difftime() {} ;
|
||||
void dirfd() {} ;
|
||||
void dirname() {} ;
|
||||
void div() {} ;
|
||||
void dngettext() {} ;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%define name nspluginwrapper
|
||||
%define version 1.1.4
|
||||
%define version 1.1.10
|
||||
%define release 1
|
||||
#define svndate 20081106
|
||||
#define svndate DATE
|
||||
|
||||
# define 32-bit arch of multiarch platforms
|
||||
%define arch_32 %{nil}
|
||||
|
@ -192,6 +192,33 @@ fi
|
|||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon Dec 08 2008 Gwenole Beauchesne <gb.public@free.fr> 1.1.10-1
|
||||
- fix NPPVpluginScriptableNPObject::Invalidate()
|
||||
- fix condition for delayed NPN_ReleaseObject() call
|
||||
- fix XEMBED (rework for lost events/focus regressions)
|
||||
- fix RPC for calls initiated by the plugin (SYNC mode)
|
||||
- fix invalid RPC after the plugin was NPP_Destroy()'ed
|
||||
|
||||
* Mon Dec 01 2008 Gwenole Beauchesne <gb.public@free.fr> 1.1.8-1
|
||||
- delay NPN_ReleaseObject() if there is incoming RPC
|
||||
- improve plugins restart machinery (Martin Stransky)
|
||||
- close npviewer.bin sockets on exec()
|
||||
- close all open files on fork() (initial patch by Dan Walsh)
|
||||
- make `which` failures silent for soundwrappers (Stanislav Brabec)
|
||||
- allow direct execution of native plugins if NPW_DIRECT_EXEC is set
|
||||
|
||||
* Thu Nov 23 2008 Gwenole Beauchesne <gb.public@free.fr> 1.1.6-1
|
||||
- enable glib memory hooks by default
|
||||
- lower priority of RPC events so that timeouts are triggered first
|
||||
- fix string_of_NPVariant() that could make some plugins crash
|
||||
- fix args release in NPClass::Invoke(|Default)()
|
||||
- fix memory leak in NPN_GetStringIdentifiers()
|
||||
- fix NPN_ReleaseObject() that could dereference a deallocated NPObject
|
||||
- fix (sync) NPObject referenceCount when the object is passed to the plugin
|
||||
- fix plugin window resize in XEMBED hack mode
|
||||
- fix "javascript:" streams requests in standalone player
|
||||
- fix NPP_Write() and propage negative lengths too (DiamondX plugin)
|
||||
|
||||
* Thu Nov 6 2008 Gwenole Beauchesne <gb.public@free.fr> 1.1.4-1
|
||||
- fix memory leaks in NPRuntime bridge
|
||||
- fix XEMBED support (workaround Gtk2 and Firefox bugs)
|
||||
|
|
91
src/debug.c
91
src/debug.c
|
@ -29,22 +29,61 @@
|
|||
#include "debug.h"
|
||||
|
||||
|
||||
static int g_debug_level = -1;
|
||||
static int g_indent_level = 0;
|
||||
|
||||
void npw_indent(int inc)
|
||||
{
|
||||
g_indent_level += inc;
|
||||
}
|
||||
|
||||
static int _can_indent_messages(void)
|
||||
{
|
||||
const char *indent_str = getenv("NPW_INDENT_MESSAGES");
|
||||
if (indent_str) {
|
||||
// XXX: also check for "yes", "no", "true", "false"
|
||||
errno = 0;
|
||||
long v = strtol(indent_str, NULL, 10);
|
||||
if ((v != LONG_MIN && v != LONG_MAX) || errno != ERANGE)
|
||||
return v;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int get_indent_level(void)
|
||||
{
|
||||
static int can_indent_messages = -1;
|
||||
if (can_indent_messages < 0)
|
||||
can_indent_messages = _can_indent_messages();
|
||||
if (can_indent_messages)
|
||||
return g_indent_level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int _get_debug_level(void)
|
||||
{
|
||||
const char *debug_str = getenv("NPW_DEBUG");
|
||||
if (debug_str) {
|
||||
errno = 0;
|
||||
long v = strtol(debug_str, NULL, 10);
|
||||
if ((v != LONG_MIN && v != LONG_MAX) || errno != ERANGE)
|
||||
return v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int get_debug_level(void)
|
||||
{
|
||||
static int g_debug_level = -1;
|
||||
if (g_debug_level < 0)
|
||||
g_debug_level = _get_debug_level();
|
||||
return g_debug_level;
|
||||
}
|
||||
|
||||
|
||||
void npw_dprintf(const char *format, ...)
|
||||
{
|
||||
if (g_debug_level < 0) {
|
||||
g_debug_level = 0;
|
||||
const char *debug_str = getenv("NPW_DEBUG");
|
||||
if (debug_str) {
|
||||
errno = 0;
|
||||
long v = strtol(debug_str, NULL, 10);
|
||||
if ((v != LONG_MIN && v != LONG_MAX) || errno != ERANGE)
|
||||
g_debug_level = v;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_debug_level > 0) {
|
||||
if (get_debug_level() > 0) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
npw_vprintf(format, args);
|
||||
|
@ -52,6 +91,20 @@ void npw_dprintf(const char *format, ...)
|
|||
}
|
||||
}
|
||||
|
||||
void npw_idprintf(int inc, const char *format, ...)
|
||||
{
|
||||
if (get_debug_level() > 0) {
|
||||
if (inc < 0)
|
||||
npw_indent(inc);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
npw_vprintf(format, args);
|
||||
va_end(args);
|
||||
if (inc > 0)
|
||||
npw_indent(inc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static FILE *g_log_file = NULL;
|
||||
|
||||
|
@ -85,10 +138,22 @@ static void __attribute__((destructor)) log_file_sentinel(void)
|
|||
}
|
||||
|
||||
|
||||
void npw_print_indent(FILE *fp)
|
||||
{
|
||||
static const char blanks[] = " ";
|
||||
const int blanks_length = sizeof(blanks) - 1;
|
||||
int n_blanks = 2 * get_indent_level();
|
||||
for (int i = 0; i < n_blanks / blanks_length; i++)
|
||||
fwrite(blanks, blanks_length, 1, fp);
|
||||
if ((n_blanks = (n_blanks % blanks_length)) > 0)
|
||||
fwrite(blanks, n_blanks, 1, fp);
|
||||
}
|
||||
|
||||
void npw_vprintf(const char *format, va_list args)
|
||||
{
|
||||
FILE *log_file = npw_log_file();
|
||||
fprintf(log_file, "*** NSPlugin %s *** ", NPW_COMPONENT_NAME);
|
||||
npw_print_indent(log_file);
|
||||
vfprintf(log_file, format, args);
|
||||
fflush(log_file);
|
||||
}
|
||||
|
|
32
src/debug.h
32
src/debug.h
|
@ -29,6 +29,9 @@ extern "C" {
|
|||
|
||||
extern void npw_dprintf(const char *format, ...) attribute_hidden;
|
||||
|
||||
extern void npw_indent(int inc) attribute_hidden;
|
||||
extern void npw_idprintf(int inc, const char *format, ...) attribute_hidden;
|
||||
|
||||
extern void npw_printf(const char *format, ...) attribute_hidden;
|
||||
extern void npw_vprintf(const char *format, va_list args) attribute_hidden;
|
||||
|
||||
|
@ -37,14 +40,43 @@ extern void npw_vprintf(const char *format, va_list args) attribute_hidden;
|
|||
# if 0 && (defined(__GNUC__) && (__GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ == 96)))
|
||||
# define bug(format, ...) \
|
||||
npw_dprintf("[%-20s:%4d] " format, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
# define bugiI(format, ...) \
|
||||
npw_idprintf(+1, "[%-20s:%4d] " format, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
# define bugiD(format, ...) \
|
||||
npw_idprintf(-1, "[%-20s:%4d] " format, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
# else
|
||||
# define bug npw_dprintf
|
||||
# define bugiI(...) npw_idprintf(+1, __VA_ARGS__)
|
||||
# define bugiD(...) npw_idprintf(-1, __VA_ARGS__)
|
||||
# endif
|
||||
# define D(x) x
|
||||
#else
|
||||
# define D(x) ;
|
||||
#endif
|
||||
|
||||
/* XXX: add an ENABLE_CHECKS config option? */
|
||||
#if DEBUG
|
||||
# define npw_return_if_fail_warning(expr_str) do { \
|
||||
npw_printf("WARNING:(%s:%d):%s: assertion failed: (%s)\n", \
|
||||
__FILE__, __LINE__, __func__, expr_str); \
|
||||
} while (0)
|
||||
# define npw_return_if_fail(expr) do { \
|
||||
if (!(expr)) { \
|
||||
npw_return_if_fail_warning(#expr); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
# define npw_return_val_if_fail(expr, val) do { \
|
||||
if (!(expr)) { \
|
||||
npw_return_if_fail_warning(#expr); \
|
||||
return (val); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
# define npw_return_if_fail(expr, val) do {} while (0)
|
||||
# define npw_return_val_if_fail(expr, val) do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
typedef struct {
|
||||
NPObject *npobj;
|
||||
uint32_t npobj_id;
|
||||
bool is_valid;
|
||||
void *plugin;
|
||||
} NPObjectInfo;
|
||||
|
||||
extern NPObjectInfo *npobject_info_new(NPObject *npobj) attribute_hidden;
|
||||
|
@ -41,15 +43,6 @@ extern void npobject_bridge_destroy(void) attribute_hidden;
|
|||
|
||||
extern NPClass npclass_bridge;
|
||||
|
||||
extern void npclass_invoke_Invalidate(NPObject *npobj) attribute_hidden;
|
||||
extern bool npclass_invoke_HasMethod(NPObject *npobj, NPIdentifier name) attribute_hidden;
|
||||
extern bool npclass_invoke_Invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) attribute_hidden;
|
||||
extern bool npclass_invoke_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result) attribute_hidden;
|
||||
extern bool npclass_invoke_HasProperty(NPObject *npobj, NPIdentifier name) attribute_hidden;
|
||||
extern bool npclass_invoke_GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) attribute_hidden;
|
||||
extern bool npclass_invoke_SetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value) attribute_hidden;
|
||||
extern bool npclass_invoke_RemoveProperty(NPObject *npobj, NPIdentifier name) attribute_hidden;
|
||||
|
||||
extern int npclass_handle_Invalidate(rpc_connection_t *connection) attribute_hidden;
|
||||
extern int npclass_handle_HasMethod(rpc_connection_t *connection) attribute_hidden;
|
||||
extern int npclass_handle_Invoke(rpc_connection_t *connection) attribute_hidden;
|
||||
|
@ -65,4 +58,7 @@ extern void npvariant_clear(struct _NPVariant *variant) attribute_hidden;
|
|||
extern char *string_of_NPVariant(const struct _NPVariant *arg) attribute_hidden;
|
||||
extern void print_npvariant_args(const struct _NPVariant *args, uint32_t nargs) attribute_hidden;
|
||||
|
||||
// Deactivate all NPObject instances
|
||||
extern void npruntime_deactivate(void);
|
||||
|
||||
#endif /* NPRUNTIME_IMPL_H */
|
||||
|
|
331
src/npruntime.c
331
src/npruntime.c
|
@ -24,6 +24,7 @@
|
|||
#include <glib.h> /* <glib/ghash.h> */
|
||||
#include "utils.h"
|
||||
#include "npw-common.h"
|
||||
#include "npw-malloc.h"
|
||||
|
||||
#define DEBUG 1
|
||||
#include "debug.h"
|
||||
|
@ -32,28 +33,58 @@
|
|||
// Defined in npw-{wrapper,viewer}.c
|
||||
extern rpc_connection_t *g_rpc_connection attribute_hidden;
|
||||
|
||||
// Defined in npw-viewer.c
|
||||
#if USE_PID_CHECK && NPW_IS_PLUGIN
|
||||
extern bool pid_check(void);
|
||||
#else
|
||||
#define pid_check() true
|
||||
#endif
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === NPClass Bridge === */
|
||||
/* ====================================================================== */
|
||||
|
||||
static void g_NPClass_Invalidate(NPObject *npobj);
|
||||
static bool g_NPClass_HasMethod(NPObject *npobj, NPIdentifier name);
|
||||
static bool g_NPClass_Invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);
|
||||
static bool g_NPClass_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
|
||||
static bool g_NPClass_HasProperty(NPObject *npobj, NPIdentifier name);
|
||||
static bool g_NPClass_GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result);
|
||||
static bool g_NPClass_SetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value);
|
||||
static bool g_NPClass_RemoveProperty(NPObject *npobj, NPIdentifier name);
|
||||
|
||||
NPClass npclass_bridge = {
|
||||
NPW_NP_CLASS_STRUCT_VERSION,
|
||||
NULL,
|
||||
NULL,
|
||||
npclass_invoke_Invalidate,
|
||||
npclass_invoke_HasMethod,
|
||||
npclass_invoke_Invoke,
|
||||
npclass_invoke_InvokeDefault,
|
||||
npclass_invoke_HasProperty,
|
||||
npclass_invoke_GetProperty,
|
||||
npclass_invoke_SetProperty,
|
||||
npclass_invoke_RemoveProperty
|
||||
g_NPClass_Invalidate,
|
||||
g_NPClass_HasMethod,
|
||||
g_NPClass_Invoke,
|
||||
g_NPClass_InvokeDefault,
|
||||
g_NPClass_HasProperty,
|
||||
g_NPClass_GetProperty,
|
||||
g_NPClass_SetProperty,
|
||||
g_NPClass_RemoveProperty
|
||||
};
|
||||
|
||||
static inline bool is_valid_npobject_class(NPObject *npobj)
|
||||
{
|
||||
if (npobj == NULL || npobj->_class == NULL)
|
||||
return false;
|
||||
NPObjectInfo *npobj_info = npobject_info_lookup(npobj);
|
||||
if (npobj_info == NULL)
|
||||
return false;
|
||||
if (!npobj_info->is_valid)
|
||||
npw_printf("ERROR: NPObject %p is no longer valid!\n", npobj);
|
||||
return npobj_info->is_valid;
|
||||
}
|
||||
|
||||
// NPClass::Invalidate
|
||||
int npclass_handle_Invalidate(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("npclass_handle_Invalidate\n"));
|
||||
|
||||
NPObject *npobj;
|
||||
int error = rpc_method_get_args(connection,
|
||||
RPC_TYPE_NP_OBJECT, &npobj,
|
||||
|
@ -64,17 +95,19 @@ int npclass_handle_Invalidate(rpc_connection_t *connection)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (npobj && npobj->_class && npobj->_class->invalidate) {
|
||||
D(bug("NPClass::Invalidate(npobj %p)\n", npobj));
|
||||
if (npobj && is_valid_npobject_class(npobj) && npobj->_class->invalidate) {
|
||||
D(bugiI("NPClass::Invalidate(npobj %p)\n", npobj));
|
||||
npobj->_class->invalidate(npobj);
|
||||
D(bug(" done\n"));
|
||||
D(bugiD("NPClass::Invalidate done\n"));
|
||||
}
|
||||
|
||||
return rpc_method_send_reply(connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
void npclass_invoke_Invalidate(NPObject *npobj)
|
||||
static void npclass_invoke_Invalidate(NPObject *npobj)
|
||||
{
|
||||
npw_return_if_fail(rpc_method_invoke_possible(g_rpc_connection));
|
||||
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NPCLASS_INVALIDATE,
|
||||
RPC_TYPE_NP_OBJECT, npobj,
|
||||
|
@ -93,9 +126,26 @@ void npclass_invoke_Invalidate(NPObject *npobj)
|
|||
}
|
||||
}
|
||||
|
||||
void g_NPClass_Invalidate(NPObject *npobj)
|
||||
{
|
||||
if (!is_valid_npobject_class(npobj))
|
||||
return;
|
||||
|
||||
if (!pid_check()) {
|
||||
npw_printf("WARNING: NPClass::Invalidate called from the wrong process\n");
|
||||
return;
|
||||
}
|
||||
|
||||
D(bugiI("NPClass::Invalidate(npobj %p)\n", npobj));
|
||||
npclass_invoke_Invalidate(npobj);
|
||||
D(bugiD("NPClass::Invalidate done\n"));
|
||||
}
|
||||
|
||||
// NPClass::HasMethod
|
||||
int npclass_handle_HasMethod(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("npclass_handle_HasMethod\n"));
|
||||
|
||||
NPObject *npobj;
|
||||
NPIdentifier name;
|
||||
int error = rpc_method_get_args(connection,
|
||||
|
@ -109,10 +159,10 @@ int npclass_handle_HasMethod(rpc_connection_t *connection)
|
|||
}
|
||||
|
||||
uint32_t ret = false;
|
||||
if (npobj && npobj->_class && npobj->_class->hasMethod) {
|
||||
D(bug("NPClass::HasMethod(npobj %p, name id %p)\n", npobj, name));
|
||||
if (npobj && is_valid_npobject_class(npobj) && npobj->_class->hasMethod) {
|
||||
D(bugiI("NPClass::HasMethod(npobj %p, name id %p)\n", npobj, name));
|
||||
ret = npobj->_class->hasMethod(npobj, name);
|
||||
D(bug(" return: %d\n", ret));
|
||||
D(bugiD("NPClass::HasMethod return: %d\n", ret));
|
||||
}
|
||||
|
||||
return rpc_method_send_reply(connection,
|
||||
|
@ -120,8 +170,10 @@ int npclass_handle_HasMethod(rpc_connection_t *connection)
|
|||
RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
bool npclass_invoke_HasMethod(NPObject *npobj, NPIdentifier name)
|
||||
static bool npclass_invoke_HasMethod(NPObject *npobj, NPIdentifier name)
|
||||
{
|
||||
npw_return_val_if_fail(rpc_method_invoke_possible(g_rpc_connection), false);
|
||||
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NPCLASS_HAS_METHOD,
|
||||
RPC_TYPE_NP_OBJECT, npobj,
|
||||
|
@ -144,9 +196,27 @@ bool npclass_invoke_HasMethod(NPObject *npobj, NPIdentifier name)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool g_NPClass_HasMethod(NPObject *npobj, NPIdentifier name)
|
||||
{
|
||||
if (!is_valid_npobject_class(npobj))
|
||||
return false;
|
||||
|
||||
if (!pid_check()) {
|
||||
npw_printf("WARNING: NPClass::HasMethod called from the wrong process\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
D(bugiI("NPClass::HasMethod(npobj %p, name id %p)\n", npobj, name));
|
||||
bool ret = npclass_invoke_HasMethod(npobj, name);
|
||||
D(bugiD("NPClass::HasMethod return: %d\n", ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NPClass::Invoke
|
||||
int npclass_handle_Invoke(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("npclass_handle_Invoke\n"));
|
||||
|
||||
NPObject *npobj;
|
||||
NPIdentifier name;
|
||||
uint32_t argCount;
|
||||
|
@ -165,12 +235,12 @@ int npclass_handle_Invoke(rpc_connection_t *connection)
|
|||
uint32_t ret = false;
|
||||
NPVariant result;
|
||||
VOID_TO_NPVARIANT(result);
|
||||
if (npobj && npobj->_class && npobj->_class->invoke) {
|
||||
D(bug("NPClass::Invoke(npobj %p, name id %p)\n", npobj, name));
|
||||
if (npobj && is_valid_npobject_class(npobj) && npobj->_class->invoke) {
|
||||
D(bugiI("NPClass::Invoke(npobj %p, name id %p)\n", npobj, name));
|
||||
print_npvariant_args(args, argCount);
|
||||
ret = npobj->_class->invoke(npobj, name, args, argCount, &result);
|
||||
gchar *result_str = string_of_NPVariant(&result);
|
||||
D(bug(" return: %d (%s)\n", ret, result_str));
|
||||
D(bugiD("NPClass::Invoke return: %d (%s)\n", ret, result_str));
|
||||
g_free(result_str);
|
||||
}
|
||||
|
||||
|
@ -189,12 +259,10 @@ int npclass_handle_Invoke(rpc_connection_t *connection)
|
|||
return rpc_ret;
|
||||
}
|
||||
|
||||
bool npclass_invoke_Invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args, uint32_t argCount,
|
||||
NPVariant *result)
|
||||
static bool npclass_invoke_Invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args, uint32_t argCount,
|
||||
NPVariant *result)
|
||||
{
|
||||
if (result == NULL)
|
||||
return false;
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
npw_return_val_if_fail(rpc_method_invoke_possible(g_rpc_connection), false);
|
||||
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NPCLASS_INVOKE,
|
||||
|
@ -222,9 +290,35 @@ bool npclass_invoke_Invoke(NPObject *npobj, NPIdentifier name, const NPVariant *
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool g_NPClass_Invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args, uint32_t argCount,
|
||||
NPVariant *result)
|
||||
{
|
||||
if (result == NULL)
|
||||
return false;
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
|
||||
if (!is_valid_npobject_class(npobj))
|
||||
return false;
|
||||
|
||||
if (!pid_check()) {
|
||||
npw_printf("WARNING: NPClass::Invoke called from the wrong process\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
D(bugiI("NPClass::Invoke(npobj %p, name id %p)\n", npobj, name));
|
||||
print_npvariant_args(args, argCount);
|
||||
bool ret = npclass_invoke_Invoke(npobj, name, args, argCount, result);
|
||||
gchar *result_str = string_of_NPVariant(result);
|
||||
D(bugiD("NPClass::Invoke return: %d (%s)\n", ret, result_str));
|
||||
g_free(result_str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NPClass::InvokeDefault
|
||||
int npclass_handle_InvokeDefault(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("npclass_handle_InvokeDefault\n"));
|
||||
|
||||
NPObject *npobj;
|
||||
uint32_t argCount;
|
||||
NPVariant *args;
|
||||
|
@ -241,12 +335,12 @@ int npclass_handle_InvokeDefault(rpc_connection_t *connection)
|
|||
uint32_t ret = false;
|
||||
NPVariant result;
|
||||
VOID_TO_NPVARIANT(result);
|
||||
if (npobj && npobj->_class && npobj->_class->invokeDefault) {
|
||||
D(bug("NPClass::InvokeDefault(npobj %p)\n", npobj));
|
||||
if (npobj && is_valid_npobject_class(npobj) && npobj->_class->invokeDefault) {
|
||||
D(bugiI("NPClass::InvokeDefault(npobj %p)\n", npobj));
|
||||
print_npvariant_args(args, argCount);
|
||||
ret = npobj->_class->invokeDefault(npobj, args, argCount, &result);
|
||||
gchar *result_str = string_of_NPVariant(&result);
|
||||
D(bug(" return: %d (%s)\n", ret, result_str));
|
||||
D(bugiD("NPClass::InvokeDefault return: %d (%s)\n", ret, result_str));
|
||||
g_free(result_str);
|
||||
}
|
||||
|
||||
|
@ -265,12 +359,10 @@ int npclass_handle_InvokeDefault(rpc_connection_t *connection)
|
|||
return rpc_ret;
|
||||
}
|
||||
|
||||
bool npclass_invoke_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount,
|
||||
NPVariant *result)
|
||||
static bool npclass_invoke_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount,
|
||||
NPVariant *result)
|
||||
{
|
||||
if (result == NULL)
|
||||
return false;
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
npw_return_val_if_fail(rpc_method_invoke_possible(g_rpc_connection), false);
|
||||
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NPCLASS_INVOKE_DEFAULT,
|
||||
|
@ -297,9 +389,35 @@ bool npclass_invoke_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool g_NPClass_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount,
|
||||
NPVariant *result)
|
||||
{
|
||||
if (result == NULL)
|
||||
return false;
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
|
||||
if (!is_valid_npobject_class(npobj))
|
||||
return false;
|
||||
|
||||
if (!pid_check()) {
|
||||
npw_printf("WARNING: NPClass::InvokeDefault called from the wrong process\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
D(bugiI("NPClass::InvokeDefault(npobj %p)\n", npobj));
|
||||
print_npvariant_args(args, argCount);
|
||||
bool ret = npclass_invoke_InvokeDefault(npobj, args, argCount, result);
|
||||
gchar *result_str = string_of_NPVariant(result);
|
||||
D(bugiD("NPClass::InvokeDefault return: %d (%s)\n", ret, result_str));
|
||||
g_free(result_str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NPClass::HasProperty
|
||||
int npclass_handle_HasProperty(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("npclass_handle_HasProperty\n"));
|
||||
|
||||
NPObject *npobj;
|
||||
NPIdentifier name;
|
||||
int error = rpc_method_get_args(connection,
|
||||
|
@ -313,10 +431,10 @@ int npclass_handle_HasProperty(rpc_connection_t *connection)
|
|||
}
|
||||
|
||||
uint32_t ret = false;
|
||||
if (npobj && npobj->_class && npobj->_class->hasProperty) {
|
||||
D(bug("NPClass::HasProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
if (npobj && is_valid_npobject_class(npobj) && npobj->_class->hasProperty) {
|
||||
D(bugiI("NPClass::HasProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
ret = npobj->_class->hasProperty(npobj, name);
|
||||
D(bug(" return: %d\n", ret));
|
||||
D(bugiD("NPClass::HasProperty return: %d\n", ret));
|
||||
}
|
||||
|
||||
return rpc_method_send_reply(connection,
|
||||
|
@ -324,8 +442,10 @@ int npclass_handle_HasProperty(rpc_connection_t *connection)
|
|||
RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
bool npclass_invoke_HasProperty(NPObject *npobj, NPIdentifier name)
|
||||
static bool npclass_invoke_HasProperty(NPObject *npobj, NPIdentifier name)
|
||||
{
|
||||
npw_return_val_if_fail(rpc_method_invoke_possible(g_rpc_connection), false);
|
||||
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NPCLASS_HAS_PROPERTY,
|
||||
RPC_TYPE_NP_OBJECT, npobj,
|
||||
|
@ -348,9 +468,27 @@ bool npclass_invoke_HasProperty(NPObject *npobj, NPIdentifier name)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool g_NPClass_HasProperty(NPObject *npobj, NPIdentifier name)
|
||||
{
|
||||
if (!is_valid_npobject_class(npobj))
|
||||
return false;
|
||||
|
||||
if (!pid_check()) {
|
||||
npw_printf("WARNING: NPClass::HasProperty called from the wrong process\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
D(bugiI("NPClass::HasProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
bool ret = npclass_invoke_HasProperty(npobj, name);
|
||||
D(bugiD("NPClass::HasProperty return: %d\n", ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NPClass::GetProperty
|
||||
int npclass_handle_GetProperty(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("npclass_handle_GetProperty\n"));
|
||||
|
||||
NPObject *npobj;
|
||||
NPIdentifier name;
|
||||
int error = rpc_method_get_args(connection,
|
||||
|
@ -366,11 +504,11 @@ int npclass_handle_GetProperty(rpc_connection_t *connection)
|
|||
uint32_t ret = false;
|
||||
NPVariant result;
|
||||
VOID_TO_NPVARIANT(result);
|
||||
if (npobj && npobj->_class && npobj->_class->getProperty) {
|
||||
D(bug("NPClass::GetProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
if (npobj && is_valid_npobject_class(npobj) && npobj->_class->getProperty) {
|
||||
D(bugiI("NPClass::GetProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
ret = npobj->_class->getProperty(npobj, name, &result);
|
||||
gchar *result_str = string_of_NPVariant(&result);
|
||||
D(bug(" return: %d (%s)\n", ret, result_str));
|
||||
D(bugiD("NPClass::GetProperty return: %d (%s)\n", ret, result_str));
|
||||
g_free(result_str);
|
||||
}
|
||||
|
||||
|
@ -383,11 +521,9 @@ int npclass_handle_GetProperty(rpc_connection_t *connection)
|
|||
return rpc_ret;
|
||||
}
|
||||
|
||||
bool npclass_invoke_GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
|
||||
static bool npclass_invoke_GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
|
||||
{
|
||||
if (result == NULL)
|
||||
return false;
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
npw_return_val_if_fail(rpc_method_invoke_possible(g_rpc_connection), false);
|
||||
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NPCLASS_GET_PROPERTY,
|
||||
|
@ -414,9 +550,33 @@ bool npclass_invoke_GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *r
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool g_NPClass_GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
|
||||
{
|
||||
if (result == NULL)
|
||||
return false;
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
|
||||
if (!is_valid_npobject_class(npobj))
|
||||
return false;
|
||||
|
||||
if (!pid_check()) {
|
||||
npw_printf("WARNING: NPClass::GetProperty called from the wrong process\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
D(bugiI("NPClass::GetProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
bool ret = npclass_invoke_GetProperty(npobj, name, result);
|
||||
gchar *result_str = string_of_NPVariant(result);
|
||||
D(bugiD("NPClass::GetProperty return: %d (%s)\n", ret, result_str));
|
||||
g_free(result_str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NPClass::SetProperty
|
||||
int npclass_handle_SetProperty(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("npclass_handle_SetProperty\n"));
|
||||
|
||||
NPObject *npobj;
|
||||
NPIdentifier name;
|
||||
NPVariant value;
|
||||
|
@ -432,10 +592,10 @@ int npclass_handle_SetProperty(rpc_connection_t *connection)
|
|||
}
|
||||
|
||||
uint32_t ret = false;
|
||||
if (npobj && npobj->_class && npobj->_class->setProperty) {
|
||||
D(bug("NPClass::SetProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
if (npobj && is_valid_npobject_class(npobj) && npobj->_class->setProperty) {
|
||||
D(bugiI("NPClass::SetProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
ret = npobj->_class->setProperty(npobj, name, &value);
|
||||
D(bug(" return: %d\n", ret));
|
||||
D(bugiD("NPClass::SetProperty return: %d\n", ret));
|
||||
}
|
||||
|
||||
int rpc_ret = rpc_method_send_reply(connection,
|
||||
|
@ -446,10 +606,9 @@ int npclass_handle_SetProperty(rpc_connection_t *connection)
|
|||
return rpc_ret;
|
||||
}
|
||||
|
||||
bool npclass_invoke_SetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
|
||||
static bool npclass_invoke_SetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
|
||||
{
|
||||
if (value == NULL)
|
||||
return false;
|
||||
npw_return_val_if_fail(rpc_method_invoke_possible(g_rpc_connection), false);
|
||||
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NPCLASS_SET_PROPERTY,
|
||||
|
@ -476,9 +635,32 @@ bool npclass_invoke_SetProperty(NPObject *npobj, NPIdentifier name, const NPVari
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool g_NPClass_SetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
|
||||
{
|
||||
if (value == NULL) {
|
||||
npw_printf("WARNING: NPClass::SetProperty() called with a NULL value\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_valid_npobject_class(npobj))
|
||||
return false;
|
||||
|
||||
if (!pid_check()) {
|
||||
npw_printf("WARNING: NPClass::SetProperty called from the wrong process\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
D(bugiI("NPClass::SetProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
bool ret = npclass_invoke_SetProperty(npobj, name, value);
|
||||
D(bugiD("NPClass::SetProperty return: %d\n", ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NPClass::RemoveProperty
|
||||
int npclass_handle_RemoveProperty(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("npclass_handle_RemoveProperty\n"));
|
||||
|
||||
NPObject *npobj;
|
||||
NPIdentifier name;
|
||||
int error = rpc_method_get_args(connection,
|
||||
|
@ -492,10 +674,10 @@ int npclass_handle_RemoveProperty(rpc_connection_t *connection)
|
|||
}
|
||||
|
||||
uint32_t ret = false;
|
||||
if (npobj && npobj->_class && npobj->_class->removeProperty) {
|
||||
D(bug("NPClass::RemoveProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
if (npobj && is_valid_npobject_class(npobj) && npobj->_class->removeProperty) {
|
||||
D(bugiI("NPClass::RemoveProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
ret = npobj->_class->removeProperty(npobj, name);
|
||||
D(bug(" return: %d\n", ret));
|
||||
D(bugiD("NPClass::RemoveProperty return: %d\n", ret));
|
||||
}
|
||||
|
||||
return rpc_method_send_reply(connection,
|
||||
|
@ -503,8 +685,10 @@ int npclass_handle_RemoveProperty(rpc_connection_t *connection)
|
|||
RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
bool npclass_invoke_RemoveProperty(NPObject *npobj, NPIdentifier name)
|
||||
static bool npclass_invoke_RemoveProperty(NPObject *npobj, NPIdentifier name)
|
||||
{
|
||||
npw_return_val_if_fail(rpc_method_invoke_possible(g_rpc_connection), false);
|
||||
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NPCLASS_REMOVE_PROPERTY,
|
||||
RPC_TYPE_NP_OBJECT, npobj,
|
||||
|
@ -527,6 +711,22 @@ bool npclass_invoke_RemoveProperty(NPObject *npobj, NPIdentifier name)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool g_NPClass_RemoveProperty(NPObject *npobj, NPIdentifier name)
|
||||
{
|
||||
if (!is_valid_npobject_class(npobj))
|
||||
return false;
|
||||
|
||||
if (!pid_check()) {
|
||||
npw_printf("WARNING: NPClass::RemoveProperty called from the wrong process\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
D(bugiI("NPClass::RemoveProperty(npobj %p, name id %p)\n", npobj, name));
|
||||
bool ret = npclass_invoke_RemoveProperty(npobj, name);
|
||||
D(bugiD("NPClass::RemoveProperty return: %d\n", ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === NPObjectInfo === */
|
||||
|
@ -534,19 +734,22 @@ bool npclass_invoke_RemoveProperty(NPObject *npobj, NPIdentifier name)
|
|||
|
||||
NPObjectInfo *npobject_info_new(NPObject *npobj)
|
||||
{
|
||||
NPObjectInfo *npobj_info = malloc(sizeof(*npobj_info));
|
||||
NPObjectInfo *npobj_info = NPW_MemNew0(NPObjectInfo, 1);
|
||||
if (npobj_info) {
|
||||
static uint32_t id;
|
||||
npobj_info->npobj = npobj;
|
||||
npobj_info->npobj_id = ++id;
|
||||
npobj_info->is_valid = true;
|
||||
}
|
||||
return npobj_info;
|
||||
}
|
||||
|
||||
void npobject_info_destroy(NPObjectInfo *npobj_info)
|
||||
{
|
||||
if (npobj_info)
|
||||
free(npobj_info);
|
||||
if (npobj_info) {
|
||||
npw_plugin_instance_unref(npobj_info->plugin);
|
||||
NPW_MemFree(npobj_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -593,6 +796,7 @@ NPObject *npobject_new(uint32_t npobj_id, NPP instance, NPClass *class)
|
|||
return NULL;
|
||||
}
|
||||
npobj_info->npobj_id = npobj_id;
|
||||
npobj_info->plugin = npw_plugin_instance_ref(NPW_PLUGIN_INSTANCE(instance));
|
||||
npobject_associate(npobj, npobj_info);
|
||||
return npobj;
|
||||
}
|
||||
|
@ -665,6 +869,17 @@ NPObject *npobject_lookup(uint32_t npobj_id)
|
|||
return g_hash_table_lookup(g_npobject_ids, (void *)(uintptr_t)npobj_id);
|
||||
}
|
||||
|
||||
static void npruntime_deactivate_func(gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
NPObjectInfo *npobj_info = (NPObjectInfo *)value;
|
||||
npobj_info->is_valid = false;
|
||||
}
|
||||
|
||||
void npruntime_deactivate(void)
|
||||
{
|
||||
g_hash_table_foreach(g_npobjects, npruntime_deactivate_func, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === NPVariant helpers === */
|
||||
|
@ -703,6 +918,8 @@ gchar *
|
|||
string_of_NPVariant(const NPVariant *arg)
|
||||
{
|
||||
#if DEBUG
|
||||
if (arg == NULL)
|
||||
return NULL;
|
||||
GString *str = g_string_new(NULL);
|
||||
switch (arg->type)
|
||||
{
|
||||
|
@ -752,7 +969,7 @@ print_npvariant_args(const NPVariant *args, uint32_t nargs)
|
|||
g_string_append(str, argstr);
|
||||
g_free(argstr);
|
||||
}
|
||||
D(bug(" %u args (%s)\n", nargs, str->str));
|
||||
D(bug("%u args (%s)\n", nargs, str->str));
|
||||
g_string_free(str, TRUE);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -25,6 +25,57 @@
|
|||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === Plugin instances === */
|
||||
/* ====================================================================== */
|
||||
|
||||
void *
|
||||
npw_plugin_instance_new(NPW_PluginInstanceClass *klass)
|
||||
{
|
||||
NPW_PluginInstance *plugin;
|
||||
if (klass && klass->allocate)
|
||||
plugin = klass->allocate ();
|
||||
else
|
||||
plugin = NPW_MemNew0 (NPW_PluginInstance, 1);
|
||||
if (plugin)
|
||||
{
|
||||
plugin->klass = klass;
|
||||
plugin->refcount = 1;
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
|
||||
void *
|
||||
npw_plugin_instance_ref(void *ptr)
|
||||
{
|
||||
NPW_PluginInstance *plugin = (NPW_PluginInstance *)ptr;
|
||||
if (plugin)
|
||||
plugin->refcount++;
|
||||
return plugin;
|
||||
}
|
||||
|
||||
void
|
||||
npw_plugin_instance_unref(void *ptr)
|
||||
{
|
||||
NPW_PluginInstance *plugin = (NPW_PluginInstance *)ptr;
|
||||
if (plugin == NULL)
|
||||
return;
|
||||
if (--plugin->refcount > 0)
|
||||
return;
|
||||
NPW_PluginInstanceClass *klass = plugin->klass;
|
||||
if (klass && klass->finalize)
|
||||
klass->finalize (plugin);
|
||||
if (klass && klass->deallocate)
|
||||
klass->deallocate (plugin);
|
||||
else
|
||||
NPW_MemFree (plugin);
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === NPAPI interface === */
|
||||
/* ====================================================================== */
|
||||
|
||||
static NPNetscapeFuncs g_mozilla_funcs;
|
||||
static NPPluginFuncs g_plugin_funcs;
|
||||
|
||||
|
@ -38,10 +89,6 @@ NPW_InitializeFuncs (NPNetscapeFuncs *mozilla_funcs,
|
|||
MIN (sizeof (g_plugin_funcs), plugin_funcs->size));
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === NPAPI interface === */
|
||||
/* ====================================================================== */
|
||||
|
||||
void *
|
||||
NPN_MemAlloc (uint32_t size)
|
||||
{
|
||||
|
|
|
@ -55,16 +55,46 @@
|
|||
|
||||
/* PluginInstance */
|
||||
#define NPW_DECL_PLUGIN_INSTANCE \
|
||||
NPP instance; \
|
||||
uint32_t instance_id;
|
||||
NPW_PluginInstanceClass *klass; \
|
||||
uint32_t refcount; \
|
||||
NPP instance; \
|
||||
uint32_t instance_id;
|
||||
|
||||
typedef struct _NPW_PluginInstance NPW_PluginInstance;
|
||||
typedef struct _NPW_PluginInstanceClass NPW_PluginInstanceClass;
|
||||
|
||||
typedef struct _NPW_PluginInstance NPW_PluginInstance;
|
||||
struct _NPW_PluginInstance
|
||||
{
|
||||
NPW_DECL_PLUGIN_INSTANCE;
|
||||
};
|
||||
|
||||
#define NPW_PLUGIN_INSTANCE(instance) npw_get_plugin_instance (instance)
|
||||
typedef void *
|
||||
(*NPW_PluginInstanceAllocateFunctionPtr) (void);
|
||||
|
||||
typedef void
|
||||
(*NPW_PluginInstanceDeallocateFunctionPtr) (NPW_PluginInstance *plugin);
|
||||
|
||||
typedef void
|
||||
(*NPW_PluginInstanceFinalizeFunctionPtr) (NPW_PluginInstance *plugin);
|
||||
|
||||
struct _NPW_PluginInstanceClass
|
||||
{
|
||||
NPW_PluginInstanceAllocateFunctionPtr allocate;
|
||||
NPW_PluginInstanceDeallocateFunctionPtr deallocate;
|
||||
NPW_PluginInstanceFinalizeFunctionPtr finalize;
|
||||
};
|
||||
|
||||
void *
|
||||
npw_plugin_instance_new(NPW_PluginInstanceClass *klass) attribute_hidden;
|
||||
|
||||
void *
|
||||
npw_plugin_instance_ref(void *ptr) attribute_hidden;
|
||||
|
||||
void
|
||||
npw_plugin_instance_unref(void *ptr) attribute_hidden;
|
||||
|
||||
#define NPW_PLUGIN_INSTANCE(instance) npw_get_plugin_instance (instance)
|
||||
#define NPW_PLUGIN_INSTANCE_NPP(plugin) npw_get_plugin_instance_npp (plugin)
|
||||
|
||||
static inline NPW_PluginInstance *
|
||||
_npw_get_plugin_instance (NPP instance)
|
||||
|
@ -95,6 +125,12 @@ npw_get_plugin_instance (NPP instance)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline NPP
|
||||
npw_get_plugin_instance_npp (NPW_PluginInstance *plugin)
|
||||
{
|
||||
return plugin ? plugin->instance : NULL;
|
||||
}
|
||||
|
||||
/* StreamInstance */
|
||||
#define NPW_DECL_STREAM_INSTANCE \
|
||||
NPStream *stream; \
|
||||
|
@ -109,13 +145,25 @@ struct _NPW_StreamInstance
|
|||
|
||||
#define NPW_STREAM_INSTANCE(stream) npw_get_stream_instance (stream)
|
||||
|
||||
static inline NPW_StreamInstance *
|
||||
_npw_get_stream_instance (NPStream *np_stream)
|
||||
{
|
||||
return (NPW_StreamInstance *)np_stream->_NPW_INSTANCE_PRIVATE_DATA;
|
||||
}
|
||||
|
||||
static inline NPW_StreamInstance *
|
||||
npw_get_stream_instance (NPStream *np_stream)
|
||||
{
|
||||
NPW_StreamInstance *stream;
|
||||
stream = (NPW_StreamInstance *)np_stream->_NPW_INSTANCE_PRIVATE_DATA;
|
||||
assert (stream->stream == np_stream);
|
||||
return stream;
|
||||
if (np_stream)
|
||||
{
|
||||
NPW_StreamInstance *stream;
|
||||
if ((stream = _npw_get_stream_instance (np_stream)) != NULL)
|
||||
{
|
||||
assert (stream->stream == np_stream);
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Unimplemented functions */
|
||||
|
@ -124,7 +172,7 @@ npw_get_stream_instance (NPStream *np_stream)
|
|||
__func__, __FILE__, __LINE__)
|
||||
|
||||
/* Initialize NPAPI hooks */
|
||||
extern void
|
||||
void
|
||||
NPW_InitializeFuncs (NPNetscapeFuncs *mozilla_funcs,
|
||||
NPPluginFuncs *plugin_funcs)
|
||||
attribute_hidden;
|
||||
|
@ -146,19 +194,19 @@ struct _NPW_Identifier
|
|||
};
|
||||
|
||||
/* Create identifier from an integer */
|
||||
extern NPW_Identifier
|
||||
NPW_Identifier
|
||||
NPW_CreateIntIdentifier (int32_t value);
|
||||
|
||||
/* Create identifier from a string (that is copied) */
|
||||
extern NPW_Identifier
|
||||
NPW_Identifier
|
||||
NPW_CreateStringIdentifier (const char *str);
|
||||
|
||||
/* Create identifier from a string (that is now owned by the identifier) */
|
||||
extern NPW_Identifier
|
||||
NPW_Identifier
|
||||
NPW_CreateStringIdentifierSink (char *str);
|
||||
|
||||
/* Destroy identifier */
|
||||
extern void
|
||||
void
|
||||
NPW_DestroyIdentifier (NPW_Identifier id);
|
||||
|
||||
/* Check whether identifier is an integer */
|
||||
|
|
|
@ -30,4 +30,10 @@ NPW_MemAlloc0 (uint32_t size);
|
|||
void
|
||||
NPW_MemFree (void *ptr);
|
||||
|
||||
#define NPW_MemNew(type, n) \
|
||||
((type *) NPW_MemAlloc ((n) * sizeof (type)))
|
||||
|
||||
#define NPW_MemNew0(type, n) \
|
||||
((type *) NPW_MemAlloc0 ((n) * sizeof (type)))
|
||||
|
||||
#endif /* NPW_MALLOC_H */
|
||||
|
|
|
@ -1284,17 +1284,17 @@ stream_new (Plugin *plugin,
|
|||
const gchar *src, const gchar *type, void *notify_data,
|
||||
NPError *error)
|
||||
{
|
||||
NPError ret = NPERR_NO_ERROR;
|
||||
StreamInstance *pstream = NULL;
|
||||
NPStream *np_stream = NULL;
|
||||
NPError ret = NPERR_NO_ERROR;
|
||||
|
||||
StreamInstance *pstream = g_new0 (StreamInstance, 1);
|
||||
if (pstream == NULL)
|
||||
if ((pstream = g_new0 (StreamInstance, 1)) == NULL)
|
||||
{
|
||||
ret = NPERR_OUT_OF_MEMORY_ERROR;
|
||||
goto l_error;
|
||||
}
|
||||
|
||||
NPStream *np_stream = np_stream_new (src, notify_data);
|
||||
if (np_stream == NULL)
|
||||
if ((np_stream = np_stream_new (src, notify_data)) == NULL)
|
||||
{
|
||||
ret = NPERR_OUT_OF_MEMORY_ERROR;
|
||||
goto l_error;
|
||||
|
@ -1643,10 +1643,6 @@ on_stream_close_cb (gpointer user_data)
|
|||
{
|
||||
if (!(pstream->status & STREAM_STATUS_ACTIVE))
|
||||
{
|
||||
/* XXX: consider the stream in error if it was never started */
|
||||
if (pstream->buffers == NULL)
|
||||
pstream->status |= STREAM_STATUS_ERROR;
|
||||
|
||||
/* Special case for JavaScript that CURL could not handle */
|
||||
const gchar * const url = pstream->np_stream->url;
|
||||
if (g_ascii_strncasecmp (url, "javascript:", 11) == 0)
|
||||
|
@ -1697,6 +1693,10 @@ on_stream_close_cb (gpointer user_data)
|
|||
g_string_free (text, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: consider the stream in error if it was never started */
|
||||
if (pstream->buffers == NULL)
|
||||
pstream->status |= STREAM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
stream_schedule_destroy (pstream, FALSE);
|
||||
|
|
|
@ -90,22 +90,19 @@ int rpc_type_of_NPPVariable(int variable)
|
|||
|
||||
|
||||
/*
|
||||
* Process NPP objects
|
||||
* Process NPW_PluginInstance objects
|
||||
*/
|
||||
|
||||
static int do_send_NPP(rpc_message_t *message, void *p_value)
|
||||
static int do_send_NPW_PluginInstance(rpc_message_t *message, void *p_value)
|
||||
{
|
||||
NPW_PluginInstance *plugin = (NPW_PluginInstance *)p_value;
|
||||
uint32_t instance_id = 0;
|
||||
NPP instance = (NPP)p_value;
|
||||
if (instance) {
|
||||
NPW_PluginInstance *plugin = NPW_PLUGIN_INSTANCE(instance);
|
||||
if (plugin)
|
||||
instance_id = plugin->instance_id;
|
||||
}
|
||||
if (plugin)
|
||||
instance_id = plugin->instance_id;
|
||||
return rpc_message_send_uint32(message, instance_id);
|
||||
}
|
||||
|
||||
static int do_recv_NPP(rpc_message_t *message, void *p_value)
|
||||
static int do_recv_NPW_PluginInstance(rpc_message_t *message, void *p_value)
|
||||
{
|
||||
int error;
|
||||
uint32_t instance_id;
|
||||
|
@ -115,9 +112,35 @@ static int do_recv_NPP(rpc_message_t *message, void *p_value)
|
|||
|
||||
NPW_PluginInstance *plugin = id_lookup(instance_id);
|
||||
if (instance_id && plugin == NULL)
|
||||
npw_printf("ERROR: passing an unknown instance\n");
|
||||
if (plugin && plugin->instance == NULL)
|
||||
npw_printf("ERROR: passing a NULL instance through plugin instance id\n");
|
||||
npw_printf("ERROR: no valid NPP -> PluginInstance mapping found\n");
|
||||
else if (plugin && plugin->instance == NULL)
|
||||
npw_printf("ERROR: no valid PluginInstance -> NPP mapping found\n");
|
||||
*((NPW_PluginInstance **)p_value) = plugin;
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process NPP objects
|
||||
*/
|
||||
|
||||
static int do_send_NPP(rpc_message_t *message, void *p_value)
|
||||
{
|
||||
NPP instance = (NPP)p_value;
|
||||
NPW_PluginInstance *plugin = NULL;
|
||||
if (instance)
|
||||
plugin = NPW_PLUGIN_INSTANCE(instance);
|
||||
return do_send_NPW_PluginInstance(message, plugin);
|
||||
}
|
||||
|
||||
static int do_recv_NPP(rpc_message_t *message, void *p_value)
|
||||
{
|
||||
int error;
|
||||
NPW_PluginInstance *plugin;
|
||||
|
||||
if ((error = do_recv_NPW_PluginInstance(message, &plugin)) < 0)
|
||||
return error;
|
||||
|
||||
*((NPP *)p_value) = plugin ? plugin->instance : NULL;
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
@ -1145,7 +1168,6 @@ static int do_recv_NPPrintData(rpc_message_t *message, void *p_value)
|
|||
* Process NPObject objects
|
||||
*/
|
||||
|
||||
// XXX propagate reference counters?
|
||||
static int do_send_NPObject(rpc_message_t *message, void *p_value)
|
||||
{
|
||||
uint32_t npobj_id = 0;
|
||||
|
@ -1165,7 +1187,19 @@ static int do_send_NPObject(rpc_message_t *message, void *p_value)
|
|||
#endif
|
||||
assert(npobj_id != 0);
|
||||
}
|
||||
return rpc_message_send_uint32(message, npobj_id);
|
||||
int error = rpc_message_send_uint32(message, npobj_id);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
#ifdef BUILD_WRAPPER
|
||||
// synchronize referenceCount
|
||||
if (npobj) {
|
||||
if ((error = rpc_message_send_uint32(message, npobj->referenceCount)) < 0)
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
static int do_recv_NPObject(rpc_message_t *message, void *p_value)
|
||||
|
@ -1187,7 +1221,20 @@ static int do_recv_NPObject(rpc_message_t *message, void *p_value)
|
|||
}
|
||||
#endif
|
||||
assert(npobj != NULL);
|
||||
|
||||
#ifdef BUILD_VIEWER
|
||||
// synchronize referenceCount
|
||||
uint32_t referenceCount;
|
||||
if ((error = rpc_message_recv_uint32(message, &referenceCount)) < 0)
|
||||
return error;
|
||||
if (npobj->referenceCount != referenceCount) {
|
||||
D(bug("synchronize NPObject::referenceCount (%d -> %d)\n",
|
||||
npobj->referenceCount, referenceCount));
|
||||
npobj->referenceCount = referenceCount;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
*((NPObject **)p_value) = npobj;
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
@ -1451,6 +1498,12 @@ static const rpc_message_descriptor_t message_descs[] = {
|
|||
do_send_NPP,
|
||||
do_recv_NPP
|
||||
},
|
||||
{
|
||||
RPC_TYPE_NPW_PLUGIN_INSTANCE,
|
||||
sizeof(NPW_PluginInstance *),
|
||||
do_send_NPW_PluginInstance,
|
||||
do_recv_NPW_PluginInstance
|
||||
},
|
||||
{
|
||||
RPC_TYPE_NP_STREAM,
|
||||
sizeof(NPStream *),
|
||||
|
|
|
@ -115,7 +115,8 @@ enum {
|
|||
RPC_TYPE_NP_IDENTIFIER,
|
||||
RPC_TYPE_NP_STRING, /* 15 */
|
||||
RPC_TYPE_NP_VARIANT,
|
||||
RPC_TYPE_NP_UTF8
|
||||
RPC_TYPE_NP_UTF8,
|
||||
RPC_TYPE_NPW_PLUGIN_INSTANCE
|
||||
};
|
||||
|
||||
// NPPrintData is used to get the plugin printed tmpfile
|
||||
|
|
1169
src/npw-viewer.c
1169
src/npw-viewer.c
File diff suppressed because it is too large
Load Diff
|
@ -110,11 +110,11 @@ case " $@ " in
|
|||
case "$LOADER" in
|
||||
*linux32)
|
||||
if test "$OS" = "Linux"; then
|
||||
soundwrapper=`which soundwrapper`
|
||||
soundwrapper=`which soundwrapper 2>/dev/null`
|
||||
if test -x "$soundwrapper"; then
|
||||
LOADER="$LOADER $soundwrapper"
|
||||
elif ps aux | grep artsd | grep -vq grep; then
|
||||
soundwrapper=`which artsdsp`
|
||||
soundwrapper=`which artsdsp 2>/dev/null`
|
||||
if test -x "$soundwrapper"; then
|
||||
LOADER="$LOADER $soundwrapper"
|
||||
fi
|
||||
|
|
1128
src/npw-wrapper.c
1128
src/npw-wrapper.c
File diff suppressed because it is too large
Load Diff
505
src/rpc.c
505
src/rpc.c
|
@ -74,6 +74,11 @@
|
|||
#define RPC_INIT_TIMEOUT 5
|
||||
#endif
|
||||
|
||||
// Set close-on-exec flag on the newly created socket (Linux >= 2.6.27)
|
||||
#ifndef SOCK_CLOEXEC
|
||||
#define SOCK_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === Utility functions === */
|
||||
|
@ -255,6 +260,9 @@ const char *rpc_strerror(int error)
|
|||
case RPC_ERROR_MESSAGE_ARGUMENT_INVALID:
|
||||
str = "Message argument invalid";
|
||||
break;
|
||||
case RPC_ERROR_MESSAGE_SYNC_NOT_ALLOWED:
|
||||
str = "SYNC message forbidden";
|
||||
break;
|
||||
default:
|
||||
str = "<unknown>";
|
||||
break;
|
||||
|
@ -456,6 +464,13 @@ struct rpc_connection {
|
|||
pthread_t server_thread;
|
||||
rpc_map_t *types;
|
||||
rpc_map_t *methods;
|
||||
rpc_error_callback_t error_callback;
|
||||
void *error_callback_data;
|
||||
int dispatch_depth;
|
||||
int invoke_depth;
|
||||
int handle_depth;
|
||||
int sync_depth;
|
||||
int pending_sync_depth;
|
||||
};
|
||||
|
||||
// Increment connection reference count
|
||||
|
@ -475,6 +490,55 @@ void rpc_connection_unref(rpc_connection_t *connection)
|
|||
}
|
||||
}
|
||||
|
||||
// Returns whether we are in sync mode or not (i.e. needs other end sync)
|
||||
static inline bool _rpc_connection_is_sync_mode(rpc_connection_t *connection)
|
||||
{
|
||||
return connection->type == RPC_CONNECTION_SERVER;
|
||||
}
|
||||
|
||||
// Returns whether we are "synchronized" with the other end
|
||||
static inline bool _rpc_connection_is_sync(rpc_connection_t *connection)
|
||||
{
|
||||
if (connection->dispatch_depth < 1)
|
||||
return false;
|
||||
return connection->dispatch_depth == connection->handle_depth;
|
||||
}
|
||||
|
||||
// Returns whether we are allowed to synchronize with the other end
|
||||
static inline bool _rpc_connection_is_sync_allowed(rpc_connection_t *connection)
|
||||
{
|
||||
if (_rpc_connection_is_sync_mode(connection)) {
|
||||
npw_printf("ERROR: RPC is not allowed to receive MESSAGE_SYNC\n");
|
||||
return false;
|
||||
}
|
||||
return connection->pending_sync_depth == 0;
|
||||
}
|
||||
|
||||
// Set error callback for a connection
|
||||
void rpc_connection_set_error_callback(rpc_connection_t *connection,
|
||||
rpc_error_callback_t callback,
|
||||
void *callback_data)
|
||||
{
|
||||
if (connection == NULL)
|
||||
return;
|
||||
if (connection->error_callback != NULL)
|
||||
return;
|
||||
connection->error_callback = callback;
|
||||
connection->error_callback_data = callback_data;
|
||||
}
|
||||
|
||||
// Call error callback if the connection is closed
|
||||
static inline void _rpc_connection_invoke_error_callback(rpc_connection_t *connection)
|
||||
{
|
||||
connection->error_callback(connection, connection->error_callback_data);
|
||||
}
|
||||
|
||||
static inline void rpc_connection_invoke_error_callback(rpc_connection_t *connection)
|
||||
{
|
||||
if (connection && connection->error_callback)
|
||||
_rpc_connection_invoke_error_callback(connection);
|
||||
}
|
||||
|
||||
// Returns connection status
|
||||
static inline int _rpc_status(rpc_connection_t *connection)
|
||||
{
|
||||
|
@ -506,13 +570,27 @@ static void _rpc_set_status(rpc_connection_t *connection, int error)
|
|||
}
|
||||
}
|
||||
|
||||
static inline int rpc_error(rpc_connection_t *connection, int error)
|
||||
// Set error status. The caller must return after a call to this function
|
||||
// e.g. the usual practise is to "return rpc_error();"
|
||||
// This is necessary because the error callback can decide to kill the
|
||||
// RPC connection in that case, so anything beyond rpc_error() should
|
||||
// be considered garbage.
|
||||
static int rpc_error(rpc_connection_t *connection, int error)
|
||||
{
|
||||
// XXX: this function must be called only in case of error
|
||||
// (otherwise, it's an internal error)
|
||||
// (otherwise, it's an internal error, hence the assert()s)
|
||||
assert(error < 0);
|
||||
assert(connection != NULL);
|
||||
_rpc_set_status(connection, error);
|
||||
|
||||
switch (_rpc_status(connection)) {
|
||||
case RPC_STATUS_CLOSED:
|
||||
case RPC_STATUS_BROKEN:
|
||||
rpc_connection_invoke_error_callback(connection);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -605,6 +683,13 @@ rpc_connection_t *rpc_init_server(const char *ident)
|
|||
connection->status = RPC_STATUS_CLOSED;
|
||||
connection->socket = -1;
|
||||
connection->server_thread_active = 0;
|
||||
connection->error_callback = NULL;
|
||||
connection->error_callback_data = NULL;
|
||||
connection->dispatch_depth = 0;
|
||||
connection->invoke_depth = 0;
|
||||
connection->handle_depth = 0;
|
||||
connection->sync_depth = 0;
|
||||
connection->pending_sync_depth = 0;
|
||||
if ((connection->types = rpc_map_new_full((free))) == NULL) {
|
||||
rpc_exit(connection);
|
||||
return NULL;
|
||||
|
@ -614,7 +699,7 @@ rpc_connection_t *rpc_init_server(const char *ident)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if ((connection->server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||
if ((connection->server_socket = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0)) < 0) {
|
||||
perror("server socket");
|
||||
rpc_exit(connection);
|
||||
return NULL;
|
||||
|
@ -665,6 +750,13 @@ rpc_connection_t *rpc_init_client(const char *ident)
|
|||
connection->refcnt = 1;
|
||||
connection->status = RPC_STATUS_CLOSED;
|
||||
connection->server_socket = -1;
|
||||
connection->error_callback = NULL;
|
||||
connection->error_callback_data = NULL;
|
||||
connection->dispatch_depth = 0;
|
||||
connection->invoke_depth = 0;
|
||||
connection->handle_depth = 0;
|
||||
connection->sync_depth = 0;
|
||||
connection->pending_sync_depth = 0;
|
||||
if ((connection->types = rpc_map_new_full((free))) == NULL) {
|
||||
rpc_exit(connection);
|
||||
return NULL;
|
||||
|
@ -674,7 +766,7 @@ rpc_connection_t *rpc_init_client(const char *ident)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if ((connection->socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||
if ((connection->socket = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0)) < 0) {
|
||||
perror("client socket");
|
||||
rpc_exit(connection);
|
||||
return NULL;
|
||||
|
@ -862,6 +954,9 @@ enum {
|
|||
RPC_MESSAGE_ACK = -3003,
|
||||
RPC_MESSAGE_REPLY = -3004,
|
||||
RPC_MESSAGE_FAILURE = -3005,
|
||||
RPC_MESSAGE_SYNC = -3006,
|
||||
RPC_MESSAGE_SYNC_END = -3007,
|
||||
RPC_MESSAGE_SYNC_ACK = -3008,
|
||||
};
|
||||
|
||||
// Message type
|
||||
|
@ -1088,20 +1183,26 @@ static int rpc_message_send_args(rpc_message_t *message, va_list args)
|
|||
case RPC_TYPE_ARRAY: {
|
||||
int i;
|
||||
int array_type = va_arg(args, int32_t);
|
||||
int array_size = va_arg(args, uint32_t);
|
||||
unsigned int array_size = va_arg(args, uint32_t);
|
||||
void *array_arg = va_arg(args, void *);
|
||||
bool is_valid_array = array_size > 0 && array_arg != NULL;
|
||||
if ((error = rpc_message_send_int32(message, array_type)) < 0)
|
||||
return error;
|
||||
if ((error = rpc_message_send_uint32(message, array_size)) < 0)
|
||||
return error;
|
||||
if ((error = rpc_message_send_char(message, is_valid_array)) < 0)
|
||||
return error;
|
||||
if (!is_valid_array)
|
||||
break;
|
||||
switch (array_type) {
|
||||
case RPC_TYPE_CHAR: {
|
||||
unsigned char *array = va_arg(args, unsigned char *);
|
||||
unsigned char *array = (unsigned char *)array_arg;
|
||||
error = rpc_message_send_bytes(message, array, array_size);
|
||||
break;
|
||||
}
|
||||
case RPC_TYPE_BOOLEAN:
|
||||
case RPC_TYPE_INT32: {
|
||||
int32_t *array = va_arg(args, int32_t *);
|
||||
int32_t *array = (int32_t *)array_arg;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
if ((error = rpc_message_send_int32(message, array[i])) < 0)
|
||||
break;
|
||||
|
@ -1109,15 +1210,31 @@ static int rpc_message_send_args(rpc_message_t *message, va_list args)
|
|||
break;
|
||||
}
|
||||
case RPC_TYPE_UINT32: {
|
||||
uint32_t *array = va_arg(args, uint32_t *);
|
||||
uint32_t *array = (uint32_t *)array_arg;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
if ((error = rpc_message_send_uint32(message, array[i])) < 0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RPC_TYPE_UINT64: {
|
||||
uint64_t *array = (uint64_t *)array_arg;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
if ((error = rpc_message_send_uint64(message, array[i])) < 0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RPC_TYPE_DOUBLE: {
|
||||
double *array = (double *)array_arg;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
if ((error = rpc_message_send_double(message, array[i])) < 0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RPC_TYPE_STRING: {
|
||||
char **array = va_arg(args, char **);
|
||||
char **array = (char **)array_arg;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
if ((error = rpc_message_send_string(message, array[i])) < 0)
|
||||
break;
|
||||
|
@ -1127,7 +1244,7 @@ static int rpc_message_send_args(rpc_message_t *message, va_list args)
|
|||
default:
|
||||
if ((desc = rpc_message_descriptor_lookup(message, array_type)) != NULL) {
|
||||
// arguments are passed by value (XXX: needs a way to differenciate reference/value)
|
||||
uint8_t *array = va_arg(args, uint8_t *);
|
||||
uint8_t *array = (uint8_t *)array_arg;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
if ((error = desc->send_callback(message, &array[i * desc->size])) < 0)
|
||||
break;
|
||||
|
@ -1342,13 +1459,21 @@ static int rpc_message_recv_args(rpc_message_t *message, va_list args)
|
|||
int i;
|
||||
int32_t array_type;
|
||||
uint32_t array_size;
|
||||
char is_valid_array;
|
||||
if ((error = rpc_message_recv_int32(message, &array_type)) < 0)
|
||||
return error;
|
||||
if ((error = rpc_message_recv_uint32(message, &array_size)) < 0)
|
||||
return error;
|
||||
if ((error = rpc_message_recv_char(message, &is_valid_array)) < 0)
|
||||
return error;
|
||||
p_value = va_arg(args, void *);
|
||||
*((uint32_t *)p_value) = array_size;
|
||||
*((int32_t *)p_value) = array_size;
|
||||
p_value = va_arg(args, void *);
|
||||
if (!is_valid_array) {
|
||||
*((void **)p_value) = NULL;
|
||||
break;
|
||||
}
|
||||
assert(array_size > 0); // otherwise, it's an internal error, see send()
|
||||
switch (array_type) {
|
||||
case RPC_TYPE_CHAR: {
|
||||
unsigned char *array;
|
||||
|
@ -1375,8 +1500,8 @@ static int rpc_message_recv_args(rpc_message_t *message, va_list args)
|
|||
break;
|
||||
}
|
||||
case RPC_TYPE_UINT32: {
|
||||
unsigned int *array;
|
||||
if ((array = (unsigned int *)malloc(array_size * sizeof(*array))) == NULL)
|
||||
uint32_t *array;
|
||||
if ((array = (uint32_t *)malloc(array_size * sizeof(*array))) == NULL)
|
||||
return RPC_ERROR_NO_MEMORY;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
uint32_t value;
|
||||
|
@ -1387,6 +1512,32 @@ static int rpc_message_recv_args(rpc_message_t *message, va_list args)
|
|||
*((void **)p_value) = (void *)array;
|
||||
break;
|
||||
}
|
||||
case RPC_TYPE_UINT64: {
|
||||
uint64_t *array;
|
||||
if ((array = (uint64_t *)malloc(array_size * sizeof(*array))) == NULL)
|
||||
return RPC_ERROR_NO_MEMORY;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
uint64_t value;
|
||||
if ((error = rpc_message_recv_uint64(message, &value)) < 0)
|
||||
return error;
|
||||
array[i] = value;
|
||||
}
|
||||
*((void **)p_value) = (void *)array;
|
||||
break;
|
||||
}
|
||||
case RPC_TYPE_DOUBLE: {
|
||||
double *array;
|
||||
if ((array = (double *)malloc(array_size * sizeof(*array))) == NULL)
|
||||
return RPC_ERROR_NO_MEMORY;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
double value;
|
||||
if ((error = rpc_message_recv_double(message, &value)) < 0)
|
||||
return error;
|
||||
array[i] = value;
|
||||
}
|
||||
*((void **)p_value) = (void *)array;
|
||||
break;
|
||||
}
|
||||
case RPC_TYPE_STRING: {
|
||||
char **array;
|
||||
if ((array = (char **)malloc(array_size * sizeof(*array))) == NULL)
|
||||
|
@ -1484,7 +1635,7 @@ static inline rpc_method_callback_t rpc_lookup_callback(rpc_connection_t *connec
|
|||
}
|
||||
|
||||
// Dispatch message received in the server loop
|
||||
static int _rpc_dispatch(rpc_connection_t *connection, rpc_message_t *message)
|
||||
static int _rpc_dispatch_1(rpc_connection_t *connection, rpc_message_t *message)
|
||||
{
|
||||
// recv: <invoke> (body: <method-id> MESSAGE_END
|
||||
D(bug("receiving message\n"));
|
||||
|
@ -1531,6 +1682,62 @@ static int _rpc_dispatch(rpc_connection_t *connection, rpc_message_t *message)
|
|||
return method;
|
||||
}
|
||||
|
||||
static int _rpc_dispatch(rpc_connection_t *connection, rpc_message_t *message)
|
||||
{
|
||||
++connection->dispatch_depth;
|
||||
int ret = _rpc_dispatch_1(connection, message);
|
||||
--connection->dispatch_depth;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
assert(expected_msg_tag != 0);
|
||||
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;
|
||||
switch (msg_tag) {
|
||||
case RPC_MESSAGE_SYNC:
|
||||
if (!_rpc_connection_is_sync_allowed(connection))
|
||||
return RPC_ERROR_MESSAGE_SYNC_NOT_ALLOWED;
|
||||
connection->pending_sync_depth = connection->invoke_depth;
|
||||
break;
|
||||
case RPC_MESSAGE_START:
|
||||
if ((error = _rpc_dispatch(connection, message)) < 0)
|
||||
return error;
|
||||
break;
|
||||
default:
|
||||
return RPC_ERROR_MESSAGE_TYPE_INVALID;
|
||||
}
|
||||
}
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
// Dispatch pending remote calls in SYNC mode (i.e. until MESSAGE_SYNC_END)
|
||||
static int _rpc_dispatch_sync(rpc_connection_t *connection)
|
||||
{
|
||||
rpc_message_t message;
|
||||
rpc_message_init(&message, connection);
|
||||
|
||||
// send: MESSAGE_SYNC_ACK
|
||||
int error = rpc_message_send_int32(&message, RPC_MESSAGE_SYNC_ACK);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return error;
|
||||
error = rpc_message_flush(&message);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return error;
|
||||
|
||||
// call: rpc_dispatch() (pending remote calls)
|
||||
// recv: MESSAGE_SYNC_END
|
||||
return _rpc_dispatch_until(connection, &message, RPC_MESSAGE_SYNC_END);
|
||||
}
|
||||
|
||||
// Dispatch message received in the server loop (public entry point)
|
||||
int rpc_dispatch(rpc_connection_t *connection)
|
||||
{
|
||||
int32_t msg_tag;
|
||||
|
@ -1541,6 +1748,8 @@ int rpc_dispatch(rpc_connection_t *connection)
|
|||
int error = rpc_message_recv_int32(&message, &msg_tag);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
if (msg_tag == RPC_MESSAGE_SYNC) // optional
|
||||
return _rpc_dispatch_sync(connection);
|
||||
if (msg_tag != RPC_MESSAGE_START)
|
||||
return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
|
||||
|
||||
|
@ -1550,35 +1759,6 @@ int rpc_dispatch(rpc_connection_t *connection)
|
|||
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 === */
|
||||
|
@ -1653,26 +1833,66 @@ int rpc_connection_remove_method_descriptors(rpc_connection_t *connection, const
|
|||
/* === Remote Procedure Call (method invocation) === */
|
||||
/* ====================================================================== */
|
||||
|
||||
// Invoke remote procedure (client side)
|
||||
int rpc_method_invoke(rpc_connection_t *connection, int method, ...)
|
||||
// Returns whether it is possible to rpc_method_invoke() now or not
|
||||
bool rpc_method_invoke_possible(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("rpc_method_invoke method=%d\n", method));
|
||||
|
||||
if (connection == NULL)
|
||||
return RPC_ERROR_CONNECTION_NULL;
|
||||
if (_rpc_status(connection) == RPC_STATUS_CLOSED)
|
||||
return RPC_ERROR_CONNECTION_CLOSED;
|
||||
if (rpc_status(connection) != RPC_STATUS_ACTIVE)
|
||||
return false;
|
||||
/* XXX: at this time, we can can call rpc_method_invoke() only if we
|
||||
are not processing incoming calls already or if we are
|
||||
"synchronized" with the other side. i.e. we are between an
|
||||
rpc_method_get_args() and rpc_method_send_reply() in an RPC handler
|
||||
function. */
|
||||
return connection->dispatch_depth == connection->handle_depth;
|
||||
}
|
||||
|
||||
// Invoke remote procedure (client side)
|
||||
static int _rpc_method_invoke_valist(rpc_connection_t *connection, int method, va_list args)
|
||||
{
|
||||
rpc_message_t message;
|
||||
rpc_message_init(&message, connection);
|
||||
|
||||
// call: rpc_dispatch() (pending remote calls)
|
||||
int error = _rpc_dispatch_until(connection, &message, 0);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
/* Strategy to synchronize the connections.
|
||||
|
||||
The purpose of connection synchronization is to ensure that the
|
||||
other end is ready to receive our rpc_method_invoke() calls,
|
||||
i.e. make sure it is not already processing RPC, or has not
|
||||
started an rpc_method_invoke() call itself.
|
||||
|
||||
There are two locations where it is safe to process incoming RPC:
|
||||
- rpc_dispatch(), i.e. from the public entry-point
|
||||
- rpc_method_wait_for_reply(), while waiting for MESSAGE_REPLY
|
||||
|
||||
Otherwise, we need to synchronize both ends:
|
||||
- Send MSG_SYNC, and block until we get MSG_SYNC_ACK
|
||||
- Process any pending calls while we are blocked
|
||||
- Honour MSG_SYNC in either rpc_dispatch() or at the end of
|
||||
rpc_method_wait_for_reply(), i.e. while there is nothing else
|
||||
to process, and until MSG_SYNC_END actually
|
||||
*/
|
||||
bool is_sync_mode = _rpc_connection_is_sync_mode(connection);
|
||||
if (is_sync_mode && !_rpc_connection_is_sync(connection)) {
|
||||
assert(connection->sync_depth == 0);
|
||||
assert(connection->invoke_depth == 1);
|
||||
|
||||
// send: MESSAGE_SYNC
|
||||
int error = rpc_message_send_int32(&message, RPC_MESSAGE_SYNC);
|
||||
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);
|
||||
|
||||
// call: rpc_dispatch() (pending remote calls)
|
||||
error = _rpc_dispatch_until(connection, &message, RPC_MESSAGE_SYNC_ACK);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
|
||||
connection->sync_depth = connection->invoke_depth;
|
||||
}
|
||||
|
||||
// send: <invoke> = MESSAGE_START <method-id> MESSAGE_END
|
||||
error = rpc_message_send_int32(&message, RPC_MESSAGE_START);
|
||||
int 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);
|
||||
|
@ -1686,16 +1906,14 @@ int rpc_method_invoke(rpc_connection_t *connection, int method, ...)
|
|||
return rpc_error(connection, error);
|
||||
|
||||
// send optional arguments
|
||||
va_list args;
|
||||
va_start(args, method);
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
int arg_type = va_arg(args, int);
|
||||
va_end(args);
|
||||
if (arg_type != RPC_TYPE_INVALID) {
|
||||
|
||||
// send: <method-args> = MESSAGE_ARGS [ <arg-type> <arg-value> ]+ MESSAGE_END
|
||||
va_start(args, method);
|
||||
error = rpc_message_send_args(&message, args);
|
||||
va_end(args);
|
||||
error = rpc_message_send_args(&message, args_copy);
|
||||
va_end(args_copy);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
error = rpc_message_flush(&message);
|
||||
|
@ -1703,17 +1921,46 @@ int rpc_method_invoke(rpc_connection_t *connection, int method, ...)
|
|||
return rpc_error(connection, error);
|
||||
}
|
||||
|
||||
// wait: MESSAGE_ACK
|
||||
error = _rpc_dispatch_until(connection, &message, RPC_MESSAGE_ACK);
|
||||
if (error == RPC_ERROR_ERRNO_SET)
|
||||
perror("rpc_method_invoke");
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
int rpc_method_invoke(rpc_connection_t *connection, int method, ...)
|
||||
{
|
||||
D(bug("rpc_method_invoke method=%d\n", method));
|
||||
|
||||
if (connection == NULL)
|
||||
return RPC_ERROR_CONNECTION_NULL;
|
||||
if (_rpc_status(connection) == RPC_STATUS_CLOSED)
|
||||
return RPC_ERROR_CONNECTION_CLOSED;
|
||||
|
||||
++connection->invoke_depth;
|
||||
|
||||
va_list args;
|
||||
va_start(args, method);
|
||||
int ret = _rpc_method_invoke_valist(connection, method, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Retrieve procedure arguments (server side)
|
||||
static int _rpc_method_get_args_valist(rpc_connection_t *connection, va_list args)
|
||||
{
|
||||
rpc_message_t message;
|
||||
rpc_message_init(&message, connection);
|
||||
|
||||
// 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>
|
||||
int error = rpc_message_recv_args(&message, args);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
// Retrieve procedure arguments (server side)
|
||||
int rpc_method_get_args(rpc_connection_t *connection, ...)
|
||||
{
|
||||
D(bug("rpc_method_get_args\n"));
|
||||
|
@ -1723,42 +1970,19 @@ int rpc_method_get_args(rpc_connection_t *connection, ...)
|
|||
if (_rpc_status(connection) == RPC_STATUS_CLOSED)
|
||||
return RPC_ERROR_CONNECTION_CLOSED;
|
||||
|
||||
rpc_message_t message;
|
||||
rpc_message_init(&message, connection);
|
||||
++connection->handle_depth;
|
||||
|
||||
// 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);
|
||||
int ret = _rpc_method_get_args_valist(connection, args);
|
||||
va_end(args);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
|
||||
// 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);
|
||||
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Wait for a reply from the remote procedure (client side)
|
||||
int rpc_method_wait_for_reply(rpc_connection_t *connection, ...)
|
||||
static int _rpc_method_wait_for_reply_valist(rpc_connection_t *connection, va_list args)
|
||||
{
|
||||
D(bug("rpc_method_wait_for_reply\n"));
|
||||
|
||||
if (connection == NULL)
|
||||
return RPC_ERROR_CONNECTION_NULL;
|
||||
if (_rpc_status(connection) == RPC_STATUS_CLOSED)
|
||||
return RPC_ERROR_CONNECTION_CLOSED;
|
||||
|
||||
int error;
|
||||
int32_t msg_tag;
|
||||
rpc_message_t message;
|
||||
|
@ -1771,16 +1995,14 @@ int rpc_method_wait_for_reply(rpc_connection_t *connection, ...)
|
|||
return rpc_error(connection, error);
|
||||
|
||||
// receive optional arguments
|
||||
va_list args;
|
||||
va_start(args, connection);
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
int type = va_arg(args, int);
|
||||
va_end(args);
|
||||
if (type != RPC_TYPE_INVALID) {
|
||||
|
||||
// recv: [ <method-args> ]
|
||||
va_start(args, connection);
|
||||
error = rpc_message_recv_args(&message, args);
|
||||
va_end(args);
|
||||
error = rpc_message_recv_args(&message, args_copy);
|
||||
va_end(args_copy);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
}
|
||||
|
@ -1792,26 +2014,59 @@ int rpc_method_wait_for_reply(rpc_connection_t *connection, ...)
|
|||
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);
|
||||
|
||||
// send: MESSAGE_SYNC_END (done pending message)
|
||||
if (connection->sync_depth) {
|
||||
if (connection->sync_depth == connection->invoke_depth) {
|
||||
assert(connection->invoke_depth == 1);
|
||||
|
||||
// send: MESSAGE_SYNC_END
|
||||
int error = rpc_message_send_int32(&message, RPC_MESSAGE_SYNC_END);
|
||||
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);
|
||||
|
||||
connection->sync_depth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// send: MESSAGE_SYNC_ACK (pending message)
|
||||
if (connection->pending_sync_depth) {
|
||||
if (connection->pending_sync_depth == connection->invoke_depth) {
|
||||
assert(connection->invoke_depth == 1);
|
||||
assert(_rpc_wait_dispatch(connection, 0) == 0);
|
||||
|
||||
connection->pending_sync_depth = 0;
|
||||
return _rpc_dispatch_sync(connection);
|
||||
}
|
||||
}
|
||||
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
// Send a reply to the client (server side)
|
||||
int rpc_method_send_reply(rpc_connection_t *connection, ...)
|
||||
int rpc_method_wait_for_reply(rpc_connection_t *connection, ...)
|
||||
{
|
||||
D(bug("rpc_method_send_reply\n"));
|
||||
D(bug("rpc_method_wait_for_reply\n"));
|
||||
|
||||
if (connection == NULL)
|
||||
return RPC_ERROR_CONNECTION_NULL;
|
||||
if (_rpc_status(connection) == RPC_STATUS_CLOSED)
|
||||
return RPC_ERROR_CONNECTION_CLOSED;
|
||||
|
||||
va_list args;
|
||||
va_start(args, connection);
|
||||
int ret = _rpc_method_wait_for_reply_valist(connection, args);
|
||||
va_end(args);
|
||||
|
||||
--connection->invoke_depth;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Send a reply to the client (server side)
|
||||
static int _rpc_method_send_reply_valist(rpc_connection_t *connection, va_list args)
|
||||
{
|
||||
rpc_message_t message;
|
||||
rpc_message_init(&message, connection);
|
||||
|
||||
|
@ -1819,10 +2074,7 @@ int rpc_method_send_reply(rpc_connection_t *connection, ...)
|
|||
int error = rpc_message_send_int32(&message, RPC_MESSAGE_REPLY);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
va_list args;
|
||||
va_start(args, connection);
|
||||
error = rpc_message_send_args(&message, args);
|
||||
va_end(args);
|
||||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
error = rpc_message_send_int32(&message, RPC_MESSAGE_END);
|
||||
|
@ -1832,17 +2084,28 @@ int rpc_method_send_reply(rpc_connection_t *connection, ...)
|
|||
if (error != RPC_ERROR_NO_ERROR)
|
||||
return rpc_error(connection, error);
|
||||
|
||||
// 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);
|
||||
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
int rpc_method_send_reply(rpc_connection_t *connection, ...)
|
||||
{
|
||||
D(bug("rpc_method_send_reply\n"));
|
||||
|
||||
if (connection == NULL)
|
||||
return RPC_ERROR_CONNECTION_NULL;
|
||||
if (_rpc_status(connection) == RPC_STATUS_CLOSED)
|
||||
return RPC_ERROR_CONNECTION_CLOSED;
|
||||
|
||||
va_list args;
|
||||
va_start(args, connection);
|
||||
int ret = _rpc_method_send_reply_valist(connection, args);
|
||||
va_end(args);
|
||||
|
||||
--connection->handle_depth;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === Test Program === */
|
||||
|
|
|
@ -41,6 +41,7 @@ enum {
|
|||
RPC_ERROR_MESSAGE_ARGUMENT_MISMATCH = -1010,
|
||||
RPC_ERROR_MESSAGE_ARGUMENT_UNKNOWN = -1011,
|
||||
RPC_ERROR_MESSAGE_ARGUMENT_INVALID = -1012,
|
||||
RPC_ERROR_MESSAGE_SYNC_NOT_ALLOWED = -1013,
|
||||
};
|
||||
extern const char *rpc_strerror(int error) attribute_hidden;
|
||||
|
||||
|
@ -113,6 +114,7 @@ extern int rpc_connection_add_method_descriptor(rpc_connection_t *connection, co
|
|||
extern int rpc_connection_add_method_descriptors(rpc_connection_t *connection, const rpc_method_descriptor_t *descs, int n_descs) attribute_hidden;
|
||||
|
||||
// Remote Procedure Call (method invocation)
|
||||
extern bool rpc_method_invoke_possible(rpc_connection_t *connection) attribute_hidden;
|
||||
extern int rpc_method_invoke(rpc_connection_t *connection, int method, ...) attribute_hidden;
|
||||
extern int rpc_method_wait_for_reply(rpc_connection_t *connection, ...) attribute_hidden;
|
||||
extern int rpc_method_get_args(rpc_connection_t *connection, ...) attribute_hidden;
|
||||
|
@ -122,4 +124,10 @@ extern int rpc_method_send_reply(rpc_connection_t *connection, ...) attribute_hi
|
|||
}
|
||||
#endif
|
||||
|
||||
// This callback is called when the connection is closed or broken
|
||||
typedef void (*rpc_error_callback_t)(rpc_connection_t *connection, void *user_data);
|
||||
|
||||
// Set error callback for a connection
|
||||
void rpc_connection_set_error_callback(rpc_connection_t *connection, rpc_error_callback_t callback, void *callback_data);
|
||||
|
||||
#endif /* RPC_H */
|
||||
|
|
119
src/utils.c
119
src/utils.c
|
@ -18,12 +18,17 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <glib.h> /* <glib/ghash.h> */
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "rpc.h"
|
||||
|
@ -51,7 +56,9 @@ static inline void *id_key(uint32_t id)
|
|||
|
||||
bool id_init(void)
|
||||
{
|
||||
return (g_ids = g_hash_table_new(NULL, NULL)) != NULL;
|
||||
if (g_ids == NULL)
|
||||
g_ids = g_hash_table_new(NULL, NULL);
|
||||
return g_ids != NULL;
|
||||
}
|
||||
|
||||
void id_kill(void)
|
||||
|
@ -219,6 +226,64 @@ const char *string_of_NPEvent_type(int type)
|
|||
|
||||
return str;
|
||||
}
|
||||
|
||||
const char *string_of_NPPVariable(int variable)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
switch (variable) {
|
||||
#define _(VAL) case VAL: str = #VAL; break;
|
||||
_(NPPVpluginNameString);
|
||||
_(NPPVpluginDescriptionString);
|
||||
_(NPPVpluginWindowBool);
|
||||
_(NPPVpluginTransparentBool);
|
||||
_(NPPVjavaClass);
|
||||
_(NPPVpluginWindowSize);
|
||||
_(NPPVpluginTimerInterval);
|
||||
_(NPPVpluginScriptableInstance);
|
||||
_(NPPVpluginScriptableIID);
|
||||
_(NPPVjavascriptPushCallerBool);
|
||||
_(NPPVpluginKeepLibraryInMemory);
|
||||
_(NPPVpluginNeedsXEmbed);
|
||||
_(NPPVpluginScriptableNPObject);
|
||||
_(NPPVformValue);
|
||||
#undef _
|
||||
default:
|
||||
str = "<unknown variable>";
|
||||
break;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
const char *string_of_NPNVariable(int variable)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
switch (variable) {
|
||||
#define _(VAL) case VAL: str = #VAL; break;
|
||||
_(NPNVxDisplay);
|
||||
_(NPNVxtAppContext);
|
||||
_(NPNVnetscapeWindow);
|
||||
_(NPNVjavascriptEnabledBool);
|
||||
_(NPNVasdEnabledBool);
|
||||
_(NPNVisOfflineBool);
|
||||
_(NPNVserviceManager);
|
||||
_(NPNVDOMElement);
|
||||
_(NPNVDOMWindow);
|
||||
_(NPNVToolkit);
|
||||
_(NPNVSupportsXEmbedBool);
|
||||
_(NPNVWindowNPObject);
|
||||
_(NPNVPluginElementNPObject);
|
||||
_(NPNVSupportsWindowless);
|
||||
#undef _
|
||||
default:
|
||||
str = "<unknown variable>";
|
||||
break;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -265,6 +330,58 @@ char *npw_asprintf(const char *format, ...)
|
|||
return str;
|
||||
}
|
||||
|
||||
/* Return 1 + max value the system can allocate to a new fd */
|
||||
static int get_open_max(void)
|
||||
{
|
||||
int open_max = -1;
|
||||
/* SCO OpenServer has an fcntl() to retrieve the highest *currently
|
||||
open* file descriptor. */
|
||||
#ifdef F_GETHFDO
|
||||
if ((open_max = fcntl(-1, F_GETHFDO, 0)) >= 0)
|
||||
return open_max + 1;
|
||||
#endif
|
||||
/* IEEE Std 1003.1-2001/Cor 1-2002 clarified the fact that return
|
||||
value of sysconf(_SC_OPEN_MAX) may change if setrlimit() was
|
||||
called to set RLIMIT_NOFILE. So, we should be on the safe side to
|
||||
call getrlimit() first to get the soft limit.
|
||||
|
||||
Note: dgettablesize() was a possibility but (i) it's equivalent
|
||||
to getrlimit(), and (ii) it is not recommended for new code. */
|
||||
struct rlimit ru;
|
||||
if (getrlimit(RLIMIT_NOFILE, &ru) == 0)
|
||||
return ru.rlim_cur;
|
||||
if ((open_max = sysconf(_SC_OPEN_MAX)) >= 0)
|
||||
return open_max;
|
||||
/* XXX: simply guess something reasonable. */
|
||||
return 256;
|
||||
}
|
||||
|
||||
void npw_close_all_open_files(void)
|
||||
{
|
||||
const int min_fd = 3;
|
||||
|
||||
DIR *dir = opendir("/proc/self/fd");
|
||||
if (dir) {
|
||||
const int dfd = dirfd(dir);
|
||||
struct dirent *d;
|
||||
while ((d = readdir(dir)) != NULL) {
|
||||
char *end;
|
||||
long n = strtol(d->d_name, &end, 10);
|
||||
if (*end == '\0') {
|
||||
int fd = n;
|
||||
if (fd >= min_fd && fd != dfd)
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
else {
|
||||
const int open_max = get_open_max();
|
||||
for (int fd = min_fd; fd < open_max; fd++)
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === Test Program === */
|
||||
|
|
|
@ -39,11 +39,14 @@ extern const char *string_of_NPError(int error) attribute_hidden;
|
|||
extern const char *string_of_NPReason(int reason) attribute_hidden;
|
||||
extern const char *string_of_NPStreamType(int stype) attribute_hidden;
|
||||
extern const char *string_of_NPEvent_type(int type) attribute_hidden;
|
||||
extern const char *string_of_NPPVariable(int variable) attribute_hidden;
|
||||
extern const char *string_of_NPNVariable(int variable) attribute_hidden;
|
||||
|
||||
// Misc utility functions
|
||||
extern void npw_perror(const char *prefix, int error) attribute_hidden;
|
||||
extern const char *npw_strerror(int error) attribute_hidden;
|
||||
extern char *npw_asprintf(const char *format, ...) attribute_hidden;
|
||||
extern void npw_close_all_open_files(void) attribute_hidden;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ Various sample data to exercise the NPAPI plugins compatibility layer
|
|||
<li><p><b>Tcl Plugin Demos</b><br>
|
||||
<a href="http://www.tcl.tk/software/plugin/applets.html">http://www.tcl.tk/software/plugin/applets.html</a>
|
||||
<li><p><b>Squeak VM plugin tests</b><br>
|
||||
<a href="http://www.squeakland.org/plugin/launch.html">http://www.squeakland.org/plugin/launch.html</a>
|
||||
<a href="http://wiki.squeak.org/squeak/5858">http://wiki.squeak.org/squeak/5858</a>
|
||||
<li><p><b>Citrix ICA Client demo</b><br>
|
||||
<a href="http://www.rentonlinesoftware.com/store/tryademo.asp">http://www.rentonlinesoftware.com/store/tryademo.asp</a>
|
||||
</ul>
|
||||
|
|
|
@ -46,7 +46,6 @@ 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
|
||||
|
@ -54,9 +53,9 @@ 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;
|
||||
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;
|
||||
g_test.funcs.post_dispatch_hook = funcs->post_dispatch_hook;
|
||||
}
|
||||
|
||||
rpc_connection_t *
|
||||
|
@ -71,10 +70,10 @@ 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_exit_status = status;
|
||||
g_main_loop_quit (g_main_loop);
|
||||
if (g_child_watch_id)
|
||||
g_source_remove (g_child_watch_id);
|
||||
g_source_remove (g_child_watch_id);
|
||||
g_spawn_close_pid (pid);
|
||||
}
|
||||
|
||||
|
@ -82,12 +81,12 @@ static void
|
|||
kill_child_now (void)
|
||||
{
|
||||
if (g_child_watch_id)
|
||||
g_source_remove (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);
|
||||
}
|
||||
{
|
||||
g_spawn_close_pid (g_child_pid);
|
||||
kill (g_child_pid, SIGTERM);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -97,7 +96,6 @@ urgent_exit_sig (int sig)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SERVER
|
||||
static gboolean
|
||||
rpc_event_prepare (GSource *source, gint *timeout)
|
||||
{
|
||||
|
@ -117,15 +115,15 @@ 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;
|
||||
}
|
||||
{
|
||||
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);
|
||||
g_test.funcs.post_dispatch_hook (g_test.user_data);
|
||||
|
||||
return rc != RPC_ERROR_CONNECTION_CLOSED;
|
||||
}
|
||||
|
@ -137,14 +135,13 @@ 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
|
||||
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)
|
||||
|
@ -152,12 +149,12 @@ 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);
|
||||
rc = rpc_test_execute (g_test.user_data);
|
||||
RPC_TEST_ENSURE ((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);
|
||||
rpc_test_exit_full (0);
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -169,15 +166,15 @@ clone_args (gchar **args)
|
|||
gint i, n, rc = 0;
|
||||
|
||||
if ((new_args = g_strdupv (args)) == NULL)
|
||||
g_error ("could not duplicate the program arguments");
|
||||
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);
|
||||
RPC_TEST_ENSURE (n >= 2);
|
||||
g_free (new_args[1]);
|
||||
for (i = 1; i < n - 1; i++)
|
||||
new_args[i] = new_args[i + 1];
|
||||
new_args[i] = new_args[i + 1];
|
||||
new_args[i] = NULL;
|
||||
#endif
|
||||
|
||||
|
@ -191,13 +188,13 @@ rpc_test_init_invoke (gchar **program_args)
|
|||
gint n, rc = 0;
|
||||
|
||||
if ((args = clone_args (program_args)) == NULL)
|
||||
g_error ("could not clone program arguments");
|
||||
g_error ("could not clone program arguments");
|
||||
n = g_strv_length (args);
|
||||
|
||||
if (rpc_test_init)
|
||||
rc = rpc_test_init (n, args);
|
||||
rc = rpc_test_init (n, args);
|
||||
g_strfreev (args);
|
||||
g_assert (rc == 0);
|
||||
RPC_TEST_ENSURE (rc == 0);
|
||||
|
||||
g_timeout_add (0, rpc_test_execute_cb, NULL);
|
||||
}
|
||||
|
@ -206,11 +203,7 @@ 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_exit_status = status;
|
||||
g_main_loop_quit (g_main_loop);
|
||||
}
|
||||
|
||||
|
@ -220,9 +213,9 @@ 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);
|
||||
RPC_TEST_METHOD_EXIT,
|
||||
RPC_TYPE_INT32, status,
|
||||
RPC_TYPE_INVALID);
|
||||
#endif
|
||||
|
||||
rpc_test_exit (status);
|
||||
|
@ -235,11 +228,11 @@ handle_rpc_test_exit (rpc_connection_t *connection)
|
|||
gint32 status;
|
||||
|
||||
error = rpc_method_get_args (connection,
|
||||
RPC_TYPE_INT32, &status,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TYPE_INT32, &status,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
if (error == RPC_ERROR_NO_ERROR)
|
||||
rpc_test_exit (status);
|
||||
rpc_test_exit (status);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -248,15 +241,15 @@ int
|
|||
main (int argc, char *argv[])
|
||||
{
|
||||
if (rpc_test_get_connection_path)
|
||||
g_connection_path = rpc_test_get_connection_path ();
|
||||
g_connection_path = rpc_test_get_connection_path ();
|
||||
else
|
||||
g_connection_path = NPW_CONNECTION_PATH "/Test.RPC";
|
||||
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");
|
||||
g_error ("no server program provided on command line");
|
||||
|
||||
signal (SIGSEGV, urgent_exit_sig);
|
||||
signal (SIGBUS, urgent_exit_sig);
|
||||
|
@ -264,49 +257,59 @@ main (int argc, char *argv[])
|
|||
signal (SIGABRT, urgent_exit_sig);
|
||||
|
||||
if ((child_args = clone_args (argv)) == NULL)
|
||||
g_error ("could not create server program arguments\n");
|
||||
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]);
|
||||
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");
|
||||
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");
|
||||
g_error ("failed to initialize RPC server connection");
|
||||
#endif
|
||||
|
||||
GSource *rpc_source;
|
||||
int fd = -1;
|
||||
GSource *rpc_source = NULL;
|
||||
guint rpc_source_id = 0;
|
||||
GPollFD rpc_event_poll_fd;
|
||||
|
||||
if ((rpc_source = g_source_new (&rpc_event_funcs, sizeof (GSource))) == NULL)
|
||||
g_error ("failed to initialize RPC source");
|
||||
#ifdef BUILD_CLIENT
|
||||
fd = rpc_socket (g_connection);
|
||||
#endif
|
||||
#ifdef BUILD_SERVER
|
||||
fd = rpc_listen_socket (g_connection);
|
||||
#endif
|
||||
RPC_TEST_ENSURE (fd >= 0);
|
||||
|
||||
g_source_id = g_source_attach (rpc_source, NULL);
|
||||
if ((rpc_source = g_source_new (&rpc_event_funcs, sizeof (GSource))) == NULL)
|
||||
g_error ("failed to initialize RPC source");
|
||||
|
||||
rpc_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.fd = fd;
|
||||
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 }
|
||||
{ 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_error ("could not add method descriptor for TEST_RPC_METHOD_EXIT");
|
||||
|
||||
g_main_loop = g_main_loop_new (NULL, TRUE);
|
||||
#ifdef BUILD_CLIENT
|
||||
|
@ -314,5 +317,9 @@ main (int argc, char *argv[])
|
|||
#endif
|
||||
rpc_test_init_invoke (argv);
|
||||
g_main_loop_run (g_main_loop);
|
||||
if (rpc_source_id)
|
||||
g_source_remove (rpc_source_id);
|
||||
if (g_connection)
|
||||
rpc_exit (g_connection);
|
||||
return g_exit_status;
|
||||
}
|
||||
|
|
|
@ -26,17 +26,37 @@
|
|||
|
||||
enum
|
||||
{
|
||||
/* void rpc_test_exit (int status); */
|
||||
RPC_TEST_METHOD_EXIT = 0,
|
||||
/* 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,
|
||||
RPC_TEST_EXECUTE_SUCCESS = 0,
|
||||
RPC_TEST_EXECUTE_FAILURE = 1,
|
||||
RPC_TEST_EXECUTE_DONT_QUIT = 0x8000,
|
||||
};
|
||||
|
||||
#define RPC_TEST_ENSURE(expr) do { \
|
||||
if (!(expr)) { \
|
||||
npw_printf ("ERROR:(%s:%d):%s: assertion failed: (%s)\n", \
|
||||
__FILE__, __LINE__, __func__, #expr); \
|
||||
abort (); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RPC_TEST_ENSURE_ERROR(error, error_code) do { \
|
||||
if ((error) != (error_code)) { \
|
||||
npw_printf ("ERROR:(%s:%d):%s: %s\n", \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
rpc_strerror (error)); \
|
||||
abort (); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RPC_TEST_ENSURE_NO_ERROR(error) \
|
||||
RPC_TEST_ENSURE_ERROR(error, RPC_ERROR_NO_ERROR)
|
||||
|
||||
typedef struct _RPCTestFuncs RPCTestFuncs;
|
||||
struct _RPCTestFuncs
|
||||
{
|
||||
|
|
|
@ -29,74 +29,134 @@
|
|||
|
||||
enum
|
||||
{
|
||||
RPC_TEST_METHOD_PRINT = 1
|
||||
RPC_TEST_METHOD_STEP = 1,
|
||||
RPC_TEST_METHOD_DONE
|
||||
};
|
||||
|
||||
static gboolean g_is_silent = TRUE;
|
||||
static gint g_print_count = 5000;
|
||||
static gboolean g_is_silent = TRUE;
|
||||
static gint g_n_steps = 5000;
|
||||
static gboolean g_got_done = FALSE;
|
||||
|
||||
static void
|
||||
invoke_print (const gchar *str)
|
||||
invoke_step (int n)
|
||||
{
|
||||
rpc_connection_t *connection;
|
||||
int error;
|
||||
int32_t ret;
|
||||
|
||||
connection = rpc_test_get_connection ();
|
||||
RPC_TEST_ENSURE (connection != NULL);
|
||||
|
||||
error = rpc_method_invoke (connection,
|
||||
RPC_TEST_METHOD_STEP,
|
||||
RPC_TYPE_INT32, n,
|
||||
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. */
|
||||
RPC_TEST_ENSURE (error != RPC_ERROR_MESSAGE_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
error = rpc_method_wait_for_reply (connection,
|
||||
RPC_TYPE_INT32, &ret,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
RPC_TEST_ENSURE (ret == n);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_step (rpc_connection_t *connection)
|
||||
{
|
||||
int32_t n;
|
||||
int error;
|
||||
|
||||
error = rpc_method_get_args (connection,
|
||||
RPC_TYPE_INT32, &n,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
if (!g_is_silent)
|
||||
npw_printf ("Got message %d from the other end\n", n);
|
||||
|
||||
error = rpc_method_send_reply (connection,
|
||||
RPC_TYPE_INT32, n,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
invoke_done (void)
|
||||
{
|
||||
rpc_connection_t *connection;
|
||||
int error;
|
||||
|
||||
connection = rpc_test_get_connection ();
|
||||
g_assert (connection != NULL);
|
||||
RPC_TEST_ENSURE (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);
|
||||
RPC_TEST_METHOD_DONE,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
error = rpc_method_wait_for_reply (connection, RPC_TYPE_INVALID);
|
||||
g_assert (error == RPC_ERROR_NO_ERROR);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_print (rpc_connection_t *connection)
|
||||
handle_done (rpc_connection_t *connection)
|
||||
{
|
||||
char *str;
|
||||
int error;
|
||||
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);
|
||||
error = rpc_method_get_args (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
if (!g_is_silent)
|
||||
npw_printf ("Got message from the other end: '%s'\n", str);
|
||||
free (str);
|
||||
g_got_done = TRUE;
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
#ifdef BUILD_CLIENT
|
||||
if (g_n_steps == 0)
|
||||
rpc_test_exit_full (0);
|
||||
#endif
|
||||
|
||||
error = rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static inline void
|
||||
print_msg (void)
|
||||
do_step (int n)
|
||||
{
|
||||
invoke_print ("Hello from " NPW_COMPONENT_NAME);
|
||||
invoke_step (n);
|
||||
}
|
||||
|
||||
static inline void
|
||||
do_done (void)
|
||||
{
|
||||
invoke_done ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
invoke_print_cb (gpointer user_data)
|
||||
invoke_step_cb (gpointer user_data)
|
||||
{
|
||||
print_msg ();
|
||||
do_step (g_n_steps);
|
||||
|
||||
--g_print_count;
|
||||
if (--g_n_steps == 0)
|
||||
{
|
||||
#ifdef BUILD_CLIENT
|
||||
if (g_print_count == 0)
|
||||
if (g_got_done)
|
||||
rpc_test_exit_full (0);
|
||||
#endif
|
||||
return g_print_count > 0;
|
||||
#ifdef BUILD_SERVER
|
||||
do_done ();
|
||||
#endif
|
||||
}
|
||||
|
||||
return g_n_steps > 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -105,50 +165,52 @@ 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (++i < argc)
|
||||
{
|
||||
unsigned long v = strtoul (argv[i], NULL, 10);
|
||||
if (v > 0)
|
||||
g_n_steps = 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);
|
||||
RPC_TEST_ENSURE (connection != NULL);
|
||||
|
||||
static const rpc_method_descriptor_t vtable[] = {
|
||||
{ RPC_TEST_METHOD_PRINT, handle_print },
|
||||
{ RPC_TEST_METHOD_STEP, handle_step },
|
||||
{ RPC_TEST_METHOD_DONE, handle_done }
|
||||
};
|
||||
|
||||
if (rpc_connection_add_method_descriptor (connection, &vtable[0]) < 0)
|
||||
g_error ("could not add method descriptors");
|
||||
if (rpc_connection_add_method_descriptors (connection, &vtable[0],
|
||||
G_N_ELEMENTS (vtable)) < 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);
|
||||
}
|
||||
{
|
||||
/* XXX: we hope to trigger concurrent rpc_method_invoke() */
|
||||
/* XXX: add a barrier to synchronize both processes? */
|
||||
//g_idle_add (invoke_step_cb, NULL);
|
||||
g_timeout_add (0, invoke_step_cb, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (--g_print_count >= 0)
|
||||
print_msg ();
|
||||
}
|
||||
{
|
||||
while (--g_n_steps >= 0)
|
||||
do_step (g_n_steps);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -157,7 +219,7 @@ rpc_test_execute (gpointer user_data)
|
|||
{
|
||||
#ifdef BUILD_CLIENT
|
||||
if (RPC_TEST_USE_IDLE)
|
||||
return RPC_TEST_EXECUTE_SUCCESS|RPC_TEST_EXECUTE_DONT_QUIT;
|
||||
return RPC_TEST_EXECUTE_SUCCESS|RPC_TEST_EXECUTE_DONT_QUIT;
|
||||
#endif
|
||||
return RPC_TEST_EXECUTE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
enum
|
||||
{
|
||||
RPC_TEST_METHOD_GET_PID = 1
|
||||
RPC_TEST_METHOD_GET_PID = 1
|
||||
};
|
||||
|
||||
static gint
|
||||
|
@ -38,17 +38,17 @@ get_remote_pid (void)
|
|||
gint32 pid;
|
||||
|
||||
connection = rpc_test_get_connection ();
|
||||
g_assert (connection != NULL);
|
||||
RPC_TEST_ENSURE (connection != NULL);
|
||||
|
||||
error = rpc_method_invoke (connection,
|
||||
RPC_TEST_METHOD_GET_PID,
|
||||
RPC_TYPE_INVALID);
|
||||
g_assert (error == RPC_ERROR_NO_ERROR);
|
||||
RPC_TEST_METHOD_GET_PID,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
error = rpc_method_wait_for_reply (connection,
|
||||
RPC_TYPE_INT32, &pid,
|
||||
RPC_TYPE_INVALID);
|
||||
g_assert (error == RPC_ERROR_NO_ERROR);
|
||||
RPC_TYPE_INT32, &pid,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
@ -78,13 +78,16 @@ handle_get_pid (rpc_connection_t *connection)
|
|||
int error;
|
||||
|
||||
error = rpc_method_get_args (connection, RPC_TYPE_INVALID);
|
||||
g_assert (error == RPC_ERROR_NO_ERROR);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
pid = get_client_pid ();
|
||||
|
||||
return rpc_method_send_reply (connection,
|
||||
RPC_TYPE_INT32, pid,
|
||||
RPC_TYPE_INVALID);
|
||||
error = rpc_method_send_reply (connection,
|
||||
RPC_TYPE_INT32, pid,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -93,14 +96,14 @@ rpc_test_init (int argc, char *argv[])
|
|||
rpc_connection_t *connection;
|
||||
|
||||
connection = rpc_test_get_connection ();
|
||||
g_assert (connection != NULL);
|
||||
RPC_TEST_ENSURE (connection != NULL);
|
||||
|
||||
static const rpc_method_descriptor_t vtable[] = {
|
||||
{ RPC_TEST_METHOD_GET_PID, handle_get_pid },
|
||||
{ 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");
|
||||
g_error ("could not add method descriptors");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -110,7 +113,7 @@ rpc_test_execute (gpointer user_data)
|
|||
{
|
||||
#ifdef BUILD_CLIENT
|
||||
gint pid = get_remote_pid ();
|
||||
g_assert (pid == get_local_pid ());
|
||||
RPC_TEST_ENSURE (pid == get_local_pid ());
|
||||
#endif
|
||||
return RPC_TEST_EXECUTE_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* test-rpc-nested-2.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_F1 = 1,
|
||||
RPC_TEST_METHOD_F2,
|
||||
RPC_TEST_METHOD_F3,
|
||||
RPC_TEST_METHOD_F4,
|
||||
RPC_TEST_METHOD_F5
|
||||
};
|
||||
|
||||
static const char *
|
||||
f_name (int method)
|
||||
{
|
||||
switch (method)
|
||||
{
|
||||
case RPC_TEST_METHOD_F1: return "f1";
|
||||
case RPC_TEST_METHOD_F2: return "f2";
|
||||
case RPC_TEST_METHOD_F3: return "f3";
|
||||
case RPC_TEST_METHOD_F4: return "f4";
|
||||
case RPC_TEST_METHOD_F5: return "f5";
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
#define print_func(pfx, method) npw_printf ("%s: %s()\n", pfx, f_name (method))
|
||||
#define print_func_SEND(method) print_func ("SEND", method)
|
||||
#define print_func_RECV(method) print_func ("RECV", method)
|
||||
|
||||
static void
|
||||
f (int method)
|
||||
{
|
||||
rpc_connection_t *connection;
|
||||
int error;
|
||||
|
||||
print_func_SEND (method);
|
||||
|
||||
connection = rpc_test_get_connection ();
|
||||
RPC_TEST_ENSURE (connection != NULL);
|
||||
|
||||
RPC_TEST_ENSURE (rpc_method_invoke_possible (connection));
|
||||
error = rpc_method_invoke (connection, method, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
error = rpc_method_wait_for_reply (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_f1 (rpc_connection_t *connection)
|
||||
{
|
||||
int error;
|
||||
|
||||
print_func_RECV (RPC_TEST_METHOD_F1);
|
||||
|
||||
error = rpc_method_get_args (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
f (RPC_TEST_METHOD_F2);
|
||||
|
||||
error = rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_fN (rpc_connection_t *connection, int method)
|
||||
{
|
||||
int error;
|
||||
|
||||
print_func_RECV (method);
|
||||
|
||||
error = rpc_method_get_args (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
error = rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_f2 (rpc_connection_t *connection)
|
||||
{
|
||||
int error;
|
||||
|
||||
print_func_RECV (RPC_TEST_METHOD_F2);
|
||||
|
||||
error = rpc_method_get_args (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
f (RPC_TEST_METHOD_F3);
|
||||
|
||||
error = rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_f3 (rpc_connection_t *connection)
|
||||
{
|
||||
int error;
|
||||
|
||||
print_func_RECV (RPC_TEST_METHOD_F3);
|
||||
|
||||
error = rpc_method_get_args (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
f (RPC_TEST_METHOD_F4);
|
||||
|
||||
error = rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
RPC_TEST_ENSURE_NO_ERROR (error);
|
||||
|
||||
f (RPC_TEST_METHOD_F5);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_f4 (rpc_connection_t *connection)
|
||||
{
|
||||
handle_fN (connection, RPC_TEST_METHOD_F4);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_f5 (rpc_connection_t *connection)
|
||||
{
|
||||
handle_fN (connection, RPC_TEST_METHOD_F5);
|
||||
}
|
||||
|
||||
int
|
||||
rpc_test_init (int argc, char *argv[])
|
||||
{
|
||||
rpc_connection_t *connection;
|
||||
|
||||
connection = rpc_test_get_connection ();
|
||||
RPC_TEST_ENSURE (connection != NULL);
|
||||
|
||||
static const rpc_method_descriptor_t vtable[] = {
|
||||
{ RPC_TEST_METHOD_F1, handle_f1 },
|
||||
{ RPC_TEST_METHOD_F2, handle_f2 },
|
||||
{ RPC_TEST_METHOD_F3, handle_f3 },
|
||||
{ RPC_TEST_METHOD_F4, handle_f4 },
|
||||
{ RPC_TEST_METHOD_F5, handle_f5 }
|
||||
};
|
||||
|
||||
if (rpc_connection_add_method_descriptors (connection, &vtable[0],
|
||||
G_N_ELEMENTS (vtable)) < 0)
|
||||
g_error ("could not add method descriptors");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rpc_test_execute (gpointer user_data)
|
||||
{
|
||||
#ifdef BUILD_CLIENT
|
||||
f (RPC_TEST_METHOD_F1);
|
||||
#endif
|
||||
npw_printf ("done\n");
|
||||
return RPC_TEST_EXECUTE_SUCCESS;
|
||||
}
|
|
@ -30,16 +30,24 @@
|
|||
|
||||
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,
|
||||
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,
|
||||
RPC_TEST_METHOD_VOID__CHAR_ARRAY,
|
||||
RPC_TEST_METHOD_VOID__INT32_ARRAY,
|
||||
RPC_TEST_METHOD_VOID__UINT64_ARRAY,
|
||||
RPC_TEST_METHOD_VOID__DOUBLE_ARRAY,
|
||||
RPC_TEST_METHOD_VOID__STRING_ARRAY,
|
||||
RPC_TEST_METHOD_VOID__NULL_ARRAY,
|
||||
RPC_TEST_METHOD_VOID__0LEN_ARRAY,
|
||||
RPC_TEST_METHOD_VOID__MIXED_ARRAY
|
||||
};
|
||||
|
||||
const gchar *
|
||||
|
@ -57,85 +65,116 @@ rpc_test_signature (gboolean is_invoke, ...)
|
|||
GString *str;
|
||||
|
||||
if ((str = g_string_new (NULL)) == NULL)
|
||||
return;
|
||||
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, ", ");
|
||||
if (was_array)
|
||||
{
|
||||
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_arg (args, guint32);
|
||||
if (is_invoke)
|
||||
va_arg (args, gpointer);
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case RPC_TYPE_CHAR:
|
||||
g_string_append (str, "char");
|
||||
if (is_invoke && !was_array)
|
||||
va_arg (args, int);
|
||||
was_array = FALSE;
|
||||
break;
|
||||
case RPC_TYPE_BOOLEAN:
|
||||
g_string_append (str, "bool");
|
||||
if (is_invoke && !was_array)
|
||||
va_arg (args, int);
|
||||
was_array = FALSE;
|
||||
break;
|
||||
case RPC_TYPE_INT32:
|
||||
g_string_append (str, "int32");
|
||||
if (is_invoke && !was_array)
|
||||
va_arg (args, gint32);
|
||||
was_array = FALSE;
|
||||
break;
|
||||
case RPC_TYPE_UINT32:
|
||||
g_string_append (str, "uint32");
|
||||
if (is_invoke && !was_array)
|
||||
va_arg (args, guint32);
|
||||
was_array = FALSE;
|
||||
break;
|
||||
case RPC_TYPE_UINT64:
|
||||
g_string_append (str, "uint64");
|
||||
if (is_invoke && !was_array)
|
||||
va_arg (args, guint64);
|
||||
was_array = FALSE;
|
||||
break;
|
||||
case RPC_TYPE_DOUBLE:
|
||||
g_string_append (str, "double");
|
||||
if (is_invoke && !was_array)
|
||||
va_arg (args, gdouble);
|
||||
was_array = FALSE;
|
||||
break;
|
||||
case RPC_TYPE_STRING:
|
||||
g_string_append (str, "string");
|
||||
if (is_invoke && !was_array)
|
||||
va_arg (args, gchar *);
|
||||
was_array = FALSE;
|
||||
break;
|
||||
case RPC_TYPE_ARRAY:
|
||||
/* XXX: don't allow array of arrays */
|
||||
if (!was_array)
|
||||
{
|
||||
g_string_append (str, "array of ");
|
||||
was_array = TRUE;
|
||||
break;
|
||||
}
|
||||
/* fall-through */
|
||||
default:
|
||||
npw_printf ("ERROR: unknown type %d\n", type);
|
||||
abort ();
|
||||
}
|
||||
if (!is_invoke && type != RPC_TYPE_ARRAY)
|
||||
va_arg (args, gpointer);
|
||||
}
|
||||
va_end (args);
|
||||
if (n_args == 0)
|
||||
g_string_append (str, "void");
|
||||
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__); \
|
||||
#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); \
|
||||
RPC_TEST_ENSURE_NO_ERROR (error); \
|
||||
error = rpc_method_wait_for_reply (connection, RPC_TYPE_INVALID); \
|
||||
RPC_TEST_ENSURE_NO_ERROR (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); \
|
||||
#define rpc_test_get_args(connection, ...) do { \
|
||||
int error; \
|
||||
rpc_test_signature (FALSE, __VA_ARGS__); \
|
||||
error = rpc_method_get_args (connection, __VA_ARGS__); \
|
||||
RPC_TEST_ENSURE_NO_ERROR (error); \
|
||||
} while (0)
|
||||
|
||||
static gchar g_char_array[] =
|
||||
{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
|
||||
static gint32 g_int32_array[] =
|
||||
{ G_MININT32, G_MININT32+1, -2, -1, 0, 1, 2, G_MAXINT32-1, G_MAXINT32 };
|
||||
static guint64 g_uint64_array[] =
|
||||
{ 0, 1, G_MAXUINT32-1, G_MAXUINT32, G_MAXUINT32+1, G_MAXUINT64-1, G_MAXUINT64 };
|
||||
static gdouble g_double_array[] =
|
||||
{ -2.0, -1.0, 0.0, 1.0, 2.0 };
|
||||
static const gchar *g_string_array[] =
|
||||
{ "string", "", NULL, "another one" };
|
||||
|
||||
#ifdef BUILD_SERVER
|
||||
typedef union _RPCTestArg RPCTestArg;
|
||||
|
||||
|
@ -148,15 +187,33 @@ union _RPCTestArg
|
|||
guint64 j;
|
||||
gdouble d;
|
||||
gchar *s;
|
||||
struct {
|
||||
gint l;
|
||||
void *p;
|
||||
} a;
|
||||
};
|
||||
|
||||
#define RPC_TEST_ARG_CHAR c
|
||||
#define RPC_TEST_ARG_BOOLEAN b
|
||||
#define RPC_TEST_ARG_INT32 i
|
||||
#define RPC_TEST_ARG_UINT32 u
|
||||
#define RPC_TEST_ARG_UINT64 j
|
||||
#define RPC_TEST_ARG_DOUBLE d
|
||||
#define RPC_TEST_ARG_STRING s
|
||||
|
||||
static RPCTestArg g_args[RPC_TEST_MAX_ARGS];
|
||||
|
||||
#define RPC_GET_ARG(N, TYPE) \
|
||||
RPC_TYPE_##TYPE, &g_args[N].RPC_TEST_ARG_##TYPE
|
||||
|
||||
#define RPC_GET_ARRAY_ARG(N, TYPE) \
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_##TYPE, &g_args[N].a.l, &g_args[N].a.p
|
||||
|
||||
static int
|
||||
handle_VOID__VOID (rpc_connection_t *connection)
|
||||
{
|
||||
rpc_test_get_args (connection,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -165,10 +222,10 @@ static int
|
|||
handle_VOID__CHAR (rpc_connection_t *connection)
|
||||
{
|
||||
rpc_test_get_args (connection,
|
||||
RPC_TYPE_CHAR, &g_args[0].c,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TYPE_CHAR, &g_args[0].c,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
g_assert (g_args[0].c == 'a');
|
||||
RPC_TEST_ENSURE (g_args[0].c == 'a');
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -177,28 +234,28 @@ 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);
|
||||
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');
|
||||
RPC_TEST_ENSURE (g_args[0].c == 'a');
|
||||
RPC_TEST_ENSURE (g_args[1].c == 'b');
|
||||
RPC_TEST_ENSURE (g_args[2].c == 'c');
|
||||
RPC_TEST_ENSURE (g_args[3].c == 'd');
|
||||
RPC_TEST_ENSURE (g_args[4].c == 'e');
|
||||
RPC_TEST_ENSURE (g_args[5].c == '1');
|
||||
RPC_TEST_ENSURE (g_args[6].c == '2');
|
||||
RPC_TEST_ENSURE (g_args[7].c == '3');
|
||||
RPC_TEST_ENSURE (g_args[8].c == '4');
|
||||
RPC_TEST_ENSURE (g_args[9].c == '5');
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -207,10 +264,10 @@ static int
|
|||
handle_VOID__BOOL (rpc_connection_t *connection)
|
||||
{
|
||||
rpc_test_get_args (connection,
|
||||
RPC_TYPE_BOOLEAN, &g_args[0].b,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TYPE_BOOLEAN, &g_args[0].b,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
g_assert (g_args[0].b == TRUE);
|
||||
RPC_TEST_ENSURE (g_args[0].b == TRUE);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -219,28 +276,28 @@ 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);
|
||||
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);
|
||||
RPC_TEST_ENSURE (g_args[0].b == TRUE);
|
||||
RPC_TEST_ENSURE (g_args[1].b == FALSE);
|
||||
RPC_TEST_ENSURE (g_args[2].b == TRUE);
|
||||
RPC_TEST_ENSURE (g_args[3].b == FALSE);
|
||||
RPC_TEST_ENSURE (g_args[4].b == TRUE);
|
||||
RPC_TEST_ENSURE (g_args[5].b == FALSE);
|
||||
RPC_TEST_ENSURE (g_args[6].b == TRUE);
|
||||
RPC_TEST_ENSURE (g_args[7].b == FALSE);
|
||||
RPC_TEST_ENSURE (g_args[8].b == TRUE);
|
||||
RPC_TEST_ENSURE (g_args[9].b == FALSE);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -249,28 +306,28 @@ 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);
|
||||
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);
|
||||
|
||||
RPC_TEST_ENSURE (g_args[0].i == 0);
|
||||
RPC_TEST_ENSURE (g_args[1].i == 1);
|
||||
RPC_TEST_ENSURE (g_args[2].i == -1);
|
||||
RPC_TEST_ENSURE (g_args[3].i == 2);
|
||||
RPC_TEST_ENSURE (g_args[4].i == -2);
|
||||
RPC_TEST_ENSURE (g_args[5].i == G_MAXINT32);
|
||||
RPC_TEST_ENSURE (g_args[6].i == G_MININT32);
|
||||
RPC_TEST_ENSURE (g_args[7].i == G_MAXINT32 - 1);
|
||||
RPC_TEST_ENSURE (g_args[8].i == G_MININT32 + 1);
|
||||
RPC_TEST_ENSURE (g_args[9].i == 0);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -279,28 +336,28 @@ 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);
|
||||
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);
|
||||
RPC_TEST_ENSURE (g_args[0].u == 0);
|
||||
RPC_TEST_ENSURE (g_args[1].u == 1);
|
||||
RPC_TEST_ENSURE (g_args[2].u == 0xffffffff);
|
||||
RPC_TEST_ENSURE (g_args[3].u == 2);
|
||||
RPC_TEST_ENSURE (g_args[4].u == 0xfffffffe);
|
||||
RPC_TEST_ENSURE (g_args[5].u == G_MAXUINT32);
|
||||
RPC_TEST_ENSURE (g_args[6].u == G_MAXUINT32 - 1);
|
||||
RPC_TEST_ENSURE (g_args[7].u == 0x80000000);
|
||||
RPC_TEST_ENSURE (g_args[8].u == 0x80000001);
|
||||
RPC_TEST_ENSURE (g_args[9].u == 0);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -309,28 +366,28 @@ 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);
|
||||
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));
|
||||
RPC_TEST_ENSURE (g_args[0].j == 0);
|
||||
RPC_TEST_ENSURE (g_args[1].j == G_GINT64_CONSTANT (0x00000000000000ffU));
|
||||
RPC_TEST_ENSURE (g_args[2].j == G_GINT64_CONSTANT (0x000000000000ff00U));
|
||||
RPC_TEST_ENSURE (g_args[3].j == G_GINT64_CONSTANT (0x0000000000ff0000U));
|
||||
RPC_TEST_ENSURE (g_args[4].j == G_GINT64_CONSTANT (0x00000000ff000000U));
|
||||
RPC_TEST_ENSURE (g_args[5].j == G_GINT64_CONSTANT (0x000000ff00000000U));
|
||||
RPC_TEST_ENSURE (g_args[6].j == G_GINT64_CONSTANT (0x0000ff0000000000U));
|
||||
RPC_TEST_ENSURE (g_args[7].j == G_GINT64_CONSTANT (0x00ff000000000000U));
|
||||
RPC_TEST_ENSURE (g_args[8].j == G_GINT64_CONSTANT (0xff00000000000000U));
|
||||
RPC_TEST_ENSURE (g_args[9].j == G_GINT64_CONSTANT (0x0123456789abcdefU));
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -339,18 +396,18 @@ 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);
|
||||
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);
|
||||
RPC_TEST_ENSURE (g_args[0].d == 0.0);
|
||||
RPC_TEST_ENSURE (g_args[1].d == 1.0);
|
||||
RPC_TEST_ENSURE (g_args[2].d == -1.0);
|
||||
RPC_TEST_ENSURE (g_args[3].d == 2.0);
|
||||
RPC_TEST_ENSURE (g_args[4].d == -2.0);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -359,16 +416,185 @@ 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);
|
||||
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);
|
||||
RPC_TEST_ENSURE (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);
|
||||
RPC_TEST_ENSURE (g_args[1].s && strcmp (g_args[1].s, "one") == 0);
|
||||
free (g_args[1].s);
|
||||
g_assert (g_args[2].s == NULL);
|
||||
RPC_TEST_ENSURE (g_args[2].s == NULL);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_VOID__CHAR_ARRAY (rpc_connection_t *connection)
|
||||
{
|
||||
guint32 len;
|
||||
gchar *array;
|
||||
|
||||
rpc_test_get_args (connection,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, &len, &array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
RPC_TEST_ENSURE (len == G_N_ELEMENTS (g_char_array));
|
||||
RPC_TEST_ENSURE (array != NULL);
|
||||
for (int i = 0; i < len; i++)
|
||||
RPC_TEST_ENSURE (array[i] == g_char_array[i]);
|
||||
|
||||
free (array);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_VOID__INT32_ARRAY (rpc_connection_t *connection)
|
||||
{
|
||||
guint32 len;
|
||||
gint32 *array;
|
||||
|
||||
rpc_test_get_args (connection,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_INT32, &len, &array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
RPC_TEST_ENSURE (len == G_N_ELEMENTS (g_int32_array));
|
||||
RPC_TEST_ENSURE (array != NULL);
|
||||
for (int i = 0; i < len; i++)
|
||||
RPC_TEST_ENSURE (array[i] == g_int32_array[i]);
|
||||
|
||||
free (array);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_VOID__UINT64_ARRAY (rpc_connection_t *connection)
|
||||
{
|
||||
guint32 len;
|
||||
guint64 *array;
|
||||
|
||||
rpc_test_get_args (connection,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_UINT64, &len, &array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
RPC_TEST_ENSURE (len == G_N_ELEMENTS (g_uint64_array));
|
||||
RPC_TEST_ENSURE (array != NULL);
|
||||
for (int i = 0; i < len; i++)
|
||||
RPC_TEST_ENSURE (array[i] == g_uint64_array[i]);
|
||||
|
||||
free (array);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_VOID__DOUBLE_ARRAY (rpc_connection_t *connection)
|
||||
{
|
||||
guint32 len;
|
||||
gdouble *array;
|
||||
|
||||
rpc_test_get_args (connection,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_DOUBLE, &len, &array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
RPC_TEST_ENSURE (len == G_N_ELEMENTS (g_double_array));
|
||||
RPC_TEST_ENSURE (array != NULL);
|
||||
for (int i = 0; i < len; i++)
|
||||
RPC_TEST_ENSURE (array[i] == g_double_array[i]);
|
||||
|
||||
free (array);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_VOID__STRING_ARRAY (rpc_connection_t *connection)
|
||||
{
|
||||
guint32 len;
|
||||
gchar **array;
|
||||
|
||||
rpc_test_get_args (connection,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_STRING, &len, &array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
RPC_TEST_ENSURE (len == G_N_ELEMENTS (g_string_array));
|
||||
RPC_TEST_ENSURE (array != NULL);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (g_string_array[i])
|
||||
{
|
||||
RPC_TEST_ENSURE (array[i] != NULL);
|
||||
RPC_TEST_ENSURE (strcmp (array[i], g_string_array[i]) == 0);
|
||||
|
||||
free (array[i]);
|
||||
}
|
||||
else
|
||||
RPC_TEST_ENSURE (array[i] == NULL);
|
||||
}
|
||||
|
||||
free (array);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_VOID__NULL_ARRAY_with_length (rpc_connection_t *connection,
|
||||
gint32 expected_length)
|
||||
{
|
||||
gint32 len;
|
||||
gchar *array = GUINT_TO_POINTER (0xdeadbeef);
|
||||
|
||||
rpc_test_get_args (connection,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, &len, &array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
RPC_TEST_ENSURE (len == expected_length);
|
||||
RPC_TEST_ENSURE (array == NULL);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_VOID__NULL_ARRAY (rpc_connection_t *connection)
|
||||
{
|
||||
return handle_VOID__NULL_ARRAY_with_length (connection, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_VOID__0LEN_ARRAY (rpc_connection_t *connection)
|
||||
{
|
||||
return handle_VOID__NULL_ARRAY_with_length (connection, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_VOID__MIXED_ARRAY (rpc_connection_t *connection)
|
||||
{
|
||||
rpc_test_get_args (connection,
|
||||
RPC_GET_ARRAY_ARG (0, CHAR),
|
||||
RPC_GET_ARRAY_ARG (1, CHAR),
|
||||
RPC_GET_ARRAY_ARG (2, CHAR),
|
||||
RPC_GET_ARRAY_ARG (3, CHAR),
|
||||
RPC_GET_ARRAY_ARG (4, CHAR),
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
RPC_TEST_ENSURE (g_args[0].a.l == G_N_ELEMENTS (g_char_array));
|
||||
RPC_TEST_ENSURE (g_args[0].a.p != NULL);
|
||||
RPC_TEST_ENSURE (memcmp (g_args[0].a.p, g_char_array, g_args[0].a.l) == 0);
|
||||
RPC_TEST_ENSURE (g_args[1].a.l == G_N_ELEMENTS (g_char_array));
|
||||
RPC_TEST_ENSURE (g_args[1].a.p != NULL);
|
||||
RPC_TEST_ENSURE (memcmp (g_args[1].a.p, g_char_array, g_args[1].a.l) == 0);
|
||||
RPC_TEST_ENSURE (g_args[2].a.l == 0);
|
||||
RPC_TEST_ENSURE (g_args[2].a.p == NULL);
|
||||
RPC_TEST_ENSURE (g_args[3].a.l == 0);
|
||||
RPC_TEST_ENSURE (g_args[3].a.p == NULL);
|
||||
RPC_TEST_ENSURE (g_args[4].a.l == 1);
|
||||
RPC_TEST_ENSURE (g_args[4].a.p == NULL);
|
||||
|
||||
free (g_args[0].a.p);
|
||||
free (g_args[1].a.p);
|
||||
|
||||
return rpc_method_send_reply (connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
@ -382,25 +608,33 @@ rpc_test_init (int argc, char *argv[])
|
|||
|
||||
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 },
|
||||
{ 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 },
|
||||
{ RPC_TEST_METHOD_VOID__CHAR_ARRAY, handle_VOID__CHAR_ARRAY },
|
||||
{ RPC_TEST_METHOD_VOID__INT32_ARRAY, handle_VOID__INT32_ARRAY },
|
||||
{ RPC_TEST_METHOD_VOID__UINT64_ARRAY, handle_VOID__UINT64_ARRAY },
|
||||
{ RPC_TEST_METHOD_VOID__DOUBLE_ARRAY, handle_VOID__DOUBLE_ARRAY },
|
||||
{ RPC_TEST_METHOD_VOID__STRING_ARRAY, handle_VOID__STRING_ARRAY },
|
||||
{ RPC_TEST_METHOD_VOID__NULL_ARRAY, handle_VOID__NULL_ARRAY },
|
||||
{ RPC_TEST_METHOD_VOID__0LEN_ARRAY, handle_VOID__0LEN_ARRAY },
|
||||
{ RPC_TEST_METHOD_VOID__MIXED_ARRAY, handle_VOID__MIXED_ARRAY }
|
||||
};
|
||||
|
||||
connection = rpc_test_get_connection ();
|
||||
g_assert (connection != NULL);
|
||||
RPC_TEST_ENSURE (connection != NULL);
|
||||
|
||||
if (rpc_connection_add_method_descriptors(connection,
|
||||
vtable,
|
||||
G_N_ELEMENTS (vtable)) < 0)
|
||||
g_error ("could not add method descriptors");
|
||||
vtable,
|
||||
G_N_ELEMENTS (vtable)) < 0)
|
||||
g_error ("could not add method descriptors");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -410,95 +644,140 @@ int
|
|||
rpc_test_execute (gpointer user_data)
|
||||
{
|
||||
#ifdef BUILD_CLIENT
|
||||
/* Basic types */
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__VOID,
|
||||
RPC_TYPE_INVALID);
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__CHAR,
|
||||
RPC_TYPE_CHAR, 'a',
|
||||
RPC_TYPE_INVALID);
|
||||
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_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_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_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_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_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_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_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);
|
||||
RPC_TYPE_STRING, "",
|
||||
RPC_TYPE_STRING, "one",
|
||||
RPC_TYPE_STRING, NULL,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
/* Arrays */
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__CHAR_ARRAY,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR,
|
||||
(gint32)G_N_ELEMENTS (g_char_array), g_char_array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__INT32_ARRAY,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_INT32,
|
||||
(gint32)G_N_ELEMENTS (g_int32_array), g_int32_array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__UINT64_ARRAY,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_UINT64,
|
||||
(gint32)G_N_ELEMENTS (g_uint64_array), g_uint64_array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__DOUBLE_ARRAY,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_DOUBLE,
|
||||
(gint32)G_N_ELEMENTS (g_double_array), g_double_array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__STRING_ARRAY,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_STRING,
|
||||
(gint32)G_N_ELEMENTS (g_string_array), g_string_array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__NULL_ARRAY,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, 1, NULL,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__0LEN_ARRAY,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, 0, g_char_array,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
rpc_test_invoke (RPC_TEST_METHOD_VOID__MIXED_ARRAY,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR,
|
||||
(gint32)G_N_ELEMENTS (g_char_array), g_char_array,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR,
|
||||
(gint32)G_N_ELEMENTS (g_char_array), g_char_array,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, 0, NULL,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, 0, g_char_array,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, 1, NULL,
|
||||
RPC_TYPE_INVALID);
|
||||
#endif
|
||||
return RPC_TEST_EXECUTE_SUCCESS;
|
||||
}
|
||||
|
|
1069
utils/npw-shadow.c
1069
utils/npw-shadow.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue