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