--- tags: dev --- # Note --- ## Code Review (2022/04/01) ### 1. 架構 ![](https://i.imgur.com/zpgf6sH.png) ### 2. 功能 #### 1. python3 ./config_generator.py demo: 產生範本config.csv檔 #### 2. python3 ./config_generator.py struct: 產生config.h檔 #### 3. python3 ./config_generator.py db: 產生config.sqlite檔 --- ## Sqlite Introduction (2022/1/15) ### Benchmark | time | create | rand, read | rand. update | | ---- | ---- | ---- | ---- | | 100次 | 13 | 0.55 | 16 | | 1000次 | 26 | 0.4 | 23 | | 10000次(emmc)| 252 | 4.9 | 244 | | 10000次(ram)| 8.75 | 5 | 244 | ### Development Resource * Linux/Windows * C/C++ API ready * read/write encrypted database files with add-on * sqlite3 CLI tool - debugging ### Data Model * Relational Database ![](https://i.imgur.com/tmiaXMa.png) ### Syntax Example ```sql= -- get data by keyword 'Texas' and id 6 SELECT * FROM table_name; UPDATE COMPANY SET ADDRESS = 'Texas' WHERE ID = 6; --- delete data by age == 25 but abort delete for some reason BEGIN; DELETE FROM COMPANY WHERE AGE = 25; ROLLBACK; --- delete data by age == 25 and execute indeed. BEGIN; DELETE FROM COMPANY WHERE AGE = 25; COMMIT; ``` --- ## Redis config code review(2021/12/03) ref: 1. https://github.com/redis/redis#running-redis-with-tls ![](https://i.imgur.com/juZcM9P.png) ### what is Redis? 1. data structures server 2. server-client model with TCP sockets 3. The implementation of data structures emphasizes memory efficiency ### config.c 1. config #2525 2. init #387 3. load from string #398 --- ## mbedtls example ssl server code review(2021/11/19) --- ref: 1. [ARMmbed/mbedtls](https://github.com/ARMmbed/mbedtls) ![](https://i.imgur.com/5qpXW9g.png) 2. [那些關於SSL/TLS的二三事](https://medium.com/@clu1022/%E9%82%A3%E4%BA%9B%E9%97%9C%E6%96%BCssl-tls%E7%9A%84%E4%BA%8C%E4%B8%89%E4%BA%8B-%E4%B9%9D-ssl-communication-31a2a8a888a6) 3. [密碼套件cipher suite](https://zh.wikipedia.org/wiki/%E5%AF%86%E7%A0%81%E5%A5%97%E4%BB%B6) ### SSL Handshake ![SSL Handshake](https://miro.medium.com/max/1400/1*T0fYgX-r9tT90Zwxcqzvbg.png) ### SSL 四元素 1. 身分驗證 1. 憑證 * 確認訊息來源 1. 非對稱加密 1. RSA、DH 2. 憑證/X509 3. PKI (public key infrastructure) * 保護金鑰 4. 對稱加密 1. 金鑰 * 保護訊息不被偷看 5. 完整性檢查 1. MD5、SHA256 * HMAC(key-hashed message authentication code) * 保護訊息不被竄改 ### cipher suite的意思 * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 1. TLS 2. ECDHE 3. RSA 4. AES128 5. GCM 6. SHA256 ### code review point programs/ssl/ssl_server.c 1. #162行:利用mbedtls_printf解釋code 2. #143行:fflush的必要性 3. #267行:ssl這個struct的設計 4. library/ssl_tls.c #5262行:mbedtls_ssl_handshake握手結構的設計 --- ## multiplex socket communication(2021/10/29) ref: 1. [Linux IO: select, poll, epoll](https://blog.maxkit.com.tw/2019/07/linux-io-select-poll-epoll.html) 2. [官網](https://libevent.org/) ### Psuedo code 1. select * 陣列 * 32bit/1024 64bit/2048 * 自己聽 自己讀 ```c= for (int i = 0; i < MAX_FD_SETS; ++i) { ... } ``` 2. poll * linked list * 無上限 * 自己聽 自己讀 ```c= while (fds->next != NULL){ ... } ``` 3. epoll * rb tree * 無上限 * kernel聽 自己讀 ```c= wait_ev(socket) ``` 4. libevent * 跨平台 * 效能佳 * 架構好 lib底層幫忙聽幫忙讀 ```c= add_listener(write_cb, read_cb, error_cb); ``` --- ## 操作TLV (2021/10/22) ![tlv image](https://slidetodoc.com/presentation_image_h/19407ee64e65e3b435bc430d65abcd01/image-8.jpg) 參考資料:[TLV c語法hack](https://wirelessr.gitbooks.io/working-life/content/tlvsu_cheng_jiang_jie.html) ```c= typedef struct _tlv_1{ int type; int len; char val[0]; // c99-support // char val[]; } tlv_1; typedef struct _tlv_2{ int type; int len; char *p_val; } tlv_2; int val_of_len = 10; tlv_1 *obj_1 = (tlv_1*)malloc(sizeof(tlv_1) + val_of_len); tlv_2 *obj_2 = (tlv_2*)malloc(sizeof(tlv_2) + val_of_len - sizeof(char*)); // 優勢在於sizeof的時候可以直接省去扣掉一個指標的大小 int i = 0; while (i < 10) { obj_1 += sizeof(tlv_1) + obj_1->len; obj_2 += sizeof(tlv_2) - sizeof(char*) + obj_2->len; ++i; } ``` --- ## code review OpenVPN ![](https://i.imgur.com/hfdeTmY.png) ![](https://i.imgur.com/FpkA93t.png) [OpenVPN github link](https://github.com/OpenVPN/openvpn) 1. tun/tap 2. encrypt 3. buffer 使用 4. openvpn_main -> process_io -> read_incoming_tun -> encrypt_sign --- ## 類wireshark的CLI工具termshark https://github.com/gcla/termshark * 有點肥123MB ### 安裝 ```bash= sudo apt install termshark ``` ### 使用 ```bash= sudo termshark -i ens5 ``` --- ## code review mongoose https://github.com/cesanta/mongoose.git 1. tcp socket 1. listen 2. accept 3. recv 2. http header ```xml= GET / HTTP/1.1 \r\n host: www.google.com \r\n \r\n ``` 5. 優點 * 適度的抽象化 * 簡單的測試 * 幾乎不依賴任何lib * 精簡但看得懂的命名 7. review point 1. mg_http_listen 2. mg_mgr_poll 3. mg_call 4. str家族 5. mg_http_parse 6. mg_http_get_header 7. 8. readme ## 如何使用hsearch, tsearch, bsearch(2021/08/13) ### bsearch * binary search * 時機:資料少或沒有頻繁update data時 * c89標準 * stdlib * array必須先排序 (qsort可幫忙) * [Stackoverflow參考連結](https://en.wikipedia.org/wiki/Sorted_array) * [linux man參考連結](https://man7.org/linux/man-pages/man3/bsearch.3.html) * sorted array時間複雜度 ![](https://i.imgur.com/jIoTtrP.png) ```c= #include <stdio.h> #include <stdlib.h> #include <string.h> struct mi { int nr; char *name; } months[] = { { 1, "jan" }, { 2, "feb" }, { 3, "mar" }, { 4, "apr" }, { 5, "may" }, { 6, "jun" }, { 7, "jul" }, { 8, "aug" }, { 9, "sep" }, {10, "oct" }, {11, "nov" }, {12, "dec" } }; #define nr_of_months (sizeof(months)/sizeof(months[0])) static int compmi(const void *m1, const void *m2) { const struct mi *mi1 = m1; const struct mi *mi2 = m2; return strcmp(mi1->name, mi2->name); } int main(int argc, char **argv) { qsort(months, nr_of_months, sizeof(months[0]), compmi); for (int i = 1; i < argc; i++) { struct mi key; struct mi *res; key.name = argv[i]; res = bsearch(&key, months, nr_of_months, sizeof(months[0]), compmi); if (res == NULL) printf("'%s': unknown month\n", argv[i]); else printf("%s: month #%d\n", res->name, res->nr); } exit(EXIT_SUCCESS); } ``` ### tsearch * POSIX, GNU C(非標準c) * 時機:頻繁update data時 * Knuth (6.2.2) algorith(optimal binary search tree) * binary search tree * [wiki參考連結](https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%85%83%E6%90%9C%E5%B0%8B%E6%A8%B9) * [Stackoverflow參考連結](https://stackoverflow.com/questions/647054/porting-stdmap-to-c) * bst時間複雜度 ![](https://i.imgur.com/PNaJdjk.png) ```c= #include <search.h> #include <stdlib.h> #include <string.h> #include <stdio.h> typedef struct { int key; char* value; } intStrMap; int compar(const void *l, const void *r) { const intStrMap *lm = l; const intStrMap *lr = r; return lm->key - lr->key; } int main(int argc, char **argv) { void *root = 0; intStrMap *a = malloc(sizeof(intStrMap)); a->key = 2; a->value = strdup("two"); tsearch(a, &root, compar); /* insert */ intStrMap *find_a = malloc(sizeof(intStrMap)); find_a->key = 2; void *r = tfind(find_a, &root, compar); /* read */ printf("%s", (*(intStrMap**)r)->value); return 0; } ``` ### hsearch * POSIX, GNU C(非標準c) * 時機:資料量大且不常update data * hash * Knuth (6.3) algorithm * [Linux man參考連結](https://man7.org/linux/man-pages/man3/hsearch.3.html) ```c= #include <stdio.h> #include <stdlib.h> #include <search.h> static char *data[] = { "alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliet", "kilo", "lima", "mike", "november", "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform", "victor", "whisky", "x-ray", "yankee", "zulu" }; int main(void) { ENTRY e; ENTRY *ep; hcreate(30); for (int i = 0; i < 24; i++) { e.key = data[i]; /* data is just an integer, instead of a pointer to something */ e.data = (void *) i; ep = hsearch(e, ENTER); /* there should be no failures */ if (ep == NULL) { fprintf(stderr, "entry failed\n"); exit(EXIT_FAILURE); } } for (int i = 22; i < 26; i++) { /* print two entries from the table, and show that two are not in the table */ e.key = data[i]; ep = hsearch(e, FIND); printf("%9.9s -> %9.9s:%d\n", e.key, ep ? ep->key : "NULL", ep ? (int)(ep->data) : 0); } hdestroy(); exit(EXIT_SUCCESS); } ``` --- ## 如何使用address sanitizer 和thread sanitizer (2021/06/24) > [sanitizer](https://github.com/google/sanitizers)是一個google發起的專案 > 本次目的是使用libasan.so和libtsan.so幫忙抓出runtime的bug > > [libasan](https://github.com/google/sanitizers/wiki/AddressSanitizer): segmentation fault和memory leak之類記憶體類問題 > [libtsan](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual): race condition ### 1. address sanitizer example #### 測試compiler:arm-linux-gnueabihf (32bit) ```c= // testasan.c int foo3(char *p) { // segmentation fault at here p[0] = 1; } int foo2(char *p) { foo3(p); } int foo1(char *p) { foo2(p); } ``` ```c= // test.c int main() { int a = 0; foo1((char*)a); } ``` 在找個資料夾,把上面兩份code存成testasan.c和test.c然後執行下面指令 ```bash= gcc testasan.c -o libtestasan.so -fsanitize=address -fPIC -shared -Wl,-rpath=. gcc test.c -o testasan.out -fsanitize=address -L. -ltestasan -Wl,-rpath=. ./testasan.out ``` #### asan的測試結果 ![](https://i.imgur.com/7vv3dMm.png) ### 2. thread sanitizer example #### 測試測試compiler:x86_64-linux-gnu (64bit限定,據說32bit不支援) ```c= // test.c #include <pthread.h> #include <stdlib.h> #include <stdio.h> int *gp_var = NULL; #define MAX 10 void* count() { // race condition at here for (size_t i = 0; i < MAX; ++i) { ++*gp_var; } } int main() { gp_var = (int*)malloc(sizeof(int) * 1); pthread_t t[MAX]; for (size_t i = 0; i < MAX; ++i) { pthread_create(&t[i], NULL, count, NULL); } for (size_t i = 0; i < MAX; ++i) { pthread_join(t[i], NULL); } printf("gp_var: %d\n", *gp_var); // memeory leak at here // free(gp_var); gp_var = NULL; } ``` ```bash= gcc testtsan.c -o testtsan.out -lpthread -fsanitize=thread && ./testtsan.out ``` #### tsan 抓race condition的測試結果 ![](https://i.imgur.com/xoQmvUf.png) 剛好這個例子換指令可以用-fsanitize=address抓到memory leak ```bash= gcc testtsan.c -o testtsan.out -lpthread -fsanitize=address && ./testtsan.out ``` #### asan測試抓memory leak的結果,但很遺憾asan和tsan兩個參數不能同時全上 ![](https://i.imgur.com/8hXJwI7.png) --- ## 關於gcc 的linker參數(2021/06/04) ### 1. Q. link階段的error可不可以跳過? #### A. 可以,gcc帶上參數 ```bash= gcc test.c -Wl,--unresolved-symbols=ignore-in-object-files ``` [資料來源](https://stackoverflow.com/questions/5555632/can-gcc-not-complain-about-undefined-references) ### 2. Q. -Wl是什麼意思? #### A. -Wl是把參數帶給linker的意思,後面用逗號隔開,下面三者對linker的作用等價gcc -Wl,aaa -Wl,bbb -Wl,ccc ```bash= gcc -Wl,aaa -Wl,bbb -Wl,ccc ``` ```bash= gcc -Wl,aaa,bbb,ccc ``` ```bash= ld aaa bbb ccc ``` ### 3. Q. LD_LIBRARY_PATH可不可以在編譯階段就先指定好路徑 #### A. 可以,把參數帶給linker,但在這邊要注意一下不是用gnu linker的話可能不能這樣用。 ```bash= gcc -Wl,-rpath=/usr/lib/moxa ``` [A2和A3的資料來源](https://stackoverflow.com/questions/6562403/i-dont-understand-wl-rpath-wl)