1 // Copyright 2006 Alp Toker <alp@atoker.com>
2 // This software is made available under the MIT License
3 // See COPYING for details
4 
5 using System;
6 using DBus;
7 using org.freedesktop.DBus;
8 
9 using System.IO;
10 using Mono.Unix;
11 
12 using System.Threading;
13 
14 using System.Text;
15 using DBus.Transports;
16 
17 public class TestServerNative
18 {
19 	//TODO: complete this test daemon/server example, and a client
20 	//TODO: maybe generalise it and integrate it into the core
Main(string[] args)21 	public static void Main (string[] args)
22 	{
23 		bool isServer;
24 
25 		if (args.Length == 1 && args[0] == "server")
26 			isServer = true;
27 		else if (args.Length == 1 && args[0] == "client")
28 			isServer = false;
29 		else {
30 			Console.Error.WriteLine ("Usage: test-server [server|client]");
31 			return;
32 		}
33 
34 		//string addr = "unix:abstract=/tmp/dbus-ABCDEFGHIJ";
35 		string addr = "unix:path=/tmp/dbus-ABCDEFGHIJ";
36 
37 		Connection conn;
38 
39 		ObjectPath myOpath = new ObjectPath ("/org/ndesk/test");
40 		string myNameReq = "org.ndesk.test";
41 
42 		if (!isServer) {
43 			conn = new Connection (Transport.Create (AddressEntry.Parse (addr)));
44 			DemoObject demo = conn.GetObject<DemoObject> (myNameReq, myOpath);
45 			demo.GiveNoReply ();
46 			//float ret = demo.Hello ("hi from test client", 21);
47 			float ret = 200;
48 			while (ret > 5) {
49 				ret = demo.Hello ("hi from test client", (int)ret);
50 				Console.WriteLine ("Returned float: " + ret);
51 				System.Threading.Thread.Sleep (1000);
52 			}
53 		} else {
54 			string path;
55 			bool abstr;
56 
57 			AddressEntry entry = AddressEntry.Parse (addr);
58 			path = entry.Properties["path"];
59 
60 			UnixSocket server = new UnixSocket ();
61 
62 
63 			byte[] p = Encoding.Default.GetBytes (path);
64 
65 			byte[] sa = new byte[2 + p.Length + 1];
66 
67 			//we use BitConverter to stay endian-safe
68 			byte[] afData = BitConverter.GetBytes (UnixSocket.AF_UNIX);
69 			sa[0] = afData[0];
70 			sa[1] = afData[1];
71 
72 			for (int i = 0 ; i != p.Length ; i++)
73 				sa[2 + i] = p[i];
74 			sa[2 + p.Length] = 0; //null suffix for domain socket addresses, see unix(7)
75 
76 
77 			server.Bind (sa);
78 			//server.Listen (1);
79 			server.Listen (5);
80 
81 			while (true) {
82 				Console.WriteLine ("Waiting for client on " + addr);
83 				UnixSocket client = server.Accept ();
84 				Console.WriteLine ("Client accepted");
85 				//client.Blocking = true;
86 
87 				//PeerCred pc = new PeerCred (client);
88 				//Console.WriteLine ("PeerCred: pid={0}, uid={1}, gid={2}", pc.ProcessID, pc.UserID, pc.GroupID);
89 
90 				UnixNativeTransport transport = new UnixNativeTransport ();
91 				transport.Stream = new UnixStream (client.Handle);
92 				conn = new Connection (transport);
93 
94 				//ConnectionHandler.Handle (conn);
95 
96 				//in reality a thread per connection is of course too expensive
97 				ConnectionHandler hnd = new ConnectionHandler (conn);
98 				new Thread (new ThreadStart (hnd.Handle)).Start ();
99 
100 				Console.WriteLine ();
101 			}
102 		}
103 	}
104 }
105 
106 public class ConnectionHandler
107 {
108 	protected Connection conn;
109 
ConnectionHandler(Connection conn)110 	public ConnectionHandler (Connection conn)
111 	{
112 		this.conn = conn;
113 	}
114 
Handle()115 	public void Handle ()
116 	{
117 		ConnectionHandler.Handle (conn);
118 	}
119 
Handle(Connection conn)120 	public static void Handle (Connection conn)
121 	{
122 		string myNameReq = "org.ndesk.test";
123 		ObjectPath myOpath = new ObjectPath ("/org/ndesk/test");
124 
125 		DemoObject demo = new DemoObject ();
126 		conn.Register (myNameReq, myOpath, demo);
127 
128 		//TODO: handle lost connections etc. properly instead of stupido try/catch
129 		try {
130 		while (true)
131 			conn.Iterate ();
132 		} catch (Exception e) {
133 			//Console.Error.WriteLine (e);
134 		}
135 
136 		conn.Unregister (myNameReq, myOpath);
137 	}
138 }
139 
140 [Interface ("org.ndesk.test")]
141 public class DemoObject : MarshalByRefObject
142 {
Hello(string arg0, int arg1)143 	public float Hello (string arg0, int arg1)
144 	{
145 		Console.WriteLine ("Got a Hello(" + arg0 + ", " + arg1 +")");
146 
147 		return (float)arg1/2;
148 	}
149 
GiveNoReply()150 	public void GiveNoReply ()
151 	{
152 		Console.WriteLine ("Asked to give no reply");
153 	}
154 }
155