Skip to content

Commit b21fed2

Browse files
afrindfacebook-github-bot
authored andcommitted
Use Consumer interface for MoQSession publishing (facebookexperimental#12)
Summary: This is a major rewrite of MoQSession using the new Consumers interfaces. It's separated into the writes (this diff) and reads (next diff). Note the relay -- which does writes and reads -- is slightly broken in this diff but fixed in the next, so don't read too much into it. The previous "publish" API required the session to maintain a huge map of every currently open stream across the session and perform lookups into this map in order to do the writes. It also had a number API error cases that could be eliminated by constraining the interface. Now subscribeOK and fetchOK return a Consumer object which the publisher will use to pass track data according to those APIs. No maps are required -- the publisher hangs onto the handle(s) it needs to publish. MoQForwarder also had a major rewrite. It conveniently now implements the TrackConsumer interface as well, so a publisher can trivially publish to one or N subscribers. Differential Revision: D66881597
1 parent 93fe21d commit b21fed2

File tree

10 files changed

+1628
-884
lines changed

10 files changed

+1628
-884
lines changed

moxygen/MoQSession.cpp

Lines changed: 827 additions & 341 deletions
Large diffs are not rendered by default.

moxygen/MoQSession.h

Lines changed: 73 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <folly/coro/Task.h>
1717
#include <folly/coro/UnboundedQueue.h>
1818
#include <folly/logging/xlog.h>
19+
#include <moxygen/MoQConsumers.h>
1920
#include "moxygen/util/TimedBaton.h"
2021

2122
#include <boost/variant.hpp>
@@ -71,7 +72,7 @@ class MoQSession : public MoQControlCodec::ControlCallback,
7172
if (maxConcurrent > maxConcurrentSubscribes_) {
7273
auto delta = maxConcurrent - maxConcurrentSubscribes_;
7374
maxSubscribeID_ += delta;
74-
sendMaxSubscribeID(/*signal=*/true);
75+
sendMaxSubscribeID(/*signalWriteLoop=*/true);
7576
}
7677
}
7778

@@ -191,9 +192,11 @@ class MoQSession : public MoQControlCodec::ControlCallback,
191192
TrackHandle(
192193
FullTrackName fullTrackName,
193194
SubscribeID subscribeID,
195+
folly::EventBase* evb,
194196
folly::CancellationToken token)
195197
: fullTrackName_(std::move(fullTrackName)),
196198
subscribeID_(subscribeID),
199+
evb_(evb),
197200
cancelToken_(std::move(token)) {
198201
auto contract = folly::coro::makePromiseContract<
199202
folly::Expected<std::shared_ptr<TrackHandle>, SubscribeError>>();
@@ -217,10 +220,18 @@ class MoQSession : public MoQControlCodec::ControlCallback,
217220
return subscribeID_;
218221
}
219222

223+
void setNewObjectTimeout(std::chrono::milliseconds objectTimeout) {
224+
objectTimeout_ = objectTimeout;
225+
}
226+
220227
[[nodiscard]] folly::CancellationToken getCancelToken() const {
221228
return cancelToken_;
222229
}
223230

231+
void mergeReadCancelToken(folly::CancellationToken readToken) {
232+
cancelToken_ = folly::CancellationToken::merge(cancelToken_, readToken);
233+
}
234+
224235
void fin();
225236

226237
folly::coro::Task<
@@ -327,6 +338,7 @@ class MoQSession : public MoQControlCodec::ControlCallback,
327338
private:
328339
FullTrackName fullTrackName_;
329340
SubscribeID subscribeID_;
341+
folly::EventBase* evb_;
330342
using SubscribeResult =
331343
folly::Expected<std::shared_ptr<TrackHandle>, SubscribeError>;
332344
folly::coro::Promise<SubscribeResult> promise_;
@@ -343,21 +355,21 @@ class MoQSession : public MoQControlCodec::ControlCallback,
343355
GroupOrder groupOrder_;
344356
folly::Optional<AbsoluteLocation> latest_;
345357
folly::CancellationToken cancelToken_;
358+
std::chrono::milliseconds objectTimeout_{std::chrono::hours(24)};
346359
bool allDataReceived_{false};
347360
};
348361

349362
folly::coro::Task<
350363
folly::Expected<std::shared_ptr<TrackHandle>, SubscribeError>>
351364
subscribe(SubscribeRequest sub);
352-
void subscribeOk(SubscribeOk subOk);
365+
std::shared_ptr<TrackConsumer> subscribeOk(SubscribeOk subOk);
353366
void subscribeError(SubscribeError subErr);
354367
void unsubscribe(Unsubscribe unsubscribe);
355-
void subscribeDone(SubscribeDone subDone);
356368
void subscribeUpdate(SubscribeUpdate subUpdate);
357369

358370
folly::coro::Task<folly::Expected<std::shared_ptr<TrackHandle>, FetchError>>
359371
fetch(Fetch fetch);
360-
void fetchOk(FetchOk fetchOk);
372+
std::shared_ptr<FetchConsumer> fetchOk(FetchOk fetchOk);
361373
void fetchError(FetchError fetchError);
362374
void fetchCancel(FetchCancel fetchCancel);
363375

@@ -371,23 +383,54 @@ class MoQSession : public MoQControlCodec::ControlCallback,
371383
proxygen::WebTransport::ErrorCode errorCode;
372384
};
373385

374-
// Publish this object.
375-
folly::SemiFuture<folly::Unit> publish(
376-
const ObjectHeader& objHeader,
377-
SubscribeID subscribeID,
378-
uint64_t payloadOffset,
379-
std::unique_ptr<folly::IOBuf> payload,
380-
bool eom);
381-
folly::SemiFuture<folly::Unit> publishStreamPerObject(
382-
const ObjectHeader& objHeader,
383-
SubscribeID subscribeID,
384-
uint64_t payloadOffset,
385-
std::unique_ptr<folly::IOBuf> payload,
386-
bool eom);
387-
folly::SemiFuture<folly::Unit> publishStatus(
388-
const ObjectHeader& objHeader,
389-
SubscribeID subscribeID);
390-
folly::Try<folly::Unit> closeFetchStream(SubscribeID subID);
386+
class PublisherImpl {
387+
public:
388+
PublisherImpl(
389+
MoQSession* session,
390+
SubscribeID subscribeID,
391+
Priority priority,
392+
GroupOrder groupOrder)
393+
: session_(session),
394+
subscribeID_(subscribeID),
395+
priority_(priority),
396+
groupOrder_(groupOrder) {}
397+
virtual ~PublisherImpl() = default;
398+
399+
SubscribeID subscribeID() const {
400+
return subscribeID_;
401+
}
402+
uint8_t priority() const {
403+
return priority_;
404+
}
405+
void setPriority(uint8_t priority) {
406+
priority_ = priority;
407+
}
408+
void setGroupOrder(GroupOrder groupOrder) {
409+
groupOrder_ = groupOrder;
410+
}
411+
412+
virtual void reset(ResetStreamErrorCode error) = 0;
413+
414+
virtual void onStreamComplete(const ObjectHeader& finalHeader) = 0;
415+
416+
folly::Expected<folly::Unit, MoQPublishError> subscribeDone(
417+
SubscribeDone subDone);
418+
419+
void fetchComplete();
420+
421+
protected:
422+
proxygen::WebTransport* getWebTransport() const {
423+
if (session_) {
424+
return session_->wt_;
425+
}
426+
return nullptr;
427+
}
428+
429+
MoQSession* session_{nullptr};
430+
SubscribeID subscribeID_;
431+
uint8_t priority_;
432+
GroupOrder groupOrder_;
433+
};
391434

392435
void onNewUniStream(proxygen::WebTransport::StreamReadHandle* rh) override;
393436
void onNewBidiStream(proxygen::WebTransport::BidiStreamHandle bh) override;
@@ -398,13 +441,16 @@ class MoQSession : public MoQControlCodec::ControlCallback,
398441
}
399442

400443
private:
444+
void cleanup();
445+
401446
folly::coro::Task<void> controlWriteLoop(
402447
proxygen::WebTransport::StreamWriteHandle* writeHandle);
403448
folly::coro::Task<void> readLoop(
404449
StreamType streamType,
405450
proxygen::WebTransport::StreamReadHandle* readHandle);
406451

407452
std::shared_ptr<TrackHandle> getTrack(TrackIdentifier trackidentifier);
453+
void subscribeDone(SubscribeDone subDone);
408454

409455
void onClientSetup(ClientSetup clientSetup) override;
410456
void onServerSetup(ServerSetup setup) override;
@@ -445,72 +491,9 @@ class MoQSession : public MoQControlCodec::ControlCallback,
445491
void onConnectionError(ErrorCode error) override;
446492
void checkForCloseOnDrain();
447493

448-
folly::SemiFuture<folly::Unit> publishImpl(
449-
const ObjectHeader& objHeader,
450-
SubscribeID subscribeID,
451-
uint64_t payloadOffset,
452-
std::unique_ptr<folly::IOBuf> payload,
453-
bool eom,
454-
bool streamPerObject);
455-
456-
uint64_t order(const ObjectHeader& objHeader, const SubscribeID subscribeID);
457-
458-
void retireSubscribeId(bool signal);
459-
void sendMaxSubscribeID(bool signal);
460-
461-
struct PublishKey {
462-
TrackIdentifier trackIdentifier;
463-
uint64_t group;
464-
uint64_t subgroup;
465-
ForwardPreference pref;
466-
uint64_t object;
467-
468-
bool operator==(const PublishKey& other) const {
469-
if (trackIdentifier != other.trackIdentifier || pref != other.pref) {
470-
return false;
471-
}
472-
if (pref == ForwardPreference::Datagram) {
473-
return object == other.object;
474-
} else if (pref == ForwardPreference::Subgroup) {
475-
return group == other.group && subgroup == other.subgroup;
476-
} else if (pref == ForwardPreference::Track) {
477-
return true;
478-
} else if (pref == ForwardPreference::Fetch) {
479-
return true;
480-
}
481-
return false;
482-
}
483-
484-
struct hash {
485-
size_t operator()(const PublishKey& ook) const {
486-
if (ook.pref == ForwardPreference::Datagram) {
487-
return folly::hash::hash_combine(
488-
TrackIdentifierHash{}(ook.trackIdentifier),
489-
ook.group,
490-
ook.object);
491-
} else if (ook.pref == ForwardPreference::Subgroup) {
492-
return folly::hash::hash_combine(
493-
TrackIdentifierHash{}(ook.trackIdentifier),
494-
ook.group,
495-
ook.subgroup);
496-
}
497-
// Track or Fetch
498-
return folly::hash::hash_combine(
499-
TrackIdentifierHash{}(ook.trackIdentifier));
500-
}
501-
};
502-
};
503-
504-
struct PublishData {
505-
uint64_t streamID;
506-
uint64_t group;
507-
uint64_t subgroup;
508-
uint64_t objectID;
509-
folly::Optional<uint64_t> objectLength;
510-
uint64_t offset;
511-
bool streamPerObject;
512-
bool cancelled{false};
513-
};
494+
void retireSubscribeId(bool signalWriteLoop);
495+
void sendMaxSubscribeID(bool signalWriteLoop);
496+
void fetchComplete(SubscribeID subscribeID);
514497

515498
// Get the max subscribe id from the setup params. If MAX_SUBSCRIBE_ID key is
516499
// not present, we default to 0 as specified. 0 means that the peer MUST NOT
@@ -555,13 +538,10 @@ class MoQSession : public MoQControlCodec::ControlCallback,
555538
TrackNamespace::hash>
556539
pendingSubscribeAnnounces_;
557540

558-
struct PubTrack {
559-
uint8_t priority;
560-
GroupOrder groupOrder;
561-
};
562541
// Subscriber ID -> metadata about a publish track
563-
folly::F14FastMap<SubscribeID, PubTrack, SubscribeID::hash> pubTracks_;
564-
folly::F14FastMap<PublishKey, PublishData, PublishKey::hash> publishDataMap_;
542+
folly::
543+
F14FastMap<SubscribeID, std::shared_ptr<PublisherImpl>, SubscribeID::hash>
544+
pubTracks_;
565545
uint64_t nextTrackId_{0};
566546
uint64_t closedSubscribes_{0};
567547
// TODO: Make this value configurable. maxConcurrentSubscribes_ represents

0 commit comments

Comments
 (0)