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 //=============================================================================
26 #include "ocstackconfig.h"
27 #include "occlientcb.h"
28 #include "ocobserve.h"
39 //-----------------------------------------------------------------------------
41 //-----------------------------------------------------------------------------
42 #define TAG PCF("OCCoAP")
43 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
44 {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
45 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg); goto exit;} }
47 //=============================================================================
49 //=============================================================================
51 static uint8_t coapWKIpAddr[] = { 224, 0, 1, 187 };
52 static coap_context_t *gCoAPCtx = NULL;
54 //=============================================================================
56 //=============================================================================
58 //generate a coap token
59 void OCGenerateCoAPToken(OCCoAPToken * token)
63 token->tokenLength = MAX_TOKEN_LENGTH;
64 OCFillRandomMem((uint8_t*)token->token, token->tokenLength);
68 //This function is called back by libcoap when ack or rst are received
69 static void HandleCoAPAckRst(struct coap_context_t * ctx, uint8_t msgType,
70 const coap_queue_t * sentQueue){
75 OCStackResult result = OC_STACK_OK;
76 OCCoAPToken sentToken;
77 uint8_t * observeOption = NULL;
78 coap_pdu_t * sentPdu = sentQueue->pdu;
80 // fill the buffers of Uri and Query
81 result = ParseCoAPPdu(sentPdu, NULL, NULL, &observeOption, NULL, NULL, NULL, NULL);
82 VERIFY_SUCCESS(result, OC_STACK_OK);
84 // fill OCCoAPToken structure
85 RetrieveOCCoAPToken(sentPdu, &sentToken);
87 if(msgType == COAP_MESSAGE_RST){
88 // now the observer should be deleted
89 if(myStackMode != OC_CLIENT)
91 result = OCObserverStatus(&sentToken, OC_OBSERVER_NOT_INTERESTED);
92 if(result == OC_STACK_OK){
94 "Received RST, removing all queues associated with Token %d bytes",
95 sentToken.tokenLength);
96 OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength);
97 coap_cancel_all_messages(ctx, &sentQueue->remote, sentToken.token,
98 sentToken.tokenLength);
101 }else if(observeOption && msgType == COAP_MESSAGE_ACK){
102 OC_LOG_V(DEBUG, TAG, "Received ACK, for Token %d bytes",sentToken.tokenLength);
103 OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength);
104 // now the observer is still interested
105 if(myStackMode != OC_CLIENT)
107 OCObserverStatus(&sentToken, OC_OBSERVER_STILL_INTERESTED);
112 OCFree(observeOption);
115 //This function is called back by libcoap when a request is received
116 static void HandleCoAPRequests(struct coap_context_t *ctx,
117 const coap_queue_t * rcvdRequest)
122 if(myStackMode == OC_CLIENT)
124 //TODO: should the client be responding to requests?
128 OCStackResult result = OC_STACK_ERROR;
129 OCStackResult responseResult = OC_STACK_ERROR;
130 OCRequest * request = NULL;
131 OCEntityHandlerRequest entityHandlerRequest;
132 OCCoAPToken rcvdToken;
133 OCObserveReq * rcvdObsReq = NULL;
134 coap_pdu_t * sendPdu = NULL;
135 coap_list_t *optList = NULL;
136 uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
137 uint32_t maxAge = 0x2ffff;
140 unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
141 unsigned char rcvdQuery[MAX_QUERY_LENGTH] = { 0 };
142 unsigned char bufRes[MAX_RESPONSE_LENGTH] = { 0 };
143 unsigned char newResourceUri[MAX_RESPONSE_LENGTH] = { 0 };
144 uint8_t * rcvObserveOption = NULL;
145 unsigned char * bufReqPayload = NULL;
146 uint32_t observeOption = OC_RESOURCE_NO_OBSERVE;
147 coap_send_flags_t sendFlag;
148 memset(&entityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
150 coap_pdu_t * recvPdu = rcvdRequest->pdu;
152 // fill the buffers of Uri and Query
153 result = ParseCoAPPdu(recvPdu, rcvdUri, rcvdQuery, &rcvObserveOption, NULL, &bufReqPayload,
154 entityHandlerRequest.rcvdVendorSpecificHeaderOptions,
155 &(entityHandlerRequest.numRcvdVendorSpecificHeaderOptions));
156 VERIFY_SUCCESS(result, OC_STACK_OK);
157 if(rcvObserveOption){
158 observeOption = (uint32_t)(*rcvObserveOption);
161 // fill OCCoAPToken structure
162 RetrieveOCCoAPToken(recvPdu, &rcvdToken);
164 switch (recvPdu->hdr->code)
166 case COAP_REQUEST_GET:
168 ocMethod = OC_REST_GET;
171 case COAP_REQUEST_POST:
173 ocMethod = OC_REST_POST;
176 case COAP_REQUEST_DELETE:
178 ocMethod = OC_REST_DELETE;
181 case COAP_REQUEST_PUT:
183 ocMethod = OC_REST_PUT;
188 OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
194 // fill OCEntityHandlerRequest structure
195 result = FormOCEntityHandlerRequest(&entityHandlerRequest, ocMethod,
196 bufRes, bufReqPayload, rcvdQuery, newResourceUri);
197 VERIFY_SUCCESS(result, OC_STACK_OK);
200 result = FormOCObserveReq(&rcvdObsReq, observeOption,
201 (OCDevAddr *)&(rcvdRequest->remote), &rcvdToken);
202 VERIFY_SUCCESS(result, OC_STACK_OK);
204 // fill OCRequest structure
205 result = FormOCRequest(&request, (recvPdu->hdr->type == COAP_MESSAGE_CON) ?
206 OC_HIGH_QOS : OC_LOW_QOS, rcvdUri, rcvdObsReq, &entityHandlerRequest);
207 VERIFY_SUCCESS(result, OC_STACK_OK);
209 OC_LOG_V(INFO, TAG, " Receveid uri: %s", request->resourceUrl);
210 OC_LOG_V(INFO, TAG, " Receveid query: %s", entityHandlerRequest.query);
211 OC_LOG_V(INFO, TAG, " Receveid payload: %s",
212 request->entityHandlerRequest->reqJSONPayload);
213 OC_LOG_V(INFO, TAG, " Token received %d bytes",
214 rcvdToken.tokenLength);
215 OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);
217 // process the request
218 responseResult = HandleStackRequests(request);
220 if(responseResult == OC_STACK_PRESENCE_DO_NOT_HANDLE)
226 OC_LOG_V(INFO, TAG, "Response from ocstack: %s",
227 request->entityHandlerRequest->resJSONPayload);
231 switch(rcvdObsReq->result)
234 observeOption = rcvdObsReq->option;
235 result = FormOptionList(&optList, &mediaType, &maxAge,
236 sizeof(observeOption), &observeOption,
237 NULL, 0, NULL, 0, NULL,
238 request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
239 request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
241 case OC_STACK_OBSERVER_NOT_ADDED:
242 case OC_STACK_OBSERVER_NOT_REMOVED:
243 case OC_STACK_INVALID_OBSERVE_PARAM:
245 result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
247 request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
248 request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
254 if (responseResult == OC_STACK_RESOURCE_CREATED)
256 result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
257 strlen((char *)newResourceUri), newResourceUri, 0, NULL,
258 request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
259 request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
263 result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
265 request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
266 request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
270 VERIFY_SUCCESS(result, OC_STACK_OK);
272 // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
273 sendPdu = GenerateCoAPPdu(
274 (rcvdRequest->pdu->hdr->type == COAP_MESSAGE_CON) ?
275 COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
276 OCToCoAPResponseCode(responseResult), rcvdRequest->pdu->hdr->id,
278 request->entityHandlerRequest->resJSONPayload, optList);
279 VERIFY_NON_NULL(sendPdu);
280 coap_show_pdu(sendPdu);
282 sendFlag = (coap_send_flags_t)(rcvdRequest->delayedResponse ? SEND_DELAYED : 0);
283 sendFlag = (coap_send_flags_t)( sendFlag | (rcvdRequest->secure ? SEND_SECURE_PORT : 0));
285 if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
288 OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
292 OCFree(rcvObserveOption);
297 uint32_t GetTime(float afterSeconds)
301 return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
304 //This function is called back by libcoap when a response is received
305 static void HandleCoAPResponses(struct coap_context_t *ctx,
306 const coap_queue_t * rcvdResponse) {
307 OCResponse * response = NULL;
308 OCCoAPToken rcvdToken;
309 OCClientResponse clientResponse;
310 ClientCB * cbNode = NULL;
311 unsigned char * bufRes = NULL;
312 uint8_t * rcvObserveOption = NULL;
313 uint8_t * rcvMaxAgeOption = NULL;
314 uint32_t sequenceNumber = OC_RESOURCE_NO_OBSERVE;
316 OCStackResult result = OC_STACK_ERROR;
317 coap_pdu_t *sendPdu = NULL;
318 coap_pdu_t * recvPdu = NULL;
319 uint8_t remoteIpAddr[4];
320 uint16_t remotePortNu;
321 unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
322 unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
323 uint8_t isObserveNotification = 0;
325 uint8_t isPresenceNotification = 0;
327 uint32_t higherBound;
330 memset(&clientResponse, 0, sizeof(OCClientResponse));
332 VERIFY_NON_NULL(ctx);
333 VERIFY_NON_NULL(rcvdResponse);
334 recvPdu = rcvdResponse->pdu;
336 result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &rcvObserveOption, &rcvMaxAgeOption, &bufRes,
337 clientResponse.rcvdVendorSpecificHeaderOptions,
338 &(clientResponse.numRcvdVendorSpecificHeaderOptions));
339 VERIFY_SUCCESS(result, OC_STACK_OK);
341 if(rcvObserveOption){
342 sequenceNumber = *((uint32_t *) rcvObserveOption);
346 maxAge = *((uint32_t *) rcvMaxAgeOption);
349 OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u", sequenceNumber);
350 OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", maxAge);
351 OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
353 if(sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
355 isObserveNotification = 1;
356 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
360 if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
361 isPresenceNotification = 1;
362 OC_LOG(INFO, TAG, PCF("Received a presence notification"));
363 tok = strtok((char *)bufRes, ":");
364 sequenceNumber = (uint32_t )atoi(tok);
365 OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
366 tok = strtok(NULL, ":");
367 maxAge = (uint32_t )atoi(tok);
368 OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
369 bufRes[strlen((char *)bufRes)] = ':';
373 // fill OCCoAPToken structure
374 RetrieveOCCoAPToken(recvPdu, &rcvdToken);
375 OC_LOG_V(INFO, TAG,"Received a pdu with Token", rcvdToken.tokenLength);
376 OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);
378 // fill OCClientResponse structure
379 result = FormOCClientResponse(&clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code),
380 (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, bufRes);
381 VERIFY_SUCCESS(result, OC_STACK_OK);
383 cbNode = GetClientCB(&rcvdToken, NULL, NULL);
386 // we should check if we are monitoring the presence of this resource
387 //get the address of the remote
388 OCDevAddrToIPv4Addr((OCDevAddr *) &(rcvdResponse->remote), remoteIpAddr,
389 remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
390 OCDevAddrToPort((OCDevAddr *) &(rcvdResponse->remote), &remotePortNu);
391 sprintf((char *)fullUri, "coap://%d.%d.%d.%d:%d%s",
392 remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
393 remotePortNu,rcvdUri);
394 cbNode = GetClientCB(NULL, NULL, fullUri);
397 // fill OCResponse structure
398 result = FormOCResponse(&response, cbNode, maxAge, &clientResponse);
399 VERIFY_SUCCESS(result, OC_STACK_OK);
403 if(isObserveNotification)
405 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
406 if(recvPdu->hdr->type == COAP_MESSAGE_CON)
408 sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0,
409 recvPdu->hdr->id, NULL, NULL, NULL);
410 VERIFY_NON_NULL(sendPdu);
411 result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
413 (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
415 //TODO: check the standard for methods to detect wrap around condition
416 if(cbNode->method == OC_REST_OBSERVE &&
417 (clientResponse.sequenceNumber <= cbNode->sequenceNumber ||
418 (clientResponse.sequenceNumber > cbNode->sequenceNumber &&
419 clientResponse.sequenceNumber == MAX_SEQUENCE_NUMBER)))
421 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
422 Ignoring Incoming:%d Against Current:%d.",
423 clientResponse.sequenceNumber, cbNode->sequenceNumber);
426 if(clientResponse.sequenceNumber > cbNode->sequenceNumber){
427 cbNode->sequenceNumber = clientResponse.sequenceNumber;
433 if(isPresenceNotification)
435 OC_LOG(INFO, TAG, PCF("Received a presence notification"));
436 if(!cbNode->presence)
438 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
439 VERIFY_NON_NULL(cbNode->presence);
440 cbNode->presence->timeOut = NULL;
441 cbNode->presence->timeOut = (uint32_t *)
442 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
443 if(!(cbNode->presence->timeOut)){
444 OCFree(cbNode->presence);
450 OC_LOG(INFO, TAG, "===============Stopping presence");
451 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
455 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
456 cbNode->presence->TTL = maxAge;
457 for(int index = 0; index < PresenceTimeOutSize; index++)
459 lowerBound = GetTime(((float)(PresenceTimeOut[index])
460 /(float)100)*(float)cbNode->presence->TTL);
461 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
462 /(float)100)*(float)cbNode->presence->TTL);
463 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
464 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
465 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
466 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d", cbNode->presence->timeOut[index]);
468 cbNode->presence->TTLlevel = 0;
469 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
470 if(cbNode->sequenceNumber == clientResponse.sequenceNumber)
472 OC_LOG(INFO, TAG, "===============No presence change");
475 OC_LOG(INFO, TAG, "===============Presence changed, calling up the stack");
476 cbNode->sequenceNumber = clientResponse.sequenceNumber;;
481 HandleStackResponses(response);
483 else if(!cbNode && isObserveNotification)
485 OC_LOG(INFO, TAG, PCF("Received an observe notification, but I do not have callback \
486 ------------ sending RESET"));
487 sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0,
488 recvPdu->hdr->id, NULL, NULL, NULL);
489 VERIFY_NON_NULL(sendPdu);
490 result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, sendPdu,
491 (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
492 VERIFY_SUCCESS(result, OC_STACK_OK);
495 else if(!cbNode && isPresenceNotification)
497 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
498 ------------ ignoring"));
503 OC_LOG(INFO, TAG, PCF("Received a response, but I do not have callback. \
504 ------------ sending RESET"));
505 sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0,
506 recvPdu->hdr->id, NULL, NULL, NULL);
507 VERIFY_NON_NULL(sendPdu);
508 result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, sendPdu,
509 (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
510 VERIFY_SUCCESS(result, OC_STACK_OK);
513 OCFree(rcvObserveOption);
514 OCFree(rcvMaxAgeOption);
518 //=============================================================================
520 //=============================================================================
523 * Initialize the CoAP client or server with its IPv4 address and CoAP port
526 * IP Address of host device
528 * Port of host device
530 * Host device is client, server, or client-server
536 OCStackResult OCInitCoAP(const char *address, uint16_t port, OCMode mode) {
538 OCStackResult ret = OC_STACK_ERROR;
540 TODO ("Below should go away and be replaced by OC_LOG");
541 coap_log_t log_level = (coap_log_t)(LOG_DEBUG + 1);
544 uint8_t ipAddr[4] = { 0 };
545 uint16_t parsedPort = 0;
547 OC_LOG(INFO, TAG, PCF("Entering OCInitCoAP"));
549 coap_set_log_level(log_level);
553 if (!ParseIPv4Address((unsigned char *) address, ipAddr, &parsedPort))
555 ret = OC_STACK_ERROR;
559 OC_LOG_V(INFO, TAG, "Parsed IP Address %d.%d.%d.%d",
560 ipAddr[0],ipAddr[1],ipAddr[2],ipAddr[3]);
563 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
566 gCoAPCtx = coap_new_context((coap_address_t*) &devAddr);
567 VERIFY_NON_NULL(gCoAPCtx);
569 // To allow presence notification work we need to init socket gCoAPCtx->sockfd_wellknown
570 // for servers as well as clients
571 OCBuildIPv4Address(coapWKIpAddr[0], coapWKIpAddr[1], coapWKIpAddr[2],
572 coapWKIpAddr[3], COAP_DEFAULT_PORT, &mcastAddr);
574 coap_join_wellknown_group(gCoAPCtx,
575 (coap_address_t* )&mcastAddr), 0);
577 coap_register_request_handler(gCoAPCtx, HandleCoAPRequests);
578 coap_register_response_handler(gCoAPCtx, HandleCoAPResponses);
579 coap_register_ack_rst_handler(gCoAPCtx, HandleCoAPAckRst);
584 if (ret != OC_STACK_OK)
592 * Discover OC resources
594 * @param method - method to perform on the resource
595 * @param qos - Quality of Service the request will be sent on
596 * @param token - token which will added to the request
597 * @param Uri - URI of the resource to interact with
598 * @param payload - the request payload to be added to the request before sending
599 * by the stack when discovery or resource interaction is complete
600 * @param options - The address of an array containing the vendor specific
601 * header options to be sent with the request
606 OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token,
607 const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions)
610 OCStackResult ret = OC_STACK_ERROR;
611 coap_pdu_t *pdu = NULL;
614 uint8_t ipAddr[4] = { 0 };
616 coap_list_t *optList = NULL;
619 uint32_t observeOption;
620 coap_send_flags_t flag = (coap_send_flags_t)0;
622 OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResource"));
625 OC_LOG_V(INFO, TAG, "URI = %s", Uri);
626 VERIFY_SUCCESS(coap_split_uri((unsigned char * )Uri, strlen(Uri), &uri), OC_STACK_OK);
628 // Generate the destination address
629 if (uri.host.length && ParseIPv4Address(uri.host.s, ipAddr, &port)) {
630 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], uri.port,
636 VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, 0, NULL,
637 (uint16_t*)&uri.port, uri.path.length, uri.path.s, uri.query.length,
638 uri.query.s, options, numOptions), OC_STACK_OK);
640 //TODO : Investigate the scenario where there will be no uri for OCDoCoAPResource
641 //flag = (coap_send_flags_t) (uri.secure ? SEND_SECURE_PORT : 0);
642 OC_LOG_V(DEBUG, TAG, "uri.host.s %s", uri.host.s);
643 OC_LOG_V(DEBUG, TAG, "uri.path.s %s", uri.path.s);
644 OC_LOG_V(DEBUG, TAG, "uri.port %d", uri.port);
645 OC_LOG_V(DEBUG, TAG, "uri.query.s %s", uri.query.s);
648 coapMsgType = OCToCoAPQoS(qos);
650 // Decide method type
654 case OC_REST_PRESENCE:
656 coapMethod = COAP_REQUEST_GET;
659 coapMethod = COAP_REQUEST_PUT;
662 coapMethod = COAP_REQUEST_POST;
665 coapMethod = COAP_REQUEST_DELETE;
667 case OC_REST_OBSERVE_ALL:
668 case OC_REST_OBSERVE:
669 case OC_REST_CANCEL_OBSERVE:
670 coapMethod = COAP_REQUEST_GET;
671 observeOption = (method == OC_REST_CANCEL_OBSERVE)?
672 OC_RESOURCE_OBSERVE_DEREGISTER:OC_RESOURCE_OBSERVE_REGISTER;
673 coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_OBSERVE,
674 sizeof(observeOption), (uint8_t *)&observeOption), OrderOptions);
677 coapMethod = OC_REST_NOMETHOD;
678 OC_LOG(FATAL, TAG, PCF("OCDoCoAPResource only supports GET, PUT, & OBSERVE methods"));
682 VERIFY_NON_NULL(gCoAPCtx);
683 pdu = GenerateCoAPPdu(coapMsgType, coapMethod,
684 coap_new_message_id(gCoAPCtx), token,
685 (unsigned char*) payload, optList);
686 VERIFY_NON_NULL(pdu);
688 ret = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &dst, pdu, flag);
691 if (ret!= OC_STACK_OK)
693 OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
698 OCStackResult OCSendCoAPNotification (unsigned char * uri, OCDevAddr *dstAddr,
699 OCQualityOfService qos, OCCoAPToken * token,
700 unsigned char *payload, OCResource *resPtr, uint32_t maxAge)
702 OCStackResult result = OC_STACK_ERROR;
703 coap_list_t *optList = NULL;
704 uint8_t coapMsgType = COAP_MESSAGE_NON;
705 uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
708 OC_LOG(INFO, TAG, PCF("Entering OCSendCoAPNotification"));
710 coapMsgType = OCToCoAPQoS(qos);
713 if(!strcmp((const char *)uri, OC_PRESENCE_URI))
715 result = FormOptionList(&optList, &mediaType, NULL, 0, NULL,
716 NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
721 result = FormOptionList(&optList, &mediaType, &maxAge, sizeof(resPtr->sequenceNum),
722 &resPtr->sequenceNum, NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
726 VERIFY_SUCCESS(result, OC_STACK_OK);
728 if(resPtr->resourceProperties == 0)
730 result = OC_STACK_RESOURCE_DELETED;
733 sendPdu = GenerateCoAPPdu(
734 coapMsgType == COAP_MESSAGE_CON ? COAP_MESSAGE_CON : COAP_MESSAGE_NON,
735 OCToCoAPResponseCode(result), coap_new_message_id(gCoAPCtx),
736 token, payload, optList);
737 VERIFY_NON_NULL(sendPdu);
738 coap_show_pdu(sendPdu);
740 // TODO : resourceProperties will determine if the packet will be send using secure port
741 if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) dstAddr, sendPdu , (coap_send_flags_t)0 )
744 OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
748 return OC_STACK_ERROR;
752 * Stop the CoAP client or server processing
754 * @return 0 - success, else - TBD error
756 OCStackResult OCStopCoAP() {
757 OC_LOG(INFO, TAG, PCF("Entering OCStopCoAP"));
758 coap_free_context(gCoAPCtx);
764 * Called in main loop of CoAP client or server. Allows low-level CoAP processing of
765 * send, receive, timeout, discovery, callbacks, etc.
767 * @return 0 - success, else - TBD error
769 OCStackResult OCProcessCoAP() {
771 OC_LOG(INFO, TAG, PCF("Entering OCProcessCoAP"));
773 read = coap_read(gCoAPCtx, gCoAPCtx->sockfd);
776 OC_LOG(INFO, TAG, PCF("This is a Unicast<============"));
778 if (-1 != gCoAPCtx->sockfd_wellknown) {
779 read = coap_read(gCoAPCtx, gCoAPCtx->sockfd_wellknown);
782 OC_LOG(INFO, TAG, PCF("This is a Multicast<==========="));
785 coap_dispatch(gCoAPCtx);
787 HandleSendQueue(gCoAPCtx);