Fixes for scons builds
[platform/upstream/iotivity.git] / resource / csdk / occoap / src / occoap.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21
22 //=============================================================================
23 // Includes
24 //=============================================================================
25 #include "occoap.h"
26 #include "ocstackconfig.h"
27 #include "occlientcb.h"
28 #include "ocobserve.h"
29 #include "logger.h"
30 #include "ocmalloc.h"
31 #include <coap.h>
32
33 #ifndef WITH_ARDUINO
34 #include <unistd.h>
35 #endif
36 #include <limits.h>
37 #include <ctype.h>
38
39 //=============================================================================
40 // Macros
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;} }
46
47 //=============================================================================
48 // Defines
49 //=============================================================================
50 #define COAP_BLOCK_FILL_VALUE   (0xFF)
51
52 //=============================================================================
53 // Private Variables
54 //=============================================================================
55
56 static uint8_t coapWKIpAddr[] = { 224, 0, 1, 187 };
57 static coap_context_t *gCoAPCtx = NULL;
58
59 //=============================================================================
60 // Helper Functions
61 //=============================================================================
62
63 //generate a coap token
64 void OCGenerateCoAPToken(OCCoAPToken * token)
65 {
66     if (token)
67     {
68         token->tokenLength = MAX_TOKEN_LENGTH;
69         OCFillRandomMem((uint8_t*)token->token, token->tokenLength);
70     }
71 }
72
73 //This function is called back by libcoap when ack or rst are received
74 static void HandleCoAPAckRst(struct coap_context_t * ctx, uint8_t msgType,
75         const coap_queue_t * sentQueue){
76
77     // silence warnings
78     (void) ctx;
79     coap_pdu_t * sentPdu = sentQueue->pdu;
80     OCStackResult result = OC_STACK_ERROR;
81     uint32_t observationOption = OC_OBSERVE_NO_OPTION;
82     // {{0}} to eliminate warning for known compiler bug 53119
83     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
84     OCCoAPToken sentToken = {{0}};
85
86     result = ParseCoAPPdu(sentPdu, NULL, NULL, &observationOption, NULL, NULL, NULL,
87             NULL, NULL, NULL, NULL, NULL);
88     VERIFY_SUCCESS(result, OC_STACK_OK);
89
90     // fill OCCoAPToken structure
91     RetrieveOCCoAPToken(sentPdu, &sentToken);
92
93     if(msgType == COAP_MESSAGE_RST)
94     {
95         if(myStackMode != OC_CLIENT)
96         {
97             result = OCStackFeedBack(&sentToken, OC_OBSERVER_NOT_INTERESTED);
98             if(result == OC_STACK_OK)
99             {
100                 OC_LOG_V(DEBUG, TAG,
101                         "Received RST, removing all queues associated with Token %d bytes",
102                         sentToken.tokenLength);
103                 OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength);
104                 coap_cancel_all_messages(ctx, &sentQueue->remote, sentToken.token,
105                         sentToken.tokenLength);
106             }
107         }
108     }
109     else if(observationOption != OC_OBSERVE_NO_OPTION && msgType == COAP_MESSAGE_ACK)
110     {
111         OC_LOG_V(DEBUG, TAG, "Received ACK, for Token %d bytes",sentToken.tokenLength);
112         OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength);
113         // now the observer is still interested
114         if(myStackMode != OC_CLIENT)
115         {
116             OCStackFeedBack(&sentToken, OC_OBSERVER_STILL_INTERESTED);
117         }
118     }
119 exit:
120     return;
121 }
122
123 //This function is called back by libcoap when a request is received
124 static void HandleCoAPRequests(struct coap_context_t *ctx,
125         const coap_queue_t * rcvdRequest)
126 {
127     // silence warnings
128     (void) ctx;
129     OCServerProtocolRequest protocolRequest = {(OCMethod)0};
130     coap_block_t rcvdBlock1;
131     coap_block_t rcvdBlock2;
132     memset(&rcvdBlock1, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
133     memset(&rcvdBlock2, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
134     uint16_t rcvdSize1 = 0;
135     coap_pdu_t * rcvdPdu = rcvdRequest->pdu;
136     coap_pdu_t * sendPdu = NULL;
137     coap_send_flags_t sendFlag;
138     OCStackResult result = OC_STACK_ERROR;
139     OCStackResult requestResult = OC_STACK_ERROR;
140
141     if(myStackMode == OC_CLIENT)
142     {
143         //TODO: should the client be responding to requests?
144         return;
145     }
146
147     protocolRequest.observationOption = OC_OBSERVE_NO_OPTION;
148     protocolRequest.qos = (rcvdPdu->hdr->type == COAP_MESSAGE_CON) ?
149             OC_HIGH_QOS : OC_LOW_QOS;
150     protocolRequest.coapID = rcvdPdu->hdr->id;
151     protocolRequest.delayedResNeeded = rcvdRequest->delayedResNeeded;
152     protocolRequest.secured = rcvdRequest->secure;
153
154     // fill OCCoAPToken structure
155     RetrieveOCCoAPToken(rcvdPdu, &protocolRequest.requestToken);
156     OC_LOG_V(INFO, TAG, " Token received %d bytes",
157             protocolRequest.requestToken.tokenLength);
158     OC_LOG_BUFFER(INFO, TAG, protocolRequest.requestToken.token,
159             protocolRequest.requestToken.tokenLength);
160
161     // fill OCDevAddr
162     memcpy(&protocolRequest.requesterAddr, (OCDevAddr *) &rcvdRequest->remote,
163             sizeof(OCDevAddr));
164
165     // Retrieve Uri and Query from received coap pdu
166     result =  ParseCoAPPdu(rcvdPdu, protocolRequest.resourceUrl,
167             protocolRequest.query,
168             &(protocolRequest.observationOption), NULL,
169             &(protocolRequest.numRcvdVendorSpecificHeaderOptions),
170             protocolRequest.rcvdVendorSpecificHeaderOptions,
171             &rcvdBlock1, &rcvdBlock2, &rcvdSize1, NULL,
172             protocolRequest.reqJSONPayload);
173     VERIFY_SUCCESS(result, OC_STACK_OK);
174
175     switch (rcvdPdu->hdr->code)
176     {
177         case COAP_REQUEST_GET:
178         {
179             protocolRequest.method = OC_REST_GET;
180             break;
181         }
182         case COAP_REQUEST_POST:
183         {
184             protocolRequest.method = OC_REST_POST;
185             break;
186         }
187         case COAP_REQUEST_DELETE:
188         {
189             protocolRequest.method = OC_REST_DELETE;
190             break;
191         }
192         case COAP_REQUEST_PUT:
193         {
194             protocolRequest.method = OC_REST_PUT;
195             break;
196         }
197         default:
198         {
199             OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
200                     rcvdPdu->hdr->code);
201             goto exit;
202         }
203     }
204
205     if(rcvdBlock1.szx != 7)
206     {
207         protocolRequest.reqPacketSize = 1 << (rcvdBlock1.szx + 4);
208         protocolRequest.reqMorePacket = rcvdBlock1.m;
209         protocolRequest.reqPacketNum  = rcvdBlock1.num;
210     }
211     else
212     {
213         // No block1 received
214         rcvdSize1= strlen((const char*)protocolRequest.reqJSONPayload)+1;
215         protocolRequest.reqTotalSize = rcvdSize1;
216     }
217
218     if(rcvdBlock2.szx != 7)
219     {
220         protocolRequest.resPacketSize = 1 << (rcvdBlock2.szx + 4);
221         protocolRequest.resPacketNum  = rcvdBlock2.num;
222     }
223
224     requestResult = HandleStackRequests(&protocolRequest);
225
226     if(requestResult == OC_STACK_VIRTUAL_DO_NOT_HANDLE ||
227             requestResult == OC_STACK_OK ||
228             requestResult == OC_STACK_RESOURCE_CREATED ||
229             requestResult == OC_STACK_RESOURCE_DELETED)
230     {
231         goto exit;
232     }
233     else if(requestResult == OC_STACK_NO_MEMORY ||
234             requestResult == OC_STACK_ERROR ||
235             requestResult == OC_STACK_NOTIMPL ||
236             requestResult == OC_STACK_NO_RESOURCE ||
237             requestResult == OC_STACK_RESOURCE_ERROR)
238     {
239         // TODO: should we send an error also when we receive a non-secured request to a secure resource?
240         // TODO: should we consider some sort of error response
241         OC_LOG(DEBUG, TAG, PCF("We should send some sort of error message"));
242         // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
243         sendPdu = GenerateCoAPPdu((rcvdPdu->hdr->type == COAP_MESSAGE_CON)? COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
244                 OCToCoAPResponseCode(requestResult), rcvdPdu->hdr->id,
245                 &protocolRequest.requestToken, NULL, NULL);
246         VERIFY_NON_NULL(sendPdu);
247         coap_show_pdu(sendPdu);
248         sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
249         if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
250                 sendFlag)
251                 != OC_STACK_OK){
252             OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
253         }
254         goto exit;
255     }
256     else if(requestResult == OC_STACK_SLOW_RESOURCE)
257     {
258         if(rcvdPdu->hdr->type == COAP_MESSAGE_CON)
259         {
260             // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
261             sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, rcvdPdu->hdr->id,
262                     NULL, NULL, NULL);
263             VERIFY_NON_NULL(sendPdu);
264             coap_show_pdu(sendPdu);
265
266             sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
267             if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
268                     sendFlag)
269                     != OC_STACK_OK){
270                 OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
271             }
272         }
273         else
274         {
275             goto exit;
276         }
277     }
278 exit:
279     return;
280 }
281
282 uint32_t GetTime(float afterSeconds)
283 {
284     coap_tick_t now;
285     coap_ticks(&now);
286     return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
287 }
288
289 //This function is called back by libcoap when a response is received
290 static void HandleCoAPResponses(struct coap_context_t *ctx,
291         const coap_queue_t * rcvdResponse) {
292     OCStackResult result = OC_STACK_OK;
293     OCCoAPToken rcvdToken = {{0}};
294     OCResponse * response = NULL;
295     OCClientResponse * clientResponse = NULL;
296     unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
297     coap_pdu_t * sendPdu = NULL;
298     coap_pdu_t * recvPdu = NULL;
299     uint8_t remoteIpAddr[4] = {0};
300     uint16_t remotePortNu = 0;
301     uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
302     uint32_t maxAge = 0;
303     unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
304     unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
305     coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE};
306     coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE};
307     uint16_t rcvdSize2 = 0;
308
309     VERIFY_NON_NULL(ctx);
310     VERIFY_NON_NULL(rcvdResponse);
311     recvPdu = rcvdResponse->pdu;
312
313     clientResponse = (OCClientResponse *) OCCalloc(1, sizeof(OCClientResponse));
314
315     result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge,
316             &(clientResponse->numRcvdVendorSpecificHeaderOptions),
317             clientResponse->rcvdVendorSpecificHeaderOptions,
318             &rcvdBlock1, &rcvdBlock2, NULL, &rcvdSize2, bufRes);
319     VERIFY_SUCCESS(result, OC_STACK_OK);
320
321     // get the address of the remote
322     OCDevAddrToIPv4Addr((OCDevAddr *) &(rcvdResponse->remote), remoteIpAddr,
323             remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
324     OCDevAddrToPort((OCDevAddr *) &(rcvdResponse->remote), &remotePortNu);
325     snprintf((char *)fullUri, MAX_URI_LENGTH, "coap://%d.%d.%d.%d:%d%s",
326             remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
327             remotePortNu,rcvdUri);
328
329     // fill OCCoAPToken structure
330     RetrieveOCCoAPToken(recvPdu, &rcvdToken);
331     OC_LOG_V(INFO, TAG,"Received a pdu with Token", rcvdToken.tokenLength);
332     OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);
333
334     // fill OCClientResponse structure
335     result = FormOCClientResponse(clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code),
336             (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, NULL);
337     VERIFY_SUCCESS(result, OC_STACK_OK);
338
339     result = FormOCResponse(&response, NULL, maxAge, fullUri, rcvdUri,
340             &rcvdToken, clientResponse, bufRes);
341     VERIFY_SUCCESS(result, OC_STACK_OK);
342
343     result = HandleStackResponses(response);
344
345     if(result == OC_STACK_ERROR)
346     {
347         OC_LOG(INFO, TAG, PCF("Received a notification or response that is malformed or incorrect \
348                          ------------ sending RESET"));
349         sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0,
350                 recvPdu->hdr->id, NULL, NULL, NULL);
351         VERIFY_NON_NULL(sendPdu);
352         result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, sendPdu,
353                      (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
354         VERIFY_SUCCESS(result, OC_STACK_OK);
355     }
356     else if(result == OC_STACK_NO_MEMORY)
357     {
358         OC_LOG(ERROR, TAG, PCF("Received a notification or response. While processing, local " \
359                 "platform or memory pool ran out memory."));
360     }
361
362     if(recvPdu->hdr->type == COAP_MESSAGE_CON)
363     {
364         sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0,
365                 recvPdu->hdr->id, NULL, NULL, NULL);
366         VERIFY_NON_NULL(sendPdu);
367         result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
368                 sendPdu,
369                 (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
370         VERIFY_SUCCESS(result, OC_STACK_OK);
371     }
372
373     exit:
374         OCFree(response);
375         OCFree(clientResponse);
376 }
377
378 //=============================================================================
379 // Functions
380 //=============================================================================
381
382 /**
383  * Initialize the CoAP client or server with its IPv4 address and CoAP port
384  *
385  * @param ipAddr
386  *     IP Address of host device
387  * @param port
388  *     Port of host device
389  * @param mode
390  *     Host device is client, server, or client-server
391  *
392  * @return
393  *   0   - success
394  *   TBD - TBD error
395  */
396 OCStackResult OCInitCoAP(const char *address, uint16_t port, OCMode mode) {
397
398     OCStackResult ret = OC_STACK_ERROR;
399
400     TODO ("Below should go away and be replaced by OC_LOG");
401     coap_log_t log_level = (coap_log_t)(LOG_DEBUG + 1);
402     OCDevAddr mcastAddr;
403     uint8_t ipAddr[4] = { 0 };
404     uint16_t parsedPort = 0;
405
406     OC_LOG(INFO, TAG, PCF("Entering OCInitCoAP"));
407
408     coap_set_log_level(log_level);
409
410     if (address)
411     {
412         if (!ParseIPv4Address((unsigned char *) address, ipAddr, &parsedPort))
413         {
414             ret = OC_STACK_ERROR;
415             goto exit;
416         }
417
418         OC_LOG_V(INFO, TAG, "Parsed IP Address %d.%d.%d.%d",
419                                ipAddr[0],ipAddr[1],ipAddr[2],ipAddr[3]);
420     }
421
422     gCoAPCtx = coap_new_context(ipAddr, port);
423     VERIFY_NON_NULL(gCoAPCtx);
424
425     // To allow presence notification work we need to init socket gCoAPCtx->sockfd_wellknown
426     // for servers as well as clients
427     OCBuildIPv4Address(coapWKIpAddr[0], coapWKIpAddr[1], coapWKIpAddr[2],
428             coapWKIpAddr[3], COAP_DEFAULT_PORT, &mcastAddr);
429     VERIFY_SUCCESS(
430             coap_join_wellknown_group(gCoAPCtx,
431                     (coap_address_t* )&mcastAddr), 0);
432
433     coap_register_request_handler(gCoAPCtx, HandleCoAPRequests);
434     coap_register_response_handler(gCoAPCtx, HandleCoAPResponses);
435     coap_register_ack_rst_handler(gCoAPCtx, HandleCoAPAckRst);
436
437     ret = OC_STACK_OK;
438
439 exit:
440     if (ret != OC_STACK_OK)
441     {
442         OCStopCoAP();
443     }
444     return ret;
445 }
446
447 /**
448  * Discover OC resources
449  *
450  * @param method          - method to perform on the resource
451  * @param qos             - Quality of Service the request will be sent on
452  * @param token           - token which will added to the request
453  * @param Uri             - URI of the resource to interact with
454  * @param payload         - the request payload to be added to the request before sending
455  *                          by the stack when discovery or resource interaction is complete
456  * @param options         - The address of an array containing the vendor specific
457  *                          header options to be sent with the request
458  * @return
459  *   0   - success
460  *   TBD - TBD error
461  */
462 OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token,
463                      const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions)
464 {
465
466     OCStackResult ret = OC_STACK_ERROR;
467     coap_pdu_t *pdu = NULL;
468     coap_uri_t uri;
469     OCDevAddr dst;
470     uint8_t ipAddr[4] = { 0 };
471     uint16_t port = 0;
472     coap_list_t *optList = NULL;
473     uint8_t coapMsgType;
474     uint8_t coapMethod;
475     uint32_t observeOption;
476     coap_send_flags_t flag = (coap_send_flags_t)0;
477
478     OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResource"));
479
480     if (Uri) {
481         OC_LOG_V(INFO, TAG, "URI = %s", Uri);
482         VERIFY_SUCCESS(coap_split_uri((unsigned char * )Uri, strlen(Uri), &uri), OC_STACK_OK);
483
484         // Generate the destination address
485         if (uri.host.length && ParseIPv4Address(uri.host.s, ipAddr, &port)) {
486             OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], uri.port,
487                     &dst);
488         } else {
489             goto exit;
490         }
491
492         VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, NULL,
493                 (uint16_t*)&uri.port, uri.path.length, uri.path.s, uri.query.length,
494                 uri.query.s, options, numOptions), OC_STACK_OK);
495
496         //TODO : Investigate the scenario where there will be no uri for OCDoCoAPResource
497         flag = (coap_send_flags_t) (uri.secure ? SEND_SECURE_PORT : 0);
498         OC_LOG_V(DEBUG, TAG, "uri.host.s %s", uri.host.s);
499         OC_LOG_V(DEBUG, TAG, "uri.path.s %s", uri.path.s);
500         OC_LOG_V(DEBUG, TAG, "uri.port %d", uri.port);
501         OC_LOG_V(DEBUG, TAG, "uri.query.s %s", uri.query.s);
502         OC_LOG_V(DEBUG, TAG, "secure uri %d", uri.secure);
503     }
504
505     coapMsgType = OCToCoAPQoS(qos);
506
507     // Decide method type
508     switch (method) {
509         case OC_REST_GET:
510             coapMethod = COAP_REQUEST_GET;
511             break;
512         case OC_REST_PUT:
513             coapMethod = COAP_REQUEST_PUT;
514             break;
515         case OC_REST_POST:
516             coapMethod = COAP_REQUEST_POST;
517             break;
518         case OC_REST_DELETE:
519             coapMethod = COAP_REQUEST_DELETE;
520             break;
521         case OC_REST_OBSERVE_ALL:
522         case OC_REST_OBSERVE:
523         case OC_REST_CANCEL_OBSERVE:
524             coapMethod = COAP_REQUEST_GET;
525             observeOption = (method == OC_REST_CANCEL_OBSERVE)?
526                     OC_OBSERVE_DEREGISTER:OC_OBSERVE_REGISTER;
527             coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_OBSERVE,
528                         sizeof(observeOption), (uint8_t *)&observeOption), OrderOptions);
529             break;
530         default:
531             coapMethod = OC_REST_NOMETHOD;
532             OC_LOG(FATAL, TAG, PCF("OCDoCoAPResource only supports GET, PUT, & OBSERVE methods"));
533             break;
534     }
535
536     VERIFY_NON_NULL(gCoAPCtx);
537     pdu = GenerateCoAPPdu(coapMsgType, coapMethod,
538             coap_new_message_id(gCoAPCtx), token,
539             (unsigned char*) payload, optList);
540     VERIFY_NON_NULL(pdu);
541
542     ret = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &dst, pdu, flag);
543
544 exit:
545     if (ret!= OC_STACK_OK)
546     {
547         OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
548     }
549     return ret;
550 }
551
552 OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response)
553 {
554     OCStackResult result = OC_STACK_ERROR;
555     coap_pdu_t * sendPdu = NULL;
556     coap_list_t *optList = NULL;
557     uint8_t msgType = COAP_MESSAGE_NON;
558     uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
559     uint32_t maxAge = 0x2ffff;
560     coap_send_flags_t sendFlag = (coap_send_flags_t)0;
561
562     //uint32_t observeOption = OC_OBSERVE_NO_OPTION;
563     //OCStackResult responseResult;
564
565     OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResponse"));
566
567     if(response->notificationFlag && response->qos == OC_HIGH_QOS)
568     {
569         msgType = COAP_MESSAGE_CON;
570     }
571     else if(response->notificationFlag && response->qos != OC_HIGH_QOS)
572     {
573         msgType = COAP_MESSAGE_NON;
574     }
575     else if(!response->notificationFlag && !response->slowFlag && response->qos == OC_HIGH_QOS)
576     {
577         msgType = COAP_MESSAGE_ACK;
578     }
579     else if(!response->notificationFlag && response->slowFlag && response->qos == OC_HIGH_QOS)
580     {
581         msgType = COAP_MESSAGE_CON;
582     }
583     else if(!response->notificationFlag)
584     {
585         msgType = COAP_MESSAGE_NON;
586     }
587
588     if(response->coapID == 0)
589     {
590         response->coapID = coap_new_message_id(gCoAPCtx);
591     }
592
593     if (response->observationOption != OC_OBSERVE_NO_OPTION)
594     {
595         result = FormOptionList(&optList, &mediaType, &maxAge,
596                 &response->observationOption, NULL,
597                 strlen((char *)response->resourceUri), response->resourceUri,
598                 0, NULL,
599                 response->sendVendorSpecificHeaderOptions,
600                 response->numSendVendorSpecificHeaderOptions);
601     }
602     else
603     {
604         result = FormOptionList(&optList, &mediaType, &maxAge,
605                 NULL, NULL,
606                 strlen((char *)response->resourceUri), response->resourceUri,
607                 0, NULL,
608                 response->sendVendorSpecificHeaderOptions,
609                 response->numSendVendorSpecificHeaderOptions);
610     }
611     VERIFY_SUCCESS(result, OC_STACK_OK);
612
613     sendPdu = GenerateCoAPPdu(msgType, OCToCoAPResponseCode(response->result),
614             response->coapID, response->requestToken, (unsigned char *)response->payload,
615             optList);
616
617     VERIFY_NON_NULL(sendPdu);
618     coap_show_pdu(sendPdu);
619
620     sendFlag = (coap_send_flags_t)(response->delayedResNeeded ? SEND_DELAYED : 0);
621     sendFlag = (coap_send_flags_t)( sendFlag | (response->secured ? SEND_SECURE_PORT : 0));
622
623     if (SendCoAPPdu(gCoAPCtx, (coap_address_t *) (response->requesterAddr), sendPdu, sendFlag)
624             != OC_STACK_OK)
625     {
626         OC_LOG(ERROR, TAG, PCF("A problem occurred in sending a pdu"));
627         return OC_STACK_ERROR;
628     }
629     return OC_STACK_OK;
630 exit:
631     OC_LOG(ERROR, TAG, PCF("Error formatting server response"));
632     return OC_STACK_ERROR;
633 }
634
635 /**
636  * Stop the CoAP client or server processing
637  *
638  * @return 0 - success, else - TBD error
639  */
640 OCStackResult OCStopCoAP() {
641     OC_LOG(INFO, TAG, PCF("Entering OCStopCoAP"));
642     coap_free_context(gCoAPCtx);
643     gCoAPCtx = NULL;
644     return OC_STACK_OK;
645 }
646
647 /**
648  * Called in main loop of CoAP client or server.  Allows low-level CoAP processing of
649  * send, receive, timeout, discovery, callbacks, etc.
650  *
651  * @return 0 - success, else - TBD error
652  */
653 OCStackResult OCProcessCoAP() {
654
655     OC_LOG(INFO, TAG, PCF("Entering OCProcessCoAP"));
656     int read = 0;
657     read = coap_read(gCoAPCtx, gCoAPCtx->sockfd);
658     if(read > 0) {
659         OC_LOG(INFO, TAG, PCF("This is a Unicast<============"));
660     }
661     if (-1 != gCoAPCtx->sockfd_wellknown) {
662         read = coap_read(gCoAPCtx, gCoAPCtx->sockfd_wellknown);
663         if(read > 0)
664         {
665             OC_LOG(INFO, TAG, PCF("This is a Multicast<==========="));
666         }
667     }
668     if (-1 != gCoAPCtx->sockfd_dtls) {
669         read = coap_read(gCoAPCtx, gCoAPCtx->sockfd_dtls);
670         if(read > 0)
671         {
672             OC_LOG(INFO, TAG, PCF("This is a Secure packet<==========="));
673         }
674     }
675     coap_dispatch(gCoAPCtx);
676
677     HandleSendQueue(gCoAPCtx);
678
679     return OC_STACK_OK;
680 }
681
682
683 /**
684  * Retrieve the info about the end-point where resource is being hosted.
685  * Currently, this method only provides the IP port with which the socket
686  * is bound.
687  *
688  * @return 0 - success, else - TBD error
689  */
690 OCStackResult OCGetResourceEndPointInfo (OCResource *resPtr, void *info) {
691
692     OCStackResult result = OC_STACK_ERROR;
693     int sfd;
694     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceEndPointInfo"));
695     VERIFY_NON_NULL(resPtr);
696     VERIFY_NON_NULL(info);
697
698     sfd = (resPtr->resourceProperties & OC_SECURE) ? gCoAPCtx->sockfd_dtls :
699             gCoAPCtx->sockfd;
700
701     if (OCGetSocketInfo(sfd, (uint16_t*)info) == ERR_SUCCESS)
702         result = OC_STACK_OK;
703 exit:
704     return result;
705 }
706
707