VNC Connects Then Hangs

Posted by Benjamin Close on August 6, 2009 under Computers, OpenSource, UniSA | Be the First to Comment

The other day I was working with a few colleges using VNC. We came across an issue with our VNC setup. We could connect a VNC client (be it tightvnc, vncviewer, vinagre or x4vnclient) to our vnc server but never see anything on the screen. It was if the server was freezing or hanging.  This left us wondering why. Initially we thought we had broken something in the VNC server – after all we had made code modifications. However the solution turned out to be a very simple fix.

You see the VNC protocol has the ability to place a client ONHOLD. During this state the clients events are not transmitted and the server sends back no images. This is what was happening to us. Normally the VNCServer will place the client on hold during a connection, asking the user to accept/reject the client. However we had been playing around with configuration files and set the prompt to disabled – we wanted automatic connection, with no prompt. Hence the VNCServer was placing the client on hold, noticed prompts were disabled and because authentication had not been established, sat there twiddling it’s thumbs.

A simple configuration file fix and everything was working again. Ironically at the same time we also discovered that modifying files by had in ~/.gconf/* doesn’t do anything as there’s a daemon that holds the configuration and it periodically writes to ~/.gconf/* overwriting any changes you might have made – hence we used gconftool2.

Xinput 1 -> XInput 2 conversion guide

Posted by Benjamin Close on July 30, 2009 under Computers, FreeDesktop, OpenSource, Programming | 2 Comments to Read

Recently I was tasked with porting GTK+ to support Xinput 2 (XI2), and whilst the port isn’t finished I quickly discovered just how big the conversion was. This page is designed to help someone who is familiar with XInput 1 switch to XInput 2 – it’s certainly is by no means a complete guide and anyone reading this should also take a look at the various Input2 recipies published.

XI2 is the first major rewrite of the XInput specification in years and with it comes a lot of enhanced functionality, but also a new API. The API was deliberately designed not to be backward compatible. Why? To prevent both XI1 and XI2 features to be intermingled. XI2 brings with it a new device model and a new input model. Both of these are incompatible with XI1. The decision to break the API was not a light one by Peter Hutterer, the main XI2 developer. Supporting XI1 would have ment future changes to XI2 would be impossible – there’s only so far you can push an out dated protocol and api. The added complexity of trying to maintain 2 code paths was also determined to be too high. XI2 is more than just a api/abi change. It literally change the entire input subsystem of the Xorg Xserver. XI2 supports:

With that in mind, the new XI2 API often leaves someone who’s been working with the XI1 wondering what the equivilant XI2 API call is. Most functions have an equivilant in XI2 function though the usage has more often than not, changed dramatically. Below is some examples of how to convert XI1 code to XI2 compatible code and a list of some of the changes which have occurred. If you find something missing, please add to the comments.

Change Overview

The biggest change that any XI1 developer will notice is the XDevice * type has vanished. All XI2 devices make use of the XID type instead. Under the hoods, in the Xserver and XDevice really equates back to an XID anyway now. The next biggest change XI1 developers will notice is the entire XInput2 API has had shifted namespaces. All XInput2 functions, types, etc are now prefixed with XI (ie XIEventMask). This was designed to force segregation of XI1 -> XI2 code.

The header file you include has also changed. Instead of:

#include <X11/extensions/XInput.h>

It’s now:

#include <X11/extensions/XInput2.h>

Notable Changes

  • Proximity events are no longer supported, these are now reported as regular events on another axis (ie think of a pressure axis)
  • Events are longer use device classes, instead all events are type XIEvent (a type of XEvent). Hence there is no need to pass around an array of integer classes anymore when registering for events, instead a single XIEventMask will do what is needed. The macros XISetMask and XIGetMask help with using the mask.

There’s also been a lot of changes to structures, functions, types and how they are used.

Event Changes

XI1 Event XI2 Event Notes
XDeviceKeyEvent,  XDeviceKeyPressedEvent, XDeviceKeyReleasedEvent, XDeviceButtonEvent,  XDeviceButtonPressedEvent,  XDeviceButtonReleasedEvent ,XDeviceMotionEvent XIDeviceEvent The various events are now incorporated into the one event type. XIDeviceEvent->evtype indicates the subtype of event. Ie XIMotion is a motion event for that device.
XProximityNotifyEvent, XProximityInEvent, XProximityOutEvent XIDeviceEvent (See Note) Proximity Events have been replaced with device events. Proximity is represented as a value in the valuator on one of the axes

Structure/Type Changes

XI1 Structure/Type XI2 Structure/Type Notes
XDeviceState XIDeviceInfo XIDeviceInfo also contains a name and classes
XAnyClassPtr XIAnyClassInfo *
XValuatorInfo XIValuatorClassInfo
XInputClass XIAnyClassInfo
XEventClass XIEventMask Used for selecting events to be monitored.
One mask is used per device. Standard usage is:

XIEventMask mask;
mask.deviceid=//some device or XIAllDevices for all devices&lt;
mask.mask_len=2;
mask.mask=calloc(mask.mask_len, sizeof(char));
XISetMask(mask.mask, XI_ButtonPress);
..
XISelectEvents(display, win, &mask, 1)
XExtensionVersion Struct Removed XIQueryVersion should be used instead
XDeviceKeyEvent, XDeviceKeyPressedEvent, XDeviceKeyReleasedEvent, XDeviceButtonEvent, XDeviceButtonPressedEvent, XDeviceButtonReleasedEvent, Structs Removed XIDeviceEvents are now used instead
XDeviceFocusChangeEvnet, XDeviceFocusInEvent, XDeviceFocusOutEvent Structs Removed XIDeviceEvents are now used
XProximityNotifyEvent, XProximityInEvent, XProximityOutEvent Structs Removed XIDeviceEvents are now used

Function/Macro Changes

XI1 Function XI2 Function Notes
XFreeDeviceList XIFreeDeviceInfo
XDefineDeviceCursor XIDefineCursor
DeviceButton1Motion

DeviceButton2Motion

(No Equivelant)
XWarpPointer

XWarpDevicePointer

XIWarpPointer XIWarpPointer makes use of the device id like XWarpDevicePointer (XI1.5). XWarpPointer is considered obsolete as it has no concept of a device
XQueryDeviceState XIQueryDevice Return type is XIDeviceInfo *, can be called with deviceid = XIAllDevices to query all devices hence the ndevices return
XFreeDeviceState XIFreeDeviceInfo
DeviceGrabButton XIGrabButton
XSelectExtensionEvent XISelectEvents Instead of a list of classes now a list of XIEventMask is used, one mask per device. XSelectExtensionEvent is still used for other extension events not related to XInput2
XGetExtensionVersion XIQueryVersion If only XI1 is present this will be returned vi the major/minor numbers (ie major = 1)

Examples

Below are some examples of how to use some of the new XI2 functions.

Event Processing – Registering For Events

A simple indication how to register for events (XI2 greatly simplifies this)

static int           motion_type = INVALID_EVENT_TYPE;
static int           button_press_type = INVALID_EVENT_TYPE;
static int           button_release_type = INVALID_EVENT_TYPE;
static int           key_press_type = INVALID_EVENT_TYPE;
static int           key_release_type = INVALID_EVENT_TYPE;
static int           proximity_in_type = INVALID_EVENT_TYPE;
static int           proximity_out_type = INVALID_EVENT_TYPE;
 
static int register_event(Display *dpy, XDeviceInfo *info)
{
    XEventClass         event_list[7];
    int                 i;
    XDevice             *device;
    XInputClassInfo     *ip;
 
    device = XOpenDevice(dpy, info->id);
 
    // Check for open error
    if (device->num_classes > 0) {
        for (ip = device->classes, i=0; i<info->num_classes; ip++, i++) {
            switch (ip->input_class) {
            case ButtonClass:
                DeviceButtonPress(device, button_press_type, event_list[number]); number++;
                DeviceButtonRelease(device, button_release_type, event_list[number]); number++;
                break;
 
            case ValuatorClass:
                DeviceMotionNotify(device, motion_type, event_list[number]); number++;
                if (handle_proximity) {
                    ProximityIn(device, proximity_in_type, event_list[number]); number++;
                    ProximityOut(device, proximity_out_type, event_list[number]); number++;
                }
                break;
 
            default:
                fprintf(stderr, "unknown class\n");
                break;
            }
      }
 
   if (XSelectExtensionEvent(dpy, root_win, event_list, number)) {
            fprintf(stderr, "error selecting extended events\n");
            return 0;
        }
   }
  • XInput 2:
    (Taken from: http://who-t.blogspot.com/2009/05/xi2-recipes-part-1.html)
  • XIEventMask eventmask;
    unsigned char mask[1] = { 0 }; /* the actual mask */
     
    eventmask.deviceid = 2;
    eventmask.mask_len = sizeof(mask); /* always in bytes */
    eventmask.mask = mask;
    /* now set the mask */
    XISetMask(mask, XI_ButtonPress);
    XISetMask(mask, XI_Motion);
    XISetMask(mask, XI_KeyPress);
     
    /* select on the window */
    XISelectEvents(display, window, &eventmask, 1);

Event Processing – Listening/Processing Events

A simple indication how to get events from XI1 and XI2

  • XInput 1:
    //setup via other means
    int motion_type, button_press_type,button_release_type;
     
    void doEvents(Display    *dpy)
    {
     
     XEvent        Event;
     
        while(1) {
            XNextEvent(dpy, &Event);
            if (Event.type == motion_type) {
                XDeviceMotionEvent *motion = (XDeviceMotionEvent *) &Event;
                ...
     
            } else if ((Event.type == button_press_type) ||
                       (Event.type == button_release_type)) {
                          XDeviceButtonEvent *button = (XDeviceButtonEvent *) &Event;
     
                ...
            }else if ((Event.type= .... )){
                ...
         }
    }
  • XInput 2
    //Somewhere else...
     
    int xi_opcode;
    if (!XQueryExtension(display, "XInputExtension",&xi_opcode,&event, &error)) {
    printf("X Input extension not available.\n");
    return EXIT_FAILURE;
    }

    void doEvents (Display *dpy )
    {
        while(1) {
            XEvent        ev;
            XGenericEventCookie *cookie = &ev.xcookie;
            XNextEvent(dpy, &ev);
     
            if (XGetEventData(dpy, cookie) && cookie->type == GenericEvent
                && cookie->extension==xi_opcode)
            {
                XIDeviceEvent *event = cookie->data;
     
                printf("EVENT type %d\n", event->evtype);
                switch (event->evtype)
                {
                    //
                    // In all below event>deviceid contains the id of the device
                    //
                    case XI_DeviceChanged:
                        XIDeviceChangedEvent *dc = cookie->data;
                        ...
                        break;
                    case XI_HierarchyChanged:
                        XIHierarchyEvent *he = cookie->data;
                        ...
                        break;
                    case XI_RawEvent:
                        XIRawEvent *re = cookie->data;
                        ...
                        break;
                    case XI_FocusIn:
                    case XI_Enter:
                        XIEnterEvent *ee = cookie->data;
                        ...
                        break;
                    case XI_FocusOut:
                    case XI_Leave:
                        XILeaveEvent *le = cookie->data;
                        ...
                        break;
                    case XI_PropertyEvent:
                        XIPropertyEvent *pe = cookie->data;
                        ...
                        break;
                    case XI_Motion:
                    case XI_ButtonPress:
                    case XI_ButtonRelease:
                    case XI_KeyPress:
                    case XI_KeyRelease:
                        // do something with event (XIDeviceEvent contains data)
                        break;
                }
            }
         }
      }

Caldav calendar & icalserver

Posted by Benjamin Close on June 24, 2009 under Computers, FreeBSD, OpenSource | 2 Comments to Read

For quite a while now I’ve been using Apple’s ICal server on FreeBSD and Sunbird/Lightning as a front end to the calendar. However, one thing that has always annoyed me was the lack of a web frontend to my calendars.

Well today after searching on a completely different topic I found a javascript front end to caldav. After only a few minutes setup I had the frontend up and running. Sadly however, It didn’t play happy with ICalServer. A little debugging of the caldav REPORT request and I had it querying correctly.

Now there was valid data populating the table… or was it. Looking a little closer there were bugs with the reoccurring events and also with the lastMonday function. A quick fix (after 20mins finding them) and now the calendar works great!

Best thing about it is I can now have a public caldav calendar which everyone can view whilst being able to update thing directly on my own writable version of the caldav calendar.

samba ADS nightmares

Posted by Benjamin Close on February 2, 2009 under OpenSource, UniSA | Be the First to Comment

Recently Ben and I have been trying to get a FreeBSD box to join an Active Directory domain. The domain controller was running Windows Server 2008. After a *lot* of stuffing around to get this working we finally found the solution to our problem – the version of samba.
You see the problem we were facing was:

# net ads join -U cis-closebs
cis-closebs's password:
Failed to join domain: Improperly formed account name

Now we checked the logs, checked kerberos, samba, but could not get this working. The debug logs showed something but nothing really useful:

# net ads join -U cis-closebs
cis-closebs's password:
Failed to join domain: Improperly formed account name
# net ads join -d 3 -U cis-closebs
[2009/02/02 12:55:26, 3] param/loadparm.c:lp_load(5031)
  lp_load: refreshing parameters
[2009/02/02 12:55:26, 3] param/loadparm.c:init_globals(1430)
  Initialising global parameters
[2009/02/02 12:55:26, 3] param/params.c:pm_process(572)
  params.c:pm_process() - Processing configuration file "/usr/local/etc/smb.conf"
[2009/02/02 12:55:26, 3] param/loadparm.c:do_section(3770)
  Processing section "[global]"
[2009/02/02 12:55:26, 2] lib/interface.c:add_interface(81)
  added interface ip=130.220.236.62 bcast=130.220.237.255 nmask=255.255.254.0
[2009/02/02 12:55:26, 3] libsmb/namequery.c:get_dc_list(1489)
  get_dc_list: preferred server list: "130.220.64.77, uninet.unisa.edu.au, *"
[2009/02/02 12:55:26, 3] libads/ldap.c:ads_connect(394)
  Connected to LDAP server 130.220.64.77
[2009/02/02 12:55:26, 3] libsmb/namequery.c:get_dc_list(1489)
  get_dc_list: preferred server list: "130.220.64.77, uninet.unisa.edu.au, *"
[2009/02/02 12:55:26, 3] libsmb/namequery.c:get_dc_list(1489)
  get_dc_list: preferred server list: "130.220.64.77, uninet.unisa.edu.au, *"
cis-closebs's password:
[2009/02/02 12:55:27, 3] libsmb/namequery.c:get_dc_list(1489)
  get_dc_list: preferred server list: "130.220.64.77, uninet.unisa.edu.au, *"
[2009/02/02 12:55:27, 3] libads/ldap.c:ads_connect(394)
  Connected to LDAP server 130.220.64.77
[2009/02/02 12:55:27, 3] libads/sasl.c:ads_sasl_spnego_bind(213)
  ads_sasl_spnego_bind: got OID=1 2 840 48018 1 2 2
[2009/02/02 12:55:27, 3] libads/sasl.c:ads_sasl_spnego_bind(213)
  ads_sasl_spnego_bind: got OID=1 2 840 113554 1 2 2
[2009/02/02 12:55:27, 3] libads/sasl.c:ads_sasl_spnego_bind(213)
  ads_sasl_spnego_bind: got OID=1 2 840 113554 1 2 2 3
[2009/02/02 12:55:27, 3] libads/sasl.c:ads_sasl_spnego_bind(213)
  ads_sasl_spnego_bind: got OID=1 3 6 1 4 1 311 2 2 10
[2009/02/02 12:55:27, 3] libads/sasl.c:ads_sasl_spnego_bind(222)
  ads_sasl_spnego_bind: got server principal name = not_defined_in_RFC4178@please_ignore
[2009/02/02 12:55:27, 3] libsmb/clikrb5.c:ads_krb5_mk_req(593)
  ads_krb5_mk_req: krb5_cc_get_principal failed (No such file or directory)
[2009/02/02 12:55:27, 1] libsmb/clikrb5.c:ads_krb5_mk_req(602)
  ads_krb5_mk_req: krb5_get_credentials failed for not_defined_in_RFC4178@please_ignore (Server not found in Kerberos database)
[2009/02/02 12:55:27, 1] utils/net_ads.c:net_ads_join(1470)
  error on ads_startup: Server not found in Kerberos database
Failed to join domain: Improperly formed account name
[2009/02/02 12:55:27, 2] utils/net.c:main(1036)
  return code = -1

Turns out that it was the version of samba we were using. Version 3.0.28 had issues with joining a Windows Server 2008 Active Directory domain. This was fixed in Samba 3.0.28a and as can be seen with the FreeBSD ports commit:

Revision 1.169download - view: textmarkupannotated - select for diffs
Thu May 1 16:32:53 2008 UTC (9 months ago) by timur
Branches: MAIN
Diff to: previous 1.168: preferredcolored
Changes since revision 1.168: +2 -2 lines

Update port to the 3.0.28a revision.

Major changes:

  o Failure to join Windows 2008 domains
  o Windows Vista (including SP1 RC) interop issues

Approved by:	shaun (mentor, implicit)

So if you find yourself hunting around chasing something that surely should work.. consider upgrading samba!

Adding Multiple Mice Support to FLTK using MPX

Posted by Benjamin Close on November 25, 2008 under OpenSource, UniSA | Read the First Comment

For a while now I’ve been working on modifying FLTK to support multiple Mice. We need this functionality for applications we are working on. FLTK was chosen for a number of reasons. 

  1. It’s light weight
  2. It’s cross platform
  3. It was already in use by the applications being extended.
However, FLTK didn’t support multiple mice out the box. Multiple Mice support exists both under Win32 via the RAWINPUT api and under Xorg via MPX.
Though support in the various toolkits is still lacking. Not surprizing considering how recent MPX/RAWINPUT is.

Read more of this article »

jhbuild just won’t build! (aka Include path madness)

Posted by Benjamin Close on November 18, 2008 under FreeDesktop, OpenSource, Programming, UniSA | Read the First Comment

I’ve been recently trying to work out why jhbuild fails to build xorg on my FreeBSD box. Traditionally I compile to /usr/local/ however after wanting to experiment with MPX I’ve set things up so that I compile to /usr/local/MPX

Sadly this kept breaking in xorg/lib/libX11 with the error:

Read more of this article »

Setting up Sendmail with TLS & Auth support under FreeBSD

Posted by Benjamin Close on November 13, 2008 under FreeBSD, OpenSource | 5 Comments to Read

In order to setup a secure mail transport agent (MTA) that helps eliminate some spam and also allows roaming client support, some sort of authentication mechanisim must be added when setting up a MTA. In my case I’m using FreeBSD 4.9 with sendmail as my MTA. Setting Up Sendmail

Read more of this article »

LDAPAddressBook

Posted by Benjamin Close on under OpenSource, Projects | Be the First to Comment

LDAP is a great protocol. It allows multiple clients to obtain data about virtually anything that you can think of. The LDAPAddressBook project is a project to determine a LDAP Schema that works in the following clients:

  • Mozilla Thunderbird
  • Windows Address Book
  • OS X Address Book
  • Squirrel Mail

In fact any client that supports LDAP.

Read more of this article »

MPX & XTst

Posted by Benjamin Close on under Computers, FreeDesktop, OpenSource | Be the First to Comment

MPX is a modification of the Xorg X Windowing system created by Peter Hutterer whilst doing his PHD in the Wearable Computer Lab, at the University of South Australia.

It allows independent device control and contains a number of different API enhancements to support these.

You can find more about MPX at: http://wearables.unisa.edu.au/mpx/

Some of the new symbols defined are:

  • XTestFakeDeviceButton
  • XTestFakeDeviceButtonEvent
  • XTestFakeDeviceMotionEvent
  • XTestFakeProximityEvent
  • XtestFakeDeviceKeyEvent.

These are in the xtst library: http://cgit.freedesktop.org/xorg/libs/xtst/

Proxying a page/website through Apache

Posted by Benjamin Close on November 8, 2008 under Computers, OpenSource | Be the First to Comment

Sometimes you want to expose one port in your firewall but not another. However, often you have different servers running on different ports. Apache has the ability to proxy pages, this allows one server to be externally visible with the other running only locally. It allows you to secure one server and only open one port to external attacks. To setup this proxying put the following in your apache config file:

    RewriteEngine on
    RewriteLog /SOMELOGFILE
    RewriteLogLevel 2
    RewriteRule ^/(.*)$ http://localhost:8180/$1 [P]
    ProxyPassReverse / http://localhost:8180/

The above will proxy the entire domain to the server on the same machine running on port 8180. The [P] tells apache to use the proxy module to do the work. This is not a redirect but a proxy so it hides the internal URL with the external facing one. The ProxyPassReverse directive tells apache to do the rewrite of the URL to remove the localhost:8180 bit back to the originating url

Was this helpful?


Throw some money in the tip jar