digraph { /* new idea */ {rank=same; M_entry_whole_code M_title M_entry_allocation M_entry_interactive} M_entry_whole_code [label="whole\ncode"] M_entry_whole_code -> M_S1 M_title [label="Message\nMachine" style="dotted"] M_entry_whole_code -> M_title [style="invis"] M_entry_allocation [label="allocation"] M_entry_allocation -> M_S1B [label="already\nconnected"] M_entry_interactive [label="interactive"] M_entry_interactive -> M_S1B {rank=same; M_S1 M_S1B} M_S1 [label="1: know nothing"] M_S1B [label="1: know nothing\n(bound)"] M_S1 -> M_S1B [label="connect()"] M_S1B -> M_S1 [label="lose()"] M_S1 -> M_S2 [label="M_set_nameplate()"] M_S1B -> M_P_claim1 [label="M_set_nameplate()"] M_P_claim1 [shape="box" label="tx claim()"] M_P_claim1 -> M_S2B {rank=same; M_S2 M_S2B M_P_claim2} M_S2 [label="2: know nameplate\nwant claim\nunknown mailbox\nwant open"] M_S2B [label="2: know nameplate\nwant claim\nunknown mailbox\nwant open\n(bound)"] M_S2 -> M_P_claim2 [label="connect()"] M_S2B -> M_S2 [label="lose()"] M_P_claim2 [shape="box" label="tx claim()"] M_P_claim2 -> M_S2B M_S2 -> M_P2_queue [label="M_send(msg)" style="dotted"] M_P2_queue [shape="box" label="queue" style="dotted"] M_P2_queue -> M_S2 [style="dotted"] M_S2B -> M_P2B_queue [label="M_send(msg)" style="dotted"] M_P2B_queue [shape="box" label="queue" style="dotted"] M_P2B_queue -> M_S2B [style="dotted"] M_S2 -> M_S3 [label="(none)" style="invis"] M_S2B -> M_P_open [label="rx_claimed()"] M_P_open [shape="box" label="store mailbox\ntx open()\ntx add(queued)"] M_P_open -> M_S3B {rank=same; M_S3 M_S3B M_P3_open M_P3_send} M_S3 [label="3: claimed\nknown mailbox\nwant open"] M_S3B [label="3: claimed\nknown mailbox\nwant open\n(bound)"] M_S3 -> M_P3_open [label="connect()"] M_S3B -> M_S3 [label="lose()"] /*M_S3B -> M_S2 [label="lose()"]*/ /* not worth it */ M_P3_open [shape="box" label="tx open()\ntx add(queued)"] M_P3_open -> M_S3B M_S3B -> M_S3B [label="rx_claimed()"] M_S3B -> M_P3_send [label="M_send(msg)"] M_P3_send [shape="box" label="queue\ntx add(msg)"] M_P3_send -> M_S3B M_S3 -> M_P3_queue [label="M_send(msg)" style="dotted"] M_P3_queue [shape="box" label="queue" style="dotted"] M_P3_queue -> M_S3 [style="dotted"] M_S3 -> M_S4 [label="(none)" style="invis"] M_S3B -> M_P3_process_ours [label="rx_message(side=me)"] M_P3_process_ours [shape="box" label="dequeue"] M_P3_process_ours -> M_S3B M_S3B -> M_P3_process_theirs [label="rx_message(side!=me)"] M_P3_process_theirs [shape="box" label="tx release()\nprocess message"] M_P3_process_theirs -> M_S4B M_S3B -> M_P3_close [label="M_close()"] M_P3_close [shape="box" label="tx release()\n"] M_P3_close -> M_P_close {rank=same; M_S4 M_P4_release M_S4B M_P4_process M_P4_send M_P4_queue} M_S4 [label="4: released\nunwant nameplate\nwant mailbox\nopen\n"] M_S4B [label="4: released\nunwant nameplate\nwant mailbox\nopen\n(bound)"] M_S4 -> M_P4_release [label="connect()"] /* it is currently an error to release a nameplate you aren't currently claiming, so release() is not idempotent. #118 fixes that */ M_P4_release [shape="box" label="tx open()\ntx add(queued)\ntx release()"] /*M_S4B -> M_S4B [label="rx_claimed() *#118"]*/ M_S4B -> M_P_close [label="M_close()"] M_S4B -> M_P4_send [label="M_send(msg)"] M_P4_send [shape="box" label="queue\ntx add(msg)"] M_P4_send -> M_S4B M_S4 -> M_P4_queue [label="M_send(msg)" style="dotted"] M_P4_queue [shape="box" label="queue" style="dotted"] M_P4_queue -> M_S4 [style="dotted"] M_P4_release -> M_S4B M_S4B -> M_S4 [label="lose()"] /*M_S4B -> M_S2 [label="lose()"]*/ M_S4B -> M_P4_process [label="rx_message()"] M_P4_process [shape="box" label="process message"] M_P4_process -> M_S4B M_S4 -> M_S5 [label="(none)" style="invis"] M_S4B -> M_S5B [label="rx_released()"] seed [label="from Seed?"] seed -> M_S5 {rank=same; seed M_S5 M_S5B M_P5_open M_P5_process} M_S5 [label="5: released\nunwant nameplate\nwant mailbox\nopen\n"] M_S5B [label="5: released\nunwant nameplate\nwant mailbox\nopen\n(bound)" color="green"] M_S5 -> M_P5_open [label="connect()"] M_P5_open [shape="box" label="tx open()\ntx add(queued)"] M_P5_open -> M_S5B M_S5B -> M_S5 [label="lose()"] M_S5B -> M_P5_process [label="rx_message()"] M_P5_process [shape="box" label="process message"] M_P5_process -> M_S5B M_S5B -> M_P5_send [label="M_send(msg)"] M_P5_send [shape="box" label="queue\ntx add(msg)"] M_P5_send -> M_S5B M_S5 -> M_P5_queue [label="M_send(msg)" style="dotted"] M_P5_queue [shape="box" label="queue" style="dotted"] M_P5_queue -> M_S5 [style="dotted"] M_S5 -> M_S6 [label="M_close()"] /*M_S5 -> M_P7_drop [label="M_close()"]*/ M_S5B -> M_P_close [label="M_close()"] M_P_close [shape="box" label="tx close()"] M_P_close -> M_S6B {rank=same; M_S6 M_P6_close M_S6B} M_S6 [label="6: closing\nunwant mailbox\nopen\n"] M_S6B [label="6: closing\nunwant mailbox\nopen\n(bound)"] M_S6 -> M_P6_close [label="connect()"] M_P6_close [shape="box" label="tx close()"] M_P6_close -> M_S6B M_S6B -> M_S6 [label="lose()"] M_S6B -> M_S6B [label="rx_released()"] M_S6B -> M_S6B [label="M_close()"] M_S6B -> M_S6B [label="M_send()"] M_S6 -> M_S6 [label="M_send()"] M_S6 -> M_S7 [label="(none)" style="invis"] /*M_S6 -> M_P7_drop [label="M_close()"]*/ M_S6B -> M_P7_drop [label="rx_closed()"] M_P7_drop [shape="box" label="C_stop()"] M_P7_drop -> M_S7B {rank=same; M_S7 M_S7B} M_S7 [label="7: closed\n"] M_S7B [label="7: closed\n(bound)"] M_S7 -> M_S7B [label="connect()" style="invis"] M_S7B -> M_S7 [label="lose()"] M_S7B -> M_S7B [label="M_close()"] M_S7B -> M_S7B [label="M_send()"] M_process [shape="box" label="process"] M_process_me [shape="box" label="dequeue"] M_process -> M_process_me [label="side == me"] M_process_them [shape="box" label="" style="dotted"] M_process -> M_process_them [label="side != me"] M_process_them -> M_process_pake [label="phase == pake"] M_process_pake [shape="box" label="WM_rx_pake()"] M_process_them -> M_process_other [label="phase in (version,numbered)"] M_process_other [shape="box" label="WM_rx_msg()"] }