Upgrade to Pro — share decks privately, control downloads, hide ads and more …

自作WebSocket (RFC6455)

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

自作WebSocket (RFC6455)

趣味でC言語(C23) + アセンブラを使い、外部ライブラリ依存なしでRFC6455準拠のWebSocketサーバーライブラリを自作した話です。
HTTP 0.9からWebSocket・HTTP3.0までのWeb通信の変遷を振り返りつつ、libcに依存せずシステムコールを直接呼び出す実装アプローチや、macOS・Linux・Windowsそれぞれの制約についても触れています。
バイナリサイズ1MB以下・scratchコンテナで動作するシングルバイナリが推しポイントです。

More Decks by 株式会社イノベーション(エンジニア)

Other Decks in Technology

Transcript

  1. [introduce] name = “林 宏次郎” joining_date = “ 2025/3/3” department

    = “SRE” hobby = [“卓球🏓”, “謎解き🔍”] UTF-8 NORMAL main introduce.toml
  2. OSI 7階層モデル L1 物理層 (ケーブル‧電気信号) L2 データリンク層 (Ethernet, WiFi) L3

    ネットワーク層 (IP, ICMP) L4 トランスポート層 (UDP / TCP) L6 プレゼンテーション層 (SSL/TLS) L7 アプリケーション層 (HTTP / WebSocket / SMTP / FTP) L5 セッション層 (HTTPのハンドシェイク)
  3. Web通信の変遷 3 1997年〜 HTTP 1.1 [RFC2068 -> RFC2616 -> RFC7230〜7235

    -> RFC9112] 単⼀のTCPコネクションで複数のHTTPリクエストが送れるようになった GET /index.html HTTP/1.1 Host: foo.example.com Connection: keep-alive -> TCPコネクションを使いまわす
  4. Web通信の変遷 4 2011年〜 WebSocket [RFC6445] 単⼀TCPストリームでリクエスト/レスポンスの双⽅向通信ができるようになった HTTP1.1 で動作する GET /resource

    HTTP/1.1 Host: example.com Upgrade: websocket Connection: upgrade Sec-WebSocket-Version: 13 Sec-WebSocket-Key: E4WSEcseoWr4csPLS2QJHA==
  5. Web通信の変遷 6 2015年〜 SSE (Server Sent Event) [RFC] HTTPでサーバーから通知を送れるようになった (サーバー

    -> クライアントの⼀⽅通⾏) HTTP1.1, HTTP2.0で実⾏可能 GET /events HTTP/1.1 Host: example.com Accept: text/event-stream -> 継続的にサーバーからイベントが貰える Cache-Control: no-cache Connection: keep-alive
  6. ⾃作WebSocketライブラリの特徴 ‧開発⾔語: C⾔語 (C23) + アセンブラ ‧サポートOS: macOS, Linux ‧ライブラリ依存:

    無し (Linuxの場合) ‧機能サポート状況: 右記 (機能的には最低限) opcode support 0x1 (text), 0x2(binary), 0x8 (close), 0xA (pong) TLS support No Sub Protocol No Extensions No Compression / Decode No
  7. 推しポイント 1. C⾔語 + アセンブラによる構成 -> ⾼速 2. 依存ライブラリなし ->

    Dockerコンテナ(scratch)にバイナリ1つコピーすれば動作する -> コンパクトなバイナリ/コンテナ (サイズ < 1MB)
  8. システムコール (Linux / x86_64の場合) __linux_x8664_asm_syscall: movq %rdi, %rax movq %rsi,

    %rdi movq %rdx, %rsi movq %rcx, %rdx movq %r8, %r10 movq %r9, %r8 syscall ret システムコールを アセンブラで呼ぶ必要がある OSやCPUアーキテクチャで 使うレジスタや書き⽅が変わる
  9. システムコール (Linux / x86_64の場合) syscall (arg1, arg2, arg3, arg4, arg5,

    arg6) rdi rsi rdx rcx r8 r9 rax rdi rsi rdx r10 r8 システムコールで 使うレジスタ 引数の値が 渡されるレジスタ syscall レジスタを読み替えて渡す必要がある
  10. システムコール (他のOSの場合) さっき書いたスペック表 ‧開発⾔語: C⾔語 (C23) + アセンブラ ‧サポートOS: macOS,

    Linux ‧ライブラリ依存: 無し (Linuxの場合) => これには理由があります ‧機能サポート状況: 右記 (機能的には最低限)
  11. システムコール (余談: Windows の場合) カーネル 空間 システム コール ユーザー 空間

    libc Windows API (DLL) NTDLL (DLL) OSや アーキテクチャ の差異を吸収 ここまではサポートされている
  12. どのくらい⾃作したか WebSocketのパーサー / ハンドシェイク(通信確⽴)の他には... ‧ハンドシェイクに必要なHTTP1.1の解釈 (RFC9110 / RFC9112) ‧ デバッグするためのログ出⼒

    ‧ハンドシェイクに必要な暗号化の関数 (base64 / sha1) ※sha1はパブリックドメインのソースを埋め込み & リファクタ TCP/IPから上のレイヤーは、ほぼ⾃作 (TCP/IPはカーネルの機能を使⽤)
  13. 課題 ‧SSL/TLSの⾃作 => ⼀旦断念している ‧暗号系の関数 (楕円曲線暗号など) を⾃作するコストが⾮常に⾼い ‧外部に出すには必須 => 今のところ、テストや内部ネットワーク⽤

    ‧HTTP1.1にしか対応していない ‧HTTP2.0で動かすには、RFC8441等の実装が必要 ‧HTTP3.0は標準でTLS通信をサポートしているため、実装が難しい
  14. 今後の展望 ‧SSL/TLSの⾃作 (いつか) ‧HTTP 2.0 でのWebSocket サポート (RFC8441) ‧WebSocketとしての機能拡充 (NoをYesにしていく)

    opcode support 0x1 (text), 0x2(binary), 0x8 (close), 0xA (pong) TLS support No Sub Protocol No Extensions No Compression / Decode No