Expose the resource name the client used to the websocket server
This information is exposed to the websocket server through the client_connected-signal. example.com/chat?id=10 gives the resource name "/chat?id=10"
This commit is contained in:
parent
de83ee57e5
commit
1475f617a3
6 changed files with 26 additions and 21 deletions
|
@ -116,8 +116,11 @@
|
||||||
</argument>
|
</argument>
|
||||||
<argument index="1" name="protocol" type="String">
|
<argument index="1" name="protocol" type="String">
|
||||||
</argument>
|
</argument>
|
||||||
|
<argument index="2" name="resource_name" type="String">
|
||||||
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Emitted when a new client connects. "protocol" will be the sub-protocol agreed with the client.
|
Emitted when a new client connects. "protocol" will be the sub-protocol agreed with the client, and "resource_name" will be the resource name of the URI the peer used.
|
||||||
|
"resource_name" is a path (at the very least a single forward slash) and potentially a query string.
|
||||||
</description>
|
</description>
|
||||||
</signal>
|
</signal>
|
||||||
<signal name="client_disconnected">
|
<signal name="client_disconnected">
|
||||||
|
|
|
@ -56,7 +56,7 @@ Error EMWSPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
|
||||||
int is_bin = write_mode == WebSocketPeer::WRITE_MODE_BINARY ? 1 : 0;
|
int is_bin = write_mode == WebSocketPeer::WRITE_MODE_BINARY ? 1 : 0;
|
||||||
godot_js_websocket_send(peer_sock, p_buffer, p_buffer_size, is_bin);
|
godot_js_websocket_send(peer_sock, p_buffer, p_buffer_size, is_bin);
|
||||||
return OK;
|
return OK;
|
||||||
};
|
}
|
||||||
|
|
||||||
Error EMWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
|
Error EMWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
|
||||||
if (_in_buffer.packets_left() == 0)
|
if (_in_buffer.packets_left() == 0)
|
||||||
|
@ -70,19 +70,19 @@ Error EMWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
|
||||||
r_buffer_size = read;
|
r_buffer_size = read;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
};
|
}
|
||||||
|
|
||||||
int EMWSPeer::get_available_packet_count() const {
|
int EMWSPeer::get_available_packet_count() const {
|
||||||
return _in_buffer.packets_left();
|
return _in_buffer.packets_left();
|
||||||
};
|
}
|
||||||
|
|
||||||
bool EMWSPeer::was_string_packet() const {
|
bool EMWSPeer::was_string_packet() const {
|
||||||
return _is_string;
|
return _is_string;
|
||||||
};
|
}
|
||||||
|
|
||||||
bool EMWSPeer::is_connected_to_host() const {
|
bool EMWSPeer::is_connected_to_host() const {
|
||||||
return peer_sock != -1;
|
return peer_sock != -1;
|
||||||
};
|
}
|
||||||
|
|
||||||
void EMWSPeer::close(int p_code, String p_reason) {
|
void EMWSPeer::close(int p_code, String p_reason) {
|
||||||
if (peer_sock != -1) {
|
if (peer_sock != -1) {
|
||||||
|
@ -91,7 +91,7 @@ void EMWSPeer::close(int p_code, String p_reason) {
|
||||||
_is_string = 0;
|
_is_string = 0;
|
||||||
_in_buffer.clear();
|
_in_buffer.clear();
|
||||||
peer_sock = -1;
|
peer_sock = -1;
|
||||||
};
|
}
|
||||||
|
|
||||||
IPAddress EMWSPeer::get_connected_host() const {
|
IPAddress EMWSPeer::get_connected_host() const {
|
||||||
ERR_FAIL_V_MSG(IPAddress(), "Not supported in HTML5 export.");
|
ERR_FAIL_V_MSG(IPAddress(), "Not supported in HTML5 export.");
|
||||||
|
@ -99,7 +99,7 @@ IPAddress EMWSPeer::get_connected_host() const {
|
||||||
|
|
||||||
uint16_t EMWSPeer::get_connected_port() const {
|
uint16_t EMWSPeer::get_connected_port() const {
|
||||||
ERR_FAIL_V_MSG(0, "Not supported in HTML5 export.");
|
ERR_FAIL_V_MSG(0, "Not supported in HTML5 export.");
|
||||||
};
|
}
|
||||||
|
|
||||||
void EMWSPeer::set_no_delay(bool p_enabled) {
|
void EMWSPeer::set_no_delay(bool p_enabled) {
|
||||||
ERR_FAIL_MSG("'set_no_delay' is not supported in HTML5 export.");
|
ERR_FAIL_MSG("'set_no_delay' is not supported in HTML5 export.");
|
||||||
|
@ -107,10 +107,10 @@ void EMWSPeer::set_no_delay(bool p_enabled) {
|
||||||
|
|
||||||
EMWSPeer::EMWSPeer() {
|
EMWSPeer::EMWSPeer() {
|
||||||
close();
|
close();
|
||||||
};
|
}
|
||||||
|
|
||||||
EMWSPeer::~EMWSPeer() {
|
EMWSPeer::~EMWSPeer() {
|
||||||
close();
|
close();
|
||||||
};
|
}
|
||||||
|
|
||||||
#endif // JAVASCRIPT_ENABLED
|
#endif // JAVASCRIPT_ENABLED
|
||||||
|
|
|
@ -71,7 +71,7 @@ void WebSocketServer::_bind_methods() {
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("client_close_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason")));
|
ADD_SIGNAL(MethodInfo("client_close_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason")));
|
||||||
ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::BOOL, "was_clean_close")));
|
ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::BOOL, "was_clean_close")));
|
||||||
ADD_SIGNAL(MethodInfo("client_connected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "protocol")));
|
ADD_SIGNAL(MethodInfo("client_connected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "protocol"), PropertyInfo(Variant::STRING, "resource_name")));
|
||||||
ADD_SIGNAL(MethodInfo("data_received", PropertyInfo(Variant::INT, "id")));
|
ADD_SIGNAL(MethodInfo("data_received", PropertyInfo(Variant::INT, "id")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,13 +141,13 @@ void WebSocketServer::_on_peer_packet(int32_t p_peer_id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketServer::_on_connect(int32_t p_peer_id, String p_protocol) {
|
void WebSocketServer::_on_connect(int32_t p_peer_id, String p_protocol, String p_resource_name) {
|
||||||
if (_is_multiplayer) {
|
if (_is_multiplayer) {
|
||||||
// Send add to clients
|
// Send add to clients
|
||||||
_send_add(p_peer_id);
|
_send_add(p_peer_id);
|
||||||
emit_signal("peer_connected", p_peer_id);
|
emit_signal("peer_connected", p_peer_id);
|
||||||
} else {
|
} else {
|
||||||
emit_signal("client_connected", p_peer_id, p_protocol);
|
emit_signal("client_connected", p_peer_id, p_protocol, p_resource_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
virtual void disconnect_peer(int p_peer_id, int p_code = 1000, String p_reason = "") = 0;
|
virtual void disconnect_peer(int p_peer_id, int p_code = 1000, String p_reason = "") = 0;
|
||||||
|
|
||||||
void _on_peer_packet(int32_t p_peer_id);
|
void _on_peer_packet(int32_t p_peer_id);
|
||||||
void _on_connect(int32_t p_peer_id, String p_protocol);
|
void _on_connect(int32_t p_peer_id, String p_protocol, String p_resource_name);
|
||||||
void _on_disconnect(int32_t p_peer_id, bool p_was_clean);
|
void _on_disconnect(int32_t p_peer_id, bool p_was_clean);
|
||||||
void _on_close_request(int32_t p_peer_id, int p_code, String p_reason);
|
void _on_close_request(int32_t p_peer_id, int p_code, String p_reason);
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
|
|
||||||
bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) {
|
bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols, String &r_resource_name) {
|
||||||
Vector<String> psa = String((char *)req_buf).split("\r\n");
|
Vector<String> psa = String((char *)req_buf).split("\r\n");
|
||||||
int len = psa.size();
|
int len = psa.size();
|
||||||
ERR_FAIL_COND_V_MSG(len < 4, false, "Not enough response headers, got: " + itos(len) + ", expected >= 4.");
|
ERR_FAIL_COND_V_MSG(len < 4, false, "Not enough response headers, got: " + itos(len) + ", expected >= 4.");
|
||||||
|
@ -45,6 +45,7 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) {
|
||||||
// Wrong protocol
|
// Wrong protocol
|
||||||
ERR_FAIL_COND_V_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", false, "Invalid method or HTTP version.");
|
ERR_FAIL_COND_V_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", false, "Invalid method or HTTP version.");
|
||||||
|
|
||||||
|
r_resource_name = req[1];
|
||||||
Map<String, String> headers;
|
Map<String, String> headers;
|
||||||
for (int i = 1; i < len; i++) {
|
for (int i = 1; i < len; i++) {
|
||||||
Vector<String> header = psa[i].split(":", false, 1);
|
Vector<String> header = psa[i].split(":", false, 1);
|
||||||
|
@ -95,7 +96,7 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uint64_t p_timeout) {
|
Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uint64_t p_timeout, String &r_resource_name) {
|
||||||
if (OS::get_singleton()->get_ticks_msec() - time > p_timeout) {
|
if (OS::get_singleton()->get_ticks_msec() - time > p_timeout) {
|
||||||
print_verbose(vformat("WebSocket handshake timed out after %.3f seconds.", p_timeout * 0.001));
|
print_verbose(vformat("WebSocket handshake timed out after %.3f seconds.", p_timeout * 0.001));
|
||||||
return ERR_TIMEOUT;
|
return ERR_TIMEOUT;
|
||||||
|
@ -130,7 +131,7 @@ Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uin
|
||||||
int l = req_pos;
|
int l = req_pos;
|
||||||
if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') {
|
if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') {
|
||||||
r[l - 3] = '\0';
|
r[l - 3] = '\0';
|
||||||
if (!_parse_request(p_protocols)) {
|
if (!_parse_request(p_protocols, r_resource_name)) {
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
String s = "HTTP/1.1 101 Switching Protocols\r\n";
|
String s = "HTTP/1.1 101 Switching Protocols\r\n";
|
||||||
|
@ -196,8 +197,9 @@ void WSLServer::poll() {
|
||||||
|
|
||||||
List<Ref<PendingPeer>> remove_peers;
|
List<Ref<PendingPeer>> remove_peers;
|
||||||
for (List<Ref<PendingPeer>>::Element *E = _pending.front(); E; E = E->next()) {
|
for (List<Ref<PendingPeer>>::Element *E = _pending.front(); E; E = E->next()) {
|
||||||
|
String resource_name;
|
||||||
Ref<PendingPeer> ppeer = E->get();
|
Ref<PendingPeer> ppeer = E->get();
|
||||||
Error err = ppeer->do_handshake(_protocols, handshake_timeout);
|
Error err = ppeer->do_handshake(_protocols, handshake_timeout, resource_name);
|
||||||
if (err == ERR_BUSY) {
|
if (err == ERR_BUSY) {
|
||||||
continue;
|
continue;
|
||||||
} else if (err != OK) {
|
} else if (err != OK) {
|
||||||
|
@ -220,7 +222,7 @@ void WSLServer::poll() {
|
||||||
|
|
||||||
_peer_map[id] = ws_peer;
|
_peer_map[id] = ws_peer;
|
||||||
remove_peers.push_back(ppeer);
|
remove_peers.push_back(ppeer);
|
||||||
_on_connect(id, ppeer->protocol);
|
_on_connect(id, ppeer->protocol, resource_name);
|
||||||
}
|
}
|
||||||
for (List<Ref<PendingPeer>>::Element *E = remove_peers.front(); E; E = E->next()) {
|
for (List<Ref<PendingPeer>>::Element *E = remove_peers.front(); E; E = E->next()) {
|
||||||
_pending.erase(E->get());
|
_pending.erase(E->get());
|
||||||
|
|
|
@ -46,7 +46,7 @@ class WSLServer : public WebSocketServer {
|
||||||
private:
|
private:
|
||||||
class PendingPeer : public RefCounted {
|
class PendingPeer : public RefCounted {
|
||||||
private:
|
private:
|
||||||
bool _parse_request(const Vector<String> p_protocols);
|
bool _parse_request(const Vector<String> p_protocols, String &r_resource_name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ref<StreamPeerTCP> tcp;
|
Ref<StreamPeerTCP> tcp;
|
||||||
|
@ -62,7 +62,7 @@ private:
|
||||||
CharString response;
|
CharString response;
|
||||||
int response_sent = 0;
|
int response_sent = 0;
|
||||||
|
|
||||||
Error do_handshake(const Vector<String> p_protocols, uint64_t p_timeout);
|
Error do_handshake(const Vector<String> p_protocols, uint64_t p_timeout, String &r_resource_name);
|
||||||
};
|
};
|
||||||
|
|
||||||
int _in_buf_size = DEF_BUF_SHIFT;
|
int _in_buf_size = DEF_BUF_SHIFT;
|
||||||
|
|
Loading…
Reference in a new issue