WebSocketConnector::connectAsync functionality

This commit is contained in:
lganzzzo 2019-01-14 15:03:16 +02:00
parent 8f542a6f11
commit 5b12f1a92f
4 changed files with 73 additions and 17 deletions

View File

@ -28,7 +28,7 @@
namespace oatpp { namespace web { namespace client {
std::shared_ptr<WebSocketConnector::IOStream> WebSocketConnector::connectAndHandshake(const oatpp::String& path) {
std::shared_ptr<WebSocketConnector::Connection> WebSocketConnector::connect(const oatpp::String& path) {
auto connection = m_connectionProvider->getConnection();
auto connectionHandle = std::make_shared<HttpRequestExecutor::HttpConnectionHandle>(connection);
@ -52,12 +52,67 @@ std::shared_ptr<WebSocketConnector::IOStream> WebSocketConnector::connectAndHand
}
WebSocketConnector::WebSocket WebSocketConnector::connect(const oatpp::String& path) {
return WebSocket(connectAndHandshake(path), true);
oatpp::async::Action WebSocketConnector::connectAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
AsyncCallback callback,
const oatpp::String& path)
{
class ConnectCoroutine : public oatpp::async::CoroutineWithResult<ConnectCoroutine, const std::shared_ptr<Connection>&> {
private:
std::shared_ptr<oatpp::network::ClientConnectionProvider> m_connectionProvider;
HttpRequestExecutor m_requestExecutor;
oatpp::String m_path;
std::shared_ptr<Connection> m_connection;
protocol::websocket::Handshaker::Headers m_handshakeHeaders;
public:
ConnectCoroutine(const std::shared_ptr<oatpp::network::ClientConnectionProvider>& connectionProvider,
const HttpRequestExecutor& requestExecutor,
const oatpp::String path)
: m_connectionProvider(connectionProvider)
, m_requestExecutor(requestExecutor)
, m_path(path)
{}
Action act() override {
oatpp::network::ClientConnectionProvider::AsyncCallback callback =
static_cast<oatpp::network::ClientConnectionProvider::AsyncCallback>(&ConnectCoroutine::onConnected);
return m_connectionProvider->getConnectionAsync(this, callback);
}
std::shared_ptr<WebSocketConnector::WebSocket> WebSocketConnector::connectShared(const oatpp::String& path) {
return std::make_shared<WebSocketConnector::WebSocket>(connectAndHandshake(path), true);
Action onConnected(const std::shared_ptr<Connection>& connection) {
m_connection = connection;
auto connectionHandle = std::make_shared<HttpRequestExecutor::HttpConnectionHandle>(m_connection);
m_handshakeHeaders.clear();
protocol::websocket::Handshaker::clientsideHandshake(m_handshakeHeaders);
oatpp::web::client::RequestExecutor::AsyncCallback callback =
static_cast<oatpp::web::client::RequestExecutor::AsyncCallback>(&ConnectCoroutine::onServerResponse);
return m_requestExecutor.executeAsync(this, callback, "GET", m_path, m_handshakeHeaders, nullptr, connectionHandle);
}
Action onServerResponse(const std::shared_ptr<protocol::http::incoming::Response>& response) {
auto res = protocol::websocket::Handshaker::clientsideConfirmHandshake(m_handshakeHeaders, response);
if(res == protocol::websocket::Handshaker::STATUS_OK) {
return _return(m_connection);
} else if(res == protocol::websocket::Handshaker::STATUS_SERVER_ERROR) {
throw std::runtime_error("[oatpp::web::client::WebSocketConnector::connectAsync(){ConnectCoroutine}]: Server responded with invalid code");
} else if(res == protocol::websocket::Handshaker::STATUS_SERVER_WRONG_KEY) {
throw std::runtime_error("[oatpp::web::client::WebSocketConnector::connectAsync(){ConnectCoroutine}]: Server wrong handshake key");
} else if(res == protocol::websocket::Handshaker::STATUS_UNKNOWN_PROTOCOL_SUGGESTED) {
throw std::runtime_error("[oatpp::web::client::WebSocketConnector::connectAsync(){ConnectCoroutine}]: Server response contains unexpected headers");
} else {
throw std::runtime_error("[oatpp::web::client::WebSocketConnector::connectAsync(){ConnectCoroutine}]: Unknown error");
}
}
};
return parentCoroutine->startCoroutineForResult<ConnectCoroutine>(callback, m_connectionProvider, m_requestExecutor, path);
}
}}}

View File

@ -33,19 +33,17 @@ namespace oatpp { namespace web { namespace client {
class WebSocketConnector {
public:
typedef protocol::websocket::WebSocket WebSocket;
typedef oatpp::data::stream::IOStream IOStream;
typedef oatpp::data::stream::IOStream Connection;
typedef oatpp::async::Action Action;
typedef Action (oatpp::async::AbstractCoroutine::*AsyncCallback)(const std::shared_ptr<Connection>&);
private:
std::shared_ptr<oatpp::network::ClientConnectionProvider> m_connectionProvider;
HttpRequestExecutor m_requestExecutor;
private:
std::shared_ptr<IOStream> connectAndHandshake(const oatpp::String& path);
public:
WebSocketConnector(const std::shared_ptr<oatpp::network::ClientConnectionProvider>& connectionProvider)
: m_connectionProvider(connectionProvider)
, m_requestExecutor(connectionProvider)
{}
public:
static std::shared_ptr<WebSocketConnector> createShared(const std::shared_ptr<oatpp::network::ClientConnectionProvider>& connectionProvider) {
@ -53,15 +51,18 @@ public:
}
/**
* Connect to server, do websocket-handshake and return WebSocket
* Connect to server, do websocket-handshake and return Connection which can be then passed to
* WebSocket constructor
* (Blocking call)
*/
WebSocket connect(const oatpp::String& path);
std::shared_ptr<Connection> connect(const oatpp::String& path);
/**
* Same as connect() but return std::shared_ptr<WebSocket>
* Connect to server, do websocket-handshake and return Connection which can be then passed to
* WebSocket constructor
* (Async call)
*/
std::shared_ptr<WebSocket> connectShared(const oatpp::String& path);
Action connectAsync(oatpp::async::AbstractCoroutine* parentCoroutine, AsyncCallback callback, const oatpp::String& path);
};

View File

@ -100,7 +100,7 @@ RequestHeadersReader::Action RequestHeadersReader::readHeadersAsync(oatpp::async
const std::shared_ptr<oatpp::data::stream::IOStream>& connection)
{
class ReaderCoroutine : public oatpp::async::CoroutineWithResult<ReaderCoroutine, Result> {
class ReaderCoroutine : public oatpp::async::CoroutineWithResult<ReaderCoroutine, const Result&> {
private:
std::shared_ptr<oatpp::data::stream::IOStream> m_connection;
p_char8 m_buffer;

View File

@ -100,7 +100,7 @@ ResponseHeadersReader::Action ResponseHeadersReader::readHeadersAsync(oatpp::asy
const std::shared_ptr<oatpp::data::stream::IOStream>& connection)
{
class ReaderCoroutine : public oatpp::async::CoroutineWithResult<ReaderCoroutine, Result> {
class ReaderCoroutine : public oatpp::async::CoroutineWithResult<ReaderCoroutine, const Result&> {
private:
std::shared_ptr<oatpp::data::stream::IOStream> m_connection;
p_char8 m_buffer;