private void confirmfail(WvDbusMsg response) { WVPASS(response.type = Wv.Dbus.MType.Error); WVPASS(response.signature = "s"); var i = response.iter(); WVPASSEQ(i.pop(), failmsg); }
public WvDbusMsg reply(string signature) { WvDbusMsg reply = new WvDbusMsg(); reply.type = Dbus.MType.MethodReturn; reply.flags = Dbus.MFlag.NoReplyExpected | Dbus.MFlag.NoAutoStart; reply.rserial = this.serial; reply.dest = this.sender; reply.signature = signature; return reply; }
internal static void SendChunkRecordSignal(WvDbus conn, WvDbusMsg call, string sender, VxColumnInfo[] colinfo, object[][] data, byte[][] nulls) { WvDbusWriter writer = VxDbusRouter.PrepareRecordsetWriter(colinfo, data, nulls); writer.Write(call.serial); new WvDbusSignal(call.sender, call.path, "vx.db", "ChunkRecordsetSig", "a(issnny)vaayu") .write(writer) .send(conn); }
static void CallGetSchemaChecksums(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature.ne()) { reply = CreateUnknownMethodReply(call, "GetSchemaChecksums"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } // FIXME: Add vx.db.toomuchdata error WvDbusWriter writer = new WvDbusWriter(); //FIXME: No exception catching? using (var dbi = VxSqlPool.create(clientid)) { VxDbSchema backend = new VxDbSchema(dbi); VxSchemaChecksums sums = backend.GetChecksums(); sums.WriteChecksums(writer); } reply = call.reply(VxSchemaChecksums.GetDbusSignature()).write(writer); }
static void CallExecChunkRecordset(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { // XXX: Stuff in this comment block shamelessly stolen from // "CallExecRecordset". if (call.signature != "s") { reply = CreateUnknownMethodReply(call, "ExecChunkRecordset"); return; } if (call.Body == null) { reply = call.err_reply ("org.freedesktop.DBus.Error.InvalidSignature", "Signature provided but no body received"); return; } /// XXX VxDb.ExecChunkRecordset(conn, call, out reply); }
public static void CallExecRecordset(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature != "s") { reply = CreateUnknownMethodReply(call, "ExecRecordset"); return; } if (call.Body == null) { reply = call.err_reply ("org.freedesktop.DBus.Error.InvalidSignature", "Signature provided but no body received"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } var it = call.iter(); string query = it.pop(); VxColumnInfo[] colinfo; object[][] data; byte[][] nullity; VxDb.ExecRecordset(clientid, (string)query, out colinfo, out data, out nullity); // FIXME: Add vx.db.toomuchdata error WvDbusWriter writer = PrepareRecordsetWriter(colinfo, data, nullity); reply = call.reply("a(issnny)vaay").write(writer); }
static void CallExecScalar(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature != "s") { reply = CreateUnknownMethodReply(call, "ExecScalar"); return; } if (call.Body == null) { reply = call.err_reply ("org.freedesktop.DBus.Error.InvalidSignature", "Signature provided but no body received"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } var it = call.iter(); string query = it.pop(); object result; VxColumnType coltype; VxDb.ExecScalar(clientid, (string)query, out coltype, out result); WvDbusWriter writer = new WvDbusWriter(); writer.WriteSig(VxColumnTypeToSignature(coltype)); WriteV(writer, coltype, result); reply = call.reply("v").write(writer); }
static void CallQuit(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { // FIXME: Check permissions here WvDbusWriter writer = new WvDbusWriter(); writer.Write("Quit"); reply = call.reply("s").write(writer); Versaplexd.want_to_die = true; }
static void CallGetSchemaData(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature != "ss") { reply = CreateUnknownMethodReply(call, "GetSchemaData"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } var it = call.iter(); string tablename = it.pop(); string where = it.pop(); WvDbusWriter writer = new WvDbusWriter(); // FIXME: No exception catching? // FIXME: Should receive the replace/skip parameters via dbus using (var dbi = VxSqlPool.create(clientid)) { VxDbSchema backend = new VxDbSchema(dbi); string schemadata = backend.GetSchemaData(tablename, 0, where, null, null); writer.Write(schemadata); } reply = call.reply("s").write(writer); }
private static void HandleCancelQuery(WvDbus conn, WvDbusMsg msg) { log.print(WvLog.L.Debug4, "Received CancelQuery request\n"); //FIXME: Should I be in yet another thread? Action perform = null; if (msg.signature != "u" && msg.signature != "s") { //accept 's' signatures for Perl DBus, which is stupid and can't //send me 'u' parameters, even though the api accepts them. log.print(WvLog.L.Debug4, "CancelQuery: bad signature {0}\n", msg.signature); perform = () => { conn.send(msg.err_reply( "org.freedesktop.DBus.Error.UnknownMethod", "No overload of {0} has signature '{1}'", "CancelQuery", msg.signature)); }; } else { var it = msg.iter(); uint tokill; if (msg.signature == "s") { log.print(WvLog.L.Debug4, "CancelQuery: converting arg from string\n"); string temps = it.pop(); tokill = Convert.ToUInt32(temps); } else tokill = it.pop(); log.print(WvLog.L.Debug4, "CancelQuery: try killing msg id {0}\n", tokill); lock (action_mutex) { if (curaction != null && curaction.conn == conn && curaction.src.serial == tokill) { log.print(WvLog.L.Debug4, "CancelQuery: killing current action!\n"); WvSqlRows_IDataReader.Cancel(); curaction = null; } else { log.print(WvLog.L.Debug4, "CancelQuery: traversing action queue...\n"); //Traverse the action queue, killing stuff foreach (VxActionTriple t in action_queue) if (t.conn == conn && t.src.serial == tokill) { log.print(WvLog.L.Debug4, "CancelQuery: found culprit, killing.\n"); //action_queue.Remove(t); //FIXME: What message should we really put here? t.action = () => { conn.send(t.src.err_reply("vx.db.sqlerror", "This message got canceled")); }; break; } } } //Pointless return to make Perl happy. perform = () => { WvDbusWriter writer = new WvDbusWriter(); writer.Write("Cancel"); conn.send(msg.reply("s").write(writer)); }; log.print(WvLog.L.Debug4, "CancelQuery: complete\n"); } //FIXME: It's not clear whether for just add operations, in conjuction //with RemoveAt(0) going on in the otherthread, we need a mutex. action_queue.Add(new VxActionTriple(conn, msg, perform)); }
public static string GetClientId(WvDbusMsg call) { string sender = call.sender; // For now, the client ID is just the username of the Unix UID that // DBus has associated with the connection. string username; var conn = Versaplexd.conn; if (!usernames.TryGetValue(sender, out username)) { try { // FIXME: This will likely change as we find a more // universal way to do SSL authentication via D-Bus. username = VxSqlPool.GetUsernameForCert( conn.GetCertFingerprint(sender)); } catch { try { // FIXME: This system call isn't actually standard username = conn.GetUnixUserName(sender); } catch { try { // FIXME: This system call is standard, but not useful // on Windows. username = conn.GetUnixUser(sender).ToString(); } catch { username = "******"; // use default connection, if any } } } // Remember the result, so we don't have to ask DBus all the time usernames[sender] = username; log.print(WvLog.L.Info, "New connection '{0}' is user '{1}'\n", sender, username); } return username; }
void ExecuteCall(MethodCallProcessor processor, WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { try { processor(conn, call, out reply); } catch (VxRequestException e) { reply = call.err_reply(e.DBusErrorType, e.Message); log.print("SQL result: {0}\n", e.Short()); } catch (Exception e) { reply = call.err_reply("vx.db.exception", "An internal error occurred."); log.print("{0}\n", e.ToString()); } }
public bool route(WvDbus conn, WvDbusMsg msg, out WvDbusMsg reply) { MethodCallProcessor p; if (msg.ifc != "vx.db" || msg.path != "/db") { reply = null; return false; } if (msg.method == "Test") p = CallTest; else if (msg.method == "Quit") p = CallQuit; else if (msg.method == "ExecScalar") p = CallExecScalar; else if (msg.method == "ExecRecordset") p = CallExecRecordset; else if (msg.method == "ExecChunkRecordset") p = CallExecChunkRecordset; else if (msg.method == "GetSchemaChecksums") p = CallGetSchemaChecksums; else if (msg.method == "GetSchema") p = CallGetSchema; else if (msg.method == "PutSchema") p = CallPutSchema; else if (msg.method == "DropSchema") p = CallDropSchema; else if (msg.method == "GetSchemaData") p = CallGetSchemaData; else if (msg.method == "PutSchemaData") p = CallPutSchemaData; else { // FIXME: this should be done at a higher level somewhere reply = msg.err_reply( "org.freedesktop.DBus.Error.UnknownMethod", "Method name {0} not found on interface {1}", msg.method, msg.ifc); return true; } ExecuteCall(p, conn, msg, out reply); return true; }
internal static void ExecChunkRecordset(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { string connid = VxDbusRouter.GetClientId(call); if (connid == null) { reply = call.err_reply( "org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } var it = call.iter(); string query = query_parser(it.pop(), VxSqlPool.access_restrictions(connid)); log.print(WvLog.L.Debug3, "ExecChunkRecordset {0}\n", query); //Times we tried going through this loop to completion int numtries = 0; while (true) { try { List<object[]> rows = new List<object[]>(); List<byte[]> rownulls = new List<byte[]>(); VxColumnInfo[] colinfo; // Our size here is just an approximation. int cursize = 0; // FIXME: Sadly, this is stupidly similar to ExecRecordset. // Anything we can do here to identify commonalities? using (var dbi = VxSqlPool.create(connid)) using (WvSqlRows resultset = dbi.select(query)) { var columns = resultset.columns.ToArray(); colinfo = ProcessSchema(columns); int ncols = columns.Count(); foreach (WvSqlRow cur_row in resultset) { object[] row = new object[ncols]; byte[] rownull = new byte[ncols]; cursize += rownull.Length; for (int i = 0; i < ncols; i++) { WvAutoCast cval = cur_row[i]; bool isnull = cval.IsNull; row[i] = null; rownull[i] = isnull ? (byte)1 : (byte)0; switch (colinfo[i].VxColumnType) { case VxColumnType.Int64: row[i] = !isnull ? (Int64)cval : new Int64(); cursize += sizeof(Int64); break; case VxColumnType.Int32: row[i] = !isnull ? (Int32)cval : new Int32(); cursize += sizeof(Int32); break; case VxColumnType.Int16: row[i] = !isnull ? (Int16)cval : new Int16(); cursize += sizeof(Int16); break; case VxColumnType.UInt8: row[i] = !isnull ? (Byte)cval : new Byte(); cursize += sizeof(Byte); break; case VxColumnType.Bool: row[i] = !isnull ? (bool)cval : new Boolean(); cursize += sizeof(Boolean); break; case VxColumnType.Double: // Might return a Single or Double // FIXME: Check if getting a single causes // this to croak row[i] = !isnull ? (double)cval : (double)0.0; cursize += sizeof(double); break; case VxColumnType.Uuid: //FIXME: Do I work? row[i] = !isnull ? (string)cval : ""; cursize += !isnull ? ((string)cval).Length * sizeof(Char):0; break; case VxColumnType.Binary: { if (isnull) { row[i] = new byte[0]; break; } row[i] = (byte[])cval; cursize += ((byte[])cval).Length; break; } case VxColumnType.String: row[i] = !isnull ? (string)cval : ""; cursize += !isnull ? ((string)cval).Length * sizeof(Char):0; break; case VxColumnType.DateTime: row[i] = !isnull ? new VxDbusDateTime((DateTime)cval) : new VxDbusDateTime(); cursize += System.Runtime.InteropServices.Marshal.SizeOf((VxDbusDateTime)row[i]); break; case VxColumnType.Decimal: row[i] = !isnull ? ((Decimal)cval).ToString() : ""; cursize += ((string)(row[i])).Length * sizeof(Char); break; } } // column iterator rows.Add(row); rownulls.Add(rownull); if (cursize >= 1024*1024) //approx 1 MB { log.print(WvLog.L.Debug4, "(1 MB reached; {0} rows)\n", rows.Count); SendChunkRecordSignal(conn, call, call.sender, colinfo, rows.ToArray(), rownulls.ToArray()); rows = new List<object[]>(); rownulls = new List<byte[]>(); cursize = 0; } } // row iterator } // using // OK, we're down to either one more packet or no more data // Package that up in the 'reply' to this message, saving some // data being sent. if (cursize > 0) log.print(WvLog.L.Debug4, "(Remaining data; {0} rows)\n", rows.Count); // Create reply, either with or with no data WvDbusWriter replywriter = VxDbusRouter.PrepareRecordsetWriter(colinfo, rows.ToArray(), rownulls.ToArray()); reply = call.reply("a(issnny)vaay").write(replywriter); break; } catch (DbException e) { throw new VxSqlException(e.Message, e); } catch (VxConfigException e) { if (e.Message.StartsWith("Connect: A network-related or instance-specific error") && ++numtries <= 1) //only one retry { log.print(WvLog.L.Debug4, "Can't connect to DB, fishy..., attempting to reconnect... (attempt #{0})\n", numtries); } else throw e; //rethrow } } //while }
static void CallPutSchemaData(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature != "ss") { reply = CreateUnknownMethodReply(call, "PutSchemaData"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } var it = call.iter(); string tablename = it.pop(); string text = it.pop(); using (var dbi = VxSqlPool.create(clientid)) { VxDbSchema backend = new VxDbSchema(dbi); backend.PutSchemaData(tablename, text, 0); } reply = call.reply(); }
static bool WvDbusMsgReady(WvDbus conn, WvDbusMsg msg) { // FIXME: This should really queue things to be run from the thread // pool and then the response would be sent back through the action // queue log.print(WvLog.L.Debug4, "WvDbusMsgReady\n"); switch (msg.type) { case Wv.Dbus.MType.MethodCall: if (msg.ifc == "vx.db") { if (msg.path == "/db" && msg.method == "CancelQuery") HandleCancelQuery(conn, msg); else //not 'CancelQuery' { //FIXME: It's not clear whether for just add operations, //in conjuction with RemoveAt(0) going on in the other //thread, we need a mutex. action_queue.Add(new VxActionTriple(conn, msg, () => { WvDbusMsg reply; if (msgrouter.route(conn, msg, out reply)) { if (reply == null) { // FIXME: Do something if this happens, maybe? log.print("Empty reply from RouteWvDbusMsg\n"); } else { // XXX: Should this be done further down rather // than passing the reply out here? conn.send(reply); } } })); } return true; } return false; default: log.print(WvLog.L.Warning, "Unexpected DBus message received: #{0} {1}->{2} {3}:{4}.{5}\n", msg.serial, msg.sender, msg.dest, msg.path, msg.ifc, msg.method); return false; } }
private void confirmpass(WvDbusMsg response) { WVPASS(response.type == Wv.Dbus.MType.MethodReturn); }
public VxActionTriple(WvDbus _conn, WvDbusMsg _src, Action _action) { this.conn = _conn; this.src = _src; this.action = _action; }
static void CallDropSchema(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature != "as") { reply = CreateUnknownMethodReply(call, "DropSchema"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } var it = call.iter(); string[] keys = it.pop().Cast<string>().ToArray(); VxSchemaErrors errs; using (var dbi = VxSqlPool.create(clientid)) { VxDbSchema backend = new VxDbSchema(dbi); errs = backend.DropSchema(keys); } WvDbusWriter writer = new WvDbusWriter(); VxSchemaErrors.WriteErrors(writer, errs); reply = call.reply(VxSchemaErrors.GetDbusSignature()).write(writer); if (errs != null && errs.Count > 0) { reply.type = Wv.Dbus.MType.Error; reply.err = "org.freedesktop.DBus.Error.Failed"; } }
static WvDbusMsg CreateUnknownMethodReply(WvDbusMsg call, string methodname) { return call.err_reply("org.freedesktop.DBus.Error.UnknownMethod", "No overload of {0} has signature '{1}'", methodname, call.signature); }
static void CallPutSchema(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature != String.Format("{0}i", VxSchema.GetDbusSignature())) { reply = CreateUnknownMethodReply(call, "PutSchema"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } var it = call.iter(); VxSchema schema = new VxSchema(it.pop()); int opts = it.pop(); VxSchemaErrors errs; using (var dbi = VxSqlPool.create(clientid)) { VxDbSchema backend = new VxDbSchema(dbi); errs = backend.Put(schema, null, (VxPutOpts)opts); } WvDbusWriter writer = new WvDbusWriter(); VxSchemaErrors.WriteErrors(writer, errs); reply = call.reply(VxSchemaErrors.GetDbusSignature()).write(writer); if (errs != null && errs.Count > 0) { reply.type = Wv.Dbus.MType.Error; reply.err = "org.freedesktop.DBus.Error.Failed"; } }
static void CallTest(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature.ne()) { reply = CreateUnknownMethodReply(call, "Test"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } VxColumnInfo[] colinfo; object[][] data; byte[][] nullity; VxDb.ExecRecordset(clientid, "select 'Works! :D'", out colinfo, out data, out nullity); // FIXME: Add vx.db.toomuchdata error WvDbusWriter writer = PrepareRecordsetWriter(colinfo, data, nullity); reply = call.reply("a(issnny)vaay").write(writer); }
static void CallGetSchema(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature != "as") { reply = CreateUnknownMethodReply(call, "GetSchema"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } var it = call.iter(); string[] names = it.pop().Cast<string>().ToArray(); WvDbusWriter writer = new WvDbusWriter(); using (var dbi = VxSqlPool.create(clientid)) { VxDbSchema backend = new VxDbSchema(dbi); VxSchema schema = backend.Get(names); schema.WriteSchema(writer); } reply = call.reply(VxSchema.GetDbusSignature()).write(writer); }