Skip to content

Commit 66325f9

Browse files
committed
Polymorphic codecs and transports
New features: - Session is now a move-only type that can be instantiated on the stack. - Deprecated Session::create. - Added ConnectionWish and ConnectionWishList which should now be used in place of the old Connection and ConnectionList classes. - Passing ConnectionWish and ConnectionWishList via Session::connect is now preferred over passing the legacy Connector instances via Session::create. - TcpHost and UdsPath now have withFormat methods which generate a ConnectionWish that can be passed to Session. - The authenticate, publish, yield, and cancel methods of Session not taking a completion handler now return an ErrorOrDone. The thread-safe overloads for those now return a `std::future<ErrorOrDone>`. - AnyCompletionExecutor is now used by session to contain the user executor. - Added Session::ongoingCall for progressive call results, which automatically applies rpc.withProgessiveResults(true). - Renamed Session::reset to Session::terminate, leaving the former as a deprecated alias. - Renamed Session::userExecutor to Session::fallbackExecutor, leaving the former as a deprecated alias. - Session::fallbackExecutor type relaxed to AnyCompletionExecutor. - Handlers registered via Session's setWarningHandler, setTraceHandler, and setStateChangeHandler will no longer be fired after Session::terminate is called and before Session::connect is called. - Added wamp::spawn and wamp::YieldContext in <cppwamp/spawn.hpp>, which are aliases to their Boost.Asio counterparts. - Added wamp::spawnCompletionHandler and wamp::CompletionYieldContext to support spawning coroutines via Event::executor and Invocation::executor. - When CPPWAMP_USE_COMPLETION_YIELD_CONTEXT is defined, wamp::BasicYieldContext<wamp::AnyCompletionExecutor> will be passed to coroutines spawned via Event/Invocation unpackers. The relaxes the requirement that the Session::userExecutor() originate from boost::asio::io_context. - When CPPWAMP_USE_COMPLETION_YIELD_CONTEXT and ASIO_DISABLE_BOOST_COROUTINE are defined, the coroutine Event/Invocation unpackers will use the new Boost.Context-based coroutines introduced in Boost 1.80.0. - Instead of throwing an exception, Session now emits a TransportErrc::badTxLength error via the completion handler or return value when the payload exceeds the transport's limit. - Challenge::authenticate, Invocation::yield and Interruption::yield now have thread-safe and non-thread-safe overloads. - Added SessionErrc error codes corresponding to new predefined error URIs that have appeared in the WAMP spec. - Added Session::setLogHandler which takes a handler of type 'void (LogEntry)' and unifies all log event handling. - Added Session::setLogLevel for use with Session::setLogHandler. - Renamed AsioContext to IoContext, leaving the former as a deprecated alias. - Deprecated AsioErrorCode. - Deprecated ProtocolErrc and ProtocolCategory in favor of SessionErrc::protocolViolation. - Deprecated Session::setWarningHandler and Session::setTraceHandler in favor of Session::setLogHandler. Implementation improvements: - Adding more codecs or transports in the future will no longer result in a combinatorial explosion of explicit template instantions due to the number of transport/codec combinations. - Codecs are now specializations of SinkEncoder and SourceDecoder. - Simplified codec tags to only provide their numeric ID. - Added AnyCodec polymorphic wrapper for codecs. - Added Transporting interface class which replaces the old Transport type requirement. - internal::Client is now non-templated and is retained by Session during the latter's lifetime. - Session::connect logic has been moved to internal::Client. - Renamed internal::AsioTransport to internal::RawsockTransport and simplified its previously convoluted design. - internal::RawsockConnector and internal::RawsockTransport now use policy classes instead of polymorphism to alter their behavior for tests. - Tidying of transport tests. - internal::Peer composition instead of inheritance. - Avoid unnecessary boost::asio::post in intermediate handlers. Beaking Changes: - Session::call can no longer be used for progessive call results, use Session::ongoingCall instead. - The Session destructor now automatically invokes Session::disconnect instead of Session::terminate, to better emulate the cancellation behavior of Asio sockets being destroyed. - Event::executor and Invocation::executor can no longer be directly used by Boost.Coroutine-based boost::asio::spawn to spawn coroutines. - The undecorated Challenge::authenticate, Invocation::yield and Interruption::yield are no longer thread-safe.
1 parent 29153f6 commit 66325f9

File tree

107 files changed

+8858
-6681
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+8858
-6681
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ cmake_minimum_required (VERSION 3.12)
3838
include_guard()
3939

4040
project(CppWAMP
41-
VERSION 0.10.0
41+
VERSION 0.11.0
4242
LANGUAGES CXX)
4343

4444
include(ProcessorCount)

README.md

Lines changed: 76 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,13 @@ This library has been tested with:
7171
Roadmap
7272
-------
7373

74-
### v0.11
75-
76-
- Polymorphic codecs and transports to prevent combinatorial explosion of
77-
explicit template instantiations when new codecs/transports are added.
78-
7974
### v1.0
8075

76+
- Embedded router functionality
8177
- Remove all deprecated types and functions.
8278
- Aim for API stability until v2.0.
8379

84-
### v1.1
85-
86-
- Embedded router functionality
87-
88-
### v1.2 (maybe)
80+
### v1.1 (maybe)
8981

9082
- Websocket support via Boost.Beast
9183

@@ -119,37 +111,39 @@ documentation._
119111
### Establishing a WAMP session
120112
```c++
121113
wamp::AsioContext ioctx;
122-
boost::asio::spawn(ioctx, [&](boost::asio::yield_context yield)
123-
{
124-
// Specify a TCP transport and JSON serialization
125-
auto tcp = wamp::connector<wamp::Json>(
126-
ioctx, wamp::TcpHost("localhost", 8001));
127-
auto session = wamp::CoroSession<>::create(ioctx, tcp);
128-
session->connect(yield);
129-
auto sessionInfo = session->join(wamp::Realm("myrealm"), yield);
130-
std::cout << "Client joined. Session ID = "
131-
<< sessionInfo.id() << "\n";
132-
// etc.
133-
});
114+
wamp::Session session(ioctx);
115+
wamp::spawn(
116+
ioctx,
117+
[&](wamp::YieldContext yield)
118+
{
119+
auto tcp = wamp::TcpHost("localhost", 8001).withFormat(wamp::json);
120+
session.connect(tcp, yield).value();
121+
auto sessionInfo = session.join(wamp::Realm("myrealm"), yield).value();
122+
std::cout << "Client joined. Session ID = "
123+
<< sessionInfo.id() << "\n";
124+
// etc.
125+
});
134126
ioctx.run();
135127
```
136128
137129
### Registering a remote procedure
138130
```c++
139-
boost::asio::spawn(ioctx, [&](boost::asio::yield_context yield)
140-
{
141-
:::
142-
session->enroll(wamp::Procedure("add"),
143-
wamp::basicRpc<int, int, int>(
144-
[](int n, int m) -> int {return n+m;}),
145-
yield);
146-
:::
147-
});
131+
wamp::spawn(
132+
ioctx,
133+
[&](wamp::YieldContext yield)
134+
{
135+
:::
136+
session.enroll(wamp::Procedure("add"),
137+
wamp::simpleRpc<int, int, int>(
138+
[](int n, int m) -> int {return n+m;}),
139+
yield).value();
140+
:::
141+
});
148142
```
149143

150144
### Calling a remote procedure
151145
```c++
152-
auto result = session->call(wamp::Rpc("add").withArgs(2, 2), yield);
146+
auto result = session.call(wamp::Rpc("add").withArgs(2, 2), yield).value();
153147
std::cout << "2 + 2 is " << result[0].to<int>() << "\n";
154148
```
155149

@@ -160,20 +154,22 @@ void sensorSampled(float value)
160154
std::cout << "Sensor sampled, value = " << value << "\n";
161155
}
162156

163-
boost::asio::spawn(ioctx, [&](boost::asio::yield_context yield)
164-
{
165-
:::
166-
session->subscribe(wamp::Topic("sensorSampled"),
167-
wamp::basicEvent<float>(&sensorSampled),
168-
yield);
169-
:::
170-
});
157+
wamp::spawn(
158+
ioctx,
159+
[&](wamp::YieldContext yield)
160+
{
161+
:::
162+
session.subscribe(wamp::Topic("sensorSampled"),
163+
wamp::simpleEvent<float>(&sensorSampled),
164+
yield).value();
165+
:::
166+
});
171167
```
172168
173169
### Publishing an event
174170
```c++
175171
float value = std::rand() % 10;
176-
session->publish(wamp::Pub("sensorSampled").withArgs(value));
172+
session.publish(wamp::Pub("sensorSampled").withArgs(value));
177173
```
178174

179175

@@ -185,25 +181,24 @@ Usage Examples Using Asynchronous Callbacks
185181
class App : public std::enable_shared_from_this<App>
186182
{
187183
public:
188-
void start(wamp::AnyExecutor executor)
189-
{
190-
// Specify a TCP transport and JSON serialization
191-
auto tcp = wamp::connector<wamp::Json>(
192-
executor, wamp::TcpHost("localhost", 8001));
193-
194-
session_ = wamp::Session::create(executor, tcp);
184+
App(wamp::AnyIoExecutor exec)
185+
: session_(std::move(exec))
186+
{}
195187

188+
void start(wamp::ConnectionWish where)
189+
{
196190
// `self` is used to ensure the App instance still exists
197191
// when the callback is invoked.
198192
auto self = shared_from_this();
199193

200194
// Perform the connection, then chain to the next operation.
201-
session_->connect(
202-
[this, self](wamp::AsyncResult<size_t> result)
195+
session_.connect(
196+
where,
197+
[this, self](wamp::ErrorOr<size_t> result)
203198
{
204199
// 'result' contains the index of the connector used to
205200
// establish the connection, or an error
206-
result.get(); // Throws if result contains an error
201+
result.value(); // Throws if result contains an error
207202
onConnect();
208203
});
209204
}
@@ -212,11 +207,11 @@ private:
212207
void onConnect()
213208
{
214209
auto self = shared_from_this();
215-
session_->join(
210+
session_.join(
216211
wamp::Realm("myrealm"),
217-
[this, self](wamp::AsyncResult<wamp::SessionInfo> info)
212+
[this, self](wamp::ErrorOr<wamp::SessionInfo> info)
218213
{
219-
onJoin(info.get());
214+
onJoin(info.value());
220215
});
221216
}
222217

@@ -227,14 +222,14 @@ private:
227222
// etc...
228223
}
229224

230-
wamp::Session::Ptr session_;
225+
wamp::Session session_;
231226
};
232227

233228
int main()
234229
{
235230
wamp::AsioContext ioctx;
236-
App app;
237-
app.start(ioctx.get_executor());
231+
App app(ioctx.get_executor());
232+
app.start(wamp::TcpHost("localhost", 8001).withFormat(wamp::json);
238233
ioctx.run();
239234
}
240235

@@ -245,22 +240,23 @@ int main()
245240
class App : public std::shared_from_this<App>
246241
{
247242
public:
248-
void start(wamp::AnyExecutor executor) {/* As above */}
243+
App(wamp::AnyIoExecutor exec); // As above
244+
void start(wamp::ConnectionWish where); // As above
249245

250246
private:
251247
static int add(int n, int m) {return n + m;}
252248

253-
void onConnect() {/* As above */}
249+
void onConnect(); // As above
254250

255251
void onJoin(wamp::SessionInfo)
256252
{
257253
auto self = shared_from_this();
258-
session_->enroll(
254+
session_.enroll(
259255
wamp::Procedure("add"),
260-
wamp::basicRpc<int, int, int>(&App::add),
261-
[this, self](AsyncResult<Registration> reg)
256+
wamp::simpleRpc<int, int, int>(&App::add),
257+
[this, self](wamp::ErrorOr<Registration> reg)
262258
{
263-
onRegistered(reg.get());
259+
onRegistered(reg.value());
264260
});
265261
}
266262

@@ -269,7 +265,7 @@ private:
269265
// etc
270266
}
271267

272-
wamp::Session::Ptr session_;
268+
wamp::Session session_;
273269
};
274270

275271
```
@@ -279,19 +275,20 @@ private:
279275
class App : public std::shared_from_this<App>
280276
{
281277
public:
282-
void start(wamp::AnyExecutor executor) {/* As above */}
278+
App(wamp::AnyIoExecutor exec); // As above
279+
void start(wamp::ConnectionWish where); // As above
283280
284281
private:
285-
void onConnect() {/* As above */}
282+
void onConnect(); // As above
286283
287284
void onJoin(wamp::SessionInfo info)
288285
{
289286
auto self = shared_from_this();
290-
session_->call(
287+
session_.call(
291288
wamp::Rpc("add").withArgs(2, 2),
292-
[this, self](wamp::AsyncResult<wamp::Result> sum)
289+
[this, self](wamp::ErrorOr<wamp::Result> sum)
293290
{
294-
onAdd(sum.get());
291+
onAdd(sum.value());
295292
});
296293
}
297294
@@ -300,7 +297,7 @@ private:
300297
std::cout << "2 + 2 is " << result[0].to<int>() << "\n";
301298
}
302299
303-
wamp::Session::Ptr session_;
300+
wamp::Session session_;
304301
};
305302
```
306303

@@ -309,25 +306,26 @@ private:
309306
class App : public std::shared_from_this<App>
310307
{
311308
public:
312-
void start(wamp::AnyExecutor executor) {/* As above */}
309+
App(wamp::AnyIoExecutor exec); // As above
310+
void start(wamp::ConnectionWish where); // As above
313311

314312
private:
315313
static void sensorSampled(float value)
316314
{
317315
std::cout << "Sensor sampled, value = " << value << "\n";
318316
}
319317

320-
void onConnect() {/* As above */}
318+
void onConnect(); // As above
321319

322320
void onJoin(wamp::SessionInfo info)
323321
{
324322
auto self = shared_from_this();
325-
session_->subscribe(
323+
session_.subscribe(
326324
wamp::Topic("sensorSampled"),
327-
wamp::basicEvent<float>(&App::sensorSampled),
328-
[this, self](wamp::AsyncResult<wamp::Subscription> sub)
325+
wamp::simpleEvent<float>(&App::sensorSampled),
326+
[this, self](wamp::ErrorOr<wamp::Subscription> sub)
329327
{
330-
onSubscribed(sub.get());
328+
onSubscribed(sub.value());
331329
});
332330
}
333331

@@ -336,14 +334,14 @@ private:
336334
std::cout << "Subscribed, subscription ID = " << sub.id() << "\n";
337335
}
338336

339-
wamp::Session::Ptr session_;
337+
wamp::Session session_;
340338
};
341339
```
342340
343341
### Publishing an event
344342
```c++
345343
float value = std::rand() % 10;
346-
session_->publish(wamp::Pub("sensorSampled").withArgs(value));
344+
session_.publish(wamp::Pub("sensorSampled").withArgs(value));
347345
```
348346

349347

cmake/CppWAMPDependencies.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ set(CPPWAMP_VENDORIZED_BOOST_VERSION 1.79.0)
1616
set(CPPWAMP_VENDORIZED_BOOST_SHA256
1717
"475d589d51a7f8b3ba2ba4eda022b170e562ca3b760ee922c146b6c65856ef39")
1818

19+
# Stackful coroutines have a bug in Boost 1.80.0
20+
# https://github.com/chriskohlhoff/asio/issues/1110
21+
#set(CPPWAMP_VENDORIZED_BOOST_VERSION 1.80.0)
22+
#set(CPPWAMP_VENDORIZED_BOOST_SHA256
23+
# "1e19565d82e43bc59209a168f5ac899d3ba471d55c7610c677d4ccf2c9c500c0")
24+
1925
string(REPLACE "." "_" CPPWAMP_BOOST_FILE_STEM "boost_${CPPWAMP_VENDORIZED_BOOST_VERSION}")
2026
string(CONCAT CPPWAMP_BOOST_URL
2127
"https://boostorg.jfrog.io/artifactory/main/release/"

0 commit comments

Comments
 (0)