-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Unix file descriptors
- Loading branch information
1 parent
cc407c8
commit e95ea9d
Showing
5 changed files
with
149 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
from gi.repository import Gio | ||
|
||
# signature type code | ||
TYPE_FD = "h" | ||
|
||
def is_supported(conn): | ||
""" | ||
Check if the message bus supports passing of Unix file descriptors. | ||
""" | ||
return conn.get_capabilities() & Gio.DBusCapabilityFlags.UNIX_FD_PASSING | ||
|
||
|
||
def extract(params, signature, fd_list): | ||
""" | ||
Extract any file descriptors from a UnixFDList (e.g. after | ||
receiving from D-Bus) to a parameter list. | ||
Receiver must call os.dup on any fd it decides to keep/use. | ||
""" | ||
if not fd_list: | ||
return params | ||
return [fd_list.get(0) | ||
if arg == TYPE_FD | ||
else val | ||
for val, arg | ||
in zip(params, signature)] | ||
|
||
|
||
def make_fd_list(params, signature, steal=False): | ||
""" | ||
Embed any unix file descriptors in a parameter list into a | ||
UnixFDList (for D-Bus-dispatch). | ||
If steal is true, the responsibility for closing the file | ||
descriptors are transferred to the UnixFDList object. | ||
If steal is false, the file descriptors will be duplicated | ||
and the caller must close the original file descriptors. | ||
""" | ||
if not any(arg | ||
for arg in signature | ||
if arg == TYPE_FD): | ||
return None | ||
|
||
fds = [param | ||
for param, arg | ||
in zip(params, signature) | ||
if arg == TYPE_FD] | ||
|
||
if steal: | ||
return Gio.UnixFDList.new_from_array(fds) | ||
|
||
fd_list = Gio.UnixFDList() | ||
for fd in fds: | ||
fd_list.append(fd) | ||
return fd_list |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from pydbus import SessionBus | ||
from gi.repository import GLib | ||
from threading import Thread | ||
import sys | ||
import os | ||
|
||
loop = GLib.MainLoop() | ||
with open(__file__) as f: | ||
contents = f.read() | ||
|
||
|
||
class TestObject(object): | ||
""" | ||
<node> | ||
<interface name="baz.bar.Foo"> | ||
<method name="Hello"> | ||
<arg type="h" name="in_fd" direction="in"/> | ||
<arg type="h" name="out_fd" direction="out"/> | ||
</method> | ||
</interface> | ||
</node> | ||
""" | ||
def Hello(self, in_fd): | ||
with open(in_fd) as in_file: | ||
in_file.seek(0) | ||
assert(contents == in_file.read()) | ||
print("Received fd as in parameter ok") | ||
with open(__file__) as out_file: | ||
assert(contents == out_file.read()) | ||
return os.dup(out_file.fileno()) | ||
|
||
bus = SessionBus() | ||
|
||
|
||
with bus.publish("baz.bar.Foo", TestObject()): | ||
remote = bus.get("baz.bar.Foo") | ||
|
||
def thread_func(): | ||
with open(__file__) as in_file: | ||
assert(contents == in_file.read()) | ||
out_fd = remote.Hello(in_file.fileno()) | ||
with open(out_fd) as out_file: | ||
out_file.seek(0) | ||
assert(contents == out_file.read()) | ||
print("Received fd as out argument ok") | ||
loop.quit() | ||
|
||
thread = Thread(target=thread_func) | ||
thread.daemon = True | ||
|
||
def handle_timeout(): | ||
exit("ERROR: Timeout.") | ||
|
||
GLib.timeout_add_seconds(2, handle_timeout) | ||
|
||
thread.start() | ||
loop.run() | ||
thread.join() |