Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2004 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/base/asyncudpsocket.h"
     12 #include "webrtc/base/logging.h"
     13 
     14 namespace rtc {
     15 
     16 static const int BUF_SIZE = 64 * 1024;
     17 
     18 AsyncUDPSocket* AsyncUDPSocket::Create(
     19     AsyncSocket* socket,
     20     const SocketAddress& bind_address) {
     21   scoped_ptr<AsyncSocket> owned_socket(socket);
     22   if (socket->Bind(bind_address) < 0) {
     23     LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError();
     24     return NULL;
     25   }
     26   return new AsyncUDPSocket(owned_socket.release());
     27 }
     28 
     29 AsyncUDPSocket* AsyncUDPSocket::Create(SocketFactory* factory,
     30                                        const SocketAddress& bind_address) {
     31   AsyncSocket* socket =
     32       factory->CreateAsyncSocket(bind_address.family(), SOCK_DGRAM);
     33   if (!socket)
     34     return NULL;
     35   return Create(socket, bind_address);
     36 }
     37 
     38 AsyncUDPSocket::AsyncUDPSocket(AsyncSocket* socket)
     39     : socket_(socket) {
     40   ASSERT(socket_);
     41   size_ = BUF_SIZE;
     42   buf_ = new char[size_];
     43 
     44   // The socket should start out readable but not writable.
     45   socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent);
     46   socket_->SignalWriteEvent.connect(this, &AsyncUDPSocket::OnWriteEvent);
     47 }
     48 
     49 AsyncUDPSocket::~AsyncUDPSocket() {
     50   delete [] buf_;
     51 }
     52 
     53 SocketAddress AsyncUDPSocket::GetLocalAddress() const {
     54   return socket_->GetLocalAddress();
     55 }
     56 
     57 SocketAddress AsyncUDPSocket::GetRemoteAddress() const {
     58   return socket_->GetRemoteAddress();
     59 }
     60 
     61 int AsyncUDPSocket::Send(const void *pv, size_t cb,
     62                          const rtc::PacketOptions& options) {
     63   return socket_->Send(pv, cb);
     64 }
     65 
     66 int AsyncUDPSocket::SendTo(const void *pv, size_t cb,
     67                            const SocketAddress& addr,
     68                            const rtc::PacketOptions& options) {
     69   return socket_->SendTo(pv, cb, addr);
     70 }
     71 
     72 int AsyncUDPSocket::Close() {
     73   return socket_->Close();
     74 }
     75 
     76 AsyncUDPSocket::State AsyncUDPSocket::GetState() const {
     77   return STATE_BOUND;
     78 }
     79 
     80 int AsyncUDPSocket::GetOption(Socket::Option opt, int* value) {
     81   return socket_->GetOption(opt, value);
     82 }
     83 
     84 int AsyncUDPSocket::SetOption(Socket::Option opt, int value) {
     85   return socket_->SetOption(opt, value);
     86 }
     87 
     88 int AsyncUDPSocket::GetError() const {
     89   return socket_->GetError();
     90 }
     91 
     92 void AsyncUDPSocket::SetError(int error) {
     93   return socket_->SetError(error);
     94 }
     95 
     96 void AsyncUDPSocket::OnReadEvent(AsyncSocket* socket) {
     97   ASSERT(socket_.get() == socket);
     98 
     99   SocketAddress remote_addr;
    100   int len = socket_->RecvFrom(buf_, size_, &remote_addr);
    101   if (len < 0) {
    102     // An error here typically means we got an ICMP error in response to our
    103     // send datagram, indicating the remote address was unreachable.
    104     // When doing ICE, this kind of thing will often happen.
    105     // TODO: Do something better like forwarding the error to the user.
    106     SocketAddress local_addr = socket_->GetLocalAddress();
    107     LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString() << "] "
    108                  << "receive failed with error " << socket_->GetError();
    109     return;
    110   }
    111 
    112   // TODO: Make sure that we got all of the packet.
    113   // If we did not, then we should resize our buffer to be large enough.
    114   SignalReadPacket(this, buf_, static_cast<size_t>(len), remote_addr,
    115                    CreatePacketTime(0));
    116 }
    117 
    118 void AsyncUDPSocket::OnWriteEvent(AsyncSocket* socket) {
    119   SignalReadyToSend(this);
    120 }
    121 
    122 }  // namespace rtc
    123