Monday, March 2, 2009

UPnP 入門

UPnP 入門
- 64 -
デバイスがこのように自己紹介する動作をUPnP ではAdvertisement と呼んでいます。
「デバイスが既にネットワークに接続された状態でコントロールポイントを
起動した場合はどうなるの? 自己紹介終わっているよ」
この場合には逆にコントロールポイントが「こういうデバイスを制御したいから、該当者は自
己紹介してくれ」とネットワークに接続されたデバイス達に対してUDP プロトコルを使って要
求をします。この要求に対してデバイスが適時UDP で応答するようにUPnP では決められてい
ます。この情報を集めて保持すれば、Advertisement と同様にデバイスを制御することが可
能となります。これが2 つ目のカラクリです。この要求作業をUPnP ではM-Search と呼んで
います。
では、それぞれの仕様をもう少し細かく見ていきましょう。
2-4-1 Advertisement
Advertisement は、デバイスがネットワークに対して自己紹介する動作になります(図
2-17)。
図2-17 Advertiseのイメージ
また、デバイスはネットワークから切断される際(例えばユーザが電源オフボタンを押したな
ど)には自分がいなくなる旨の宣言を行いますが、この動作もAdvertisement となります。
この場合図2-17 でいうUPnP デバイスA は「ネットワークから離れます。さようなら」と宣言
し、UPnP コントロールポイントは自分で持っているデバイスのリストからUPnP デバイスA を
削除することとなります。
UPnP コントロールポイント UPnP デバイスA
ポート1900 じゃ
関係ないな
.……
UPnP デバイスA
でーす。
自己紹介しまーす
アドレスは
192.168.0.3
です。
お、UPnP デバイス
からの
Advertiseだ。
持っている情報を更新せねば。
非UPnP デバイス1 非UPnP デバイス
第2章 UPnP 入門
- 65 -
Advertisement にはUDP 通信を使います。相手先IP アドレスは、239.255.255.250 と
いうマルチキャストアドレスです。つまり同一ネットワーク上に存在する複数のデバイスに向け
て発信することになります。ポート番号は1900 を使います。1900 番はSSDP というプロトコ
ルを意味します。SSDP は「The Simple Service Discovery Protocol」の略語です。
「えー、また新しいプロトコルなの~?」
大丈夫です。新しいプロトコルなのですが、基本はHTTP ですので、HTTP が解っていれば全
然難しくはありません。
■接続の告知
UPnP デバイスはネットワークに接続しますと、まずはSSDP で自己紹介を行います。
SSDP の基本はHTTP で、複数デバイスに対するデータ通信となりますので、UDP が使われます。
そして、UDP ヘッダの後に以下のようなテキストデータが続くことになります(リスト2-2)。
“ ”の中は説明文です。実際にはデバイス毎に異なる文字列が設定されることとなります。

NOTIFY * HTTP/1.1 ¥r¥n
HOST: 235.255.255.250:1900 ¥r¥n
CHACHE-CONTROL: max-age = ”アドバタイズが有効となる時間を設定” ¥r¥n
LOCATION: ”デバイスにアクセスするためのURL を指定” ¥r¥n
NT: ”どのデータを通知するのかタイプを指定” ¥r¥n
NTS: ssdp:alive ¥r¥n
SERVER: ”サーバOS の名前 UPnP/1.0 製品名/バージョン”¥r¥n
USN: ”ユニークサービス名、要は何を告知したいかの記述”¥r¥n
¥r¥n

リスト2-2 SSDP、告知の基本(最後にブランク行が必要)
どうでしょうか。HTTP のデータそのものとなっています※。“NOTIFY”というリクエストが
あり、その下にヘッダが続くという形になります。そしてデータ本体は存在しないという構造に
なっています。これがSSDP の基本となります。
※ 先頭行に “HTTP1.1”と記述されていますし……。
NOTIFY はその名の通りで、通知を意味します。その後の文字列はとりあえずこういうものだ
という理解で良いと思います。補足しますとリスト2-2 の場合はHTTP1.1 に従ったプロトコル
であるという意味です。それぞれのヘッダについては、表2-1 にまとめておきました。
これも具体例をお見せした方が理解しやすいと思いますので、リスト2-3 に先ほど実験をし
たインテルのメディアサーバデバイスが発行するSSDP データの例を示しておきます。、
UPnP 入門
- 140 -
3-5-3 CMooDevice の実装
ここからはUPnP デバイスとしてのプログラミングとなります。UPnP デバイスの動作を
VisualC++で実装するとなりますと、デバイスとしての制御を行うデバイスクラスとサービス
の制御を行うサービスクラスの2 つのクラスにについて実装する必要があります。
まずはデバイスの制御を行うクラスの実装を行います。本書の場合ですとCMooDevice クラ
スがこれに相当します。実装する必要のある関数は以下の通りです。
 コンストラクタ
 デストラクタ
 イニシャライズ(IUPnPDeviceControl で定義)
 サービスオブジェクト取得(IUPnPDeviceControl で定義)
最初にヘッダクラスを修正します。リスト3-9 のように修正します。
public:
//ここはコメントアウトします CMooDevice()
//{
//}
CMooDevice(); // コンストラクタの宣言を追加
virtual ~CMooDevice(); // デストラクタの宣言を追加
――(略)――
// IUPnPDeviceControl Methods
public:
//このように関数定義のみとする
STDMETHOD(Initialize)(BSTR bstrXMLDesc, BSTR bstrDeviceIdentifier, BSTR bstrInitString);
STDMETHOD(GetServiceObject)(BSTR bstrUDN, BSTR bstrServiceID, LPDISPATCH * ppdispService);
private: // 以下のメンバ変数を独自に追加
BSTR m_bstrUDNMooDeviceXML; // MooDevice.xml で定義されたデバイスのUDN
BSTR m_bstrUDNByDeviceHost; // GetUniqueDeviceName 関数でUPnPhost が作成したUDN
BSTR m_bstrServiceID; // MooDevice.xml で定義されたサービスID
IDispatch* pIMooServiceDispatch;// MooDevice 用のIDispatch のポインタ
};
リスト3-9 MooDevice.h の修正
関数の実体を .cpp に記述しますので、.h では宣言だけとします。また、.cpp で使う独自
の変数についての宣言もしています。
第3章 UPnP デバイスの実装
- 141 -
次はいよいよ実際のソースコードとなります。リスト3-10 のように記述します。
// MooDevice.cpp : CMooDevice の実装
#include "stdafx.h"
#include "MooDevice.h"
#include "MooService.h" // これを追加しておく
// CMooDevice
CMooDevice:: CMooDevice()
{
OutputDebugString(TEXT("CMooDevice::CMooDevice simple ¥n"));
// 各変数の初期化
// 以下2つはXML ファイルの定義をそのまま使うこと
m_bstrUDNMooDeviceXML = SysAllocString(L"RootDevice");
m_bstrServiceID=
SysAllocString(L"urn:booklabo-com:serviceId:X_MooService1.0");
m_bstrUDNByDeviceHost = NULL;
pIMooServiceDispatch = NULL;
}
CMooDevice::~CMooDevice()
{
OutputDebugString(TEXT("CMooDevice::~CMooDevice¥n"));
//リソースの解放処理
if (pIMooServiceDispatch != NULL)
{
pIMooServiceDispatch->Release();
pIMooServiceDispatch=NULL;
}
SysFreeString(m_bstrUDNMooDeviceXML);
SysFreeString(m_bstrServiceID);
}
STDMETHODIMP CMooDevice::Initialize
(BSTR bstrXMLDesc,BSTR deviceID,BSTR bstrInitString)
{
HRESULT hResult = S_OK;
HANDLE fHandle = NULL;
IUPnPRegistrar *pIUPnPRegistrar = NULL;
CComObject *pMooService = NULL;
// UPnP デバイスとしての初期化
// UPnP ホストコンポーネントから呼び出される。

No comments: