Home | History | Annotate | Download | only in base
      1 /*
      2  * libjingle
      3  * Copyright 2010, 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/base/socketstream.h"
     29 
     30 namespace talk_base {
     31 
     32 SocketStream::SocketStream(AsyncSocket* socket) : socket_(NULL) {
     33   Attach(socket);
     34 }
     35 
     36 SocketStream::~SocketStream() {
     37   delete socket_;
     38 }
     39 
     40 void SocketStream::Attach(AsyncSocket* socket) {
     41   if (socket_)
     42     delete socket_;
     43   socket_ = socket;
     44   if (socket_) {
     45     socket_->SignalConnectEvent.connect(this, &SocketStream::OnConnectEvent);
     46     socket_->SignalReadEvent.connect(this,    &SocketStream::OnReadEvent);
     47     socket_->SignalWriteEvent.connect(this,   &SocketStream::OnWriteEvent);
     48     socket_->SignalCloseEvent.connect(this,   &SocketStream::OnCloseEvent);
     49   }
     50 }
     51 
     52 AsyncSocket* SocketStream::Detach() {
     53   AsyncSocket* socket = socket_;
     54   if (socket_) {
     55     socket_->SignalConnectEvent.disconnect(this);
     56     socket_->SignalReadEvent.disconnect(this);
     57     socket_->SignalWriteEvent.disconnect(this);
     58     socket_->SignalCloseEvent.disconnect(this);
     59     socket_ = NULL;
     60   }
     61   return socket;
     62 }
     63 
     64 StreamState SocketStream::GetState() const {
     65   ASSERT(socket_ != NULL);
     66   switch (socket_->GetState()) {
     67     case Socket::CS_CONNECTED:
     68       return SS_OPEN;
     69     case Socket::CS_CONNECTING:
     70       return SS_OPENING;
     71     case Socket::CS_CLOSED:
     72     default:
     73       return SS_CLOSED;
     74   }
     75 }
     76 
     77 StreamResult SocketStream::Read(void* buffer, size_t buffer_len,
     78                                 size_t* read, int* error) {
     79   ASSERT(socket_ != NULL);
     80   int result = socket_->Recv(buffer, buffer_len);
     81   if (result < 0) {
     82     if (socket_->IsBlocking())
     83       return SR_BLOCK;
     84     if (error)
     85       *error = socket_->GetError();
     86     return SR_ERROR;
     87   }
     88   if ((result > 0) || (buffer_len == 0)) {
     89     if (read)
     90       *read = result;
     91     return SR_SUCCESS;
     92   }
     93   return SR_EOS;
     94 }
     95 
     96 StreamResult SocketStream::Write(const void* data, size_t data_len,
     97                                  size_t* written, int* error) {
     98   ASSERT(socket_ != NULL);
     99   int result = socket_->Send(data, data_len);
    100   if (result < 0) {
    101     if (socket_->IsBlocking())
    102       return SR_BLOCK;
    103     if (error)
    104       *error = socket_->GetError();
    105     return SR_ERROR;
    106   }
    107   if (written)
    108     *written = result;
    109   return SR_SUCCESS;
    110 }
    111 
    112 void SocketStream::Close() {
    113   ASSERT(socket_ != NULL);
    114   socket_->Close();
    115 }
    116 
    117 void SocketStream::OnConnectEvent(AsyncSocket* socket) {
    118   ASSERT(socket == socket_);
    119   SignalEvent(this, SE_OPEN | SE_READ | SE_WRITE, 0);
    120 }
    121 
    122 void SocketStream::OnReadEvent(AsyncSocket* socket) {
    123   ASSERT(socket == socket_);
    124   SignalEvent(this, SE_READ, 0);
    125 }
    126 
    127 void SocketStream::OnWriteEvent(AsyncSocket* socket) {
    128   ASSERT(socket == socket_);
    129   SignalEvent(this, SE_WRITE, 0);
    130 }
    131 
    132 void SocketStream::OnCloseEvent(AsyncSocket* socket, int err) {
    133   ASSERT(socket == socket_);
    134   SignalEvent(this, SE_CLOSE, err);
    135 }
    136 
    137 
    138 }  // namespace talk_base
    139