Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
Merge pull request #62 from steffen-kiess/unixfd
Browse files Browse the repository at this point in the history
Add support for Unix FD passing
  • Loading branch information
garuma authored Oct 7, 2017
2 parents 2686c4f + 9ff5f77 commit 5ff480a
Show file tree
Hide file tree
Showing 29 changed files with 1,266 additions and 223 deletions.
142 changes: 142 additions & 0 deletions examples/UnixFDClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Copyright 2017 Steffen Kiess <[email protected]>
// This software is made available under the MIT License
// See COPYING for details

using System;

using DBus;
using org.freedesktop.DBus;

using Mono.Unix;
using Mono.Unix.Native;

class SignalsImpl : Signals {
public event Action<UnixFD> GotFD;

public void CallGotFD (UnixFD fd) {
var handler = GotFD;
if (handler != null)
handler (fd);
}
}

public class ManagedDBusTest
{
public static void Main (string[] args)
{
Bus conn;

if (args.Length == 0)
conn = Bus.Session;
else {
if (args[0] == "--session")
conn = Bus.Session;
else if (args[0] == "--system")
conn = Bus.System;
else
conn = Bus.Open (args[0]);
}

IBus bus = conn.GetObject<IBus> ("org.freedesktop.DBus", new ObjectPath ("/org/freedesktop/DBus"));
Console.WriteLine (bus.ListNames ().Length);

var obj = conn.GetObject<Interface> (Constants.BusName, Constants.ObjectPath);
var obj2 = conn.GetObject<Interface2> (Constants.BusName, Constants.ObjectPath);
var objIntr = conn.GetObject<Introspectable> (Constants.BusName, Constants.ObjectPath);
obj.Ping ();
Console.WriteLine (obj.GetBytes (3).Length);

Console.WriteLine ("conn.UnixFDSupported = " + conn.UnixFDSupported);
if (!conn.UnixFDSupported)
return;

using (var disposableList = new DisposableList ()) {
var res = obj.GetFD (disposableList, false);
Console.WriteLine ("Got FD:");
Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + res.Handle);
}
using (var disposableList = new DisposableList ()) {
var res = obj.GetFDList (disposableList, false);
Console.WriteLine ("Got FDs:");
foreach (var fd in res)
Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle);
}
using (var disposableList = new DisposableList ()) {
var res = (UnixFD[]) obj.GetFDListVariant (disposableList, false);
Console.WriteLine ("Got FDs as variant:");
foreach (var fd in res)
Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle);
}

using (var disposableList = new DisposableList ()) {
try {
obj.GetFD (disposableList, true);
throw new Exception ("Expected an exception");
} catch (Exception e) {
if (!e.Message.Contains ("Throwing an exception after creating a UnixFD object"))
throw;
}
}
using (var disposableList = new DisposableList ()) {
try {
obj.GetFDList (disposableList, true);
throw new Exception ("Expected an exception");
} catch (Exception e) {
if (!e.Message.Contains ("Throwing an exception after creating a UnixFD object"))
throw;
}
}
using (var disposableList = new DisposableList ()) {
try {
obj.GetFDListVariant (disposableList, true);
throw new Exception ("Expected an exception");
} catch (Exception e) {
if (!e.Message.Contains ("Throwing an exception after creating a UnixFD object"))
throw;
}
}

// Check whether this leaks an FD
obj.GetFD (null, false);
obj.GetFDList (null, false);
obj.GetFDListVariant (null, false);
try { obj.GetFD (null, true); } catch {}
try { obj.GetFDList (null, true); } catch {}
try { obj.GetFDListVariant (null, true); } catch {}
obj2.GetFD (false);
obj2.GetFDList (false);
obj2.GetFDListVariant (false);
try { obj2.GetFD (true); } catch {}
try { obj2.GetFDList (true); } catch {}
try { obj2.GetFDListVariant (true); } catch {}

var fd_ = Syscall.open ("/dev/null", OpenFlags.O_RDWR, 0);
if (fd_ < 0)
UnixMarshal.ThrowExceptionForLastError ();
using (var fd = new UnixFD (fd_)) {
obj.SendFD (fd);
obj.SendFD (fd);
obj.SendFDList (new UnixFD[] { fd, fd });
obj.SendFDListVariant (new UnixFD[] { fd, fd });

var impl = new SignalsImpl ();
var spath = new ObjectPath ("/mono_dbus_sharp_test/Signals");
conn.Register (spath, impl);
obj.RegisterSignalInterface (conn.UniqueName, spath);
impl.CallGotFD (fd);
}

Console.WriteLine (objIntr.Introspect ().Length);

obj.ListOpenFDs ();
Console.WriteLine ("Open FDs:");
Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/");
}
}

// vim: noexpandtab
// Local Variables:
// tab-width: 4
// c-basic-offset: 4
// indent-tabs-mode: t
// End:
61 changes: 61 additions & 0 deletions examples/UnixFDInterface.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2017 Steffen Kiess <[email protected]>
// This software is made available under the MIT License
// See COPYING for details

using System;
using DBus;

public static class Constants {
public const string BusName = "mono_dbus_sharp_test.UnixFDService";
public static readonly ObjectPath ObjectPath = new ObjectPath ("/mono_dbus_sharp_test/UnixFDService");
}

[DBus.Interface ("mono_dbus_sharp_test.UnixFDService")]
public interface Interface {
void Ping ();

void ListOpenFDs ();

byte[] GetBytes (int len);

UnixFD GetFD (DisposableList disposableList, bool throwError);
UnixFD[] GetFDList (DisposableList disposableList, bool throwError);
object GetFDListVariant (DisposableList disposableList, bool throwError);

void SendFD (UnixFD fd);
void SendFDList (UnixFD[] fds);
void SendFDListVariant (object fds);

void RegisterSignalInterface (string busName, ObjectPath path);
}

[DBus.Interface ("mono_dbus_sharp_test.UnixFDService")]
public interface Interface2 {
void Ping ();

void ListOpenFDs ();

byte[] GetBytes (int len);

UnixFD GetFD (bool throwError);
UnixFD[] GetFDList (bool throwError);
object GetFDListVariant (bool throwError);

void SendFD (UnixFD fd);
void SendFDList (UnixFD[] fds);
void SendFDListVariant (object fds);

void RegisterSignalInterface (string busName, ObjectPath path);
}

[DBus.Interface ("mono_dbus_sharp_test.UnixFDSignals")]
public interface Signals {
event Action<UnixFD> GotFD;
}

// vim: noexpandtab
// Local Variables:
// tab-width: 4
// c-basic-offset: 4
// indent-tabs-mode: t
// End:
137 changes: 137 additions & 0 deletions examples/UnixFDService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright 2017 Steffen Kiess <[email protected]>
// This software is made available under the MIT License
// See COPYING for details

/*
PATH="$HOME/mono-master/bin:$PATH" ./autogen.sh && make -j8
make && ( cd examples && mcs -g UnixFDService.cs UnixFDInterface.cs -r ../src/dbus-sharp.dll -r Mono.Posix ) && MONO_PATH=src $HOME/mono-master/bin/mono --debug examples/UnixFDService.exe
make && ( cd examples && mcs -g UnixFDClient.cs UnixFDInterface.cs -r ../src/dbus-sharp.dll -r Mono.Posix ) && MONO_PATH=src $HOME/mono-master/bin/mono --debug examples/UnixFDClient.exe
python3
import dbus; dbus.SessionBus().get_object('mono_dbus_sharp_test.UnixFDService', '/mono_dbus_sharp_test/UnixFDService').GetBytes(3)
import dbus; f = dbus.SessionBus().get_object('mono_dbus_sharp_test.UnixFDService', '/mono_dbus_sharp_test/UnixFDService').GetFD ()
*/

using System;

using Mono.Unix;
using Mono.Unix.Native;

using DBus;
using org.freedesktop.DBus;

public class Impl : Interface {
Connection conn;

public Impl (Connection conn)
{
this.conn = conn;
}

public void Ping ()
{
}

public void ListOpenFDs ()
{
Console.WriteLine ("Open FDs:");
Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/");
}

public UnixFD GetFD (DisposableList disposableList, bool throwError)
{
var fd_ = Syscall.open ("/dev/null", OpenFlags.O_RDWR, 0);
if (fd_ < 0)
UnixMarshal.ThrowExceptionForLastError ();
var fd = new UnixFD (fd_);
disposableList.Add (fd);

if (throwError)
throw new Exception ("Throwing an exception after creating a UnixFD object");

return fd;
}

public UnixFD[] GetFDList (DisposableList disposableList, bool throwError)
{
return new UnixFD[] {
GetFD (disposableList, false), GetFD (disposableList, throwError), GetFD (disposableList, false)
};
}

public object GetFDListVariant (DisposableList disposableList, bool throwError)
{
return GetFDList (disposableList, throwError);
}

public byte[] GetBytes (int len)
{
return new byte[len];
}

public void SendFD (UnixFD fd)
{
Console.WriteLine ("Got FD as parameter:");
Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle);
}

public void SendFDList (UnixFD[] fds)
{
Console.WriteLine ("Got FDs as parameter:");
foreach (var fd in fds)
Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle);
}

public void SendFDListVariant (object fds)
{
Console.WriteLine ("Got FDs as variant parameter:");
foreach (var fd in (UnixFD[]) fds)
Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle);
}

public void RegisterSignalInterface (string busName, ObjectPath path)
{
Console.WriteLine ("Register for GotFD event at {0} / {1}", busName, path);
conn.GetObject<Signals> (busName, path).GotFD += fd => {
Console.WriteLine ("Got FD from signal:");
Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle);
};
}
}

public class UnixFDService
{
public static void Main (string[] args)
{
Bus conn;

if (args.Length == 0)
conn = Bus.Session;
else {
if (args[0] == "--session")
conn = Bus.Session;
else if (args[0] == "--system")
conn = Bus.System;
else
conn = Bus.Open (args[0]);
}

conn.Register (Constants.ObjectPath, new Impl (conn));

if (conn.RequestName (Constants.BusName) != org.freedesktop.DBus.RequestNameReply.PrimaryOwner)
throw new Exception ("Could not request name");

Console.WriteLine ("Waiting for requests...");

while (conn.IsConnected) {
conn.Iterate ();
}
}
}

// vim: noexpandtab
// Local Variables:
// tab-width: 4
// c-basic-offset: 4
// indent-tabs-mode: t
// End:
10 changes: 10 additions & 0 deletions src/Authentication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ public virtual bool Run (IEnumerable<AuthCommand> commands)
class SaslClient : SaslPeer
{
public string Identity = String.Empty;
public bool TransportSupportsUnixFD = false;
public bool UnixFDSupported = false;

//static Regex rejectedRegex = new Regex (@"^REJECTED(\s+(\w+))*$");

Expand Down Expand Up @@ -387,6 +389,14 @@ public override IEnumerator<AuthCommand> GetEnumerator ()
else
ActualId = UUID.Parse (reply[1]);

if (TransportSupportsUnixFD) {
yield return new AuthCommand ("NEGOTIATE_UNIX_FD");
if (!replies.MoveNext ())
yield break;
reply = replies.Current;
UnixFDSupported = reply[0] == "AGREE_UNIX_FD";
}

yield return new AuthCommand ("BEGIN");
yield break;
}
Expand Down
Loading

0 comments on commit 5ff480a

Please sign in to comment.