Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Conflicts:
	coap.c
  • Loading branch information
Heds Simons committed Jul 24, 2014
2 parents 9e6c22b + fc8144d commit 9c24926
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 67 deletions.
2 changes: 1 addition & 1 deletion Makefile
@@ -1,5 +1,5 @@
all:
gcc -Wall -o coap main-posix.c coap.c endpoints.c -DDEBUG
gcc -Wall -o coap endpoints.c main-posix.c coap.c -DDEBUG

clean:
rm -f coap
17 changes: 9 additions & 8 deletions README.md
@@ -1,18 +1,17 @@
microcoap
=========

A miminal CoAP server implementation for microcontrollers.

Written from the RFC, http://tools.ietf.org/html/draft-ietf-core-coap-18
A tiny CoAP server for microcontrollers.
See http://tools.ietf.org/html/draft-ietf-core-coap-18

Endpoint handlers are defined in endpoints.c

* Arduino demo
* Arduino demo (Mega + Ethernet shield, LED + 220R on pin 6, PUT "0" or "1" to /light)
* POSIX (OS X/Linux) demo
* GET/PUT/POST
* Probably not compliant
* Content Types in responses (ie. /.well-known/core as application/linkformat)
* No retry logic
* No retries
* Piggybacked ACK only


For linux/OSX

Expand All @@ -26,7 +25,9 @@ For Arduino
To test, use libcoap

./coap-client -v 100 -m get coap://127.0.0.1/.well-known/core
./coap-client -v 100 -m get coap://127.0.0.1/hello
./coap-client -v 100 -m get coap://127.0.0.1/light
./coap-client -e "1" -m put coap://127.0.0.1/light
./coap-client -e "0" -m put coap://127.0.0.1/light

Or use copper (Firefox plugin)

Expand Down
106 changes: 82 additions & 24 deletions coap.c
Expand Up @@ -6,6 +6,7 @@
#include <stddef.h>
#include "coap.h"

extern void endpoint_setup(void);
extern const coap_endpoint_t endpoints[];

#ifdef DEBUG
Expand Down Expand Up @@ -81,37 +82,57 @@ int coap_parseToken(coap_buffer_t *tokbuf, const coap_header_t *hdr, const uint8
int coap_parseOption(coap_option_t *option, uint16_t *running_delta, const uint8_t **buf, size_t buflen)
{
const uint8_t *p = *buf;
uint8_t len;
uint16_t delta;
uint8_t headlen = 1;
uint16_t len, delta;

if (buflen < 1) // too small
if (buflen < headlen) // too small
return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER;

delta = (p[0] & 0xF0) >> 4;
len = p[0] & 0x0F;

// These are untested and may be buggy
if (len == 13)
if (delta == 13)
{
if (buflen < 2)
headlen++;
if (buflen < headlen)
return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER;
delta = p[1] + 13;
p++;
}
else
if (len == 14)
if (delta == 14)
{
if (buflen < 3)
headlen += 2;
if (buflen < headlen)
return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER;
delta = ((p[1] << 8) | p[2]) + 269;
p+=2;
}
else
if (delta == 15)
return COAP_ERR_OPTION_DELTA_INVALID;

if (len == 13)
{
headlen++;
if (buflen < headlen)
return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER;
len = p[1] + 13;
p++;
}
else
if (len == 14)
{
headlen += 2;
if (buflen < headlen)
return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER;
len = ((p[1] << 8) | p[2]) + 269;
p+=2;
}
else
if (len == 15)
return COAP_ERR_OPTION_LEN_INVALID;
else
if (len > 12)
return COAP_ERR_OPTION_TOO_BIG;

if ((p + 1 + len) > (*buf + buflen))
return COAP_ERR_OPTION_TOO_BIG;
Expand Down Expand Up @@ -139,7 +160,7 @@ int coap_parseOptionsAndPayload(coap_option_t *options, uint8_t *numOptions, coa
int rc;
if (p > end)
return COAP_ERR_OPTION_OVERRUNS_PACKET; // out of bounds

//coap_dump(p, end - p);

// 0xFF is payload marker
Expand Down Expand Up @@ -247,6 +268,7 @@ int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt)
size_t i;
uint8_t *p;
uint16_t running_delta = 0;

// build header
if (*buflen < 4 + pkt->hdr.tkl)
return COAP_ERR_BUFFER_TOO_SMALL;
Expand All @@ -266,27 +288,45 @@ int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt)
if (pkt->hdr.tkl > 0)
memcpy(p, pkt->tok.p, pkt->hdr.tkl);

// http://tools.ietf.org/html/draft-ietf-core-coap-18#section-3.1
// inject options
p += pkt->hdr.tkl;

for (i=0;i<pkt->numopts;i++)
{
uint8_t delta;
uint8_t optDelta, len, delta = 0;

if (p-buf > *buflen)
return COAP_ERR_BUFFER_TOO_SMALL;
delta = pkt->opts[i].num - running_delta;
if (delta > 12) {
return COAP_ERR_UNSUPPORTED; // FIXME
return COAP_ERR_BUFFER_TOO_SMALL;
optDelta = pkt->opts[i].num - running_delta;
coap_option_nibble(optDelta, &delta);
coap_option_nibble(pkt->opts[i].buf.len, &len);

*p++ = (0xFF & (delta << 4 | len));
if (delta == 13)
{
*p++ = (optDelta - 13);
}
if (pkt->opts[i].buf.len > 12) {
return COAP_ERR_UNSUPPORTED; // FIXME
else
if (delta == 14)
{
*p++ = ((optDelta-269) >> 8);
*p++ = (0xFF & (optDelta-269));
}
*p++ = (delta << 4) | (pkt->opts[i].buf.len & 0x0F);
if ((p+pkt->opts[i].buf.len) - buf > *buflen)
return COAP_ERR_BUFFER_TOO_SMALL;
if (len == 13)
{
*p++ = (pkt->opts[i].buf.len - 13);
}
else
if (len == 14)
{
*p++ = (pkt->opts[i].buf.len >> 8);
*p++ = (0xFF & (pkt->opts[i].buf.len-269));
}

memcpy(p, pkt->opts[i].buf.p, pkt->opts[i].buf.len);
p += pkt->opts[i].buf.len;
running_delta = delta;
running_delta = pkt->opts[i].num;
}

opts_len = (p - buf) - 4; // number of bytes used by options
Expand All @@ -304,6 +344,22 @@ int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt)
return 0;
}

void coap_option_nibble(uint8_t value, uint8_t *nibble)
{
if (value<13)
{
*nibble = (0xFF & value);
}
else
if (value<=0xFF+13)
{
*nibble = 13;
} else if (value<=0xFFFF+269)
{
*nibble = 14;
}
}

int coap_make_response(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const uint8_t *content, size_t content_len, uint8_t msgid_hi, uint8_t msgid_lo, const coap_buffer_t* tok, coap_responsecode_t rspcode, coap_content_type_t content_type)
{
pkt->hdr.ver = 0x01;
Expand Down Expand Up @@ -364,10 +420,12 @@ int coap_handle_req(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_
ep++;
}

coap_make_response(scratch, outpkt, NULL, 0, inpkt->hdr.id[0], inpkt->hdr.id[1], 0, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
coap_make_response(scratch, outpkt, NULL, 0, inpkt->hdr.id[0], inpkt->hdr.id[1], &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);

return 0;
}


void coap_setup(void)
{
}

23 changes: 19 additions & 4 deletions coap.h
@@ -1,6 +1,10 @@
#ifndef COAP_H
#define COAP_H 1

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
Expand Down Expand Up @@ -53,6 +57,7 @@ typedef enum
COAP_OPTION_URI_HOST = 3,
COAP_OPTION_ETAG = 4,
COAP_OPTION_IF_NONE_MATCH = 5,
COAP_OPTION_OBSERVE = 6,
COAP_OPTION_URI_PORT = 7,
COAP_OPTION_LOCATION_PATH = 8,
COAP_OPTION_URI_PATH = 11,
Expand Down Expand Up @@ -89,7 +94,9 @@ typedef enum
typedef enum
{
COAP_RSPCODE_CONTENT = MAKE_RSPCODE(2, 5),
COAP_RSPCODE_NOT_FOUND = MAKE_RSPCODE(4, 4)
COAP_RSPCODE_NOT_FOUND = MAKE_RSPCODE(4, 4),
COAP_RSPCODE_BAD_REQUEST = MAKE_RSPCODE(4, 0),
COAP_RSPCODE_CHANGED = MAKE_RSPCODE(2, 4)
} coap_responsecode_t;

//http://tools.ietf.org/html/draft-ietf-core-coap-18#section-12.3
Expand All @@ -114,24 +121,26 @@ typedef enum
COAP_ERR_OPTION_TOO_BIG = 7,
COAP_ERR_OPTION_LEN_INVALID = 8,
COAP_ERR_BUFFER_TOO_SMALL = 9,
COAP_ERR_UNSUPPORTED = 10
COAP_ERR_UNSUPPORTED = 10,
COAP_ERR_OPTION_DELTA_INVALID = 11,
} coap_error_t;

///////////////////////

typedef int (*coap_endpoint_func)(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo);

#define MAX_SEGMENTS 2 // 2 = /foo/bar, 3 = /foo/bar/baz
typedef struct
{
int count;
const char *elems[];
const char *elems[MAX_SEGMENTS];
} coap_endpoint_path_t;

typedef struct
{
coap_method_t method;
coap_endpoint_func handler;
const coap_endpoint_path_t *path;
const char *core_attr;
} coap_endpoint_t;


Expand All @@ -144,6 +153,12 @@ int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt);
void coap_dump(const uint8_t *buf, size_t buflen, bool bare);
int coap_make_response(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const uint8_t *content, size_t content_len, uint8_t msgid_hi, uint8_t msgid_lo, const coap_buffer_t* tok, coap_responsecode_t rspcode, coap_content_type_t content_type);
int coap_handle_req(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt);
void coap_option_nibble(uint8_t value, uint8_t *nibble);
void coap_setup(void);
void endpoint_setup(void);

#ifdef __cplusplus
}
#endif

#endif

0 comments on commit 9c24926

Please sign in to comment.