1f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/* 2f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * 4f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * Use of this source code is governed by a BSD-style license 5f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 6f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 7f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * in the file PATENTS. All contributing project authors may 8f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org */ 10f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 11f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/asyncudpsocket.h" 12f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/logging.h" 13f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 14f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgnamespace rtc { 15f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 16f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstatic const int BUF_SIZE = 64 * 1024; 17f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 18f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncUDPSocket* AsyncUDPSocket::Create( 19f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org AsyncSocket* socket, 20f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org const SocketAddress& bind_address) { 21f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org scoped_ptr<AsyncSocket> owned_socket(socket); 22f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (socket->Bind(bind_address) < 0) { 23f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError(); 24f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return NULL; 25f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 26f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return new AsyncUDPSocket(owned_socket.release()); 27f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 28f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 29f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncUDPSocket* AsyncUDPSocket::Create(SocketFactory* factory, 30f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org const SocketAddress& bind_address) { 31f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org AsyncSocket* socket = 32f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org factory->CreateAsyncSocket(bind_address.family(), SOCK_DGRAM); 33f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (!socket) 34f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return NULL; 35f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return Create(socket, bind_address); 36f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 37f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 38f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncUDPSocket::AsyncUDPSocket(AsyncSocket* socket) 39f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org : socket_(socket) { 40f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org ASSERT(socket_); 41f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org size_ = BUF_SIZE; 42f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org buf_ = new char[size_]; 43f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 44f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org // The socket should start out readable but not writable. 45f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent); 46f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org socket_->SignalWriteEvent.connect(this, &AsyncUDPSocket::OnWriteEvent); 47f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 48f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 49f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncUDPSocket::~AsyncUDPSocket() { 50f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org delete [] buf_; 51f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 52f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 53f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgSocketAddress AsyncUDPSocket::GetLocalAddress() const { 54f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return socket_->GetLocalAddress(); 55f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 56f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 57f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgSocketAddress AsyncUDPSocket::GetRemoteAddress() const { 58f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return socket_->GetRemoteAddress(); 59f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 60f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 61f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint AsyncUDPSocket::Send(const void *pv, size_t cb, 62f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org const rtc::PacketOptions& options) { 63c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan rtc::SentPacket sent_packet(options.packet_id, rtc::Time()); 64c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan int ret = socket_->Send(pv, cb); 65c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan SignalSentPacket(this, sent_packet); 66c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan return ret; 67f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 68f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 69f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint AsyncUDPSocket::SendTo(const void *pv, size_t cb, 70f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org const SocketAddress& addr, 71f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org const rtc::PacketOptions& options) { 72c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan rtc::SentPacket sent_packet(options.packet_id, rtc::Time()); 73c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan int ret = socket_->SendTo(pv, cb, addr); 74c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan SignalSentPacket(this, sent_packet); 75c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan return ret; 76f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 77f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 78f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint AsyncUDPSocket::Close() { 79f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return socket_->Close(); 80f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 81f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 82f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncUDPSocket::State AsyncUDPSocket::GetState() const { 83f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return STATE_BOUND; 84f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 85f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 86f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint AsyncUDPSocket::GetOption(Socket::Option opt, int* value) { 87f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return socket_->GetOption(opt, value); 88f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 89f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 90f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint AsyncUDPSocket::SetOption(Socket::Option opt, int value) { 91f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return socket_->SetOption(opt, value); 92f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 93f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 94f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint AsyncUDPSocket::GetError() const { 95f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return socket_->GetError(); 96f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 97f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 98f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid AsyncUDPSocket::SetError(int error) { 99f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return socket_->SetError(error); 100f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 101f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 102f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid AsyncUDPSocket::OnReadEvent(AsyncSocket* socket) { 103f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org ASSERT(socket_.get() == socket); 104f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 105f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org SocketAddress remote_addr; 106f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org int len = socket_->RecvFrom(buf_, size_, &remote_addr); 107f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (len < 0) { 108f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org // An error here typically means we got an ICMP error in response to our 109f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org // send datagram, indicating the remote address was unreachable. 110f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org // When doing ICE, this kind of thing will often happen. 111f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org // TODO: Do something better like forwarding the error to the user. 112f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org SocketAddress local_addr = socket_->GetLocalAddress(); 113f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString() << "] " 114f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org << "receive failed with error " << socket_->GetError(); 115f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return; 116f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 117f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 118f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org // TODO: Make sure that we got all of the packet. 119f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org // If we did not, then we should resize our buffer to be large enough. 120f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org SignalReadPacket(this, buf_, static_cast<size_t>(len), remote_addr, 121f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org CreatePacketTime(0)); 122f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 123f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 124f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid AsyncUDPSocket::OnWriteEvent(AsyncSocket* socket) { 125f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org SignalReadyToSend(this); 126f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 127f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 128f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} // namespace rtc 129