Yes We Can / yeswecancoap

Dependencies:   DebugLib EthernetInterface cantcoap mbed-rtos

Dependents:   COAP coap

Fork of yeswecancoap by Sille Van Landschoot

Files at this revision

API Documentation at this revision

Comitter:
dwini
Date:
Wed Oct 21 11:27:22 2015 +0000
Parent:
7:1bed29e1b0a4
Parent:
8:0169da22e764
Child:
10:77bd145ec06c
Commit message:
Merge with first implementation of client

Changed in this revision

--- a/EthernetInterface.lib	Wed Oct 21 10:23:21 2015 +0000
+++ b/EthernetInterface.lib	Wed Oct 21 11:27:22 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/EthernetInterface/#097a9996f8d5
+http://mbed.org/users/mbed_official/code/EthernetInterface/#2fc406e2553f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client.cpp	Wed Oct 21 11:27:22 2015 +0000
@@ -0,0 +1,110 @@
+#include "client.h"
+
+// Identifier is some trivial string used for console output
+Client::Client(const char * server, const int port, std::string identifier) {
+    udp_socket.init();
+    udp_socket.set_blocking(false, 1000);
+    new_token_id = 0;
+    coap_server.set_address(server, port);
+    this->identifier = identifier;
+    new_message_id = 0;
+}
+
+// Respons handler can be left null if no content respons is expected
+void Client::sendRequest(char* uri, void (*response_handler)(CoapPDU*, CoapPDU*), Method method) {
+
+    CoapPDU *req_pdu = new CoapPDU();
+    
+    switch (method) {
+        case GET:
+            req_pdu->setType(CoapPDU::COAP_CONFIRMABLE);
+            req_pdu->setCode(CoapPDU::COAP_GET);
+            break;
+    }
+    req_pdu->setMessageID(new_message_id++);
+    req_pdu->setToken((uint8_t *)new_token_id, sizeof(new_token_id));
+    req_pdu->setURI(uri, strlen(uri));
+
+    unsigned int retries = 5;
+    while (retries > 0 && udp_socket.sendTo(coap_server, (char *)(req_pdu->getPDUPointer()), req_pdu->getPDULength()) < 0) {
+        retries--;
+    }
+    
+    if (retries == 0) {
+        printf("UDP socket problem - Could not send PDU\r\n");
+        return;
+    } else {
+        if (method == GET) {  // Or confirmable ...
+            // We need to save request and wait for respons of server
+            ResourceRequest req { new_token_id, uri, response_handler, method, req_pdu };
+            requests.push_back(req);
+        }
+    }
+}
+
+void Client::checkForResponse(void) {
+
+    if (requests.size() > 0) {       // responses still need to be received
+
+        char buffer[256];
+        // printf("\r\nChecking for response UDP packet...\r\n");
+
+        // Check for udp packet from endpoint
+        int size = udp_socket.receiveFrom(coap_server, buffer, sizeof(buffer)-1);
+        if (size > 0) {
+            buffer[size] = '\0';
+            
+            char uriBuffer[32];
+            int recvURILen;
+            int msgId;
+            uint32_t token;
+
+            // Lets coap
+            CoapPDU *recvPDU = new CoapPDU((uint8_t*)buffer, 256, size);
+            if(recvPDU->validate()) {
+                recvPDU->getURI(uriBuffer, 32, &recvURILen); 
+                msgId = recvPDU->getMessageID();
+
+                // Parse token
+                if (recvPDU->getTokenLength() == sizeof(new_token_id)) {
+                    token = *((uint32_t*)recvPDU->getTokenPointer());
+                } else if (recvPDU->getTokenLength() == 0) {    // Server does not care about tokens ? 
+                    // Then we force to match with first request
+                    token = requests[0].token_id;
+                } else {
+                    printf("Invalid token length\r\n");
+                    delete recvPDU;
+                    return;
+                }
+            } else {
+                printf("Invalid Coap PDU received\r\n");
+                recvPDU->printHuman();
+                delete recvPDU;
+                return;
+            }
+            
+            // Check for which request the response is meant
+            int i = 0;
+            while (i < requests.size() && requests[i].token_id != token) {
+                i++;
+            }
+
+            if (i < requests.size()) {      // Found
+                // [TODO] Here we should check if it's not a premature ACK !!!!!!
+                
+                // Call handler if one exists
+                if (requests[i].response_handler) {
+                    requests[i].response_handler(requests[i].req_pdu, recvPDU);
+                }
+
+                delete requests[i].req_pdu;
+                requests.erase(requests.begin() + i);
+            } else {
+                printf("Respons for unknown request\r\n");
+                recvPDU->printHuman();
+            }
+
+            delete recvPDU;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client.h	Wed Oct 21 11:27:22 2015 +0000
@@ -0,0 +1,48 @@
+#pragma once
+
+/*
+Waarom client per server
+Ten eerste moeten van een repons dan niet bepalen voor welke request hij juist was.
+Alles dat voor een bepaalde client / socket toekomt is voor die client.
+Dat betekent ook dat we niet eeuwig moeten wachten op een respons maar dat we async
+kunnen werken en werken met timeouts. We overlopen dan gewoon constant de clients die nog
+geen respons hebben gekregen.
+*/
+
+#include <string>
+#include <vector>
+#include "cantcoap.h"
+#include "coap.h"
+
+enum Method;
+
+class Client {
+    
+    private:
+        // ResourceRequest holding info of previous request
+        struct ResourceRequest{
+            uint32_t token_id;
+            char* uri;
+            void (*response_handler)(CoapPDU*, CoapPDU*);       // Not sure if we need request and respons PDU's
+            int method;
+            CoapPDU * req_pdu;
+        };
+    
+    private:
+        UDPSocket udp_socket;
+        Endpoint coap_server;       // One client per endpoint
+        uint32_t new_token_id;      // Matches requests and responses
+        uint16_t new_message_id;
+        std::string identifier;     // Identifier is some trivial string used for console output
+        
+        // List of unhandled previous requests
+        std::vector<ResourceRequest> requests;
+    
+    public:
+        Client(const char * server, const int port, std::string identifier="Client");
+        
+    public:
+        void sendRequest(char* uri, void (*response_handler)(CoapPDU*, CoapPDU*), Method method);
+        void checkForResponse(void);
+    
+};
\ No newline at end of file
--- a/coap.h	Wed Oct 21 10:23:21 2015 +0000
+++ b/coap.h	Wed Oct 21 11:27:22 2015 +0000
@@ -6,6 +6,7 @@
 #include "dbg.h"
 
 #include "server.h"
+#include "client.h"
 
 enum Method {GET, POST, PUT, DELETE};
 
--- a/mbed-rtos.lib	Wed Oct 21 10:23:21 2015 +0000
+++ b/mbed-rtos.lib	Wed Oct 21 11:27:22 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed-rtos/#5dfe422a963d
+http://mbed.org/users/mbed_official/code/mbed-rtos/#12552ef4e980