---
# System prepended metadata

title: Note
tags: [dev]

---

---
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)

