|
14 | 14 | #include <openssl/ec.h>
|
15 | 15 | #include <openssl/err.h>
|
16 | 16 | #include <openssl/ssl.h>
|
| 17 | +#include <stdint.h> |
17 | 18 | #include <string.h>
|
18 | 19 |
|
19 | 20 | struct Dc {
|
@@ -674,32 +675,85 @@ int32_t Update(Dc *dc, Event *evt) {
|
674 | 675 | return 0;
|
675 | 676 | }
|
676 | 677 |
|
| 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 | + |
677 | 735 | static int32_t SendData(Dc *dc, Client *client, const uint8_t *data,
|
678 | 736 | int32_t length, DataChannelProtoIdentifier proto) {
|
679 | 737 | if (client->state < Client_DataChannelOpen) {
|
680 | 738 | return -1;
|
681 | 739 | }
|
682 | 740 |
|
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 | + } |
701 | 745 |
|
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 | + } |
703 | 757 | return 0;
|
704 | 758 | }
|
705 | 759 |
|
|
0 commit comments