トラックの公開
ハブは自分のトラック(購読の単位になる、名前付きのデータの流れ)を公開できます。
このページでは hello をトラック greeting として公開し、クライアントが SUBSCRIBE で購読して受け取ります。
コード
#define WIRED_MAIN#include "wired.h"
static wired_moqt_hub g_hub;
int wired_main(int argc, char** argv) { /* The same fixed demo identity as the HTTP/3 pages, plus QUIC DATAGRAM * support, which WebTransport clients ask for. */ static wired_srvboot_demo_keys keys; wired_srvboot_id id; wired_srvboot_demo(&id, &keys, 0x50, "guide-mp"); id.max_datagram_frame_size = 65535;
wired_moqt_io io = wired_moqraw_io(); wired_moqt_init(&g_hub, io);
/* Publish "hello" as track "greeting" (Track Alias 1). The hub frames it * once into wire and sends it to every peer that SUBSCRIBEs. */ static u8 wire[MOQDATA_BLOB_WIRE_CAP(5)]; wired_moqt_publish_blob( &g_hub, wired_span_cstr("greeting"), 1, wired_span_cstr("hello"), wired_mspan_of(wire, sizeof 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;}クライアント
package main
import ( "bufio" "context" "fmt" "io" "log" "os" "time"
"wired-guide/moqtclient")
func main() { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // The session handshake of the hub page: subprotocol "moqt-22", then // one SETUP each way on the two uni control streams. s := moqtclient.Dial(ctx, os.Args[1]+"/moqt") defer s.Conn.CloseWithError(0, "") fmt.Println("status", s.Status) fmt.Printf("recv SETUP type=%#x options=%d bytes\n", s.SetupType, len(s.SetupOptions))
// SUBSCRIBE (0x3) on a bidi request stream of its own: Request ID 0, // Track Namespace ("guide"), Track Name ("greeting"), no parameters. // The reply, SUBSCRIBE_OK, comes back on the same stream. fmt.Println("send SUBSCRIBE guide/greeting") reply, _ := s.Subscribe(ctx, 0, "greeting") if !reply.Ok { log.Fatalf("SUBSCRIBE refused, error_code=%d", reply.ErrCode) } fmt.Printf("recv SUBSCRIBE_OK track_alias=%d\n", reply.Alias)
// The object arrives on its own uni stream: a SUBGROUP_HEADER (Type, // Track Alias, Group ID), then Object ID delta, payload length, payload. uni, err := s.AcceptUniStream(ctx) moqtclient.Check(err) u := bufio.NewReader(uni) // The hub sends Type 0x70: FIRST_OBJECT (0x40) set, no Subgroup ID // field, default priority, no properties. moqtclient.Varint(u) alias, group, id := moqtclient.Varint(u), moqtclient.Varint(u), moqtclient.Varint(u) payload := make([]byte, moqtclient.Varint(u)) _, err = io.ReadFull(u, payload) moqtclient.Check(err) fmt.Printf("recv object track_alias=%d group=%d id=%d payload=%q\n", alias, group, id, payload)}実行結果
$ ./moqt-publish --port 4433conn closed by peer (CONNECTION_CLOSE)$ go run . https://127.0.0.1:4433status 200recv SETUP type=0x2f00 options=4 bytessend SUBSCRIBE guide/greetingrecv SUBSCRIBE_OK track_alias=1recv object track_alias=1 group=0 id=0 payload="hello"wired_moqt_publish_blob(&hub, name, alias, blob, wire)は、起動時に一度だけblobをフレーム化してwireに書きます。wireの大きさはMOQDATA_BLOB_WIRE_CAP(n)で決めます。wireは、ハブより長く生きている必要があります。- SUBSCRIBE は、クライアントが開く専用の双方向リクエストストリーム(draft-ietf-moq-transport-22 の 6.4.2)に載って届き、その上で応答されます。
このトラックを指定した SUBSCRIBE には、その Track Alias(トラックを指す数値の別名)を載せた SUBSCRIBE_OK(9.7)が返ります。
続いて、フレーム化したバイト列が io 表の
send_uniを通じ、新しい単方向ストリームでそのピアに送られます。 - ストリームの中身は、SUBGROUP_HEADER(Track Alias、Group 0)と、それに続く Object(ID 0、ペイロード
hello)です。 ハブが照合するのは Track Name だけで、名前空間は照合しません。 - それ以外は MoQT ハブのページと同じです。