Wednesday, December 15, 2010

Factoring exception handling code in C++

When writing exception handlers (e.g. around calls to database or network related code), you often end up with the same set of catch clauses at each call site. Suppose you end up with the following code:

try {
  //...
} catch (std::runtime_error& e) {
  std::cout << "Runtime error: " << e.what() << std::endl;
} catch (...) {
  std::cout << "Unknown exception!" << std::endl;
}

You have this piece of code repeated dozens of times, which is not really a Good Thing(tm)... A little C++ trick can help you avoid those repetitions: (1) factor the common code into a single function or method that rethrows the active exception and catches it immediately, and (2) catch all exceptions at the call sites and call this handler!

#include <iostream>
#include <stdexcept>

void exception_handler() {
  try {
    throw; //rethrow the current exception
  } catch (std::runtime_error& e) {
    std::cout << "Runtime error: " << e.what() << std::endl;
  } catch (...) {
    std::cout << "Unknown exception!" << std::endl;
  }
}

int main() {
  try {
    throw std::runtime_error("unable to comply...");
  } catch (...) { exception_handler(); }

  try {
    throw 1;
  } catch (...) { exception_handler(); }

  return 0;
}

You must be careful to not call exception_handler() outside a catch clause: the trow statement calls terminate() if there is no active exception to rethrow!

You may wonder if one could use the std::uncaught_exception() function to protect against this.

void exception_handler() {
  try {
    if (!std::uncaught_exception()) {
      return; // Nothing to rethrow...
    }
    throw; //rethrow the current exception
  } ...
}

But this does not work: uncaught_exception() "returns true after completing evaluation of the object to be thrown until completing the initialization of the exception-declaration in the matching handler", as the standard says. And when exception_handler is entered, this is generally from the catch clause, and the exception has thus been caught... Your handler would now simply swallow all the exceptions!...

Actually, uncaught_exception is pretty much useless...

Thursday, December 9, 2010

Using a VPN when connecting to open Wifi networks

You may have heard about Firesheep, a Firefox extension that allows to hijack other people's online accounts.  Basically, when you're using an open Wifi hotspot to check your Facebook, Twitter or Gmail[1] account, any other user connected to the same hotspot is able to sniff enough information to impersonate you and connect to your account.  Do you really want to risk having your online accounts used by anybody?

The issue is that although those sites use HTTPS (i.e. secured HTTP) during the login phase, they do not use it for the remainder of the session. And because the Wifi network is not encrypted either, your traffic can be intercepted and read by anyone connected to the same hotspot. This kind of vulnerability, known as session hijacking, exists since a long time, but it is only recently, with the advent of Firesheep, that it received wide coverage.

What can you do against it?

The simplest is that you stop using open Wifi networks... Pretty useful, no? Ok. Next one...

In order to prevent session hijacking, you can configure your accounts to always use HTTPS instead of using it only for the login phase.  This will encrypt the entire session, preventing attackers to read the cookie that identifies you against the site you're connecting to.  This is an option that's available for Gmail, but is not for Facebook or Twitter.

If you still want to use those sites when on the road, you should use a Virtual Private Network that will encrypt your entire traffic.  VPNs are usually set up to allow employees to connect to corporate servers from outside the company's network.  Mobile users can thus check their mails, access source code repositories, bug database, etc.

VPNs can also be used on your home network to gain access to your music or video library, or any other service, in a secure manner.  But the trick here will be to allow users connected through the VPN to access the Internet at large, not only your local network.  The link from your mobile device to your home server will be protected by the VPN, and the connexion from your home server to the Internet will be assumed to be safe: if you're worried about people who could wiretap your ADSL line, then you should probably not connect any Internet site at all...


Setting up a VPN server

There are tons of tutorials out there about how to configure a PC with any reasonably modern OS to act as a VPN server.  Here are some information for Windows 7 or Vista (Start > Control Panel > Network and Internet > Network and Sharing Center > Manage network connections, then hit the Alt key, choose File > New Incoming Connection), Mac OS X, or Linux.

Note that, on Windows, you are not offered the possibility to choose your type of VPN service: it's PPTP, and no other.  You need to know this when you configure your client...  And if you don't have a password on your main account, you must create a new user with a strong password.

Note also that if you have a router, you'll need to configure it to allow the traffic to come to your VPN server. The tutorial for Windows above has some information about this subject.

The only issue I had while setting up my Windows 7 box was that you really want to configure it so that IP addresses for incoming connexions use a specify range, with at least two possible addresses...


Setting up your client

Setting up a server is a necessary step, but you'll also want to configure your mobile device (be it a laptop or a smartphone) to connect to your VPN server.  For a Windows client, the 'Connect to a Workplace' wizard will do: Click the Start button > Control Panel > Network and Internet > Network and Sharing Center > Set up a connection or network > Connect to a workplace.

On the iPhone, you have to navigate to Settings > General > Network.  Don't worry, it'll be much easier to just turn it on once it's configured... On the lower part of the page, you'll find a button that will allow you to configure a VPN connexion.  Here is how I did it:




Use the PPTP protocol, with your own (external) IP address, the name of the account you chose when configuring the server, and its password.  Make sure 'Send All Traffic' is ON, so that you are really protected!

You can check your setup is correct by connecting with your iPhone to a service that shows your IP address (don't try this from home, it would not prove anything!  Or disconnect the Wifi on your iPhone!): it should tell you that your address is the one of your ADSL connection...

You can now enjoy free Wifi secure connexions!...

Thursday, August 26, 2010

Implementing One-to-Many Relationships in C++

The need to manage relations between objects is at the core of many business applications: objects refer to each other with various semantics, with or without inverse links, for various durations.

A very common case is the One-to-Many relation: a Owner object has relationships with several User objects. The owner must know which objects it is related to, and the users have an inverse link to their owner.  When a user is added to or removed from its owner, both links should be updated.  When the owner is destroyed, all the owned objects are also destroyed.  Such relations are extremely common, and often implemented with ad-hoc code.

This paper proposes a set of classes to implement those One-to-Many relations with a minimal amount of code to be written in the Owner and User classes, and performance equivalent to hand-written code, both in terms of memory and CPU.

Here is an example...

#include "relations.h"

#include <iostream>
#include <string>

using namespace relations;

class User;
class Owner;

class Named {
public:
  Named(const std::string& name) 
    : _name(name) {}
  const std::string& name() const {
    return _name;
  }
  ~Named() { 
    std::cout << "Object '" << _name << "' destroyed" << std::endl; 
  }
private:
  std::string _name;
};

class User 
  : public RelationUser<Owner, User>
  , public Named {
public:
  User(Owner* owner, const std::string& name)
    : RelationUser<Owner,User>(owner)
    , Named(name)
  {}
};

class Owner 
  : public RelationOwner<RelationUser<Owner, User> > {
public:
  void show();
};

void Owner::show() {
  std::cout << "Users of Owner: ";
  for (Owner::iterator it (begin()); it != end(); ++it) {
    std::cout << (*it)->name() << " ";
  }
  std::cout << std::endl;
}

void test()  {
  Owner* owner (new Owner());
  User* user1 (new User(owner, "1"));
  User* user2 (new User(owner, "2"));
  User* user3 (new User(owner, "3"));
  owner->show();

  delete user2;
  owner->show();

  delete owner; // All users deleted
}

int main() {
  test();
  return 0;
}


And the output is:

  Users of Owner: 1 2 3
  User '2' destroyed
  Users of Owner: 1 3
  User '1' destroyed
  User '3' destroyed

Enjoy...