Skip to content

Commit 5a02de3

Browse files
committed
feat: support ordered sctp data packet fragment.
Signed-off-by: ayamir <[email protected]>
1 parent 709bbbc commit 5a02de3

File tree

1 file changed

+73
-19
lines changed

1 file changed

+73
-19
lines changed

src/Dc.cc

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <openssl/ec.h>
1515
#include <openssl/err.h>
1616
#include <openssl/ssl.h>
17+
#include <stdint.h>
1718
#include <string.h>
1819

1920
struct Dc {
@@ -674,32 +675,85 @@ int32_t Update(Dc *dc, Event *evt) {
674675
return 0;
675676
}
676677

678+
struct SctpAssembleContext {
679+
Dc *dc;
680+
Client *client;
681+
const uint8_t *data;
682+
int32_t length;
683+
DataChannelProtoIdentifier proto;
684+
bool isBegin;
685+
bool isEnd;
686+
SctpHeader *packet;
687+
SctpChunk *rc;
688+
SctpAssembleContext(Dc *dc, Client *client, const uint8_t *data,
689+
int32_t length, DataChannelProtoIdentifier proto,
690+
bool isBegin, bool isEnd, SctpHeader *packet,
691+
SctpChunk *rc)
692+
: dc(dc), client(client), data(data), length(length), proto(proto),
693+
isBegin(isBegin), isEnd(isEnd), packet(packet), rc(rc) {}
694+
SctpAssembleContext(const SctpAssembleContext &other) = delete;
695+
};
696+
697+
static void AssembleSctpPacket(SctpAssembleContext *assembleCtx) {
698+
assembleCtx->packet->sourcePort = assembleCtx->dc->port;
699+
assembleCtx->packet->destinationPort = assembleCtx->client->remoteSctpPort;
700+
assembleCtx->packet->verificationTag =
701+
assembleCtx->client->sctpVerificationTag;
702+
703+
auto fragmentFlagsGenerator = [&](bool isBegin, bool isEnd) -> uint8_t {
704+
auto beginFlag = SctpFlagBeginFragment & isBegin;
705+
auto endFlag = SctpFlagEndFragment & isEnd;
706+
return beginFlag | endFlag;
707+
};
708+
assembleCtx->rc->flags =
709+
fragmentFlagsGenerator(assembleCtx->isBegin, assembleCtx->isEnd);
710+
assembleCtx->rc->type = Sctp_Data;
711+
assembleCtx->rc->length = SctpDataChunkLength(assembleCtx->length);
712+
713+
auto *chunkData = &assembleCtx->rc->as.data;
714+
chunkData->tsn = assembleCtx->client->tsn++;
715+
// TODO: expose stream identifier to support multi-stream multiplexing
716+
chunkData->streamId = 0;
717+
chunkData->streamSeq = 0;
718+
chunkData->protoId = assembleCtx->proto;
719+
chunkData->userData = assembleCtx->data;
720+
chunkData->userDataLength = assembleCtx->length;
721+
}
722+
723+
static void SendSctpDataPacket(Dc *dc, Client *client, const uint8_t *data,
724+
int32_t length, DataChannelProtoIdentifier proto,
725+
bool isBegin, bool isEnd) {
726+
SctpHeader packet;
727+
SctpChunk rc;
728+
SctpAssembleContext assembleCtx{
729+
dc, client, data, length, proto, isBegin, isEnd, &packet, &rc,
730+
};
731+
AssembleSctpPacket(&assembleCtx);
732+
SendSctp(dc, client, &packet, &rc, 1);
733+
}
734+
677735
static int32_t SendData(Dc *dc, Client *client, const uint8_t *data,
678736
int32_t length, DataChannelProtoIdentifier proto) {
679737
if (client->state < Client_DataChannelOpen) {
680738
return -1;
681739
}
682740

683-
SctpHeader packet;
684-
packet.sourcePort = dc->port;
685-
packet.destionationPort = client->remoteSctpPort;
686-
packet.verificationTag = client->sctpVerificationTag;
687-
688-
SctpChunk rc;
689-
rc.type = Sctp_Data;
690-
rc.flags = kSctpFlagCompleteUnreliable;
691-
rc.length = SctpDataChunkLength(length);
692-
693-
auto *chunkData = &rc.as.data;
694-
chunkData->tsn = client->tsn++;
695-
// TODO: expose stream identifier to support multi-stream multiplexing
696-
chunkData->streamId = 0;
697-
chunkData->streamSeq = 0;
698-
chunkData->protoId = proto;
699-
chunkData->userData = data;
700-
chunkData->userDataLength = length;
741+
int32_t packetNum = 1;
742+
if (length > kDefaultMTU) {
743+
packetNum += length / kDefaultMTU;
744+
}
701745

702-
SendSctp(dc, client, &packet, &rc, 1);
746+
if (packetNum == 1) {
747+
SendSctpDataPacket(dc, client, data, length, proto, true, true);
748+
} else {
749+
// begin packet
750+
SendSctpDataPacket(dc, client, data, length, proto, true, false);
751+
for (int i = 1; i < packetNum - 1; i++) {
752+
SendSctpDataPacket(dc, client, data, length, proto, false, false);
753+
}
754+
// end packet
755+
SendSctpDataPacket(dc, client, data, length, proto, false, false);
756+
}
703757
return 0;
704758
}
705759

0 commit comments

Comments
 (0)