Skip to content

implement http server/client#1

Open
tokuhirat wants to merge 1 commit into
mainfrom
feature/add-minimum-server
Open

implement http server/client#1
tokuhirat wants to merge 1 commit into
mainfrom
feature/add-minimum-server

Conversation

@tokuhirat

Copy link
Copy Markdown
Owner

No description provided.

@takumihara takumihara left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

お疲れ様です!goto cleanup/fatal でリソース解放をまとめているのが良いですね。strtol を使った数式パースで連続演算(4+5-3+1)に対応しているのも面白いです!

Comment thread server.c
goto fatal;
}

int n = read(conn_fd, buffer, BUFFERSIZE);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read は1回の呼び出しで全データが読めるとは限らなくて、ネットワーク越しだとリクエストが分割されて届くことがあります。\r\n\r\n(ヘッダの終端)が見つかるまでループで読み続けるようにすると安全です!

あと、read(conn_fd, buffer, BUFFERSIZE) だと、ちょうど1024バイト読んだ場合に NUL 終端がなくなって、後続の strtokstrcpy がバッファの外を読んでしまいます。BUFFERSIZE - 1 にすると安全です。

細かいですが、read の返り値の型は ssize_t です!
https://man7.org/linux/man-pages/man2/read.2.html

Comment thread server.c
goto cleanup;
}

if (write(conn_fd, result, strlen(result)) == -1) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read 同様に write が全部書き込めるかは分からないです

Comment thread server.c
goto cleanup;
}

if (write(conn_fd, result, strlen(result)) == -1) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SIGPIPE のハンドリングも入れてもいいかもです!クライアントが途中で切断した後に write すると SIGPIPE でプロセスが死んじゃいます

Comment thread server.c
Comment on lines +146 to +148
if (strcmp(version, "HTTP/1.1\r\n\r\n") != 0) {
fprintf(stderr, "Unsupported HTTP version: %s (only HTTP/1.1 is supported)\n", version);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここ、fprintf だけで return していないので、バージョンが不正でも処理が続行しちゃいますね。
あと、ブラウザからのリクエストだとヘッダが付くので、version のトークンに \r\n\r\n が含まれないケースがあって、その場合は常に不一致になりそうです

Comment thread server.c
fprintf(stderr, "HTTP header error");
return EXIT_FAILURE;
}
strcpy(method, token);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こういうリクエストが来たらどうなりますか?

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /calc?query=1+2 HTTP/1.1

method[16]strcpy で長さ制限なしで書き込んでいるので、スタックが壊れそうです

Comment thread server.c
Comment on lines +136 to +139
if (strtok(NULL, " ") != NULL) {
fprintf(stderr, "HTTP header error");
return EXIT_FAILURE;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ブラウザからリクエストを送ると、ヘッダが付きますよね?

GET /calc?query=1+2 HTTP/1.1\r\nHost: localhost\r\n\r\n

スペースで strtok すると4つ以上のトークンが出て、ここでエラーになりませんか?

Comment thread server.c
Comment on lines +73 to +74
if (parse_query(buffer, &value) != 0) {
goto cleanup;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

パースが失敗したとき、クライアントには何もレスポンスを返さずに接続を切っていますが、400 Bad Request とかを返してあげるとクライアント側でエラーの原因が分かりやすくなりそうです

Comment thread server.c
return parse_formula(formula, strlen(formula), out);
}

int parse_formula(char* formula, const int formula_len, int* out) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formula_len が使われていないみたいです

Comment thread server.c

int parse_formula(char* formula, const int formula_len, int* out) {
char *p = formula;
int value = strtol(p, &p, 10);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strtol を使っているのはいいですね!ただ、例えば query=99999999999+1 みたいにめちゃくちゃ大きい数が来た場合、strtolERANGEerrno にセットするので、それをチェックするとオーバーフローを検出できます

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants