2023-12-17 00:03:48 +00:00
extends Node
# Stream XMPP
# Author : AleaJactaEst
#
# https://xmpp.org/extensions/xep-0178.html
# https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml
# Boucle
# - non connecte
# - connecte en claire
# - connecte en TLS
# - lance l'authentification
# - step authentification
# - identifie
signal send_msg_debug ( message : String )
signal send_msg_error ( message : String )
signal new_stanza ( stanza )
enum StreamState {
END , # Stream is over. Starting with this.
START , # Stream hass started.
TLS , # Connection has been made and the first header is send. Let's get ssl!
AUTHENTICATE , # We have negotiated whether to use TLS, let's authenticate.
STANZA # We have authenticated, account is now allowed to send stanzas
}
var stream_status = StreamState . END
2023-12-18 20:25:25 +00:00
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
}
@ export var server_xmpp_name : String = " localhost " :
set = set_server_xmpp_name , get = get_server_xmpp_name
2023-12-17 00:03:48 +00:00
2023-12-18 20:25:25 +00:00
func set_server_xmpp_name ( value : String ) :
server_xmpp_name = value
2023-12-17 00:03:48 +00:00
2023-12-18 20:25:25 +00:00
func get_server_xmpp_name ( ) - > String :
return server_xmpp_name
2023-12-17 00:03:48 +00:00
@ export var port_number : int = 5222 :
set = set_port_number , get = get_port_number
func set_port_number ( value : int ) :
port_number = value
func get_port_number ( ) - > int :
return port_number
@ export var account_name : String = " undefined@localhost " :
set = set_account_name , get = get_account_name
func set_account_name ( value : String ) :
account_name = value
func get_account_name ( ) - > String :
return account_name
@ export var password : String = " undefined " :
set = set_password , get = get_password
func set_password ( value : String ) :
password = value
func get_password ( ) - > String :
return password
@ export var locale : String = " en " :
set = set_locale , get = get_locale
func set_locale ( value : String ) :
locale = value
func get_locale ( ) - > String :
return locale
@ export var xmppclient : bool = false :
get :
return xmppclient
set ( value ) :
xmppclient = value
2023-12-18 20:25:25 +00:00
const MAX_WAIT_CONNECTING : float = 60.0
const MAX_WAIT_MISSING_TLS : float = 1800.0
2023-12-17 00:03:48 +00:00
var try_connect : int = 0
2023-12-18 20:25:25 +00:00
var count_connecting_time : float = MAX_WAIT_CONNECTING
2023-12-17 00:03:48 +00:00
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
2023-12-18 20:25:25 +00:00
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
2023-12-17 00:03:48 +00:00
2023-12-18 20:25:25 +00:00
func _init ( ) - > void :
2023-12-17 00:03:48 +00:00
var language = OS . get_locale ( )
set_locale ( language )
tgt_peer = tcp_peer
2023-12-18 20:25:25 +00:00
# reinit_stream()
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
2023-12-17 00:03:48 +00:00
2023-12-18 20:25:25 +00:00
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 :
2023-12-17 00:03:48 +00:00
print ( " STATUS_CONNECTED: " , delta )
if ( tgt_peer . has_method ( " poll " ) ) :
tgt_peer . poll ( )
if tgt_peer . get_available_bytes ( ) > 0 :
var response = tgt_peer . get_string ( tgt_peer . get_available_bytes ( ) )
send_msg_debug . emit ( " Stream: response: " + response )
if stream_status == self . StreamState . STANZA :
#collect_stanza(remove_stream_header(response))
print ( " collect_stanza " )
else :
print ( " stream_process " )
stream_process ( remove_stream_header ( response ) )
# print(remove_stream_header(response))
elif stream_status == self . StreamState . END :
2023-12-18 20:25:25 +00:00
reinit_stream ( )
#start_stream()
#stream_status = self.StreamState.START
2023-12-17 00:03:48 +00:00
count_connecting_time = 0
if tgt_peer . get_status ( ) == StreamPeerTCP . STATUS_CONNECTING :
print ( " STATUS_CONNECTING: " , delta )
count_connecting_time += delta
if ( tgt_peer . has_method ( " poll " ) ) :
tgt_peer . poll ( )
if count_connecting_time > 60 : # (1 -> 1s) if it took more than 1s to connect, error
print ( " **** Stream: Stuck connecting, will now disconnect " )
Global . msg_error ( " Stream: Stuck connecting, will now disconnect " , [ ] )
send_msg_debug . emit ( " Stream: Stuck connecting, will now disconnect " )
tgt_peer . disconnect_from_host ( ) #interrupts connection to nothing
set_process ( false ) # stop listening for packets
try_connect = 20
stream_status = self . StreamState . END
2023-12-18 20:25:25 +00:00
reinit_stream ( )
2023-12-17 00:03:48 +00:00
if tgt_peer . get_status ( ) == StreamPeerTCP . STATUS_NONE and xmppclient :
print ( " connect_to_server: " , xmppclient )
connect_to_server ( )
xmppclient = false
func connect_to_server ( ) :
""" Connect to the server ip and port, and start checking whether there ' s stream info yet. """
if tcp_peer . get_status ( ) == StreamPeerTCP . STATUS_CONNECTED :
pass
if try_connect == 0 and tcp_peer . get_status ( ) == StreamPeerTCP . STATUS_NONE :
#print("-> ", server_ip, ":", port_number, "/" , tcp_peer.get_status())
2023-12-18 20:25:25 +00:00
var res = tcp_peer . connect_to_host ( server_xmpp_name , port_number )
2023-12-17 00:03:48 +00:00
if res == OK :
count_connecting_time = 0
stream_status = self . StreamState . END
set_process ( true )
tgt_peer = tcp_peer
else :
try_connect = 20
else :
try_connect -= 1
func send_string ( stanza : String ) - > void :
""" Send a string in the appropriate encoding. """
send_msg_debug . emit ( " Sending data: ' % ' " . format ( [ stanza ] , " % " ) )
tgt_peer . put_data ( stanza . to_utf8_buffer ( ) )
2023-12-18 20:25:25 +00:00
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 ( ) )
2023-12-17 00:03:48 +00:00
func conv_string_to_PackedByteArray ( message : String ) - > PackedByteArray :
return message . to_ascii_buffer ( )
#func send_PackedByteArray(message:PackedByteArray) -> void:
# """ Send a PackedByteArray """
# send_msg_debug.emit("Sending data: '" + message.get_string_from_utf8() + "'")
# tgt_peer.put_data(message)
func start_stream ( ) - > 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_string ( message )
func remove_stream_header ( text : String ) - > String :
var index = 0
if text . begins_with ( " <? " ) :
# Strip xml header
index = text . find ( " ?> " )
text = text . substr ( index + 2 ) . strip_edges ( )
# strip stream header
var rg = RegEx . new ( )
rg . compile ( " < \\ s?(stream|stream:stream) \\ s " )
var result = rg . search ( text )
if result :
send_msg_debug . emit ( " Stream: Response header received " )
index = text . find ( " > " , result . get_end ( ) )
text = text . substr ( index + 1 )
return text
func stream_process ( response : String = " " ) - > void :
""" Try to authenticate using SASL. We can currently only do plain.
For SCRAM based methods , we need HMAC at the very least .
"""
if ( ! response . length ( ) == 0 and stream_status != self . StreamState . STANZA ) :
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: % \n \n Stream errors cannot be recovered from, the connection will be closed. ' . format ( [ error_name , stream_error . human_friendly_error_message ( ) ] , " % " ) )
error . emit ( error )
elif 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_string ( request_tls )
stream_status = self . StreamState . TLS
elif stream_features . parsedDictionary . has ( " mechanisms " ) :
print ( " response: " , response )
var 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_sasl ( authentication_methods )
stream_status = self . StreamState . AUTHENTICATE
else :
if stream_status == StreamState . TLS :
if response . begins_with ( " <proceed " ) :
send_msg_debug . emit ( " Stream: gotten go ahead for ssl " )
negotiate_tls ( )
else :
send_msg_error . emit ( tr ( " Tls negotiation failed. " ) )
elif stream_status == StreamState . AUTHENTICATE :
if response . begins_with ( " <success " ) :
stream_status = self . StreamState . STANZA
# start_stream()
return
else :
var parser = XMLParser . new ( )
# parser.open_buffer(response.to_utf8())
var failure_text = [ ]
while parser . read ( ) == OK :
if parser . get_node_type ( ) == XMLParser . NODE_TEXT :
failure_text . append ( parser . get_node_data ( ) )
print ( failure_text )
# failure_text = tr("Authentication failed! %".format([PoolStringArray(failure_text).join(" ")], "%"))
var msg : String = " "
for item in failure_text :
msg += item
send_msg_error . emit ( msg )
elif stream_status == self . StreamState . START :
connect_to_server ( )
start_stream ( )
else :
print ( " Mystery stream status: " + str ( stream_status ) )
2023-12-18 20:25:25 +00:00
func negotiate_tls ( ) - > bool :
2023-12-17 00:03:48 +00:00
#var ssl_peer = StreamPeerTLS.new()
# I am unsure how to validate the ssl certificate for an unknown host?
#var ssl_succes = FAILED
var options : TLSOptions = TLSOptions . client_unsafe ( )
print ( " accept_stream " )
#var ssl_succes = ssl_peer.accept_stream(tcp_peer, options)
var ssl_succes = ssl_peer . connect_to_stream ( tcp_peer , " localhost " , options )
print ( " resultat: " , ssl_succes )
if ssl_succes == OK :
send_msg_debug . emit ( " Stream: switched to SSL! " )
print ( " get_status: " , ssl_peer . get_status ( ) )
# Wait connection done
while ssl_peer . get_status ( ) == StreamPeerTLS . STATUS_HANDSHAKING :
ssl_peer . poll ( )
print ( " get_status: " , ssl_peer . get_status ( ) )
tgt_peer = ssl_peer
start_stream ( )
print ( " get_status: " , ssl_peer . get_status ( ) )
print ( " ----- " )
#stream_status == StreamState.START
2023-12-18 20:25:25 +00:00
return true
2023-12-17 00:03:48 +00:00
else :
send_msg_error . emit ( " SSL failed, error % " . format ( [ ssl_succes ] , " % " ) )
2023-12-18 20:25:25 +00:00
return false
2023-12-17 00:03:48 +00:00
func negotiate_sasl ( authentication_methods : Array ) - > void :
2023-12-18 20:25:25 +00:00
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 " + \
2023-12-17 00:03:48 +00:00
" xmlns= ' urn:ietf:params:xml:ns:xmpp-sasl ' " + \
" mechanism= ' PLAIN ' " + \
" > " + auth_account + " </auth> "
2023-12-18 20:25:25 +00:00
send_string ( request_sasl )
else :
send_msg_error . emit ( " Impossible to authenticate (unknown protocol) " )
end_stream ( )
2023-12-17 00:03:48 +00:00
func end_stream ( ) - > void :
""" End the stream """
send_msg_debug . emit ( " Stream: Ending stream " )
send_string ( " </stream> " )
if tcp_peer . has_method ( " disconnect_from_stream " ) :
tcp_peer . disconnect_from_stream ( )
else :
tcp_peer . disconnect_from_host ( )
set_process ( false )
stream_status = StreamState . END