Introduction
Many applications support webinterfaces, either for controlling the application or for configuration. For example; most home routers have a config page, or a download/filesharing application like eMule has a full application web interface. How convenient they may seem, getting to those pages remains cumbersome.
Accessing a homerouter usually requires an ipconfig
command at a command prompt to find the IP adres, which then can be used to point a browser to something like; http://123.123.123/
. eMule uses a specific port to access it and hence requires a URL similar to http://123.123.123:12345/
to access it and if you use dynamic IP addresses it might change over time.
What if a user could just open the network, and find icons for all the devices/services available and access is just a click away? No requirements for putting shortcuts on all systems on the lan, nor a requirement for fixed IP addresses. This article will show how to achieve this by (ab)using the UPnP device protocol (on Windows that is, but it might work on other platforms to). Have a look at the screen shot below to see how its delivered.
The code in this article uses the Developer tools for UPnP (the former Intel UPnP stack).
Background
UPnP protocol supports automatic discovery using the SSDP protocol. Windows supports UPnP out of the box and just opening the network will automatically show all UPnP devices on the network (you might have to enable UPnP to have them shown).
UPnP devices generically provide some general details about the device and can (through the UPnP protocol) be queried for services they provide or sub-devices they embed. Once the device description (with the details and services) has been retrieved from the UPnP device, the services methods and properties can be accessed. For more info on the UPnP protocol check the documentation available at http://www.upnp.org/. The most common UPnP implementations are the mediaserver and mediarender devices, if you ever used WMP to browse media on another computer, or browsed your video collection on a NAS device from your TV, you've probably used UPnP already.
How to Make it Work
UPnP has standard devices for different purposes; media servers, media renderers and network gateways are the most commonly used. The most basic version of a UPnP device is the type called 'basic' (an appropriate name). It defines no services nor embedded devices and hence only the generic information. One of the generic items is the presentation page to access the device. Its not a required item, so many devices haven't implemented it. But in this case we'll use it to serve a simple piece of redirect html to the actual web-frontend that the user needs.
So what's happening now:
- user opens the network
- under the heading 'Other devices' the device shows up
- user double clicks the icon
- Windows will open the link to the UPnP device (*) in the webbrowser
- the device page handler will return a html redirect page.
- the browser opens the actual web-frontend of your application, based on the redirect
(*) Windows has default behaviour depending on the type of UPnP device. If you have enabled UPnP on your router, it will show up in the 'Network Infrastructure' section. But because the default action in Windows for this device type is 'Disable' (I have no clue what that actually does), double clicking will not open its adminpage. So if you don't use the 'basic' its important to use a device type that has a default action that opens the UPnP device URL (check the utility in the references section below, it includes a test file with most known standard device types, to test the differences).
Using the Code
First of all, your application should add a reference to the UPnP library. Then the code needed to create a UPnP device is simple as just setting a list of properties and calling StartDevice
;
_objUPnPDevice = OpenSource.UPnP.UPnPDevice.CreateRootDevice(900, 1,
"t:\going nowhere\")
_objUPnPDevice.HasPresentation = True
_objUPnPDevice.StandardDeviceType = "basic"
_objUPnPDevice.PresentationURL = "link/forward.html"
_objUPnPDevice.AddVirtualDirectory("link", AddressOf HeaderHandler,
AddressOf PageHandler)
_objUPnPDevice.UniqueDeviceName = System.Guid.NewGuid().ToString()
_objUPnPDevice.Manufacturer = "CodeProject"
_objUPnPDevice.ManufacturerURL = "http://www.codeproject.com"
_objUPnPDevice.ModelName = "UPnP access to webinterface"
_objUPnPDevice.ModelDescription =
"Network based URL shortcut available to all users on the network (subnet)"
_objUPnPDevice.ModelURL = New Uri("http://www.codeproject.com")
_objUPnPDevice.ModelNumber = ""
_objUPnPDevice.SerialNumber = ""
_objUPnPDevice.ProductCode = ""
_objUPnPDevice.FriendlyName = "New UPnP icon, please customize me!"
to start or stop the device the _objUPnPDevice.StartDevice
and _objUPnPDevice.StopDevice
can be called. The only thing needed beyond this is the page and header handlers. These handlers handle the http page request and will serve the html redirect page. Here's the code;
Public Shared Sub HeaderHandler(ByVal sender As OpenSource.UPnP.UPnPDevice,
ByVal msg As OpenSource.UPnP.HTTPMessage,
ByVal WebSession As OpenSource.UPnP.HTTPSession, ByVal VirtualDir As String)
End Sub
Public Shared Sub PageHandler(ByVal sender As OpenSource.UPnP.UPnPDevice,
ByVal msg As OpenSource.UPnP.HTTPMessage,
ByVal WebSession As OpenSource.UPnP.HTTPSession, ByVal VirtualDir As String)
Dim response As New OpenSource.UPnP.HTTPMessage
With response
.StatusCode = 200
.StatusData = "OK"
.AddTag("Content-Type", "text/html")
.BodyBuffer = System.Text.Encoding.UTF8.GetBytes( _
"<html><head>" & vbCrLf & _
"<META HTTP-EQUIV=Refresh CONTENT=""0; URL=http://www.codeproject.com/"">" & vbCrLf & _
"</head><body>" & vbCrLf & _
"</body></html>")
End With
WebSession.Send(response)
End Sub
The header handler is empty as it isn't used, the page handler simply returns a piece of html that redirects to http://www.codeproject.com/, which should be customized to point to your application interface.
For the device to behave as a proper UPnP device, it should preferably use the same unique identifier for each session (that is the value of the _objUPnPDevice.UniqueDeviceName
property). Besides that, you should stick to the devicetype 'basic' or a custom devicetype, but not use any of the other standard types, unless you plan to implement the required services and sub-devices for that device.
Points of Interest
This very simple code, could substantially increase userfriendlyness. Unfortunately Windows will not show the UPnP device icon (Windows uses its own icons even if the device lists an available icon). I haven't tried this on Windows XP, but on Vista and Win7 it works like a charm. I created a small utility that basically lets you define any number of these devices. I'm running this on my homeserver to quickly get access to the applications without having to install shortcuts on every client in my home. Here's what it looks like, the 6 icons listed in the 'Other Devioces' section;
Note; the 'router' in the Network Infrastructure section is the same physical device as the 'DD-WRT wlan router', but because Windows has a default action, different than opening the presentation page for the router, I added it again using a html forward through the utility. The utility (which uses different code than the sample included with this article) can be downloaded here (including sources).
From a security perspective; web interfaces should be secure by themselves. If the application is not secure by itself and just relies on being hidden on some obscure ip address and port combination, then exposing the application in this way is obviously not a good idea.
One caveat; windows will only show UPnP devices when its connected to a network. So even local UPnP devices will not show when there is no network connection.
References
History
3-Feb-2011 Initial article