147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/asyncudpsocket.h" 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h" 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int BUF_SIZE = 64 * 1024; 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncUDPSocket* AsyncUDPSocket::Create( 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocket* socket, 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const SocketAddress& bind_address) { 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org scoped_ptr<AsyncSocket> owned_socket(socket); 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket->Bind(bind_address) < 0) { 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError(); 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return new AsyncUDPSocket(owned_socket.release()); 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncUDPSocket* AsyncUDPSocket::Create(SocketFactory* factory, 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const SocketAddress& bind_address) { 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocket* socket = 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org factory->CreateAsyncSocket(bind_address.family(), SOCK_DGRAM); 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!socket) 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return Create(socket, bind_address); 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncUDPSocket::AsyncUDPSocket(AsyncSocket* socket) 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : socket_(socket) { 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(socket_); 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_ = BUF_SIZE; 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org buf_ = new char[size_]; 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // The socket should start out readable but not writable. 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent); 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_->SignalWriteEvent.connect(this, &AsyncUDPSocket::OnWriteEvent); 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncUDPSocket::~AsyncUDPSocket() { 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete [] buf_; 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress AsyncUDPSocket::GetLocalAddress() const { 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket_->GetLocalAddress(); 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress AsyncUDPSocket::GetRemoteAddress() const { 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket_->GetRemoteAddress(); 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint AsyncUDPSocket::Send(const void *pv, size_t cb, 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const rtc::PacketOptions& options) { 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket_->Send(pv, cb); 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint AsyncUDPSocket::SendTo(const void *pv, size_t cb, 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const SocketAddress& addr, 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const rtc::PacketOptions& options) { 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket_->SendTo(pv, cb, addr); 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint AsyncUDPSocket::Close() { 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket_->Close(); 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncUDPSocket::State AsyncUDPSocket::GetState() const { 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return STATE_BOUND; 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint AsyncUDPSocket::GetOption(Socket::Option opt, int* value) { 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket_->GetOption(opt, value); 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint AsyncUDPSocket::SetOption(Socket::Option opt, int value) { 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket_->SetOption(opt, value); 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint AsyncUDPSocket::GetError() const { 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket_->GetError(); 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid AsyncUDPSocket::SetError(int error) { 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket_->SetError(error); 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid AsyncUDPSocket::OnReadEvent(AsyncSocket* socket) { 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(socket_.get() == socket); 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress remote_addr; 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int len = socket_->RecvFrom(buf_, size_, &remote_addr); 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (len < 0) { 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // An error here typically means we got an ICMP error in response to our 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // send datagram, indicating the remote address was unreachable. 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // When doing ICE, this kind of thing will often happen. 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO: Do something better like forwarding the error to the user. 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress local_addr = socket_->GetLocalAddress(); 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString() << "] " 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << "receive failed with error " << socket_->GetError(); 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO: Make sure that we got all of the packet. 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // If we did not, then we should resize our buffer to be large enough. 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalReadPacket(this, buf_, static_cast<size_t>(len), remote_addr, 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CreatePacketTime(0)); 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid AsyncUDPSocket::OnWriteEvent(AsyncSocket* socket) { 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalReadyToSend(this); 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 123