1
#include "AsyncSocketBase.hxx"
2
#include "AsyncSocketBaseHandler.hxx"
3
#include <boost/bind.hpp>
4
#include <rutil/WinLeakCheck.hxx>
8
#define NO_CHANNEL ((unsigned short)-1)
12
AsyncSocketBase::AsyncSocketBase(asio::io_service& ioService) :
13
mIOService(ioService),
16
mAsyncSocketBaseHandler(0)
20
AsyncSocketBase::~AsyncSocketBase()
22
if(mAsyncSocketBaseHandler) mAsyncSocketBaseHandler->onSocketDestroyed();
26
AsyncSocketBase::send(const StunTuple& destination, boost::shared_ptr<DataBuffer>& data)
28
mIOService.post(boost::bind(&AsyncSocketBase::doSend, shared_from_this(), destination, data, 0));
32
AsyncSocketBase::send(const StunTuple& destination, unsigned short channel, boost::shared_ptr<DataBuffer>& data)
34
mIOService.post(boost::bind(&AsyncSocketBase::doSend, shared_from_this(), destination, channel, data, 0));
38
AsyncSocketBase::doSend(const StunTuple& destination, boost::shared_ptr<DataBuffer>& data, unsigned int bufferStartPos)
40
doSend(destination, NO_CHANNEL, data, bufferStartPos);
44
AsyncSocketBase::doSend(const StunTuple& destination, unsigned short channel, boost::shared_ptr<DataBuffer>& data, unsigned int bufferStartPos)
46
bool writeInProgress = !mSendDataQueue.empty();
47
if(channel == NO_CHANNEL)
49
boost::shared_ptr<DataBuffer> empty;
50
mSendDataQueue.push_back(SendData(destination, empty, data, bufferStartPos));
55
boost::shared_ptr<DataBuffer> frame = allocateBuffer(4);
56
channel = htons(channel);
57
memcpy(&(*frame)[0], &channel, 2);
58
unsigned short msgsize = htons((unsigned short)data->size());
59
memcpy(&(*frame)[2], (void*)&msgsize, 2); // UDP doesn't need size - but shouldn't hurt to send it anyway
61
mSendDataQueue.push_back(SendData(destination, frame, data, bufferStartPos));
65
sendFirstQueuedData();
70
AsyncSocketBase::handleSend(const asio::error_code& e)
81
// TODO - check if closed here, and if so don't try and send more
83
// Clear this data from the queue and see if there is more data to send
84
mSendDataQueue.pop_front();
85
if (!mSendDataQueue.empty())
87
sendFirstQueuedData();
92
AsyncSocketBase::sendFirstQueuedData()
94
std::vector<asio::const_buffer> bufs;
95
if(mSendDataQueue.front().mFrameData.get() != 0) // If we have frame data
97
bufs.push_back(asio::buffer(mSendDataQueue.front().mFrameData->data(), mSendDataQueue.front().mFrameData->size()));
99
bufs.push_back(asio::buffer(mSendDataQueue.front().mData->data()+mSendDataQueue.front().mBufferStartPos, mSendDataQueue.front().mData->size()-mSendDataQueue.front().mBufferStartPos));
100
transportSend(mSendDataQueue.front().mDestination, bufs);
104
AsyncSocketBase::receive()
106
mIOService.post(boost::bind(&AsyncSocketBase::doReceive, shared_from_this()));
110
AsyncSocketBase::doReceive()
115
mReceiveBuffer = allocateBuffer(RECEIVE_BUFFER_SIZE);
121
AsyncSocketBase::framedReceive()
123
mIOService.post(boost::bind(&AsyncSocketBase::doFramedReceive, shared_from_this()));
127
AsyncSocketBase::doFramedReceive()
132
mReceiveBuffer = allocateBuffer(RECEIVE_BUFFER_SIZE);
133
transportFramedReceive();
138
AsyncSocketBase::handleReceive(const asio::error_code& e, std::size_t bytesTransferred)
144
// Handoff received buffer to appliction, and prepare receive buffer for next call
145
mReceiveBuffer->truncate(bytesTransferred);
146
onReceiveSuccess(getSenderEndpointAddress(), getSenderEndpointPort(), mReceiveBuffer);
155
AsyncSocketBase::close()
157
mIOService.post(boost::bind(&AsyncSocketBase::transportClose, shared_from_this()));
160
boost::shared_ptr<DataBuffer>
161
AsyncSocketBase::allocateBuffer(unsigned int size)
163
return boost::shared_ptr<DataBuffer>(new DataBuffer(size));
169
/* ====================================================================
171
Copyright (c) 2007-2008, Plantronics, Inc.
174
Redistribution and use in source and binary forms, with or without
175
modification, are permitted provided that the following conditions are
178
1. Redistributions of source code must retain the above copyright
179
notice, this list of conditions and the following disclaimer.
181
2. Redistributions in binary form must reproduce the above copyright
182
notice, this list of conditions and the following disclaimer in the
183
documentation and/or other materials provided with the distribution.
185
3. Neither the name of Plantronics nor the names of its contributors
186
may be used to endorse or promote products derived from this
187
software without specific prior written permission.
189
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
190
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
191
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
193
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
194
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
195
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
196
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
197
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
198
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
199
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
201
==================================================================== */