diff --git a/doc.md b/doc.md new file mode 100644 index 0000000..4578305 --- /dev/null +++ b/doc.md @@ -0,0 +1,5 @@ +# Build TCP Server +我們使用posix socket制作主要的HTTP伺服器, +我們在bind的socket使用O_NONBLOCK,在一個poll裏使用迴圈檢查是否有需要accept的request, +我們對客戶端的socket(accepted)使用blocking io與select處理鏈接。 +我們的伺服器只有單一線程,以避免相關的同步問題且避免因爲受限的環境且容易處理底下的tag syncing 問題 diff --git a/main/controlplane.c b/main/controlplane.c index c6358e1..9cd6c15 100644 --- a/main/controlplane.c +++ b/main/controlplane.c @@ -1,6 +1,7 @@ #include "./lib/meshtalos.h" #include "esp_err.h" #include "network.h" +#include "soc/rtc.h" #include #include #include diff --git a/main/lib/meshtalos.c b/main/lib/meshtalos.c index 71b2bdd..5f3743e 100644 --- a/main/lib/meshtalos.c +++ b/main/lib/meshtalos.c @@ -1,6 +1,7 @@ #include "meshtalos.h" #include "./mpack.h" #include "./picohttpparser.h" +#include "lwip/inet.h" #include "lwip/sockets.h" #include #include @@ -22,8 +23,8 @@ #define HTTPVER "HTTP/1.1" #define IMG_W_SIZE 152 #define IMG_H_SIZE 296 -#define DISPLAY_SIZE IMG_W_SIZE *IMG_H_SIZE -#define IMG_HEADER_SIZE 15 +#define DISPLAY_SIZE (IMG_W_SIZE * IMG_H_SIZE / 8) +#define IMG_HEADER_SIZE 11 #define IMG_SIZE IMG_HEADER_SIZE + DISPLAY_SIZE struct client { @@ -72,6 +73,7 @@ ssize_t client_send(struct client *cli, const char *buf, size_t len) { if (cli->invalid) { return -1; } + printf("client written: %d\n", len); int ret = send(cli->fd, buf, len, MSG_NOSIGNAL); if (ret < 0) { cli->invalid = true; @@ -174,12 +176,10 @@ int fbadreq(struct client *c, const char *s, ...) { return -1; } int api_tag_upload(struct client *c, struct http_param *p) { - - printf("INTO TAG RECV\n"); int acc = 0; for (int i = 0; i < p->headers_len; i++) { if (HEAD_MATCH("Content-Type", p->headers[i]) && - HEAD_VAL_MATCH("image/x-portable-greymap", p->headers[i])) { + HEAD_VAL_MATCH("image/x-portable-bitmap", p->headers[i])) { acc++; } if (HEAD_MATCH("Content-Length", p->headers[i])) { @@ -192,18 +192,19 @@ int api_tag_upload(struct client *c, struct http_param *p) { if (acc != 2) { return fbadreq(c, - "Only accept request with PGM P5 format that height and " + "Only accept request with PGM P4 format that height and " "width is either %03d,%03d", IMG_W_SIZE, IMG_H_SIZE); } size_t upload_size = p->body_len; memcpy(imgbuf, p->body_start, p->body_len); + printf("tag read %d\n", p->body_len); while (upload_size < IMG_SIZE) { // upload PGM sanitize if (upload_size > IMG_HEADER_SIZE) { - if (strncmp(imgbuf, "P5", 2) != 0) { + if (strncmp(imgbuf, "P4", 2) != 0) { return badreq(c); } int santinize_acc = 0; @@ -235,7 +236,11 @@ int api_tag_upload(struct client *c, struct http_param *p) { ? sizeof(httpbuf) : IMG_SIZE - upload_size; ssize_t rcv_size = client_recv(c, httpbuf, next_size); + if (rcv_size != next_size) { + return fbadreq(c, "size mistmatch"); + } memcpy(imgbuf + upload_size, httpbuf, rcv_size); + printf("tag read %d\n", p->body_len); upload_size += next_size; } @@ -311,56 +316,44 @@ void http_client_handle(struct conn *c, struct client *client, int client_id) { } } +static inline int get_bit(const uint8_t *buf, int w, int x, int y) { + int i = y * w + x; + return (buf[i >> 3] >> (7 - (i & 7))) & 1; +} + +static inline void set_bit(uint8_t *buf, int w, int x, int y, int v) { + int i = y * w + x; + uint8_t m = 1 << (7 - (i & 7)); + if (v) + buf[i >> 3] |= m; + else + buf[i >> 3] &= ~m; +} + /** - * @brief Rotates an 8-bit image 90 degrees clockwise IN-PLACE. - * @param data Pointer to the image buffer (1 byte per pixel) - * @param W Original width (e.g., 296) - * @param H Original height (e.g., 152) - * * NOTE: After this function, the logical width is H and height is W. - * The buffer must be large enough to hold W*H bytes. + * @brief In-place 90-degree clockwise rotation for 1-bit-per-pixel images. + * @param data The image buffer + * @param W Original width + * @param H Original height */ -void rotate90_clockwise_inplace(uint8_t *data, int W, int H) { - int total_pixels = W * H; +void rotate90_inline(uint8_t *data, int W, int H) { + static uint8_t temp[(IMG_H_SIZE * IMG_W_SIZE + 7) / 8] = {0}; - // We need 1 bit per pixel to track if we've moved it. - // For 296x152, this is 44,992 bits = 5,624 bytes. - uint8_t *visited = (uint8_t *)calloc((total_pixels + 7) / 8, 1); - if (!visited) - return; // Handle allocation failure (OOM) + int new_w = H; + int new_h = W; - for (int i = 0; i < total_pixels; i++) { - // Skip if this pixel was already moved as part of a previous cycle - if (visited[i >> 3] & (1 << (i & 7))) - continue; + for (int y = 0; y < H; y++) { + for (int x = 0; x < W; x++) { + int v = get_bit(data, W, x, y); - int curr_idx = i; - uint8_t val_to_move = data[i]; - - while (!(visited[curr_idx >> 3] & (1 << (curr_idx & 7)))) { - // Mark as visited - visited[curr_idx >> 3] |= (1 << (curr_idx & 7)); - - // Calculate new coordinates for 90-degree clockwise - // (x, y) -> (H - 1 - y, x) - int x = curr_idx % W; - int y = curr_idx / W; - - // The NEW dimensions are Height H and Width W (swapped) - // New 1D Index = new_y * NEW_WIDTH + new_x - // For 90deg CW: new_x = H - 1 - y, new_y = x - int next_idx = x * H + (H - 1 - y); - - // Swap values - uint8_t temp = data[next_idx]; - data[next_idx] = val_to_move; - val_to_move = temp; - - curr_idx = next_idx; + // (x, y) → (h-1-y, x) + // set_bit(temp, new_w, H - 1 - y, x, v); + set_bit(temp, new_w, y, x, v); } } - free(visited); + memcpy(data, temp, DISPLAY_SIZE); } -#define IMG_BLK_SIZE 1024 +#define IMG_BLK_SIZE 300 void flush_mpack(mpack_writer_t *wr, const char *b, size_t len) { struct client *c = mpack_writer_context(wr); @@ -380,7 +373,7 @@ void send_image(struct client *c) { mpack_write_cstr(&wr, "command"); mpack_write_cstr(&wr, "update_image"); mpack_write_cstr(&wr, "index"); - mpack_write_u64(&wr, i); + mpack_write_u64(&wr, i - IMG_HEADER_SIZE); mpack_write_cstr(&wr, "data"); mpack_write_bin(&wr, &imgbuf[i], MIN(IMG_BLK_SIZE, IMG_SIZE - i)); mpack_finish_map(&wr); @@ -414,8 +407,9 @@ void tsend() { } printf("img_w: %d, img_h: %d\n", img_w, img_h); if (img_w == IMG_H_SIZE) { - rotate90_clockwise_inplace((uint8_t *)imgbuf + IMG_HEADER_SIZE, IMG_H_SIZE, - IMG_W_SIZE); + printf("rotate\n"); + rotate90_inline((uint8_t *)imgbuf + IMG_HEADER_SIZE, IMG_H_SIZE, + IMG_W_SIZE); } for (int i = 0; i < arrlen(workers.c); i++) { send_image(workers.c + i); @@ -424,12 +418,12 @@ void tsend() { int main_listen(const int worker_port, int http_port) { // workers - int sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + int sfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in b = {0}; memset(&b, 0, sizeof(struct sockaddr_in)); b.sin_port = htons(worker_port); - b.sin_addr.s_addr = htonl(INADDR_ANY); b.sin_family = AF_INET; + b.sin_addr.s_addr = htonl(INADDR_ANY); int val = 1; assert(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) != -1); assert(bind(sfd, (struct sockaddr *)&b, sizeof(b)) != -1); @@ -443,8 +437,8 @@ int main_listen(const int worker_port, int http_port) { int httpfd = socket(AF_INET, SOCK_STREAM, 0); memset(&b, 0, sizeof(struct sockaddr_in)); b.sin_port = htons(http_port); - b.sin_addr.s_addr = htonl(INADDR_ANY); b.sin_family = AF_INET; + b.sin_addr.s_addr = htonl(INADDR_ANY); val = 1; assert(setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) != -1); assert(bind(httpfd, (struct sockaddr *)&b, sizeof(b)) != -1); diff --git a/main/lib/meshtalos.h b/main/lib/meshtalos.h index 70e5bff..2fcf13b 100644 --- a/main/lib/meshtalos.h +++ b/main/lib/meshtalos.h @@ -11,12 +11,6 @@ #include "./storage.h" #define TOPIC_LEN 20 -#define IMG_W_SIZE 152 -#define IMG_H_SIZE 296 -#define DISPLAY_SIZE IMG_W_SIZE *IMG_H_SIZE -#define IMG_HEADER_SIZE 15 -#define IMG_SIZE IMG_HEADER_SIZE + DISPLAY_SIZE -#define IMG_BLK_SIZE 300 struct Meshtalos { struct Storage *storage; diff --git a/tests/fill_random.py b/tests/fill_random.py new file mode 100644 index 0000000..758b8ca --- /dev/null +++ b/tests/fill_random.py @@ -0,0 +1,9 @@ +import requests as req +import random + +blksize = 152 * 296 + +body = random.randbytes(blksize) + +r = req.get("http://10.189.34.75/api/tag",data=body) +print(r.status_code)