DLTcollab / TA-endpoint

Connect resource constrained endpoints with Tangle-Accelerator
Apache License 2.0
0 stars 2 forks source link

Reorganize directory structure #31

Closed splasky closed 4 years ago

splasky commented 4 years ago

There are three directory at the root directory. Why don't we put source code into same src directory and put headers file into same include directory?

jserv commented 4 years ago

It is not "folder" but "directory." Show the tree view rather than words while you are proposing something.

howjmay commented 4 years ago

@splasky Provide the structure you designed here.

splasky commented 4 years ago

How to porting TA-endpoint on your device

tags: TA-endpoint

Written by HY Chang\hychang@biilabs.io\

Directory Overview

How to implement your device

Create your device folder into devices.

mkdir devices/<my_device>

Implement your device operations, which are included from hal/device.h

device.h:

... 

#define DECLARE_DEVICE(name)                                  \
  void init_##name##_init(void) __attribute__((constructor)); \
  void init_##name##_init(void) { name##_device_type.op->init(); }

typedef struct device_type device_t;
enum { DEVICE_OK, DEVICE_ERROR };

struct device_operations {
  retcode_t (*init)(void);            /**< init for device */
  void (*fini)(void);           /**< destructor for device  */
  retcode_t (*get_key)(uint8_t *);    /**< get device private key */
  retcode_t (*get_device_id)(char *); /**< get device id          */
};

struct logging_operations {
  void (*write_log)(char *path, char *msg, size_t msg_len);
}; // Will be removed

struct uart_operations {
  retcode_t (*init)(const char *device);
  void (*write)(const int fd, const char *cmd);
  char *(*read)(const int fd);
  void (*clean)(const int fd);
};

struct secure_store_operations {
  retcode_t (*init)(void); /**< init secure storage */
  retcode_t (*write)(const char *name, const uint8_t *bufPtr, size_t bufSize);
  retcode_t (*read)(const char *name, uint8_t *bufPtr, size_t *bufSizePtr);
  retcode_t (*delete)(const char *name);
};

struct device_type {
  const char *name;
  int uart_fd;
  const struct device_operations *op;
  const struct uart_operations *uart;
  const struct secure_store_operations *sec_ops;
  device_t *next;
};

device_t *get_device(const char *);
retcode_t register_device(struct device_type *dv);
retcode_t unregister_device(struct device_type *dv);
...

add your device into hal/Makefile:

all: $(DEVICES_OBJ) ... mydevice.o: device.o $(MAKE) -C ../devices/mydevice ...


implement device:
must include
1. impl.c
2. Makefile

edit Makefile, example device name as mydevice:

all: mydevice.o mydevice.o: impl.c $(CC) $(CFLAGS) $(INCLUDES) -c $^ -o $@

`$(CC)`,`$(CFLAGS)`,`$(INCLUDES)` is provide by TA-endpoint. Don't define same flags inside your Makefile.

impl.c
```c=
#include "impl.h"
...

static inline void register_emulator(void);
static inline void unregister_emulator(void);
...

static struct device_operations emulator_ops = {.init = &emulator_init,
                                                .fini = &emulator_release,
                                                .get_key = &emulator_get_key,
                                                .get_device_id = &emulator_get_device_id};

static struct logging_operations emulator_logger = {.write_log = &write_log}; // Will be removed

static struct uart_operations emulator_uart = {
    .init = &uart_init, .write = &uart_write, .read = &uart_read, .clean = &uart_clean};

static struct device_type emulator_device_type = {
    .name = "emulator", .op = &emulator_ops, .uart = &emulator_uart, .logger = &emulator_logger};

static inline void register_emulator(void) {
  int err = register_device(&emulator_device_type);
  if (err) LOG_ERROR("register emulator device error:%d", err);
}

static inline void unregister_emulator(void) {
  int err = unregister_device(&emulator_device_type);
  if (err) LOG_ERROR("unregister device emulator error:%d", err);
}

static int emulator_init(void) {
  register_emulator();
  return DEVICE_OK;
}

static void emulator_release(void) { unregister_emulator(); }

...

// must be declared at the end of impl.c
DECLARE_DEVICE(emulator);

UML:

classDiagram
    class device_operations{
        +init(void) int
        +get_key(uint8_t*) retcode_t
        +get_device_id(char*) retcode_t
        +fini(void) void
    }

    class uart_operations{
        +init(const char*) int
        +read(const int) char*
        +write(const int, const char*) void
        +clean(const int) void
    }

    class secure_store_operations{
         +init(void) retcode_t
         +write(const char *name, const uint8_t *bufPtr, size_t bufSize) retcode_t
         +read(const char *name, uint8_t *bufPtr, size_t *bufSizePtr) retcode_t
         +delete(const char *name) retcode_t
    }

    class device_t{
        const char* name
        int uart_fd
        device_operation* op
        uart_operation* uart
        device_t* next
    }
    uart_operations <|-- device_t
    device_operations <|-- device_t
    secure_store_operations <|-- device_t
    class wp7702{
        +DECLARE_DEVICE("wp7702")
    }

    class emulator{
        +DECLARE_DEVICE("emulator")
    }

     device_t <|.. emulator
    device_t <|.. wp7702

template inc:

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "conn_http.h"
#include "crypto_utils.h"
#include "device.h"
#include "logger.h"
#include "serializer.h"
#include "tryte_byte_conv.h"
#include "tryte_msg.h"
#include "url.h"

#define SSL_SEED "nonce"
#define ADDRESS                                                                \
  "POWEREDBYTANGLEACCELERATOR999999999999999999999999999999999999999999999999" \
  "999999A"
#define ADDR_LEN 81

int runner(const char* host, const char* port, const char* api)
{
    uint8_t addr[ADDR_LEN] = ADDRESS, next_addr[ADDR_LEN] = {0}, iv[16] = {0};
    char raw_msg[1000] = {0}, ciphertext[1024] = {0};
    char tryte_msg[1024] = {0}, msg[1024] = {0};
    uint32_t raw_msg_len = 1 + ADDR_LEN + 20, msg_len = 0;
    srand(time(NULL));

    device_t *dv = get_device("{% device_name %}");
    int fd = dv->uart->init("{% uart_port %}");
    if (fd < 0) {
      LOG_ERROR("Error in initializing UART\n");
      return -1;
    }

    char* log_msg = malloc(sizeof(char)*ADDR_LEN + 3);
    memset(log_msg, '0', ADDR_LEN + 3);
    snprintf(log_msg, strlen(next_addr), "\n%s", next_addr);
    dv->logger->write_log("{% log_path %}", next_addr, strlen(next_addr));
    free(log_msg);

    char *response = NULL;
    time_t timer;
    char time_str[26];
    struct tm *tm_info;

    fd_set rset;
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 500;
    while (true) {
      FD_ZERO(&rset);
      FD_SET(fd, &rset);
      select(fd + 1, &rset, NULL, NULL, &tv);

      if (FD_ISSET(fd, &rset)) {
        time(&timer);
        tm_info = localtime(&timer);
        strftime(time_str, 26, "%Y-%m-%d %H:%M:%S", tm_info);
        LOG_DEBUG("%s\n", time_str);
        gen_rand_trytes(ADDR_LEN, next_addr);

        response = dv->uart->read(fd);
        snprintf(raw_msg, raw_msg_len, "%s:%s", next_addr, response);

        LOG_DEBUG("Raw Message: %s\n", raw_msg);
        uint8_t private_key[AES_BLOCK_SIZE] = {0};
        uint8_t id[IMSI_LEN] = {0};

        if (dv->op->get_key(private_key) != 0) {
          LOG_ERROR("%s\n", "get aes key error");
          return -1;
        }

        // fetch Device_ID (IMSI, len <= 16)
        if (dv->op->get_device_id(id) != 0) {
          LOG_ERROR("%s\n", "get device id error");
          return -1;
        }
        int ciphertext_len = encrypt(raw_msg, strlen(raw_msg), ciphertext, 1024, iv, private_key, id);
        if (ciphertext_len == 0) {
          LOG_ERROR("encrypt msg error");
          return -1;
        }
        serialize_msg(iv, ciphertext_len, ciphertext, msg, &msg_len);
        bytes_to_trytes((const unsigned char *)msg, msg_len, tryte_msg);

        // Init http session. verify: check the server CA cert.
        char msg_body[1024];
        gen_tryte_msg(tryte_msg, addr, msg_body);
        if (send_https_msg(host, port, api, msg_body, 1024, SSL_SEED) != HTTP_OK) {
          LOG_ERROR("Response from ta server failed");
        }

        memcpy(addr, next_addr, ADDR_LEN);
        free(response);
        response = NULL;
        LOG_INFO("Finish transaction");
      }
      dv->uart->clean(fd);
    }
}

device will be used:

    device_t *dv = get_device("{% device_name %}");
    int fd = dv->uart->init("{% uart_port %}");

test_driver.c:

#define STRINGIZE(x) #x
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)

const char *HOST = STRINGIZE_VALUE_OF(TA_HOST);
const char *PORT = STRINGIZE_VALUE_OF(TA_PORT);
const char *API = STRINGIZE_VALUE_OF(TA_API);

#include "use_models.h"

int main(void) { return runner(HOST, PORT, API); }

build process:

splasky commented 4 years ago

The TA-endpoint is migrated into tangle-accelerator so I close this issue.