89 typedef const packet_type* const_packet_pointer;
90 typedef std::deque<const_packet_pointer> send_queue;
91 typedef typename protocol_type::socket socket_type;
92 typedef std::shared_ptr<socket_type> socket_pointer;
93 typedef boost::asio::ssl::stream<tcp_protocol::socket> secure_stream_type;
94 typedef std::shared_ptr<secure_stream_type> secure_stream_pointer;
95 typedef std::variant<std::monostate, socket_pointer, secure_stream_pointer> socket_holder_type;
96 typedef boost::asio::ssl::context secure_stream_context;
97 typedef std::unique_ptr<secure_stream_context> secure_stream_context_pointer;
98 typedef typename protocol_type::endpoint endpoint_type;
99 typedef typename protocol_type::resolver resolver_type;
100 typedef std::array<char, ReceiveBufferSize *
sizeof(CharType)> receive_buffer;
101 typedef boost::asio::ssl::context secure_context;
105 handler_proxy(our_type& aParent) : iParentDestroyed{ aParent }, iParent{ aParent }, iOrphaned{
false }
109 void handle_resolve(
const boost::system::error_code& aError,
typename resolver_type::iterator aEndPointIterator)
111 if (!iParentDestroyed && !iOrphaned)
112 iParent.handle_resolve(aError, aEndPointIterator);
114 void handle_connect(
const boost::system::error_code& aError)
116 if (!iParentDestroyed && !iOrphaned)
117 iParent.handle_connect(aError);
119 void handle_handshake(
const boost::system::error_code& aError)
121 if (!iParentDestroyed && !iOrphaned)
122 iParent.handle_handshake(aError);
124 void handle_write(
const boost::system::error_code& aError,
size_t aBytesTransferred)
126 if (!iParentDestroyed && !iOrphaned)
127 iParent.handle_write(aError, aBytesTransferred);
129 void handle_read(
const boost::system::error_code& aError,
size_t aBytesTransferred)
131 if (!iParentDestroyed && !iOrphaned)
132 iParent.handle_read(aError, aBytesTransferred);
134 void orphan(
bool aCreateNewHandlerProxy =
true)
137 if (aCreateNewHandlerProxy)
138 iParent.iHandlerProxy = std::make_shared<handler_proxy>(iParent);
140 iParent.iHandlerProxy.reset();
151 struct no_socket : std::logic_error {
no_socket() : std::logic_error(
"neolib::packet_connection::no_socket") {} };
158 bool aSecure =
false,
162 iHandlerProxy(new handler_proxy(*this)),
168 iProtocolFamily(aProtocolFamily),
170 iResolver(aIoTask.io_service().native_object<boost::asio::io_service>()),
172 iPacketBeingSent(nullptr),
173 iReceiveBufferPtr(&iReceiveBuffer[0]),
174 iReceivePacket(aOwner.handle_create_empty_packet())
180 const std::string& aRemoteHostName,
181 unsigned short aRemotePort,
182 bool aSecure =
false,
186 iHandlerProxy(new handler_proxy(*this)),
189 iRemoteHostName(aRemoteHostName),
190 iRemotePort(aRemotePort),
192 iProtocolFamily(aProtocolFamily),
194 iResolver(aIoTask.io_service().native_object<boost::asio::io_service>()),
196 iPacketBeingSent(nullptr),
197 iReceiveBufferPtr(&iReceiveBuffer[0]),
198 iReceivePacket(aOwner.handle_create_empty_packet())
210 bool open(
const std::string& aRemoteHostName,
unsigned short aRemotePort,
bool aSecure =
false,
protocol_family aProtocolFamily =
IPv4)
214 iLocalHostName = std::string();
216 iRemoteHostName = aRemoteHostName;
217 iRemotePort = aRemotePort;
219 iProtocolFamily = aProtocolFamily;
223 bool open(
bool aAcceptingSocket =
false)
229 iSocketHolder = socket_pointer(
new socket_type(iIoTask.
io_service().
native_object<boost::asio::io_service>()));
233 if (iSecureStreamContext ==
nullptr)
234 iSecureStreamContext.reset(
new secure_stream_context(boost::asio::ssl::context::sslv23));
235 iSocketHolder = secure_stream_pointer(
new secure_stream_type(iIoTask.
io_service().
native_object<boost::asio::io_service>(), *iSecureStreamContext));
237 if (aAcceptingSocket)
239 boost::system::error_code ec;
240 socket().open(to_protocol<protocol_type>(iProtocolFamily), ec);
250 iHandlerProxy->orphan();
252 if (!std::holds_alternative<std::monostate>(iSocketHolder))
254 iSocketHolder =
none;
255 bool wasConnected = iConnected;
257 iReceiveBufferPtr = &iReceiveBuffer[0];
259 iOwner.handle_connection_closed();
261 void send_packet(
const packet_type& aPacket,
bool aHighPriority =
false)
263 iSendQueue.insert(aHighPriority ? iSendQueue.begin() : iSendQueue.end(), &aPacket);
270 return std::holds_alternative<socket_pointer>(iSocketHolder) && std::get<socket_pointer>(iSocketHolder) !=
nullptr;
274 return std::holds_alternative<secure_stream_pointer>(iSocketHolder) && std::get<secure_stream_pointer>(iSocketHolder) !=
nullptr;
301 const boost::system::error_code&
error()
const
307 return iLocalEndPoint;
311 return iRemoteEndPoint;
313 template <
typename CharType2,
size_t ReceiveBufferSize2>
319 template <
typename CharType2,
size_t ReceiveBufferSize2>
329 return *std::get<secure_stream_pointer>(iSocketHolder);
335 return *std::get<secure_stream_pointer>(iSocketHolder);
340 iLocalHostName =
socket().local_endpoint().address().to_string();
341 iLocalPort =
socket().local_endpoint().port();
350 boost::system::error_code ec;
351 if (iLocalHostName.empty())
352 socket().bind(endpoint_type(to_protocol<protocol_type>(iProtocolFamily), iLocalPort), ec);
355 typename resolver_type::iterator result = iResolver.resolve(
typename resolver_type::query(iLocalHostName, uint32_to_string<char>(iLocalPort)), ec);
358 bool foundGoodMatch =
false;
359 for (
typename resolver_type::iterator i = result; !foundGoodMatch && i !=
typename resolver_type::iterator(); ++i)
361 endpoint_type endpoint = *i;
364 iLocalEndPoint = endpoint;
365 socket().bind(iLocalEndPoint, ec);
366 foundGoodMatch =
true;
371 iLocalEndPoint = *result;
372 socket().bind(iLocalEndPoint, ec);
378 iLocalEndPoint =
socket().local_endpoint();
379 iLocalHostName =
socket().local_endpoint().address().to_string();
380 iLocalPort =
socket().local_endpoint().port();
387 iOwner.handle_connection_failure(ec);
393 if (!iRemoteHostName.empty())
395 iResolver.async_resolve(
typename resolver_type::query(iRemoteHostName, uint32_to_string<char>(iRemotePort)),
396 boost::bind(&handler_proxy::handle_resolve, iHandlerProxy, boost::asio::placeholders::error, boost::asio::placeholders::iterator));
402 void handle_resolve(
const boost::system::error_code& aError,
typename resolver_type::iterator aEndPointIterator)
408 bool foundGoodMatch =
false;
409 for (
typename resolver_type::iterator i = aEndPointIterator; !foundGoodMatch && i !=
typename resolver_type::iterator(); ++i)
411 endpoint_type endpoint = *i;
414 foundGoodMatch =
true;
415 iRemoteEndPoint = endpoint;
416 socket().async_connect(iRemoteEndPoint, boost::bind(&handler_proxy::handle_connect, iHandlerProxy, boost::asio::placeholders::error));
421 iRemoteEndPoint = *aEndPointIterator;
422 socket().async_connect(iRemoteEndPoint, boost::bind(&handler_proxy::handle_connect, iHandlerProxy, boost::asio::placeholders::error));
429 iOwner.handle_connection_failure(aError);
432 void handle_connect(
const boost::system::error_code& aError)
442 iOwner.handle_connection_established();
450 std::get<secure_stream_pointer>(iSocketHolder)->async_handshake(
451 boost::asio::ssl::stream_base::client,
452 boost::bind(&handler_proxy::handle_handshake, iHandlerProxy, boost::asio::placeholders::error));
459 iOwner.handle_connection_failure(aError);
462 void handle_handshake(
const boost::system::error_code& aError)
469 iOwner.handle_connection_established();
479 iOwner.handle_connection_failure(aError);
486 if (iSendQueue.empty())
488 if (iPacketBeingSent !=
nullptr)
490 iPacketBeingSent = iSendQueue.front();
491 iSendQueue.pop_front();
494 boost::asio::async_write(
496 boost::asio::buffer(iPacketBeingSent->data(), iPacketBeingSent->length()),
498 &handler_proxy::handle_write,
500 boost::asio::placeholders::error,
501 boost::asio::placeholders::bytes_transferred));
505 boost::asio::async_write(
507 boost::asio::buffer(iPacketBeingSent->data(), iPacketBeingSent->length()),
509 &handler_proxy::handle_write,
511 boost::asio::placeholders::error,
512 boost::asio::placeholders::bytes_transferred));
523 boost::asio::buffer(iReceiveBufferPtr, iReceiveBuffer.size() - (iReceiveBufferPtr - &iReceiveBuffer[0])),
525 &handler_proxy::handle_read,
527 boost::asio::placeholders::error,
528 boost::asio::placeholders::bytes_transferred));
533 boost::asio::buffer(iReceiveBufferPtr, iReceiveBuffer.size() - (iReceiveBufferPtr - &iReceiveBuffer[0])),
535 &handler_proxy::handle_read,
537 boost::asio::placeholders::error,
538 boost::asio::placeholders::bytes_transferred));
541 void handle_write(
const boost::system::error_code& aError,
size_t)
546 const_packet_pointer sentPacket = iPacketBeingSent;
547 iPacketBeingSent =
nullptr;
550 iOwner.handle_packet_sent(*sentPacket);
559 iOwner.handle_transfer_failure(*sentPacket, aError);
565 void handle_read(
const boost::system::error_code& aError,
size_t aBytesTransferred)
572 typename packet_type::const_pointer start =
reinterpret_cast<typename packet_type::pointer
>(&iReceiveBuffer[0]);
573 typename packet_type::const_pointer end = start + aBytesTransferred /
sizeof(CharType);
574 while(iReceivePacket->take_some(start, end))
576 if (!iReceivePacket->empty())
578 iOwner.handle_packet_arrived(*iReceivePacket);
581 iReceivePacket->clear();
584 iReceiveBufferPtr = std::copy(
585 reinterpret_cast<typename receive_buffer::const_pointer
>(start),
586 reinterpret_cast<typename receive_buffer::const_pointer
>(iReceiveBufferPtr + aBytesTransferred),
592 if (aError.value() != boost::asio::error::eof &&
opened())
596 iReceivePacket->clear();
597 iOwner.handle_transfer_failure(*iReceivePacket, aError);
607 i_async_task& iIoTask;
609 std::shared_ptr<handler_proxy> iHandlerProxy;
610 std::string iLocalHostName;
611 unsigned short iLocalPort;
612 std::string iRemoteHostName;
613 unsigned short iRemotePort;
617 boost::system::error_code iErrorCode;
618 resolver_type iResolver;
619 endpoint_type iLocalEndPoint;
620 endpoint_type iRemoteEndPoint;
621 secure_stream_context_pointer iSecureStreamContext;
622 socket_holder_type iSocketHolder;
624 send_queue iSendQueue;
625 const_packet_pointer iPacketBeingSent;
626 receive_buffer iReceiveBuffer;
627 typename receive_buffer::pointer iReceiveBufferPtr;
628 typename packet_type::clone_pointer iReceivePacket;