client version of coap

Dependencies:   nRF24L01P cantcoap3

Dependents:   client3

Committer:
Ka_myk
Date:
Fri Jan 18 14:12:24 2019 +0000
Revision:
0:6a6f97ca5572
Child:
1:1d936c763440
initial version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Ka_myk 0:6a6f97ca5572 1 //
Ka_myk 0:6a6f97ca5572 2 // Created by Kamil Mykitiuk on 2019-01-17.
Ka_myk 0:6a6f97ca5572 3 //
Ka_myk 0:6a6f97ca5572 4
Ka_myk 0:6a6f97ca5572 5 #include <cstring>
Ka_myk 0:6a6f97ca5572 6 #include "CoapClient.h"
Ka_myk 0:6a6f97ca5572 7
Ka_myk 0:6a6f97ca5572 8
Ka_myk 0:6a6f97ca5572 9 bool match_uri(CoapPDU& coapPDU, char* uri) {
Ka_myk 0:6a6f97ca5572 10 char respone_uri[32];
Ka_myk 0:6a6f97ca5572 11 int len = 0;
Ka_myk 0:6a6f97ca5572 12 coapPDU.getURI(respone_uri, 32, &len);
Ka_myk 0:6a6f97ca5572 13 return strcmp(uri, respone_uri) == 0;
Ka_myk 0:6a6f97ca5572 14 }
Ka_myk 0:6a6f97ca5572 15
Ka_myk 0:6a6f97ca5572 16
Ka_myk 0:6a6f97ca5572 17 bool isExpectedResponse(CoapPDU& response, u_int16_t message_id, char* uri) {
Ka_myk 0:6a6f97ca5572 18 return match_uri(response, uri) && response.getType() == CoapPDU::COAP_ACKNOWLEDGEMENT &&
Ka_myk 0:6a6f97ca5572 19 response.getMessageID() == message_id;
Ka_myk 0:6a6f97ca5572 20 }
Ka_myk 0:6a6f97ca5572 21
Ka_myk 0:6a6f97ca5572 22 bool CoapClient::isAck(CoapPDU& response, u_int16_t message_id, char* uri) {
Ka_myk 0:6a6f97ca5572 23 if (response.validate()) {
Ka_myk 0:6a6f97ca5572 24 if (isExpectedResponse(response, message_id, uri)) {
Ka_myk 0:6a6f97ca5572 25 return true;
Ka_myk 0:6a6f97ca5572 26 } else {
Ka_myk 0:6a6f97ca5572 27 sendReset(response.getMessageID()); // if this is not what we wanted, inform server about error
Ka_myk 0:6a6f97ca5572 28 }
Ka_myk 0:6a6f97ca5572 29 }
Ka_myk 0:6a6f97ca5572 30 return false;
Ka_myk 0:6a6f97ca5572 31 }
Ka_myk 0:6a6f97ca5572 32
Ka_myk 0:6a6f97ca5572 33
Ka_myk 0:6a6f97ca5572 34 /* send reset to server
Ka_myk 0:6a6f97ca5572 35 *
Ka_myk 0:6a6f97ca5572 36 * @return 0 if successful
Ka_myk 0:6a6f97ca5572 37 * -4 if radio is not working properly
Ka_myk 0:6a6f97ca5572 38 * */
Ka_myk 0:6a6f97ca5572 39 int CoapClient::sendReset(uint16_t message_id) {
Ka_myk 0:6a6f97ca5572 40 CoapPDU reset = CoapPDU();
Ka_myk 0:6a6f97ca5572 41 reset.setMessageID(message_id);
Ka_myk 0:6a6f97ca5572 42 reset.setType(CoapPDU::COAP_RESET);
Ka_myk 0:6a6f97ca5572 43 int ret = this->radioWrapper.write(reset.getPDUPointer(), reset.getPDULength());
Ka_myk 0:6a6f97ca5572 44 if (ret < 0) {
Ka_myk 0:6a6f97ca5572 45 return RADIO_NOT_WORKING;
Ka_myk 0:6a6f97ca5572 46 } else {
Ka_myk 0:6a6f97ca5572 47 return 0;
Ka_myk 0:6a6f97ca5572 48 }
Ka_myk 0:6a6f97ca5572 49 }
Ka_myk 0:6a6f97ca5572 50
Ka_myk 0:6a6f97ca5572 51 /* send get request to given uri of connected server
Ka_myk 0:6a6f97ca5572 52 *
Ka_myk 0:6a6f97ca5572 53 * @return number of saved bytes in provided buffer or
Ka_myk 0:6a6f97ca5572 54 * -1 if server responded ambiguously;
Ka_myk 0:6a6f97ca5572 55 * -2 if server timed out;
Ka_myk 0:6a6f97ca5572 56 * -3 if provided buffer is to small to save response,
Ka_myk 0:6a6f97ca5572 57 * -4 if if radio is not functioning properly
Ka_myk 0:6a6f97ca5572 58 * */
Ka_myk 0:6a6f97ca5572 59 int CoapClient::get(uint8_t* buffer, int len, char* uri) {
Ka_myk 0:6a6f97ca5572 60 CoapPDU coapPDU = CoapPDU();
Ka_myk 0:6a6f97ca5572 61 uint16_t messageId = preparePDU(coapPDU);
Ka_myk 0:6a6f97ca5572 62 coapPDU.setCode(CoapPDU::COAP_GET);
Ka_myk 0:6a6f97ca5572 63 coapPDU.setURI(uri);
Ka_myk 0:6a6f97ca5572 64
Ka_myk 0:6a6f97ca5572 65 uint8_t returnBuffer[radioWrapper.packetSize()];
Ka_myk 0:6a6f97ca5572 66 int timeout = this->listeningTimeout;
Ka_myk 0:6a6f97ca5572 67 for (int i = 0; i < this->retransmissionLimit; i++) {
Ka_myk 0:6a6f97ca5572 68 int ret = radioWrapper.write(coapPDU.getPDUPointer(), coapPDU.getPDULength()); // send empty payload to get uri
Ka_myk 0:6a6f97ca5572 69
Ka_myk 0:6a6f97ca5572 70 if (ret < 0) {
Ka_myk 0:6a6f97ca5572 71 return RADIO_NOT_WORKING;
Ka_myk 0:6a6f97ca5572 72 }
Ka_myk 0:6a6f97ca5572 73
Ka_myk 0:6a6f97ca5572 74 int readLen = radioWrapper.read(returnBuffer, radioWrapper.packetSize(), timeout); // add timeout param
Ka_myk 0:6a6f97ca5572 75 if (readLen > 0) { // if something is recieved process it
Ka_myk 0:6a6f97ca5572 76 CoapPDU response(returnBuffer, len, readLen);
Ka_myk 0:6a6f97ca5572 77 if (isAck(response, messageId, uri)) {
Ka_myk 0:6a6f97ca5572 78 if (std::memcmp(response.getTokenPointer(), this->token,
Ka_myk 0:6a6f97ca5572 79 static_cast<size_t>(response.getTokenLength())) == 0) {
Ka_myk 0:6a6f97ca5572 80 if (response.getPayloadLength() >= len) {
Ka_myk 0:6a6f97ca5572 81 std::memcpy(buffer, response.getPayloadPointer(),
Ka_myk 0:6a6f97ca5572 82 static_cast<size_t>(response.getPayloadLength()));
Ka_myk 0:6a6f97ca5572 83 return response.getPayloadLength();
Ka_myk 0:6a6f97ca5572 84 } else {
Ka_myk 0:6a6f97ca5572 85 return SMALL_BUFFER;
Ka_myk 0:6a6f97ca5572 86 }
Ka_myk 0:6a6f97ca5572 87 } else {
Ka_myk 0:6a6f97ca5572 88 return SERVER_RESPONSE_AMBIGOUS;
Ka_myk 0:6a6f97ca5572 89 }
Ka_myk 0:6a6f97ca5572 90 }
Ka_myk 0:6a6f97ca5572 91 } else if (readLen < 0) {
Ka_myk 0:6a6f97ca5572 92 return RADIO_NOT_WORKING;
Ka_myk 0:6a6f97ca5572 93 }
Ka_myk 0:6a6f97ca5572 94 timeout *= 2;
Ka_myk 0:6a6f97ca5572 95 }
Ka_myk 0:6a6f97ca5572 96 return SERVER_TIMED_OUT;
Ka_myk 0:6a6f97ca5572 97 }
Ka_myk 0:6a6f97ca5572 98
Ka_myk 0:6a6f97ca5572 99 /* send post request to given uri of connected server
Ka_myk 0:6a6f97ca5572 100 *
Ka_myk 0:6a6f97ca5572 101 * @return 0 if operation has been completed successfully
Ka_myk 0:6a6f97ca5572 102 * -1 if server responded ambiguously;
Ka_myk 0:6a6f97ca5572 103 * -2 if server timed out;
Ka_myk 0:6a6f97ca5572 104 * -4 if radio is not working properly
Ka_myk 0:6a6f97ca5572 105 * */
Ka_myk 0:6a6f97ca5572 106 int CoapClient::post(uint8_t* buffer, int len, char* uri) {
Ka_myk 0:6a6f97ca5572 107 CoapPDU coapPDU = CoapPDU();
Ka_myk 0:6a6f97ca5572 108 uint16_t messageId = preparePDU(coapPDU);
Ka_myk 0:6a6f97ca5572 109 coapPDU.setCode(CoapPDU::COAP_POST);
Ka_myk 0:6a6f97ca5572 110
Ka_myk 0:6a6f97ca5572 111 coapPDU.setURI(uri);
Ka_myk 0:6a6f97ca5572 112 coapPDU.setPayload(buffer, len);
Ka_myk 0:6a6f97ca5572 113 uint8_t returnBuffer[radioWrapper.packetSize()];
Ka_myk 0:6a6f97ca5572 114 int timeout = this->listeningTimeout;
Ka_myk 0:6a6f97ca5572 115 for (int i = 0; i < this->retransmissionLimit; i++) {
Ka_myk 0:6a6f97ca5572 116
Ka_myk 0:6a6f97ca5572 117 int ret = radioWrapper.write(coapPDU.getPDUPointer(), coapPDU.getPDULength());
Ka_myk 0:6a6f97ca5572 118 if (ret < 0) {
Ka_myk 0:6a6f97ca5572 119 return RADIO_NOT_WORKING;
Ka_myk 0:6a6f97ca5572 120 }
Ka_myk 0:6a6f97ca5572 121 int readLen = radioWrapper.read(returnBuffer, radioWrapper.packetSize(), timeout); // add timeout param
Ka_myk 0:6a6f97ca5572 122 if (readLen > 0) { // if something is recieved process it
Ka_myk 0:6a6f97ca5572 123 CoapPDU response(returnBuffer, len, readLen);
Ka_myk 0:6a6f97ca5572 124 if (isAck(response, messageId, uri)) {
Ka_myk 0:6a6f97ca5572 125 if (response.getCode() == CoapPDU::COAP_CREATED &&
Ka_myk 0:6a6f97ca5572 126 std::memcmp(response.getTokenPointer(), this->token,
Ka_myk 0:6a6f97ca5572 127 static_cast<size_t>(response.getTokenLength())) == 0) {
Ka_myk 0:6a6f97ca5572 128 return 0;
Ka_myk 0:6a6f97ca5572 129 } else // if server hasn't responded properly
Ka_myk 0:6a6f97ca5572 130 return SERVER_RESPONSE_AMBIGOUS;
Ka_myk 0:6a6f97ca5572 131 }
Ka_myk 0:6a6f97ca5572 132 } else if (readLen < 0) {
Ka_myk 0:6a6f97ca5572 133 return RADIO_NOT_WORKING;
Ka_myk 0:6a6f97ca5572 134 }
Ka_myk 0:6a6f97ca5572 135 timeout *= 2;
Ka_myk 0:6a6f97ca5572 136 }
Ka_myk 0:6a6f97ca5572 137 return SERVER_TIMED_OUT;
Ka_myk 0:6a6f97ca5572 138 }
Ka_myk 0:6a6f97ca5572 139
Ka_myk 0:6a6f97ca5572 140 uint16_t CoapClient::preparePDU(CoapPDU& coapPDU) {
Ka_myk 0:6a6f97ca5572 141 coapPDU.setVersion(1);
Ka_myk 0:6a6f97ca5572 142 coapPDU.setType(CoapPDU::COAP_CONFIRMABLE);
Ka_myk 0:6a6f97ca5572 143 coapPDU.setMessageID(this->message_counter);
Ka_myk 0:6a6f97ca5572 144 coapPDU.setToken(this->token, 4);
Ka_myk 0:6a6f97ca5572 145 return this->message_counter++;
Ka_myk 0:6a6f97ca5572 146 }
Ka_myk 0:6a6f97ca5572 147
Ka_myk 0:6a6f97ca5572 148 CoapClient::CoapClient(uint8_t* token, int retransmissionLimit, int timeout, RadioWrapper& radio) : radioWrapper(radio),
Ka_myk 0:6a6f97ca5572 149 listeningTimeout(
Ka_myk 0:6a6f97ca5572 150 timeout),
Ka_myk 0:6a6f97ca5572 151 retransmissionLimit(
Ka_myk 0:6a6f97ca5572 152 retransmissionLimit) {
Ka_myk 0:6a6f97ca5572 153 std::memcpy(this->token, token, 4);
Ka_myk 0:6a6f97ca5572 154 this->message_counter = 16;
Ka_myk 0:6a6f97ca5572 155 }