follow me on Twitter

    Blog has moved to, see June, 2007 on new site

    Blog entries for June, 2007

    This post moved to

    If you haven't seen Marc Andreessen's new blog, it is very worthwhile.

    Among others I like this post, which touched one of my pet issues better than I could have said it - "space" disease:

    But here's the problem.

    Web 2.0 has been picked up as a term by the entrepreneurial community and its corollaries in venture capital, the press, analysts, large media and Internet companies, and Wall Street to describe a theoretical new category of startup companies.

    Or a "space", if you will.

    As in, " is in the Web 2.0 space".

    At its simplest level, this is just shorthand to indicate a new Web company.

    The technology industry has a long history of creating and naming such "spaces" to use as shorthand.

    Before the "Web 2.0 space", you had the "dot com space", the "intranet space", the "B2B space", the "B2C space", the "security space", the "mobile space" (still going strong!)... and before that, the "pen computing" space, the "CD-ROM multimedia space", the "artificial intelligence" space, the "mini-supercomputer space", and going way back, the "personal computer space". And many others.

    But there is no such thing as a "space".

    There is such a thing as a market -- that's a group of people who will directly or indirectly pay money for something.

    There is such a thing as a product -- that's an offering of a new kind of good or service that is brought to a market.

    There is such a thing as a company -- that's an organized business entity that brings a product to a market.

    But there is no such thing as a "space".

    As tech industry participants, anytime we describe our ideas as either a "space" or some generic product category ("groupware", "desktop", etc.) we should be kicked in the ass. If you can't describe the market (specific target audience) and the product (specific new value to audience that said audience doesn't already have) and the company (people who will create the new value and bring it to the audience) then you are talking nonsense.

    It seems to me that there are a good number of people in the industry who take something more seriously if you label it with an existing, proven category or "space" - and less seriously if you get specific. You explain the specifics and they say "that's it?" and perhaps later they say "oh, you mean this is a play in the _____ space" - as if that makes things clearer and in some way more credible!

    The thing is, once a category or space has a name, and a bunch of existing companies, it's almost certainly a stupid idea to pile on (unless you can explain your specific new value offered that isn't the same as those existing companies - in which case the name of a category or space is wholly inadequate to explain what you want to do).

    There's no real difference on this if you're an open source project instead of a company. Project motives may be fame or popularity or freedom rather than profits, but from the perspective of the market, success will still hinge on specific value to specific audience.

    Another way to think about it is that while a "space" is a descriptive abstraction, it isn't one that's helpful for guiding action. Specifically, it doesn't set any priorities, because it doesn't say "here's the thing we're doing that's different."

    I love the project name One Laptop Per Child because it says right there in the name what the project does for what audience. In certain people's hands, this would have been about the "sub-$200 laptop space" or the "international/developing-nations client OS space" or something awful like that. Bullet well-dodged, kudos to whoever got this right.

    Other sample posts I liked so far on Marc's blog:

    I'm leaving out a bunch of stuff too, such as a list of killer OS X apps in 2007, top 10 sci-fi novelists of the 2000's, and a series on venture capital. And the guy started blogging on June 2. Either he's doing nothing but blogging; he built up posts for the last year before starting; or he has minions to help. Alternatively, he's some type of freak of nature.

    This post moved to

    Apress sent me a free copy of Foundations of GTK+ Development by Andrew Krause. On, Andrew has some sample chapters, supplementary articles, and an eBook version.

    As far as I know, this is the only up-to-date GTK+ book. It's introductory-level and strikes a nice balance of tutorial and reference. It goes through the major GTK+ features in a comprehensive way and has simple examples for each one. If you're new to GTK+ or just want to be able to look up a new widget you haven't used and get an overview, this looks like the book to get.

    While I don't know him personally, based on his book I'd say Andrew is a smart guy who writes well, and it's obvious he put in a lot of effort researching GTK+ and developing nice example code.

    Either a pro or a con depending on what you're looking for, the book doesn't include too much "deep secrets" or background commentary kind of material; in other words, there isn't a lot of "here is how this subsystem works internally" or "this API sucks, don't use it" kind of information. On the macro scale, some recommendations might include "never use gdk_draw_*, always use Cairo" or "use PyGTK+ rather than C whenever possible," for example. A more trivial example, it's useful to know that "gint" is historical cruft and just "int" is fine to use.

    The book would risk being too long and too cluttered with that kind of thing mixed in, though - one can only learn so many details at once, and the book has quite a bit of detail already. It does mention major "gotchas" that are likely to matter in real life, for example warning about using gtk_scrolled_window_add_with_viewport() with widgets such as TextView that support scrolling natively. Choosing the level of detail and background info is a tough balance to strike and Andrew did a nice job.

    One chapter I feel could use more elaboration covers writing a custom widget. I'd like to see more information on GdkWindow double-buffering and invalidation, info on no-window widgets and why they are preferred when possible, and more discussion of the default implementations of the widget methods and when to override them or not.

    Two nice supplements to this book might be a "deep GTK+ secrets"/"design and implementation of GTK+" type of book, and a "rapid development with PyGTK+ and Glade" type of book.

    That said, if you want to get started with GTK+, you'll do well with Foundations of GTK+ Development. Thanks to Andrew and Apress for offering us an up-to-date GTK+ guide.

    This post moved to

    I got a fair bit of useful feedback on my last post about local service discovery. I also have some initial code up and running to illustrate the approach. (This code requires D-Bus 1.1.1 or higher.)

    For now the code uses a straightforward but probably too inefficient implementation, where each session connects to each other session. Modifying it to use TXT records for everything or certain things is possible. Hopefully the higher level of abstraction means that the most efficient way to use Avahi can be globally worked out, instead of per-app.

    The main idea here is to make it dead easy to use local service discovery for per-session user services (as opposed to say a printer), without having to understand all the networking specs.

    This post moved to

    At Red Hat's somewhat-in-the-vicinity-of-Boston offices, a few of us have been trying to understand the local service discovery and presence work others have been doing and figure out how we'd use it to do cool things in apps.

    Today I'll blog ideas and questions about local service discovery and later I have some additional questions to throw out there for the presence experts.

    I still don't understand everything all that well, and all the docs I've found assume you know a lot more about DNS than I do, but here's my summary of how local service discovery works. Avahi implements the mDNS/DNS-SD/Rendezvous/Bonjour/Zeroconf/whatever set of specs, which in combination form a system for service discovery on a local network. There are three steps to discovering information on the network:

    • First, you can browse services. In this stage your program gets a list of hostnames, one per service offered and that's it. For example in link-local XMPP, you ask for all hostnames that end in "._presence._tcp.local." and by convention those names will be username@machinename, so the full host is "johndoe@example._presence._tcp.local." or something like that. The only information you get from this step is the "johndoe@example" for link-local XMPP, or for browsing WebDAV shares you might get "Havoc's Files" for example. there is no way to get or provide information beyond the one string.
    • Second, you can resolve the services. This means making a request for each service, and getting back the service's IP address and port so you can connect to it. You can also get some key-value pairs called TXT records, but there can't be too many of these and they can't be too big. In link-local XMPP, the TXT records optionally contain the jabber ID, email address, user name, and a hash of the user's photo, among other things. As I read the specs, TXT records should always be optional optimizations and not required - that is, you should be able to get the same information by connecting to the service and asking. I'm not sure of the rationale here.
    • Third, you can connect to the service and talk to it using its application-specific protocol, whatever that protocol is - WebDAV, XMPP, or whatever. You could do this just to find out stuff missing from the TXT records, or you could do it in order to take a service-specific action such as store a file, send an XMPP message, or print a document.

    As best I can tell, the more of these steps you do, the more expensive it is. I don't understand how expensive since I know zip about networking below the session layer. But it seems intuitive that if you had say a network of 500 machines and all 500 made an XMPP connection to the other 499 to get user photos, there could be some issues.

    You can find the Avahi API for the first two steps here, or on the publish/server side, you use this API. The docs also have a simple publish example and a simple browse example. Note that the publish example doesn't do anything, it advertises services but does not create them (does not listen on any ports or implement a protocol).

    Right now you have to write a network server (potentially inventing a new protocol) to use Avahi. See the third step I mentioned above. There are a few problems here; one, it's too hard. Two, it's a pretty rough security footprint to audit if every app that uses local discovery is listening on a port. Three, like me I'm sure app authors don't understand the performance and other issues involved in using Avahi directly - it requires a lot of knowledge. (The Avahi API is quite nice, but it is on the level of manually doing the above-mentioned three steps, which are low-level steps.)

    Right now services are not tied to sessions or people. Say I browse the network and it has "Havoc's Files" and "Bryan's Files" on there. It also has link-local XMPP for both Havoc and Bryan. However, there is no way for me to associate the files with the XMPP (as far as I know). So if I wanted to show a "See Bryan's Files" button next to his photo in chat, that would be challenging.

    If I parsed what Dan Williams had to say, Sugar somewhat addresses both of these issues. First, Sugar defines a "person" as a keypair generated on each laptop. Since there's one laptop per child, keypair equals laptop equals person. Next, Sugar uses a hash of the keypair for its XMPP identifiers. So it can map from server-based or local XMPP to people. Finally, Sugar uses XMPP not only for chat but for all IPC over the network. To avoid using XMPP directly, it tunnels arbitrary IPC through XMPP by serializing D-Bus messages and stuffing them into XMPP messages (known as Tubes).

    With the Sugar platform then, instead of using Avahi directly at all, what you could do is add additional properties available via link-local XMPP. A small number of simple properties could go in the link-local XMPP TXT records perhaps, while larger or more complex properties would require each client to establish an XMPP connection and ask for the property.

    What should we do for GNOME and its new improved flavor, Online Desktop?

    The API I'm thinking would be most convenient for apps is something like the following. First, the Mugshot client for example could do:

                          { 'mugshotId' : 'whatever',
                            'name' : 'Havoc',
                            'photoUrl' : 'http://whatever' }) 
    or say a video game:
                          { 'serverName' : 'whatever',
                            'username' : 'Havoc' })
    Then, any other app in this session or anywhere on the network could ask for "info bundles" by name as follows:
      mugshot_infos = GetInfoFromOtherSessions("org.mugshot.MugshotInfo");
    Where each info in the list would be a pair of two dictionaries, one representing the session and the other representing the requested info from that session:
      ( { 'session' : 'guid-for-session',
          'machine' : 'guid-for-machine',
          ... },
        { 'mugshotId' : 'whatever',
          'name' : 'Havoc',
          'photoUrl' : 'http://whatever' } )
    (D-Bus already provides a guid for the session and machine, if you're wondering where those come from.)

    On the network we have a set of sessions; each session contains named "infos" or bundles of related properties; clients can ask for a list of all "infos" on the network of a particular kind.

    This hypothetical API would allow apps to advertise information without writing a network server or listening on a port. It would also automatically link all advertised information to a session ID, and if some of the info advertised identifies the user, the session can in turn be linked to a user.

    This kind of API does not offer a way to establish a connection or communicate, though; just a way to advertise.

    Something like Fast User Switching could even use this - instead of using gdm to keep track of users to switch to, it could list sessions on the local machine, and one of the properties of each session would be the local username and a name/photo.

    If we add features such as link-local chat, or link-local file sharing, I would want them to work with other sessions on the same machine, in the same way they work with sessions on other machines.

    A simple API like this reduces the surface area for security exploits in the sense that there would be only one codebase that was network-facing. Of course, the issue of which things are safe to publish on the local network remains, but that is unavoidably going to be up to the judgment of app developers.

    To implement an API like this I can imagine multiple approaches, and I don't know which is best. The three I have come up with are:

    1. No network-facing daemon, just a little daemon on the session bus that allows apps to register the info bundles, and then advertises each one with a separate hostname and puts the "info bundle" properties in TXT records. This is a thin convenience layer over Avahi.
    2. The same little daemon on the session bus, but it also listens on the network and allows clients to connect and get "info bundle" properties that are too large to fit in the TXT records.
    3. Link-local XMPP. Add a session ID to the link-local XMPP TXT records. Add special XMPP messages, or Tubes messages, to get the "info bundles" that each app has made available. This approach involves by far the most code, though much of that code is already written.

    So the no-network-facing daemon approach would be a thing like:

      Havoc's Mugshot
          TXT session=guid-for-session
          TXT machine=guid-for-machine
          TXT mugshotId=whatever
          TXT photoUrl=http://whatever
      Havoc's UNIX
          TXT session=guid-for-session
          TXT machine=guid-for-machine
          TXT uid=503
          TXT gecos=Havoc
      Havoc's Card Game
          TXT session=guid-for-session
          TXT machine=guid-for-machine
          TXT game_server=http://whatever
          TXT server_username=foobar
    In this approach, only small properties can be advertised. There are lots of hostnames to browse and resolve, but no services to connect to. The TXT records are essential (the whole approach) and not an optimization.

    Remember this approach is still implemented with a daemon, but it's a small service on the session bus, not a network-facing daemon.

    If you make the daemon network-facing also, it can support connections to get all the information, so only needs to advertise one time on Avahi.

      Havoc's Stuff._gnome_session.local
          TXT session=guid-for-session  (optional, could also ask service)
          TXT machine=guid-for-machine  (optional, could also ask service)
    And then listening at "Havoc's Stuff._gnome_session.local" is a custom server that supports asking for the machine/session ID and all the "info bundles" available from the session.

    I started experimenting with this second approach by writing the small service on the session bus, and then having it also create a custom DBusServer (not a bus) listening on the network. Since D-Bus took most of the work out of writing my own network server and the Avahi API is simple, I got it going instantly (other than a long detour to make libdbus support anonymous clients).

    The third approach is essentially equivalent to the second, except it uses link-local XMPP instead of D-Bus for the network-facing protocol. With Tubes, the end result is pretty similar (the API is D-Bus, but the D-Bus is pushed through XMPP behind the scenes). There is a LOT more code involved - the Telepathy + Salut + Tubes stack is in the tens of thousands range, vs. a couple thousand for approach 2. But if that code is going to be used anyway for other purposes, it may not matter.

    Again here's the simple API for apps I was thinking of:

                          { 'mugshotId' : 'whatever',
                            'name' : 'Havoc',
                            'photoUrl' : 'http://whatever' }) 
    If we have that, then we could experiment with these three approaches or the no doubt better ideas other people have without too much trouble.

    I don't know what the performance issues with these various approaches are. For example, is it worse to have tons of advertised services as in approach one, or to have to connect to each service every time, as in the second two approaches? Or are all three of these approaches doomed in some way? On some level, it seems like 500 sessions each loading stuff from each of the others just can't work. What are the tricks to make it work?

    And what about change notification? Is it possible? How is it done without causing 499 other computers to all ask my computer for new information at once as soon as I change my user photo on a large network?

    Since my blog lacks comments, feel free to send thoughts to the online desktop group, you don't have to subscribe to receive mail in order to post, and you can post from the web UI.

    This post moved to

    I've been known to complain about the number of newfangled source control systems in the past; today it's really biting me. To build the Telekinesis stack requires 1) cvs 2) svn 3) git 4) darcs and 5) mercurial. I'm thinking of writing something that uses the stack and checking it into bzr, just for completeness. Maybe add some arch and monotone for extra kicks.

    There is just no way that the differences between git, bzr, darcs, arch, monotone, and mercurial are interesting enough to outweigh the disadvantage of having to deal with all of them in order to get stuff done.

    Back in the day, if you knew CVS, you could hack on any project. Sure CVS was a bit lame, but you understood its quirks and it worked fine most of the time. Also, we walked to school both ways uphill.

    Mildly related, the other day I discovered that darcs has an innovative new twist on the "Question? [yn]" tradition - it asks:

    Shall I pull this patch? (1/129)  [ynWvpxqadjk]
    This might be awesome in dialog form, too. Someone should write a GUI.