adding login on gdnative [c++]

This commit is contained in:
AleaJactaEst 2020-01-19 20:13:57 +01:00
parent e7ba3d0d56
commit eba1314eb3
22 changed files with 1156 additions and 298 deletions

View file

@ -31,13 +31,15 @@ scons -C godot-cpp platform=linux generate_bindings=yes custom_api_file=godot_he
### Build on 64bits ### Build on 64bits
``` ```
scons -C gdnative platform=linux bits=64 scons -C gdnative platform=linux bits=64 target=debug
scons -C gdnative platform=linux bits=64 target=release
``` ```
### Build on 32bits ### Build on 32bits
``` ```
scons -C gdnative platform=linux bits=32 scons -C gdnative platform=linux bits=32 target=debug
scons -C gdnative platform=linux bits=64 target=release
``` ```
## Package client khaganat ## Package client khaganat

View file

@ -111,7 +111,6 @@ func _enter_tree():
background.self_modulate = background_color background.self_modulate = background_color
self.add_window_part( background ) self.add_window_part( background )
print("[ui_window:3]")
# background.set_owner( self ) # background.set_owner( self )
### ###
### ###

View file

@ -10,12 +10,16 @@ var _msg_data = {}
func open_message_xml(): func open_message_xml():
var file = File.new() var file = File.new()
# Calculate MD5SUM
file.open("res://assets/Definition/msg.xml", File.READ) file.open("res://assets/Definition/msg.xml", File.READ)
var content = file.get_as_text() var content = file.get_as_text()
_msg_md5sum = content.md5_text() _msg_md5sum = content.md5_text()
file.close() file.close()
print("[res://assets/Scripts/Definition/msg.gd:open_message_xml] checksum for msg.xml:" + _msg_md5sum)
var NetworkConnexion = preload("res://networkconnexion.gdns").new()
NetworkConnexion.define_checksum_msg_xml(content.md5_buffer())
# Load XML data
_msg_xml.open("res://assets/Definition/msg.xml") _msg_xml.open("res://assets/Definition/msg.xml")
print("[msg:open_message_xml] " + _msg_md5sum)
func is_correct_md5(value): func is_correct_md5(value):
return (_msg_md5sum == value) return (_msg_md5sum == value)
@ -26,6 +30,8 @@ func read_all_node():
var ret = _msg_xml.read() var ret = _msg_xml.read()
var branch = "" var branch = ""
var leaf = "" var leaf = ""
var ibranch = 0
var ileaf = 0
while ret == OK: while ret == OK:
#print("Node: Name:" + _msg_xml.get_node_name() + ", Type:" + str(_msg_xml.get_node_type()) + ", Data:" + str(_msg_xml.get_node_data()) + ", attribut count:" + str(_msg_xml.get_attribute_count()) ) #print("Node: Name:" + _msg_xml.get_node_name() + ", Type:" + str(_msg_xml.get_node_type()) + ", Data:" + str(_msg_xml.get_node_data()) + ", attribut count:" + str(_msg_xml.get_attribute_count()) )
#i = 0 #i = 0
@ -44,7 +50,9 @@ func read_all_node():
if i < _msg_xml.get_attribute_count(): if i < _msg_xml.get_attribute_count():
branch = _msg_xml.get_attribute_value(i) branch = _msg_xml.get_attribute_value(i)
#print(branch + " " + str(_msg_xml.get_node_type())) #print(branch + " " + str(_msg_xml.get_node_type()))
_msg_data[branch] = [] _msg_data[branch] = {"leaf": {}, "pos": ibranch}
ibranch += 1
ileaf = 0
"leaf": "leaf":
i = 0 i = 0
while i < _msg_xml.get_attribute_count() and _msg_xml.get_attribute_name(i) != "name": while i < _msg_xml.get_attribute_count() and _msg_xml.get_attribute_name(i) != "name":
@ -52,21 +60,35 @@ func read_all_node():
if i < _msg_xml.get_attribute_count(): if i < _msg_xml.get_attribute_count():
leaf = _msg_xml.get_attribute_value(i) leaf = _msg_xml.get_attribute_value(i)
#print(branch + ":" + leaf + str(_msg_xml.get_node_type())) #print(branch + ":" + leaf + str(_msg_xml.get_node_type()))
_msg_data[branch].append(leaf) _msg_data[branch]["leaf"][leaf] = ileaf
ileaf += 1
ret = _msg_xml.read() ret = _msg_xml.read()
print("Branch:" + str(_msg_data.size())) if ProjectSettings.get_setting("khaganat/debug_mode"):
for key in _msg_data: #print("Branch:" + str(_msg_data.size()))
print(" " + key + ":" + str(_msg_data[key].size())) var sizebranch = _msg_data.size()
for leaf in _msg_data[key]: for key in _msg_data:
print(" " + key + ":" + leaf) var sizeleaf = _msg_data[key]["leaf"].size()
print(" " + key + " -> " + str(_msg_data[key]["pos"]) + "/" + str(sizebranch))
for leaf in _msg_data[key]["leaf"]:
var opt = str(_msg_data[key]["pos"]) + "/" + str(sizebranch) + " : " + str(_msg_data[key]["leaf"][leaf]) + "/" + str(sizeleaf)
print(" " + key + ":" + leaf + " -> " + opt)
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
open_message_xml() open_message_xml()
read_all_node() read_all_node()
print("[msg] ready") print("[res://assets/Scripts/Definition/msg.gd] ready")
# Called every frame. 'delta' is the elapsed time since the previous frame. # Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta): #func _process(delta):
# pass # pass
func read_msg(msgin):
pass
func write_msg(value):
pass

View file

@ -20,292 +20,32 @@
extends Control extends Control
enum TCONNECTIONSTATE {
NOTINITIALISED = 0, # nothing happened yet
NOTCONNECTED = 1, # init() called
AUTHENTICATE = 2, # connect() called, identified by the login server
LOGIN = 3, # connecting to the frontend, sending identification
SYNCHRONIZE = 4, # connection accepted by the frontend, synchronizing
CONNECTED = 5, # synchronized, connected, ready to work
PROBE = 6, # connection lost by frontend, probing for response
STALLED = 7, # server is stalled
DISCONNECT = 8, # disconnect() called, or timeout, or connection closed by frontend
QUIT = 9}
enum CLFECOMMON {
SYSTEM_LOGIN_CODE = 0,
SYSTEM_SYNC_CODE = 1,
SYSTEM_ACK_SYNC_CODE = 2,
SYSTEM_PROBE_CODE = 3,
SYSTEM_ACK_PROBE_CODE = 4,
SYSTEM_DISCONNECTION_CODE = 5,
SYSTEM_STALLED_CODE = 6,
SYSTEM_SERVER_DOWN_CODE = 7,
SYSTEM_QUIT_CODE = 8,
SYSTEM_ACK_QUIT_CODE = 9,
NUMBITSINLONGACK = 512}
const NUM_BITS_IN_LONG_ACK = 512
var _connection_state
var _socketUDP
var _user_addr
var _user_key
var _user_id
var _current_received_number
var _last_received_number
var _confirmed_received_number
var _last_ack_bit
var _ack_bit_mask
var _long_ack_bit_field
var _last_ack_in_long_ack
var _latest_sync
var _latest_probe_time
var _latest_probe
var _latest_probes
var _quit_id
var _update_time
var _queue_message_system
var _khaganat_host = "localhost"
var _khaganat_port = "47851"
onready var BitStream = preload("res://bitstream.gdns") onready var BitStream = preload("res://bitstream.gdns")
onready var BitSet = preload("res://bitset.gdns") onready var BitSet = preload("res://bitset.gdns")
onready var NetworkConnexion = preload("res://networkconnexion.gdns")
var _networkconnexion
func _ready(): func _ready():
_current_received_number = 0 _networkconnexion = NetworkConnexion.new()
_last_received_number = 0
_confirmed_received_number = 0
_last_ack_bit = 0
_ack_bit_mask = 0
_connection_state = TCONNECTIONSTATE.NOTINITIALISED
_socketUDP = PacketPeerUDP.new()
_queue_message_system = Array()
_long_ack_bit_field = BitSet.new()
_long_ack_bit_field.resize(512)
_last_ack_in_long_ack = 0
_latest_sync = 0
_latest_probe_time = 0
_latest_probe = 0
_latest_probes = Array()
_update_time = 0
_quit_id = 0
func send_system_login(user_addr, user_key, user_id, lang): func send_system_login(host, port, user_addr, user_key, user_id, lang):
var msgout = BitStream.new() _networkconnexion.send_system_login(host, port, user_addr, user_key, user_id, lang)
msgout.put_sint32(_current_received_number)
msgout.put_bool(true)
msgout.put_uint8(CLFECOMMON.SYSTEM_LOGIN_CODE)
msgout.put_string_hexa32(user_addr)
msgout.put_string_hexa32(user_key)
msgout.put_string_hexa32(user_id)
msgout.put_string(lang)
print("[net_low_level:send_system_login] Send System Login :" + msgout.show())
# To connect you need send 1st message
var res = _socketUDP.put_packet(msgout.get_data())
if ( res != OK):
print("[net_low_level:send_system_login] Error to send system login : " + str(res))
return
_connection_state = TCONNECTIONSTATE.CONNECTED
func send_system_sync():
var msgout = BitStream.new()
msgout.put_sint32(_current_received_number)
msgout.put_bool(true)
msgout.put_uint8(CLFECOMMON.SYSTEM_ACK_SYNC_CODE)
msgout.put_sint32(_last_received_number)
msgout.put_sint32(_last_ack_in_long_ack)
_long_ack_bit_field.write_serial(msgout)
msgout.put_sint32(_latest_sync)
_queue_message_system.append(msgout)
func send_system_ack_probe():
var msgout = BitStream.new()
msgout.put_sint32(_current_received_number)
msgout.put_bool(true)
msgout.put_uint8(CLFECOMMON.SYSTEM_ACK_PROBE_CODE)
msgout.put_sint32(_latest_probes.size())
for data in _latest_probes:
msgout.put_sint32(data)
_latest_probes.clear()
#_queue_message_system.append(msgout)
var res = _socketUDP.put_packet(msgout.get_data())
if ( res != OK):
print("[net_low_level:send_system_quit] Error to send system quit : " + str(res))
return
func send_system_quit(): func send_system_quit():
# TODO - check why we send quit_id _networkconnexion.send_system_quit()
var msgout = BitStream.new()
_quit_id += 1
msgout.put_sint32(_current_received_number)
msgout.put_bool(true)
msgout.put_uint8(CLFECOMMON.SYSTEM_QUIT_CODE)
msgout.put_sint32(_quit_id)
#_queue_message_system.append(msgout)
_connection_state == TCONNECTIONSTATE.QUIT
var res = _socketUDP.put_packet(msgout.get_data())
if ( res != OK):
print("[net_low_level:send_system_quit] Error to send system quit : " + str(res))
return
func send_systemm_disconnect(): func send_systemm_disconnect():
var msgout = BitStream.new() _networkconnexion.send_systemm_disconnect()
msgout.put_sint32(_current_received_number)
msgout.put_bool(true)
msgout.put_uint8(CLFECOMMON.SYSTEM_DISCONNECTION_CODE)
var res = _socketUDP.put_packet(msgout.get_data())
_connection_state == TCONNECTIONSTATE.QUIT
if ( res != OK):
print("[net_low_level:send_systemm_disconnect] Error to send system disconnection : " + str(res))
return
func disconnect_server(): func disconnect_server():
print("[net_low_level:disconnect_server] Disconnect") _networkconnexion.disconnect_server()
if typeof(_socketUDP) != TYPE_NIL:
send_systemm_disconnect()
print("[net_low_level:disconnect_server] Send disconnect to server")
_socketUDP.close()
_socketUDP = null
func set_khaganat_server(host, port): func connect_to_server(host, port, user_addr, user_key, user_id, lang):
_khaganat_host = host send_system_login(host, port, user_addr, user_key, user_id, lang)
_khaganat_port = port
func connect_to_server(user_addr, user_key, user_id):
var connexion = load("res://assets/Scripts/Config/connexion.gd").connexion.new()
var lang = connexion.get_language()
print("[net_low_level:connect_to_server] prepare:" + str(_khaganat_host) + ":" + str(_khaganat_port))
if typeof(_socketUDP) == TYPE_NIL:
_socketUDP = PacketPeerUDP.new()
_socketUDP.set_dest_address(_khaganat_host, _khaganat_port)
send_system_login(user_addr, user_key, user_id, lang)
func decode_system_message(msgin):
var message = msgin.get_uint8()
print("[net_low_level:analyze_message_received] Message type:" + str(message) )
match message:
CLFECOMMON.SYSTEM_LOGIN_CODE:
pass
CLFECOMMON.SYSTEM_SYNC_CODE:
var hexa = preload("res://assets/Scripts/Tools/hexa.gd").new()
var synchronize = msgin.get_uint32()
var stime = msgin.get_sint64()
_latest_sync = msgin.get_uint32()
var msg_xml = msgin.get_array_uint8(16)
var database_xml = msgin.get_array_uint8(16)
print("[net_low_level:analyze_message_received] synchronize:" + str(synchronize) + " stime:" + str(stime) + " latest_sync:" + str(_latest_sync))
var num = ""
for item in msg_xml:
num += str(item) + "."
print(num)
print(hexa.ArrayIntToStringHexa(msg_xml))
num = ""
for item in database_xml:
num += str(item) + "."
print(num)
print(hexa.ArrayIntToStringHexa(database_xml))
if not msg.is_correct_md5(hexa.ArrayIntToStringHexa(msg_xml)):
print("[net_low_level:analyze_message_received] Wrong MD5 for msg.xml")
# TODO - we need quit with message error and go to login
return
send_system_sync()
CLFECOMMON.SYSTEM_STALLED_CODE:
pass
CLFECOMMON.SYSTEM_PROBE_CODE:
_latest_probe_time = _update_time
_latest_probe = msgin.get_sint32()
_latest_probes.append(_latest_probe)
send_system_ack_probe()
CLFECOMMON.SYSTEM_SERVER_DOWN_CODE:
pass
_:
print("[net_low_level:analyze_message_received] Message type unknown (" + str(message) + ")")
func decode_normal_message(msgin):
pass
func analyze_message_received(msgbytes):
# khanat-opennel-code/code/ryzom/server/src/frontend_service/fe_receive_sub.cpp:769 void CFeReceiveSub::handleReceivedMsg( CClientHost *clienthost )
_update_time = OS.get_ticks_msec()
var msgin = BitStream.new()
msgin.put_data(msgbytes)
_current_received_number = msgin.get_sint32()
var system_mode = msgin.get_bool()
if ProjectSettings.get_setting("khaganat/debug_mode"):
print("[net_low_level:analyze_message_received] Tick:" + str(_current_received_number) + ", Mode:" + str(system_mode) + ", Size:" + str(msgin.size()))
if system_mode:
print("[net_low_level:analyze_message_received] System Mode")
if _current_received_number > _last_received_number + 1:
print("[net_low_level:analyze_message_received] lost message : " + str(_last_received_number + 1 - _current_received_number))
elif _current_received_number == _last_received_number:
print("[net_low_level:analyze_message_received] Server re-send last message")
return
elif _current_received_number < _last_received_number:
print("[net_low_level:analyze_message_received] Server re-send old message")
return
var ackBool = false
var ackBit = 0
if not system_mode:
match _connection_state:
TCONNECTIONSTATE.CONNECTED:
ackBool = true
ackBit = 1
TCONNECTIONSTATE.SYNCHRONIZE:
ackBool = true
ackBit = 1
_:
ackBool = false
if _current_received_number - _last_received_number < 32:
_ack_bit_mask <<= _current_received_number - _last_received_number
_ack_bit_mask |= _last_ack_bit << (_current_received_number - _last_received_number - 1)
elif (_current_received_number - _last_received_number) == 32 and _last_ack_bit != 0:
_ack_bit_mask = 0x80000000
else:
_ack_bit_mask = 0x00000000
_last_ack_bit = ackBit
for i in range(_last_received_number + 1, _current_received_number):
_long_ack_bit_field.clear_bit(i & (NUM_BITS_IN_LONG_ACK -1))
_long_ack_bit_field.put(_current_received_number & (NUM_BITS_IN_LONG_ACK-1), ackBool)
if _last_ack_in_long_ack <= (_last_received_number - NUM_BITS_IN_LONG_ACK):
_last_ack_in_long_ack = _last_received_number - NUM_BITS_IN_LONG_ACK + 1
_last_received_number = _current_received_number
if system_mode:
decode_system_message(msgin)
else:
decode_normal_message(msgin)
func _process(delta): func _process(delta):
if typeof(_socketUDP) == TYPE_NIL: _networkconnexion.process(delta)
return
var max_read = 10
if _connection_state == TCONNECTIONSTATE.NOTINITIALISED:
return
if _connection_state == TCONNECTIONSTATE.NOTCONNECTED:
return
if _connection_state == TCONNECTIONSTATE.QUIT:
return
if _queue_message_system.size() > 0:
var msgout = _queue_message_system.pop_front()
if ProjectSettings.get_setting("khaganat/debug_mode"):
print("[net_low_level:_process] Send data system (" + str(msgout.size()) + ", " + msgout.show() + ")" )
_socketUDP.put_packet(msgout.get_data())
if _latest_probes.size() > 0:
send_system_ack_probe()
while _socketUDP.get_available_packet_count() > 0 and max_read > 0:
var msgbytes = _socketUDP.get_packet()
if msgbytes.size() > 0:
analyze_message_received(msgbytes)
func _exit_tree(): func _exit_tree():
print("[net_low_level] End") print("[net_low_level] End")

View file

@ -50,6 +50,7 @@ void BitStream::_register_methods()
register_method("show", &BitStream::show); register_method("show", &BitStream::show);
register_method("show_detail", &BitStream::show_detail); register_method("show_detail", &BitStream::show_detail);
register_method("show_counter", &BitStream::show_counter);
register_method("get_data", &BitStream::get_data); register_method("get_data", &BitStream::get_data);
register_method("put_data", &BitStream::put_data); register_method("put_data", &BitStream::put_data);
@ -67,10 +68,15 @@ void BitStream::_register_methods()
register_method("get_array_uint8", &BitStream::get_array_uint8); register_method("get_array_uint8", &BitStream::get_array_uint8);
} }
void BitStream::clear()
{
this->_pos = 0;
this->_read = 0;
}
BitStream::BitStream() BitStream::BitStream()
{ {
this->_pos = 0; clear();
this->_read = 0;
} }
BitStream::~BitStream() BitStream::~BitStream()
@ -313,6 +319,13 @@ String BitStream::show_detail()
return "[size:" + strsize + ", pos:" + strpos + "]" + ret ; return "[size:" + strsize + ", pos:" + strpos + "]" + ret ;
} }
String BitStream::show_counter()
{
String ret = "[" + String::num_int64(this->_read) + " / " + String::num_int64(this->_pos) + "]";
return ret;
}
PoolByteArray BitStream::get_data() PoolByteArray BitStream::get_data()
{ {
return this->_data; return this->_data;
@ -441,4 +454,4 @@ PoolByteArray BitStream::get_array_uint8(uint32_t length)
--length; --length;
} }
return ret; return ret;
} }

View file

@ -34,6 +34,8 @@ private:
public: public:
static void _register_methods(); static void _register_methods();
void clear();
BitStream(); BitStream();
~BitStream(); ~BitStream();
@ -61,6 +63,7 @@ public:
String show(); String show();
String show_detail(); String show_detail();
String show_counter();
PoolByteArray get_data(); PoolByteArray get_data();
void put_data(PoolByteArray value); void put_data(PoolByteArray value);

42
gdnative/src/clfecommon.h Normal file
View file

@ -0,0 +1,42 @@
/*
Header CLFECOMMON : message send by server
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLFECOMMON_H
#define CLFECOMMON_H
namespace godot {
enum CLFECOMMON {
SYSTEM_LOGIN_CODE = 0,
SYSTEM_SYNC_CODE = 1,
SYSTEM_ACK_SYNC_CODE = 2,
SYSTEM_PROBE_CODE = 3,
SYSTEM_ACK_PROBE_CODE = 4,
SYSTEM_DISCONNECTION_CODE = 5,
SYSTEM_STALLED_CODE = 6,
SYSTEM_SERVER_DOWN_CODE = 7,
SYSTEM_QUIT_CODE = 8,
SYSTEM_ACK_QUIT_CODE = 9,
NUMBITSINLONGACK = 512
};
}
#endif // CLFECOMMON_H

View file

@ -6,8 +6,8 @@
namespace godot { namespace godot {
class Crypt : public Reference { class Crypt : public Object {
GODOT_CLASS(Crypt, Reference) GODOT_CLASS(Crypt, Object)
public: public:
static void _register_methods(); static void _register_methods();

View file

@ -21,22 +21,25 @@
#include "bitstream.h" #include "bitstream.h"
#include "bitset.h" #include "bitset.h"
#include "crypt.h" #include "crypt.h"
#include "network_connection.h"
/** GDNative Initialize **/ /** GDNative Initialize **/
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) { extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
godot::Godot::gdnative_init(o); godot::Godot::gdnative_init(o);
} }
/** GDNative Terminate **/ /** GDNative Terminate **/
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) { extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
godot::Godot::gdnative_terminate(o); terminate_network_connection();
godot::Godot::gdnative_terminate(o);
} }
/** NativeScript Initialize **/ /** NativeScript Initialize **/
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) { extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
godot::Godot::nativescript_init(handle); godot::Godot::nativescript_init(handle);
godot::register_class<godot::BitStream>(); godot::register_class<godot::BitStream>();
godot::register_class<godot::BitSet>(); godot::register_class<godot::BitSet>();
godot::register_class<godot::Crypt>(); godot::register_class<godot::Crypt>();
godot::register_class<godot::NetworkConnection>();
} }

View file

@ -0,0 +1,93 @@
/*
Library to present all functions of NetworkConnectionCore (network)
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Godot.hpp>
#include "network_connection.h"
#include "bitstream.h"
#include "network_connection_core.h"
using namespace godot;
NetworkConnectionCore *NetworkConnectionCore::singleton = NULL;
void NetworkConnection::_register_methods()
{
register_method("define_checksum_msg_xml", &NetworkConnection::define_checksum_msg_xml);
register_method("define_socket_udp", &NetworkConnection::define_socket_udp);
register_method("send_system_login", &NetworkConnection::send_system_login);
register_method("send_system_disconnect", &NetworkConnection::send_system_disconnect);
register_method("send_system_quit", &NetworkConnection::send_system_quit);
register_method("disconnect_server", &NetworkConnection::disconnect_server);
register_method("process", &NetworkConnection::process);
register_method("get_state", &NetworkConnection::get_state);
}
NetworkConnection::NetworkConnection()
{
}
NetworkConnection::~NetworkConnection()
{
}
int NetworkConnection::get_state()
{
return NetworkConnectionCore::get_singleton()->get_state();
}
void NetworkConnection::define_checksum_msg_xml(Array checksum_msg_xml)
{
NetworkConnectionCore::get_singleton()->define_checksum_msg_xml(checksum_msg_xml);
}
void NetworkConnection::define_socket_udp(PacketPeerUDP * socketUDP)
{
NetworkConnectionCore::get_singleton()->define_socket_udp(socketUDP);
}
void NetworkConnection::send_system_login(String host, int64_t port, String user_addr, String user_key, String user_id, String lang)
{
NetworkConnectionCore::get_singleton()->send_system_login(host, port, user_addr, user_key, user_id, lang);
}
void NetworkConnection::send_system_disconnect()
{
NetworkConnectionCore::get_singleton()->send_system_disconnect();
}
void NetworkConnection::send_system_quit()
{
NetworkConnectionCore::get_singleton()->send_system_quit();
}
void NetworkConnection::disconnect_server()
{
NetworkConnectionCore::get_singleton()->disconnect_server();
}
void NetworkConnection::process(int delta)
{
NetworkConnectionCore::get_singleton()->process(delta);
}
void terminate_network_connection()
{
NetworkConnectionCore::get_singleton()->terminate_connexion();
}

View file

@ -0,0 +1,62 @@
/*
Header NetworkConnection
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETWORK_CONNECTION_H
#define NETWORK_CONNECTION_H
#include <Godot.hpp>
#include <gen/PacketPeerUDP.hpp>
#include <Reference.hpp>
#include "bitstream.h"
#include "clfecommon.h"
#include "store_message.h"
#include "network_connection_core.h"
namespace godot {
class NetworkConnection : public Object {
GODOT_CLASS(NetworkConnection, Object)
private:
static void _bind_methods();
public:
NetworkConnection();
~NetworkConnection();
static void _register_methods();
/* _init must exist as it is called by Godot */
void _init() {};
void define_checksum_msg_xml(Array checksum_msg_xml);
void define_socket_udp(PacketPeerUDP * socketUDP); // Not necessary, but you can define network directly on GdScript
void send_system_login(String host, int64_t port, String user_addr, String user_key, String user_id, String lang);
void send_system_disconnect();
void send_system_quit();
void disconnect_server();
void process(int delta);
int get_state();
};
}
void terminate_network_connection();
#endif // NETWORK_CONNECTION_H

View file

@ -0,0 +1,482 @@
/*
Library to manage network
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define DEBUG_ENABLED
#include <Godot.hpp>
#include <core/Defs.hpp>
#include <gen/PacketPeerUDP.hpp>
#include "tools.h"
#include "bitset.h"
#include "bitstream.h"
#include "network_connection_core.h"
#include "state.h"
using namespace godot;
NetworkConnectionCore *NetworkConnectionCore::get_singleton()
{
if ( NetworkConnectionCore::singleton == NULL )
NetworkConnectionCore::singleton = new NetworkConnectionCore();
return NetworkConnectionCore::singleton;
}
NetworkConnectionCore::NetworkConnectionCore()
{
this->_socketUDP = NULL;
this->_state = STATE::NotInitialised ;
}
NetworkConnectionCore::~NetworkConnectionCore()
{
NetworkConnectionCore::singleton = NULL;
this->_state = STATE::NotInitialised ;
}
int NetworkConnectionCore::get_state()
{
return this->_state;
}
void NetworkConnectionCore::define_checksum_msg_xml(Array & checksum_msg_xml)
{
DEBUG_PRINT("Received msg.xml checksum");
this->_checksum_msg_xml = checksum_msg_xml;
DEBUG_PRINT("Received msg.xml checksum " + itos(checksum_msg_xml.size()));
DEBUG_PRINT("Received msg.xml checksum " + itos(this->_checksum_msg_xml.size()));
}
void NetworkConnectionCore::define_socket_udp(PacketPeerUDP * socketUDP)
{
// Use if you define PacketPeerUDP on other script
if ( this->_socketUDP == NULL)
this->_socketUDP = socketUDP;
}
void NetworkConnectionCore::autodefine_socket_udp()
{
// Create socket udp if not defined (If you don't use define_socket_udp)
if ( this->_socketUDP == NULL)
{
PacketPeerUDP::___init_method_bindings();
this->_socketUDP = PacketPeerUDP::_new();
if ( this->_socketUDP == NULL)
throw "Failed to open network";
}
}
void NetworkConnectionCore::send_system_login(String host, int64_t port, String user_addr, String user_key, String user_id, String lang)
{
// Configure socket UDP
this->autodefine_socket_udp();
if ( this->_state != STATE::NotInitialised )
{
DEBUG_PRINT("Close old network socket");
this->_socketUDP->close();
}
INFO_PRINT("Connect to " + host + ":" + itos(port));
this->_socketUDP->set_dest_address(host, port);
// Open connection and send ID
BitStream msgout;
msgout.put_sint32(_current_received_number);
msgout.put_bool(true);
msgout.put_uint8(CLFECOMMON::SYSTEM_LOGIN_CODE);
msgout.put_string_hexa32(user_addr);
msgout.put_string_hexa32(user_key);
msgout.put_string_hexa32(user_id);
msgout.put_string(lang);
godot::Error ret;
ret = this->_socketUDP->put_packet(msgout.get_data());
if ( ret != Error::OK)
{
this->_socketUDP->close();
switch(ret)
{
case Error::ERR_CANT_CONNECT:
ERR_PRINT("network connexion - Can't connect");
default:
ERR_PRINT("network connexion - Unknown error");
}
return;
}
INFO_PRINT("Connected to khganat");
this->_state = STATE::Connected;
// Initialize counter
this->_current_received_number = 0;
this->_last_received_number = 0;
this->_quit_id = 0;
this->_long_ack_bit_field.resize(NUM_BITS_IN_LONG_ACK);
this->_latest_probes.clear();
this->_ack_bit_mask = 0;
this->_last_ack_bit = 0;
this->_last_ack_in_long_ack = 0;
}
void NetworkConnectionCore::send_system_quit()
{
// TODO - check why we send quit_id
if ( this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize )
return;
DEBUG_PRINT("send quit to server");
BitStream msgout;
msgout.put_sint32(this->_current_received_number);
msgout.put_bool(true);
msgout.put_uint8(CLFECOMMON::SYSTEM_QUIT_CODE);
msgout.put_sint32(this->_quit_id);
if ( this->_socketUDP->put_packet(msgout.get_data()) != Error::OK )
{
ERR_PRINT("Error to send disconnect");
}
this->_state = STATE::Quit;
}
void NetworkConnectionCore::send_system_disconnect()
{
if ( this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize )
return;
DEBUG_PRINT("send disconnect to server");
BitStream msgout;
msgout.put_sint32(this->_current_received_number);
msgout.put_bool(true);
msgout.put_uint8(CLFECOMMON::SYSTEM_DISCONNECTION_CODE);
if ( this->_socketUDP->put_packet(msgout.get_data()) != Error::OK )
{
ERR_PRINT("Error to send disconnect");
}
this->_socketUDP->close();
this->_state = STATE::Disconnect;
}
void NetworkConnectionCore::send_system_ack_probe()
{
// khanat-opennel-code/code/ryzom/server/src/frontend_service/fe_receive_sub.cpp:1121 void CFeReceiveSub::handleReceivedMsg( CClientHost *clienthost )
if (this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize)
return;
int max = this->_latest_probes.size();
if (max == 0 )
return;
if (this->_state == STATE::ForceSynchronize && max < 5)
return;
DEBUG_PRINT("send system ACK PROBE to server");
BitStream msgout;
msgout.put_sint32(this->_current_received_number);
msgout.put_bool(true);
msgout.put_uint8(CLFECOMMON::SYSTEM_ACK_PROBE_CODE);
msgout.put_sint32(max);
for(int i=0; i < max ; ++i )
{
//DEBUG_PRINT("i:" + itos(i));
int data = this->_latest_probes[i];
//DEBUG_PRINT("data:" + itos(data));
msgout.put_sint32(data);
//DEBUG_PRINT("updated");
}
if (this->_socketUDP->put_packet(msgout.get_data()) != Error::OK)
{
ERR_PRINT("Error to send disconnect");
return;
}
this->_latest_probes.clear();
if (this->_state == STATE::ForceSynchronize && max >= 5)
{
// We have send ACK, so now we clean all queue and received all message to synchronize
this->queue.clear();
this->_state = STATE::Connected;
}
}
void NetworkConnectionCore::disconnect_server()
{
if (this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize)
return;
send_system_disconnect();
}
void NetworkConnectionCore::decode_system_message(BitStream *msgin)
{
int message = msgin->get_uint8();
switch (message)
{
case CLFECOMMON::SYSTEM_LOGIN_CODE:
DEBUG_PRINT("SYSTEM_LOGIN_CODE");
break;
case CLFECOMMON::SYSTEM_SYNC_CODE:
this->receive_system_sync(msgin);
break;
case CLFECOMMON::SYSTEM_STALLED_CODE:
DEBUG_PRINT("SYSTEM_STALLED_CODE");
break;
case CLFECOMMON::SYSTEM_SERVER_DOWN_CODE:
DEBUG_PRINT("SYSTEM_SERVER_DOWN_CODE");
break;
case CLFECOMMON::SYSTEM_PROBE_CODE:
this->receive_system_probe(msgin);
break;
default:
ERR_PRINT("Received unknown message [" + itos(message) + "]");
break;
}
}
void NetworkConnectionCore::decode_normal_message(BitStream *msgin)
{
DEBUG_PRINT("Decode normal message");
}
void NetworkConnectionCore::receive_system_sync(BitStream * msgin)
{
int i;
bool valide = true;
DEBUG_PRINT("SYSTEM_SYNC_CODE");
uint32_t synchronize = msgin->get_uint32();
int64_t stime = msgin->get_sint64();
uint32_t latestsync = msgin->get_uint32();
PoolByteArray msg_xml = msgin->get_array_uint8(16);
PoolByteArray database_xml = msgin->get_array_uint8(16);
if ( msg_xml.size() != this->_checksum_msg_xml.size() )
{
valide = false;
DEBUG_PRINT("MSG XML is incorrect (server:" + itos(msg_xml.size()) +", client:" + itos(this->_checksum_msg_xml.size()) + ")");
}
else
{
for(i=0; i<msg_xml.size(); ++i)
{
if ( (int) msg_xml[i] != (int) this->_checksum_msg_xml[i] )
{
valide = false;
DEBUG_PRINT("MSG XML is incorrect (pos:" + itos(i) +")");
}
}
}
if ( valide == true )
DEBUG_PRINT("MSG XML is correct");
else
DEBUG_PRINT("MSG.XML is wrong");
/*
self._Synchronize = msg.readUint32('Synchronize')
stime = msg.readSint64('stime')
self._LatestSync = msg.readUint32('LatestSync')
logging.getLogger(LOGGER).debug("%d %d %d" %(self._Synchronize, stime, self._LatestSync))
# khanat-opennel-code/code/ryzom/client/src/network_connection.cpp : void CNetworkConnection::receiveSystemSync(CBitMemStream &msgin)
MsgData = msg.readArrayUint8(16, 'MsgData')
DatabaseData = msg.readArrayUint8(16, 'DatabaseData')
logging.getLogger(LOGGER).debug("MsgData:" + str(MsgData))
logging.getLogger(LOGGER).debug("DatabaseData:" + str(DatabaseData))
md5Msg = bytes(MsgData)
md5Database = bytes(DatabaseData)
if md5Msg == self._MsgXmlMD5:
logging.getLogger(LOGGER).info("Check MD5 msg.xml : OK")
else:
logging.getLogger(LOGGER).error("Check MD5 msg.xml : KO")
if md5Database == self._DatabaseXmlMD5:
logging.getLogger(LOGGER).info("Check MD5 database.xml : OK")
else:
logging.getLogger(LOGGER).error("Check MD5 database.xml : KO")
logging.getLogger(LOGGER).debug("Msg Received:" + msg.showAllData())
self._MsPerTick = 100
self._CurrentServerTick = self._Synchronize + self._CurrentReceivedNumber + 2
self._CurrentClientTick = self._CurrentServerTick - ( self._LCT + self._MsPerTick ) / self._MsPerTick
self._CurrentClientTime = self._UpdateTime - (self._LCT + self._MsPerTick)
*/
}
void NetworkConnectionCore::receive_system_probe(BitStream * msgin)
{
DEBUG_PRINT("SYSTEM_PROBE_CODE size:" + itos(this->_latest_probes.size()));
this->_latest_probes.append(msgin->get_sint32());
}
void NetworkConnectionCore::wait_resynchronize(int32_t current_received_number, BitStream * msgin)
{
bool system_mode;
this->_current_received_number = current_received_number;
system_mode = msgin->get_bool();
if ( system_mode == true )
{
int message = msgin->get_uint8();
switch (message)
{
case CLFECOMMON::SYSTEM_LOGIN_CODE:
DEBUG_PRINT("SYSTEM_LOGIN_CODE");
break;
case CLFECOMMON::SYSTEM_SYNC_CODE:
DEBUG_PRINT("SYSTEM_SYNC_CODE");
break;
case CLFECOMMON::SYSTEM_STALLED_CODE:
DEBUG_PRINT("SYSTEM_STALLED_CODE");
break;
case CLFECOMMON::SYSTEM_SERVER_DOWN_CODE:
DEBUG_PRINT("SYSTEM_SERVER_DOWN_CODE");
break;
case CLFECOMMON::SYSTEM_PROBE_CODE:
this->receive_system_probe(msgin);
break;
default:
ERR_PRINT("Received unknown message [" + itos(message) + "]");
break;
}
}
this->_last_received_number = current_received_number;
}
void NetworkConnectionCore::analyze_message_receieved(int32_t current_received_number, BitStream * msgin)
{
bool system_mode;
bool ackBool = false;
int ackBit = 0;
int i;
this->_current_received_number = current_received_number;
system_mode = msgin->get_bool();
if ( system_mode == true )
{
INFO_PRINT("Received system message");
if (this->_current_received_number == this->_last_received_number + 1)
{
INFO_PRINT("Received message");
}
else if (this->_current_received_number < this->_last_received_number + 1)
{
INFO_PRINT("Received old message");
return;
}
else if (this->_current_received_number > this->_last_received_number + 1)
{
INFO_PRINT("Received message in future (lost some message)");
}
}
else
{
INFO_PRINT("Received normal message");
}
if ( system_mode != true )
{
ackBool = true;
ackBit = 1;
}
if ( current_received_number - this->_last_received_number < 32 )
{
this->_ack_bit_mask <<= current_received_number - this->_last_received_number;
this->_ack_bit_mask |= this->_last_ack_bit << (current_received_number - this->_last_received_number - 1);
}
else if (((current_received_number - this->_last_received_number) == 32) && (this->_last_ack_bit != 0))
this->_ack_bit_mask = 0x80000000;
else
this->_ack_bit_mask = 0x00000000;
this->_last_ack_bit = ackBit;
for(i=this->_last_received_number + 1 ;i < _current_received_number; ++i)
this->_long_ack_bit_field.clear_bit(i & (NUM_BITS_IN_LONG_ACK -1) );
// TODO - what's action when we have rotate onthis number (max -> 0)
if( this->_last_received_number > 0x08000000 )
{
if(this->_last_ack_in_long_ack <= (this->_last_received_number - NUM_BITS_IN_LONG_ACK))
this->_last_ack_in_long_ack = this->_last_received_number - NUM_BITS_IN_LONG_ACK + 1;
this->_last_received_number = current_received_number;
}
else
{
if(this->_last_ack_in_long_ack - 0x80000000 <= (this->_last_received_number - NUM_BITS_IN_LONG_ACK - 0x80000000))
this->_last_ack_in_long_ack = this->_last_received_number - NUM_BITS_IN_LONG_ACK + 1;
this->_last_received_number = current_received_number;
}
if ( system_mode == true )
this->decode_system_message(msgin);
else
this->decode_normal_message(msgin);
}
void NetworkConnectionCore::store_message_received(PoolByteArray & msgbytes)
{
int pos = this->queue.put_msgbytes(msgbytes);
BitStream * msgin = this->queue.get_msg(pos);
int32_t current_received_number = this->queue.get_received_number(pos);
/// TODO - check if max int execeded current_received_number < 1000 this->_last_received_number > 0x80000000
if ( this->_state == STATE::ForceSynchronize )
{
// We have detected a problem of synchro, we wait message ack probe and after server launch a re-sync
wait_resynchronize(current_received_number, msgin);
}
else if ( current_received_number - this->_last_received_number <= 0 ) // Received old message
{
INFO_PRINT("current_received_number : " + itos(current_received_number) + " / queue size : " + itos(this->queue.length()));
this->queue.erase(pos);
return;
}
else if ( this->_last_received_number + 1 == current_received_number ) // Received next message
{
INFO_PRINT("current_received_number : " + itos(current_received_number) + " / queue size : " + itos(this->queue.length()));
analyze_message_receieved(current_received_number, msgin);
this->queue.erase(pos);
}
else // Received new message (but missing some message between) -> go to queue and cross finger to received the next message (for _last_received_number)
{
INFO_PRINT("current_received_number : " + itos(current_received_number) + " / queue size : " + itos(this->queue.length()));
if (this->queue.length() >= SIZE_QUEUE_MESSAGE)
{
ERR_PRINT("Network queue is full / wait re-synchronize");
this->_state = STATE::ForceSynchronize ;
return;
}
}
}
void NetworkConnectionCore::send_message()
{
if ( this->_latest_probes.size() > 0 )
send_system_ack_probe();
}
void NetworkConnectionCore::process(int delta)
{
if (this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize)
return;
//INFO_PRINT( "Process - delta : " + itos(delta));
for(int i = 0; (this->_socketUDP->get_available_packet_count() > 0) && (i < MAX_LOOP_READ_BY_STEP) ; ++i)
{
PoolByteArray msgbytes ;
msgbytes = this->_socketUDP->get_packet();
DEBUG_PRINT("Size msg received : " + itos(msgbytes.size()) );
store_message_received(msgbytes);
}
send_message();
}
void NetworkConnectionCore::terminate_connexion()
{
DEBUG_PRINT("Terminate network connexion");
if ( this->_socketUDP == NULL )
return;
delete this-> _socketUDP;
this->_socketUDP = NULL;
}

View file

@ -0,0 +1,88 @@
/*
Header NetworkConnectionCore
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETWORK_CONNECTION_CORE_H
#define NETWORK_CONNECTION_CORE_H
#include <Godot.hpp>
#include <gen/PacketPeerUDP.hpp>
#include "bitset.h"
#include "bitstream.h"
#include "clfecommon.h"
#include "store_message.h"
#include "state.h"
#define MAX_LOOP_READ_BY_STEP 10
#define NUM_BITS_IN_LONG_ACK 512
namespace godot {
class NetworkConnectionCore : public Object {
GODOT_CLASS(NetworkConnectionCore, Object)
private:
static NetworkConnectionCore *singleton;
bool _force_resynchronize;
STATE _state;
PacketPeerUDP * _socketUDP;
int32_t _current_received_number;
int32_t _last_received_number;
int32_t _quit_id;
BitSet _long_ack_bit_field;
Array _latest_probes;
Array _checksum_msg_xml;
uint32_t _ack_bit_mask;
int32_t _last_ack_bit;
int32_t _last_ack_in_long_ack;
StoreMessage queue;
public:
static NetworkConnectionCore * get_singleton();
NetworkConnectionCore();
~NetworkConnectionCore();
int get_state();
void define_checksum_msg_xml(Array & checksum_msg_xml);
void define_socket_udp(PacketPeerUDP * socketUDP);
void autodefine_socket_udp();
void send_system_login(String host, int64_t port, String user_addr, String user_key, String user_id, String lang);
void send_system_disconnect();
void send_system_quit();
void disconnect_server();
void send_system_ack_probe();
void decode_system_message(BitStream *msgin);
void decode_normal_message(BitStream *msgin);
void receive_system_sync(BitStream * msgin);
void receive_system_probe(BitStream * msgin);
void wait_resynchronize(int32_t current_received_number, BitStream * msgin);
void analyze_message_receieved(int32_t, BitStream *msgin);
void store_message_received(PoolByteArray & msgbytes);
void send_message();
void process(int delta);
bool connected();
void terminate_connexion();
};
}
#endif

38
gdnative/src/state.h Normal file
View file

@ -0,0 +1,38 @@
/*
Header STATE : to know state of client
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef STATE_H
#define STATE_H
enum STATE {
NotInitialised = 0,
//NotConnected = 1, // When received a cookie - not used here
//Authenticate = 2,
//Login = 3,
// Synchronize = 4,
Connected = 5, // State when we are connecte
//Probe = 6,
//Stalled = 7,
Disconnect = 8,
Quit = 9,
ForceSynchronize = 10
};
#endif // STATE_H

View file

@ -0,0 +1,127 @@
/*
StoreMessage : class to manage packet received by khaganat
If we received message with bad order, with this class we can manage (with limit storage)
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Godot.hpp>
#include <core/Defs.hpp>
#include "bitstream.h"
#include "tools.h"
#include "store_message.h"
using namespace godot;
StoreMessage::StoreMessage()
{
this->clear();
}
StoreMessage::~StoreMessage()
{
}
void StoreMessage::clear()
{
for(int i = 0 ; i < SIZE_QUEUE_MESSAGE ; ++i )
{
//this->_empty[i] = true;
this->_received_number[i] = 0;
this->_msgin[i].clear();
}
this->_size = 0;
}
int StoreMessage::length()
{
return this->_size;
}
int StoreMessage::put_msgbytes(PoolByteArray & msgbytes)
{
int i = 0;
int ii ;
//while((this->_empty[i] != true)&&(i < SIZE_QUEUE_MESSAGE))
while((i < SIZE_QUEUE_MESSAGE)&&(this->_msgin[i].size_data() != 0))
++i;
if(i >= SIZE_QUEUE_MESSAGE) // Out of memory
{
ERR_PRINT("Network queue is full (" + itos(i) + " / " + itos(SIZE_QUEUE_MESSAGE) + ")");
throw "Out of memory";
}
//INFO_PRINT("-> i:" + itos(i) + "/" + itos(this->_size) + " State:" + itos(this->_msgin[i].size_data()) + " num:" + itos(this->_received_number[i]));
//INFO_PRINT("i:" + itos(i) + " / " + itos(SIZE_QUEUE_MESSAGE) );
this->_msgin[i].put_data(msgbytes);
int32_t current_received_number = this->_msgin[i].get_sint32();
this->_received_number[i] = current_received_number;
// Check we don't have other message with same _received_number (also remove it)
ii = i + 1;
while(ii < SIZE_QUEUE_MESSAGE)
{
if ( this->_received_number[ii] == current_received_number)
this->erase(ii);
++ii;
}
this->_size ++;
/*
for(int ii = 0 ; ii < SIZE_QUEUE_MESSAGE ; ++ii)
{
INFO_PRINT(itos(ii) + ") i:" + itos(i) + "/" + itos(this->_size) + " State:" + itos(this->_msgin[ii].size_data()) + " num:" + itos(this->_received_number[ii]));
}
*/
return i;
}
BitStream * StoreMessage::get_msg(int pos)
{
if ( pos >= SIZE_QUEUE_MESSAGE )
{
ERR_PRINT("Try to get data out of memory");
throw "Out of memory";
}
return & this->_msgin[pos];
}
int32_t StoreMessage::get_received_number(int pos)
{
if ( pos >= SIZE_QUEUE_MESSAGE )
{
ERR_PRINT("Try to get data out of memory");
throw "Out of memory";
}
return this->_received_number[pos];
}
void StoreMessage::erase(int pos)
{
if ( pos >= SIZE_QUEUE_MESSAGE )
{
ERR_PRINT("Try to erase data out of memory");
return;
}
//this->_empty[pos] = true;
this->_received_number[pos] = 0;
this->_msgin[pos].clear();
this->_size -- ;
}

View file

@ -0,0 +1,47 @@
/*
Header StoreMessage : message send by server
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef STORE_MESSAGE_H
#define STORE_MESSAGE_H
#define SIZE_QUEUE_MESSAGE 6
namespace godot {
class StoreMessage
{
// bool _empty[SIZE_QUEUE_MESSAGE];
int32_t _received_number[SIZE_QUEUE_MESSAGE];
BitStream _msgin[SIZE_QUEUE_MESSAGE];
int _size;
public:
StoreMessage();
~StoreMessage();
void clear();
int length();
int put_msgbytes(PoolByteArray & msgbytes);
BitStream * get_msg(int pos);
int32_t get_received_number(int pos);
void erase(int pos);
};
}
#endif // STORE_MESSAGE_H

29
gdnative/src/tools.cpp Normal file
View file

@ -0,0 +1,29 @@
/*
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Godot.hpp>
#include <core/Defs.hpp>
#include "tools.h"
using namespace godot;
String godot::itos(int64_t p_val)
{
return String::num_int64(p_val);
}

44
gdnative/src/tools.h Normal file
View file

@ -0,0 +1,44 @@
/*
Header Tools
Copyright (C) 2019 AleaJactaEst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TOOLS_H
#define TOOLS_H
#include <Godot.hpp>
namespace godot {
String itos(int64_t p_val);
#define INFO_PRINT(msg) Godot::print( String(__FUNCTION__) + ":" + String(__FILE__) + ":" + itos( __LINE__) + " " + String(msg))
#ifdef DEBUG_ENABLED
#define DEBUG_PRINT(msg) Godot::print( String(__FUNCTION__) + ":" + String(__FILE__) + ":" + itos( __LINE__) + " " + String(msg))
#else
#define DEBUG_PRINT(msg)
#endif
}
#endif // STORE_MESSAGE_H

View file

@ -14,7 +14,7 @@ func _ready():
func test_resize(): func test_resize():
var bitset = preload("res://bitset.gdns").new() var bitset = preload("res://bitset.gdns").new()
print ("[bitset:test_init]") print ("[bitset:test_resize]")
bitset.resize(1024) bitset.resize(1024)
func test_put(): func test_put():
@ -33,9 +33,20 @@ func test_put():
#print ("[bitset:test_init] " + bitset.show()) #print ("[bitset:test_init] " + bitset.show())
assert( bitset.show() == "0000000000000000000000000000010000000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") assert( bitset.show() == "0000000000000000000000000000010000000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
func test_alloc():
var BitSet = preload("res://bitset.gdns")
print ("[bitset:test_alloc]")
var tab = {}
tab[1478] = BitSet.new()
assert( tab.size() == 1 )
tab[1479] = BitSet.new()
assert( tab.size() == 2 )
tab.erase(1478)
assert( tab.size() == 1 )
func test(): func test():
print("[bitset] Start check -> start") print("[bitset] Start check -> start")
test_resize() test_resize()
test_put() test_put()
test_alloc()
print("[bitset] Start check -> end") print("[bitset] Start check -> end")

View file

@ -148,8 +148,10 @@ func _on_HTTPRequest_request_completed(result, response_code, headers, body):
print("[login_menu:_on_HTTPRequest_request_completed] state:" + state + ", cookie:" + cookie + ", fsaddr:" + fsaddr + ", ringmainurl:" + ringmainurl + ", fartp:" + fartp + ", stat:" + stat + ", r2serverversion:" + r2serverversion + ", r2backuppatchurl:" + r2backuppatchurl + ", r2patchurl:" + r2patchurl) print("[login_menu:_on_HTTPRequest_request_completed] state:" + state + ", cookie:" + cookie + ", fsaddr:" + fsaddr + ", ringmainurl:" + ringmainurl + ", fartp:" + fartp + ", stat:" + stat + ", r2serverversion:" + r2serverversion + ", r2backuppatchurl:" + r2backuppatchurl + ", r2patchurl:" + r2patchurl)
var server_info = server_info_script.nel_server_info.new(body.get_string_from_utf8()); var server_info = server_info_script.nel_server_info.new(body.get_string_from_utf8());
net_low_level.set_khaganat_server(khaganat_host, khaganat_port) var connexion = load("res://assets/Scripts/Config/connexion.gd").connexion.new()
net_low_level.connect_to_server(UserAddr, UserKey, UserId) var lang = connexion.get_language()
print("[login_menu:_on_HTTPRequest_request_completed] khaganat_host:" + khaganat_host + ", khaganat_port:" + str(khaganat_port))
net_low_level.connect_to_server(khaganat_host, khaganat_port, UserAddr, UserKey, UserId, lang)
emit_signal( "login_button_pressed" ) emit_signal( "login_button_pressed" )

7
networkconnexion.gdns Normal file
View file

@ -0,0 +1,7 @@
[gd_resource type="NativeScript" load_steps=2 format=2]
[ext_resource path="res://gdnative.gdnlib" type="GDNativeLibrary" id=1]
[resource]
class_name = "NetworkConnection"
library = ExtResource( 1 )

View file

@ -27,6 +27,10 @@ character="*res://game_scene/Game/Character/Character.tscn"
net_low_level="*res://assets/Scripts/Network/net_low_level.gd" net_low_level="*res://assets/Scripts/Network/net_low_level.gd"
msg="*res://assets/Scripts/Definition/msg.gd" msg="*res://assets/Scripts/Definition/msg.gd"
[debug]
settings/stdout/verbose_stdout=true
[display] [display]
window/size/width=1280 window/size/width=1280