diff options
Diffstat (limited to 'modules/websocket/lws_server.cpp')
-rw-r--r-- | modules/websocket/lws_server.cpp | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/modules/websocket/lws_server.cpp b/modules/websocket/lws_server.cpp new file mode 100644 index 0000000000..8a47ba557d --- /dev/null +++ b/modules/websocket/lws_server.cpp @@ -0,0 +1,177 @@ +/*************************************************************************/ +/* lws_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef JAVASCRIPT_ENABLED + +#include "lws_server.h" +#include "core/os/os.h" + +Error LWSServer::listen(int p_port, PoolVector<String> p_protocols, bool gd_mp_api) { + + ERR_FAIL_COND_V(context != NULL, FAILED); + + _is_multiplayer = gd_mp_api; + + struct lws_context_creation_info info; + memset(&info, 0, sizeof info); + + if (p_protocols.size() == 0) // default to binary protocol + p_protocols.append(String("binary")); + + // Prepare lws protocol structs + _lws_make_protocols(this, &LWSServer::_lws_gd_callback, p_protocols, &_lws_ref); + + info.port = p_port; + info.user = _lws_ref; + info.protocols = _lws_ref->lws_structs; + info.gid = -1; + info.uid = -1; + //info.ws_ping_pong_interval = 5; + + context = lws_create_context(&info); + + if (context == NULL) { + _lws_free_ref(_lws_ref); + _lws_ref = NULL; + ERR_EXPLAIN("Unable to create LWS context"); + ERR_FAIL_V(FAILED); + } + + return OK; +} + +bool LWSServer::is_listening() const { + return context != NULL; +} + +int LWSServer::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { + + LWSPeer::PeerData *peer_data = (LWSPeer::PeerData *)user; + + switch (reason) { + case LWS_CALLBACK_HTTP: + // no http for now + // closing immediately returning -1; + return -1; + + case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: + // check header here? + break; + + case LWS_CALLBACK_ESTABLISHED: { + int32_t id = _gen_unique_id(); + + Ref<LWSPeer> peer = Ref<LWSPeer>(memnew(LWSPeer)); + peer->set_wsi(wsi); + _peer_map[id] = peer; + + peer_data->peer_id = id; + peer_data->in_size = 0; + peer_data->in_count = 0; + peer_data->out_count = 0; + peer_data->rbw.resize(16); + peer_data->rbr.resize(16); + peer_data->force_close = false; + + _on_connect(id, lws_get_protocol(wsi)->name); + break; + } + + case LWS_CALLBACK_CLOSED: { + if (peer_data == NULL) + return 0; + int32_t id = peer_data->peer_id; + if (_peer_map.has(id)) { + _peer_map[id]->close(); + _peer_map.erase(id); + } + peer_data->in_count = 0; + peer_data->out_count = 0; + peer_data->rbr.resize(0); + peer_data->rbw.resize(0); + _on_disconnect(id); + return 0; // we can end here + } + + case LWS_CALLBACK_RECEIVE: { + int32_t id = peer_data->peer_id; + if (_peer_map.has(id)) { + static_cast<Ref<LWSPeer> >(_peer_map[id])->read_wsi(in, len); + if (_peer_map[id]->get_available_packet_count() > 0) + _on_peer_packet(id); + } + break; + } + + case LWS_CALLBACK_SERVER_WRITEABLE: { + if (peer_data->force_close) + return -1; + + int id = peer_data->peer_id; + if (_peer_map.has(id)) + static_cast<Ref<LWSPeer> >(_peer_map[id])->write_wsi(); + break; + } + + default: + break; + } + + return 0; +} + +void LWSServer::stop() { + if (context == NULL) + return; + + _peer_map.clear(); + destroy_context(); + context = NULL; +} + +bool LWSServer::has_peer(int p_id) const { + return _peer_map.has(p_id); +} + +Ref<WebSocketPeer> LWSServer::get_peer(int p_id) const { + ERR_FAIL_COND_V(!has_peer(p_id), NULL); + return _peer_map[p_id]; +} + +LWSServer::LWSServer() { + context = NULL; + _lws_ref = NULL; +} + +LWSServer::~LWSServer() { + invalidate_lws_ref(); // we do not want any more callbacks + stop(); +} + +#endif // JAVASCRIPT_ENABLED |