PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/versaplexd/versaplexd.cs

http://versaplex.googlecode.com/
C# | 277 lines | 219 code | 45 blank | 13 comment | 29 complexity | f87c12428647f0688477fcf8fe3dbe5e MD5 | raw file
Possible License(s): LGPL-2.0
  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using Mono.Unix;
  5. using NDesk.DBus;
  6. using org.freedesktop.DBus;
  7. using versabanq.Versaplex.Server;
  8. using versabanq.Versaplex.Dbus;
  9. using versabanq.Versaplex.Dbus.Db;
  10. using Wv;
  11. using Wv.NDesk.Options;
  12. public static class VersaMain
  13. {
  14. static WvLog log = new WvLog("Versaplex");
  15. static Connection.MessageHandler oldhandler = null;
  16. static VxMethodCallRouter msgrouter = new VxMethodCallRouter();
  17. public static Bus conn;
  18. private static void DataReady(object sender, object cookie)
  19. {
  20. // FIXME: This may require special handling for padding between
  21. // messages: it hasn't been a problem so far, but should be addressed
  22. VxBufferStream vxbs = (VxBufferStream)sender;
  23. Connection conn = (Connection)cookie;
  24. if (vxbs.BufferPending == 0) {
  25. log.print("??? DataReady but nothing to read\n");
  26. return;
  27. }
  28. // XXX: Ew.
  29. byte[] buf = new byte[vxbs.BufferPending];
  30. vxbs.Read(buf, 0, buf.Length);
  31. vxbs.BufferAmount = conn.ReceiveBuffer(buf, 0, buf.Length);
  32. }
  33. private static void NoMoreData(object sender, object cookie)
  34. {
  35. log.print(
  36. "***********************************************************\n"+
  37. "************ D-bus connection closed by server ************\n"+
  38. "***********************************************************\n");
  39. VxBufferStream vxbs = (VxBufferStream)sender;
  40. vxbs.Close();
  41. VxEventLoop.Shutdown();
  42. }
  43. private static void MessageReady(Message msg)
  44. {
  45. // FIXME: This should really queue things to be run from the thread
  46. // pool and then the response would be sent back through the action
  47. // queue
  48. log.print(WvLog.L.Debug4, "MessageReady\n");
  49. VxDbus.MessageDump("<< ", msg);
  50. switch (msg.Header.MessageType) {
  51. case MessageType.MethodCall:
  52. {
  53. Message reply;
  54. if (msgrouter.RouteMessage(msg, out reply)) {
  55. if (reply == null) {
  56. // FIXME: Do something if this happens, maybe?
  57. log.print("Empty reply from RouteMessage\n");
  58. } else {
  59. // XXX: Should this be done further down rather than
  60. // passing the reply out here?
  61. msg.Connection.Send(reply);
  62. }
  63. return;
  64. }
  65. break;
  66. }
  67. }
  68. // FIXME: This is hacky. But it covers stuff I don't want to deal with
  69. // yet.
  70. oldhandler(msg);
  71. }
  72. static void ShowHelp()
  73. {
  74. Console.Error.WriteLine
  75. ("Usage: versaplexd [-v] [-b dbus-moniker]" + Environment.NewLine +
  76. " [-c config-file]");
  77. Environment.Exit(1);
  78. }
  79. public static int Main(string[] args)
  80. {
  81. WvLog.L verbose = WvLog.L.Info;
  82. string bus = null;
  83. string cfgfile = "versaplexd.ini";
  84. new OptionSet()
  85. .Add("v|verbose", delegate(string v) { ++verbose; })
  86. .Add("b=|bus=", delegate(string v) { bus = v; })
  87. .Add("c=|config=", delegate(string v) { cfgfile = v; })
  88. .Add("?|h|help", delegate(string v) { ShowHelp(); })
  89. .Parse(args);
  90. WvLog.maxlevel = (WvLog.L)verbose;
  91. msgrouter.AddInterface(VxDbInterfaceRouter.Instance);
  92. bool cfgfound = false;
  93. if (System.IO.File.Exists(cfgfile)) {
  94. cfgfound = true;
  95. } else if (System.IO.File.Exists("/etc/versaplexd.ini")) {
  96. log.print("Using /etc/versaplexd.ini for configuration." +
  97. Environment.NewLine);
  98. cfgfound = true;
  99. cfgfile = "/etc/versaplexd.ini";
  100. }
  101. if (cfgfound == true) {
  102. VxSqlPool.SetIniFile(cfgfile);
  103. } else {
  104. throw new Exception(String.Format(
  105. "Could not find config file '{0},'" +
  106. Environment.NewLine +
  107. "and /etc/versaplexd.ini does not exist", cfgfile));
  108. }
  109. if (bus == null)
  110. bus = Address.Session;
  111. if (bus == null)
  112. {
  113. log.print
  114. ("DBUS_SESSION_BUS_ADDRESS not set and no -b option given.\n");
  115. ShowHelp();
  116. }
  117. log.print("Connecting to '{0}'\n", bus);
  118. AddressEntry aent = AddressEntry.Parse(bus);
  119. DodgyTransport trans = new DodgyTransport();
  120. trans.Open(aent);
  121. conn = new Bus(trans);
  122. string myNameReq = "com.versabanq.versaplex";
  123. RequestNameReply rnr = conn.RequestName(myNameReq,
  124. NameFlag.DoNotQueue);
  125. switch (rnr) {
  126. case RequestNameReply.PrimaryOwner:
  127. log.print("Name registered, ready\n");
  128. break;
  129. default:
  130. log.print("Register name result: \n" + rnr.ToString());
  131. return 2;
  132. }
  133. VxBufferStream vxbs = new VxBufferStream(trans.Socket);
  134. conn.Transport.Stream = vxbs;
  135. conn.ns = conn.Transport.Stream;
  136. vxbs.Cookie = conn;
  137. vxbs.DataReady += DataReady;
  138. vxbs.NoMoreData += NoMoreData;
  139. vxbs.BufferAmount = 16;
  140. oldhandler = conn.OnMessage;
  141. conn.OnMessage = MessageReady;
  142. VxEventLoop.Run();
  143. log.print("Done!\n");
  144. return 0;
  145. }
  146. }
  147. class DodgyTransport : NDesk.DBus.Transports.Transport
  148. {
  149. static bool IsMono()
  150. {
  151. return Type.GetType("Mono.Runtime") != null;
  152. }
  153. // This has to be a separate function so we can delay JITting it until
  154. // we're sure it's mono.
  155. string MonoAuthString()
  156. {
  157. return UnixUserInfo.GetRealUserId().ToString();
  158. }
  159. public override string AuthString()
  160. {
  161. if (IsMono())
  162. return MonoAuthString();
  163. else
  164. return "WIN32"; // FIXME do something better?
  165. }
  166. public override void WriteCred()
  167. {
  168. Stream.WriteByte(0);
  169. }
  170. public override void Open(AddressEntry entry)
  171. {
  172. if (entry.Method == "unix")
  173. {
  174. string path;
  175. bool abstr;
  176. if (entry.Properties.TryGetValue("path", out path))
  177. abstr = false;
  178. else if (entry.Properties.TryGetValue("abstract", out path))
  179. abstr = true;
  180. else
  181. throw new Exception("No path specified for UNIX transport");
  182. if (abstr)
  183. socket = OpenAbstractUnix(path);
  184. else
  185. socket = OpenPathUnix(path);
  186. }
  187. else if (entry.Method == "tcp")
  188. {
  189. string host = "127.0.0.1";
  190. string port = "5555";
  191. entry.Properties.TryGetValue("host", out host);
  192. entry.Properties.TryGetValue("port", out port);
  193. socket = OpenTcp(host, Int32.Parse(port));
  194. }
  195. else
  196. throw new Exception(String.Format("Unknown connection method {0}",
  197. entry.Method));
  198. socket.Blocking = true;
  199. SocketHandle = (long)socket.Handle;
  200. Stream = new NetworkStream(socket);
  201. }
  202. protected VxNotifySocket OpenAbstractUnix(string path)
  203. {
  204. AbstractUnixEndPoint ep = new AbstractUnixEndPoint(path);
  205. VxNotifySocket client = new VxNotifySocket(AddressFamily.Unix,
  206. SocketType.Stream, 0);
  207. client.Connect(ep);
  208. return client;
  209. }
  210. public VxNotifySocket OpenPathUnix(string path)
  211. {
  212. UnixEndPoint ep = new UnixEndPoint(path);
  213. VxNotifySocket client = new VxNotifySocket(AddressFamily.Unix,
  214. SocketType.Stream, 0);
  215. client.Connect(ep);
  216. return client;
  217. }
  218. public VxNotifySocket OpenTcp(string host, int port)
  219. {
  220. IPHostEntry hent = Dns.GetHostEntry(host);
  221. IPAddress ip = hent.AddressList[0];
  222. IPEndPoint ep = new IPEndPoint(ip, port);
  223. VxNotifySocket client = new VxNotifySocket(AddressFamily.InterNetwork,
  224. SocketType.Stream, 0);
  225. client.Connect(ep);
  226. return client;
  227. }
  228. protected VxNotifySocket socket;
  229. public VxNotifySocket Socket {
  230. get { return socket; }
  231. }
  232. }