DLNA에 대해서 좀 알아 보려고 했더니만 뜬금없는 uPNP가 나오네??? DLNA가 uPNP에서 파생되었다고 하는데...어쩐지 miniDLNA소스를 봐도 uPNP 밖에 안 나온다… 그래서 uPNP에 대해서 먼저 학습을 하고 DLNA로 넘어가야 겠다.
uPNP
Universal Plug and Play 로 마이크로소프트사에 의해 제안된 기술이란다. PnP랑 이름이 같길래, 난 그건줄 알았더니 거의 유사하다. PC에 연결해서 주변기기를 알아서 등록, 재생 하는 그 기술의 확장판이랄까?? 요건 네트워크에 딱 등록되면 네트워크 연동해서 똭!!! 사용이 가능 하게 해주는 기술이랄까???
여튼, 요즘같이 스마트 시대에 아주 적당한 기술이라 할 수 있겠다. 프린트, 라디오, 비디오, 스마트폰이 네트워크로 연결되서 서로 사용이 가능 하다면 얼마나 편하겠나~~~ 좋은 세상이야..
uPNP는 TCP/IP, SSDP, SOAP, GENA, HTTP, XML같은 통신 표준과 기술을 바탕으로 한다고 한다.
TCP/IP는 알겠는데 SSDP, SOAP, GENA는 또 뭐냐??? 점점 꼬리에 꼬리를 물고 알아야 할게 늘어난다 ㅡㅡ;;;
SSDP
Simple Service Discovery Protocol로 네트워크상 장치들을 찾기 위한 프로토콜. |
이라는데, 이게 뭔 소린지…흠..그냥 프로토콜 인데(?)
네트워크 상에서 1900 포트로 브로드캐스트 를 하면 같이 연결된 장치들이 그에 응답하여 서로 장치의 IP주소를 획득. 이렇게 해서 서로 같은 네트워크 상에서 장치를 인식하게 해주는 프로토콜(?) 인가 보다.
SOAP
Simple Object Access Protocol로 HTTP, HTTPS, SMTP등을 사용하여 XML 기반의 메시지를 컴퓨터 네트워크 상에서 교환하는 형태의 프로토콜이다. |
요건 모.. 그냥 XML 데이터를 HTTP, HTTPS, SMTP 프로토콜로 서로 전송, 수신 한다는 말이고…
GENA
General Event Notification Architecture는 이벤트를 HTTP로 송.수신 한다. |
뭔말인지… 그냥 이벤트를 HTTP를 통해서 전달한다는 말이겠지… 이벤트 전용 프로토콜인건가??
정리하믄 SSDP로 각 장치를 찾고, SOAP으로 데이터를 송수신 하고 GENA로 이벤트를 송수신 한다는 말인건가?
uPNP는 검색, 서술???(Description), 제어, 이벤트?(Eventing), 프리젠테이션 요런 단계로 나뉘어 진단다..
검색
Control Point 라는 놈(장치를 제어하는 놈)이 동일 네트워크 상에 장치(서비스 하는 기기)를 검색할 때 사용하나 보다. (사용할려면 어떤놈들이 있는지 부터 알아야 하니… ㅋㅋㅋ) 근데 Control Point 놈만 이걸 보내는 게 아니라, 장치 들도 네트워에 연결되면 알아서 ㅋ “나 여기 있어요~~” 라고 통지 메시지를 보낸다고 한다. 제법 기특해!~
Control Point는 M-SEARCH 메시지를 보내는데 “이 네트워크 있는 기기 들 있으면 모두 손!!!” 과 같다고 봐야 할 것 같다. 손 들라고 했으니 이 메시지를 수신 한 기기들은 Control Point로 응답 메시지(“저 여기 있어요~~~”)를 보낸다.
M-SEARCH * HTTP/1.1 HOST: 239.255.255.255:1900 MAN: “ssdp:discover” MX: 30 ST: ssdp:all
M-SEARCH * HTTP/1.1 : HOST: 239.255.255.255:1900 uPNP에서 약속된 브로드캐스팅 IP와 포트 요건 안 바뀐다. |
Control Point는 요런 형태로 네트워크 상에 있는 기기를 찾는다고 메시지를 보낸다.
HTTP/1.1 200 OK CACHE-CONTROL: max-age=100 DATE: Tue, 18 Jun 2013 03:05:18 GMT EXT: LOCATION: http://192.168.10.100:8080/api/test.xml SERVER: Linux/2.6.18 UPnP/1.0 Test Device/2.0 ST: ssdp:all USN:
|
그러면 각 장치들은 요렇게 메시지를 만들어서 Control Point에 응답한다.
위에서 장치들이 네트워크에 연결이 되면 알.아.서 본인들이 통지 메시지를 보낼 수도 있다고 했다.
NOTIFY * HTTP/1.1 HOST: 239.255.255.250:1900 CACHE-CONTROL: max-age=100 LOCATION: http://192.168.10.100:8080/api/test/xml NT: upnp:rootdevice NTS: ssdp:alive SERVER: Linux/2.6.18 UPnp/1.0 Test Device/2.0 USN: ~~~
|
그래, “나 여기 있어요” 라고 보내는 참으로 기특하다. 근데 네트워크에서 제거 될 때도 알아서 통지 메시지를 보낸다.
NOTIFY * HTTP/1.1 HOST: 239.255.255.250:1900 NT: upnp:rootdevice NTS: ssdp:byebye USN: ~~~
|
서술? 설명? (Description)
Control Point 가 이제 네트워크 상에서 장치들이 어디(IP)에 있는지 알았다. 근데 이놈들이 정확히 어떤 놈들인지에 대한 확실한 정보는 없다. 그래서 검색 시에 장치들이 응답한 데이터 중 LOCATION 위치에 있는 정보(UTF-8 로 인코딩 되어 있단다)를 요청한다. 그냥 HTTP 프로토콜 GET 이다.
근데 이게 ㅡㅡ;;; XML 로 많은 내용이 있다.
<?xml version="1.0"?> <root xmlns="urn:schemas-upnp-org:device-1-0"> <specVersion> <major>1</major> <minor>0</minor> </specVersion> <URLBase>base URL for all relative URLs</URLBase> <device> <deviceType>urn:schemas-upnp-org:device:deviceType:v</deviceType> <friendlyName>short user-friendly title</friendlyName> <manufacturer>manufacturer name</manufacturer> <manufacturerURL>URL to manufacturer site</manufacturerURL> <modelDescription>long user-friendly title</modelDescription> <modelName>model name</modelName> <modelNumber>model number</modelNumber> <modelURL>URL to model site</modelURL> <serialNumber>manufacturer's serial number</serialNumber> <UDN>uuid:UUID</UDN> <UPC>Universal Product Code</UPC> <iconList> <icon> <mimetype>image/format</mimetype> <width>horizontal pixels</width> <height>vertical pixels</height> <depth>color depth</depth> <url>URL to icon</url> </icon> XML to declare other icons, if any, go here </iconList> <serviceList> <service> <serviceType>urn:schemas-upnp-org:service:serviceType:v</serviceType> <serviceId>urn:upnp-org:serviceId:serviceID</serviceId> <SCPDURL>URL to service description</SCPDURL> <controlURL>URL for control</controlURL> <eventSubURL>URL for eventing</eventSubURL> </service> Declarations for other services defined by a UPnP Forum working committee (if any) go here Declarations for other services added by UPnP vendor (if any) go here </serviceList> <deviceList> Description of embedded devices defined by a UPnP Forum working committee (if any) go here Description of embedded devices added by UPnP vendor (if any) go here </deviceList> <presentationURL>URL for presentation</presentationURL> </device> </root> |
복잡하다… ㅡㅡ;; 이제 각 속성들을 살펴 봐야 겠다.
root | xmlns | ”run:schemas-upnp-org:device-1-0 같이 xmlns이 반드시 있어야 한단다. |
specVersion | major, minor | major , minor 버전. major 는 반드시 1이어야 한다고 하네? |
URLBase | Optional. | |
device | 장치 | |
deviceType | 장치 타입이라는데 “urn:schemas-upnp-org:device:” 로 시작해야 한다고 한다. 타입이 뭔지 모르겠다. devicetype:v 이렇게 있는데 v는 버전 정보란다. | |
friendlyName | 그냥, 최종 사용자를 위한 짧은 이름? | |
manufacturer | 제조사 | |
manufacturerURL | 제조사 URL | |
modelDescription | 모델 설명 | |
modelName | 모델 이름 | |
modelNumber | 모델 넘버 | |
modelURL | 모델 웹 사이트. | |
serialNumber | 시리얼 넘버 | |
UDN | 유일한 장치 이름. 장치 식별자. | |
UPC | 제품 코드 | |
iconList | 장치에서 사용하는 아이콘 리스트 | |
icon | Control point UI에서 표시될 아이콘 | |
mimetype | 아이콘 MIME TYPE “image/png”. | |
width | 가로 | |
height | 세로 | |
depth | depth | |
url | 아이콘 이미지 파일일 있는 URL 주소 | |
serviceList | 장치에서 제공하는 서비스들(?)^^ | |
service | 무슨 서비스를 할 것인가를 설명한 건가?? 참 어려다잉. | |
serviceType | 말 그대로 서비스 타입. “urn:schemas-upnp-org:service:”로 시작 되어야 한다고 한다. devicetype처럼 servicetype:버전 이렇게 설정한다. | |
serviceId | 서비스 식별자. “urn:upnp-org:serviceId:serviceID” 요렇게 설정. | |
SPCDURL | 서비스 설명을 위한 URL | |
controlURL | 컨트롤을 위한 URL | |
eventSubURL | 이벤팅을 위한 URL | |
devicelist | 장치 안에 장치가 또 있나 보다. 또 디바이스 리스트. | |
presentationURL | presentation을 위한 URL |
휴 많다… 이제까지 root device라는 용어가 나오는데 root device가 메인 장비?? 장치를 말하나 보다. 그 장치안에 또 장치가 있는 모양. ㅎㅎㅎ
이제, 장치에 대한 정보를 알았으니, 장치가 가지고 있는 서비스 정보에 대해서 알아야 한다. 요게 장치에서 제공하는 서비스의 액션, 변수, 데이터, 범위, 이벤트등의 정보를 가지고 있다고 한다. 그러니까 장치를 제어 하기 위해 필요한 정보 모음집으로 봐야 하나?? 하~~ 망할 영어…
Control Point는 장치 기술, 설명(description)을 HTTP GET으로 요청하고 다시 서비스 Description을 요청(HTTP GET)한단다.
<?xml version="1.0"?> <scpd xmlns="urn:schemas-upnp-org:service-1-0"> <specVersion> <major>1</major> <minor>0</minor> </specVersion> <actionList> <action> <name>actionName</name> <argumentList> <argument> <name>formalParameterName</name> <direction>in xor out</direction> <retval /> <relatedStateVariable>stateVariableName</relatedStateVariable> </argument> Declarations for other arguments defined by UPnP Forum working committee (if any) go here </argumentList> </action> Declarations for other actions defined by UPnP Forum working committee (if any) go here Declarations for other actions added by UPnP vendor (if any) go here </actionList> <serviceStateTable> <stateVariable sendEvents="yes"> <name>variableName</name> <dataType>variable data type</dataType> <defaultValue>default value</defaultValue> <allowedValueList> <allowedValue>enumerated value</allowedValue> Other allowed values defined by UPnP Forum working committee (if any) go here </allowedValueList> </stateVariable> <stateVariable sendEvents="yes"> <name>variableName</name> <dataType>variable data type</dataType> <defaultValue>default value</defaultValue> <allowedValueRange> <minimum>minimum value</minimum> <maximum>maximum value</maximum> <step>increment value</step> </allowedValueRange> </stateVariable> Declarations for other state variables defined by UPnP Forum working committee (if any) go here Declarations for other state variables added by UPnP vendor (if any) go here </serviceStateTable> </scpd> |
요놈도 장난이 아니다. 그냥 하나 하나 뜯어서 살펴 볼려니, 심신이 괴롭다. 아니 정확히 머리가 아프다..
scpd | 반드시 urn:schemas-upnp-org:service-1-0으로 시작해야 한단다. | |
specVersion | major, minor | major, minor 버전 정보. major는 반드시 1이어야 한단다. |
actionList | 액션(?) 리스트? | |
action | name | 액션 이름. 동작 함수 인듯. |
argumentList | 액션이 함수라면 인자도 있겠지~~ 그 인자 리스트 정의. | |
argument | name | 인자 이름. |
direction | 인자가 IN 타입인지 OUT 타입인지를 말하나 보다. IN, OUT 개념도 있네..흠. | |
retval | 액션 리턴 값. | |
relatedStateVariable | 액션 내부에서 사용할 StateVariable 이름??? 아직 모르겠다. | |
serviceStateTable | 변수 테이블? | |
stateVariable | name | 변수 이름 |
dateType | 데이터 타입 | |
defaultValue | 기본 값 | |
allowedValueList | allowedValue. | 문자열에서 쓰나 본데 모르겠다. |
allowValueRange | minimum, maximum,step | 변수값에 최소, 최대 값 정의. |
휴~ 요렇게 해서 Description 마쳤다.
Control Point는 장치를 제어 하기 위한 정보를 Description을 통해서 다 얻었다. 이제 장치를 제어해 봐야 겠지~~
제어
장치의 제어는 서비스 Description에서 얻은 액션이름(함수명??)으로 가능하단다. 근데 위에서 언급했듯이 SOAP이라는 놈으로 구성되어 있다.(아~~ 망할…)
POST path of control URL HTTP/1.1 HOST: host of control URL:port of control URL CONTENT-LENGTH: bytes in body CONTENT-TYPE: text/xml; charset="utf-8" SOAPACTION: "urn:schemas-upnp-org:service:serviceType:v#actionName" ---------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:actionName xmlns:u="urn:schemas-upnp-org:service:serviceType:v"> <argumentName>in arg value</argumentName> other in args and their values go here, if any </u:actionName> </s:Body> </s:Envelope> |
장치 제어는 HTTP 헤더와 body 요렇게 두 부분으로 구성되어 있다.
POST control URL HTTP/1.1 | 장치 Description에서 설정된 control URL. |
HOST | IP 주소, 도메인. |
CONTENT-LENGTH | body 크기 |
CONTENT-TYPE | text/xml; charset=”utf-8” 로 사용하란다. |
SOAPACTION | urn:schemas-upnp-org:service:serviceType:번호#액션이름 이렇게 사용하란다. 뭔말인건지.. 제어할 액션이름. |
헤더는 이렇고 body는…
Envelope | 이건 그대로 쓰면 되겠다. | |
body | 제어 부분 | |
actionName | 제어할 액션 이름을 쓴다.
xmlns:u=”urn:schemas-upnp-org:service:serviceType:v” 요건 모르겠다. 아놔 환장하겠네.. |
|
argumentName | 인자 이름. 인자 이름을 쓰고 해당 인자에 값을 표기. |
근데 이렇게 장치로 POST 했는데 “405 Method Not allowed” 라는 메시지를 리턴 받으면 다시 M-POST로 메시지를 보내야 한다고 하네? 뭐이리 복잡해.
M-POST path of control URL HTTP/1.1 HOST: host of control URL:port of control URL CONTENT-LENGTH: bytes in body CONTENT-TYPE: text/xml; charset="utf-8" MAN: "http://schemas.xmlsoap.org/soap/envelope/"; ns=01 01-SOAPACTION: "urn:schemas-upnp-org:service:serviceType:v#actionName" |
자.. 이제 제어 명령을 보냈으니, 장치가 응답을 보내겠지. 주는게 있으니 받는것도 있는 법이니까..
HTTP/1.1 200 OK CONTENT-LENGTH: bytes in body CONTENT-TYPE: text/xml; charset="utf-8" DATE: when response was generated EXT: SERVER: OS/version UPnP/1.0 product/version --------- 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> other out args and their values go here, if any </u:actionNameResponse> </s:Body> </s:Envelope> |
여기서 actionNameResponse는 actionName + Response 가 더해서 만들어진 단어인가 보다. 그렇다고 하니 그렇겠지.
제어는 대충 이런식인가 보다. 액션을 호출 하는 것만 알아 볼련다. 각 변수값들도 요청하는 게 있나 본데 솔직히 귀찮다. DLNA 수정해 보려다 uPNP때문에 미치겠다. 그래서 더 미치기 전에 간단하게 넘어 갈련다.
이벤트
Control Point가 장치의 서비스 변수의 상태가 변경이 되었을 때 통지 받고자 하면 이벤트를 요청한다고 한다. 장치 서비스는 변수의 값이 변경이 될 때마다 Control Point에게 이 값을 전달 하는게 이벤트 라고 한다.
Subscriber, publisher 뭐 이런놈들이 있는데 이건 그냥 무시하겠다… 깊게는 들어가지는 들어가지 말아야지^^
그럼 Control Point가 장치에게 이벤트 요청 메시지를 어떻게 보내냐면..
SUBSCRIBE publisher path HTTP/1.1 HOST: publisher host:publisher port CALLBACK: <delivery URL> NT: upnp:event TIMEOUT: Second-requested subscription duration |
이렇게 보낸단다.
SUBSCRIBE publisher path HTTP/1.1 | SUBSCRIBE 명령에 장비 Description에서 설정되었던 이벤트 URL 을 설정. |
HOST | 장치 IP, 포트 |
CALLBACK | 이벤트를 전달받을 URL로 설정. 이때 이 URL은 여러개가 될 수 있다. 이벤트 메시지를 보낼곳들을 설정한다. |
NT | upnp:event |
TIMEOUT | 이벤트 발생시 한번 보내고 끝내는게 아닌가 보다. 이 timeout 값에 의해 보내는 시간이 결정된단다. Second-XX 이렇게 설정하던지 아니면 infinite 무한 설정 이렇게 한단다. |
이벤트 설정? 메시지 수신 후 장치는 응답 메시지를 보낸다. 뭐~ 잘 받았다는 메시지 겠지..
HTTP/1.1 200 OK DATE: when response was generated SERVER: OS/version UPnP/1.0 product/version SID: uuid:subscription-UUID TIMEOUT: Second-actual subscription duration |
이 메시지중 SID 이 필드값 이건 아마도 이벤트 요청을 한 Control Point의 식별자를 장치가 하나 발급하나 보다. 이 SID 필드 값으로 관리하는듯… Control Point가 이 메시지를 수신 후 SID 값을 저장해 놔야 하나 보다.. 왜? 그건 renewal 메시지에서 사용하니까~~
SUBSCRIBE publisher path HTTP/1.1 HOST: publisher host:publisher port SID: uuid:subscription UUID TIMEOUT: Second-requested subscription duration |
renewal 메시지는 이벤트 요청 메시지랑 명령은 같다. 다만 NT와 CALLBACK만 빠져 있다. 아~ SID 가 추가 되어 있다. 그럼 renewal은 뭐냐?? 단순히 메세지만 봐서는 TIMEOUT 값만 다시 변경 할 때 사용하나 보다. 추가된 SID는 장치에서 송신한 SID 필드값이겠지?? ㅋ 그러므로 Control Point도 SID값을 저장해 놔야 하는듯.
이벤트를 보내 달라고 했으니 보내지 말라는 메시지도 있겠지? 당연히~~ 있네…
UNSUBSCRIBE publisher path HTTP/1.1 HOST: publisher host:publisher port SID: uuid:subscription UUID |
이렇게 보내면 장치는 이벤트 메시지를 보내지 않는다고 한다.
이벤트를 요청하고 갱신?하고 이벤트 중지 하는 메시지 까지 했으니 이제 실제 이벤트 발생시 보내지는 메시지만 남았다.
NOTIFY delivery path HTTP/1.1 HOST: delivery host:delivery port CONTENT-TYPE: text/xml CONTENT-LENGTH: Bytes in body NT: upnp:event NTS: upnp:propchange SID: uuid:subscription-UUID SEQ: event key ---------- 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> |
생김새는 제어 쪽에서 본 메시지랑 비슷하다.
NOTIFY delivery path HTTP/1.1 | NOTIFY 요건 통지 관련 메시지다는 의미일테고 delivery path는 이벤트 요청시 설정한 CALLBACK url이란다. | |
CONTENT-TYPE | text/xml | |
CONTENT-LENGTH | body 크기 | |
NT | upnp:event | |
NTS | upnp:propchange | |
SID | SID | |
SEQ | 0에서 시작해서 1씩 증가한다고 한다. | |
propertyset | urn:schemas-upnp-org:event-1-0. 이렇게 써주고. | |
property | variableName | variableName변수의 변경된 값. |
이벤트 메시지를 받았으니 메시지 잘 받았다고 응답 보내줘야지?
HTTP/1.1 200 OK |
휴~~~
이 이벤트를 끝으로 uPNP는 그만 볼련다. DLNA를 시작으로 uPNP까지 머리도 터지겠고 보기도 싫다. 이거 뭐 되지도 않는 영어 문서 붙잡고.. 하나 하나 볼려니 오역80%에 개념 상실 20%.
그래도 uPNP 어느정도 개념은 잡았으니 miniDLNA 소스 코드는 어느정도 분석은 가능하겠군.. 근데 DLNA 프로토콜도 찾아서 봐야 하는데. 이 정도라면 그만 둘까 라는 생각이 든다.
참고문서:
http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0.pdf
'프로그래밍 > C | C++' 카테고리의 다른 글
FFMPEG 디코딩 API 사용법 (1) | 2013.08.16 |
---|---|
클래스 private, protected, public 멤버 및 상속 (0) | 2013.08.14 |
클래스 가상함수, 순수가상함수 (0) | 2013.08.14 |
윈도우 malloc (0) | 2013.08.14 |
RTPLIB 1.0b 라이브러리 예제 (0) | 2013.08.14 |