Echo
include ip
include udp
include order
object ip = {
type endpoint
interpret endpoint -> bv[1]
}
type data
type message
object request = {
variant this of message = struct {
content : data
}
}
object response = {
variant this of message = struct {
content : data
}
}
type pkt = struct {
src : ip.endpoint,
payload : message
}
isolate protocol = {
action request_event(src:ip.endpoint,dst:ip.endpoint,msg:request)
action response_event(src:ip.endpoint,dst:ip.endpoint,msg:response)
specification {
relation request_sent(X:data,S:ip.endpoint,D:ip.endpoint)
relation response_sent(X:data,S:ip.endpoint,D:ip.endpoint)
after init {
request_sent(X,S,D) := false;
response_sent(X,S,D) := false;
}
after request_event {
request_sent(msg.content,src,dst) := true
}
around response_event {
require request_sent(msg.content,dst,src);
...
response_sent(msg.content,src,dst) := true
}
invariant response_sent(X,S,D) -> request_sent(X,D,S)
}
}
after init { some_requested := false; }
after message_event { if msg isa request { some_requested := true } else { ensure some_requested } }
invariant request_sent(X,S,D) -> some_requested
export message_event
isolate service = {
isolate net = {
action recv(dst:ip.endpoint,src:ip.endpoint,v:message)
action send(src:ip.endpoint,dst:ip.endpoint,v:message)
specification {
relation sent(X:message,S:ip.endpoint,D:ip.endpoint)
after init {
sent(X,S,D) := false
}
before send {
sent(v,src,dst) := true
}
before recv {
require sent(v,src,dst)
}
}
implementation {
instance low : udp_simple(ip.endpoint,pkt)
implement send {
var p : pkt;
p.src := src;
p.payload := v;
call low.send(src,dst,p)
}
implement low.recv(dst:ip.endpoint,v:pkt) {
call recv(dst,v.src,v.payload)
}
}
private {
invariant low.spec.sent(P,D) -> sent(payload(P),src(P),D)
}
}
action client_request(self:ip.endpoint,dst:ip.endpoint,content:data)
action client_response(self:ip.endpoint,content:data)
specification {
var request_pending(S:ip.endpoint) : bool
var request_content(S:ip.endpoint) : data
before client_request {
require ~request_pending(self);
request_pending(self) := true;
request_content(self) := content;
}
before client_response {
require request_pending(self);
require content = request_content(self);
}
}
implementation {
implement client_request {
var m : request;
m.content := content;
call net.send(self,dst,m);
call protocol.request_event(self,dst,m);
}
implement net.recv(self:ip.endpoint,src:ip.endpoint,m:message) {
if some (req:request) m *> req {
var resp : response;
resp.content := req.content;
call net.send(self,src,resp);
call protocol.response_event(self,src,resp)
} else if some (resp:response) m *> resp {
call client_response(self,resp.content);
}
}
}
private {
invariant net.sent(M,S,D) & M *> (R:request) -> protocol.request_sent(request.content(R),S,D)
invariant net.sent(M,S,D) & M *> (R:response) -> protocol.response_sent(response.content(R),S,D)
invariant protocol.request_sent(X,S,D) -> request_pending(S) & request_content(S) = X
}
} with protocol
export service.client_request
import service.client_response
extract process(self:ip.endpoint) = service(self)