---
tags: dev
---
# Note
---
## Code Review (2022/04/01)
### 1. 架構

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

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

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

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 四元素
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 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


[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時間複雜度

```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時間複雜度

```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的測試結果

### 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的測試結果

剛好這個例子換指令可以用-fsanitize=address抓到memory leak
```bash=
gcc testtsan.c -o testtsan.out -lpthread -fsanitize=address && ./testtsan.out
```
#### asan測試抓memory leak的結果,但很遺憾asan和tsan兩個參數不能同時全上

---
## 關於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)