aneris.examples.bag.bag

From aneris Require Export lang network notation tactics.
From aneris.examples.library Require Export lib lock bag.

Definition serve : ground_lang.val :=
  λ: "socket" "bag",
  (rec: "loop" <> :=
     match: ReceiveFrom "socket" with
       SOME "m" => let: "msg" := Fst "m" in
                   let: "sender" := Snd "m" in
                   if: "msg" = #""
                   then
                     let: "v" := remove "bag" in
                     match: "v" with
                       SOME "v" => SendTo "socket" "v" "sender"
                     | NONE => SendTo "socket" #"" "sender"
                     end
                   else
                     insert "bag" "msg";;
                     SendTo "socket" #"" "sender"
     | NONE => #()
     end;;
     "loop" #()
  ) #().

Definition bag_service : ground_lang.val :=
  λ: "addr",
  let: "socket" := NewSocket #Network.PF_INET
                             #Network.SOCK_DGRAM
                             #Network.IPPROTO_UDP in
  let: "bag" := newbag #() in
  SocketBind "socket" "addr";;
  Fork (serve "socket" "bag");;
  Fork (serve "socket" "bag").

Definition client : ground_lang.val :=
  λ: "arg" "addr" "server",
  let: "socket" := NewSocket #Network.PF_INET
                             #Network.SOCK_DGRAM
                             #Network.IPPROTO_UDP in
  SocketBind "socket" "addr";;
  SendTo "socket" "arg" "server";;
  Fst (listen_wait "socket").

Definition bag_runner :=
  "system";
   let: "caddr0" := MakeAddress #"0.0.0.0" #80 in
   let: "caddr1" := MakeAddress #"0.0.0.1" #80 in
   let: "caddr2" := MakeAddress #"0.0.0.2" #80 in
   let: "saddr" := MakeAddress #"1.1.1.1" #80 in
   Start "server" "1.1.1.1" (bag_service "saddr");;
   Start "client0" "0.0.0.0" (client #"2" "caddr0" "saddr");;
   Start "client1" "0.0.0.1" (client #"" "caddr1" "saddr");;
   Start "client2" "0.0.0.2" (client #"4" "caddr2" "saddr")
  .