Okay, get rid of WvAutoCast.iter() altogether; use GetEnumerator().
[versaplex.git] / versaplexd / vxdbus.cs
blob683f9b3a07ed7a28d2722653a000ab0a617f4f39
1 using System;
2 using System.Collections.Generic;
3 using Wv;
5 public static class VxDbus {
6 static WvLog log = new WvLog("VxDbus", WvLog.L.Debug1);
7 static WvLog smalldump = log.split(WvLog.L.Debug4);
8 static WvLog fulldump = log.split(WvLog.L.Debug5);
10 public static Message CreateError(string type, string msg, Message cause)
12 Message error = new Message();
13 error.Header.MessageType = MessageType.Error;
14 error.Header.Flags =
15 HeaderFlag.NoReplyExpected | HeaderFlag.NoAutoStart;
16 error.Header.Fields[FieldCode.ErrorName] = type;
17 error.Header.Fields[FieldCode.ReplySerial] = cause.Header.Serial;
19 object sender;
20 if (cause.Header.Fields.TryGetValue(FieldCode.Sender, out sender))
21 error.Header.Fields[FieldCode.Destination] = sender;
23 if (msg != null) {
24 error.Signature = new Signature("s");
25 MessageWriter writer =
26 new MessageWriter(Connection.NativeEndianness);
27 writer.Write(msg);
28 error.Body = writer.ToArray();
31 return error;
34 public static Message CreateReply(Message call)
36 return CreateReply(call, null, null);
39 public static Message CreateReply(Message call, string signature,
40 MessageWriter body)
42 Message reply = new Message();
43 reply.Header.MessageType = MessageType.MethodReturn;
44 reply.Header.Flags =
45 HeaderFlag.NoReplyExpected | HeaderFlag.NoAutoStart;
46 reply.Header.Fields[FieldCode.ReplySerial] = call.Header.Serial;
48 object sender;
49 if (call.Header.Fields.TryGetValue(FieldCode.Sender, out sender))
50 reply.Header.Fields[FieldCode.Destination] = sender;
52 if (signature != null && signature != "") {
53 reply.Signature = new Signature(signature);
54 reply.Body = body.ToArray();
57 return reply;
60 public static Message CreateSignal(object destination, string signalname,
61 string signature, MessageWriter body)
63 // Idea shamelessly stolen from CreateReply method above
64 Message signal = new Message();
65 signal.Header.MessageType = MessageType.Signal;
66 signal.Header.Flags =
67 HeaderFlag.NoReplyExpected | HeaderFlag.NoAutoStart;
68 // The ObjectPath is required by signals, and is the "source of the
69 // signal." OK then; seems useless to me.
70 signal.Header.Fields[FieldCode.Path] = new ObjectPath("/db");
71 signal.Header.Fields[FieldCode.Interface] = "vx.db";
72 signal.Header.Fields[FieldCode.Member] = signalname;
74 if (destination != null)
75 signal.Header.Fields[FieldCode.Destination] = destination;
77 if (signature != null && signature != "")
79 signal.Signature = new Signature(signature);
80 signal.Body = body.ToArray();
83 return signal;
86 public static void MessageDump(string prefix, Message msg)
88 Header hdr = msg.Header;
90 if (hdr.Fields.ContainsKey(FieldCode.ReplySerial))
91 log.print("MD {0} REPLY#{1}\n",
92 prefix,
93 hdr.Fields[FieldCode.ReplySerial]);
94 else if (hdr.MessageType != MessageType.Signal)
95 log.print("MD {0} #{1} {2}.{3}\n",
96 prefix,
97 hdr.Serial,
98 hdr.Fields[FieldCode.Interface],
99 hdr.Fields[FieldCode.Member]);
100 else
101 log.print("MD {0} {1}\n", prefix, hdr.Fields[FieldCode.Interface]);
103 smalldump.print("Message dump:\n");
104 smalldump.print(" endianness={0} ", hdr.Endianness);
105 smalldump.print(" t={0} ", hdr.MessageType);
106 smalldump.print(" ver={0} ", hdr.MajorVersion);
107 smalldump.print(" blen={0} ", hdr.Length);
108 smalldump.print(" ser={0}\n", hdr.Serial);
109 smalldump.print(" flags={0}\n", hdr.Flags);
111 smalldump.print(" Fields\n");
112 foreach (KeyValuePair<FieldCode,object> kvp in hdr.Fields) {
113 smalldump.print(" - {0}: {1}\n", kvp.Key, kvp.Value);
116 int hdrlen = 0;
117 byte[] header = msg.GetHeaderData();
118 if (header != null) {
119 smalldump.print("Header data:\n");
120 smalldump.print(wv.hexdump(header));
121 hdrlen = header.Length;
122 } else {
123 smalldump.print("No header data encoded\n");
126 if (msg.Body != null) {
127 fulldump.print("Body data:\n");
128 fulldump.print(wv.hexdump(msg.Body, hdrlen, msg.Body.Length));
129 } else {
130 smalldump.print("No body data encoded\n");
135 public class VxMethodCallRouter {
136 WvLog log = new WvLog("VxMethodCallRouter", WvLog.L.Debug3);
138 private IDictionary<string,VxInterfaceRouter> interfaces
139 = new Dictionary<string,VxInterfaceRouter>();
141 public void AddInterface(VxInterfaceRouter ir)
143 log.print("Adding interface {0}\n", ir.Interface);
144 interfaces.Add(ir.Interface, ir);
147 public void RemoveInterface(VxInterfaceRouter ir)
149 RemoveInterface(ir.Interface);
152 public void RemoveInterface(string iface)
154 interfaces.Remove(iface);
157 public bool RouteMessage(Message call, out Message reply)
159 if (call.Header.MessageType != MessageType.MethodCall)
160 throw new ArgumentException("Not a method call message");
162 reply = null;
164 // FIXME: Dbus spec says that interface should be optional so it
165 // should search all of the interfaces for a matching method...
166 object iface;
167 if (!call.Header.Fields.TryGetValue(FieldCode.Interface, out iface))
168 return false; // No interface; ignore it
170 log.print("Router interface {0}\n", iface);
172 VxInterfaceRouter ir;
173 if (!interfaces.TryGetValue((string)iface, out ir))
174 return false; // Interface not found
176 log.print("Passing to interface router\n");
178 return ir.RouteMessage(call, out reply);
182 public abstract class VxInterfaceRouter {
183 public readonly string Interface;
185 protected VxInterfaceRouter(string iface)
187 Interface = iface;
190 // Return value is the response
191 protected delegate
192 void MethodCallProcessor(Message call, out Message reply);
194 protected IDictionary<string,MethodCallProcessor> methods
195 = new Dictionary<string,MethodCallProcessor>();
197 public bool RouteMessage(Message call, out Message reply)
199 if (call.Header.MessageType != MessageType.MethodCall)
200 throw new ArgumentException("Not a method call message");
202 reply = null;
204 object method;
205 if (!call.Header.Fields.TryGetValue(FieldCode.Member, out method))
206 return false; // No method
208 MethodCallProcessor processor;
209 if (!methods.TryGetValue((string)method, out processor)) {
210 reply = VxDbus.CreateError(
211 "org.freedesktop.DBus.Error.UnknownMethod",
212 String.Format(
213 "Method name {0} not found on interface {1}",
214 method, Interface), call);
216 return true;
219 ExecuteCall(processor, call, out reply);
221 return true;
224 protected virtual void ExecuteCall(MethodCallProcessor processor,
225 Message call, out Message reply)
227 try {
228 processor(call, out reply);
229 } catch (Exception e) {
230 reply = VxDbus.CreateError(
231 "vx.db.exception",
232 e.ToString(), call);