1 /* 2 * Copyright 2013 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/p2p/base/asyncstuntcpsocket.h" 12 13 #include <string.h> 14 15 #include "webrtc/p2p/base/stun.h" 16 #include "webrtc/base/common.h" 17 #include "webrtc/base/logging.h" 18 19 namespace cricket { 20 21 static const size_t kMaxPacketSize = 64 * 1024; 22 23 typedef uint16_t PacketLength; 24 static const size_t kPacketLenSize = sizeof(PacketLength); 25 static const size_t kPacketLenOffset = 2; 26 static const size_t kBufSize = kMaxPacketSize + kStunHeaderSize; 27 static const size_t kTurnChannelDataHdrSize = 4; 28 29 inline bool IsStunMessage(uint16_t msg_type) { 30 // The first two bits of a channel data message are 0b01. 31 return (msg_type & 0xC000) ? false : true; 32 } 33 34 // AsyncStunTCPSocket 35 // Binds and connects |socket| and creates AsyncTCPSocket for 36 // it. Takes ownership of |socket|. Returns NULL if bind() or 37 // connect() fail (|socket| is destroyed in that case). 38 AsyncStunTCPSocket* AsyncStunTCPSocket::Create( 39 rtc::AsyncSocket* socket, 40 const rtc::SocketAddress& bind_address, 41 const rtc::SocketAddress& remote_address) { 42 return new AsyncStunTCPSocket(AsyncTCPSocketBase::ConnectSocket( 43 socket, bind_address, remote_address), false); 44 } 45 46 AsyncStunTCPSocket::AsyncStunTCPSocket( 47 rtc::AsyncSocket* socket, bool listen) 48 : rtc::AsyncTCPSocketBase(socket, listen, kBufSize) { 49 } 50 51 int AsyncStunTCPSocket::Send(const void *pv, size_t cb, 52 const rtc::PacketOptions& options) { 53 if (cb > kBufSize || cb < kPacketLenSize + kPacketLenOffset) { 54 SetError(EMSGSIZE); 55 return -1; 56 } 57 58 // If we are blocking on send, then silently drop this packet 59 if (!IsOutBufferEmpty()) 60 return static_cast<int>(cb); 61 62 int pad_bytes; 63 size_t expected_pkt_len = GetExpectedLength(pv, cb, &pad_bytes); 64 65 // Accepts only complete STUN/ChannelData packets. 66 if (cb != expected_pkt_len) 67 return -1; 68 69 AppendToOutBuffer(pv, cb); 70 71 ASSERT(pad_bytes < 4); 72 char padding[4] = {0}; 73 AppendToOutBuffer(padding, pad_bytes); 74 75 int res = FlushOutBuffer(); 76 if (res <= 0) { 77 // drop packet if we made no progress 78 ClearOutBuffer(); 79 return res; 80 } 81 82 // We claim to have sent the whole thing, even if we only sent partial 83 return static_cast<int>(cb); 84 } 85 86 void AsyncStunTCPSocket::ProcessInput(char* data, size_t* len) { 87 rtc::SocketAddress remote_addr(GetRemoteAddress()); 88 // STUN packet - First 4 bytes. Total header size is 20 bytes. 89 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 90 // |0 0| STUN Message Type | Message Length | 91 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 92 93 // TURN ChannelData 94 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 95 // | Channel Number | Length | 96 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 97 98 while (true) { 99 // We need at least 4 bytes to read the STUN or ChannelData packet length. 100 if (*len < kPacketLenOffset + kPacketLenSize) 101 return; 102 103 int pad_bytes; 104 size_t expected_pkt_len = GetExpectedLength(data, *len, &pad_bytes); 105 size_t actual_length = expected_pkt_len + pad_bytes; 106 107 if (*len < actual_length) { 108 return; 109 } 110 111 SignalReadPacket(this, data, expected_pkt_len, remote_addr, 112 rtc::CreatePacketTime(0)); 113 114 *len -= actual_length; 115 if (*len > 0) { 116 memmove(data, data + actual_length, *len); 117 } 118 } 119 } 120 121 void AsyncStunTCPSocket::HandleIncomingConnection( 122 rtc::AsyncSocket* socket) { 123 SignalNewConnection(this, new AsyncStunTCPSocket(socket, false)); 124 } 125 126 size_t AsyncStunTCPSocket::GetExpectedLength(const void* data, size_t len, 127 int* pad_bytes) { 128 *pad_bytes = 0; 129 PacketLength pkt_len = 130 rtc::GetBE16(static_cast<const char*>(data) + kPacketLenOffset); 131 size_t expected_pkt_len; 132 uint16_t msg_type = rtc::GetBE16(data); 133 if (IsStunMessage(msg_type)) { 134 // STUN message. 135 expected_pkt_len = kStunHeaderSize + pkt_len; 136 } else { 137 // TURN ChannelData message. 138 expected_pkt_len = kTurnChannelDataHdrSize + pkt_len; 139 // From RFC 5766 section 11.5 140 // Over TCP and TLS-over-TCP, the ChannelData message MUST be padded to 141 // a multiple of four bytes in order to ensure the alignment of 142 // subsequent messages. The padding is not reflected in the length 143 // field of the ChannelData message, so the actual size of a ChannelData 144 // message (including padding) is (4 + Length) rounded up to the nearest 145 // multiple of 4. Over UDP, the padding is not required but MAY be 146 // included. 147 if (expected_pkt_len % 4) 148 *pad_bytes = 4 - (expected_pkt_len % 4); 149 } 150 return expected_pkt_len; 151 } 152 153 } // namespace cricket 154