1 /* 2 * libjingle 3 * Copyright 2013 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/app/webrtc/sctputils.h" 29 30 #include "webrtc/base/buffer.h" 31 #include "webrtc/base/bytebuffer.h" 32 #include "webrtc/base/logging.h" 33 34 namespace webrtc { 35 36 // Format defined at 37 // http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-01#section 38 39 static const uint8_t DATA_CHANNEL_OPEN_MESSAGE_TYPE = 0x03; 40 static const uint8_t DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE = 0x02; 41 42 enum DataChannelOpenMessageChannelType { 43 DCOMCT_ORDERED_RELIABLE = 0x00, 44 DCOMCT_ORDERED_PARTIAL_RTXS = 0x01, 45 DCOMCT_ORDERED_PARTIAL_TIME = 0x02, 46 DCOMCT_UNORDERED_RELIABLE = 0x80, 47 DCOMCT_UNORDERED_PARTIAL_RTXS = 0x81, 48 DCOMCT_UNORDERED_PARTIAL_TIME = 0x82, 49 }; 50 51 bool IsOpenMessage(const rtc::Buffer& payload) { 52 // Format defined at 53 // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04 54 55 rtc::ByteBuffer buffer(payload); 56 uint8_t message_type; 57 if (!buffer.ReadUInt8(&message_type)) { 58 LOG(LS_WARNING) << "Could not read OPEN message type."; 59 return false; 60 } 61 return message_type == DATA_CHANNEL_OPEN_MESSAGE_TYPE; 62 } 63 64 bool ParseDataChannelOpenMessage(const rtc::Buffer& payload, 65 std::string* label, 66 DataChannelInit* config) { 67 // Format defined at 68 // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04 69 70 rtc::ByteBuffer buffer(payload); 71 uint8_t message_type; 72 if (!buffer.ReadUInt8(&message_type)) { 73 LOG(LS_WARNING) << "Could not read OPEN message type."; 74 return false; 75 } 76 if (message_type != DATA_CHANNEL_OPEN_MESSAGE_TYPE) { 77 LOG(LS_WARNING) << "Data Channel OPEN message of unexpected type: " 78 << message_type; 79 return false; 80 } 81 82 uint8_t channel_type; 83 if (!buffer.ReadUInt8(&channel_type)) { 84 LOG(LS_WARNING) << "Could not read OPEN message channel type."; 85 return false; 86 } 87 88 uint16_t priority; 89 if (!buffer.ReadUInt16(&priority)) { 90 LOG(LS_WARNING) << "Could not read OPEN message reliabilility prioirty."; 91 return false; 92 } 93 uint32_t reliability_param; 94 if (!buffer.ReadUInt32(&reliability_param)) { 95 LOG(LS_WARNING) << "Could not read OPEN message reliabilility param."; 96 return false; 97 } 98 uint16_t label_length; 99 if (!buffer.ReadUInt16(&label_length)) { 100 LOG(LS_WARNING) << "Could not read OPEN message label length."; 101 return false; 102 } 103 uint16_t protocol_length; 104 if (!buffer.ReadUInt16(&protocol_length)) { 105 LOG(LS_WARNING) << "Could not read OPEN message protocol length."; 106 return false; 107 } 108 if (!buffer.ReadString(label, (size_t) label_length)) { 109 LOG(LS_WARNING) << "Could not read OPEN message label"; 110 return false; 111 } 112 if (!buffer.ReadString(&config->protocol, protocol_length)) { 113 LOG(LS_WARNING) << "Could not read OPEN message protocol."; 114 return false; 115 } 116 117 config->ordered = true; 118 switch (channel_type) { 119 case DCOMCT_UNORDERED_RELIABLE: 120 case DCOMCT_UNORDERED_PARTIAL_RTXS: 121 case DCOMCT_UNORDERED_PARTIAL_TIME: 122 config->ordered = false; 123 } 124 125 config->maxRetransmits = -1; 126 config->maxRetransmitTime = -1; 127 switch (channel_type) { 128 case DCOMCT_ORDERED_PARTIAL_RTXS: 129 case DCOMCT_UNORDERED_PARTIAL_RTXS: 130 config->maxRetransmits = reliability_param; 131 break; 132 case DCOMCT_ORDERED_PARTIAL_TIME: 133 case DCOMCT_UNORDERED_PARTIAL_TIME: 134 config->maxRetransmitTime = reliability_param; 135 break; 136 } 137 return true; 138 } 139 140 bool ParseDataChannelOpenAckMessage(const rtc::Buffer& payload) { 141 rtc::ByteBuffer buffer(payload); 142 uint8_t message_type; 143 if (!buffer.ReadUInt8(&message_type)) { 144 LOG(LS_WARNING) << "Could not read OPEN_ACK message type."; 145 return false; 146 } 147 if (message_type != DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE) { 148 LOG(LS_WARNING) << "Data Channel OPEN_ACK message of unexpected type: " 149 << message_type; 150 return false; 151 } 152 return true; 153 } 154 155 bool WriteDataChannelOpenMessage(const std::string& label, 156 const DataChannelInit& config, 157 rtc::Buffer* payload) { 158 // Format defined at 159 // http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-00#section-6.1 160 uint8_t channel_type = 0; 161 uint32_t reliability_param = 0; 162 uint16_t priority = 0; 163 if (config.ordered) { 164 if (config.maxRetransmits > -1) { 165 channel_type = DCOMCT_ORDERED_PARTIAL_RTXS; 166 reliability_param = config.maxRetransmits; 167 } else if (config.maxRetransmitTime > -1) { 168 channel_type = DCOMCT_ORDERED_PARTIAL_TIME; 169 reliability_param = config.maxRetransmitTime; 170 } else { 171 channel_type = DCOMCT_ORDERED_RELIABLE; 172 } 173 } else { 174 if (config.maxRetransmits > -1) { 175 channel_type = DCOMCT_UNORDERED_PARTIAL_RTXS; 176 reliability_param = config.maxRetransmits; 177 } else if (config.maxRetransmitTime > -1) { 178 channel_type = DCOMCT_UNORDERED_PARTIAL_TIME; 179 reliability_param = config.maxRetransmitTime; 180 } else { 181 channel_type = DCOMCT_UNORDERED_RELIABLE; 182 } 183 } 184 185 rtc::ByteBuffer buffer( 186 NULL, 20 + label.length() + config.protocol.length(), 187 rtc::ByteBuffer::ORDER_NETWORK); 188 buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE); 189 buffer.WriteUInt8(channel_type); 190 buffer.WriteUInt16(priority); 191 buffer.WriteUInt32(reliability_param); 192 buffer.WriteUInt16(static_cast<uint16_t>(label.length())); 193 buffer.WriteUInt16(static_cast<uint16_t>(config.protocol.length())); 194 buffer.WriteString(label); 195 buffer.WriteString(config.protocol); 196 payload->SetData(buffer.Data(), buffer.Length()); 197 return true; 198 } 199 200 void WriteDataChannelOpenAckMessage(rtc::Buffer* payload) { 201 rtc::ByteBuffer buffer(rtc::ByteBuffer::ORDER_NETWORK); 202 buffer.WriteUInt8(DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE); 203 payload->SetData(buffer.Data(), buffer.Length()); 204 } 205 } // namespace webrtc 206