Code Monkey home page Code Monkey logo

lobaro-coap's Introduction

Lobaro-CoAP

Build Status Gitter Chat

Complete CoAP Implementation in C. Despite designed for embedded systems (e.g. ARM Cortex-M0/M3, AVR, ESP8266) it can be used on nearly every system that has c-lang support.

  • Royalty-free CoAP stack
  • complete request/response logic
  • unified Client & Server
  • easy to use
  • small memory footprint
  • using C99 stdlib, suitable for embedded projects
  • detached packet receive/send logic
  • Arduino support (experimental)

There is also a working OpenSource client lib available in GoLang @ https://github.com/lobaro/coap-go

Follow Lobaro on Twitter to get latest news about iot projects using our CoAP implementation!

Getting started

Read the Porting Guide for information on how to port the library to your framework.

Demo/Example

ESP8266, cheap WIFI Soc:

Related

  • GoLang CoAP Client implementation & CGO wrapper for this C lib: Lobaro CoAP-go

Future development

We use the stack internally at lobaro to build universal gateway / sensor systems for our customers. Additions will be constantly merged into this repository.

Contribute

We appreciate any feedback, do not hesitate to create issues or pull requests.

lobaro-coap's People

Contributors

cimarron-korozco avatar githubstinks avatar kratenko avatar leszek-grzegorek avatar miri64 avatar niondir avatar nzsmartie avatar tothero avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lobaro-coap's Issues

Create include directory to help include namespaced header files

Before the rebase in 0fa8289, I set my makefile to include the base folder which lobaro-coap was residing in. So my project's includes looked like:

#include "lobaro-coap/coap.h"

Namespacing the include files makes it easier when dealing multiple libraries or project file names that conflict.
In my case, esp-idf has included it's own own ported version of libcoap which I don't want to use. So #include "coap.h" could either mean libcoap's coap.h, or lobaro-coap's coap.h which my compiler isn't too happy about.

with the files now sitting under /src It would require me to create a symbolic link to fix the issue or maybe branch and rename the folder.

Instead I would like to propose that header files are moved to /include/lobaro-coap/ under the project root directory to help clean up potentially conflicting names.

reassembly for BLOCK option

Tested the block coap "about/coap" resource, working as charm.
Is client part of block is implemented? reassembly of block payloads
at esp8266 client.

TCP support

Any thoughts about supporting TCP framing described in rfc8323?

A challenge I feel from my experience of this library so far is that CoAP_onNewPacketHandler expects an entire CoAP message, whereas a TCP being a stream, it may be needed to call CoAP_onNewPacketHandler multiple times to incrementally process a message.

Reserved token length responds with incorrect message ID (confirmable)

Confirmable messages that have an invalid token length (ie >8) do not respond with a valid message code. It's due to this error handling happening before message ID is stripped out of the header.

Header error handling should probably all be moved down to after header is decoded.

if (TokenLength > 8) {
		INFO("CoAP-Parse Byte1 Error\r\n");
		return COAP_PARSE_MESSAGE_FORMAT_ERROR;
	} // return COAP_PARSE_MESSAGE_FORMAT_ERROR;

Use a more standardized API for linked heap lists

There are many linked lists in the code but all are custom made. Iterating always looks different. It would be nice to have a single heap based linked list where heap based elements can be inserted and removed. We actually have such an implementation in other projects. A first step would be to move it over to the codebase and use it in a second step.

Improve memory management

The goal would be to have no bget related code and have malloc and free as part of the API struct, so the user can choose what to use. If bget or the stdlib malloc and free is the default is up to discussion.

Optionparser fails if there are no options

We are developing a little demo but lobarocoap can't parse a response with no options. it fails of the following code in /src/coap_options.c

if (srcArr[0] == OPTION_PAYLOAD_MARKER) {
		INFO("- Options must not start with payload marker!\r\n");
		return COAP_PARSE_MESSAGE_FORMAT_ERROR;
}

Other clients like libcoap or coapthon or java libraries have no problem with the packets. And i can't see anything in the rfc either.

O the contrary there is stated options (if any):

0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Ver| T |  TKL  |      Code     |          Message ID           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Token (if any, TKL bytes) ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Options (if any) ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |1 1 1 1 1 1 1 1|    Payload (if any) ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                         Figure 7: Message Format

Debug Output:

o<<<<<<<<<<<<<<<<<<<<<<
New Datagram received [7 Bytes], Interface #d

--------------->>> Sending Endpoint:
--------------->>> IPv4, 192.168.2.41:57095
--------------->>>

--------------->>> - Options must not start with payload marker!

--------------->>> CoAP-Parse Options Error

--------------->>> - (!) ERROR (!)
--------------->>> ParseResult:
--------------->>> COAP_PARSE_MESSAGE_FORMAT_ERROR

--------------->>> o<<<<<<<<<<<<<<<<<<<<<<

--------------->>>

--------------->>> Interactions: 1

--------------->>> -------------

--------------->>> - Role: CLIENT, State: WAITING_RESPONSE

--------------->>> RetransCnt: 0, SleepUntil 0, AckTimeout: 1516699926

Edit: No options not no headers

Stack smashing due to types length mismatch while calling BGET funcs (amd64 GNU/Linux platform)

For 64bit platform based on GNU/Linux (amd64) at least one type length mismatch between BGET <-> lobaro has been found causing stack smashing. The problem is that BGET originally is based on basic types e.g. int, long, etc. and lobaro uses fixed size ones, e.g. int32_t, etc. When BGET-functions return values via pointers to lobaro funcs. they (may) overwrite the stack on platforms where length mismatch occurs - e.g. for GNU/Linux amd64 long is 64bit vs. int32_t (as according to spec. long has to be at least 32bit).

The following example of affected code is related to nget, nrel variables (int32_t vs. long) :

void _rom coap_mem_stats()
{
	bufsize curalloc, totfree, maxfree;
	int32_t nget, nrel;

	bstats(&curalloc, &totfree, &maxfree, &nget, &nrel);
void _rom bstats(curalloc, totfree, maxfree, nget, nrel)
	bufsize *curalloc, *totfree, *maxfree;
	long *nget, *nrel;
{
	struct bfhead *b = freelist.ql.flink;

	*nget = numget;
	*nrel = numrel;

Of course mentioned issue does not occur when we compile it for 32bit - there no such mismatch occurs because long data type is 32bit.

I think that either BGET original implementation should be rewritten to use fixed size data types or at least some caution in README.md added that 64bit platforms may not be fully supported.

Provide simple setup with only one .a and one .h file

With a little manual how to build a lib (.a) file for a few platforms (e.g. Linux, Windows, STM32, Adruino) it should be sufficient to link that file and add a single .h file to a project in order to be able to use the lib.

Asynchronous Response (Separate Response) with Lobaro CoAP

Hello, I've been using Lobaro CoAP for a project im doing on the ESP8266. Normal responses work well and I'm now trying to get into separate responses. I am aware of the usage of the HANDLER_POSTPONE macro as a return for my request handler so that my CoAP server sends out an empty acknowledgement to the client, but my server doesnt send the test message after using a delay in my code (3 seconds delay). Can someone please explain to me how the handler for a separate response would look like with Lobaro CoAP? Thanks for your help.

Ameer

Observe in client is not working

Description

The client is requesting correctly with the observe option and getting an ACK from the server.
But after the first CON from the server my callback (sendRequestCB) is called and the interaction is getting deleted. (@see: coap_main.c:handleClientInteraction)
In return the client sends a RST instead of an ACK because he cannot find the previous deleted interaction. (@see: coap_main.c:CoAP_HandleIncomingPacket)
The server removes the subscriber because he received a RST (Cancel Observation).

Client code

CoAP_Result_t res = CoAP_StartNewGetObserveRequest_my("din0", mCoapSocket->Handle, &mReceiver, sendRequestCB);

CoAP_Result_t CoapClient::sendRequestCB(CoAP_Message_t* pRespMsg, NetEp_t* Sender) {
    printf("--------------------------------->>>>> sendRequestCB done\n");
    ...
}

CoAP_Result_t _rom CoapClient::CoAP_StartNewGetObserveRequest_my(char* UriString, SocketHandle_t socketHandle, NetEp_t* ServerEp, CoAP_RespHandler_fn_t cb) {
    CoAP_Message_t* pReqMsg = CoAP_CreateMessage(CON, REQ_GET, CoAP_GetNextMid(), NULL, 0, 0, CoAP_GenerateToken());
    if (pReqMsg != NULL) {
        CoAP_AppendUriOptionsFromString(&(pReqMsg->pOptionsList), UriString);
        AddObserveOptionToMsg(pReqMsg, 0);
        CoAP_blockwise_option_t blkOption;
        blkOption.Type = BLOCK_2;
        blkOption.BlockSize = BLOCK_SIZE_64;
        blkOption.MoreFlag = 0;
        blkOption.BlockNum = 0;
        AddBlkOptionToMsg(pReqMsg, &blkOption);
        return CoAP_StartNewClientInteraction(pReqMsg, socketHandle, ServerEp, cb);
    }

    INFO("- New GetRequest failed: Out of Memory\r\n");
    return COAP_ERR_OUT_OF_MEMORY;
}

Example code

Hi!
Can someone provide example code of CoAP Lobaro usage?

Add "Getting started" documentation

Goal should be to have a brief tutorial on how compile and use the library.
Something like: "compile" -> "run tests" -> "take .a file and one .h file to your own project" -> "how to setup a few different endpoints"

The getting started could be in the Wiki or Readme and in future might link to more detailed tutorials that could explain specific setups e.g. for Arduino, the EPS, setup with different IDE's etc. which are out of scope of this issue.

Options not optional?

I spent sometime last week on getting a client request working from this library.

It spat the dummy on the return message. On investigation the code used to parse the Options made the assumption that there had to be 1 or more options, but in the spec options can be 0 or more.

coap_options.c: 178 if (srcArr[0] == OPTION_PAYLOAD_MARKER)

(This is a later version to the code I was looking at, but my reading of the spec implies that a payload can follow the tokens - something this doesn't allow for, and is always invoked as part of the message processing?)

I could be wrong here though, it was a quick fix to render the response of a coapthon server that may well be violating the spec.

Is there any documentation for this package beside porting guide and examples on lobaro's site?

Hello, I need an explanation about how this package works. for instance, NetAddr can be an uint32_t array with one entry and also an uint8_t array with 4 slots for IPV4.
I get the way for the 8-bit array but with 32-bit do we have to shift the numbers?
for example 192.168.1.2 is 2 + 1 + 256 + 168 + 256x256 + 192 + 256x256x256 ?
generally speaking, is there any documentation about how this package and its parts work?
I am already familiar with porting guide on GitHub and code examples on lobaro.com
thank you in advance.

Improve `/.well-known/core` Handler

Regarding the default /.well-known/core handler; I think adding a CoAP_RemoveResource(...) to complement CoAP_CreateResource(...) would enable the application to remove the default handler and help by allowing the application to dynamically remove resources as they disappear from the device (for what ever reason).

Another idea is allowing the application layer to manually register WellKnown_GetHandler (Might rename it to CoAP_DefaultWellKnownHandler for clarity). Or possibly adding a flag to CoAP_Config_t to disable automatic registration of the default handler

otherwise, maybe a callback could be added to CoAP_ResOpts_t When it's not null, WellKnown_GetHandler will call that for generating a string (i.e. </example/resource>;ct="0 50 60";rt="example";if="sensor") per resource.

Does this work on windows?

Hello, I want to use this library on windows and I am facing an error which tells me "sched.h" doesn't exist.
I googled for this and I got that I have to use Linux but based on documentation this lib is introduced as independent from the platform which is processed on. am I missing something here?

CoAP_Res_t.pDescription may be NULL and may hardfault in CoAP_StartNotifyInteractions

pDescription may be null and causes a hard-fault when observers are notified of a resource update.
https://github.com/Lobaro/lobaro-coap/blob/b6b5ced0f7d013022c848d5f3da4ddb757339b6c/src/coap_interaction.c#L279

It's set to NULL when an null or empty string is passed in as a resource description on CoAP_CreateResource:
https://github.com/Lobaro/lobaro-coap/blob/d7a4c79ad2217f744ac9757d2b4bc15599442450/src/coap_resource.c#L335-L340

Incorrect #include

The following include causes code to not compile.

#include <github.com/lobaro/c-utils/logging.h>

From inspection seems like it was intended to be
#include <stdio.h> #include <string.h>

for the calls for following calls

memmove((void*) Destination, (void*) Source, sizeof(NetEp_t));

and

int got = sscanf(s, "%d.%d.%d.%d", &i0, &i1, &i2, &i3);

Callback Functions With User Supplied Data Pointers

I propose that CoAP_CreateResource(...) (used to register resources) to have an additional opaque void* pUserData parameter that will be included in CoAP_ResourceHandler_fPtr_t and CoAP_ResourceNotifier_fPtr_t. This would allow the application to register multiple resources and pass along identifying information in pUserData to allow the apllication to quickly use without the need for a lookup table with the URI of the resource.

I'll be happy to create a PR if this idea is good. Unless another solution is preferred?

Use Case
I have a for loop that generates 100 resources, that each has small data associated with it. would be nice to pass a pointer to the data to CoAP_Res_t (through CoAP_CreateResource) that is then passed to a single resource handler for all 100 resources. to quickly access the requried data without needing to parse the resource URI and fetch the associated data.

Have only one handler for Requests and Observe

Currently we have 2 different handler functions that need to be implemented and registered separately but often share a lot of code in applications. I would like to reduce the API to a single handler for Observes and normal requests.

Ignored handler response msg code

I have observed that response message type set by handler is ignored and treated as CON.
To reproduce this issue:

  1. Send request with msg.type = CON
  2. Handler is not able to answer, return POSTPONE
  3. On next call handler is able to answer, configure response msg.type as NON
  4. Response is sent as CON

In other words:

Expected:
client CON -> server
server ACK -> client
server NON-> client

Actual:
client CON -> server
server ACK -> client
server CON -> client
client ACK -> server

According to RFC 7252 :

5.2.2. Separate
(...)
When the server finally has obtained the resource representation, it
sends the response. When it is desired that this message is not
lost, it is sent as a Confirmable message from the server to the
client and answered by the client with an Acknowledgement, echoing
the new Message ID chosen by the server. (It may also be sent as a
Non-confirmable message; see Section 5.2.3.)

So application should be able to configure whether the response is CON or NON. I have digged into the lobaro coap lib and found out, that if request was CON and ACK has been sent, response is ALWAYS sent as CON (even if handler has changed it to the NON).
Code responsible for that:

//Set response TYPE correctly if CON request, regardless of what the handler did to this resp msg field, it can't know it better :-)
//on NON requests the handler can decide if use CON or NON in response (default is also using NON in response)
if (pIA->pReqMsg->Type == CON) {
	if (pIA->ReqConfirmState ==
			ACK_SEND) { //separate empty ACK has been sent before (piggyback-ack no more possible)
		pIA->pRespMsg->Type = CON;
		pIA->pRespMsg->MessageID = CoAP_GetNextMid(); //we must use/generate a new messageID;
	} else
		pIA->pRespMsg->Type = ACK; //"piggybacked ack"
}

So current implementation is not consistent with the RFC 7252.
I understand that it was done intentionally, but I believe that it is a bug,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.