|
@@ -60,7 +60,8 @@ struct CloseMessage {
|
|
|
DataChannel::DataChannel(unsigned int stream, string label, string protocol,
|
|
|
Reliability reliability)
|
|
|
: mStream(stream), mLabel(std::move(label)), mProtocol(std::move(protocol)),
|
|
|
- mReliability(std::make_shared<Reliability>(std::move(reliability))) {}
|
|
|
+ mReliability(std::make_shared<Reliability>(std::move(reliability))),
|
|
|
+ mRecvQueue(RECV_QUEUE_SIZE) {}
|
|
|
|
|
|
DataChannel::DataChannel(unsigned int stream, shared_ptr<SctpTransport> sctpTransport)
|
|
|
: mStream(stream), mSctpTransport(sctpTransport),
|
|
@@ -70,8 +71,7 @@ DataChannel::~DataChannel() { close(); }
|
|
|
|
|
|
void DataChannel::close() {
|
|
|
mIsOpen = false;
|
|
|
- if (!mIsClosed) {
|
|
|
- mIsClosed = true;
|
|
|
+ if (!mIsClosed.exchange(true)) {
|
|
|
if (mSctpTransport)
|
|
|
mSctpTransport->reset(mStream);
|
|
|
}
|
|
@@ -88,7 +88,8 @@ void DataChannel::send(const std::variant<binary, string> &data) {
|
|
|
auto *b = reinterpret_cast<const byte *>(d.data());
|
|
|
// Before the ACK has been received on a DataChannel, all messages must be sent ordered
|
|
|
auto reliability = mIsOpen ? mReliability : nullptr;
|
|
|
- mSctpTransport->send(make_message(b, b + d.size(), type, mStream, reliability));
|
|
|
+ auto message = make_message(b, b + d.size(), type, mStream, reliability);
|
|
|
+ mSctpTransport->send(message);
|
|
|
},
|
|
|
data);
|
|
|
}
|
|
@@ -98,7 +99,33 @@ void DataChannel::send(const byte *data, size_t size) {
|
|
|
return;
|
|
|
|
|
|
auto reliability = mIsOpen ? mReliability : nullptr;
|
|
|
- mSctpTransport->send(make_message(data, data + size, Message::Binary, mStream, reliability));
|
|
|
+ auto message = make_message(data, data + size, Message::Binary, mStream, reliability);
|
|
|
+ mSctpTransport->send(message);
|
|
|
+}
|
|
|
+
|
|
|
+std::optional<std::variant<binary, string>> DataChannel::receive() {
|
|
|
+ while (auto opt = mRecvQueue.tryPop()) {
|
|
|
+ auto message = *opt;
|
|
|
+ switch (message->type) {
|
|
|
+ case Message::Control: {
|
|
|
+ auto raw = reinterpret_cast<const uint8_t *>(message->data());
|
|
|
+ if (raw[0] == MESSAGE_CLOSE) {
|
|
|
+ if (mIsOpen) {
|
|
|
+ close();
|
|
|
+ triggerClosed();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case Message::String:
|
|
|
+ return std::make_optional(
|
|
|
+ string(reinterpret_cast<const char *>(message->data()), message->size()));
|
|
|
+ case Message::Binary:
|
|
|
+ return std::make_optional(std::move(*message));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nullopt;
|
|
|
}
|
|
|
|
|
|
unsigned int DataChannel::stream() const { return mStream; }
|
|
@@ -153,16 +180,14 @@ void DataChannel::incoming(message_ptr message) {
|
|
|
processOpenMessage(message);
|
|
|
break;
|
|
|
case MESSAGE_ACK:
|
|
|
- if (!mIsOpen) {
|
|
|
- mIsOpen = true;
|
|
|
+ if (!mIsOpen.exchange(true)) {
|
|
|
triggerOpen();
|
|
|
}
|
|
|
break;
|
|
|
case MESSAGE_CLOSE:
|
|
|
- if (mIsOpen) {
|
|
|
- close();
|
|
|
- triggerClosed();
|
|
|
- }
|
|
|
+ // The close message will be processed in-order in receive()
|
|
|
+ mRecvQueue.push(message);
|
|
|
+ triggerAvailable(mRecvQueue.size());
|
|
|
break;
|
|
|
default:
|
|
|
// Ignore
|
|
@@ -170,15 +195,15 @@ void DataChannel::incoming(message_ptr message) {
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
- case Message::String: {
|
|
|
- triggerMessage(string(reinterpret_cast<const char *>(message->data()), message->size()));
|
|
|
+ case Message::String:
|
|
|
+ case Message::Binary:
|
|
|
+ mRecvQueue.push(message);
|
|
|
+ triggerAvailable(mRecvQueue.size());
|
|
|
break;
|
|
|
- }
|
|
|
- case Message::Binary: {
|
|
|
- triggerMessage(*message);
|
|
|
+ default:
|
|
|
+ // Ignore
|
|
|
break;
|
|
|
}
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
void DataChannel::processOpenMessage(message_ptr message) {
|