coap server basics -- parse input path

receive coap request and parse path
actually this is just a stub, but hey,
it's a stable one and this is my private branch

even if this commit will probably be fast-merged '°_°
This commit is contained in:
giomba 2020-01-08 22:52:59 +01:00
parent dc03eeb307
commit f34833e955
2 changed files with 177 additions and 0 deletions

124
src/coap.cpp Normal file
View File

@ -0,0 +1,124 @@
#include "coap.h"
namespace coap {
uint8_t CoapMessage::getVersion() {
return vertkl >> 6;
}
uint8_t CoapMessage::getType() {
return (vertkl & 0x30) >> 4;
}
uint8_t CoapMessage::getTKL() {
return (vertkl & 0x0f);
}
uint8_t CoapMessage::getCode() {
return code;
}
const char* CoapMessage::getMID() {
return id;
}
/* nonsense: save 8 bits in the network,
and waste tens of them for writing such an error-prone code like this! */
int CoapMessage::getOptionDelta(const unsigned char* option) {
uint8_t delta = option[0] >> 4;
if (delta <= 12) {
return delta;
}
if (delta == 13) {
delta = option[1] + 13;
return delta;
}
/* options delta larger than 269 (256 + 13) bytes are not supported */
return -1;
}
int CoapMessage::getOptionLength(const unsigned char* option) {
uint8_t len = option[0] & 0xf;
if (len <= 12) {
return len;
}
uint8_t extended_length_byte;
if (getOptionDelta(option) < 13)
extended_length_byte = option[1];
else
extended_length_byte = option[2];
if (len == 13) {
len = extended_length_byte + 13;
return len;
}
/* options longer than 269 (256 + 13) are not supported */
return -1;
}
/* offset of payload wrt beginning of option */
int CoapMessage::getOptionValueOffset(const unsigned char* option) {
int offset = 1;
if (getOptionDelta(option) >= 13) ++offset;
if (getOptionLength(option) >= 13) ++offset;
return offset;
}
const char* CoapMessage::getOptionValue(const unsigned char* option) {
return (const char*) &option[getOptionValueOffset(option)];
}
const unsigned char* CoapMessage::getOptions() {
const unsigned char* address = (const unsigned char*)this;
address += 4; /* header */
address += getTKL();
return address;
}
void CoapMessage::getUriPath(char* output_buffer, const char* last) {
/* TODO -- possible overflow, malformed input not checked */
int number = 0;
int len;
const unsigned char* options = this->getOptions();
while (number <= 11) {
number += getOptionDelta(options);
len = getOptionLength(options);
// TODO -- is here a payload? 15 - 15
if (number == 11) { /* Uri-Path option number */
*output_buffer = '/';
output_buffer += 1;
memcpy(output_buffer, getOptionValue(options), len);
output_buffer += len;
}
options += (len + getOptionValueOffset(options));
if (options == last) break;
}
*output_buffer = '\0';
return;
}
int coap_server(char* output_buffer, const char* input_buffer, int len) {
CoapMessage* input_msg = (CoapMessage*) input_buffer;
if (input_msg->getVersion() != 0x1) /* bad CoAP version number */
return -1;
if (input_msg->getType() == RESET || input_msg->getType() == ACKNOWELEDGMENT) /* not implemented on server side */
return -1;
if (input_msg->getTKL() >= 9) /* format error -- TODO, maybe we can answer RST? see RFC */
return -1;
switch (input_msg->getCode()) {
case GET:
input_msg->getUriPath(output_buffer, input_buffer + len);
return strlen(output_buffer);
break;
}
return -1;
}
} // end of namespace -- coap::

53
src/coap.h Normal file
View File

@ -0,0 +1,53 @@
#ifndef COAP_H
#define COAP_H
#include "Arduino.h"
namespace coap {
enum Type {
CONFIRMABLE = 0,
NON_CONFIRMABLE = 1,
ACKNOWELEDGMENT = 2,
RESET = 3
};
enum Code {
EMPTY = 0x00, /* 0.00 */
GET = 0x01, /* 0.01 */
POST = 0x02, /* 0.02 */
PUT = 0x03, /* 0.03 */
DELETE = 0x04, /* 0.04 */
CONTENT = 0x45, /* 2.05 */
NOT_FOUND = 0x84,/*4.04 */
METHOD_NOT_ALLOWED = 0x85 /* 4.05 */
};
class CoapMessage {
private:
char vertkl;
char code;
char id[2];
public:
uint8_t getVersion();
uint8_t getType();
uint8_t getTKL();
uint8_t getCode();
const char* getMID();
const char* getPayload();
int getOptionDelta(const unsigned char* option);
int getOptionLength(const unsigned char* option);
const char* getOptionValue(const unsigned char* option);
int getOptionValueOffset(const unsigned char* option);
const unsigned char* getOptions();
void getUriPath(char* output_buffer, const char* last);
};
int coap_server(char* output_buffer, const char* input_buffer, int len);
}
#endif