Home » Tutorials » An Introduction To MHP » The MHP APIs » Using The Return Channel

Using The Return Channel

The interactive broadcast and Internet access profiles of MHP include support for using a return channel in the MHP receiver to talk to the outside world. This return channel can take just about any form: PSTN modem, cable modem, ADSL, GPRS, or something more exotic. MHP doesn’t care. All that’s defined in the MHP specification is that this connection has to support TCP/IP.

When we say, TCP/IP, we mean just TCP/IP. While support for DNS is mandatory, no support for other protocols is required by MHP. HTTP 1.1 is an optional part of the Interactive Broadcast profile in MHP 1.0.x and MHP 1.1.x, although MHP 1.1.x rreceivers implementing the Interactive Broadcast or Internet Access profiles must include support for HTTP 1.0 and HTTPS. All other protocols such as SMTP or IMAP must be implemented by the application.

Despite these restrictions, connecting to the outside world is easy for an application developer. MHP and OCAP both use the java.net package to do this, with some restrictions. Since java.net should hold no surprises (or if it does, there are enough other good tutorials out there), we won’t cover how you use it in this document.

The only difference between using the return channel in MHP and using the standard java.net API is session management. Java.net assumes that you have a permanent connection to the Internet (or at least, that you’re already connected). This doesn’t apply to an MHP receiver that’s connecting over a PSTN modem, for instance, and so there’s a need for an API to handle this. The session management API is also needed to prevent rogue applications from using the return channel to dial premium-rate phone numbers without the user’s permission. This kind of fraud is not unknown in the PC world, and so the session management API was designed to prevent this sort of problem from occurring in the less technically-savvy consumer world.

OCAP receivers don’t need to worry about either of these problems, since OCAP specifies that the receiver has an always-on return channel using a cable modem. This removes the potential threat from rogue dialler applications, and also removes the need for any kind of session management.

The return channel session management API is defined in the org.dvb.net.rc package. There are three main classes here that we care about. The RCInterface class represents an interface to the return channel. This is a fairly simple class which models a couple of the basic properties of the interface, namely its type (e.g. cable modem, PSTN, ISDN or others) and its data rate. This class has one subclass, ConnectionRCInterface, which is more useful to us in the case of a typical receiver. This class represents an interface to a return channel which is not permanently connected. As such, it has a number of extra methods to handle connecting and disconnecting.

The complete ConnectionRCInterface class looks like this:

public class ConnectionRCInterface
  extends RCInterface
  implements ResourceProxy {

  public boolean isConnected();

  public float getSetupTimeEstimate();

  public void reserve(
    ResourceClient c,
    Object requestData)
    throws PermissionDeniedException;

  public void release();

  public void connect()
    throws IOException, PermissionDeniedException;

  public void disconnect()
    throws PermissionDeniedException;

  public ConnectionParameters getCurrentTarget()
    throws IncompleteTargetException;

  public void setTarget(ConnectionParameters target)
    throws IncompleteTargetException,
           PermissionDeniedException;

  public void setTargetToDefault()
    throws PermissionDeniedException;

  public int getConnectedTime();

  public ResourceClient getClient();

  public void addConnectionListener(
    ConnectionListener l);
  public void removeConnectionListener(
    ConnectionListener l);

}

Most of these methods have pretty obvious functions. The most interesting method is the setTarget() method which sets the parameters for the connection. This takes a ConnectionParameters object that defines where the interface should connect to. An interface may have a default target that an application can connect to if it has the necessary permissions. This allows applications to access servers via a common service provider, for instance one that a broadcaster has partnered with.

The ConnectionParameters class defines the most important parameters needed to set up a connection, such as the phone number to dial and the user name and password that should be used to authenticate the connection:

public class ConnectionParameters {

  public ConnectionParameters(String number,
                              String user name,
                              String password);

  public ConnectionParameters(String number,
                              String user name,
                              String password,
                              InetAddress[] dns);

  public String getTarget();
  public String getUsername();
  public String getPassword();
  public InetAddress[] getDNSServer();
}

These parameters are designed to reflect those needed by a PSTN modem, because that is the most common type of return channel where session management is needed. Most other kinds of return channel technology do not need session management, or the session management can be handled entirely by the receiver as necessary. For instance, an ADSL modem that connects on demand can handle session management automatically, and can be configured as part of the initial installation process rather than needing to be configured each time it connects.

Each ConnectionRCInterface may have a default target that it will connect to. The setTargetToDefault() method resets the interface so that it will connect to this default target. Since an application may not have permission to connect to this default target, this method can throw a PermissionDeniedException.

The ConnectionRCInterface class implements the ResourceProxy interface from the org.davic.resources package, which means that this class represents a scarce resource. As with other scarce resources, access to it has to be managed, and this is done using the RCInterfaceManager class. This is a singleton class, and a reference to it can be obtained by the RCInterfaceManager.getInstance() method. Once the application has a reference to it, there are a number of methods that it can use to get an interface to the return channel. The getInterfaces() method returns references to all of the return channel interfaces that the application can use (which may be an empty array, depending on the permissions assigned to the application).

The getInterface() method has several variants, which can take either a java.net.URLConnection object, a java.net.Socket object, or a java.net.InetAddress object. In the first two cases, the MHP middleware assumes that a connection already exists, and returns the interface that’s used for that connection. In the last case, the middleware returns the interface that will be used for that connection, or a null reference if that can’t be determined yet.

As you can see, this is not quite a standard implementation of the resource notification API. The main reason for this is that the methods to reserve and release the underlying resources are implemented on the resource proxy, and not on the resource server. Apart from this, there are no real surprises.

The resource server in this case is the RCInterfaceManager. This is a singleton class that not only provides the interface to register a ResourceStatusEventListener for the return channel, but also provides a way for an application to get a reference to an RCInterface object. The getInterfaces() method returns an array of all the interfaces in the system, but there are other methods which give us slightly more exact results. The getInterface() comes in three flavours, taking either a java.net.Inetaddress, java.net.URLConnection or a java.net.Socket as an argument. The last two allow the application to find out which interface is connected to a particular socket, or is used for a particular URLConnection. The first of these is a little different, in that it returns the interface that would be used for connecting to that address. If the interface isn’t known at that time, the method will return
a null reference.

To actually use this API to connect to a remote server, we could use the following code:

// First, we get a reference to the RCInterfaceManager
RCInterfaceManager rcm =
  RCInterfaceManager.getInstance();

// Now, we get the list of return channel interfaces that
// are available to our application.  This returns all
// the available interfaces
RCInterface[] interfaces = rcm.getInterfaces();

// Now choose which interface we use.

// Since we get all the interfaces, we need to check that
// we get the right type.  So, we check if the first
// interface is a ConnectionRCInterface
if (interfaces[0] instanceof ConnectionRCInterface) {

  // If it's a ConnectionRCInterface, it's not
  // permanently connected, so we need to connect it
  // first

  ConnectionRCInterface myInterface;
  myInterface = (ConnectionRCInterface)interfaces[0];
  // Now that we've got a reference to the interface, we
  // can start to use it
  try {
    // First,we reserve the connection
    myInterface.reserve();

    // Set up the connection parameters
    ConnectionParameters myConnectionParameters;
    myConnectionParameters = new ConnectionParameters
      ("0199604235697", "username", "password");

    // Then we set the target to point to our phone
    // number
    myInterface.setTarget(myConnectionParameters);

    // Now that we've done that, we can actually connect
    myInterface.connect();

    // do whatever we want to now that we've got a
    // connection

    // Once we're done, we disconnect the interface and
    // release the resource
    myInterface.disconnect();
    myInterface.release();

  } catch (permissionDeniedException e) {

    // we can't reserve the interface, so return
    return;
  }
}
else {
  // we have a permanent connection, so just use it
}

One important thing to remember about the return channel interface is that MHP specifies nothing about the server that the application connects to. Apart from the fact that it uses TCP/IP, everything else is up to the application writer. After all, MHP only cares about defining interoperability from a platform point of view. If the application runs correctly on every MHP receiver, it’s up to the developer to make sure that the application talk correctly to any servers or other infrastructure that it needs to. By providing a TCP/IP connection, MHP has provided a well-defined interface to this equipment, and it’s up to application developers to use that in the way that suits their needs best.

This may seem complicated for the application developer, who has to implement any additional protocols that are necessary to communicate with a remote database, or a server that is registering votes, or a mail server, or an instant messaging server, or any other type of remote machine that they need to connect to. In reality, however, this is simply the most flexible way of providing a communication mechanism for a wide range of applications. An application that needs to support online voting using the return channel can implement a much simpler interface than an e-commerce application (and may not even need a full IP connection at all: see below), and different e-commerce applications can use different encryption mechanisms as they see fit.

To give you an example of this flexibility, let’s consider online voting. This is a relatively common use of the return channel, and there are many different ways to implement it. Some companies may want to integrate the votes cast via DTV applications with votes cast on their web site, and in this case it may be best to to register the vote via an HTTP request to a web page on the broadcaster’s web site. In other cases, the broadcaster may have an agreement with the local telephone company about revenue sharing from SMS messages (voting using SMS is common on TV shows in many countries), in which case the receiver would prefer to use the receiver’s modem to transmit an SMS message that registers the vote.

A final method of online voting hardly involves making a connection at all. A technique called "drop call" voting allows votes to be counted simply by dialling a particular phone number. The server will detect the incoming call, register a vote and then immediately terminate the connection without even connecting to the incoming call. This allows votes to be counted very quickly, and also saves the user’s phone bills because a long connection is not needed.

MHP receivers in Italy must support this type of voting, and MHP 1.1.2 adds some extra classes that help to support this. A number of subclasses of the ConnectionFailedEvent have been defined to indicate why a connection failed. One of these is the ConnectionDroppedEvent, which tells the application that the number they dialled has dropped the connection, and thus the application can be sure that the vote has actually been registered. In earlier versions of MHP, a ConnectionFailedEvent would be generated, which could either mean that the vote was successfully counted, or that the vote could not be counted because the number for voting was busy, the phone line was disconnected or any other reason that prevented the receiver from making the call in the first place.