neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
packet_stream.hpp
Go to the documentation of this file.
1// packet_stream.hpp
2/*
3 * Copyright (c) 2007 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
39#include <stdexcept>
40#include <vector>
43#include <neolib/task/event.hpp>
48
49namespace neolib
50{
51 template <typename PacketType, typename Protocol, size_t ReceiveBufferSize = 1024>
52 class packet_stream : public lifetime<>, private i_basic_packet_connection_owner<typename PacketType::character_type>
53 {
54 // types
55 public:
56 typedef PacketType packet_type;
57 typedef Protocol protocol_type;
58 typedef std::unique_ptr<packet_stream> pointer;
60 typedef typename packet_type::clone_pointer packet_clone_pointer;
62 typedef std::unique_ptr<packet_type> queue_item;
63 typedef std::unique_ptr<packet_type> orphaned_queue_item;
64 typedef std::vector<queue_item> send_queue;
65
66 // events
67 public:
68 define_event(ConnectionEstablished, connection_established)
69 define_event(ConnectionFailure, connection_failure, const boost::system::error_code&)
70 define_event(PacketSent, packet_sent, const packet_type&)
71 define_event(PacketArrived, packet_arrived, const packet_type&)
72 define_event(TransferFailure, transfer_failure, const boost::system::error_code&)
73 define_event(ConnectionClosed, connection_closed)
74
75 // construction
76 public:
77 packet_stream(i_async_task& aIoTask, bool aSecure = false, protocol_family aProtocolFamily = IPv4) :
78 iConnection(aIoTask, *this, aSecure, aProtocolFamily)
79 {
80 }
81 packet_stream(i_async_task& aIoTask, const std::string& aHostName, unsigned short aPort, bool aSecure = false, protocol_family aProtocolFamily = IPv4) :
82 iConnection(aIoTask, *this, aHostName, aPort, aSecure, aProtocolFamily)
83 {
84 }
86 {
87 remove_all_packets();
88 }
89 packet_stream(const packet_stream& aRhs) = delete;
90 packet_stream& operator=(const packet_stream& aRhs) = delete;
91
92 // operations
93 public:
94 bool open(const std::string& aRemoteHostName, unsigned short aRemotePort, bool aSecure = false, protocol_family aProtocolFamily = IPv4)
95 {
96 return iConnection.open(aRemoteHostName, aRemotePort, aSecure, aProtocolFamily);
97 }
98 bool opened() const
99 {
100 return iConnection.opened();
101 }
102 void close()
103 {
104 remove_all_packets();
105 iConnection.close();
106 }
107 void send_packet(const packet_type& aPacket, bool aHighPriority = false)
108 {
109 iSendQueue.push_back(std::make_unique<packet_type>(aPacket));
110 iConnection.send_packet(*iSendQueue.back(), aHighPriority);
111 }
112 bool connected() const
113 {
114 return iConnection.connected();
115 }
116 bool closed() const
117 {
118 return iConnection.closed();
119 }
120 bool has_error() const
121 {
122 return iConnection.has_error();
123 }
124 std::string error() const
125 {
126 return iConnection.error().message();
127 }
128 int error_code() const
129 {
130 return iConnection.error().value();
131 }
133 {
134 return iConnection;
135 }
137 {
138 return iConnection;
139 }
140 bool underflow() const
141 {
142 return iSendQueue.empty();
143 }
144
145 // implementation
146 private:
147 // from i_basic_packet_connection_owner<typename PacketType::character_type>
148 packet_clone_pointer handle_create_empty_packet() const override
149 {
150 return packet_clone_pointer(new packet_type());
151 }
152 void handle_connection_established() override
153 {
154 ConnectionEstablished.trigger();
155 }
156 void handle_connection_failure(const boost::system::error_code& aError) override
157 {
158 ConnectionFailure.trigger(aError);
159 }
160 void handle_packet_sent(const generic_packet_type& aPacket) override
161 {
162 orphaned_queue_item sentPacket = remove_packet(static_cast<const packet_type&>(aPacket));
163 PacketSent.trigger(*sentPacket);
164 }
165 void handle_packet_arrived(const generic_packet_type& aPacket) override
166 {
167 PacketArrived.trigger(static_cast<const packet_type&>(aPacket));
168 }
169 void handle_transfer_failure(const generic_packet_type& aPacket, const boost::system::error_code& aError) override
170 {
171 orphaned_queue_item failedPacket = remove_packet(static_cast<const packet_type&>(aPacket));
172 TransferFailure.trigger(aError);
173 }
174 void handle_connection_closed() override
175 {
176 ConnectionClosed.trigger();
177 }
178 orphaned_queue_item remove_packet(const packet_type& aPacket)
179 {
180 orphaned_queue_item removedPacket;
181 for (auto i = iSendQueue.begin(); i != iSendQueue.end(); ++i)
182 if (&**i == &aPacket)
183 {
184 removedPacket = std::move(*i);
185 iSendQueue.erase(i);
186 return removedPacket;
187 }
188 return removedPacket;
189 }
190 void remove_all_packets()
191 {
192 iSendQueue.clear();
193 }
194 // attributes
195 private:
196 send_queue iSendQueue;
197 connection_type iConnection;
198 };
199
202}
i_basic_packet< typename packet_type::character_type > generic_packet_type
packet_type::clone_pointer packet_clone_pointer
packet_stream & operator=(const packet_stream &aRhs)=delete
packet_stream(const packet_stream &aRhs)=delete
define_event(ConnectionEstablished, connection_established) define_event(ConnectionFailure
const boost::system::error_code packet_arrived
basic_packet_connection< typename packet_type::character_type, Protocol, ReceiveBufferSize > connection_type
packet_stream(i_async_task &aIoTask, const std::string &aHostName, unsigned short aPort, bool aSecure=false, protocol_family aProtocolFamily=IPv4)
const connection_type & connection() const
connection_type & connection()
bool open(const std::string &aRemoteHostName, unsigned short aRemotePort, bool aSecure=false, protocol_family aProtocolFamily=IPv4)
std::unique_ptr< packet_stream > pointer
std::unique_ptr< packet_type > orphaned_queue_item
std::unique_ptr< packet_type > queue_item
std::string error() const
void send_packet(const packet_type &aPacket, bool aHighPriority=false)
std::vector< queue_item > send_queue
packet_stream< binary_packet, tcp_protocol > tcp_binary_packet_stream
protocol_family
Definition resolver.hpp:52
packet_stream< string_packet, tcp_protocol > tcp_string_packet_stream
#define define_event(name, declName,...)
Definition event.hpp:200