ちょっとしたツールを作る際にシングルヘッダのライブラリは非常に役立ちます。json を STL ライクに扱える picojson 等が有名ですね。
今日は GitHub で mmx というシングルヘッダライブラリを見つけました。
vurtun/mmx - GitHub
single header libraries for C/C++
https://github.com/vurtun/mmx
同梱されているライブラリは、JSON パーサ、C言語っぽい字句解析器、マルチスレッドスケジューラ、行列演算、ライトウェイトなウェブサーバです。
今日はこれを使ってファイルをサーブする簡単なウェブサーバを書いてみました。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#define MMW_STATIC
#define MMW_IMPLEMENTATION
#define MMW_USE_FIXED_TYPES
#define MMW_USE_ASSERT
#include "mm_web.h"
#ifdef _WIN32
#include <winsock2.h>
#define SERVER_INIT { \
WORD wsa_version = MAKEWORD(2,2); \
WSADATA wsa_data; \
if (WSAStartup(wsa_version, &wsa_data)) { \
fprintf(stderr, "WSAStartup failed\n"); \
return 1; \
} \
}
#define SERVER_FINISH \
WSACleanup();
#else
#define SERVER_INIT
#define SERVER_FINISH
#endif
#ifdef __APPLE__
#include <unistd.h>
#endif
static void
logger(const char* text) {
printf("[debug] %s\n", text);
}
static int
dispatch(struct mmw_con *conn, void *userdata) {
FILE* fp;
char buf[4096];
struct stat fi;
strcpy(buf, "./public");
strcat(buf, conn->request.uri);
if (buf[strlen(buf)-1] == '/') strcat(buf, "index.html");
if (stat(buf, &fi)) return 1;
fp = fopen(buf, "r");
if (!fp) return 1;
mmw_response_begin(conn, 200, (int) fi.st_size, NULL, 0);
while (!feof(fp)) {
int n = fread(buf, 1, sizeof buf, fp);
mmw_write(conn, buf, n);
}
mmw_response_end(conn);
fclose(fp);
return 0;
}
int
main(void) {
void *memory = NULL;
mmw_size needed_memory = 0;
struct mmw_server server;
struct mmw_config config;
memset(&config, 0, sizeof config);
config.address = "127.0.0.1";
config.port = 8888;
config.connection_max = 4;
config.request_buffer_size = 2048;
config.io_buffer_size = 8192;
config.log = logger;
config.dispatch = dispatch;
SERVER_INIT;
mmw_server_init(&server, &config, &needed_memory);
memory = calloc(needed_memory, 1);
mmw_server_start(&server, memory);
while (1) mmw_server_update(&server);
mmw_server_stop(&server);
free(memory);
SERVER_FINISH;
return 0;
}
お決まりの手順がならびますが、ライトウェイトとは言えどある程度カスタマイズが可能なウェブサーバが作れそうです。パフォーマンスを計測してみようと思ったのですが、どこかで刺さって完走できませんでした。ただ落ちるといった事はありませんし、ブラウザで閲覧する限りにはちゃんと動作している様です。
ちょろっとファイルサーバを書きたい、といったニーズには便利そうです。
ライセンスは mm_json.h、mm_lexer.h、mm_sched.h、mm_vec.h が zlib ライセンス、mm_web.h が BSD ライセンスになります。