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:
parent
dc03eeb307
commit
f34833e955
124
src/coap.cpp
Normal file
124
src/coap.cpp
Normal 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
53
src/coap.h
Normal 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
|
Loading…
Reference in New Issue
Block a user