A Brief Introduction to UPnP

Posted on December 12, 2012 -

UPnP(Universal Plug and Play) is a set of networking protocols promoted by the UPnP Forum. If you have no idea what it is, this article from Microsoft may help. It was written in 2001, which describes an intelligent home that is still attractive currently.

I will analysis the architecture of UPnP in this article.

1 The Brief Architecture

UPnP is composed of several steps, including discovery, description, control, eventing and presentation.

  • Discovery: during this step, service providers (called 'devices') and service users (called 'control points') discover each other.
  • Description: devices use XML to describe their information and services before being used.
  • Control: control points use SOAP to control devices.
  • Eventing: subscribers will be informed when devices' states change.
  • Presentation: devices are able to use browsers to present themselves. (This won't be discussed in this article.)

Before analysing the first four steps, we have to know that step 0 of UPnP requires each device and control point in a network which enables multicast.

The multicast address 239.255.255.250:1900 is used by UPnP.

2 Discovery

Discovery can be done using SSDP, which runs over HTTP based on UDP.

When a new device joins in, it multicasts the following message:

NOTIFY * HTTP/1.1
Host:239.255.255.250:1900
Cache-control:max-age=1800
Location:http://192.168.0.1:49152/des.xml
Nt:upnp:rootdevice
Nts:ssdp:alive
Usn:uuid:de5d6118-bfcb-918e-0000-00001eccef34::upnp:rootdevice

Here,

  • Host: MUST be 239.255.255.250:1900. The multicast address and port are reserved for SSDP by IANA (Internet Assigned Numbers Authority).
  • Cache-control: The integer following max-age= specifies the number of seconds the advertisement is valid, which indicates that the device need to resend this notification before expiration.
  • Location: A URL to the UPnP description of the device.
  • Nt: Notification Type.
  • Nts: Notification Sub Type. Must be ssdp:alive.
  • Usn: Unique Service Name, which identifies a unique instance of a device or service.

Similarly, a control point also multicasts a message when joining in:

M-SEARCH * HTTP/1.1
Host:239.255.255.250:1900
Man:"ssdp:discover"
Mx:5
ST:ssdp:rootdevice
  • Man: MUST be "ssdp:discover", the quotes here SHOULD be kept.
  • Mx: maximum wait time in seconds. MUST be greater than or equal to 1 and SHOULD be less than 5.
  • ST: Search Target, the device that you want to search.

The response from a device is like:

HTTP/1.1 200 OK
Cache-control:max-age=1800
Ext:
Location:http://192.168.0.1:2345/xx.xml
Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0
ST:ST:urn:schemas-upnp-org:service:ContentDirectory:1
USN:uuid:60b2e186-b084-44af-ac09-1c64ea1bb364::urn:schemas-upnp-org:service:ContentDirectory:1

3 Description

Description is based on HTTP.

Many tags can be used to describe a device. You can get a complete list from UPnP Forum. Here is an example:

<?xml version="1.0" encoding="utf-8"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
  <specVersion>
    <major>1</major>
    <minor>1</minor>
  </specVersion>

  <device>
    <deviceType>urn:schemas-upnp-org:device:BinaryLight:1</deviceType>
    <friendlyName>Kitchen Lights</friendlyName>
    <manufacturer>OpenedHand</manufacturer>
    <modelName>Virtual Light</modelName>
    <UDN>uuid:cc93d8e6-6b8b-4f60-87ca-228c36b5b0e8</UDN>

    <serviceList>
      <service>
        <serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType>
        <serviceId>urn:upnp-org:serviceId:SwitchPower:1</serviceId>
        <SCPDURL>/SwitchPower1.xml</SCPDURL>
        <controlURL>/SwitchPower/Control</controlURL>
        <eventSubURL>/SwitchPower/Event</eventSubURL>
      </service>
    </serviceList>
  </device>
</root>

specVersion tag defines the architecture on which the device is implemented. So we only discuss the device tag:

  • deviceType: UPnP device type, MUST be "urn:schemas-upnp-org:device:deviceType:v".
  • friendlyName: short description for end user.
  • manufacturer: manufacturer's name.
  • modelName: model name.
  • UDN: Unique Device Name, universally-unique identifier for the device.
  • serviceList: contains services descibed in the following.

Each service contains:

  • serviceType: UPnP service type.
  • serviceId: service identifier.
  • SCPDURL: URL for service description.
  • controlURL: URL for control.
  • eventSubURL: URL for eventing.

A service description is like this:

<?xml version="1.0" encoding="utf-8"?>
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
  <specVersion>
    <major>1</major>
    <minor>1</minor>
  </specVersion>
  <actionList>
    <action>
      <name>SetTarget</name>
      <argumentList>
        <argument>
          <name>NewTargetValue</name>
          <relatedStateVariable>Target</relatedStateVariable>
          <direction>in</direction>
        </argument>
      </argumentList>
    </action>
    <action>
      <name>GetTarget</name>
      <argumentList>
        <argument>
          <name>RetTargetValue</name>
          <relatedStateVariable>Target</relatedStateVariable>
          <direction>out</direction>
        </argument>
      </argumentList>
    </action>
    <action>
      <name>GetStatus</name>
      <argumentList>
        <argument>
          <name>ResultStatus</name>
          <relatedStateVariable>Status</relatedStateVariable>
          <direction>out</direction>
        </argument>
      </argumentList>
    </action>
  </actionList>
  <serviceStateTable>
    <stateVariable sendEvents="no">
      <name>Target</name>
      <dataType>boolean</dataType>
      <defaultValue>0</defaultValue>
    </stateVariable>
    <stateVariable sendEvents="yes">
      <name>Status</name>
      <dataType>boolean</dataType>
      <defaultValue>0</defaultValue>
    </stateVariable>
  </serviceStateTable>
</scpd>

actionList contains actions. serviceStateTable contains state variables.

Every action has a name and a list of arguments. Arguments also have a name, a direction (in or out for input or output arguments) and a related state variable. The state variable is used to determine the type of the argument, and as such is a required element. This can lead to the creation of otherwise unused state variables to define the type for an argument.

4 Control

Control messages are also expressed in XML using the SOAP.

Here is an example:

POST /control/url HTTP/1.1
HOST: hostname:portNumber
CONTENT-TYPE: text/xml; charset="utf-8"
CONTENT-LENGTH: length of body
USER-AGENT: OS/version UPnP/1.1 product/version
SOAPACTION: "urn:schemas-upnp-org:service:serviceType:v#actionName"

<?xml version="1.0"?>
<s:Envelope
 xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
 s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <s:Body>
        <u:actionName xmlns:u="urn:schemas-upnp-org:service:serviceType:v">
            <argumentName>in arg value</argumentName>
        </u:actionName>
    </s:Body>
</s:Envelope>

Here, actionName and argumentName must be correlated to the description.

The result of invocation is also expressed in XML:

HTTP/1.1 200 OK
CONTENT-TYPE: text/xml; charset="utf-8"
DATE: when response was generated
SERVER: OS/version UPnP/1.1 product/version
CONTENT-LENGTH: bytes in body

<?xml version="1.0"?>
<s:Envelope
 xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
 s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <s:Body>
        <u:actionNameResponse xmlns:u="urn:schemas-upnp-org:service:serviceType:v">
            <argumentName>out arg value</argumentName>
        </u:actionNameResponse>
    </s:Body>
</s:Envelope>

5 Eventing

Control points listen to state changes in devices. We only consider unicast eventing.

Subscription and Unsubscription

URL for subscription is given in the desription of services. Here is an example:

SUBSCRIBE publisher path HTTP/1.1
HOST: publisher host:publisher port
USER-AGENT: OS/version UPnP/1.1 product/version
CALLBACK: <delivery URL>
NT: upnp:event

The response may be:

HTTP/1.1 200 OK
DATE: when response was generated
SERVER: OS/version UPnP/1.1 product/version
SID: uuid:subscription-UUID
CONTENT-LENGTH: 0
TIMEOUT: Second-1800

Two fields need to be noticed:

  • SID: subscription identifier.
  • TIMEOUT: actual duration until subscription expires.

Renewing a subscription with SID:

SUBSCRIBE publisher path HTTP/1.1
HOST: publisher host:publisher port
SID: uuid:subscription UUID

Unsubscription is similar:

UNSUBSCRIBE publisher path HTTP/1.1
HOST: publisher host:publisher port
SID: uuid:subscription UUID

Eventing Message

We directly analyse the data packet:

NOTIFY delivery path HTTP/1.1
HOST: delivery host:delivery port
CONTENT-TYPE: text/xml; charset="utf-8"
NT: upnp:event
NTS: upnp:propchange
SID: uuid:subscription-UUID
SEQ: event key
CONTENT-LENGTH: bytes in body

<?xml version="1.0"?>
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
    <e:property>
        <variableName>new value</variableName>
    </e:property>
</e:propertyset>

e:property repeats once for each variable name and value in the event message.

SEQ is the event sequence number and begins from 0.

To acknowledge receipt of this event message, a subscriber MUST respond within 30 seconds, including expected transmission time:

HTTP/1.1 200 OK

However, if a subscriber does not respond within 30 seconds, the publisher MUST keep the subscription active until the subscription expires or is cancelled.

6 Implementation

UPnP is not complicated. Thankfully, some SDKs can be found in UPnP Forum: http://upnp.org/sdcps-and-certification/resources/sdks/.

References

  1. UPnP Hacks: UPnP background http://www.upnp-hacks.org/upnp.html
  2. UPnP Device Architecture version 1.1 http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
  3. Writing a UPnP Service http://burtonini.com/computing/gupnp-docs/server-tutorial.html