2024년 5월 28일 화요일

UPnP 용어 정리

용어 정리


https://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0.pdf

https://openconnectivity.org/upnp-specs/UPnP-arch-DeviceArchitecture-v1.1.pdf

https://openconnectivity.org/upnp-specs/UPnP-arch-DeviceArchitecture-v2.0-20200417.pdf


UPnP

Univeral Plug & Play

USN

Unique Service Name

UDN

Unique Device Name

NT

Notification Type

NTS

Notification Sub Type


ARP

Address Resolution Protocol

https://datatracker.ietf.org/doc/html/rfc826

CP

Control Point

DCP

Device Control Protocol

DDD

Device Description Document

DHCP

Dynamic Host Configuration Protocol

https://datatracker.ietf.org/doc/html/rfc2131

DNS

Domain Name System

https://datatracker.ietf.org/doc/html/rfc1034

https://datatracker.ietf.org/doc/html/rfc1035

GENA

General Event Notification Architecture

https://www.ietf.org/archive/id/draft-cohen-gena-client-00.txt

HTML

Hypertext Markup Language

https://datatracker.ietf.org/doc/html/rfc2616

HTTP

Hypertext Transfer Protocol

https://datatracker.ietf.org/doc/html/rfc2616

SCPD

Service Control Protocol Description

SOAP

Simple Object Access Protocol

https://www.w3.org/TR/soap/

SSDP

Simple Service Discovery Protocol

UDA

UPnP Device Arhictecture

UPC

Universal Product Code

URI

Uniform Resource Identifier

https://datatracker.ietf.org/doc/html/rfc3986

URL

Uniform Resource Locator

https://datatracker.ietf.org/doc/html/rfc1738

URN

Uniform Resource Name

https://datatracker.ietf.org/doc/html/rfc1737

https://datatracker.ietf.org/doc/html/rfc2141

UUID

Universal Unique Identifier

https://datatracker.ietf.org/doc/html/rfc9562

XML

Extensible Markup Language

https://www.w3.org/TR/2008/REC-xml-20081126/



2018년 10월 6일 토요일

UPnP 개발자 도구

UPnP 개발자 도구


윈도 UPnP Tools

http://www.meshcommander.com/upnptools


유용한 툴
  • Device Sniffer (SSDP monitor)
  • Device Spy (Control Point)
  • Network Light (UPnP Device)

 

위 다운로드 링크가 고장난 것으로 보임

https://github.com/jeremypoulter/DeveloperToolsForUPnP 

소스를 받아 visual studio 로 빌드 가능


e.g.)

> git clone git@github.com:jeremypoulter/DeveloperToolsForUPnP.git

> cd DeveloperToolsForUPnP\Tools

> DeveloperTools.sln


0.0.69 바이너리 다운로드

https://github.com/bjtj/DeveloperToolsForUPnP/releases/tag/0.0.69

 


Android - UPnP Tools

Play store

SOAP


SOAP requset 예



Service type
urn:schemas-upnp-org:service:ContentDirectory:1

Action name
GetSystemUpdateID

HTTP header

SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#GetSystemUpdateID"

XML
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetSystemUpdateID xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1"/>
</s:Body>
</s:Envelope>


SOAP response 예


HTTP header
HTTP/1.1 200  OK
CONTENT-TYPE:  text/xml; charset="utf-8"
EXT: 
SERVER:  UPnP/1.0 DLNADOC/1.50 Platinum/1.0.5.13
Content-Length: 328


XML
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetSystemUpdateIDResponse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
<Id>76941487</Id>
</u:GetSystemUpdateIDResponse>
</s:Body>
</s:Envelope>



2018년 4월 27일 금요일

uuid - C언어

UUID


설치


$ sudo apt install uuid-dev

sample code


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uuid/uuid.h>

int main(int argc, char *argv[])
{
    char uuid_str[37];
    uuid_t uuid;
    uuid_generate_time_safe(uuid);
    uuid_unparse_lower(uuid, uuid_str);
    printf("uuid: %s\n", uuid_str);
   
    return 0;
}


Build


$ gcc -o gen main.c `pkg-config --cflags --libs uuid`

실행


$ ./gen
uuid: 1b4e28ba-2fa1-11d2-883f-0016d3cca427



xml - libxml

xml - libxml


http://xmlsoft.org/

설치


$ sudo apt install libxml2-dev


sample code



#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libxml/parser.h>


static void s_print_attributes(xmlNode * node)
{
    xmlAttr * props = node->properties;
    xmlNode * attr;
    if (props == NULL) {
        return;
    }
    printf("{");
    for (; props; props = props->next) {
        if (props->prev) {
            printf(" ");
        }
        printf("%s: %s", props->name, props->xmlChildrenNode->content);
    }
    printf("}");
}


static void s_print_first_child(xmlNode * node, const char * prefix)
{
    xmlNode * first = node->xmlChildrenNode;
    if (!first || first->next) {
        return;
    }

    printf("%s", prefix);
    printf("Content: '%s'\n", first->content);
}

static void s_print_child_elements(xmlNode * node, const char * prefix)
{
    xmlNode * child;
    for (child = node->xmlChildrenNode; child; child = child->next) {
        if (child->type == XML_ELEMENT_NODE) {
            char prefix_[10] = {0,};
            snprintf(prefix_, sizeof(prefix_), "  %s", prefix);
            printf("%s", prefix);
            printf("Name: %s ", child->name);
            s_print_attributes(child);
            printf("\n");
            s_print_first_child(child, prefix_);
            s_print_child_elements(child, prefix_);
        }
    }
}


int main(int argc, char *argv[])
{
    LIBXML_TEST_VERSION
    xmlDoc * doc;
    xmlNode * root;
    xmlNode * cur_node = NULL;

    if (argc < 2) {
        fprintf(stderr, "usage: %s <xml path>\n", argv[0]);
        exit(1);
    }
   
    doc = xmlReadFile(argv[1], NULL, 0);
    if (doc == NULL) {
        fprintf(stderr, "xmlReadFile() failed\n");
        exit(1);
    }

    root = xmlDocGetRootElement(doc);
    s_print_child_elements(root, "");
   
    xmlFreeDoc(doc);
    xmlCleanupParser();
    xmlMemoryDump();
    return 0;
}


빌드


$ gcc -o parse main.c `pkg-config --cflags --libs libxml-2.0`

light.xml


<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
  <specVersion>
    <major>1</major>
    <minor>0</minor>
  </specVersion>
  <device>
    <deviceType>urn:schemas-upnp-org:device:BinaryLight:0.9</deviceType>
    <friendlyName>Living Room</friendlyName>
    <manufacturer>My company</manufacturer>
    <manufacturerURL>URL to manufacturer site</manufacturerURL>
    <modelDescription>Remote Light Control</modelDescription>
    <modelName>Light</modelName>
    <modelNumber>0001</modelNumber>
    <modelURL>URL to model site</modelURL>
    <serialNumber>SN0001</serialNumber>
    <UDN>uuid:UUID</UDN>
    <serviceList>
      <service>
        <serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType>
        <serviceId>urn:upnp-org:serviceId:SwitchPower:1</serviceId>
        <SCPDURL>/switchpower.xml</SCPDURL>
        <controlURL>URL for control</controlURL>
        <eventSubURL>URL for eventing</eventSubURL>
      </service>
    </serviceList>
  </device>
</root>



실행


$ ./parse light.xml
Name: specVersion
  Name: major
    Content: '1'
  Name: minor
    Content: '0'
Name: device
  Name: deviceType
    Content: 'urn:schemas-upnp-org:device:BinaryLight:0.9'
  Name: friendlyName
    Content: 'Living Room'
  Name: manufacturer
    Content: 'My company'
  Name: manufacturerURL
    Content: 'URL to manufacturer site'
  Name: modelDescription
    Content: 'Remote Light Control'
  Name: modelName
    Content: 'Light'
  Name: modelNumber
    Content: '0001'
  Name: modelURL
    Content: 'URL to model site'
  Name: serialNumber
    Content: 'SN0001'
  Name: UDN
    Content: 'uuid:UUID'
  Name: serviceList
    Name: service
      Name: serviceType
        Content: 'urn:schemas-upnp-org:service:SwitchPower:1'
      Name: serviceId
        Content: 'urn:upnp-org:serviceId:SwitchPower:1'
      Name: SCPDURL
        Content: '/switchpower.xml'
      Name: controlURL
        Content: 'URL for control'
      Name: eventSubURL
        Content: 'URL for eventing'


switchpower.xml


<?xml version="1.0"?>
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
  <specVersion>
    <major>1</major>
    <minor>0</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>


실행


$ ./parse switchpower.xml
Name: specVersion
  Name: major
    Content: '1'
  Name: minor
    Content: '0'
Name: actionList
  Name: action
    Name: name
      Content: 'SetTarget'
    Name: argumentList
      Name: argument
        Name: name
         Content: 'newTargetValue'
        Name: relatedStateVariable
         Content: 'Target'
        Name: direction
         Content: 'in'
  Name: action
    Name: name
      Content: 'GetTarget'
    Name: argumentList
      Name: argument
        Name: name
         Content: 'RetTargetValue'
        Name: relatedStateVariable
         Content: 'Target'
        Name: direction
         Content: 'out'
  Name: action
    Name: name
      Content: 'GetStatus'
    Name: argumentList
      Name: argument
        Name: name
         Content: 'ResultStatus'
        Name: relatedStateVariable
         Content: 'Status'
        Name: direction
         Content: 'out'
Name: serviceStateTable
  Name: stateVariable {sendEvents: no}
    Name: name
      Content: 'Target'
    Name: dataType
      Content: 'boolean'
    Name: defaultValue
      Content: '0'
  Name: stateVariable {sendEvents: yes}
    Name: name
      Content: 'Status'
    Name: dataType
      Content: 'boolean'
    Name: defaultValue
      Content: '0'



2018년 4월 23일 월요일

http client - libcurl

http client - libcurl


참고:

Http get sample

  • http get
  • 응답 데이터를 .out 파일로 저장

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>


static size_t cb_write(void * contents, size_t size, size_t nmemb, void * userp)
{
    FILE * fp = (FILE*)userp;
    fwrite(contents, size, nmemb, fp);
    return size * nmemb;
}

static void dumpfile(const char * path);

int main(int argc, char *argv[])
{
    FILE * out;
    CURLcode res;
    CURL * curl;

    curl_global_init(CURL_GLOBAL_ALL);

    curl = curl_easy_init();
    if (!curl) {
        printf("curl_easy_init() failed\n");
        exit(1);
    }

    out = fopen(".out", "wb");
    if (!out) {
        printf("fopen() failed\n");
        exit(1);
    }

    curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/get");
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb_write);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)out);
    res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        fclose(out);
        printf("curl_easy_perform() failed\n");
        exit(1);
    }
    fclose(out);

    dumpfile(".out");

    curl_easy_cleanup(curl);

    curl_global_cleanup();

    return 0;
}

static void dumpfile(const char * path) {

    int len;
    char buf[1024] = {0,};
    FILE * fp = fopen(path, "rb");
    if (!fp) {
        perror("fopen() failed");
        exit(1);
    }

    while ((len = fread(buf, sizeof(char), sizeof(buf), fp)) > 0) {
        printf("%.*s", len, buf);
    }

    fclose(fp);
}
 


빌드


$ gcc -o httpget main.c `pkg-config --cflags --libs libcurl`

실행


$ ./httpget
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Connection": "close",
    "Host": "httpbin.org"
  },
  "origin": "xx.xx.xx.xx",
  "url": "http://httpbin.org/get"
}



Http post sample


  • http post
  • Content-Type: text/plain


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

static size_t cb_write(void * contents, size_t size, size_t nmemb, void * userp)
{
    FILE * fp = (FILE*)userp;
    fwrite(contents, size, nmemb, fp);
    return size * nmemb;
}

static void dumpfile(const char * path);

int main(int argc, char *argv[])
{
    struct curl_slist * headers = NULL;
    static const char * msg = "hello world";
    FILE * out;
    CURLcode res;
    CURL * curl;

    curl_global_init(CURL_GLOBAL_ALL);

    curl = curl_easy_init();
    if (!curl) {
        printf("curl_easy_init() failed\n");
        exit(1);
    }

    out = fopen(".out", "wb");
    if (!out) {
        printf("fopen() failed\n");
        exit(1);
    }

    headers = curl_slist_append(headers, "Content-Type: text/plain");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

    curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/post");
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_POST, 1L);

    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(msg));
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb_write);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)out);
    res = curl_easy_perform(curl);
    curl_slist_free_all(headers);
    if (res != CURLE_OK) {
        fclose(out);
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        exit(1);
    }
    fclose(out);
    dumpfile(".out");
    curl_easy_cleanup(curl);
    curl_global_cleanup();

    return 0;
}

static void dumpfile(const char * path) {
    int len;
    char buf[1024] = {0,};
    FILE * fp = fopen(path, "rb");
    if (!fp) {
        perror("fopen() failed");
        exit(1);
    }

    while ((len = fread(buf, sizeof(char), sizeof(buf), fp)) > 0) {
        printf("%.*s", len, buf);
    }

    fclose(fp);
}



빌드


$ gcc -o httppost main.c `pkg-config --cflags --libs libcurl`

실행


$ ./httppost
{
  "args": {},
  "data": "hello world",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Connection": "close",
    "Content-Length": "11",
    "Content-Type": "text/plain",
    "Host": "httpbin.org"
  },
  "json": null,
  "origin": "xx.xx.xx.xx",
  "url": "http://httpbin.org/post"
}




2018년 4월 22일 일요일

http server - microhttpd

http server - microhttpd


micro http server



설치


$ brew install libmicrohttpd

sample code


#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define PAGE "<html><head><title>libmicrohttpd demo</title>"\
             "</head><body>libmicrohttpd demo</body></html>"

static int ahc_echo(void * cls,
   struct MHD_Connection * connection,
   const char * url,
   const char * method,
                    const char * version,
   const char * upload_data,
   size_t * upload_data_size,
                    void ** ptr) {
  static int dummy;
  const char * page = cls;
  struct MHD_Response * response;
  int ret;

  if (0 != strcmp(method, "GET"))
    return MHD_NO; /* unexpected method */
  if (&dummy != *ptr)
    {
      /* The first time only the headers are valid,
         do not respond in the first round... */
      *ptr = &dummy;
      return MHD_YES;
    }
  if (0 != *upload_data_size)
    return MHD_NO; /* upload data in a GET!? */
  *ptr = NULL; /* clear context pointer */
  response = MHD_create_response_from_buffer (strlen(page),
                                              (void*) page,
       MHD_RESPMEM_PERSISTENT);
  ret = MHD_queue_response(connection,
  MHD_HTTP_OK,
  response);
  MHD_destroy_response(response);
  return ret;
}

int main(int argc,
char ** argv) {
  struct MHD_Daemon * d;
  if (argc != 2) {
    printf("%s PORT\n",
  argv[0]);
    return 1;
  }
  d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION,
      atoi(argv[1]),
      NULL,
      NULL,
      &ahc_echo,
      PAGE,
      MHD_OPTION_END);
  if (d == NULL)
    return 1;
  (void) getc (stdin);
  MHD_stop_daemon(d);
  return 0;
}

빌드


$ gcc -o server main.c `pkg-config --cflags --libs libmicrohttpd`


UPnP 용어 정리

용어 정리 https://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0.pdf https://openconnectivity.org/upnp-specs/UPnP-arch-DeviceArchitecture...