+++ /dev/null
-//Package discovery wraps main functions of IoTivity/ocstack with golang to use Discovery functions in go project.
-package discovery
-
-/*
-
-#include <ocstack.h>
-#include <octypes.h>
-#include <ocpayload.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <memory.h>
-
-extern void cgo_discoverycallback(OCClientResponse * clientResponse);
-
-static int DuplicateString(char** targetString, const char* sourceString)
-{
- if(!sourceString)
- {
- return false;
- }
- else
- {
- *targetString = (char *) malloc(strlen(sourceString) + 1);
-
- if(*targetString)
- {
- strncpy(*targetString, sourceString, (strlen(sourceString) + 1));
- return true;
- }
- }
- return false;
-}
-
-static void DeletePlatformInfo(OCPlatformInfo *platformInfo)
-{
- free (platformInfo->manufacturerName);
- free (platformInfo->platformID);
- free (platformInfo->manufacturerUrl);
- free (platformInfo->modelNumber);
- free (platformInfo->dateOfManufacture);
- free (platformInfo->platformVersion);
- free (platformInfo->operatingSystemVersion);
- free (platformInfo->hardwareVersion);
- free (platformInfo->firmwareVersion);
- free (platformInfo->supportUrl);
- free (platformInfo->systemTime);
-}
-
-static void DeleteDeviceInfo(OCDeviceInfo *deviceInfo)
-{
- free (deviceInfo->deviceName);
- free (deviceInfo->specVersion);
- OCFreeOCStringLL (deviceInfo->dataModelVersions);
-}
-
-static OCStackResult SetPlatformInfo(const char* platformID, const char *manufacturerName,
- const char *manufacturerUrl, const char *modelNumber, const char *dateOfManufacture,
- const char *platformVersion, const char* operatingSystemVersion, const char* hardwareVersion,
- const char *firmwareVersion, const char* supportUrl, const char* systemTime)
-{
-
- OCPlatformInfo platformInfo;
-
- if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_PLATFORM_NAME_LENGTH))
- {
- return OC_STACK_INVALID_PARAM;
- }
- if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_PLATFORM_URL_LENGTH))
- {
- return OC_STACK_INVALID_PARAM;
- }
- DuplicateString(&platformInfo.platformID, platformID);
- DuplicateString(&platformInfo.manufacturerName, manufacturerName);
- DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl);
- DuplicateString(&platformInfo.modelNumber, modelNumber);
- DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture);
- DuplicateString(&platformInfo.platformVersion, platformVersion);
- DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion);
- DuplicateString(&platformInfo.hardwareVersion, hardwareVersion);
- DuplicateString(&platformInfo.firmwareVersion, firmwareVersion);
- DuplicateString(&platformInfo.supportUrl, supportUrl);
- DuplicateString(&platformInfo.systemTime, systemTime);
-
- int ret;
- ret = OCSetPlatformInfo(platformInfo);
- DeletePlatformInfo(&platformInfo);
- return ret;
-
-}
-
-static OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, const char* dataModelVersions, const char* types)
-{
- OCDeviceInfo deviceInfo;
- DuplicateString(&deviceInfo.deviceName, deviceName);
- DuplicateString(&deviceInfo.specVersion, specVersion);
- OCFreeOCStringLL(deviceInfo.dataModelVersions);
- deviceInfo.dataModelVersions = OCCreateOCStringLL(dataModelVersions);
- OCFreeOCStringLL(deviceInfo.types);
- deviceInfo.types = OCCreateOCStringLL(types);
-
- int ret;
- ret = OCSetDeviceInfo(deviceInfo);
- DeleteDeviceInfo(&deviceInfo);
- return ret;
-}
-
-static OCStackResult cCreateResource(
- void * handle,
- const char * resourceTypeName,
- const char * resourceInterfaceName,
- const char * URI,
- void * entityHandler,
- void * callbackParam,
- uint8_t resourceProperties)
-{
- OCResourceHandle handler;
- handler = (OCResourceHandle *)handle;
- return OCCreateResource(&handler, resourceTypeName, resourceInterfaceName, URI, NULL,NULL, resourceProperties);
-}
-
-
-static OCStackApplicationResult discoverycallback(void *context, OCDoHandle handle, OCClientResponse * clientResponse)
-{
-
- cgo_discoverycallback(clientResponse);
-
- return OC_STACK_KEEP_TRANSACTION;
-}
-
-static OCStackResult cDoResource(void * handle,
- OCMethod method,
- const char * requestURI,
- OCPayload * payload)
-{
- OCCallbackData callbackData;
- callbackData.cb = discoverycallback;
- callbackData.context = handle;
- callbackData.cd = (void*)0;
-
- return OCDoResource((void*)0, method, requestURI, (void*)0, payload, CT_DEFAULT, OC_LOW_QOS, &callbackData, (void*)0, 0);
-}
-
-*/
-import "C"
-
-import (
- "commons/logger"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "os"
- "runtime"
- "strconv"
- "sync"
- "time"
- "unsafe"
-)
-
-//struct copy from OCF--------------------
-type OCMode int
-
-const (
- OC_SERVER OCMode = iota
- OC_CLIENT_SERVER
- OC_GATEWAY
-)
-
-type OCTransportFlags int
-
-const (
- OC_DEFAULT_FLAGS OCTransportFlags = iota
- OC_FLAG_SECURE
- OC_IP_USE_V6
- OC_IP_USE_V4
- OC_MULTICAST
- OC_SCOPE_INTERFACE
- OC_SCOPE_LINK
- OC_SCOPE_REALM
- OC_SCOPE_ADMIN
- OC_SCOPE_SITE
- OC_SCOPE_ORG
- OC_SCOPE_GLOBAL
-)
-
-type OCTransportAdapter int
-
-const (
- OC_DEFAULT_ADAPTER OCTransportAdapter = iota
- OC_ADAPTER_IP
- OC_ADAPTER_GATT_BTLE
- OC_ADAPTER_RFCOMM_BTEDR
- OC_ADAPTER_TCP
- OC_ADAPTER_NFC
-)
-
-type OCPlatformInfo struct {
- PlatformID string
- ManufacturerName string
- ManufacturerURL string
- ModelNumber string
- DateOfManufacture string
- PlatformVersion string
- OperatingSystemVersion string
- HardwareVersion string
- FirmwareVersion string
- SupportURL string
- SystemTime string
-}
-
-type OCDeviceInfo struct {
- DeviceName string
- Types string
- SpecVersion string
- DataModelVersions string
-}
-
-//-------------------- struct copy from OCF
-
-type Attribute struct {
- DataType string
- Values interface{}
-}
-
-type Payload struct {
- URI string
- ResourceTypes []string
- Intfs []string
- Attr map[string]Attribute
-}
-
-type Resource struct {
- URI string
- Types []string
- Interfaces []string
- Port int
- Endpoint string
-}
-
-func newResource() *Resource {
- ret := new(Resource)
- ret.Types = make([]string, 0)
- ret.Interfaces = make([]string, 0)
-
- return ret
-}
-
-func (r Resource) GetURI() string {
- return r.URI
-}
-
-func (r Resource) GetTypes() []string {
- return r.Types
-}
-
-func (r Resource) GetInterfaces() []string {
- return r.Interfaces
-}
-
-func (r Resource) GetEndpoint() string {
- return r.Endpoint
-}
-
-func (r Resource) GetPort() int {
- return r.Port
-}
-
-type response struct {
- resources []Resource
- payload Payload
- wg sync.WaitGroup
-}
-
-func newResponse() *response {
- ret := new(response)
- ret.resources = make([]Resource, 0)
- ret.payload = Payload{}
-
- return ret
-}
-
-type resourcesJSON struct {
- URI string
- Types []string
-}
-
-type edgeJSON struct {
- Port int
- Endpoint string
- Resources []resourcesJSON
-}
-
-func newEdgeJSON() *edgeJSON {
- ret := new(edgeJSON)
- ret.Resources = make([]resourcesJSON, 0)
- return ret
-}
-
-const (
- multicastDiscoveryURL = "coap://224.0.1.187:5683/oic/res"
- DiscoveryOutputJSON = "discoveryOutput.json"
- presenceSecond = 30
-)
-
-type DiscoveryType int
-
-const (
- MULTICAST DiscoveryType = iota
- UNICAST
-)
-
-var mutex = &sync.Mutex{}
-var isExitedProcess chan bool
-var requests map[int32]*response
-
-func init() {
- isExitedProcess = make(chan bool)
- requests = make(map[int32]*response)
-}
-
-//@TODO open default setting or not along with Tizen / LF
-// 이 package의 ocf 인증 없이 디바이스(ex. TV)가 ocf 인증을 받을 수 있는가?
-func getDefaultPlatformInfo() *OCPlatformInfo {
- var platformInfo OCPlatformInfo
- dateOfManufacture := "2016-01-15"
- firmwareVersion := "myFirmwareVersion"
- manufacturerName := "myName"
- operatingSystemVersion := "myOS"
- hardwareVersion := "myHardwareVersion"
- platformID := "0A3E0D6F-DBF5-404E-8719-D6880042463A"
- modelNumber := "myModelNumber"
- platformVersion := "myPlatformVersion"
- systemTime := "2015-05-15T11.04"
-
- platformInfo.DateOfManufacture = dateOfManufacture
- platformInfo.FirmwareVersion = firmwareVersion
- platformInfo.ManufacturerName = manufacturerName
- platformInfo.OperatingSystemVersion = operatingSystemVersion
- platformInfo.HardwareVersion = hardwareVersion
- platformInfo.PlatformID = platformID
- platformInfo.ModelNumber = modelNumber
- platformInfo.PlatformVersion = platformVersion
- platformInfo.SystemTime = systemTime
-
- return &platformInfo
-}
-func getDefaultDeviceInfo() *OCDeviceInfo {
- var deviceInfo OCDeviceInfo
-
- specVersion := "core.1.1.0"
- dataModelVersions := "res.1.1.0,sh.1.1.0"
- deviceName := "myDeviceName"
- types := "oic.d.edge"
-
- deviceInfo.DeviceName = deviceName
- deviceInfo.SpecVersion = specVersion
- deviceInfo.DataModelVersions = dataModelVersions
- deviceInfo.Types = types
-
- return &deviceInfo
-}
-func SetPlatformInfo(platformInfo *OCPlatformInfo) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
-
- cPlatformID := C.CString(platformInfo.PlatformID)
- defer C.free(unsafe.Pointer(cPlatformID))
-
- cManufacturerName := C.CString(platformInfo.ManufacturerName)
- defer C.free(unsafe.Pointer(cManufacturerName))
-
- cManufacturerURL := C.CString(platformInfo.ManufacturerURL)
- defer C.free(unsafe.Pointer(cManufacturerURL))
-
- cModelNumber := C.CString(platformInfo.ModelNumber)
- defer C.free(unsafe.Pointer(cModelNumber))
-
- cDateOfManufacture := C.CString(platformInfo.DateOfManufacture)
- defer C.free(unsafe.Pointer(cDateOfManufacture))
-
- cPlatformVersion := C.CString(platformInfo.PlatformVersion)
- defer C.free(unsafe.Pointer(cPlatformVersion))
-
- cOperatingSystemVersion := C.CString(platformInfo.OperatingSystemVersion)
- defer C.free(unsafe.Pointer(cOperatingSystemVersion))
-
- cHardwareVersion := C.CString(platformInfo.HardwareVersion)
- defer C.free(unsafe.Pointer(cHardwareVersion))
-
- cFirmwareVersion := C.CString(platformInfo.FirmwareVersion)
- defer C.free(unsafe.Pointer(cFirmwareVersion))
-
- cSupportURL := C.CString(platformInfo.SupportURL)
- defer C.free(unsafe.Pointer(cSupportURL))
-
- cSystemTime := C.CString(platformInfo.SystemTime)
- defer C.free(unsafe.Pointer(cSystemTime))
-
- ret := C.SetPlatformInfo(cPlatformID,
- cManufacturerName,
- cManufacturerURL,
- cModelNumber,
- cDateOfManufacture,
- cPlatformVersion,
- cOperatingSystemVersion,
- cHardwareVersion,
- cFirmwareVersion,
- cSupportURL,
- cSystemTime)
- if ret != C.OC_STACK_OK {
- logger.Logging(logger.DEBUG, "ERROR::"+strconv.Itoa(int(ret)))
- }
-}
-
-func SetDeviceInfo(deviceInfo *OCDeviceInfo) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
-
- cDeviceName := C.CString(deviceInfo.DeviceName)
- defer C.free(unsafe.Pointer(cDeviceName))
-
- cSpecVersion := C.CString(deviceInfo.SpecVersion)
- defer C.free(unsafe.Pointer(cSpecVersion))
-
- cDataModelVersions := C.CString(deviceInfo.DataModelVersions)
- defer C.free(unsafe.Pointer(cDataModelVersions))
-
- cTypes := C.CString(deviceInfo.Types)
- defer C.free(unsafe.Pointer(cTypes))
-
- ret := C.SetDeviceInfo(cDeviceName, cSpecVersion, cDataModelVersions, cTypes)
- if ret != C.OC_STACK_OK {
- logger.Logging(logger.DEBUG, "ERROR::"+strconv.Itoa(int(ret)))
- }
-}
-
-func runProcess() {
- go func() {
- for {
- select {
- case <-isExitedProcess:
- break
- default:
- C.OCProcess()
- time.Sleep(100 * time.Millisecond)
- runtime.Gosched()
- }
- }
- }()
-}
-
-//Stop terminates oCProcess goroutine
-func Stop() {
- isExitedProcess <- true
-}
-
-func Init(ipAddr string, port uint16, mode OCMode) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
-
- cipAddr := C.CString(ipAddr)
- defer C.free(unsafe.Pointer(cipAddr))
- cport := C.uint16_t(port)
- cmode := C.OCMode(mode)
-
- ret := C.OCInit(cipAddr, cport, cmode)
- if ret != C.OC_STACK_OK {
- logger.Logging(logger.DEBUG, "ERROR::"+strconv.Itoa(int(ret)))
- }
-}
-
-func Init1(mode OCMode, serverFlags OCTransportFlags, clientFlags OCTransportFlags) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
- cmode := C.OCMode(mode)
- cserverFlags := C.OCTransportFlags(serverFlags)
- cclientFlags := C.OCTransportFlags(clientFlags)
-
- ret := C.OCInit1(cmode, cserverFlags, cclientFlags)
- if ret != C.OC_STACK_OK {
- logger.Logging(logger.DEBUG, "ERROR::"+strconv.Itoa(int(ret)))
- }
-}
-
-func Init2(mode OCMode, serverFlags OCTransportFlags, clientFlags OCTransportFlags, transportType OCTransportAdapter) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
- cmode := C.OCMode(mode)
- cserverFlags := C.OCTransportFlags(serverFlags)
- cclientFlags := C.OCTransportFlags(clientFlags)
- ctransportType := C.OCTransportAdapter(transportType)
-
- ret := C.OCInit2(cmode, cserverFlags, cclientFlags, ctransportType)
- if ret != C.OC_STACK_OK {
- logger.Logging(logger.DEBUG, "ERROR::"+strconv.Itoa(int(ret)))
- }
-}
-
-//Start do server-client init, set device/platform info, run oCProcess
-func Start(platformInfo *OCPlatformInfo, deviceInfo *OCDeviceInfo) {
- Init1(2, 0, 0)
-
- if platformInfo == nil {
- platformInfo = getDefaultPlatformInfo()
- }
- SetPlatformInfo(platformInfo)
- if deviceInfo == nil {
- deviceInfo = getDefaultDeviceInfo()
- }
- SetDeviceInfo(deviceInfo)
-
- C.OCStartPresence(C.uint32_t(presenceSecond))
-
- runProcess()
-}
-
-//Discovery discovers resources via multicast/unicast
-func Discovery(discoveryType DiscoveryType, query string, ips ...string) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
-
- var URI string
-
- switch discoveryType {
- case MULTICAST:
- URI = multicastDiscoveryURL
- logger.Logging(logger.DEBUG, "MULTICAST URI", URI)
-
- if len(query) > 0 {
- URI += "?rt=" + query
- }
- discoveryImpl(URI)
-
- case UNICAST:
- for _, ip := range ips {
- URI = "coap://" + ip + ":5683/oic/res"
- logger.Logging(logger.DEBUG, "UNICAST URI", URI)
-
- if len(query) > 0 {
- URI += "?rt=" + query
- }
- discoveryImpl(URI)
- }
- }
-
-}
-
-func discoveryImpl(URI string) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
-
- cHandle := C.int(0)
-
- cStr := C.CString(URI)
- defer C.free(unsafe.Pointer(cStr))
-
- ret := C.cDoResource(unsafe.Pointer(&cHandle), C.OC_REST_DISCOVER, cStr, nil)
- if ret != C.OC_STACK_OK {
- logger.Logging(logger.DEBUG, "ERROR::"+strconv.Itoa(int(ret)))
- }
-}
-
-//CreateResource creates ocf resource. it uses default entity handler.
-func CreateResource(handle unsafe.Pointer,
- resourceTypeName string,
- resourceInterfaceName string,
- URI string,
- resourceProperties uint8) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
-
- cresourceTypeName := C.CString(resourceTypeName)
- defer C.free(unsafe.Pointer(cresourceTypeName))
- cresourceInterfaceName := C.CString(resourceInterfaceName)
- defer C.free(unsafe.Pointer(cresourceInterfaceName))
- cURI := C.CString(URI)
- defer C.free(unsafe.Pointer(cURI))
- cresourceProperties := C.uint8_t(resourceProperties)
-
- ret := C.cCreateResource(handle, cresourceTypeName, cresourceInterfaceName, cURI, nil, nil, cresourceProperties)
- if ret != C.OC_STACK_OK {
- logger.Logging(logger.DEBUG, "ERROR::"+strconv.Itoa(int(ret)))
- }
-
-}
-
-//export cgo_discoverycallback
-func cgo_discoverycallback(clientResponse *C.OCClientResponse) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
- cliResp := newResponse()
- if clientResponse.result != C.OC_STACK_OK {
- logger.Logging(logger.DEBUG, "clientResponse.result != C.OC_STACK_OK, result is "+strconv.Itoa(int(clientResponse.result)))
- return
- } else {
- logger.Logging(logger.DEBUG, "clientResponse.result == C.OC_STACK_OK")
- }
-
- if clientResponse.payload == nil {
- logger.Logging(logger.ERROR, "clientResponse.payload is nil")
- return
- }
-
- payload := (*C.OCDiscoveryPayload)(unsafe.Pointer(clientResponse.payload))
- if payload == nil {
- logger.Logging(logger.ERROR, "OCDiscoveryPayload is null")
- return
- }
-
- if payload.resources == nil {
- logger.Logging(logger.ERROR, "OCDiscoveryPayload.resources is nil")
- return
- }
-
- resource := (*C.OCResourcePayload)(unsafe.Pointer(payload.resources))
- fmt.Println(resource)
- if resource == nil {
- logger.Logging(logger.ERROR, "OCResourcePayload is nil")
- return
- }
-
- addr := string(C.GoBytes(unsafe.Pointer(&clientResponse.devAddr.addr), 66)[:])
- endpoint := ""
- for idx := range addr {
- if _, err := strconv.Atoi(string([]rune(addr)[idx])); err == nil {
- endpoint += string([]rune(addr)[idx])
- } else if string([]rune(addr)[idx]) == "." {
- endpoint += string([]rune(addr)[idx])
- } else {
- break
- }
- }
- port := int(clientResponse.devAddr.port)
-
- for {
- if resource == nil {
- logger.Logging(logger.DEBUG, "clientResponse.OCResourcePayload == nil")
- break
- }
-
- URI := C.GoString(resource.uri)
- if (URI == "/oic/sec/pstat") ||
- (URI == "/oic/sec/doxm") ||
- (URI == "/oic/sec/sp") ||
- (URI == "/oic/sec/acl2") ||
- (URI == "/oic/sec/cred") ||
- (URI == "/oic/p") {
- resource = resource.next
- // logger.Logging(logger.DEBUG, "Unnecessary URI "+URI)
- continue
- }
-
- r := Resource{}
- r.URI = URI
- r.Endpoint = endpoint
- r.Port = port
- C.fflush(C.stdout)
-
- t := resource.types
- for {
- if t == nil {
- break
- }
- r.Types = append(r.Types, C.GoString(t.value))
-
- t = t.next
- }
-
- i := resource.interfaces
- for {
- if i == nil {
- break
- }
- r.Interfaces = append(r.Interfaces, C.GoString(i.value))
-
- i = i.next
- }
-
- cliResp.resources = append(cliResp.resources, r)
- logger.Logging(logger.DEBUG, "new device::"+r.GetEndpoint()+":"+strconv.Itoa(r.GetPort()))
- resource = resource.next
- }
-
- mutex.Lock()
- defer mutex.Unlock()
- edgeJSONWriter(cliResp.resources)
-}
-
-func convertResourceToEdge(resources []Resource) *edgeJSON {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
- edgeData := newEdgeJSON()
- edgeData.Port = resources[0].GetPort()
- edgeData.Endpoint = resources[0].GetEndpoint()
-
- r := new(resourcesJSON)
- for _, res := range resources {
- r.URI = res.URI
- r.Types = make([]string, len(res.Types))
- copy(r.Types, res.Types)
- edgeData.Resources = append(edgeData.Resources, *r)
- }
-
- return edgeData
-}
-
-func edgeJSONWriter(resources []Resource) {
- logger.Logging(logger.DEBUG, "IN")
- defer logger.Logging(logger.DEBUG, "OUT")
-
- f, err := os.OpenFile(DiscoveryOutputJSON, os.O_CREATE|os.O_WRONLY, 0644)
- if err != nil {
- logger.Logging(logger.DEBUG, "OpenFile err::"+err.Error())
- return
- }
- defer f.Close()
-
- data, err := ioutil.ReadFile(DiscoveryOutputJSON)
- if err != nil {
- logger.Logging(logger.DEBUG, "ioutil.ReadFile err::"+err.Error())
- return
- }
-
- datalen := len(data)
- logger.Logging(logger.DEBUG, "output file data size::"+strconv.Itoa(datalen))
-
- var existingData []edgeJSON
-
- if datalen != 0 {
- err = json.Unmarshal(data, &existingData)
- if err != nil {
- logger.Logging(logger.DEBUG, "json.Unmarshal err::"+err.Error())
- return
- }
-
- for _, edge := range existingData {
- if edge.Port == resources[0].GetPort() && edge.Endpoint == resources[0].GetEndpoint() {
- logger.Logging(logger.DEBUG, "Discovered Resource is Repeated")
- return
- }
- }
-
- }
- edgeJSONData := convertResourceToEdge(resources)
- newData := append(existingData, *edgeJSONData)
- newDataJSON, _ := json.MarshalIndent(newData, "", " ")
-
- logger.Logging(logger.DEBUG, "newDataJSON size::"+strconv.Itoa(len(newDataJSON)))
-
- _, err = f.Write(newDataJSON)
- if err != nil {
- logger.Logging(logger.DEBUG, "iotuil err::"+err.Error())
- return
- }
-}