1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 //=============================================================================
24 //=============================================================================
25 #define _POSIX_C_SOURCE 200112L
28 #include "ocstackconfig.h"
29 #include "occlientcb.h"
30 #include "ocobserve.h"
41 //=============================================================================
43 //=============================================================================
44 #define TAG PCF("OCCoAP")
45 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
46 {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
47 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg); goto exit;} }
49 //=============================================================================
51 //=============================================================================
52 #define COAP_BLOCK_FILL_VALUE (0xFF)
54 //=============================================================================
56 //=============================================================================
58 static coap_context_t *gCoAPCtx = NULL;
60 //=============================================================================
62 //=============================================================================
64 //generate a coap token
65 void OCGenerateCoAPToken(OCCoAPToken * token)
69 token->tokenLength = MAX_TOKEN_LENGTH;
70 OCFillRandomMem((uint8_t*)token->token, token->tokenLength);
74 //This function is called back by libcoap when ack or rst are received
75 static void HandleCoAPAckRst(struct coap_context_t * ctx, uint8_t msgType,
76 const coap_queue_t * sentQueue){
80 coap_pdu_t * sentPdu = sentQueue->pdu;
81 OCStackResult result = OC_STACK_ERROR;
82 uint32_t observationOption = OC_OBSERVE_NO_OPTION;
83 // {{0}} to eliminate warning for known compiler bug 53119
84 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
85 OCCoAPToken sentToken = {{0}};
87 result = ParseCoAPPdu(sentPdu, NULL, NULL, &observationOption, NULL, NULL, NULL,
88 NULL, NULL, NULL, NULL, NULL);
89 VERIFY_SUCCESS(result, OC_STACK_OK);
91 // fill OCCoAPToken structure
92 RetrieveOCCoAPToken(sentPdu, &sentToken);
94 if(msgType == COAP_MESSAGE_RST)
96 if(myStackMode != OC_CLIENT)
98 result = OCStackFeedBack(&sentToken, OC_OBSERVER_NOT_INTERESTED);
99 if(result == OC_STACK_OK)
102 "Received RST, removing all queues associated with Token %d bytes",
103 sentToken.tokenLength);
104 OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength);
105 coap_cancel_all_messages(ctx, &sentQueue->remote, sentToken.token,
106 sentToken.tokenLength);
110 else if(observationOption != OC_OBSERVE_NO_OPTION && msgType == COAP_MESSAGE_ACK)
112 OC_LOG_V(DEBUG, TAG, "Received ACK, for Token %d bytes",sentToken.tokenLength);
113 OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength);
114 // now the observer is still interested
115 if(myStackMode != OC_CLIENT)
117 OCStackFeedBack(&sentToken, OC_OBSERVER_STILL_INTERESTED);
124 //This function is called back by libcoap when a request is received
125 static void HandleCoAPRequests(struct coap_context_t *ctx,
126 const coap_queue_t * rcvdRequest)
130 OCServerProtocolRequest protocolRequest = {(OCMethod)0};
131 coap_block_t rcvdBlock1;
132 coap_block_t rcvdBlock2;
133 memset(&rcvdBlock1, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
134 memset(&rcvdBlock2, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
135 uint16_t rcvdSize1 = 0;
136 coap_pdu_t * rcvdPdu = rcvdRequest->pdu;
137 coap_pdu_t * sendPdu = NULL;
138 coap_send_flags_t sendFlag;
139 OCStackResult result = OC_STACK_ERROR;
140 OCStackResult requestResult = OC_STACK_ERROR;
142 if(myStackMode == OC_CLIENT)
144 //TODO: should the client be responding to requests?
148 protocolRequest.observationOption = OC_OBSERVE_NO_OPTION;
149 protocolRequest.qos = (rcvdPdu->hdr->type == COAP_MESSAGE_CON) ?
150 OC_HIGH_QOS : OC_LOW_QOS;
151 protocolRequest.coapID = rcvdPdu->hdr->id;
152 protocolRequest.delayedResNeeded = rcvdRequest->delayedResNeeded;
153 protocolRequest.secured = rcvdRequest->secure;
155 // fill OCCoAPToken structure
156 RetrieveOCCoAPToken(rcvdPdu, &protocolRequest.requestToken);
157 OC_LOG_V(INFO, TAG, " Token received %d bytes",
158 protocolRequest.requestToken.tokenLength);
159 OC_LOG_BUFFER(INFO, TAG, protocolRequest.requestToken.token,
160 protocolRequest.requestToken.tokenLength);
163 memcpy(&protocolRequest.requesterAddr, (OCDevAddr *) &rcvdRequest->remote,
166 // Retrieve Uri and Query from received coap pdu
167 result = ParseCoAPPdu(rcvdPdu, protocolRequest.resourceUrl,
168 protocolRequest.query,
169 &(protocolRequest.observationOption), NULL,
170 &(protocolRequest.numRcvdVendorSpecificHeaderOptions),
171 protocolRequest.rcvdVendorSpecificHeaderOptions,
172 &rcvdBlock1, &rcvdBlock2, &rcvdSize1, NULL,
173 protocolRequest.reqJSONPayload);
174 VERIFY_SUCCESS(result, OC_STACK_OK);
176 switch (rcvdPdu->hdr->code)
178 case COAP_REQUEST_GET:
180 protocolRequest.method = OC_REST_GET;
183 case COAP_REQUEST_POST:
185 protocolRequest.method = OC_REST_POST;
188 case COAP_REQUEST_DELETE:
190 protocolRequest.method = OC_REST_DELETE;
193 case COAP_REQUEST_PUT:
195 protocolRequest.method = OC_REST_PUT;
200 OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
206 if(rcvdBlock1.szx != 7)
208 protocolRequest.reqPacketSize = 1 << (rcvdBlock1.szx + 4);
209 protocolRequest.reqMorePacket = rcvdBlock1.m;
210 protocolRequest.reqPacketNum = rcvdBlock1.num;
214 // No block1 received
215 rcvdSize1 = strlen((const char *)protocolRequest.reqJSONPayload)+1;
216 protocolRequest.reqTotalSize = rcvdSize1;
219 if(rcvdBlock2.szx != 7)
221 protocolRequest.resPacketSize = 1 << (rcvdBlock2.szx + 4);
222 protocolRequest.resPacketNum = rcvdBlock2.num;
225 requestResult = HandleStackRequests(&protocolRequest);
227 if(requestResult == OC_STACK_VIRTUAL_DO_NOT_HANDLE ||
228 requestResult == OC_STACK_OK ||
229 requestResult == OC_STACK_RESOURCE_CREATED ||
230 requestResult == OC_STACK_RESOURCE_DELETED ||
231 requestResult == OC_STACK_INVALID_DEVICE_INFO)
235 else if(requestResult == OC_STACK_NO_MEMORY ||
236 requestResult == OC_STACK_ERROR ||
237 requestResult == OC_STACK_NOTIMPL ||
238 requestResult == OC_STACK_NO_RESOURCE ||
239 requestResult == OC_STACK_RESOURCE_ERROR)
241 // TODO: should we send an error also when we receive a non-secured request to a secure resource?
242 // TODO: should we consider some sort of error response
243 OC_LOG(DEBUG, TAG, PCF("We should send some sort of error message"));
244 // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
245 sendPdu = GenerateCoAPPdu((rcvdPdu->hdr->type == COAP_MESSAGE_CON)? COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
246 OCToCoAPResponseCode(requestResult), rcvdPdu->hdr->id,
247 &protocolRequest.requestToken, NULL, NULL);
248 VERIFY_NON_NULL(sendPdu);
249 coap_show_pdu(sendPdu);
250 sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
251 if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
254 OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
258 else if(requestResult == OC_STACK_SLOW_RESOURCE ||
259 requestResult == OC_STACK_DUPLICATE_REQUEST)
261 if(rcvdPdu->hdr->type == COAP_MESSAGE_CON)
263 // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
264 sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, rcvdPdu->hdr->id,
266 VERIFY_NON_NULL(sendPdu);
267 coap_show_pdu(sendPdu);
269 sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
270 if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
273 OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
285 uint32_t GetTime(float afterSeconds)
289 return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
292 //This function is called back by libcoap when a response is received
293 static void HandleCoAPResponses(struct coap_context_t *ctx,
294 const coap_queue_t * rcvdResponse) {
295 OCResponse * response = NULL;
296 OCCoAPToken rcvdToken;
297 OCClientResponse clientResponse = {0};
298 ClientCB * cbNode = NULL;
299 unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
300 uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
302 OCStackResult result = OC_STACK_ERROR;
303 coap_pdu_t * sendPdu = NULL;
304 coap_pdu_t * recvPdu = NULL;
305 unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
306 uint8_t isObserveNotification = 0;
308 char * resourceTypeName = NULL;
309 uint8_t remoteIpAddr[4];
310 uint16_t remotePortNu;
311 unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
312 uint8_t isPresenceNotification = 0;
313 uint8_t isMulticastPresence = 0;
315 uint32_t higherBound;
318 coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE};
319 coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE};
320 uint16_t rcvdSize2 = 0;
322 VERIFY_NON_NULL(ctx);
323 VERIFY_NON_NULL(rcvdResponse);
324 recvPdu = rcvdResponse->pdu;
326 result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge,
327 &clientResponse.numRcvdVendorSpecificHeaderOptions,
328 clientResponse.rcvdVendorSpecificHeaderOptions,
329 &rcvdBlock1, &rcvdBlock2, NULL, &rcvdSize2, bufRes);
331 VERIFY_SUCCESS(result, OC_STACK_OK);
333 OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u", sequenceNumber);
334 OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", maxAge);
335 OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
337 if(sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
339 isObserveNotification = 1;
340 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
344 if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
347 isPresenceNotification = 1;
348 OC_LOG(INFO, TAG, PCF("Received a presence notification"));
349 tok = strtok_r((char *)bufRes, "[:]}", &tokSavePtr);
350 bufRes[strlen((char *)bufRes)] = ':';
351 tok = strtok_r(NULL, "[:]}", &tokSavePtr);
352 bufRes[strlen((char *)bufRes)] = ':';
353 VERIFY_NON_NULL(tok);
354 sequenceNumber = (uint32_t )atol(tok);
355 OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
356 tok = strtok_r(NULL, "[:]}", &tokSavePtr);
357 VERIFY_NON_NULL(tok);
358 maxAge = (uint32_t )atol(tok);
359 OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
360 tok = strtok_r(NULL, "[:]}", &tokSavePtr);
362 bufRes[strlen((char *)bufRes)] = ':';
363 resourceTypeName = (char *)OCMalloc(strlen(tok));
364 if(!resourceTypeName)
368 strcpy(resourceTypeName, tok);
369 OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
372 bufRes[strlen((char *)bufRes)] = ']';
376 // fill OCCoAPToken structure
377 RetrieveOCCoAPToken(recvPdu, &rcvdToken);
378 OC_LOG_V(INFO, TAG,"Received a pdu with Token", rcvdToken.tokenLength);
379 OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);
381 // fill OCClientResponse structure
382 result = FormOCClientResponse(&clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code),
383 (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, bufRes);
384 VERIFY_SUCCESS(result, OC_STACK_OK);
386 cbNode = GetClientCB(&rcvdToken, NULL, NULL);
389 // Check if the application subscribed for presence
392 // get the address of the remote
393 OCDevAddrToIPv4Addr((OCDevAddr *) &(rcvdResponse->remote), remoteIpAddr,
394 remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
395 OCDevAddrToPort((OCDevAddr *) &(rcvdResponse->remote), &remotePortNu);
396 snprintf((char *)fullUri, sizeof(fullUri), "coap://%d.%d.%d.%d:%d%s",
397 remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
398 remotePortNu,rcvdUri);
399 cbNode = GetClientCB(NULL, NULL, fullUri);
402 // Check if application subscribed for multicast presence
405 snprintf((char *)fullUri, sizeof(fullUri), "%s%s", OC_MULTICAST_IP, rcvdUri);
406 cbNode = GetClientCB(NULL, NULL, fullUri);
407 isMulticastPresence = 1;
408 isPresenceNotification = 0;
412 // fill OCResponse structure
413 result = FormOCResponse(&response, cbNode, maxAge, &clientResponse);
414 VERIFY_SUCCESS(result, OC_STACK_OK);
418 if(!isObserveNotification)
421 if(!isPresenceNotification)
424 OC_LOG(INFO, TAG, PCF("Received a regular response"));
425 if(recvPdu->hdr->type == COAP_MESSAGE_CON)
427 sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0,
428 recvPdu->hdr->id, NULL, NULL, NULL);
429 VERIFY_NON_NULL(sendPdu);
430 result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
432 (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
438 if(isObserveNotification)
440 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
441 if(recvPdu->hdr->type == COAP_MESSAGE_CON)
443 sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0,
444 recvPdu->hdr->id, NULL, NULL, NULL);
445 VERIFY_NON_NULL(sendPdu);
446 result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
448 (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
450 //TODO: check the standard for methods to detect wrap around condition
451 if(cbNode->method == OC_REST_OBSERVE &&
452 (clientResponse.sequenceNumber <= cbNode->sequenceNumber ||
453 (clientResponse.sequenceNumber > cbNode->sequenceNumber &&
454 clientResponse.sequenceNumber == (MAX_SEQUENCE_NUMBER))))
456 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
457 Ignoring Incoming:%d Against Current:%d.",
458 clientResponse.sequenceNumber, cbNode->sequenceNumber);
461 if(clientResponse.sequenceNumber > cbNode->sequenceNumber){
462 cbNode->sequenceNumber = clientResponse.sequenceNumber;
468 if(isPresenceNotification)
470 OC_LOG(INFO, TAG, PCF("Received a presence notification"));
471 if(!cbNode->presence)
473 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
474 VERIFY_NON_NULL(cbNode->presence);
475 cbNode->presence->timeOut = NULL;
476 cbNode->presence->timeOut = (uint32_t *)
477 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
478 if(!(cbNode->presence->timeOut)){
479 OCFree(cbNode->presence);
485 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
486 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
489 OCFree(cbNode->presence->timeOut);
490 OCFree(cbNode->presence);
491 cbNode->presence = NULL;
496 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
497 cbNode->presence->TTL = maxAge;
498 for(int index = 0; index < PresenceTimeOutSize; index++)
500 lowerBound = GetTime(((float)(PresenceTimeOut[index])
501 /(float)100)*(float)cbNode->presence->TTL);
502 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
503 /(float)100)*(float)cbNode->presence->TTL);
504 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
505 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
506 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
507 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d", cbNode->presence->timeOut[index]);
509 cbNode->presence->TTLlevel = 0;
510 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
511 if(cbNode->sequenceNumber == clientResponse.sequenceNumber)
513 OC_LOG(INFO, TAG, PCF("===============No presence change"));
516 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
517 cbNode->sequenceNumber = clientResponse.sequenceNumber;;
520 // Ensure that a filter is actually applied.
521 if(resourceTypeName && response->cbNode->filterResourceType)
523 if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
529 else if(isMulticastPresence)
531 // Check if the same nonce for a given host
532 OCMulticastNode* mcNode = NULL;
533 unsigned char senderUri[MAX_URI_LENGTH] = { 0 };
534 snprintf((char *)senderUri, sizeof(senderUri), "%d.%d.%d.%d:%d",
535 remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
537 mcNode = GetMCPresenceNode(senderUri);
541 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
542 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
545 OCFree(cbNode->presence->timeOut);
546 OCFree(cbNode->presence);
547 cbNode->presence = NULL;
550 else if(mcNode != NULL)
552 if(mcNode->nonce == clientResponse.sequenceNumber)
554 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
557 mcNode->nonce = clientResponse.sequenceNumber;
561 uint32_t uriLen = strlen((char*)senderUri);
562 unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
565 memcpy(uri, senderUri, (uriLen + 1));
570 PCF("===============No Memory for URI to store in the presence node"));
573 result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
574 clientResponse.sequenceNumber);
575 if(result == OC_STACK_NO_MEMORY)
578 PCF("===============No Memory for Multicast Presence Node"));
583 // Ensure that a filter is actually applied.
584 if(resourceTypeName && response->cbNode->filterResourceType)
586 if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
594 HandleStackResponses(response);
596 else if(!cbNode && isObserveNotification)
598 OC_LOG(INFO, TAG, PCF("Received an observe notification, but I do not have callback \
599 ------------ sending RESET"));
600 sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0,
601 recvPdu->hdr->id, NULL, NULL, NULL);
602 VERIFY_NON_NULL(sendPdu);
603 result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, sendPdu,
604 (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
605 VERIFY_SUCCESS(result, OC_STACK_OK);
608 else if(!cbNode && isPresenceNotification)
610 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
611 ------------ ignoring"));
616 OC_LOG(INFO, TAG, PCF("Received a response, but I do not have callback. \
617 ------------ sending RESET"));
618 sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0,
619 recvPdu->hdr->id, NULL, NULL, NULL);
620 VERIFY_NON_NULL(sendPdu);
621 result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, sendPdu,
622 (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
623 VERIFY_SUCCESS(result, OC_STACK_OK);
626 OCFree(resourceTypeName);
630 //=============================================================================
632 //=============================================================================
635 * Initialize the CoAP client or server with its IPv4 address and CoAP port
638 * IP Address of host device
640 * Port of host device
642 * Host device is client, server, or client-server
648 OCStackResult OCInitCoAP(const char *address, uint16_t port, OCMode mode) {
650 OCStackResult ret = OC_STACK_ERROR;
652 TODO ("Below should go away and be replaced by OC_LOG");
653 coap_log_t log_level = (coap_log_t)(LOG_DEBUG + 1);
655 uint8_t ipAddr[4] = { 0 };
656 uint16_t parsedPort = 0;
658 OC_LOG(INFO, TAG, PCF("Entering OCInitCoAP"));
660 coap_set_log_level(log_level);
664 if (!ParseIPv4Address((unsigned char *) address, ipAddr, &parsedPort))
666 ret = OC_STACK_ERROR;
670 OC_LOG_V(INFO, TAG, "Parsed IP Address %d.%d.%d.%d",
671 ipAddr[0],ipAddr[1],ipAddr[2],ipAddr[3]);
674 gCoAPCtx = coap_new_context(ipAddr, port);
675 VERIFY_NON_NULL(gCoAPCtx);
677 // To allow presence notification work we need to init socket gCoAPCtx->sockfd_wellknown
678 // for servers as well as clients
679 OCBuildIPv4Address(COAP_WK_IPAddr_0, COAP_WK_IPAddr_1, COAP_WK_IPAddr_2,
680 COAP_WK_IPAddr_3, COAP_DEFAULT_PORT, &mcastAddr);
682 coap_join_wellknown_group(gCoAPCtx,
683 (coap_address_t* )&mcastAddr), 0);
685 coap_register_request_handler(gCoAPCtx, HandleCoAPRequests);
686 coap_register_response_handler(gCoAPCtx, HandleCoAPResponses);
687 coap_register_ack_rst_handler(gCoAPCtx, HandleCoAPAckRst);
692 if (ret != OC_STACK_OK)
700 * Discover OC resources
702 * @param method - method to perform on the resource
703 * @param qos - Quality of Service the request will be sent on
704 * @param token - token which will added to the request
705 * @param Uri - URI of the resource to interact with
706 * @param payload - the request payload to be added to the request before sending
707 * by the stack when discovery or resource interaction is complete
708 * @param options - The address of an array containing the vendor specific
709 * header options to be sent with the request
714 OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token,
715 const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions)
718 OCStackResult ret = OC_STACK_ERROR;
719 coap_pdu_t *pdu = NULL;
722 uint8_t ipAddr[4] = { 0 };
724 coap_list_t *optList = NULL;
727 uint32_t observeOption;
728 coap_send_flags_t flag = (coap_send_flags_t)0;
730 OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResource"));
733 OC_LOG_V(INFO, TAG, "URI = %s", Uri);
734 VERIFY_SUCCESS(coap_split_uri((unsigned char * )Uri, strlen(Uri), &uri), OC_STACK_OK);
736 // Generate the destination address
737 if (uri.host.length && ParseIPv4Address(uri.host.s, ipAddr, &port)) {
738 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], uri.port,
744 VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, NULL,
745 (uint16_t*)&uri.port, uri.path.length, uri.path.s, uri.query.length,
746 uri.query.s, options, numOptions), OC_STACK_OK);
748 //TODO : Investigate the scenario where there will be no uri for OCDoCoAPResource
749 flag = (coap_send_flags_t) (uri.secure ? SEND_SECURE_PORT : 0);
750 OC_LOG_V(DEBUG, TAG, "uri.host.s %s", uri.host.s);
751 OC_LOG_V(DEBUG, TAG, "uri.path.s %s", uri.path.s);
752 OC_LOG_V(DEBUG, TAG, "uri.port %d", uri.port);
753 OC_LOG_V(DEBUG, TAG, "uri.query.s %s", uri.query.s);
754 OC_LOG_V(DEBUG, TAG, "secure uri %d", uri.secure);
757 coapMsgType = OCToCoAPQoS(qos, ipAddr);
759 // Decide method type
763 case OC_REST_PRESENCE:
765 coapMethod = COAP_REQUEST_GET;
768 coapMethod = COAP_REQUEST_PUT;
771 coapMethod = COAP_REQUEST_POST;
774 coapMethod = COAP_REQUEST_DELETE;
776 case OC_REST_OBSERVE_ALL:
777 case OC_REST_OBSERVE:
778 case OC_REST_CANCEL_OBSERVE:
779 coapMethod = COAP_REQUEST_GET;
780 observeOption = (method == OC_REST_CANCEL_OBSERVE)?
781 OC_OBSERVE_DEREGISTER:OC_OBSERVE_REGISTER;
782 coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_OBSERVE,
783 sizeof(observeOption), (uint8_t *)&observeOption), OrderOptions);
786 coapMethod = OC_REST_NOMETHOD;
787 OC_LOG(FATAL, TAG, PCF("OCDoCoAPResource only supports GET, PUT, & OBSERVE methods"));
791 VERIFY_NON_NULL(gCoAPCtx);
792 pdu = GenerateCoAPPdu(coapMsgType, coapMethod,
793 coap_new_message_id(gCoAPCtx), token,
794 (unsigned char*) payload, optList);
795 VERIFY_NON_NULL(pdu);
797 ret = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &dst, pdu, flag);
800 if (ret!= OC_STACK_OK)
802 OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
807 OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response)
809 OCStackResult result = OC_STACK_ERROR;
810 coap_pdu_t * sendPdu = NULL;
811 coap_list_t *optList = NULL;
812 uint8_t msgType = COAP_MESSAGE_NON;
813 uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
814 uint32_t maxAge = 0x2ffff;
815 coap_send_flags_t sendFlag = (coap_send_flags_t)0;
817 //uint32_t observeOption = OC_OBSERVE_NO_OPTION;
818 //OCStackResult responseResult;
820 OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResponse"));
822 if(response->notificationFlag && response->qos == OC_HIGH_QOS)
824 msgType = COAP_MESSAGE_CON;
826 else if(response->notificationFlag && response->qos != OC_HIGH_QOS)
828 msgType = COAP_MESSAGE_NON;
830 else if(!response->notificationFlag && !response->slowFlag && response->qos == OC_HIGH_QOS)
832 msgType = COAP_MESSAGE_ACK;
834 else if(!response->notificationFlag && response->slowFlag && response->qos == OC_HIGH_QOS)
836 msgType = COAP_MESSAGE_CON;
838 else if(!response->notificationFlag)
840 msgType = COAP_MESSAGE_NON;
843 if(response->coapID == 0)
845 response->coapID = coap_new_message_id(gCoAPCtx);
848 if (response->observationOption != OC_OBSERVE_NO_OPTION)
850 result = FormOptionList(&optList, &mediaType, &maxAge,
851 &response->observationOption, NULL,
852 strlen((char *)response->resourceUri), response->resourceUri,
854 response->sendVendorSpecificHeaderOptions,
855 response->numSendVendorSpecificHeaderOptions);
859 result = FormOptionList(&optList, &mediaType, &maxAge,
861 strlen((char *)response->resourceUri), response->resourceUri,
863 response->sendVendorSpecificHeaderOptions,
864 response->numSendVendorSpecificHeaderOptions);
866 VERIFY_SUCCESS(result, OC_STACK_OK);
868 sendPdu = GenerateCoAPPdu(msgType, OCToCoAPResponseCode(response->result),
869 response->coapID, response->requestToken, (unsigned char *)response->payload,
872 VERIFY_NON_NULL(sendPdu);
873 coap_show_pdu(sendPdu);
875 sendFlag = (coap_send_flags_t)(response->delayedResNeeded ? SEND_DELAYED : 0);
876 sendFlag = (coap_send_flags_t)( sendFlag | (response->secured ? SEND_SECURE_PORT : 0));
878 if (SendCoAPPdu(gCoAPCtx, (coap_address_t *) (response->requesterAddr), sendPdu, sendFlag)
881 OC_LOG(ERROR, TAG, PCF("A problem occurred in sending a pdu"));
882 return OC_STACK_ERROR;
888 OC_LOG(ERROR, TAG, PCF("Error formatting server response"));
889 return OC_STACK_ERROR;
894 * Stop the CoAP client or server processing
896 * @return 0 - success, else - TBD error
898 OCStackResult OCStopCoAP() {
899 OC_LOG(INFO, TAG, PCF("Entering OCStopCoAP"));
900 coap_free_context(gCoAPCtx);
906 * Called in main loop of CoAP client or server. Allows low-level CoAP processing of
907 * send, receive, timeout, discovery, callbacks, etc.
909 * @return 0 - success, else - TBD error
911 OCStackResult OCProcessCoAP() {
913 read = coap_read(gCoAPCtx, gCoAPCtx->sockfd);
915 OC_LOG(INFO, TAG, PCF("This is a Unicast<============"));
917 if (-1 != gCoAPCtx->sockfd_wellknown) {
918 read = coap_read(gCoAPCtx, gCoAPCtx->sockfd_wellknown);
921 OC_LOG(INFO, TAG, PCF("This is a Multicast<==========="));
924 if (-1 != gCoAPCtx->sockfd_dtls) {
925 read = coap_read(gCoAPCtx, gCoAPCtx->sockfd_dtls);
928 OC_LOG(INFO, TAG, PCF("This is a Secure packet<==========="));
931 coap_dispatch(gCoAPCtx);
933 HandleSendQueue(gCoAPCtx);
940 * Retrieve the info about the end-point where resource is being hosted.
941 * Currently, this method only provides the IP port with which the socket
944 * @return 0 - success, else - TBD error
946 OCStackResult OCGetResourceEndPointInfo (OCResource *resPtr, void *info) {
948 OCStackResult result = OC_STACK_ERROR;
950 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceEndPointInfo"));
951 VERIFY_NON_NULL(resPtr);
952 VERIFY_NON_NULL(info);
954 sfd = (resPtr->resourceProperties & OC_SECURE) ? gCoAPCtx->sockfd_dtls :
957 if (OCGetSocketInfo(sfd, (uint16_t*)info) == ERR_SUCCESS)
958 result = OC_STACK_OK;