static void CAReceiveMessage(int fd) { // #1. get remote device information from file descriptor. size_t index = 0; CATCPSessionInfo_t *svritem = CAGetSessionInfoFromFD(fd, &index); if (!svritem) { OIC_LOG(ERROR, TAG, "there is no connection information in list"); return; } // #2. get already allocated memory size. size_t bufSize = (svritem->totalDataLen == 0) ? TCP_MAX_HEADER_LEN : svritem->totalDataLen; if (!svritem->recvData) { svritem->recvData = (unsigned char *) OICCalloc(1, bufSize); if (!svritem->recvData) { OIC_LOG(ERROR, TAG, "out of memory"); CADisconnectTCPSession(svritem, index); return; } } // #3. receive data from remote device. ssize_t recvLen = recv(fd, svritem->recvData + svritem->recvDataLen, bufSize - svritem->recvDataLen, 0); if (recvLen <= 0) { if(EWOULDBLOCK != errno) { OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno)); CADisconnectTCPSession(svritem, index); } return; } svritem->recvDataLen += recvLen; // #4. get actual data length from coap over tcp header. if (!svritem->totalDataLen) { coap_transport_type transport = coap_get_tcp_header_type_from_initbyte( ((unsigned char *) svritem->recvData)[0] >> 4); size_t headerLen = coap_get_tcp_header_length_for_transport(transport); if (svritem->recvDataLen >= headerLen) { svritem->totalDataLen = CAGetTotalLengthFromHeader( (unsigned char *) svritem->recvData); bufSize = svritem->totalDataLen; unsigned char *newBuf = OICRealloc(svritem->recvData, bufSize); if (!newBuf) { OIC_LOG(ERROR, TAG, "out of memory"); CADisconnectTCPSession(svritem, index); return; } svritem->recvData = newBuf; } }
static OCStackResult OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t** outPayload, size_t* size) { *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); *size = MAX_REQUEST_LENGTH; if(!*outPayload) { return OC_STACK_NO_MEMORY; } CborEncoder encoder; bool err = false; cbor_encoder_init(&encoder, *outPayload, *size, 0); CborEncoder rootArray; err = err || cbor_encoder_create_array(&encoder, &rootArray, 2); err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_SECURITY); CborEncoder map; err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength); if(payload->securityData) { err = err || AddTextStringToMap(&map, OC_RSRVD_REPRESENTATION, sizeof(OC_RSRVD_REPRESENTATION) - 1, payload->securityData); } err = err || cbor_encoder_close_container(&rootArray, &map); err = err || cbor_encoder_close_container(&encoder, &rootArray); if(err) { OC_LOG_V(ERROR, TAG, "Convert Security Payload failed", err); OICFree(*outPayload); return OC_STACK_ERROR; } *size = encoder.ptr - *outPayload; uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); if(!tempPayload) { OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); OICFree(*outPayload); return OC_STACK_ERROR; } *outPayload = tempPayload; return OC_STACK_OK; }
static OCStackResult OCConvertRepPayload(OCRepPayload* payload, uint8_t** outPayload, size_t* size) { *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); *size = MAX_REQUEST_LENGTH; if(!*outPayload) { return OC_STACK_NO_MEMORY; } CborEncoder encoder = {}; bool err = false; cbor_encoder_init(&encoder, *outPayload, *size, 0); CborEncoder rootArray; err = err || cbor_encoder_create_array(&encoder, &rootArray, CborIndefiniteLength); err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_REPRESENTATION); while(payload != NULL && !err) { err = err || OCConvertSingleRepPayload(&rootArray, payload); payload = payload->next; } // Close main array err = err || cbor_encoder_close_container(&encoder, &rootArray); if(err) { OC_LOG_V(ERROR, TAG, "Convert Rep Payload failed with : %d", err); return OC_STACK_ERROR; } *size = encoder.ptr - *outPayload; uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); if(!tempPayload) { OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); OICFree(*outPayload); return OC_STACK_ERROR; } *outPayload = tempPayload; return OC_STACK_OK; }
CAInterface_t *CAFindInterfaceChange() { char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf }; int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd; if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); return NULL; } CAInterface_t *foundNewInterface = NULL; struct ifreq* ifr = ifc.ifc_req; size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]); size_t ifreqsize = ifc.ifc_len; CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize); if (!previous) { OIC_LOG(ERROR, TAG, "OICMalloc failed"); return NULL; } memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize); size_t numprevious = caglobals.ip.nm.numIfItems; if (ifreqsize > caglobals.ip.nm.sizeIfItems) { CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize); if (!items) { OIC_LOG(ERROR, TAG, "OICRealloc failed"); OICFree(previous); return NULL; } caglobals.ip.nm.ifItems = items; caglobals.ip.nm.sizeIfItems = ifreqsize; } caglobals.ip.nm.numIfItems = 0; for (size_t i = 0; i < interfaces; i++) { struct ifreq* item = &ifr[i]; char *name = item->ifr_name; struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr; uint32_t ipv4addr = sa4->sin_addr.s_addr; if (ioctl(s, SIOCGIFFLAGS, item) < 0) { OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno)); continue; } int16_t flags = item->ifr_flags; if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) { continue; } if (ioctl(s, SIOCGIFINDEX, item) < 0) { OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno)); continue; } int ifIndex = item->ifr_ifindex; caglobals.ip.nm.ifItems[i].ifIndex = ifIndex; // refill interface list caglobals.ip.nm.numIfItems++; if (foundNewInterface) { continue; // continue updating interface list } // see if this interface didn't previously exist bool found = false; for (size_t j = 0; j < numprevious; j++) { if (ifIndex == previous[j].ifIndex) { found = true; break; } } if (found) { OIC_LOG_V(INFO, TAG, "Interface found: %s", name); continue; } foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags); } OICFree(previous); return foundNewInterface; }
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { u_arraylist_t *iflist = u_arraylist_create(); if (!iflist) { OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); return NULL; } char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf }; int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd; if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); u_arraylist_destroy(iflist); return NULL; } struct ifreq* ifr = ifc.ifc_req; size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]); size_t ifreqsize = ifc.ifc_len; if (ifreqsize > caglobals.ip.nm.sizeIfItems) { CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize); if (!items) { OIC_LOG(ERROR, TAG, "OICRealloc failed"); goto exit; } caglobals.ip.nm.ifItems = items; caglobals.ip.nm.sizeIfItems = ifreqsize; } caglobals.ip.nm.numIfItems = 0; for (size_t i = 0; i < interfaces; i++) { CAResult_t result = CA_STATUS_OK; struct ifreq* item = &ifr[i]; char *name = item->ifr_name; struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr; uint32_t ipv4addr = sa4->sin_addr.s_addr; if (ioctl(s, SIOCGIFFLAGS, item) < 0) { OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno)); continue; } int16_t flags = item->ifr_flags; if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) { continue; } if (ioctl(s, SIOCGIFINDEX, item) < 0) { OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno)); continue; } int ifindex = item->ifr_ifindex; caglobals.ip.nm.ifItems[i].ifIndex = ifindex; caglobals.ip.nm.numIfItems++; if (desiredIndex && (ifindex != desiredIndex)) { continue; } // Add IPv4 interface result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags); if (CA_STATUS_OK != result) { goto exit; } // Add IPv6 interface result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags); if (CA_STATUS_OK != result) { goto exit; } } return iflist; exit: u_arraylist_destroy(iflist); return NULL; }
OCStackResult OCConvertPayload(OCPayload* payload, uint8_t** outPayload, size_t* size) { // TinyCbor Version 47a78569c0 or better on master is required for the re-allocation // strategy to work. If you receive the following assertion error, please do a git-pull // from the extlibs/tinycbor/tinycbor directory #define CborNeedsUpdating (CborErrorOutOfMemory < CborErrorDataTooLarge) OC_STATIC_ASSERT(!CborNeedsUpdating, "tinycbor needs to be updated to at least 47a78569c0"); #undef CborNeedsUpdating OCStackResult ret = OC_STACK_INVALID_PARAM; int64_t err; uint8_t *out = NULL; size_t curSize = INIT_SIZE; VERIFY_PARAM_NON_NULL(TAG, payload, "Input param, payload is NULL"); VERIFY_PARAM_NON_NULL(TAG, outPayload, "OutPayload parameter is NULL"); VERIFY_PARAM_NON_NULL(TAG, size, "size parameter is NULL"); OIC_LOG_V(INFO, TAG, "Converting payload of type %d", payload->type); if (PAYLOAD_TYPE_SECURITY == payload->type) { size_t securityPayloadSize = ((OCSecurityPayload *)payload)->payloadSize; if (securityPayloadSize > 0) { out = (uint8_t *)OICCalloc(1, ((OCSecurityPayload *)payload)->payloadSize); VERIFY_PARAM_NON_NULL(TAG, out, "Failed to allocate security payload"); } } if (out == NULL) { out = (uint8_t *)OICCalloc(1, curSize); VERIFY_PARAM_NON_NULL(TAG, out, "Failed to allocate payload"); } err = OCConvertPayloadHelper(payload, out, &curSize); ret = OC_STACK_NO_MEMORY; if (err == CborErrorOutOfMemory) { // reallocate "out" and try again! uint8_t *out2 = (uint8_t *)OICRealloc(out, curSize); VERIFY_PARAM_NON_NULL(TAG, out2, "Failed to increase payload size"); out = out2; err = OCConvertPayloadHelper(payload, out, &curSize); while (err == CborErrorOutOfMemory) { uint8_t *out2 = (uint8_t *)OICRealloc(out, curSize); VERIFY_PARAM_NON_NULL(TAG, out2, "Failed to increase payload size"); out = out2; err = OCConvertPayloadHelper(payload, out, &curSize); } } if (err == CborNoError) { if (curSize < INIT_SIZE && PAYLOAD_TYPE_SECURITY != payload->type) { uint8_t *out2 = (uint8_t *)OICRealloc(out, curSize); VERIFY_PARAM_NON_NULL(TAG, out2, "Failed to increase payload size"); out = out2; } *size = curSize; *outPayload = out; OIC_LOG_V(DEBUG, TAG, "Payload Size: %zd Payload : ", *size); OIC_LOG_BUFFER(DEBUG, TAG, *outPayload, *size); return OC_STACK_OK; } //TODO: Proper conversion from CborError to OCStackResult. ret = (OCStackResult)-err; exit: OICFree(out); return ret; }
CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t idx) { if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); OIC_LOG(ERROR, TAG, "env error!!"); return CA_STATUS_FAILED; } jobject jni_obj_inputStream = CAEDRNativeGetInputStream(idx); if (!jni_obj_inputStream) { OIC_LOG(ERROR, TAG, "jni_obj_inputStream is null"); return CA_STATUS_FAILED; } jmethodID jni_mid_available = CAGetJNIMethodID(env, "java/io/InputStream", "available", "()I"); if (!jni_mid_available) { OIC_LOG(ERROR, TAG, "jni_mid_available is null"); return CA_STATUS_FAILED; } jint available = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_available); if (0 < available) { jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(idx); if (!jni_obj_socket) { OIC_LOG(ERROR, TAG, "jni_obj_socket is null"); return CA_STATUS_FAILED; } jstring jni_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_socket); if (!jni_str_address) { OIC_LOG(ERROR, TAG, "jni_str_address is null"); return CA_STATUS_FAILED; } const char* address = (*env)->GetStringUTFChars(env, jni_str_address, NULL); if (!address) { OIC_LOG(ERROR, TAG, "address is null"); (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } CAConnectedDeviceInfo_t *deviceInfo = (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(address); if (!deviceInfo) { OIC_LOG(ERROR, TAG, "failed to get device info from list"); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } jint bufSize = (deviceInfo->totalDataLen == 0) ? EDR_MAX_HEADER_LEN : deviceInfo->totalDataLen; if (!deviceInfo->recvData) { deviceInfo->recvData = OICCalloc(1, bufSize); if (!deviceInfo->recvData) { OIC_LOG(ERROR, TAG, "out of memory"); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } } jint remainSize = (jint) bufSize - deviceInfo->recvDataLen; if (0 >= remainSize) { OIC_LOG(ERROR, TAG, "remainSize value is invalid."); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } jbyteArray jbuf = (*env)->NewByteArray(env, remainSize); if (!jbuf) { OIC_LOG(ERROR, TAG, "jbuf is null"); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } jmethodID jni_mid_read = CAGetJNIMethodID(env, "java/io/InputStream", "read", "([BII)I"); if (!jni_mid_read) { OIC_LOG(ERROR, TAG, "jni_mid_read is null"); (*env)->DeleteLocalRef(env, jbuf); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } OIC_LOG_V(DEBUG, TAG, "read InputStream (idx:%d, addr:%s)", idx, address); jint recvLen = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_read, jbuf, (jint) 0, remainSize); if (-1 == recvLen) { OIC_LOG(ERROR, TAG, "recvLen is -1"); (*env)->DeleteLocalRef(env, jbuf); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } OIC_LOG_V(DEBUG, TAG, "read success (length: %d bytes)", recvLen); jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL); if (!buf) { OIC_LOG(ERROR, TAG, "buf is null"); (*env)->DeleteLocalRef(env, jbuf); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } memcpy(deviceInfo->recvData + deviceInfo->recvDataLen, (const char*) buf, recvLen); deviceInfo->recvDataLen += recvLen; (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0); (*env)->DeleteLocalRef(env, jbuf); if (!deviceInfo->totalDataLen && deviceInfo->recvData) { coap_transport_t transport = coap_get_tcp_header_type_from_initbyte( ((unsigned char *) deviceInfo->recvData)[0] >> 4); size_t headerLen = coap_get_tcp_header_length_for_transport(transport); if (deviceInfo->recvDataLen >= headerLen) { deviceInfo->totalDataLen = coap_get_total_message_length(deviceInfo->recvData, deviceInfo->recvDataLen); OIC_LOG_V(DEBUG, TAG, "total data length [%d] bytes", deviceInfo->totalDataLen); uint8_t *newBuf = OICRealloc(deviceInfo->recvData, deviceInfo->totalDataLen); if (!newBuf) { OIC_LOG(ERROR, TAG, "out of memory"); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } deviceInfo->recvData = newBuf; } }
OCStackResult OCConvertPayload(OCPayload* payload, uint8_t** outPayload, size_t* size) { // TinyCbor Version 47a78569c0 or better on master is required for the re-allocation // strategy to work. If you receive the following assertion error, please do a git-pull // from the extlibs/tinycbor/tinycbor directory #define CborNeedsUpdating (CborErrorOutOfMemory < CborErrorDataTooLarge) OC_STATIC_ASSERT(!CborNeedsUpdating, "tinycbor needs to be updated to at least 47a78569c0"); #undef CborNeedsUpdating if (!payload) { OC_LOG(ERROR, TAG, "Payload parameter NULL"); return OC_STACK_INVALID_PARAM; } if (!outPayload || !size) { OC_LOG(ERROR, TAG, "Out parameter/s parameter NULL"); return OC_STACK_INVALID_PARAM; } OC_LOG_V(INFO, TAG, "Converting payload of type %d", payload->type); size_t curSize = INIT_SIZE; uint8_t* out = (uint8_t*)OICCalloc(1, curSize); int64_t err = OCConvertPayloadHelper(payload, out, &curSize); if (err == CborErrorOutOfMemory) { // reallocate "out" and try again! uint8_t* out2 = (uint8_t*)OICRealloc(out, curSize); if (!out2) { OICFree(out); return OC_STACK_NO_MEMORY; } out = out2; err = OCConvertPayloadHelper(payload, out, &curSize); } if (err == 0) { if (curSize < INIT_SIZE) { uint8_t* out2 = (uint8_t*)OICRealloc(out, curSize); if (!out2) { OICFree(out); return OC_STACK_NO_MEMORY; } out = out2; } *size = curSize; *outPayload = out; return OC_STACK_OK; } else if (err < 0) { return (OCStackResult)-err; } else { return OC_STACK_ERROR; } }
static OCStackResult OCConvertPresencePayload(OCPresencePayload* payload, uint8_t** outPayload, size_t* size) { *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); *size = MAX_REQUEST_LENGTH; if(!*outPayload) { return OC_STACK_NO_MEMORY; } CborEncoder encoder = {}; bool err = false; cbor_encoder_init(&encoder, *outPayload, *size, 0); CborEncoder rootArray; err = err || cbor_encoder_create_array(&encoder, &rootArray, 2); err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PRESENCE); CborEncoder map; err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength); // Sequence Number err = err || cbor_encode_text_string(&map, OC_RSRVD_NONCE, sizeof(OC_RSRVD_NONCE) - 1); err = err || cbor_encode_uint(&map, payload->sequenceNumber); // Max Age err = err || cbor_encode_text_string(&map, OC_RSRVD_TTL, sizeof(OC_RSRVD_TTL) - 1); err = err || cbor_encode_uint(&map, payload->maxAge); // Trigger const char* triggerStr = convertTriggerEnumToString(payload->trigger); err = err || AddTextStringToMap(&map, OC_RSRVD_TRIGGER, sizeof(OC_RSRVD_TRIGGER) - 1, triggerStr); // Resource type name if(payload->trigger != OC_PRESENCE_TRIGGER_DELETE) { err = err || ConditionalAddTextStringToMap(&map, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_RESOURCE_TYPE) - 1, payload->resourceType); } // Close Map err = err || cbor_encoder_close_container(&rootArray, &map); err = err || cbor_encoder_close_container(&encoder, &rootArray); if(err) { OC_LOG_V(ERROR, TAG, "Convert Presence Payload failed with : %d", err); return OC_STACK_ERROR; } *size = encoder.ptr - *outPayload; uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); if(!tempPayload) { OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); OICFree(*outPayload); return OC_STACK_ERROR; } *outPayload = tempPayload; return OC_STACK_OK; }
static OCStackResult OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t** outPayload, size_t* size) { *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); *size = MAX_REQUEST_LENGTH; if(!*outPayload) { return OC_STACK_NO_MEMORY; } CborEncoder encoder = {}; bool err = false; cbor_encoder_init(&encoder, *outPayload, *size, 0); CborEncoder rootArray; err = err || cbor_encoder_create_array(&encoder, &rootArray, 2); err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PLATFORM); { CborEncoder map; err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength); // uri err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1, payload->uri); // Rep Map { CborEncoder repMap; err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION, sizeof(OC_RSRVD_REPRESENTATION) - 1); err = err || cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength); // Platform ID err = err || AddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_ID, sizeof(OC_RSRVD_PLATFORM_ID) - 1, payload->info.platformID); // MFG Name err = err || AddTextStringToMap(&repMap, OC_RSRVD_MFG_NAME, sizeof(OC_RSRVD_MFG_NAME) - 1, payload->info.manufacturerName); // MFG Url err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_URL, sizeof(OC_RSRVD_MFG_URL) - 1, payload->info.manufacturerUrl); // Model Num err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MODEL_NUM, sizeof(OC_RSRVD_MODEL_NUM) - 1, payload->info.modelNumber); // Date of Mfg err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_DATE, sizeof(OC_RSRVD_MFG_DATE) - 1, payload->info.dateOfManufacture); // Platform Version err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_VERSION, sizeof(OC_RSRVD_PLATFORM_VERSION) - 1, payload->info.platformVersion); // OS Version err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_OS_VERSION, sizeof(OC_RSRVD_OS_VERSION) - 1, payload->info.operatingSystemVersion); // Hardware Version err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_HARDWARE_VERSION, sizeof(OC_RSRVD_HARDWARE_VERSION) - 1, payload->info.hardwareVersion); // Firmware Version err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_FIRMWARE_VERSION, sizeof(OC_RSRVD_FIRMWARE_VERSION) - 1, payload->info.firmwareVersion); // Support URL err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SUPPORT_URL, sizeof(OC_RSRVD_SUPPORT_URL) - 1, payload->info.supportUrl); // System Time err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SYSTEM_TIME, sizeof(OC_RSRVD_SYSTEM_TIME) - 1, payload->info.systemTime); err = err || cbor_encoder_close_container(&map, &repMap); } // Close Map err = err || cbor_encoder_close_container(&rootArray, &map); } // Close main array err = err || cbor_encoder_close_container(&encoder, &rootArray); if(err) { OC_LOG_V(ERROR, TAG, "Convert Platform Payload failed with : %d", err); return OC_STACK_ERROR; } *size = encoder.ptr - *outPayload; uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); if(!tempPayload) { OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); OICFree(*outPayload); return OC_STACK_ERROR; } *outPayload = tempPayload; return OC_STACK_OK; }
static OCStackResult OCConvertDevicePayload(OCDevicePayload* payload, uint8_t** outPayload, size_t* size) { *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); *size = MAX_REQUEST_LENGTH; if(!*outPayload) { return OC_STACK_NO_MEMORY; } CborEncoder encoder = {}; bool err = false; cbor_encoder_init(&encoder, *outPayload, *size, 0); CborEncoder rootArray; err = err || cbor_encoder_create_array(&encoder, &rootArray, 2); err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DEVICE); { CborEncoder map; err = err || cbor_encoder_create_map(&rootArray, &map, 2); // uri err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1, payload->uri); // Rep Map { CborEncoder repMap; err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION, sizeof(OC_RSRVD_REPRESENTATION) - 1); err = err || cbor_encoder_create_map(&map, &repMap, 4); // Device ID err = err || cbor_encode_text_string(&repMap, OC_RSRVD_DEVICE_ID, sizeof(OC_RSRVD_DEVICE_ID) - 1); err = err || cbor_encode_byte_string(&repMap, payload->sid, UUID_SIZE); // Device Name err = err || AddTextStringToMap(&repMap, OC_RSRVD_DEVICE_NAME, sizeof(OC_RSRVD_DEVICE_NAME) - 1, payload->deviceName); // Device Spec Version err = err || AddTextStringToMap(&repMap, OC_RSRVD_SPEC_VERSION, sizeof(OC_RSRVD_SPEC_VERSION) - 1, payload->specVersion); // Device data Model Version err = err || AddTextStringToMap(&repMap, OC_RSRVD_DATA_MODEL_VERSION, sizeof(OC_RSRVD_DATA_MODEL_VERSION) - 1, payload->dataModelVersion); err = err || cbor_encoder_close_container(&map, &repMap); } // Close Map err = err || cbor_encoder_close_container(&rootArray, &map); } // Close main array err = err || cbor_encoder_close_container(&encoder, &rootArray); if(err) { OC_LOG_V(ERROR, TAG, "Convert Device Payload failed with : %d", err); return OC_STACK_ERROR; } *size = encoder.ptr - *outPayload; uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); if(!tempPayload) { OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); OICFree(*outPayload); return OC_STACK_ERROR; } *outPayload = tempPayload; return OC_STACK_OK; }
static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t** outPayload, size_t* size) { *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); *size = MAX_REQUEST_LENGTH; if(!*outPayload) { return OC_STACK_NO_MEMORY; } CborEncoder encoder = {}; bool err = false; size_t resourceCount = OCDiscoveryPayloadGetResourceCount(payload); cbor_encoder_init(&encoder, *outPayload, *size, 0); CborEncoder rootArray; err = err || cbor_encoder_create_array(&encoder, &rootArray, 1 + resourceCount); err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DISCOVERY); for(size_t i = 0; i < resourceCount; ++i) { CborEncoder map; OCResourcePayload* resource = OCDiscoveryPayloadGetResource(payload, i); err = err || cbor_encoder_create_map(&rootArray, &map, 3); // Uri err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1, resource->uri); // Server ID err = err || cbor_encode_text_string(&map, OC_RSRVD_SERVER_INSTANCE_ID, sizeof(OC_RSRVD_SERVER_INSTANCE_ID) - 1); err = err || cbor_encode_byte_string(&map, resource->sid, UUID_SIZE); // Prop Tag { CborEncoder propMap; err = err || cbor_encode_text_string(&map, OC_RSRVD_PROPERTY, sizeof(OC_RSRVD_PROPERTY) -1 ); err = err || cbor_encoder_create_map(&map, &propMap, 3); // Resource Type { CborEncoder rtArray; err = err || cbor_encode_text_string(&propMap, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_RESOURCE_TYPE) - 1); err = err || cbor_encoder_create_array(&propMap, &rtArray, CborIndefiniteLength); OCStringLL* rtPtr = resource->types; while(rtPtr) { err = err || cbor_encode_text_string(&rtArray, rtPtr->value, strlen(rtPtr->value)); rtPtr = rtPtr->next; } err = err || cbor_encoder_close_container(&propMap, &rtArray); } // Interface Types { CborEncoder ifArray; err = err || cbor_encode_text_string(&propMap, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1); err = err || cbor_encoder_create_array(&propMap, &ifArray, CborIndefiniteLength); OCStringLL* ifPtr = resource->interfaces; while(ifPtr) { err = err || cbor_encode_text_string(&ifArray, ifPtr->value, strlen(ifPtr->value)); ifPtr= ifPtr->next; } err = err || cbor_encoder_close_container(&propMap, &ifArray); } // Policy { CborEncoder policyMap; err = err || cbor_encode_text_string(&propMap, OC_RSRVD_POLICY, sizeof(OC_RSRVD_POLICY) - 1); err = err || cbor_encoder_create_map(&propMap, &policyMap, CborIndefiniteLength); // Bitmap err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP, sizeof(OC_RSRVD_BITMAP) - 1); err = err || cbor_encode_uint(&policyMap, resource->bitmap); if(resource->secure) { err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE, sizeof(OC_RSRVD_SECURE) - 1); err = err || cbor_encode_boolean(&policyMap, OC_RESOURCE_SECURE); if(resource->port != 0) { err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT, sizeof(OC_RSRVD_HOSTING_PORT) - 1); err = err || cbor_encode_uint(&policyMap, resource->port); } } err = err || cbor_encoder_close_container(&propMap, &policyMap); } // Close err = err || cbor_encoder_close_container(&map, &propMap); } // Close Item err = err || cbor_encoder_close_container(&rootArray, &map); } // Close main array err = err || cbor_encoder_close_container(&encoder, &rootArray); if(err) { OC_LOG_V(ERROR, TAG, "Convert Discovery Payload failed with : %d", err); return OC_STACK_ERROR; } *size = encoder.ptr - *outPayload; uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); if(!tempPayload) { OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); OICFree(*outPayload); return OC_STACK_ERROR; } *outPayload = tempPayload; return OC_STACK_OK; }
CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id) { if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); OIC_LOG(ERROR, TAG, "env error!!"); return CA_STATUS_FAILED; } // check whether this socket object is connected or not. jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(id); if (!jni_obj_socket) { return CA_STATUS_INVALID_PARAM; } // check it whether is still connected or not through google api jboolean ret = CAEDRIsConnectedForSocket(env, jni_obj_socket); if (!ret) { OIC_LOG(ERROR, TAG, "it is not connected yet."); // remove socket to list CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket); return CA_STATUS_FAILED; } // start to read through InputStream jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket"); if (!jni_cid_BTsocket) { OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null"); return CA_STATUS_FAILED; } jmethodID jni_mid_getInputStream = (*env)->GetMethodID(env, jni_cid_BTsocket, "getInputStream", "()Ljava/io/InputStream;"); jobject jni_obj_inputStream = (*env)->CallObjectMethod(env, jni_obj_socket, jni_mid_getInputStream); if (!jni_obj_inputStream) { OIC_LOG(ERROR, TAG, "jni_obj_inputStream is null"); (*env)->DeleteLocalRef(env, jni_cid_BTsocket); return CA_STATUS_FAILED; } jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream"); if (!jni_cid_InputStream) { OIC_LOG(ERROR, TAG, "jni_cid_InputStream is null"); (*env)->DeleteLocalRef(env, jni_obj_inputStream); (*env)->DeleteLocalRef(env, jni_cid_BTsocket); return CA_STATUS_FAILED; } jmethodID jni_mid_available = (*env)->GetMethodID(env, jni_cid_InputStream, "available", "()I"); if (!jni_mid_available) { OIC_LOG(ERROR, TAG, "jni_mid_available is null"); goto exit; } jint available = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_available); CAConnectedDeviceInfo_t *deviceInfo = NULL; if (0 < available) { jstring jni_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_socket); if (!jni_str_address) { OIC_LOG(ERROR, TAG, "jni_str_address is null"); goto exit; } const char* address = (*env)->GetStringUTFChars(env, jni_str_address, NULL); if (!address) { OIC_LOG(ERROR, TAG, "address is null"); (*env)->DeleteLocalRef(env, jni_str_address); goto exit; } OIC_LOG_V(DEBUG, TAG, "get InputStream..%d, %s", id, address); jmethodID jni_mid_read = (*env)->GetMethodID(env, jni_cid_InputStream, "read", "([BII)I"); if (!jni_mid_read) { OIC_LOG(ERROR, TAG, "jni_mid_read is null"); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); goto exit; } deviceInfo = (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(address); if (!deviceInfo) { OIC_LOG(ERROR, TAG, "failed to get device info from list"); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); goto exit; } jint bufSize = (deviceInfo->totalDataLen == 0) ? EDR_MAX_HEADER_LEN : deviceInfo->totalDataLen; if (!deviceInfo->recvData) { deviceInfo->recvData = OICCalloc(1, bufSize); if (!deviceInfo->recvData) { OIC_LOG(ERROR, TAG, "out of memory"); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); goto exit; } } jbyteArray jbuf = (*env)->NewByteArray(env, (jint) bufSize - deviceInfo->recvDataLen); if (!jbuf) { OIC_LOG(ERROR, TAG, "jbuf is null"); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); goto exit; } jint recvLen = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_read, jbuf, (jint) 0, (jint) bufSize - deviceInfo->recvDataLen); if (-1 == recvLen) { OIC_LOG(ERROR, TAG, "recvLen is -1"); (*env)->DeleteLocalRef(env, jbuf); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); goto exit; } jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL); if (!buf) { OIC_LOG(ERROR, TAG, "buf is null"); (*env)->DeleteLocalRef(env, jbuf); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); goto exit; } memcpy(deviceInfo->recvData + deviceInfo->recvDataLen, (const char*) buf, recvLen); deviceInfo->recvDataLen += recvLen; OIC_LOG(DEBUG, TAG, "read something from InputStream"); if (!deviceInfo->totalDataLen) { coap_transport_type transport = coap_get_tcp_header_type_from_initbyte( ((unsigned char *) deviceInfo->recvData)[0] >> 4); size_t headerLen = coap_get_tcp_header_length_for_transport(transport); if (deviceInfo->recvData && deviceInfo->recvDataLen >= headerLen) { deviceInfo->totalDataLen = coap_get_total_message_length(deviceInfo->recvData, deviceInfo->recvDataLen); OIC_LOG_V(DEBUG, TAG, "total data length [%d] bytes", deviceInfo->totalDataLen); uint8_t *newBuf = OICRealloc(deviceInfo->recvData, deviceInfo->totalDataLen); if (!newBuf) { OIC_LOG(ERROR, TAG, "out of memory"); (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0); (*env)->DeleteLocalRef(env, jbuf); (*env)->ReleaseStringUTFChars(env, jni_str_address, address); (*env)->DeleteLocalRef(env, jni_str_address); goto exit; } deviceInfo->recvData = newBuf; } }
static CAResult_t CAReceiveMessage() { uint32_t length = u_arraylist_length(caglobals.tcp.svrlist); size_t i = 0; unsigned char *recvBuffer = NULL; CATCPServerInfo_t *svritem = NULL; for (i = 0; i < length; i++) { svritem = (CATCPServerInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i); if (svritem->u4tcp.fd < 0) { continue; } size_t bufSize = TCP_MAX_HEADER_LEN; recvBuffer = (unsigned char *) OICCalloc(1, bufSize); if (!recvBuffer) { OIC_LOG(ERROR, TAG, "out of memory"); goto exit; } bool isHeaderChecked = false; size_t totalLen = 0; size_t totalReceivedLen = 0; do { ssize_t recvLen = recv(svritem->u4tcp.fd, recvBuffer + totalReceivedLen, bufSize - totalReceivedLen, 0); if (recvLen <= 0) { if(EWOULDBLOCK != errno) { OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno)); goto exit; } // if received data length is zero, we are breaking loop. // because we use non-blocking socket to receive data from remote device. if (!totalReceivedLen) { break; } continue; } totalReceivedLen += recvLen; if (!isHeaderChecked && totalReceivedLen) { coap_transport_type transport = coap_get_tcp_header_type_from_initbyte( ((unsigned char *)recvBuffer)[0] >> 4); size_t headerLen = coap_get_tcp_header_length_for_transport(transport); if (totalReceivedLen >= headerLen) { // get actual data length from coap over tcp header totalLen = CAGetTotalLengthFromHeader((unsigned char *) recvBuffer); bufSize = totalLen; unsigned char *newBuf = OICRealloc(recvBuffer, bufSize); if (NULL == newBuf) { OIC_LOG(ERROR, TAG, "out of memory"); goto exit; } recvBuffer = newBuf; isHeaderChecked = true; } } if (totalLen == totalReceivedLen) { CAEndpoint_t ep = { .adapter = CA_ADAPTER_TCP, .port = svritem->u4tcp.port }; strncpy(ep.addr, svritem->addr, sizeof(ep.addr)); if (g_packetReceivedCallback) { g_packetReceivedCallback(&ep, recvBuffer, totalLen); } OIC_LOG_V(DEBUG, TAG, "received data len:%d", totalLen); break; } } while (!totalLen || totalLen > totalReceivedLen); OICFree(recvBuffer); }