[DEV] set websocket support the reconnection to an other server after http rediredt event
This commit is contained in:
parent
6ec43d60ed
commit
c653ed5b4b
@ -43,6 +43,14 @@ enet::WebSocket::WebSocket(enet::Tcp _connection, bool _isServer) :
|
|||||||
setInterface(etk::move(_connection), _isServer);
|
setInterface(etk::move(_connection), _isServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const etk::String& enet::WebSocket::getRemoteAddress() const {
|
||||||
|
if (m_interface == nullptr) {
|
||||||
|
static const etk::String tmpOut;
|
||||||
|
return tmpOut;
|
||||||
|
}
|
||||||
|
return m_interface->getRemoteAddress();
|
||||||
|
}
|
||||||
|
|
||||||
void enet::WebSocket::setInterface(enet::Tcp _connection, bool _isServer) {
|
void enet::WebSocket::setInterface(enet::Tcp _connection, bool _isServer) {
|
||||||
_connection.setTCPNoDelay(true);
|
_connection.setTCPNoDelay(true);
|
||||||
if (_isServer == true) {
|
if (_isServer == true) {
|
||||||
@ -92,8 +100,12 @@ void enet::WebSocket::start(const etk::String& _uri, const etk::Vector<etk::Stri
|
|||||||
ENET_ERROR("Nullptr interface ...");
|
ENET_ERROR("Nullptr interface ...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (m_interface->isServer() == true) {
|
||||||
|
m_interface->start();
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
m_redirectInProgress = false;
|
||||||
m_interface->start();
|
m_interface->start();
|
||||||
if (m_interface->isServer() == false) {
|
|
||||||
enet::HttpRequest req(enet::HTTPReqType::HTTP_GET);
|
enet::HttpRequest req(enet::HTTPReqType::HTTP_GET);
|
||||||
req.setProtocol(enet::HTTPProtocol::http_1_1);
|
req.setProtocol(enet::HTTPProtocol::http_1_1);
|
||||||
req.setUri(_uri);
|
req.setUri(_uri);
|
||||||
@ -122,20 +134,28 @@ void enet::WebSocket::start(const etk::String& _uri, const etk::Vector<etk::Stri
|
|||||||
if (interface != nullptr) {
|
if (interface != nullptr) {
|
||||||
interface->setHeader(req);
|
interface->setHeader(req);
|
||||||
int32_t timeout = 500000; // 5 second
|
int32_t timeout = 500000; // 5 second
|
||||||
while (timeout>=0) {
|
while ( timeout>=0
|
||||||
|
&& m_redirectInProgress == false) {
|
||||||
if ( m_connectionValidate == true
|
if ( m_connectionValidate == true
|
||||||
|| m_interface->isAlive() == false) {
|
|| m_interface->isAlive() == false) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ethread::sleepMilliSeconds((10));
|
ethread::sleepMilliSeconds(10);
|
||||||
timeout--;
|
timeout--;
|
||||||
}
|
}
|
||||||
|
if (m_redirectInProgress == true) {
|
||||||
|
ENET_WARNING("Request a redirection (wait 500ms)");
|
||||||
|
ethread::sleepMilliSeconds(500);
|
||||||
|
ENET_WARNING("Request a redirection (wait-end)");
|
||||||
|
} else {
|
||||||
if ( m_connectionValidate == false
|
if ( m_connectionValidate == false
|
||||||
|| m_interface->isAlive() == false) {
|
|| m_interface->isAlive() == false) {
|
||||||
ENET_ERROR("Connection refused by SERVER ...");
|
ENET_ERROR("Connection refused by SERVER ...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} while (m_redirectInProgress == true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void enet::WebSocket::stop(bool _inThread) {
|
void enet::WebSocket::stop(bool _inThread) {
|
||||||
@ -370,9 +390,22 @@ void enet::WebSocket::onReceiveRequest(const enet::HttpRequest& _data) {
|
|||||||
listProtocol[iii] = removeStartAndStopSpace(listProtocol[iii]);
|
listProtocol[iii] = removeStartAndStopSpace(listProtocol[iii]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_observerUriCheck != nullptr) {
|
if (m_observerUriCheck != nullptr) {
|
||||||
if (m_observerUriCheck(_data.getUri(), listProtocol) == false) {
|
etk::String ret = m_observerUriCheck(_data.getUri(), listProtocol);
|
||||||
|
if (ret == "OK") {
|
||||||
|
// Nothing to do
|
||||||
|
} else if (ret.startWith("REDIRECT:") == true) {
|
||||||
|
ENET_INFO("Request redirection of HTTP/WebSocket connection to : '" << ret.extract(9, ret.size()) << "'");
|
||||||
|
enet::HttpAnswer answer(enet::HTTPAnswerCode::c307_temporaryRedirect);
|
||||||
|
answer.setProtocol(enet::HTTPProtocol::http_1_1);
|
||||||
|
answer.setKey("Location", ret.extract(9, ret.size()));
|
||||||
|
interface->setHeader(answer);
|
||||||
|
interface->stop(true);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (ret != "CLOSE") {
|
||||||
|
ENET_ERROR("UNKNOW return type of URI request: '" << ret << "'");
|
||||||
|
}
|
||||||
enet::HttpAnswer answer(enet::HTTPAnswerCode::c404_notFound);
|
enet::HttpAnswer answer(enet::HTTPAnswerCode::c404_notFound);
|
||||||
answer.setProtocol(enet::HTTPProtocol::http_1_1);
|
answer.setProtocol(enet::HTTPProtocol::http_1_1);
|
||||||
answer.setKey("Connection", "close");
|
answer.setKey("Connection", "close");
|
||||||
@ -399,6 +432,14 @@ void enet::WebSocket::onReceiveAnswer(const enet::HttpAnswer& _data) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_data.display();
|
_data.display();
|
||||||
|
if (_data.getErrorCode() == enet::HTTPAnswerCode::c307_temporaryRedirect) {
|
||||||
|
ENET_ERROR("Request connection redirection to '" << _data.getKey("Location") << "'");
|
||||||
|
// We are a client mode, we need to recreate a TCP connection on the new remote interface
|
||||||
|
// This is the generic way to accept a redirection
|
||||||
|
m_redirectInProgress = true;
|
||||||
|
m_interface->redirectTo(_data.getKey("Location"), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_data.getErrorCode() != enet::HTTPAnswerCode::c101_switchingProtocols) {
|
if (_data.getErrorCode() != enet::HTTPAnswerCode::c101_switchingProtocols) {
|
||||||
ENET_ERROR("change protocol has not been accepted ... " << _data.getErrorCode() << " with message : " << _data.getHelp());
|
ENET_ERROR("change protocol has not been accepted ... " << _data.getErrorCode() << " with message : " << _data.getHelp());
|
||||||
m_interface->stop(true);
|
m_interface->stop(true);
|
||||||
|
@ -22,6 +22,7 @@ namespace enet {
|
|||||||
echrono::Steady m_lastReceive;
|
echrono::Steady m_lastReceive;
|
||||||
echrono::Steady m_lastSend;
|
echrono::Steady m_lastSend;
|
||||||
ethread::Mutex m_mutex;
|
ethread::Mutex m_mutex;
|
||||||
|
bool m_redirectInProgress = false;
|
||||||
public:
|
public:
|
||||||
const echrono::Steady& getLastTimeReceive() {
|
const echrono::Steady& getLastTimeReceive() {
|
||||||
return m_lastReceive;
|
return m_lastReceive;
|
||||||
@ -51,6 +52,12 @@ namespace enet {
|
|||||||
void setProtocol(const etk::String& _protocol) {
|
void setProtocol(const etk::String& _protocol) {
|
||||||
m_protocol = _protocol;
|
m_protocol = _protocol;
|
||||||
}
|
}
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Get the address of the connection source IP:port or empty string
|
||||||
|
* @return string with the remote address name.
|
||||||
|
*/
|
||||||
|
const etk::String& getRemoteAddress() const;
|
||||||
public:
|
public:
|
||||||
using Observer = etk::Function<void(etk::Vector<uint8_t>&, bool)>; //!< Define an Observer: function pointer
|
using Observer = etk::Function<void(etk::Vector<uint8_t>&, bool)>; //!< Define an Observer: function pointer
|
||||||
protected:
|
protected:
|
||||||
@ -73,7 +80,15 @@ namespace enet {
|
|||||||
}
|
}
|
||||||
// Only server:
|
// Only server:
|
||||||
public:
|
public:
|
||||||
using ObserverUriCheck = etk::Function<bool(const etk::String&, const etk::Vector<etk::String>&)>; //!< Define an Observer: function pointer
|
/**
|
||||||
|
* @brief Define an Observer: function pointer
|
||||||
|
* @param[in] _uri Current HTTP URI
|
||||||
|
* @param[in] _protocols List of protocol requested
|
||||||
|
* @return "OK" Connection accepted ==> send header
|
||||||
|
* @return "CLOSE" Close the current connection: 404
|
||||||
|
* @return "REDIRECT:IP:port" Redirect at the specific IP and port
|
||||||
|
*/
|
||||||
|
using ObserverUriCheck = etk::Function<etk::String(const etk::String&, const etk::Vector<etk::String>&)>;
|
||||||
protected:
|
protected:
|
||||||
ObserverUriCheck m_observerUriCheck;
|
ObserverUriCheck m_observerUriCheck;
|
||||||
public:
|
public:
|
||||||
@ -84,7 +99,7 @@ namespace enet {
|
|||||||
* @param[in] _args Argument optinnal the user want to add.
|
* @param[in] _args Argument optinnal the user want to add.
|
||||||
*/
|
*/
|
||||||
template<class CLASS_TYPE>
|
template<class CLASS_TYPE>
|
||||||
void connectUri(CLASS_TYPE* _class, bool (CLASS_TYPE::*_func)(const etk::String&, const etk::Vector<etk::String>&)) {
|
void connectUri(CLASS_TYPE* _class, etk::String (CLASS_TYPE::*_func)(const etk::String&, const etk::Vector<etk::String>&)) {
|
||||||
m_observerUriCheck = [=](const etk::String& _value, const etk::Vector<etk::String>& _protocols){
|
m_observerUriCheck = [=](const etk::String& _value, const etk::Vector<etk::String>& _protocols){
|
||||||
return (*_class.*_func)(_value, _protocols);
|
return (*_class.*_func)(_value, _protocols);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user