Bug #12 done, almost

1 view
Skip to first unread message

Peter McCurdy

unread,
Jan 13, 2008, 2:48:58 AM1/13/08
to versap...@googlegroups.com
So I've almost got bug #12 done. The problem is that the relatively
small amount of work left depends fairly greatly on the details of the
DBus SSL connection work, so for now I've left it just using the same
hardcoded database connection parameters as before. Do we need to
support multiple database users before the SSL support is complete?
If not, I recommend being lazy, and waiting until the SSL stuff is
there so it's easy to get the user information. If we do need
multi-user support sooner, it should be straightforward enough to add,
I'll just need some guidance on what exactly is needed.

For reference, when I was doing this I realized that it should be
pretty simple to have vxodbc send its DSN information to Versaplex in
the DBus authentication session, once we overhaul that for SSL
support. This has two benefits: (a) it avoids having to do some messy
work trying to get db login information from the clients into
Versaplex, and (b) it avoids having to do some messy work trying to
figure out which username maps to which connection.

Avery, how do you feel about this?

Peter.

Avery Pennarun

unread,
Jan 13, 2008, 6:51:22 PM1/13/08
to versap...@googlegroups.com
On 13/01/2008, Peter McCurdy <peterm...@alumni.uwaterloo.ca> wrote:
> So I've almost got bug #12 done. The problem is that the relatively
> small amount of work left depends fairly greatly on the details of the
> DBus SSL connection work, so for now I've left it just using the same
> hardcoded database connection parameters as before. Do we need to
> support multiple database users before the SSL support is complete?
> If not, I recommend being lazy, and waiting until the SSL stuff is
> there so it's easy to get the user information. If we do need
> multi-user support sooner, it should be straightforward enough to add,
> I'll just need some guidance on what exactly is needed.

I don't think that actually would count as "lazy", since debugging an
SSL authentication layer at the same time as the database access layer
sounds like it would be pretty complicated. I'd much rather have a
fully-functional program first, then add SSL to it.

> For reference, when I was doing this I realized that it should be
> pretty simple to have vxodbc send its DSN information to Versaplex in
> the DBus authentication session, once we overhaul that for SSL
> support. This has two benefits: (a) it avoids having to do some messy
> work trying to get db login information from the clients into
> Versaplex, and (b) it avoids having to do some messy work trying to
> figure out which username maps to which connection.

I don't think versaplexd should know anything about the dbus
authentication phase, because it currently doesn't act as a
dbus-daemon and we don't want to artificially boost the priority of
that feature.

All versaplexd wants to do is *ask* the dbus-daemon who the client
actually is, and get an answer back. The answer can be in whatever
format, and that might change. For now, I'd say make it an opaque
string and versaplexd can treat that string in some kind of defined
way (basically a many-to-one mapping of various auth strings to a
database connection string, ie the same database connection string can
be the target of more than one auth string).

To implement the asking part, versaplexd would take the source field
from an incoming request message, then send a message back to the bus
daemon asking who that source is. wvdbusd would know what to do in
that case, and dbus-daemon wouldn't.

We could define a particular, non-standard service name whose job it
is to map source fields to auth strings. That would actually be kind
of cool; in wvdbusd, that service provider could be built into the bus
daemon (and thus pull stuff out of the SSL connection, etc), while in
a normal dbus-daemon, it might theoretically be provided using a
PAP/CHAP style authentication system by just having another daemon
provide that service on the bus. We don't need to provide such a
daemon, but the fact that it's possible means that it's a good design.

Naturally, versaplexd should cache the sourceid-to-authstring mapping,
since a given sourceid is guaranteed to always have the same
authstring.

Does this make sense? With this design, I believe the only change
required to authenticate SSL certs instead of just hardcoding it would
be to update wvdbusd to answer the mapping request differently.

Does that answer the question?

Thanks,

Avery

Peter McCurdy

unread,
Jan 13, 2008, 11:13:34 PM1/13/08
to versap...@googlegroups.com
On Jan 13, 2008 6:51 PM, Avery Pennarun <apen...@gmail.com> wrote:
>
> On 13/01/2008, Peter McCurdy <peterm...@alumni.uwaterloo.ca> wrote:
> > For reference, when I was doing this I realized that it should be
> > pretty simple to have vxodbc send its DSN information to Versaplex in
> > the DBus authentication session, once we overhaul that for SSL
> > support. This has two benefits: (a) it avoids having to do some messy
> > work trying to get db login information from the clients into
> > Versaplex, and (b) it avoids having to do some messy work trying to
> > figure out which username maps to which connection.
>
> I don't think versaplexd should know anything about the dbus
> authentication phase, because it currently doesn't act as a
> dbus-daemon and we don't want to artificially boost the priority of
> that feature.

Sorry, I wasn't clear, that's basically what I meant. When I said
"vxodbc send[s] its DSN information to Versaplex", I meant "vxodbc
sends its DSN information to the DBus daemon, which remembers it and
can give it to Versaplex if asked". Strictly speaking it doesn't have
to be part of the authentication session, but that just strikes me as
the easiest and least error-prone way to go, since we'll already be
sending usernames and passwords around. It'll may be a tiny bit
faster to boot, as we might be able to save a round-trip.

> All versaplexd wants to do is *ask* the dbus-daemon who the client
> actually is, and get an answer back. The answer can be in whatever
> format, and that might change. For now, I'd say make it an opaque
> string and versaplexd can treat that string in some kind of defined
> way (basically a many-to-one mapping of various auth strings to a
> database connection string, ie the same database connection string can
> be the target of more than one auth string).

OK, this is almost what I have done already. The opaque string is the
unix UID, for now. The only issue is that at the moment there's just
one hard-coded database connection string. My only remaining question
then is what you mean by "some kind of defined way". I suppose
technically, returning a single connection string is "a many-to-one
mapping of various auth strings to a database connection string", but
I imagine you might want something a bit more useful :)

If I work things right, I can phrase the API as "get me a connection
string from this client ID string"; for now, it can be through a table
or something, later that function can parse the client ID string to
retrieve the relevant parameters.

> To implement the asking part, versaplexd would take the source field
> from an incoming request message, then send a message back to the bus
> daemon asking who that source is. wvdbusd would know what to do in
> that case, and dbus-daemon wouldn't.

That's a good plan, for one very significant reason: it's the only
possible way anything will work :) It's very difficult for the bus to
provide additional data when forwarding a message, especially if you
want to have half a hope of ever working with the standard DBus
daemon. The only sane way to go is to send additional queries from
Versaplex. It adds some round trips here and there, but nothing too
horrible with some caching. That's what I'm already doing, except the
only information I get for the source is the Unix UID provided from
the GetConnectionUnixUser method.

> We could define a particular, non-standard service name whose job it
> is to map source fields to auth strings. That would actually be kind
> of cool; in wvdbusd, that service provider could be built into the bus
> daemon (and thus pull stuff out of the SSL connection, etc), while in
> a normal dbus-daemon, it might theoretically be provided using a
> PAP/CHAP style authentication system by just having another daemon
> provide that service on the bus. We don't need to provide such a
> daemon, but the fact that it's possible means that it's a good design.

I was actually thinking about this at first - call it a holdover from
having written a message-passing operating system in school, my first
instinct whenever any new message type needs an answer is to write a
new daemon :) At first I didn't bother because I couldn't figure out
how to get the authentication daemon to authenticate itself to the
message bus. I suppose that's fairly minor in the scheme of things -
just yell really really loudly if the real auth daemon can't register
its name. However, the more pressing practical matter is that I
wouldn't be able to take advantage of the magical dbus-sharp bus
method proxying (which only works for methods on the
org.freedesktop.Dbus object, AFAIK), and I still haven't figured out
how to make a regular old DBus method call from inside Versaplex.

This would be simple to change later though, assuming you've by then
whipped dbus-sharp into shape or replaced it with something else -
just change the object name used in Versaplex and wvdbusd, nobody else
will be using the old method. You can even continue answering to the
old method name in wvdbusd if you really want.

And yes, it does rather reek of good design - hooray for message passing!

> Naturally, versaplexd should cache the sourceid-to-authstring mapping,
> since a given sourceid is guaranteed to always have the same
> authstring.

Already done.

> Does this make sense? With this design, I believe the only change
> required to authenticate SSL certs instead of just hardcoding it would
> be to update wvdbusd to answer the mapping request differently.
>
> Does that answer the question?

I'm still a bit confused about where the database connection strings
come from. Should I be working on sending them from vxodbc to
wvdbusd? Is it acceptable for now to just have a list of hard-coded
strings in Versaplex? Use a config file? Were you thinking about
something else altogether?

Also, did you have any bright ideas for what sort of opaque id strings
to provide to Versaplex from the bus? The Unix UID was a convenient
hack, since the method is already there in the real DBus daemon, but
it has certain issues (like not making sense over TCP).

But otherwise, it sounds like we're generally talking along the same
lines for everything, which is nice.

Peter.

Peter McCurdy

unread,
Jan 16, 2008, 10:05:35 AM1/16/08
to versap...@googlegroups.com
Is there any update on this? I'd like to get it finished up, one way
or the other (though I don't have a big problem waiting if there's a
good reason to). Or we can talk about it when you're in Montreal, if
you'd prefer.

Thanks.

Peter.

On Jan 13, 2008 11:13 PM, Peter McCurdy

Avery Pennarun

unread,
Jan 16, 2008, 10:25:16 AM1/16/08
to versap...@googlegroups.com
Sorry for the delay. Somehow I didn't see this message at all. See
my replies inline:

> Sorry, I wasn't clear, that's basically what I meant. When I said
> "vxodbc send[s] its DSN information to Versaplex", I meant "vxodbc
> sends its DSN information to the DBus daemon, which remembers it and
> can give it to Versaplex if asked". Strictly speaking it doesn't have
> to be part of the authentication session, but that just strikes me as
> the easiest and least error-prone way to go, since we'll already be
> sending usernames and passwords around. It'll may be a tiny bit
> faster to boot, as we might be able to save a round-trip.

It's just that the "authentication phase" with the bus is a particular
part of the protocol that is non-extensible in the standard
dbus-daemon, so relying on that makes it so that a separate
authentication daemon wouldn't be possible.

If by "authentication session" you mean the message to the auth
service, then yes, that works.

Incidentally, "DSN information" is also a little unclear. versaplexd
probably shouldn't need to know anything about DSNs, just opaque
authentication strings. So *part* of vxodbc's ODBC DSN (ie. one of
the name-value pairs) would be something like "Auth=apenwarr" or
something like that. One day, it would be
"Auth=a_big_binary_ssl_certificate".

> > All versaplexd wants to do is *ask* the dbus-daemon who the client
> > actually is, and get an answer back. The answer can be in whatever
> > format, and that might change. For now, I'd say make it an opaque
> > string and versaplexd can treat that string in some kind of defined
> > way (basically a many-to-one mapping of various auth strings to a
> > database connection string, ie the same database connection string can
> > be the target of more than one auth string).
>
> OK, this is almost what I have done already. The opaque string is the
> unix UID, for now. The only issue is that at the moment there's just
> one hard-coded database connection string. My only remaining question
> then is what you mean by "some kind of defined way". I suppose
> technically, returning a single connection string is "a many-to-one
> mapping of various auth strings to a database connection string", but
> I imagine you might want something a bit more useful :)

versaplexd needs a configuration file that lists the database
connection strings, which should no longer be hardcoded. (Wv.Net
already has a class for reading/writing inifiles, so this part should
be easy.) Then, another part of the config file is a mapping of
opaque auth string to database connection name.

Something like this:

[Connections]
db1 = mssql://user@hostname:port/database
db2 = mysql:username

[User Map]
apenwarr = db1
pmccurdy = db1
andrei = db2

We'll probably change later exactly how the connection mapping works
(ie. the above doesn't have a way to allow a user access to more than
one database) but this is good enough for now.

Don't get hung up on the exact format of the connection string, I just
made that up. Ideally it would be one single moniker, though. Using
a DSN *here* might not be a bad idea.

> That's a good plan, for one very significant reason: it's the only
> possible way anything will work :) It's very difficult for the bus to
> provide additional data when forwarding a message, especially if you
> want to have half a hope of ever working with the standard DBus
> daemon. The only sane way to go is to send additional queries from
> Versaplex. It adds some round trips here and there, but nothing too
> horrible with some caching. That's what I'm already doing, except the
> only information I get for the source is the Unix UID provided from
> the GetConnectionUnixUser method.

The other thing we could do is emit a broadcast signal every time
someone registers with the auth daemon, but I doubt the speed
improvement from that would be worth much. And to deal with servers
who join later than clients (probably a rare situation), we'd have to
support polling mode anyway.

The key thing is that we cache the answer once we get it. Beyond
that, it's probably not important for speed.

> At first I didn't bother because I couldn't figure out
> how to get the authentication daemon to authenticate itself to the
> message bus. I suppose that's fairly minor in the scheme of things -
> just yell really really loudly if the real auth daemon can't register
> its name.

The standard dbus-daemon already has security features like that for
the "system" bus. Basically only certain uids (set in a config file)
are allowed to register certain service names. wvdbusd doesn't have
that (yet?), but it proves that it's possible, at least :)

> However, the more pressing practical matter is that I
> wouldn't be able to take advantage of the magical dbus-sharp bus
> method proxying (which only works for methods on the
> org.freedesktop.Dbus object, AFAIK), and I still haven't figured out
> how to make a regular old DBus method call from inside Versaplex.

Okay, well, we can always change the service name later. Automatic
bus method proxying sounds is something I personally would want to
delete anyhow :)

> I'm still a bit confused about where the database connection strings
> come from. Should I be working on sending them from vxodbc to
> wvdbusd? Is it acceptable for now to just have a list of hard-coded
> strings in Versaplex? Use a config file? Were you thinking about
> something else altogether?

I've now answered most of that above. The key thing to emphasize is
that vxodbc should have no idea what kind of database versaplexd is
connected to, or where it is, or which user it's logged in as, nor
should it care. So we need versaplexd to be able to map vxodbc's
request to the real connection.

> Also, did you have any bright ideas for what sort of opaque id strings
> to provide to Versaplex from the bus? The Unix UID was a convenient
> hack, since the method is already there in the real DBus daemon, but
> it has certain issues (like not making sense over TCP).

For now, vxodbc should probably just register using its unix uid, but
the registration daemon should *announce* the completed registration
using the username. UID is necessary to actually confirm that the
user is who he says it is (with unix domain socket credentials stuff),
but isn't actually useful for people on other machines, etc.

This all isn't very secure, but that doesn't matter, because we'll
replace it with SSL before we use it in real life.

Sorry again for the delay.

Have fun,

Avery

Peter McCurdy

unread,
Jan 16, 2008, 1:39:59 PM1/16/08
to versap...@googlegroups.com
On Jan 16, 2008 10:25 AM, Avery Pennarun <apen...@gmail.com> wrote:
> > Sorry, I wasn't clear, that's basically what I meant. When I said
> > "vxodbc send[s] its DSN information to Versaplex", I meant "vxodbc
> > sends its DSN information to the DBus daemon, which remembers it and
> > can give it to Versaplex if asked". Strictly speaking it doesn't have
> > to be part of the authentication session, but that just strikes me as
> > the easiest and least error-prone way to go, since we'll already be
> > sending usernames and passwords around. It'll may be a tiny bit
> > faster to boot, as we might be able to save a round-trip.
>
> It's just that the "authentication phase" with the bus is a particular
> part of the protocol that is non-extensible in the standard
> dbus-daemon, so relying on that makes it so that a separate
> authentication daemon wouldn't be possible.

Isn't it? I thought the standard daemon had some facilities for
supporting new auth methods. Oh well, not a big deal either way, if
it even might be a problem then sending a message is just about as
easy.

> If by "authentication session" you mean the message to the auth
> service, then yes, that works.

That wasn't what I meant exactly, but yeah, the intent is the same.

> Incidentally, "DSN information" is also a little unclear. versaplexd
> probably shouldn't need to know anything about DSNs, just opaque
> authentication strings. So *part* of vxodbc's ODBC DSN (ie. one of
> the name-value pairs) would be something like "Auth=apenwarr" or
> something like that. One day, it would be
> "Auth=a_big_binary_ssl_certificate".

Yeah, I realized after I sent it. I was talking about the connection
string as a whole, particularly the user= and password= fields; I was
thinking that you'd want to be able to set the db login information
from the clients. But evidently not, as you explain below.

Cool, that's exactly what I was looking for. And yeah, ODBC
connection strings (calling them DSNs earlier was a mistake, really)
make a reasonable amount of sense, especially if we can pass them
straight to the C# connection functions. Even if not, they're easy
enough to parse.

> The other thing we could do is emit a broadcast signal every time
> someone registers with the auth daemon, but I doubt the speed
> improvement from that would be worth much. And to deal with servers
> who join later than clients (probably a rare situation), we'd have to
> support polling mode anyway.
>
> The key thing is that we cache the answer once we get it. Beyond
> that, it's probably not important for speed.

Right, I keep forgetting about signals.

> The standard dbus-daemon already has security features like that for
> the "system" bus. Basically only certain uids (set in a config file)
> are allowed to register certain service names. wvdbusd doesn't have
> that (yet?), but it proves that it's possible, at least :)

Ah, the benefits of having an actual operating system running behind
you, instead of writing your own - you get luxuries like config files
and uids :)

> Okay, well, we can always change the service name later. Automatic
> bus method proxying sounds is something I personally would want to
> delete anyhow :)

It's kind of nice. In an "OMG I can't follow that code, but I know
it's dynamically generating CLR assembly code behind the scenes
somewhere" kind of way. So yeah, maybe worth getting rid of in the
long run :)

> I've now answered most of that above. The key thing to emphasize is
> that vxodbc should have no idea what kind of database versaplexd is
> connected to, or where it is, or which user it's logged in as, nor
> should it care. So we need versaplexd to be able to map vxodbc's
> request to the real connection.

Ah, OK, that's a good set of principles to keep in mind. And it'll
certainly be a refreshing change of pace from most database client
configuration.

> For now, vxodbc should probably just register using its unix uid, but
> the registration daemon should *announce* the completed registration
> using the username. UID is necessary to actually confirm that the
> user is who he says it is (with unix domain socket credentials stuff),
> but isn't actually useful for people on other machines, etc.
>
> This all isn't very secure, but that doesn't matter, because we'll
> replace it with SSL before we use it in real life.

The only issue is that wvdbusd doesn't support Unix domain sockets,
and won't until the Unix domain sockets in WvStreams are rewritten to
use the funky new WvListener interface. I only glanced at the
WvListener stuff though, so I don't know how much work that entails.
So for now we'll just have to assume that the TCP connection is from
the local machine, and that it's trustworthy. But then, like you say,
SSL can ensure that our clients are trusted, and we can only listen
for TCP connections on localhost, so even if we never do the Unix
domain sockets we'll be OK.

> Sorry again for the delay.

Not a problem, I've been keeping busy in the meantime anyway. It'll
be nice to get this all wrapped up, but I can't promise I'll be able
to get it done right away - it might have to wait for the weekend.

Peter.

Avery Pennarun

unread,
Jan 16, 2008, 2:29:00 PM1/16/08
to versap...@googlegroups.com
> Isn't it? I thought the standard daemon had some facilities for
> supporting new auth methods. Oh well, not a big deal either way, if
> it even might be a problem then sending a message is just about as
> easy.

Well, the authentication methods are "pluggable", but by that they
mean "write more code and plug it into the dbus-daemon source code and
then recompile."

If something like xplc was actually popular, it would be easy to go
from there to real plugins, but alas, no such luck.

> > Okay, well, we can always change the service name later. Automatic
> > bus method proxying sounds is something I personally would want to
> > delete anyhow :)
>
> It's kind of nice. In an "OMG I can't follow that code, but I know
> it's dynamically generating CLR assembly code behind the scenes
> somewhere" kind of way. So yeah, maybe worth getting rid of in the
> long run :)

It's very... cute. But I don't really follow how hard-coding assembly
language is justifiable just to save a couple lines of code,
particularly when it turns out that it *doesn't* actually save a
couple of lines code because varargs in C# is typesafe anyhow and so
there's no reason you can't just have a generic "call remote function"
function.

But that's something for another day :)

> > I've now answered most of that above. The key thing to emphasize is
> > that vxodbc should have no idea what kind of database versaplexd is
> > connected to, or where it is, or which user it's logged in as, nor
> > should it care. So we need versaplexd to be able to map vxodbc's
> > request to the real connection.
>
> Ah, OK, that's a good set of principles to keep in mind. And it'll
> certainly be a refreshing change of pace from most database client
> configuration.

Well, it really just pushes the decision back a level. But having
*both* levels be highly configurable is kind of pointless. Someday
versaplexd might be so easy to install that we can actually make it
*easier* to connect to databases than it would be natively (eg. using
ZeroConf or something to auto-discover servers and populate a
dropdown). But for now, our lack of any installer whatsoever kind of
precludes that.

But "don't make things worse" is a good place to start :)

> The only issue is that wvdbusd doesn't support Unix domain sockets,

Oh, right. Well, in that case, we'll have 100% totally insecure tcp
non-authentication then. Works for me for now :)

Have fun,

Avery

Peter McCurdy

unread,
Jan 21, 2008, 4:21:56 AM1/21/08
to versap...@googlegroups.com
On Jan 16, 2008 2:29 PM, Avery Pennarun <apen...@gmail.com> wrote:
> It's very... cute. But I don't really follow how hard-coding assembly
> language is justifiable just to save a couple lines of code,
> particularly when it turns out that it *doesn't* actually save a
> couple of lines code because varargs in C# is typesafe anyhow and so
> there's no reason you can't just have a generic "call remote function"
> function.

But... but... then it wouldn't look like a method call! :)

Anyway, I think I'm done now. It turns out I was caching the wrong
thing (the computed connection string given a uid, rather than the uid
given a unique bus name), but that was trivial to fix. The config
file format is pretty much what you specified. The easiest way to
describe it is probably with an example, so here's my current version:

[Connections]
testdb = mssql:User Id=asta;Password=m!ddle-tear;Server=amsdev;Initial
Catalog=adrian_test

[User Map]
pmccurdy = testdb

The mssql: entries under [Connections] are defined to just be the
standard MS SQL connection string, for laziness. I.e. one can just
assign them to a SqlConnectionStringBuilder. This also means that (a)
they're already well specified and (b) they support just about all
possible connection options, two things that wouldn't be true if I
dreamed up something myself. As for the format not giving a user
access to multiple databases, you could always declare the values in
the [User Map] section to be a space-separated list of connections;
you'd still need a way to request a particular database, but that's
orthogonal. Or there are plenty of other options, I suppose.

For now, Versaplex still just retrieves Unix uids from wvdbusd, and
does its own username lookup. Do you still think it's worth exporting
usernames from wvdbusd, or was that tied to you thinking that wvdbusd
would be using Unix domain sockets?

The other unresolved issue in my head is that if a username or
connection string is missing from the config file, the error message
sent back to the client is a slightly cryptic null reference message
when code tries to use a nonexistent connection after TakeConnection
returns null. I don't know what the overall philosophy on returning
errors from Versaplex is (throw an exception as soon as we find a
problem? Return an error reply to DBus when we eventually notice that
we couldn't find a connection?). I was leaning towards throwing an
exception as soon as we find a problem, as it seems like the easiest
way to get a proper error message out to DBus, but then I got cold
feet about adding some not-horrendously-exceptional exceptions. This
should also be easy to fix one way or the other.

Stuff that remains:
* Checking in a sample versaplexd.ini config file (or is this too much
of a pain, due to having to change a file checked into Subversion?).
* Fixing the unit tests to not have hardcoded connection information
mashed into them. Ideally the unit tests wouldn't need to connect to
a real database server at all (and would start their own DBus daemon,
and would have a way to only run a subset of them, and would be better
at reporting where errors happen by default...), but that'd take a
fair bit of work to fix.
* Possibly making wvdbusd export usernames instead of (or in addition
to) uids, and making versaplex ask for names instead of uids.
* Possibly fixing the error messages.

Anyway, I'll tidy up those last bits tomorrow or Tuesday, but does the
rest of it sound sensible?

Peter.

Avery Pennarun

unread,
Jan 21, 2008, 11:44:11 AM1/21/08
to versap...@googlegroups.com
On 21/01/2008, Peter McCurdy <peterm...@alumni.uwaterloo.ca> wrote:
> On Jan 16, 2008 2:29 PM, Avery Pennarun <apen...@gmail.com> wrote:
> > It's very... cute. But I don't really follow how hard-coding assembly
> > language is justifiable just to save a couple lines of code,
> > particularly when it turns out that it *doesn't* actually save a
> > couple of lines code because varargs in C# is typesafe anyhow and so
> > there's no reason you can't just have a generic "call remote function"
> > function.
>
> But... but... then it wouldn't look like a method call! :)

Darn it. I once had a link to a great old paper out of Sun that
explained the whole problem with RPC turned out to be in making things
look too much like method calls, but I think I lost it.

> Anyway, I think I'm done now. It turns out I was caching the wrong
> thing (the computed connection string given a uid, rather than the uid
> given a unique bus name), but that was trivial to fix.

I might have cached the uid rather than the connection string, simply
because you can map from a uid to a connection string without a
network turnaround anyway, and the uid might be useful for other
stuff. But that's easy enough to change later.

> The mssql: entries under [Connections] are defined to just be the
> standard MS SQL connection string, for laziness. I.e. one can just
> assign them to a SqlConnectionStringBuilder. This also means that (a)
> they're already well specified and (b) they support just about all
> possible connection options, two things that wouldn't be true if I
> dreamed up something myself.

That sounds fine to me.

> As for the format not giving a user
> access to multiple databases, you could always declare the values in
> the [User Map] section to be a space-separated list of connections;
> you'd still need a way to request a particular database, but that's
> orthogonal. Or there are plenty of other options, I suppose.

Yup. We can solve that another day too.

> For now, Versaplex still just retrieves Unix uids from wvdbusd, and
> does its own username lookup. Do you still think it's worth exporting
> usernames from wvdbusd, or was that tied to you thinking that wvdbusd
> would be using Unix domain sockets?

I think the usernames are much more useful. Remember, versaplexd is
quite probably running on Windows (and possibly on a totally different
machine than wvdbusd, although that's less likely), where there are no
uids at all. (Well, they have something similar involving GUIDs, but
they're almost equally non-portable between machines.)

> The other unresolved issue in my head is that if a username or
> connection string is missing from the config file, the error message
> sent back to the client is a slightly cryptic null reference message
> when code tries to use a nonexistent connection after TakeConnection
> returns null. I don't know what the overall philosophy on returning
> errors from Versaplex is (throw an exception as soon as we find a
> problem?

Ignoring any screwball behaviour of dbus-sharp that converts
versaplexd internal exceptions automatically into DBus messages -
which we will want to definitely turn off for security / information
leak reasons eventually - we basically want things that go wrong to
send sensible error messages back as dbus messages.

Think of our dbus protocol as any network protocol. The encapsulation
here happens to be dbus, but that doesn't change the rules of network
etiquette. Your SMTP server isn't supposed to say "Exception: NULL
pointer dereference" and give a stack trace when you forget a
parameter; it's supposed to tell you what parameter you forgot.

We want to do the same thing here. Always check the input from the
network before we use it. That's our security boundary, after all.
We don't want invalid data leaking deeper into the system.

> Return an error reply to DBus when we eventually notice that
> we couldn't find a connection?). I was leaning towards throwing an
> exception as soon as we find a problem, as it seems like the easiest
> way to get a proper error message out to DBus, but then I got cold
> feet about adding some not-horrendously-exceptional exceptions. This
> should also be easy to fix one way or the other.

As long as we don't think of them as exceptions, it should be okay.
There's no such thing as an exceptions in vxodbc (which is mostly C)
anyway, and DBus does them by returning an "error" packet, which we
can treat however we want.

So in this case, they're just errors, not exceptions. Certainly we
should report an error any time something goes wrong.

> Stuff that remains:
> * Checking in a sample versaplexd.ini config file (or is this too much
> of a pain, due to having to change a file checked into Subversion?).

What I normally do is:

1) Check in a template file like versaplexd.ini.tmpl
2) svn:ignore the actual config file, versaplexd.ini
3) Have versaplexd die on startup if there's no versaplexd.ini

That prevents accidentally checking in config files, and also prevents
the confusion caused when users forget to create them.

> * Fixing the unit tests to not have hardcoded connection information
> mashed into them. Ideally the unit tests wouldn't need to connect to
> a real database server at all (and would start their own DBus daemon,
> and would have a way to only run a subset of them, and would be better
> at reporting where errors happen by default...), but that'd take a
> fair bit of work to fix.

I'm not sure how we could possibly test our database connectivity
without an actual database. Someday when we support sqlite or
something, I guess we could test everything except the actual MS SQL
functionality without an active database engine, but one will still be
needed for a *full* test, so that's not worth working on right away.

Not sure why making the unit tests not be hardcoded is difficult at
all; just read the settings out of a config file, applying the three
rules I listed above.

Presumably it should auto-start wvdbusd and versaplexd, so the only
config option will really be a single database connection string or
so. That should be easy enough to do.

Have fun,

Avery

Andrei Thorp

unread,
Jan 21, 2008, 1:46:25 PM1/21/08
to versap...@googlegroups.com
Woo, thanks

With these latest changes, my system finally works! You're awesome,
Peter.

-AT

Andrei Thorp

unread,
Jan 21, 2008, 2:24:51 PM1/21/08
to versap...@googlegroups.com
I'm thinking that if we end up with a few config, we might consider
writing an "Installation" script of some sort to place the configs in
the various places they go, perhaps with some user interaction. This
would somewhat solve the SVN issue, as well as lay down some
infrastructure for, well, installation. Another reason I say "write a
script" is because the information would probably be duplicated amongst
several files and it would be easier for the person setting it up to
only have to type the info in once.

-AT

(Please ignore the other thread I started on this topic)

Peter McCurdy

unread,
Jan 21, 2008, 4:40:00 PM1/21/08
to versap...@googlegroups.com
On Jan 21, 2008 11:44 AM, Avery Pennarun <apen...@gmail.com> wrote:
> On 21/01/2008, Peter McCurdy <peterm...@alumni.uwaterloo.ca> wrote:
> > But... but... then it wouldn't look like a method call! :)
>
> Darn it. I once had a link to a great old paper out of Sun that
> explained the whole problem with RPC turned out to be in making things
> look too much like method calls, but I think I lost it.

Dang, that sounds interesting.

> > Anyway, I think I'm done now. It turns out I was caching the wrong
> > thing (the computed connection string given a uid, rather than the uid
> > given a unique bus name), but that was trivial to fix.
>
> I might have cached the uid rather than the connection string, simply
> because you can map from a uid to a connection string without a
> network turnaround anyway, and the uid might be useful for other
> stuff. But that's easy enough to change later.

Sorry, I didn't complete my thought (it was late) - I did fix it. The
connection string cache was particularly useless, as saved a grand
total of two hash table lookups, at the cost of another hash table
lookup (and another hash table, and making the code somewhat uglier).

> > For now, Versaplex still just retrieves Unix uids from wvdbusd, and
> > does its own username lookup. Do you still think it's worth exporting
> > usernames from wvdbusd, or was that tied to you thinking that wvdbusd
> > would be using Unix domain sockets?
>
> I think the usernames are much more useful. Remember, versaplexd is
> quite probably running on Windows (and possibly on a totally different
> machine than wvdbusd, although that's less likely), where there are no
> uids at all. (Well, they have something similar involving GUIDs, but
> they're almost equally non-portable between machines.)

OK, I'll fix that up. Should be pretty simple.

> As long as we don't think of them as exceptions, it should be okay.
> There's no such thing as an exceptions in vxodbc (which is mostly C)
> anyway, and DBus does them by returning an "error" packet, which we
> can treat however we want.
>
> So in this case, they're just errors, not exceptions. Certainly we
> should report an error any time something goes wrong.

Right, that makes sense. But internally, what's the best way to get
error information from the innards where stuff goes wrong up to the
level that knows how to send errors to DBus, given that there's no
real error infrastructure in place?

The easiest way might be to create a VersaplexRequestErrorException or
something else distinctive, and throw that whenever we run into an
error we want to report back to DBus. Then at the appropriate spot,
we can catch just that exception, extract the error message, and send
it off (either with or without the rest of the stack trace). Then we
could disable the rest of dbus-sharp's auto-exception-forwarding, and
know that we only send DBus errors when we expect to. I don't know
how you're feeling towards that much exception use overall though.
It'd be possible to do it all with error returns, of course, but we'd
be hampered by a lack of WvError, and generally by Versaplex's
somewhat puzzling all-static-method architecture.

> > Stuff that remains:
> > * Checking in a sample versaplexd.ini config file (or is this too much
> > of a pain, due to having to change a file checked into Subversion?).
>
> What I normally do is:
>
> 1) Check in a template file like versaplexd.ini.tmpl
> 2) svn:ignore the actual config file, versaplexd.ini
> 3) Have versaplexd die on startup if there's no versaplexd.ini
>
> That prevents accidentally checking in config files, and also prevents
> the confusion caused when users forget to create them.

Right. I should know that by now, I was just too tired to think of it
last night.

> I'm not sure how we could possibly test our database connectivity
> without an actual database. Someday when we support sqlite or
> something, I guess we could test everything except the actual MS SQL
> functionality without an active database engine, but one will still be
> needed for a *full* test, so that's not worth working on right away.

Well, given that the unit tests make very static queries, in theory
it'd be possible to record the MS SQL connection and replay it when
running the tests, much like the fake Versaplex server I wrote for the
vxodbc unit tests, though probably even more mindless. You'd still
need MS SQL around for writing new tests or changing existing queries,
and you'd have to be careful when switching to new versions of MS SQL
or new databases. In practice, that may be a bit too much of a pain,
but it would be just as useful as a real server for testing
versaplexd.

> Not sure why making the unit tests not be hardcoded is difficult at
> all; just read the settings out of a config file, applying the three
> rules I listed above.

It's not difficult at all, it's just that it was late and I was tired
and I wanted to check in. I realized at the last minute I'd forgotten
the unit tests, and basically said "to hell with it" and made a note
in the email so I wouldn't forget :)

> Presumably it should auto-start wvdbusd and versaplexd, so the only
> config option will really be a single database connection string or
> so. That should be easy enough to do.

How portable is starting new processes in C#? Do we care if the unit
tests only work in Linux? Is it worth dealing with this at all right
now? If it wasn't clear, I was just expounding on my ideal unit test
system a bit.

I just realized the one potential drawback to auto-starting all the
servers is all the log messages will get mashed together. That may be
just as much of a benefit as a drawback though, if you're tracing one
particular connection instead of looking at a server as a whole.

Peter.

Avery Pennarun

unread,
Jan 21, 2008, 4:55:15 PM1/21/08
to versap...@googlegroups.com
On 21/01/2008, Peter McCurdy <peterm...@alumni.uwaterloo.ca> wrote:
> On Jan 21, 2008 11:44 AM, Avery Pennarun <apen...@gmail.com> wrote:
> > On 21/01/2008, Peter McCurdy <peterm...@alumni.uwaterloo.ca> wrote:
> > > But... but... then it wouldn't look like a method call! :)
> >
> > Darn it. I once had a link to a great old paper out of Sun that
> > explained the whole problem with RPC turned out to be in making things
> > look too much like method calls, but I think I lost it.
>
> Dang, that sounds interesting.

I think it's probably linked inside the proprietary NITI wiki somewhere...

> Right, that makes sense. But internally, what's the best way to get
> error information from the innards where stuff goes wrong up to the
> level that knows how to send errors to DBus, given that there's no
> real error infrastructure in place?
>
> The easiest way might be to create a VersaplexRequestErrorException or
> something else distinctive, and throw that whenever we run into an
> error we want to report back to DBus. Then at the appropriate spot,
> we can catch just that exception, extract the error message, and send
> it off (either with or without the rest of the stack trace). Then we
> could disable the rest of dbus-sharp's auto-exception-forwarding, and
> know that we only send DBus errors when we expect to. I don't know
> how you're feeling towards that much exception use overall though.
> It'd be possible to do it all with error returns, of course, but we'd
> be hampered by a lack of WvError, and generally by Versaplex's
> somewhat puzzling all-static-method architecture.

In general, I'd someday like to use a WvError-like thingy in
versaplexd. But for now, I think your idea of a particular exception
class will do the job. Basically:

1) If it's a VxRequestException, take the message (not stack trace)
and send it back as an error in response to the given request. Also
log it at a debug level.

2) If it's any other kind of exception, send back a meaningless "fatal
error" type message to the sender - because all method call messages
should always get an answer, but we don't want to reveal our bugs to
the client - and then log all the actual details from versaplexd.

Rule of thumb: bugs in versaplexd stay in versaplexd. Bugs in the
client should be caught by versaplexd and return sensible errors in
VxRequestException.

In other words, report errors back to the guy who can do something
about it. The current behaviour of reporting null pointer exceptions
in versaplexd back to vxodbc, and then *not printing the errors to the
log* (!!) is completely backwards.

Initially, we might have more of type 2 than type 1, but that's okay;
we can add more error checking as we discover new kinds of client
screw-ups.

> > I'm not sure how we could possibly test our database connectivity
> > without an actual database. Someday when we support sqlite or
> > something, I guess we could test everything except the actual MS SQL
> > functionality without an active database engine, but one will still be
> > needed for a *full* test, so that's not worth working on right away.
>
> Well, given that the unit tests make very static queries, in theory
> it'd be possible to record the MS SQL connection and replay it when
> running the tests, much like the fake Versaplex server I wrote for the
> vxodbc unit tests, though probably even more mindless. You'd still
> need MS SQL around for writing new tests or changing existing queries,
> and you'd have to be careful when switching to new versions of MS SQL
> or new databases. In practice, that may be a bit too much of a pain,
> but it would be just as useful as a real server for testing
> versaplexd.

A large part of versaplexd's bugs will almost certainly involve the
thread pool, MS SQL data transfer encodings, maximum packet sizes,
race conditions, authentication, overlapping transactions, access
control, and so on. We can't possibly test those things end-to-end
without a real live MS SQL database.

Of course, there are plenty of classes ("units") in versaplexd that
could be tested without an actual MS SQL session. Eventually we
should probably test those individually. But that's less important
than end-to-end tests at first.

Have fun,

Avery

Reply all
Reply to author
Forward
0 new messages