コンテンツにスキップ

購読者の認可

デフォルトでは、ハブはすべての SUBSCRIBE(購読のリクエスト)を許可します。 wired_moqt_hub.authorize_subscribe を設定すると、ハブはリレーになり、 自分のトラックとピア(接続相手)のトラックを問わず、他のどの処理よりも前に すべてのリクエストを検査します。

コード

main.c
#define WIRED_MAIN
#include "wired.h"
/* draft-ietf-moq-transport-22 15.3 subscriber authorization: this
* sample's policy grants "public" and refuses everything else (the token
* carries CAT/Privacy Pass in a real deployment; this demo ignores it). */
static int authorize(
void* ctx, const moqctl_ftn* name, const moqctl_token* token) {
(void)ctx;
(void)token;
return wired_span_eq_cstr(name->name, "public");
}
static wired_moqt_hub g_hub;
int wired_main(int argc, char** argv) {
/* The same fixed demo identity as the other MoQT pages, plus QUIC
* DATAGRAM support. */
static wired_srvboot_demo_keys keys;
wired_srvboot_id id;
wired_srvboot_demo(&id, &keys, 0x50, "guide-az");
id.max_datagram_frame_size = 65535;
wired_moqt_io io = wired_moqraw_io();
wired_moqt_init(&g_hub, io);
g_hub.authorize_subscribe = authorize;
/* The hub holds exactly one blob track at a time (a second publish
* would replace it), so "secret" is never published at all: the policy
* below refuses it before matching ever runs, the same outcome a real
* relay wants for a track its policy will never grant regardless of
* whether it exists. */
static u8 public_wire[MOQDATA_BLOB_WIRE_CAP(2)];
wired_moqt_publish_blob(
&g_hub, wired_span_cstr("public"), 1, wired_span_cstr("ok"),
wired_mspan_of(public_wire, sizeof public_wire));
/* The hub owns every WebTransport session. A client that offers the
* subprotocol "moqt-22" gets draft-ietf-moq-transport-22: the hub sends
* SETUP on a uni control stream of its own (6.3), answers each request
* on the bidi stream it arrived on (6.4.2), and forgets it on close. */
wired_srvrun_opt opt = {0};
opt.incoming_cpu = -1;
opt.wt_protocols = "moqt-22";
opt.wt_on_session = wired_moqt_on_session;
opt.wt_session_ctx = &g_hub;
opt.wt_on_stream_data = wired_moqt_on_stream_data;
opt.wt_stream_data_ctx = &g_hub;
opt.wt_on_datagram = wired_moqt_on_datagram;
opt.wt_datagram_ctx = &g_hub;
opt.wt_on_session_close = wired_moqt_on_session_close;
opt.wt_session_close_ctx = &g_hub;
u16 port = (u16)wired_cliargs_int(argc, argv, "--port", 4433);
wired_srvrun_handler h = {0};
wired_srvrun_obs obs = {0};
return wired_server_run_opt(port, &id, h, obs, &opt) ? 0 : 1;
}

クライアント

client.go
package main
import (
"bufio"
"context"
"fmt"
"os"
"time"
"wired-guide/moqtclient"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// "moqt-22" session: SETUP exchanged on the two uni control streams.
s := moqtclient.Dial(ctx, os.Args[1]+"/moqt")
defer s.Conn.CloseWithError(0, "")
// "public": the policy grants it -- SUBSCRIBE_OK on its request
// stream, then its Object on a uni stream.
if reply, _ := s.Subscribe(ctx, 0, "public"); reply.Ok {
fmt.Printf("public SUBSCRIBE_OK alias=%d\n", reply.Alias)
uni, err := s.AcceptUniStream(ctx)
moqtclient.Check(err)
_, _, payload := moqtclient.ReadObject(bufio.NewReader(uni))
fmt.Printf("public payload=%q\n", payload)
} else {
fmt.Printf("public REQUEST_ERROR error_code=%d\n", reply.ErrCode)
}
// "secret": the policy refuses it -- REQUEST_ERROR, no stream ever
// opens for it.
if reply, _ := s.Subscribe(ctx, 2, "secret"); reply.Ok {
fmt.Printf("secret SUBSCRIBE_OK alias=%d\n", reply.Alias)
} else {
fmt.Printf("secret REQUEST_ERROR error_code=%d\n", reply.ErrCode)
}
}

実行結果

Terminal window
$ ./moqt-authorize --port 4433
conn closed by peer (CONNECTION_CLOSE)
Terminal window
$ go run . https://127.0.0.1:4433
public SUBSCRIBE_OK alias=1
public payload="ok"
secret REQUEST_ERROR error_code=1
  • hub.authorize_subscribe = authorize でフックを登録します。 authorize_ctx はフックの第一引数としてそのまま渡される値で、SDK は中身を解釈しません。 0(wired_moqt_init のデフォルト)のままなら、ハブは誰にでも開かれたままです。
  • フックには、要求された Full Track Name(名前空間と名前の組)と、提示された AUTHORIZATION TOKEN パラメータ(リクエストが何も持たなければ 0)が渡されます。 実際のトークン方式(CAT、Privacy Pass)を検証するのは、デプロイする側の仕事です。 SDK はバイト列を運び、フックを呼ぶだけです。
  • draft-ietf-moq-transport-22 の 15.3 節のとおり、すべての SUBSCRIBE は、 トラックの照合より前にこの検査を通ります。 ポリシーが拒否した名前には、その名前のトラックが 1 つも存在しない場合でも REQUEST_ERROR(9.4)UNAUTHORIZED が返ります。 このページの secret はどこにも公開されていないので、この拒否は、 トラックが存在しないことの副作用ではなく、ポリシーそのものによるものです。
  • ポリシーが許可した名前は、前のページまでと同じ経路を進みます。 ハブ自身のトラック(およびピアのトラック)と照合され、SUBSCRIBE_OK が返り、 いつもの配信が始まります。