mirror of
https://port.numenaute.org/aleajactaest/bazar_alea.git
synced 2024-11-09 16:59:02 +00:00
update XMPP
This commit is contained in:
parent
0ab321c3e1
commit
981a05cb14
2 changed files with 362 additions and 37 deletions
|
@ -28,14 +28,31 @@ enum StreamState {
|
|||
}
|
||||
var stream_status = StreamState.END
|
||||
|
||||
@export var server_ip:String = "localhost":
|
||||
set = set_server_ip, get = get_server_ip
|
||||
enum XMPPState {
|
||||
NONE, # Nothing is configured
|
||||
TRY_CONNECT_SERVER, # Try to connect to server
|
||||
CONNECTED_SERVER, # Confirmed we are connected to server
|
||||
INTIALIZE, # Initialize first connection with server
|
||||
INTIALIZED, # when initialize is finished
|
||||
FEATURE_SERVER, # We received Feature (TLS ?)
|
||||
START_TLS, # We start TLS
|
||||
WAIT_TLS, # Wait TLS Done
|
||||
MISSING_TLS, # Missing feature TLS -> wait 30min and retry
|
||||
STARTED_TLS, # TLS connection is done
|
||||
AUTHENTICATE_STEP_1, # Launch authenticate
|
||||
AUTHENTICATE_STEP_2, # Launch authenticate
|
||||
AUTHENTICATE_STEP_3, # Launch authenticate
|
||||
AUTHENTICATED, # We finished authenticate
|
||||
}
|
||||
|
||||
func set_server_ip(value:String):
|
||||
server_ip = value
|
||||
@export var server_xmpp_name:String = "localhost":
|
||||
set = set_server_xmpp_name, get = get_server_xmpp_name
|
||||
|
||||
func get_server_ip() -> String:
|
||||
return server_ip
|
||||
func set_server_xmpp_name(value:String):
|
||||
server_xmpp_name = value
|
||||
|
||||
func get_server_xmpp_name() -> String:
|
||||
return server_xmpp_name
|
||||
|
||||
@export var port_number:int = 5222:
|
||||
set = set_port_number, get = get_port_number
|
||||
|
@ -79,28 +96,321 @@ func get_locale() -> String:
|
|||
set(value):
|
||||
xmppclient = value
|
||||
|
||||
const MAX_WAIT_CONNECTING:float = 60.0
|
||||
const MAX_WAIT_MISSING_TLS:float = 1800.0
|
||||
|
||||
var try_connect:int = 0
|
||||
var count_connecting_time:float = 0
|
||||
var count_connecting_time:float = MAX_WAIT_CONNECTING
|
||||
var partial_stanza:String = ""
|
||||
var tcp_peer:StreamPeerTCP = StreamPeerTCP.new()
|
||||
var ssl_peer:StreamPeerTLS = StreamPeerTLS.new()
|
||||
var tgt_peer = null
|
||||
var status:StreamState = StreamState.END
|
||||
var xmpp_state = XMPPState.NONE
|
||||
var authentication_methods = []
|
||||
|
||||
func reinit_stream():
|
||||
if ssl_peer != null:
|
||||
ssl_peer.disconnect_from_stream()
|
||||
else:
|
||||
ssl_peer = StreamPeerTLS.new()
|
||||
if tcp_peer != null:
|
||||
tcp_peer.disconnect_from_host()
|
||||
else:
|
||||
tcp_peer = StreamPeerTCP.new()
|
||||
tgt_peer = tcp_peer
|
||||
start_stream()
|
||||
stream_status = self.StreamState.START
|
||||
|
||||
|
||||
func _init():
|
||||
func _init() -> void:
|
||||
var language = OS.get_locale()
|
||||
set_locale(language)
|
||||
tgt_peer = tcp_peer
|
||||
# reinit_stream()
|
||||
|
||||
func _process(delta):
|
||||
#Global.msg_info("TCP:%d", [tcp_peer.get_status()])
|
||||
print(server_ip, ":", port_number, " / get_status:" , tcp_peer.get_status(), " / count_connecting_time:", count_connecting_time, " / stream_status:", stream_status)
|
||||
# if tcp_peer.get_status() == StreamPeerTCP.STATUS_NONE and stream_status == self.StreamState.TLS:
|
||||
# #negotiate_tls()
|
||||
# print("negotiate_tls")
|
||||
# pass
|
||||
if (tgt_peer.get_status() == StreamPeerTCP.STATUS_CONNECTED) :
|
||||
|
||||
func _process(delta) -> void:
|
||||
print(server_xmpp_name, ":", port_number, " / get_status:" , tcp_peer.get_status(), " / count_connecting_time:", count_connecting_time, " / stream_status:", stream_status, " / xmpp_state:", XMPPState.keys()[xmpp_state])
|
||||
if xmppclient == false:
|
||||
return
|
||||
# Wait MAX_WAIT_MISSING_TLS (s) if server can't negociate with TLS
|
||||
if xmpp_state == XMPPState.MISSING_TLS:
|
||||
if count_connecting_time >= MAX_WAIT_MISSING_TLS:
|
||||
xmpp_state = XMPPState.NONE
|
||||
else:
|
||||
count_connecting_time += delta
|
||||
elif xmpp_state == XMPPState.NONE:
|
||||
if count_connecting_time >= MAX_WAIT_CONNECTING:
|
||||
xmpp_state = XMPPState.TRY_CONNECT_SERVER
|
||||
if ssl_peer.get_status() != StreamPeerTLS.STATUS_DISCONNECTED:
|
||||
ssl_peer.disconnect_from_stream()
|
||||
if tcp_peer.get_status() != StreamPeerTCP.STATUS_NONE:
|
||||
tcp_peer.disconnect_from_host()
|
||||
else:
|
||||
count_connecting_time += delta
|
||||
elif xmpp_state == XMPPState.TRY_CONNECT_SERVER:
|
||||
if tcp_peer.get_status() == StreamPeerTCP.STATUS_CONNECTED:
|
||||
xmpp_state = XMPPState.CONNECTED_SERVER
|
||||
count_connecting_time = MAX_WAIT_CONNECTING
|
||||
elif count_connecting_time >= MAX_WAIT_CONNECTING:
|
||||
var res = tcp_peer.connect_to_host(server_xmpp_name, port_number)
|
||||
if res == OK:
|
||||
send_msg_debug.emit("Send connect_to_host : ok")
|
||||
#stream_status = self.StreamState.END
|
||||
#xmpp_state = XMPPState.CONNECTED_SERVER
|
||||
count_connecting_time = 0
|
||||
else:
|
||||
send_msg_error.emit("Error to connect to XMPP server (return:%d)" % res)
|
||||
xmpp_state = XMPPState.NONE
|
||||
count_connecting_time = 0
|
||||
else:
|
||||
if (tcp_peer.has_method("poll")):
|
||||
tcp_peer.poll()
|
||||
count_connecting_time += delta
|
||||
elif xmpp_state == XMPPState.CONNECTED_SERVER:
|
||||
if tcp_peer.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||
xmpp_state = XMPPState.NONE
|
||||
count_connecting_time = 0
|
||||
return
|
||||
if count_connecting_time >= MAX_WAIT_CONNECTING:
|
||||
count_connecting_time = 0
|
||||
send_msg_debug.emit("send_tcp_initialize_xmpp")
|
||||
send_tcp_initialize_xmpp()
|
||||
else:
|
||||
count_connecting_time += delta
|
||||
if (tcp_peer.has_method("poll")):
|
||||
tcp_peer.poll()
|
||||
if tcp_peer.get_available_bytes()>0:
|
||||
var response = tcp_peer.get_string(tcp_peer.get_available_bytes())
|
||||
send_msg_debug.emit("Stream: response: " + response)
|
||||
response = remove_stream_header(response)
|
||||
if not analyze_error(response):
|
||||
if analyze_feature_starttls(response):
|
||||
xmpp_state = XMPPState.START_TLS
|
||||
else:
|
||||
count_connecting_time = 0
|
||||
xmpp_state = XMPPState.MISSING_TLS
|
||||
elif xmpp_state == XMPPState.START_TLS:
|
||||
if tcp_peer.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||
xmpp_state = XMPPState.NONE
|
||||
count_connecting_time = 0
|
||||
return
|
||||
if count_connecting_time >= MAX_WAIT_CONNECTING:
|
||||
count_connecting_time = 0
|
||||
xmpp_state = XMPPState.NONE
|
||||
else:
|
||||
count_connecting_time += delta
|
||||
if (tcp_peer.has_method("poll")):
|
||||
tcp_peer.poll()
|
||||
if tcp_peer.get_available_bytes()>0:
|
||||
var response = tcp_peer.get_string(tcp_peer.get_available_bytes())
|
||||
send_msg_debug.emit("Stream: response: " + response)
|
||||
response = remove_stream_header(response)
|
||||
if response.begins_with("<proceed"):
|
||||
send_msg_debug.emit("Stream: gotten go ahead for ssl")
|
||||
var options:TLSOptions = TLSOptions.client_unsafe()
|
||||
var ssl_succes = ssl_peer.connect_to_stream(tcp_peer, "localhost", options)
|
||||
if ssl_succes == OK:
|
||||
send_msg_debug.emit("Stream: switched to SSL!")
|
||||
xmpp_state = XMPPState.WAIT_TLS
|
||||
else:
|
||||
count_connecting_time = 0
|
||||
xmpp_state = XMPPState.MISSING_TLS
|
||||
else:
|
||||
send_msg_error.emit(tr("TlS negotiation failed."))
|
||||
count_connecting_time = 0
|
||||
xmpp_state = XMPPState.MISSING_TLS
|
||||
elif xmpp_state == XMPPState.WAIT_TLS:
|
||||
if tcp_peer.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||
xmpp_state = XMPPState.NONE
|
||||
count_connecting_time = 0
|
||||
return
|
||||
if ssl_peer.get_status() == StreamPeerTLS.STATUS_CONNECTED:
|
||||
xmpp_state = XMPPState.STARTED_TLS
|
||||
count_connecting_time = MAX_WAIT_CONNECTING
|
||||
elif ssl_peer.get_status() == StreamPeerTLS.STATUS_HANDSHAKING:
|
||||
ssl_peer.poll()
|
||||
if count_connecting_time >= MAX_WAIT_CONNECTING:
|
||||
count_connecting_time = 0
|
||||
xmpp_state = XMPPState.MISSING_TLS
|
||||
else:
|
||||
count_connecting_time += delta
|
||||
else:
|
||||
count_connecting_time = 0
|
||||
xmpp_state = XMPPState.MISSING_TLS
|
||||
elif xmpp_state == XMPPState.STARTED_TLS:
|
||||
if tcp_peer.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||
xmpp_state = XMPPState.NONE
|
||||
count_connecting_time = 0
|
||||
return
|
||||
if ssl_peer.get_status() != StreamPeerTLS.STATUS_CONNECTED:
|
||||
xmpp_state = XMPPState.NONE
|
||||
count_connecting_time = 0
|
||||
return
|
||||
if count_connecting_time >= MAX_WAIT_CONNECTING:
|
||||
count_connecting_time = 0
|
||||
send_msg_debug.emit("send_ssl_initialize_xmpp")
|
||||
send_ssl_initialize_xmpp()
|
||||
else:
|
||||
count_connecting_time += delta
|
||||
if (ssl_peer.has_method("poll")):
|
||||
ssl_peer.poll()
|
||||
if ssl_peer.get_available_bytes()>0:
|
||||
var response = ssl_peer.get_string(ssl_peer.get_available_bytes())
|
||||
send_msg_debug.emit("Stream: response: " + response)
|
||||
response = remove_stream_header(response)
|
||||
if not analyze_error(response):
|
||||
if analyze_feature_mechanisms(response):
|
||||
if authentication_methods.size() > 0:
|
||||
count_connecting_time = MAX_WAIT_CONNECTING
|
||||
xmpp_state = XMPPState.AUTHENTICATE_STEP_1
|
||||
#send_msg_debug.emit("AUTHENTICATE_STEP_1")
|
||||
# elif response.begins_with("<success"):
|
||||
# stream_status = self.StreamState.STANZA
|
||||
if xmpp_state == XMPPState.AUTHENTICATE_STEP_1:
|
||||
if tcp_peer.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||
xmpp_state = XMPPState.NONE
|
||||
count_connecting_time = 0
|
||||
return
|
||||
if count_connecting_time >= MAX_WAIT_CONNECTING:
|
||||
count_connecting_time = 0
|
||||
negotiate_ssl_sasl(authentication_methods)
|
||||
else:
|
||||
count_connecting_time += delta
|
||||
if (ssl_peer.has_method("poll")):
|
||||
ssl_peer.poll()
|
||||
if ssl_peer.get_available_bytes()>0:
|
||||
var response = ssl_peer.get_string(ssl_peer.get_available_bytes())
|
||||
send_msg_debug.emit("Stream: response: " + response)
|
||||
response = remove_stream_header(response)
|
||||
if response.begins_with("<success"):
|
||||
count_connecting_time = 0
|
||||
xmpp_state = XMPPState.AUTHENTICATED
|
||||
|
||||
|
||||
func analyze_error(response:String) -> bool:
|
||||
if response.begins_with("<stream:error"):
|
||||
var stream_error = XMPPStreamError.new()
|
||||
stream_error.parse_from_xml(response)
|
||||
var error_name = stream_error.error_name_for_enum(stream_error.error_type)
|
||||
var error = tr('A stream error of type "%" occured, or in other words: % (Stream errors cannot be recovered from, the connection will be closed.'.format([error_name, stream_error.human_friendly_error_message()], "%)"))
|
||||
error.emit(error)
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func analyze_feature_starttls(response:String) -> bool:
|
||||
if response.begins_with("<stream:features"):
|
||||
var stream_features = XMPPStreamFeatures.new()
|
||||
stream_features.parse_from_xml(response)
|
||||
|
||||
if stream_features.parsedDictionary.has("starttls"):
|
||||
send_msg_debug.emit("Stream: sending request for ssl")
|
||||
var request_tls = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
|
||||
send_tcp_string(request_tls)
|
||||
stream_status = self.StreamState.TLS
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func analyze_feature_mechanisms(response:String) -> bool:
|
||||
if response.begins_with("<stream:features"):
|
||||
var stream_features = XMPPStreamFeatures.new()
|
||||
stream_features.parse_from_xml(response)
|
||||
if stream_features.parsedDictionary.has("mechanisms"):
|
||||
print("response:", response)
|
||||
authentication_methods = stream_features.parsedDictionary["mechanisms"]
|
||||
if (authentication_methods.size() > 0):
|
||||
var tmp:String = ""
|
||||
var sep:String = ""
|
||||
for item in authentication_methods:
|
||||
tmp += sep + item
|
||||
sep = ", "
|
||||
send_msg_debug.emit("Stream: authentication methods: " + tmp)
|
||||
#negotiate_ssl_sasl(authentication_methods)
|
||||
#stream_status = self.StreamState.AUTHENTICATE
|
||||
return true
|
||||
#negotiate_ssl_sasl(authentication_methods)
|
||||
return false
|
||||
|
||||
|
||||
func send_tcp_initialize_xmpp() -> void:
|
||||
""" Send the stream header.
|
||||
Needs to be done several times over stream negotiation.
|
||||
"""
|
||||
var message:String = "<?xml version='1.0'?>" + \
|
||||
"<stream:stream" + \
|
||||
" xmlns=\"jabber:client\"" + \
|
||||
" version=\"1.0\"" + \
|
||||
" xmlns:stream=\"http://etherx.jabber.org/streams\"" + \
|
||||
" to=\"" + server_xmpp_name + "\" " + \
|
||||
" xml:lang=\"en\"" + \
|
||||
" > "
|
||||
# " from=\"" + account_name + "\" " + \
|
||||
# + locale + "'" +
|
||||
print(message)
|
||||
send_tcp_string(message)
|
||||
|
||||
|
||||
func send_ssl_initialize_xmpp() -> void:
|
||||
""" Send the stream header.
|
||||
Needs to be done several times over stream negotiation.
|
||||
"""
|
||||
var server_name = account_name.split("@")[-1]
|
||||
var message:String = "<?xml version='1.0'?>" + \
|
||||
"<stream:stream" + \
|
||||
" xmlns=\"jabber:client\"" + \
|
||||
" version=\"1.0\"" + \
|
||||
" xmlns:stream=\"http://etherx.jabber.org/streams\"" + \
|
||||
" from=\"" + account_name + "\" " + \
|
||||
" to=\"" + server_name + "\" " + \
|
||||
" xml:lang=\"en\"" + \
|
||||
" > "
|
||||
# " from=\"" + account_name + "\" " + \
|
||||
# + locale + "'" +
|
||||
print(message)
|
||||
send_ssl_string(message)
|
||||
|
||||
|
||||
|
||||
func negotiate_ssl_sasl(authentication_methods : Array) -> bool:
|
||||
if ( authentication_methods.has("PLAIN")):
|
||||
send_msg_debug.emit("Stream: sending request for plain")
|
||||
var msg:PackedByteArray = PackedByteArray()
|
||||
msg.push_back(0)
|
||||
var t = account_name.split("@")[0]
|
||||
msg += t.to_ascii_buffer()
|
||||
#msg += conv_string_to_PackedByteArray(account_name.split("@")[0])
|
||||
msg.push_back(0)
|
||||
msg += password.to_ascii_buffer()
|
||||
var auth_account:String = Marshalls.raw_to_base64(msg)
|
||||
var request_sasl:String = "<auth" + \
|
||||
" xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" + \
|
||||
" mechanism='PLAIN'" + \
|
||||
" >" + auth_account + "</auth>"
|
||||
send_ssl_string(request_sasl)
|
||||
return true
|
||||
else:
|
||||
send_msg_error.emit("Impossible to authenticate (unknown protocol)")
|
||||
return false
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
func connect_to_server_xmpp() -> void:
|
||||
var res = tcp_peer.connect_to_host(server_xmpp_name, port_number)
|
||||
if res == OK:
|
||||
count_connecting_time = 0
|
||||
stream_status = self.StreamState.END
|
||||
set_process(true)
|
||||
tgt_peer = tcp_peer
|
||||
|
||||
func _process_old(delta) -> void:
|
||||
print(server_xmpp_name, ":", port_number, " / get_status:" , tcp_peer.get_status(), " / count_connecting_time:", count_connecting_time, " / stream_status:", stream_status)
|
||||
if tgt_peer.get_status() == StreamPeerTCP.STATUS_CONNECTED:
|
||||
print("STATUS_CONNECTED:", delta)
|
||||
if (tgt_peer.has_method("poll")):
|
||||
tgt_peer.poll()
|
||||
|
@ -109,15 +419,15 @@ func _process(delta):
|
|||
send_msg_debug.emit("Stream: response: " + response)
|
||||
if stream_status == self.StreamState.STANZA:
|
||||
#collect_stanza(remove_stream_header(response))
|
||||
Global.msg_info("", [])
|
||||
print("collect_stanza")
|
||||
else:
|
||||
print("stream_process")
|
||||
stream_process(remove_stream_header(response))
|
||||
# print(remove_stream_header(response))
|
||||
elif stream_status == self.StreamState.END:
|
||||
start_stream()
|
||||
stream_status = self.StreamState.START
|
||||
reinit_stream()
|
||||
#start_stream()
|
||||
#stream_status = self.StreamState.START
|
||||
count_connecting_time = 0
|
||||
if tgt_peer.get_status() == StreamPeerTCP.STATUS_CONNECTING:
|
||||
print("STATUS_CONNECTING:", delta)
|
||||
|
@ -132,6 +442,7 @@ func _process(delta):
|
|||
set_process(false) # stop listening for packets
|
||||
try_connect = 20
|
||||
stream_status = self.StreamState.END
|
||||
reinit_stream()
|
||||
if tgt_peer.get_status() == StreamPeerTCP.STATUS_NONE and xmppclient:
|
||||
print("connect_to_server:", xmppclient)
|
||||
connect_to_server()
|
||||
|
@ -144,7 +455,7 @@ func connect_to_server():
|
|||
pass
|
||||
if try_connect == 0 and tcp_peer.get_status() == StreamPeerTCP.STATUS_NONE:
|
||||
#print("-> ", server_ip, ":", port_number, "/" , tcp_peer.get_status())
|
||||
var res = tcp_peer.connect_to_host(server_ip, port_number)
|
||||
var res = tcp_peer.connect_to_host(server_xmpp_name, port_number)
|
||||
if res == OK:
|
||||
count_connecting_time = 0
|
||||
stream_status = self.StreamState.END
|
||||
|
@ -162,6 +473,18 @@ func send_string(stanza:String) ->void:
|
|||
tgt_peer.put_data(stanza.to_utf8_buffer())
|
||||
|
||||
|
||||
func send_tcp_string(stanza:String) ->void:
|
||||
""" Send a string in the appropriate encoding. """
|
||||
send_msg_debug.emit("Sending data: '%'".format([stanza], "%"))
|
||||
tcp_peer.put_data(stanza.to_utf8_buffer())
|
||||
|
||||
|
||||
func send_ssl_string(stanza:String) ->void:
|
||||
""" Send a string in the appropriate encoding. """
|
||||
send_msg_debug.emit("Sending data: '%'".format([stanza], "%"))
|
||||
ssl_peer.put_data(stanza.to_utf8_buffer())
|
||||
|
||||
|
||||
func conv_string_to_PackedByteArray(message:String) -> PackedByteArray:
|
||||
return message.to_ascii_buffer()
|
||||
|
||||
|
@ -277,7 +600,7 @@ func stream_process(response :String = "") -> void:
|
|||
print("Mystery stream status: "+str(stream_status))
|
||||
|
||||
|
||||
func negotiate_tls() -> void:
|
||||
func negotiate_tls() -> bool:
|
||||
#var ssl_peer = StreamPeerTLS.new()
|
||||
# I am unsure how to validate the ssl certificate for an unknown host?
|
||||
#var ssl_succes = FAILED
|
||||
|
@ -298,13 +621,14 @@ func negotiate_tls() -> void:
|
|||
print("get_status:", ssl_peer.get_status())
|
||||
print("-----")
|
||||
#stream_status == StreamState.START
|
||||
return true
|
||||
else:
|
||||
send_msg_error.emit("SSL failed, error %".format([ssl_succes], "%"))
|
||||
return false
|
||||
|
||||
|
||||
func negotiate_sasl(authentication_methods : Array) -> void:
|
||||
if (!authentication_methods.has("PLAIN")):
|
||||
end_stream()
|
||||
if ( authentication_methods.has("PLAIN")):
|
||||
send_msg_debug.emit("Stream: sending request for plain")
|
||||
var msg:PackedByteArray = PackedByteArray()
|
||||
msg.push_back(0)
|
||||
|
@ -313,14 +637,15 @@ func negotiate_sasl(authentication_methods : Array) -> void:
|
|||
#msg += conv_string_to_PackedByteArray(account_name.split("@")[0])
|
||||
msg.push_back(0)
|
||||
msg += password.to_ascii_buffer()
|
||||
print("7:", msg)
|
||||
|
||||
var auth_account:String = Marshalls.raw_to_base64(msg)
|
||||
var request_sasl:String = "<auth" + \
|
||||
" xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" + \
|
||||
" mechanism='PLAIN'" + \
|
||||
" >" + auth_account + "</auth>"
|
||||
send_string(request_sasl)
|
||||
else:
|
||||
send_msg_error.emit("Impossible to authenticate (unknown protocol)")
|
||||
end_stream()
|
||||
|
||||
|
||||
func end_stream() -> void:
|
||||
|
|
|
@ -35,7 +35,7 @@ func _ready():
|
|||
Multi.update_my_position.connect(_on_update_me)
|
||||
Multi.update_player_position.connect(_on_update_player)
|
||||
Multi.remove_player.connect(_on_remove_player)
|
||||
Stream.set_server_ip("localhost")
|
||||
Stream.set_server_xmpp_name("localhost")
|
||||
Stream.set_port_number(5222)
|
||||
Stream.send_msg_debug.connect(show_stream_debug)
|
||||
Stream.send_msg_error.connect(show_stream_error)
|
||||
|
|
Loading…
Reference in a new issue