• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SocketStream(AsyncSocket * socket)32 SocketStream::SocketStream(AsyncSocket* socket) : socket_(NULL) {
33   Attach(socket);
34 }
35 
~SocketStream()36 SocketStream::~SocketStream() {
37   delete socket_;
38 }
39 
Attach(AsyncSocket * socket)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 
Detach()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 
GetState() const64 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 
Read(void * buffer,size_t buffer_len,size_t * read,int * error)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 
Write(const void * data,size_t data_len,size_t * written,int * error)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 
Close()112 void SocketStream::Close() {
113   ASSERT(socket_ != NULL);
114   socket_->Close();
115 }
116 
OnConnectEvent(AsyncSocket * socket)117 void SocketStream::OnConnectEvent(AsyncSocket* socket) {
118   ASSERT(socket == socket_);
119   SignalEvent(this, SE_OPEN | SE_READ | SE_WRITE, 0);
120 }
121 
OnReadEvent(AsyncSocket * socket)122 void SocketStream::OnReadEvent(AsyncSocket* socket) {
123   ASSERT(socket == socket_);
124   SignalEvent(this, SE_READ, 0);
125 }
126 
OnWriteEvent(AsyncSocket * socket)127 void SocketStream::OnWriteEvent(AsyncSocket* socket) {
128   ASSERT(socket == socket_);
129   SignalEvent(this, SE_WRITE, 0);
130 }
131 
OnCloseEvent(AsyncSocket * socket,int err)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