@@ -229,7 +229,27 @@ handshake_other_started(#hs_data{socket = Socket, f_recv = Recv} = HSData0) ->
229
229
end .
230
230
231
231
-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 ).
233
253
234
254
% We are connected
235
255
-spec connection (# hs_data {}, non_neg_integer ()) -> no_return ().
@@ -359,6 +379,20 @@ check_flags(Flags0, HSData) ->
359
379
? shutdown (Reason )
360
380
end .
361
381
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
+
362
396
% Ensure name is somewhat valid
363
397
-spec check_name (binary ()) -> ok .
364
398
check_name (Name ) ->
@@ -378,13 +412,13 @@ send_status(Status, #hs_data{socket = Socket, f_send = Send} = HSData) ->
378
412
ok
379
413
end .
380
414
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 ) ->
383
417
case Recv (Socket , 0 , infinity ) of
384
418
{ok , <<$s , Result /binary >>} ->
385
419
Result ;
386
420
{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 }});
388
422
{error , Reason } ->
389
423
? shutdown2 ({HSData # hs_data .other_node , recv_error }, Reason )
390
424
end .
@@ -403,7 +437,7 @@ mark_pending(#hs_data{kernel_pid = Kernel, this_node = ThisNode, other_node = Ot
403
437
alive ->
404
438
send_status (<<" alive" >>, HSData ),
405
439
reset_timer (HSData # hs_data .timer ),
406
- case recv_status_reply (HSData ) of
440
+ case recv_status (HSData ) of
407
441
<<" true" >> -> ok ;
408
442
<<" false" >> -> ? shutdown (OtherNode );
409
443
Other -> ? shutdown ({OtherNode , {unexpected , Other }})
@@ -434,6 +468,28 @@ send_challenge(
434
468
ok
435
469
end .
436
470
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
+
437
493
-spec recv_challenge_reply (# hs_data {}) -> {non_neg_integer (), binary ()}.
438
494
recv_challenge_reply (# hs_data {socket = Socket , f_recv = Recv } = HSData ) ->
439
495
case Recv (Socket , 0 , infinity ) of
@@ -445,6 +501,23 @@ recv_challenge_reply(#hs_data{socket = Socket, f_recv = Recv} = HSData) ->
445
501
? shutdown2 ({HSData # hs_data .other_node , recv_error }, Reason )
446
502
end .
447
503
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
+
448
521
-spec check_challenge (
449
522
Cookie :: binary (), Challenge :: non_neg_integer (), Digest :: binary (), # hs_data {}
450
523
) -> ok .
@@ -470,6 +543,17 @@ send_challenge_ack(Cookie, Challenge, #hs_data{socket = Socket, f_send = Send} =
470
543
ok
471
544
end .
472
545
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
+
473
557
-spec shutdown (atom (), non_neg_integer (), term ()) -> no_return ().
474
558
shutdown (Module , Line , Data ) ->
475
559
shutdown (Module , Line , Data , shutdown ).
0 commit comments