/[resiprocate]/main/reTurn/AsyncTcpSocketBase.cxx
ViewVC logotype

Contents of /main/reTurn/AsyncTcpSocketBase.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10137 - (show annotations) (download)
Sun Apr 28 18:43:19 2013 UTC (6 years, 6 months ago) by sgodin
File MIME type: text/plain
File size: 8138 byte(s)
-merge work from b-counterpath-recon-20130424 with some changes
 - upped receive buffer size from 2048 to 4096
 - added setOnBeforeSocketClosedFp to AsyncSocketBase - Provides an opportunity
   for the app to clean up, e.g., QoS-related data or resources just before 
   the socket is closed
 - OS level Udp socket receive buffer size set to 66560
 - TurnAsyncSocketBase - use dispatch instead of post for send API for
   increased efficiency
 - TurnAsyncSocket - new client side APIs
   - setLocalPassword for checking integrity of incoming STUN messages
   - connectivityCheck for ICE connectivity checks 
   - setOnBeforeSocketClosedFp for QOS cleanup (windows)
   - send API now split into send(To)Framed and send(To)Unframed
   - Queue of guards modified to use a weak functor template instead
   - onBindFailure and onBindSuccess now return the Tuple that failed or succeeded
 - DataBuffer improvements
 - StunMessage - added ice attributes

1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <boost/bind.hpp>
6
7 #include "AsyncTcpSocketBase.hxx"
8 #include "AsyncSocketBaseHandler.hxx"
9 #include <rutil/Logger.hxx>
10 #include "ReTurnSubsystem.hxx"
11
12 #define RESIPROCATE_SUBSYSTEM ReTurnSubsystem::RETURN
13
14 using namespace std;
15
16 namespace reTurn {
17
18 AsyncTcpSocketBase::AsyncTcpSocketBase(asio::io_service& ioService)
19 : AsyncSocketBase(ioService),
20 mSocket(ioService),
21 mResolver(ioService)
22 {
23 }
24
25 AsyncTcpSocketBase::~AsyncTcpSocketBase()
26 {
27 }
28
29 unsigned int
30 AsyncTcpSocketBase::getSocketDescriptor()
31 {
32 return (unsigned int)mSocket.native();
33 }
34
35 asio::error_code
36 AsyncTcpSocketBase::bind(const asio::ip::address& address, unsigned short port)
37 {
38 asio::error_code errorCode;
39 mSocket.open(address.is_v6() ? asio::ip::tcp::v6() : asio::ip::tcp::v4(), errorCode);
40 if(!errorCode)
41 {
42 mSocket.set_option(asio::ip::tcp::no_delay(true), errorCode); // ?slg? do we want this?
43 mSocket.set_option(asio::ip::tcp::socket::reuse_address(true), errorCode);
44 mSocket.bind(asio::ip::tcp::endpoint(address, port), errorCode);
45 }
46 return errorCode;
47 }
48
49 void
50 AsyncTcpSocketBase::connect(const std::string& address, unsigned short port)
51 {
52 // Start an asynchronous resolve to translate the address
53 // into a list of endpoints.
54 resip::Data service(port);
55 #ifdef USE_IPV6
56 asio::ip::tcp::resolver::query query(address, service.c_str());
57 #else
58 asio::ip::tcp::resolver::query query(asio::ip::tcp::v4(), address, service.c_str());
59 #endif
60 mResolver.async_resolve(query,
61 boost::bind(&AsyncSocketBase::handleTcpResolve, shared_from_this(),
62 asio::placeholders::error,
63 asio::placeholders::iterator));
64 }
65
66 void
67 AsyncTcpSocketBase::handleTcpResolve(const asio::error_code& ec,
68 asio::ip::tcp::resolver::iterator endpoint_iterator)
69 {
70 if (!ec)
71 {
72 // Attempt a connection to the first endpoint in the list. Each endpoint
73 // will be tried until we successfully establish a connection.
74 //asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
75 mSocket.async_connect(endpoint_iterator->endpoint(),
76 boost::bind(&AsyncSocketBase::handleConnect, shared_from_this(),
77 asio::placeholders::error, endpoint_iterator));
78 }
79 else
80 {
81 onConnectFailure(ec);
82 }
83 }
84
85 void
86 AsyncTcpSocketBase::handleConnect(const asio::error_code& ec,
87 asio::ip::tcp::resolver::iterator endpoint_iterator)
88 {
89 if (!ec)
90 {
91 // The connection was successful.
92 mConnected = true;
93 mConnectedAddress = endpoint_iterator->endpoint().address();
94 mConnectedPort = endpoint_iterator->endpoint().port();
95
96 onConnectSuccess();
97 }
98 else if (++endpoint_iterator != asio::ip::tcp::resolver::iterator())
99 {
100 // The connection failed. Try the next endpoint in the list.
101 asio::error_code ec;
102 mSocket.close(ec);
103 mSocket.async_connect(endpoint_iterator->endpoint(),
104 boost::bind(&AsyncSocketBase::handleConnect, shared_from_this(),
105 asio::placeholders::error, endpoint_iterator));
106 }
107 else
108 {
109 onConnectFailure(ec);
110 }
111 }
112
113 void
114 AsyncTcpSocketBase::setConnectedAddressAndPort()
115 {
116 asio::error_code ec;
117 mConnectedAddress = mSocket.remote_endpoint(ec).address();
118 mConnectedPort = mSocket.remote_endpoint(ec).port();
119 }
120
121 const asio::ip::address
122 AsyncTcpSocketBase::getSenderEndpointAddress()
123 {
124 return mConnectedAddress;
125 }
126
127 unsigned short
128 AsyncTcpSocketBase::getSenderEndpointPort()
129 {
130 return mConnectedPort;
131 }
132
133 void
134 AsyncTcpSocketBase::transportSend(const StunTuple& destination, std::vector<asio::const_buffer>& buffers)
135 {
136 // Note: destination is ignored for TCP
137 asio::async_write(mSocket, buffers,
138 boost::bind(&AsyncTcpSocketBase::handleSend, shared_from_this(), asio::placeholders::error));
139 }
140
141 void
142 AsyncTcpSocketBase::transportReceive()
143 {
144 mSocket.async_read_some(asio::buffer((void*)mReceiveBuffer->data(), RECEIVE_BUFFER_SIZE),
145 boost::bind(&AsyncTcpSocketBase::handleReceive, shared_from_this(), asio::placeholders::error, asio::placeholders::bytes_transferred));
146 }
147
148 void
149 AsyncTcpSocketBase::transportFramedReceive()
150 {
151 asio::async_read(mSocket, asio::buffer((void*)mReceiveBuffer->data(), 4),
152 boost::bind(&AsyncSocketBase::handleReadHeader, shared_from_this(), asio::placeholders::error));
153 }
154
155 void
156 AsyncTcpSocketBase::handleReadHeader(const asio::error_code& e)
157 {
158 if (!e)
159 {
160 /*
161 std::cout << "Read header from tcp socket: " << std::endl;
162 for(unsigned int i = 0; i < 4; i++)
163 {
164 std::cout << (char)(*mReceiveBuffer)[i] << "(" << (int)(*mReceiveBuffer)[i] << ") ";
165 }
166 std::cout << std::endl;
167 */
168
169 // Note: For both StunMessages and ChannelData messages the length in bytes 3 and 4
170 UInt16 dataLen;
171 memcpy(&dataLen, &(*mReceiveBuffer)[2], 2);
172 dataLen = ntohs(dataLen);
173
174 if(((*mReceiveBuffer)[0] & 0xC0) == 0) // If first 2 bits are 00 then this is a stun message
175 {
176 dataLen += 16; // There are 20 bytes in total in the header, and we have already read 4 - read the rest of the header + the body
177 }
178 if(dataLen+4 < RECEIVE_BUFFER_SIZE)
179 {
180 asio::async_read(mSocket, asio::buffer(&(*mReceiveBuffer)[4], dataLen),
181 boost::bind(&AsyncTcpSocketBase::handleReceive, shared_from_this(), asio::placeholders::error, dataLen+4));
182 }
183 else
184 {
185 WarningLog(<< "Receive buffer (" << RECEIVE_BUFFER_SIZE << ") is not large enough to accomdate incoming framed data (" << dataLen+4 << ") closing connection.");
186 close();
187 }
188 }
189 else if (e != asio::error::operation_aborted)
190 {
191 if(e != asio::error::eof &&
192 #ifdef _WIN32
193 e.value() != ERROR_CONNECTION_ABORTED && // This happens on Windows 7 when closing the socket
194 #endif
195 e != asio::error::connection_reset)
196 {
197 WarningLog(<< "Read header error: " << e.value() << "-" << e.message());
198 }
199 close();
200 }
201 }
202
203 void
204 AsyncTcpSocketBase::transportClose()
205 {
206 if (mOnBeforeSocketCloseFp)
207 {
208 mOnBeforeSocketCloseFp((unsigned int)mSocket.native());
209 }
210
211 asio::error_code ec;
212 mSocket.close(ec);
213 }
214
215 }
216
217
218 /* ====================================================================
219
220 Copyright (c) 2007-2008, Plantronics, Inc.
221 All rights reserved.
222
223 Redistribution and use in source and binary forms, with or without
224 modification, are permitted provided that the following conditions are
225 met:
226
227 1. Redistributions of source code must retain the above copyright
228 notice, this list of conditions and the following disclaimer.
229
230 2. Redistributions in binary form must reproduce the above copyright
231 notice, this list of conditions and the following disclaimer in the
232 documentation and/or other materials provided with the distribution.
233
234 3. Neither the name of Plantronics nor the names of its contributors
235 may be used to endorse or promote products derived from this
236 software without specific prior written permission.
237
238 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
239 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
240 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
241 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
242 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
243 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
244 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
247 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
248 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
249
250 ==================================================================== */
251

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27