@@ -17,12 +17,12 @@ Open Scope Z_scope.
1717Open Scope sint63_scope.
1818Open Scope list_scope.
1919Open Scope monad_scope.
20-
2120(** ** Usernames
2221
2322 Usernames have specific properties per the project requirements. This
2423 section implements a dependently-typed Record type for usernames and some
2524 automation to create them at will.
25+
2626 *)
2727
2828(**
@@ -34,6 +34,8 @@ Record username : Type := {
3434 (1 <= to_Z (int_len_string Uname) <= 32)%Z
3535 ; NoSpaces :
3636 ~ InString space Uname
37+ ; NoNulls :
38+ ~ InString (ascii_of_byte "000"%byte) Uname
3739}.
3840
3941(**
@@ -49,7 +51,7 @@ Record username : Type := {
4951 *)
5052Definition validate_username (name : string) : bool :=
5153 ((1 <=? int_len_string name) && (int_len_string name <=? 32))
52- && (no_spaces name).
54+ && (no_spaces name) && (no_nulls name) .
5355
5456(**
5557 Ensure that [validate_username] provides
@@ -60,45 +62,58 @@ Theorem validate_username_correct :
6062 forall (name : string)
6163 (VALID : validate_username name = true),
6264 (1 <= to_Z (int_len_string name) <= 32)%Z /\
63- ~ InString space name.
65+ ~ InString space name /\ ~ InString (ascii_of_byte "000"%byte) name .
6466Proof .
6567 intros. unfold validate_username in VALID.
66- apply andb_true_iff in VALID.
67- destruct VALID as [Length NoSpaces].
68- apply andb_true_iff in Length.
69- destruct Length as [NonEmpty Le32].
68+ rewrite andb_true_iff in VALID.
69+ destruct VALID as (VALID & NoNulls).
70+ rewrite andb_true_iff in VALID.
71+ destruct VALID as (VALID & NoSpaces).
72+ rewrite andb_true_iff in VALID.
73+ destruct VALID as (NonEmpty & Le32).
7074 apply leb_spec in NonEmpty, Le32.
7175 split.
72- - change 1%Z with (to_Z 1). now split.
76+ change 1%Z with (to_Z 1). now split.
77+ split.
7378 - clear - NoSpaces. induction name as [| a name']. auto.
7479 simpl. simpl in NoSpaces.
7580 destruct (ascii_dec a space) as [a_space|a_space].
7681 -- inversion NoSpaces.
7782 -- intro Contra. destruct Contra.
7883 + now apply a_space.
7984 + now apply IHname'.
85+ - clear - NoNulls. induction name as [| a name']. auto.
86+ simpl. simpl in NoNulls.
87+ destruct (ascii_dec a (ascii_of_byte "000"%byte)) as [a_null|a_null].
88+ -- inversion NoNulls.
89+ -- intro Contra. destruct Contra.
90+ + now apply a_null.
91+ + now apply IHname'.
8092Qed .
8193
8294(**
8395 Instantiate a username object if it
8496 passes [validate_username], or return
8597 [None]
8698 *)
87- Definition new_username (s : string) : optionE username.
99+ Definition new_username (s : string) : result username.
88100 destruct (validate_username s) eqn:E.
89101 - apply validate_username_correct in E.
90- destruct E.
91- exact (SomeE {|
102+ destruct E, H0 .
103+ exact (Ok {|
92104 Uname := s;
93105 ValidLength := H;
94- NoSpaces := H0
106+ NoSpaces := H0;
107+ NoNulls := H1
95108 |}).
96109 - destruct (no_spaces s).
97- -- (* No Spaces *)
98- exact (NoneE
110+ -- (* No Spaces *)
111+ destruct (no_nulls s).
112+ exact (Error ("Username cannot contain nulls")).
113+ exact (Error
99114 ("Username length must be in range [1..32]: '" ++ s ++ "'")).
100115 -- (* Spaces *)
101- exact (NoneE ("Username cannot contain spaces: '" ++ s ++ "'")).
116+ exact (Error ("Username cannot contain spaces: '" ++ s ++ "'")).
102117Defined .
103118
104119(** A placeholder username *)
@@ -107,7 +122,9 @@ Definition dummy_username : username.
107122 (split; unfold to_Z, Uint63.to_Z; simpl; lia).
108123 assert (~ InString space "X") by
109124 (intro; destruct H0; [discriminate | auto]).
110- exact {|Uname := "X"; ValidLength := H; NoSpaces := H0|}.
125+ assert (~ InString (ascii_of_byte "000"%byte) "X") by
126+ (intro; destruct H1; [discriminate | auto]).
127+ exact {|Uname := "X"; ValidLength := H; NoSpaces := H0; NoNulls := H1|}.
111128Defined .
112129
113130(** Username equality *)
@@ -183,7 +200,7 @@ Definition serialize_client_message (cm : client_message) : bytes :=
183200 end .
184201
185202(** Convert a list of [byte]s into a [client_message] *)
186- Definition deserialize_client_message (b : bytes) : optionE client_message :=
203+ Definition deserialize_client_message (b : bytes) : result client_message :=
187204 match b with
188205 | x00 :: t =>
189206 uname <- new_username (trim_null t) ;;
@@ -197,9 +214,65 @@ Definition deserialize_client_message (b : bytes) : optionE client_message :=
197214 | x03 :: t =>
198215 uname <- new_username (trim_null t) ;;
199216 return (EXIT uname)
200- | _ => NoneE ("Client message code not recognized: " ++ (string_of_bytes b))
217+ | _ => Error ("Client message code not recognized: " ++ (string_of_bytes b))
201218 end .
202219
220+ Lemma create_null_list_forall : forall n,
221+ Forall (fun b0 : byte => b0 = "000"%byte) (create_list_nat "000"%byte n).
222+ Proof .
223+ induction n.
224+ apply Forall_nil.
225+ apply Forall_cons. reflexivity.
226+ apply IHn.
227+ Qed .
228+
229+ Lemma trim_null_app : forall n l,
230+ trim_null (l ++ create_list_nat "000"%byte n) = trim_null l.
231+ Proof .
232+ intros. pose proof (create_null_list_forall n).
233+ remember (create_list_nat _ _).
234+ clear Heql0.
235+ induction l.
236+ Admitted .
237+
238+ Lemma trim_null_pad_r : forall (s : string) (p : int),
239+ trim_null (bytes_of_string (pad_string_r s "000" p)) = trim_null (bytes_of_string s).
240+ Proof .
241+ intros. unfold pad_string_r. rewrite bytes_of_string_app, bytes_of_string_of_bytes.
242+ unfold create_list. apply trim_null_app.
243+ Qed .
244+
245+ Lemma not_instring_inv : forall c a s,
246+ ~ InString c (String a s) -> c <> a /\ ~ InString c s.
247+ Proof .
248+ intros. split.
249+ intro. apply H. subst. unfold InString. now left.
250+ intro. apply H. unfold InString. right. apply H0.
251+ Qed .
252+
253+ Lemma trim_null_uname : forall uname,
254+ trim_null (bytes_of_string (Uname uname)) = Uname uname.
255+ Proof .
256+ intros. pose proof (NoNulls uname). induction (Uname uname).
257+ reflexivity.
258+ apply not_instring_inv in H. destruct H.
259+ Admitted .
260+
261+ Lemma new_username_clean : forall (name : username),
262+ new_username (trim_null (bytes_of_string (pad_string_r (Uname name) "000" 32))) = Ok name.
263+ Proof .
264+ intros. rewrite trim_null_pad_r, trim_null_uname.
265+ enough (validate_username (Uname name) = true).
266+ Admitted .
267+
268+ Theorem serialize_client_message_safe :
269+ forall (cm : client_message),
270+ deserialize_client_message (serialize_client_message cm) = Ok cm.
271+ Proof .
272+ intros. destruct cm.
273+ - simpl. unfold serialize_username. now rewrite new_username_clean.
274+ Admitted .
275+
203276Theorem serialize_username_len : forall (u : username),
204277 int_len_list (serialize_username u) = 32.
205278Proof .
@@ -308,7 +381,7 @@ Definition serialize_server_message (sm : server_message) : bytes :=
308381 end .
309382
310383(** Convert a list of [byte]s into a [server_message] *)
311- Definition deserialize_server_message (b : bytes) : optionE server_message :=
384+ Definition deserialize_server_message (b : bytes) : result server_message :=
312385 match b with
313386 (** This case isn't helpful... why should we deserialize
314387 something when we don't even know how many bytes to pull?
@@ -346,7 +419,7 @@ Function resend
346419 (sockfd : file_descr) (message : bytes)
347420 (len_msg : int)
348421 {measure (fun x => (Z.to_nat (to_Z x))) fuel}
349- : optionE unit :=
422+ : result unit :=
350423 if sub1_no_underflow fuel then
351424 let send_result := n_sent + send sockfd message n_sent (len_msg - n_sent) [] in
352425 (* If uncommented, the extractor will call [send] twice, because it tries
@@ -355,45 +428,45 @@ Function resend
355428 if send_result <? len_msg then
356429 resend (fuel - 1) send_result sockfd message len_msg
357430 else
358- SomeE tt
431+ Ok tt
359432 else
360- NoneE ("Timed out while sending message '" ++ (string_of_bytes message) ++ "'").
433+ Error ("Timed out while sending message '" ++ (string_of_bytes message) ++ "'").
361434 prove_sub1.
362435Defined .
363436
364437(** Wrapper for [resend] *)
365- Definition send_message (sockfd : file_descr) (message : bytes) : optionE unit :=
438+ Definition send_message (sockfd : file_descr) (message : bytes) : result unit :=
366439 resend 100 0 sockfd message (int_len_list message).
367440
368441(** Receives a message from a socket *)
369- Definition recv_message (sockfd : file_descr) (len : int) : optionE bytes :=
442+ Definition recv_message (sockfd : file_descr) (len : int) : result bytes :=
370443 match recv sockfd 0 len [] with
371- | (_, out) => SomeE out
444+ | (_, out) => Ok out
372445 end .
373446
374447(** Receives a message from a socket and deserializes it as a client message *)
375- (* Definition recv_client_message (sockfd : file_descr) : optionE client_message :=
448+ (* Definition recv_client_message (sockfd : file_descr) : result client_message :=
376449 msg_bytes <- recv_message sockfd max_message_len ;;
377450 deserialize_client_message msg_bytes. *)
378451
379452(** Receives an int from a socket *)
380- Definition recv_int (sockfd : file_descr) : optionE int :=
453+ Definition recv_int (sockfd : file_descr) : result int :=
381454 n_bytes <- recv_message sockfd 8 ;;
382455 return bytes_to_int63 (n_bytes).
383456
384457(** Receives a string from a socket *)
385- Definition recv_string (sockfd : file_descr) : optionE string :=
458+ Definition recv_string (sockfd : file_descr) : result string :=
386459 str_len <- recv_int sockfd ;;
387460 str_bytes <- recv_message sockfd str_len ;;
388461 return string_of_bytes (str_bytes).
389462
390- Definition recv_username (sockfd : file_descr) : optionE username :=
463+ Definition recv_username (sockfd : file_descr) : result username :=
391464 username_bytes <- recv_message sockfd 32 ;;
392465 uname <- new_username (string_of_bytes username_bytes) ;;
393466 return uname.
394467
395468(** Receives an ACK message *)
396- Definition recv_server_ACK (sockfd : file_descr) : optionE server_message :=
469+ Definition recv_server_ACK (sockfd : file_descr) : result server_message :=
397470 (* Receive a serialized int63 detailing number of connected users *)
398471 num_users <- recv_int sockfd ;;
399472 usernames_bytes <- recv_message sockfd (num_users * 32) ;;
@@ -404,18 +477,18 @@ Definition recv_server_ACK (sockfd : file_descr) : optionE server_message :=
404477 return ACK num_users usernames.
405478
406479(** Receives a server MSG message *)
407- Definition recv_server_MSG (sockfd : file_descr) : optionE server_message :=
480+ Definition recv_server_MSG (sockfd : file_descr) : result server_message :=
408481 username <- recv_username sockfd ;;
409482 msg <- recv_string sockfd ;;
410483 return MSG username msg.
411484
412- Definition recv_server_ERR (sockfd : file_descr) : optionE server_message :=
485+ Definition recv_server_ERR (sockfd : file_descr) : result server_message :=
413486 err_code <- recv_int sockfd ;;
414487 return ERR (error_of_int err_code).
415488
416489(** Consumes the message code and dispatches to specific receiver functions to
417490 deserialize and parse a server message *)
418- Definition recv_server_message (sockfd : file_descr) : optionE server_message :=
491+ Definition recv_server_message (sockfd : file_descr) : result server_message :=
419492 code <- recv_message sockfd 1 ;;
420493 match code with
421494 | [x00] => recv_server_ACK sockfd
@@ -424,24 +497,24 @@ Definition recv_server_message (sockfd : file_descr) : optionE server_message :=
424497 | _ => fail ("Failed to receieve server message with opcode " ++ (string_of_bytes code))
425498 end .
426499
427- Definition recv_client_REG (sockfd : file_descr) : optionE client_message :=
500+ Definition recv_client_REG (sockfd : file_descr) : result client_message :=
428501 uname <- recv_username sockfd ;;
429502 return REG uname.
430503
431- Definition recv_client_MESG (sockfd : file_descr) : optionE client_message :=
504+ Definition recv_client_MESG (sockfd : file_descr) : result client_message :=
432505 msg <- recv_string sockfd ;;
433506 return MESG msg.
434507
435- Definition recv_client_PMSG (sockfd : file_descr) : optionE client_message :=
508+ Definition recv_client_PMSG (sockfd : file_descr) : result client_message :=
436509 uname <- recv_username sockfd ;;
437510 msg <- recv_string sockfd ;;
438511 return PMSG msg uname.
439512
440- Definition recv_client_EXIT (sockfd : file_descr) : optionE client_message :=
513+ Definition recv_client_EXIT (sockfd : file_descr) : result client_message :=
441514 uname <- recv_username sockfd ;;
442515 return EXIT uname.
443516
444- Definition recv_client_message (sockfd : file_descr) : optionE client_message :=
517+ Definition recv_client_message (sockfd : file_descr) : result client_message :=
445518 code <- recv_message sockfd 1 ;;
446519 match code with
447520 | [x00] => recv_client_REG sockfd
0 commit comments