Networking
The Playbit networking APIs allow for communication between apps via Playbit's own data protocols and infrastructure. These APIs are currently available as a technical preview, and are not yet well suited for sensitive information as encryption is not yet implemented.
PBNet
typedef struct PBNet {
PBSysHandle handle;
} PBNet;
PBNet is a general network capability
PBNetSession
typedef struct PBNetSession {
PBSysHandle handle;
} PBNetSession;
PBNetSession is a Playbit network session
PBNetChannelOpenFlags
typedef u64 PBNetChannelOpenFlags;
PBNetChannelOpenFlags are flags for PBNetChannelOpenEx
PBNetChannelOpenFlag
enum PBNetChannelOpenFlag PB_ENUM_TYPE(u64){
/*
PBNetChannelOpenFlag_SUBSCRIBE causes the PBNetChannel to automatically send SUBSCRIBE messages whenever the underlying access point connection is established, or re-established. If this flag is not set, nothing will be delivered to the opened PBNetChannel, until you send a SUBSCRIBE message yourself. Not setting this flag can be useful if you are only writing to a channel.
*/
PBNetChannelOpenFlag_SUBSCRIBE = 1u << 0,
/*
PBNetChannelOpenFlag_TRACK_SUBSCRIBERS enables reception of SUBSCRIBE and UNSUBSCRIBE messages as other peers join and leave the channel. It can be used for participation discovery. PBNetChannelOpenFlag_SUBSCRIBE must be set if PBNetChannelOpenFlag_TRACK_SUBSCRIBERS is set.
Corresponds to setting PBApFrameFlag_TRACK in the AP protocol on outgoing SUBSCRIBE message.
*/
PBNetChannelOpenFlag_TRACK_SUBSCRIBERS = 1u << 1,
};
PBNetChannelPublishFlags
typedef u64 PBNetChannelPublishFlags;
PBNetChannelPublishFlags are flags for PBNetChannelPublishCommit et al
PBNetChannelPublishFlag
enum PBNetChannelPublishFlag PB_ENUM_TYPE(u64){
/*
PBNetChannelPublishFlag_ECHO makes the message delivered back to the sender, in addition to being sent to everyone else in a channel. It corresponds to PBApFrameFlag_ECHO in the AP protocol.
*/
PBNetChannelPublishFlag_ECHO = 1u << 0,
/*
PBNetChannelPublishFlag_DEFER disables sending of the message on publish. Useful if you are sending many small messages in rapid succession: set PBNetChannelPublishFlag_DEFER for the first N-1 publish calls and don't set this flag for the last.
Note that a call to PBNetChannelProcessIO will cause queued messages to be sent regardless of this flag, granted the underlying stream is writable.
*/
PBNetChannelPublishFlag_DEFER = 1u << 1,
};
PBNetChannelFrameType
typedef enum PBNetChannelFrameType PB_ENUM_TYPE(u8){
PBNetChannelFrameType_DIRECT = PBApFrameType_DIRECT,
PBNetChannelFrameType_PUBLISH = PBApFrameType_PUBLISH,
PBNetChannelFrameType_SUBSCRIBE = PBApFrameType_SUBSCRIBE,
PBNetChannelFrameType_UNSUBSCRIBE = PBApFrameType_UNSUBSCRIBE,
PBNetChannelFrameType_ERROR = PBApFrameType_ERROR,
PBNetChannelFrameType_ERROR_CHAN = PBApFrameType_ERROR_CHAN,
PBNetChannelFrameType_ERROR_SUB = PBApFrameType_ERROR_SUB,
PBNetChannelFrameType_ERROR_PEER = PBApFrameType_ERROR_PEER,
PBNetChannelFrameType_ERROR_DIRECT = PBApFrameType_ERROR_DIRECT,
} PBNetChannelFrameType;
PBNetChannelFrameType identifies frames delivered on a NetSession channel stream.
PBNetChannelFrame
typedef struct PBNetChannelFrame {
u32 bodyLen; // Size of body in bytes.
PBNetChannelFrameType type; // Frame type.
u8 flags; // Type-specific AP frame flags.
u8 senderIdLen; // Number of bytes at senderId.
u8 _reserved;
const u8* body; // Pointer to the frame body. Always 16-byte aligned.
u8 senderId[]; // Sender peer ID bytes. May be empty.
} PBNetChannelFrame;
PBNetChannelFrame is a frame of information received via a PBNetChannel
PBNetDefault
PBNet PBNetDefault();
PBNetDefault returns the default/initial network capability provided to the current thread when it was started.
Note: You can check .handle == PBSysHandle_INVALID on the return value to check if the current thread has a default network capability, or use PBExpectValidHandle to get a panic if not. All functions that take a PBNet as an argument will check its validity and panic if invalid, so for programs what want to simply crash if no networking is available, it's easier to just do no checking at all.
PBNetSessionOpen
PBSysErr PBNetSessionOpen(PBNet net,
PBNetSession* netSession,
PBStrSlice sessionId,
const PBSysNetSessionConfig* config);
PBNetSessionOpen opens a logical Playbit network session.
A Playbit network session allows communication between multiple playbit programs participating in the same session. A session houses "channels" (see PBNetChannelOpen and PBNetChannel).
net: Networking capabilitynetSession: Session to initializesessionId: Session identifier, unique within app-id namespaceconfig: Optional configuration. Pass NULL for defaults.
PBNetSessionClose
PBSysErr PBNetSessionClose(PBNetSession* netSession);
PBNetSessionClose closes a network session
PBNetChannelOpen
PBSysErr PBNetChannelOpen(PBNetChannel* netChannelOut,
const PBNetSession* netSession,
PBStrSlice channelId,
PBMem ma);
PBNetChannelOpen opens a stream to channel identified by channelId, and queues a SUBSCRIBE message.
PBNetChannelOpen is equivalent to calling PBNetChannelOpenEx with PBNetChannelOpenFlag_SUBSCRIBE.
netChannelOut: Points to an open PBNetChannel on successnetSession: The network session to open a channel inchannelId: The identifier of the channel, unique within the sessionma: Memory allocator to use for PBNetChannel and its resources. Must remain valid untilPBNetChannelClosehas been called.
PBNetChannelOpenEx
PBSysErr PBNetChannelOpenEx(PBNetChannel* netChannelOut,
const PBNetSession* netSession,
PBStrSlice channelId,
PBMem ma,
PBNetChannelOpenFlags flags);
PBNetChannelOpen opens a stream to channel identified by channelId.
netChannelOut: Points to an open PBNetChannel on successnetSession: The network session to open a channel inchannelId: The identifier of the channel, unique within the sessionma: Memory allocator to use for PBNetChannel and its resources. Must remain valid untilPBNetChannelClosehas been called.flags: Customizes behavior. SeePBNetChannelOpenFlags
PBNetChannelClose
void PBNetChannelClose(PBNetChannel* netChannel);
PBNetChannelClose closes the underlying stream, frees buffers owned by netChannel, and frees the channel object itself. The caller should discard any saved pointer after calling.
PBNetChannelHandle
PBSysHandle PBNetChannelHandle(const PBNetChannel* netChannel);
PBNetChannelHandle returns the underlying stream handle for a channel
PBNetChannelPublish
PBSysErr PBNetChannelPublish(PBNetChannel* netChannel,
const u8* body,
u32 bodyLen);
PBNetChannelPublish queues one complete PUBLISH frame by copying body into an internal buffer.
Equivalent to calling PBNetChannelPublishBegin with 0 flags, copying body and then calling PBNetChannelPublishCommit with 0 flags.
- Returns:
PBSysErr_TOO_LARGEifbodyLenis too large, as limited byPBNetChannelSetSendLimit
PBNetChannelPublishEx
PBSysErr PBNetChannelPublishEx(PBNetChannel* netChannel,
const u8* body,
u32 bodyLen,
PBNetChannelPublishFlags flags);
PBNetChannelPublishEx queues one complete PUBLISH frame with explicit AP frame flags.
Equivalent to calling PBNetChannelPublishBegin with flags, copying body and then calling PBNetChannelPublishCommit with flags.
- Returns:
PBSysErr_TOO_LARGEifbodyLenis too large, as limited byPBNetChannelSetSendLimit
PBNetChannelPublishBegin
PBSysErr PBNetChannelPublishBegin(PBNetChannel* netChannel,
u32 bodyLen,
u8* bodyOut,
PBNetChannelPublishFlags flags);
PBNetChannelPublishBegin allocates one outgoing PUBLISH frame.
On success, reserves space in the send buffer, stores the body pointer in bodyOut, and expects a matching call to PBNetChannelPublishCommit.
bodyOut: On success,*bodyOutis set to a pointer into an internal buffer of at leastbodyLensize, with at least 16 byte address alignment. The pointer remains valid untilPBNetChannelPublishCommitis called.- Returns:
PBSysErr_TOO_LARGEifbodyLenis too large, as limited byPBNetChannelSetSendLimit
PBNetChannelPublishCommit
PBSysErr PBNetChannelPublishCommit(PBNetChannel* netChannel,
u8* body,
PBNetChannelPublishFlags flags);
PBNetChannelPublishCommit commits a draft PUBLISH frame previously started with PBNetChannelPublishBegin.
body: Must be the exact pointer returned from the begin call
PBNetChannelProcessIO
PBSysErr PBNetChannelProcessIO(PBNetChannel* netChannel,
PBSysSignals signals,
PBNetChannelFrame* frameOut);
PBNetChannelProcessIO processes stream IO for a channel.
signals: Current streamsignalsfrom aPBEventType_SIGNALevent, but 0 is also valid and still allows flushing of buffered outgoing data.- Returns: On success, *frameOut is set to NULL if no complete frame is ready yet, or to a frame pointer owned by
netChannelif one frame was decoded. The returned frame remains valid untilPBNetChannelReleaseFrameis called.
PBNetChannelReleaseFrame
void PBNetChannelReleaseFrame(PBNetChannel* netChannel,
PBNetChannelFrame* frame);
PBNetChannelReleaseFrame releases a frame previously returned by PBNetChannelProcessIO. Frames must be released in the order they were received.
PBNetChannelRecvDiscardCount
u32 PBNetChannelRecvDiscardCount(const PBNetChannel* netChannel);
PBNetChannelRecvDiscardCount returns the number of received messages which were discarded because they exceeded size limit set by PBNetChannelSetRecvLimit
PBNetChannelSetRecvLimit
u32 PBNetChannelSetRecvLimit(PBNetChannel* netChannel,
u32 nbytes);
PBNetChannelSetRecvLimit limits the size of received messages (body, not including protocol header.)
nbytes: Max number of bytes to allow receiving.- Returns: Previous limit
PBNetChannelSetSendLimit
u32 PBNetChannelSetSendLimit(PBNetChannel* netChannel,
u32 nbytes);
PBNetChannelSetSendLimit limits the size of published messages (body, not including protocol header.)
nbytes: Max number of bytes per published message
Playbit Access Point protocol
PBApFrameType
typedef enum PBApFrameType PB_ENUM_TYPE(u8){
PBApFrameType_HELLO = 0, // 'src' is peer ID on recv, body=auth_tok
PBApFrameType_REGISTER = 1, // 'flags' holds APRegisterResStatus
PBApFrameType_DIRECT = 2, // 'dst' is peer ID, 'flags' is unused
PBApFrameType_PUBLISH = 3, // 'dst' is channel ID, 'flags' may have ECHO
PBApFrameType_SUBSCRIBE = 4, // 'dst' is channel ID, 'flags' may have TRACK
PBApFrameType_UNSUBSCRIBE = 5, // 'dst' is channel ID, 'flags' is unused
PBApFrameType_ERROR = 200, // generic error (text description in data)
PBApFrameType_ERROR_CHAN = 201, // operation on non-existing channel
PBApFrameType_ERROR_SUB = 202, // already subscribed or not subscribed
PBApFrameType_ERROR_PEER = 203, // no route to peer
PBApFrameType_ERROR_DIRECT = 204, // failed to deliver direct message
} PBApFrameType;
PBApFrameFlags
typedef u8 PBApFrameFlags;
PBApFrameFlag
enum PBApFrameFlag PB_ENUM_TYPE(u8){
PBApFrameFlag_ECHO = 1u << 0,
PBApFrameFlag_TRACK = 1u << 0,
};
PBApFrameHeaderSize
const int PBApFrameHeaderSize = 8;
PBApFrameBodyAlign
const int PBApFrameBodyAlign = 16;