@@ -634,11 +634,19 @@ module Sockopt = struct
634634 let tcp_keepidle = 4 (* TCP_KEEPIDLE *)
635635 let tcp_keepintvl = 5 (* TCP_KEEPINTVL *)
636636 let tcp_keepcnt = 6 (* TCP_KEEPCNT *)
637+ let tcp_syncnt = 7 (* TCP_SYNCNT *)
637638 let tcp_linger2 = 8 (* TCP_LINGER2 *)
638639 let tcp_defer_accept = 9 (* TCP_DEFER_ACCEPT *)
640+ let tcp_window_clamp = 10 (* TCP_WINDOW_CLAMP *)
641+ let tcp_quickack = 12 (* TCP_QUICKACK *)
639642 let tcp_congestion = 13 (* TCP_CONGESTION *)
640643 let tcp_user_timeout = 18 (* TCP_USER_TIMEOUT *)
644+ let tcp_fastopen = 23 (* TCP_FASTOPEN *)
641645 let ipproto_tcp = 6 (* IPPROTO_TCP *)
646+ let ipproto_ip = 0 (* IPPROTO_IP *)
647+ let ip_freebind = 15 (* IP_FREEBIND *)
648+ let ip_bind_address_no_port = 24 (* IP_BIND_ADDRESS_NO_PORT *)
649+ let ip_local_port_range = 51 (* IP_LOCAL_PORT_RANGE *)
642650
643651 external setsockopt_int : Unix .file_descr -> int -> int -> int -> unit = " caml_eio_sockopt_int_set"
644652 external getsockopt_int : Unix .file_descr -> int -> int -> int = " caml_eio_sockopt_int_get"
@@ -653,69 +661,155 @@ module Sockopt = struct
653661 | TCP_KEEPCNT : int Eio.Net.Sockopt .t
654662 | TCP_USER_TIMEOUT : int Eio.Net.Sockopt .t
655663 | TCP_MAXSEG : int Eio.Net.Sockopt .t
656- | TCP_LINGER2 : int Eio.Net.Sockopt .t
664+ | TCP_LINGER2 : int option Eio.Net.Sockopt .t
657665 | TCP_DEFER_ACCEPT : int Eio.Net.Sockopt .t
658666 | TCP_CONGESTION : string Eio.Net.Sockopt .t
667+ | TCP_SYNCNT : int Eio.Net.Sockopt .t
668+ | TCP_WINDOW_CLAMP : int Eio.Net.Sockopt .t
669+ | TCP_QUICKACK : bool Eio.Net.Sockopt .t
670+ | TCP_FASTOPEN : int Eio.Net.Sockopt .t
671+ | IP_FREEBIND : bool Eio.Net.Sockopt .t
672+ | IP_BIND_ADDRESS_NO_PORT : bool Eio.Net.Sockopt .t
673+ | IP_LOCAL_PORT_RANGE : (int * int ) Eio.Net.Sockopt .t
659674
660675 let set : type a. Fd.t -> a Eio.Net.Sockopt.t -> a -> unit = fun fd opt v ->
661676 match opt with
662677 | TCP_CORK ->
663- Fd. use_exn " setsockopt" fd (fun unix_fd ->
664- setsockopt_int unix_fd ipproto_tcp tcp_cork (if v then 1 else 0 ))
678+ Fd. use_exn " setsockopt" fd (fun fd ->
679+ setsockopt_int fd ipproto_tcp tcp_cork (if v then 1 else 0 ))
665680 | TCP_KEEPIDLE ->
666- Fd. use_exn " setsockopt" fd (fun unix_fd ->
667- setsockopt_int unix_fd ipproto_tcp tcp_keepidle v)
681+ if v < 0 then
682+ invalid_arg (Printf. sprintf " TCP_KEEPIDLE must be non-negative, got %d" v);
683+ Fd. use_exn " setsockopt" fd (fun fd ->
684+ setsockopt_int fd ipproto_tcp tcp_keepidle v)
668685 | TCP_KEEPINTVL ->
669- Fd. use_exn " setsockopt" fd (fun unix_fd ->
670- setsockopt_int unix_fd ipproto_tcp tcp_keepintvl v)
686+ if v < 0 then
687+ invalid_arg (Printf. sprintf " TCP_KEEPINTVL must be non-negative, got %d" v);
688+ Fd. use_exn " setsockopt" fd (fun fd ->
689+ setsockopt_int fd ipproto_tcp tcp_keepintvl v)
671690 | TCP_KEEPCNT ->
672- Fd. use_exn " setsockopt" fd (fun unix_fd ->
673- setsockopt_int unix_fd ipproto_tcp tcp_keepcnt v)
691+ if v < 0 then
692+ invalid_arg (Printf. sprintf " TCP_KEEPCNT must be non-negative, got %d" v);
693+ Fd. use_exn " setsockopt" fd (fun fd ->
694+ setsockopt_int fd ipproto_tcp tcp_keepcnt v)
674695 | TCP_USER_TIMEOUT ->
675- Fd. use_exn " setsockopt" fd (fun unix_fd ->
676- setsockopt_int unix_fd ipproto_tcp tcp_user_timeout v)
696+ if v < 0 then
697+ invalid_arg (Printf. sprintf " TCP_USER_TIMEOUT must be non-negative, got %d" v);
698+ Fd. use_exn " setsockopt" fd (fun fd ->
699+ setsockopt_int fd ipproto_tcp tcp_user_timeout v)
677700 | TCP_MAXSEG ->
678- Fd. use_exn " setsockopt" fd (fun unix_fd ->
679- setsockopt_int unix_fd ipproto_tcp tcp_maxseg v)
701+ if v < 0 then
702+ invalid_arg (Printf. sprintf " TCP_MAXSEG must be non-negative, got %d" v);
703+ Fd. use_exn " setsockopt" fd (fun fd ->
704+ setsockopt_int fd ipproto_tcp tcp_maxseg v)
680705 | TCP_LINGER2 ->
681- Fd. use_exn " setsockopt" fd (fun unix_fd ->
682- setsockopt_int unix_fd ipproto_tcp tcp_linger2 v)
706+ let v = match v with
707+ | None -> - 1
708+ | Some n when n < 0 ->
709+ invalid_arg (Printf. sprintf " TCP_LINGER2 must be non-negative, got %d" n);
710+ | Some n -> n
711+ in
712+ Fd. use_exn " setsockopt" fd (fun fd ->
713+ setsockopt_int fd ipproto_tcp tcp_linger2 v)
683714 | TCP_DEFER_ACCEPT ->
684- Fd. use_exn " setsockopt" fd (fun unix_fd ->
685- setsockopt_int unix_fd ipproto_tcp tcp_defer_accept v)
715+ if v < 0 then
716+ invalid_arg (Printf. sprintf " TCP_DEFER_ACCEPT must be non-negative, got %d" v);
717+ Fd. use_exn " setsockopt" fd (fun fd ->
718+ setsockopt_int fd ipproto_tcp tcp_defer_accept v)
686719 | TCP_CONGESTION ->
687- Fd. use_exn " setsockopt" fd (fun unix_fd ->
688- setsockopt_string unix_fd ipproto_tcp tcp_congestion v)
720+ Fd. use_exn " setsockopt" fd (fun fd ->
721+ setsockopt_string fd ipproto_tcp tcp_congestion v)
722+ | TCP_SYNCNT ->
723+ if v < 1 || v > 255 then
724+ invalid_arg (Printf. sprintf " TCP_SYNCNT must be between 1 and 255, got %d" v);
725+ Fd. use_exn " setsockopt" fd (fun fd ->
726+ setsockopt_int fd ipproto_tcp tcp_syncnt v)
727+ | TCP_WINDOW_CLAMP ->
728+ if v < 0 then
729+ invalid_arg (Printf. sprintf " TCP_WINDOW_CLAMP must be non-negative, got %d" v);
730+ Fd. use_exn " setsockopt" fd (fun fd ->
731+ setsockopt_int fd ipproto_tcp tcp_window_clamp v)
732+ | TCP_QUICKACK ->
733+ Fd. use_exn " setsockopt" fd (fun fd ->
734+ setsockopt_int fd ipproto_tcp tcp_quickack (if v then 1 else 0 ))
735+ | TCP_FASTOPEN ->
736+ if v < 0 then
737+ invalid_arg (Printf. sprintf " TCP_FASTOPEN queue length must be non-negative, got %d" v);
738+ Fd. use_exn " setsockopt" fd (fun fd ->
739+ setsockopt_int fd ipproto_tcp tcp_fastopen v)
740+ | IP_FREEBIND ->
741+ Fd. use_exn " setsockopt" fd (fun fd ->
742+ setsockopt_int fd ipproto_ip ip_freebind (if v then 1 else 0 ))
743+ | IP_BIND_ADDRESS_NO_PORT ->
744+ Fd. use_exn " setsockopt" fd (fun fd ->
745+ setsockopt_int fd ipproto_ip ip_bind_address_no_port (if v then 1 else 0 ))
746+ | IP_LOCAL_PORT_RANGE ->
747+ let (lower, upper) = v in
748+ if lower < 0 || lower > 65535 then
749+ invalid_arg (Printf. sprintf " IP_LOCAL_PORT_RANGE lower bound must be 0-65535, got %d" lower);
750+ if upper < 0 || upper > 65535 then
751+ invalid_arg (Printf. sprintf " IP_LOCAL_PORT_RANGE upper bound must be 0-65535, got %d" upper);
752+ if lower <> 0 && upper <> 0 && lower > upper then
753+ invalid_arg (Printf. sprintf " IP_LOCAL_PORT_RANGE lower bound (%d) must be <= upper bound (%d)" lower upper);
754+ let combined = (upper lsl 16 ) lor lower in
755+ Fd. use_exn " setsockopt" fd (fun fd ->
756+ setsockopt_int fd ipproto_ip ip_local_port_range combined)
689757 | _ -> Eio_unix.Net.Sockopt. set fd opt v
690758
691759 let get : type a. Fd.t -> a Eio.Net.Sockopt.t -> a = fun fd opt ->
692760 match opt with
693761 | TCP_CORK ->
694- Fd. use_exn " getsockopt" fd (fun unix_fd ->
695- getsockopt_int unix_fd ipproto_tcp tcp_cork <> 0 )
762+ Fd. use_exn " getsockopt" fd (fun fd ->
763+ getsockopt_int fd ipproto_tcp tcp_cork <> 0 )
696764 | TCP_KEEPIDLE ->
697- Fd. use_exn " getsockopt" fd (fun unix_fd ->
698- getsockopt_int unix_fd ipproto_tcp tcp_keepidle)
765+ Fd. use_exn " getsockopt" fd (fun fd ->
766+ getsockopt_int fd ipproto_tcp tcp_keepidle)
699767 | TCP_KEEPINTVL ->
700- Fd. use_exn " getsockopt" fd (fun unix_fd ->
701- getsockopt_int unix_fd ipproto_tcp tcp_keepintvl)
768+ Fd. use_exn " getsockopt" fd (fun fd ->
769+ getsockopt_int fd ipproto_tcp tcp_keepintvl)
702770 | TCP_KEEPCNT ->
703- Fd. use_exn " getsockopt" fd (fun unix_fd ->
704- getsockopt_int unix_fd ipproto_tcp tcp_keepcnt)
771+ Fd. use_exn " getsockopt" fd (fun fd ->
772+ getsockopt_int fd ipproto_tcp tcp_keepcnt)
705773 | TCP_USER_TIMEOUT ->
706- Fd. use_exn " getsockopt" fd (fun unix_fd ->
707- getsockopt_int unix_fd ipproto_tcp tcp_user_timeout)
774+ Fd. use_exn " getsockopt" fd (fun fd ->
775+ getsockopt_int fd ipproto_tcp tcp_user_timeout)
708776 | TCP_MAXSEG ->
709- Fd. use_exn " getsockopt" fd (fun unix_fd ->
710- getsockopt_int unix_fd ipproto_tcp tcp_maxseg)
777+ Fd. use_exn " getsockopt" fd (fun fd ->
778+ getsockopt_int fd ipproto_tcp tcp_maxseg)
711779 | TCP_LINGER2 ->
712- Fd. use_exn " getsockopt" fd (fun unix_fd ->
713- getsockopt_int unix_fd ipproto_tcp tcp_linger2)
780+ let v = Fd. use_exn " getsockopt" fd (fun fd ->
781+ getsockopt_int fd ipproto_tcp tcp_linger2)
782+ in
783+ if v = - 1 then None else Some v
714784 | TCP_DEFER_ACCEPT ->
715- Fd. use_exn " getsockopt" fd (fun unix_fd ->
716- getsockopt_int unix_fd ipproto_tcp tcp_defer_accept)
785+ Fd. use_exn " getsockopt" fd (fun fd ->
786+ getsockopt_int fd ipproto_tcp tcp_defer_accept)
717787 | TCP_CONGESTION ->
718- Fd. use_exn " getsockopt" fd (fun unix_fd ->
719- getsockopt_string unix_fd ipproto_tcp tcp_congestion)
788+ Fd. use_exn " getsockopt" fd (fun fd ->
789+ getsockopt_string fd ipproto_tcp tcp_congestion)
790+ | TCP_SYNCNT ->
791+ Fd. use_exn " getsockopt" fd (fun fd ->
792+ getsockopt_int fd ipproto_tcp tcp_syncnt)
793+ | TCP_WINDOW_CLAMP ->
794+ Fd. use_exn " getsockopt" fd (fun fd ->
795+ getsockopt_int fd ipproto_tcp tcp_window_clamp)
796+ | TCP_QUICKACK ->
797+ Fd. use_exn " getsockopt" fd (fun fd ->
798+ getsockopt_int fd ipproto_tcp tcp_quickack <> 0 )
799+ | TCP_FASTOPEN ->
800+ Fd. use_exn " getsockopt" fd (fun fd ->
801+ getsockopt_int fd ipproto_tcp tcp_fastopen)
802+ | IP_FREEBIND ->
803+ Fd. use_exn " getsockopt" fd (fun fd ->
804+ getsockopt_int fd ipproto_ip ip_freebind <> 0 )
805+ | IP_BIND_ADDRESS_NO_PORT ->
806+ Fd. use_exn " getsockopt" fd (fun fd ->
807+ getsockopt_int fd ipproto_ip ip_bind_address_no_port <> 0 )
808+ | IP_LOCAL_PORT_RANGE ->
809+ Fd. use_exn " getsockopt" fd (fun fd ->
810+ let combined = getsockopt_int fd ipproto_ip ip_local_port_range in
811+ let lower = combined land 0xFFFF in
812+ let upper = (combined lsr 16 ) land 0xFFFF in
813+ (lower, upper))
720814 | _ -> Eio_unix.Net.Sockopt. get fd opt
721815end
0 commit comments