@@ -229,7 +229,27 @@ handshake_other_started(#hs_data{socket = Socket, f_recv = Recv} = HSData0) ->
229229 end .
230230
231231-spec handshake_we_started (# hs_data {}) -> no_return ().
232- handshake_we_started (# hs_data {}) -> ok .
232+ handshake_we_started (# hs_data {} = HSData0 ) ->
233+ HSData1 = HSData0 # hs_data {
234+ other_started = false ,
235+ this_flags = ? MANDATORY_DFLAGS
236+ },
237+ send_name (HSData1 ),
238+ case recv_status (HSData1 ) of
239+ <<" ok" >> -> ok ;
240+ <<" ok_simultaneous" >> -> ok ;
241+ <<" nok" >> -> ? shutdown ({HSData1 # hs_data .other_node , simultaneous });
242+ <<" alive" >> -> send_status (<<" true" >>, HSData1 );
243+ Other -> ? shutdown ({HSData1 # hs_data .other_node , {unexpected , Other }})
244+ end ,
245+ Cookie = net_kernel :get_cookie (HSData1 # hs_data .other_node ),
246+ {OtherChallenge , OtherFlags , Creation } = recv_challenge (HSData1 ),
247+ check_flags (OtherFlags , HSData1 ),
248+ <<MyChallenge :32 >> = crypto :strong_rand_bytes (4 ),
249+ send_challenge_reply (Cookie , OtherChallenge , MyChallenge , HSData1 ),
250+ OtherDigest = recv_challenge_ack (HSData1 ),
251+ check_challenge (Cookie , MyChallenge , OtherDigest , HSData1 ),
252+ connection (HSData1 , Creation ).
233253
234254% We are connected
235255-spec connection (# hs_data {}, non_neg_integer ()) -> no_return ().
@@ -359,6 +379,20 @@ check_flags(Flags0, HSData) ->
359379 ? shutdown (Reason )
360380 end .
361381
382+ % send name
383+ send_name (
384+ # hs_data {socket = Socket , f_send = Send , this_node = ThisNode , this_flags = ThisFlags } = HSData
385+ ) ->
386+ Creation = atomvm :get_creation (),
387+ NodeName = atom_to_binary (ThisNode , latin1 ),
388+ NameLen = byte_size (NodeName ),
389+ case Send (Socket , <<$N , ThisFlags :64 , Creation :32 , NameLen :16 , NodeName /binary >>) of
390+ {error , _ } = Error ->
391+ ? shutdown2 ({HSData # hs_data .other_node , Socket }, {send_name_failed , Error });
392+ ok ->
393+ ok
394+ end .
395+
362396% Ensure name is somewhat valid
363397-spec check_name (binary ()) -> ok .
364398check_name (Name ) ->
@@ -378,13 +412,13 @@ send_status(Status, #hs_data{socket = Socket, f_send = Send} = HSData) ->
378412 ok
379413 end .
380414
381- -spec recv_status_reply (# hs_data {}) -> binary ().
382- recv_status_reply (# hs_data {socket = Socket , f_recv = Recv } = HSData ) ->
415+ -spec recv_status (# hs_data {}) -> binary ().
416+ recv_status (# hs_data {socket = Socket , f_recv = Recv } = HSData ) ->
383417 case Recv (Socket , 0 , infinity ) of
384418 {ok , <<$s , Result /binary >>} ->
385419 Result ;
386420 {ok , Other } ->
387- ? shutdown ({HSData # hs_data .other_node , {unexpected , recv_status_reply , Other }});
421+ ? shutdown ({HSData # hs_data .other_node , {unexpected , recv_status , Other }});
388422 {error , Reason } ->
389423 ? shutdown2 ({HSData # hs_data .other_node , recv_error }, Reason )
390424 end .
@@ -403,7 +437,7 @@ mark_pending(#hs_data{kernel_pid = Kernel, this_node = ThisNode, other_node = Ot
403437 alive ->
404438 send_status (<<" alive" >>, HSData ),
405439 reset_timer (HSData # hs_data .timer ),
406- case recv_status_reply (HSData ) of
440+ case recv_status (HSData ) of
407441 <<" true" >> -> ok ;
408442 <<" false" >> -> ? shutdown (OtherNode );
409443 Other -> ? shutdown ({OtherNode , {unexpected , Other }})
@@ -434,6 +468,28 @@ send_challenge(
434468 ok
435469 end .
436470
471+ recv_challenge (
472+ # hs_data {other_node = OtherNode , socket = Socket , f_recv = Recv } = HSData
473+ ) ->
474+ case Recv (Socket , 0 , infinity ) of
475+ {ok , <<
476+ $N , OtherFlags :64 , Challenge :32 , OtherCreation :32 , _OtherNameLen :16 , OtherName /binary
477+ >>} ->
478+ case atom_to_binary (OtherNode , utf8 ) =/= OtherName of
479+ true ->
480+ ? shutdown ({
481+ HSData # hs_data .other_node , {mismatch , recv_challenge , OtherNode , OtherName }
482+ });
483+ false ->
484+ ok
485+ end ,
486+ {Challenge , OtherFlags , OtherCreation };
487+ {ok , Other } ->
488+ ? shutdown ({HSData # hs_data .other_node , {unexpected , recv_challenge , Other }});
489+ {error , Reason } ->
490+ ? shutdown2 ({HSData # hs_data .other_node , recv_error }, Reason )
491+ end .
492+
437493-spec recv_challenge_reply (# hs_data {}) -> {non_neg_integer (), binary ()}.
438494recv_challenge_reply (# hs_data {socket = Socket , f_recv = Recv } = HSData ) ->
439495 case Recv (Socket , 0 , infinity ) of
@@ -445,6 +501,23 @@ recv_challenge_reply(#hs_data{socket = Socket, f_recv = Recv} = HSData) ->
445501 ? shutdown2 ({HSData # hs_data .other_node , recv_error }, Reason )
446502 end .
447503
504+ -spec send_challenge_reply (
505+ Cookie :: binary (),
506+ OtherChallenge :: non_neg_integer (),
507+ MyChallenge :: non_neg_integer (),
508+ # hs_data {}
509+ ) -> ok .
510+ send_challenge_reply (
511+ Cookie , OtherChallenge , MyChallenge , # hs_data {socket = Socket , f_send = Send } = HSData
512+ ) ->
513+ Digest = gen_digest (Cookie , OtherChallenge ),
514+ case Send (Socket , <<$r , MyChallenge :32 , Digest :16 /binary >>) of
515+ {error , _ } = Error ->
516+ ? shutdown2 ({HSData # hs_data .other_node , Socket }, {send_challenge_reply_failed , Error });
517+ ok ->
518+ ok
519+ end .
520+
448521-spec check_challenge (
449522 Cookie :: binary (), Challenge :: non_neg_integer (), Digest :: binary (), # hs_data {}
450523) -> ok .
@@ -470,6 +543,17 @@ send_challenge_ack(Cookie, Challenge, #hs_data{socket = Socket, f_send = Send} =
470543 ok
471544 end .
472545
546+ -spec recv_challenge_ack (# hs_data {}) -> binary ().
547+ recv_challenge_ack (# hs_data {socket = Socket , f_recv = Recv } = HSData ) ->
548+ case Recv (Socket , 0 , infinity ) of
549+ {ok , <<$a , Digest /binary >>} ->
550+ Digest ;
551+ {ok , Other } ->
552+ ? shutdown ({HSData # hs_data .other_node , {unexpected , recv_challenge_ack , Other }});
553+ {error , _ } = Error ->
554+ ? shutdown2 ({HSData # hs_data .other_node , Socket }, {recv_challenge_ack , Error })
555+ end .
556+
473557-spec shutdown (atom (), non_neg_integer (), term ()) -> no_return ().
474558shutdown (Module , Line , Data ) ->
475559 shutdown (Module , Line , Data , shutdown ).
0 commit comments