This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,38 @@
(* Copyright (C) 2014--2024 Petter A. Urkedal <paurkedal@gmail.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version, with the LGPL-3.0 Linking Exception.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* and the LGPL-3.0 Linking Exception along with this library. If not, see
* <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively.
*)
open Caqti_platform
module System = System
module Pool = System.Pool
module Loader = Caqti_platform_unix.Driver_loader.Make (System) (System_unix)
include Connector.Make (System) (Pool) (Loader)
let connect
?subst ?env ?config ?tweaks_version ?(sw = Caqti_lwt.Switch.eternal) uri =
connect ?subst ?env ?config ?tweaks_version ~sw ~stdenv:() uri
let with_connection = with_connection ~stdenv:()
let connect_pool
?pool_config ?post_connect ?subst ?env ?config ?tweaks_version
?(sw = Caqti_lwt.Switch.eternal) uri =
connect_pool
?pool_config ?post_connect ?subst ?env ?config ?tweaks_version
~sw ~stdenv:() uri

View file

@ -0,0 +1,37 @@
(* Copyright (C) 2014--2023 Petter A. Urkedal <paurkedal@gmail.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version, with the LGPL-3.0 Linking Exception.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* and the LGPL-3.0 Linking Exception along with this library. If not, see
* <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively.
*)
(** Connecting on Unix-like platforms using Lwt
This module contains functions for connecting to databases using the
lwt.unix library, providing support for all drivers.
See also {!Caqti_lwt} for basic Lwt support. *)
(**/**) (* for test_pool_lwt.ml *)
module System = System
(**/**)
module Pool : Caqti_pool_sig.S with type 'a fiber := 'a Lwt.t
include Caqti_connect_sig.S
with type 'a fiber := 'a Lwt.t
and type ('a, 'e) stream := ('a, 'e) Caqti_lwt.Stream.t
and type ('a, 'e) pool := ('a, 'e) Pool.t
and type connection := Caqti_lwt.connection
and type 'a with_switch := ?sw: Caqti_lwt.Switch.t -> 'a
and type 'a with_stdenv := 'a

View file

@ -0,0 +1,8 @@
(library
(name caqti_lwt_unix)
(public_name caqti-lwt.unix)
(libraries
caqti caqti-lwt caqti.platform caqti.platform.unix
domain-name ipaddr
logs logs.lwt lwt lwt.unix
mtime mtime.clock.os))

View file

@ -0,0 +1,148 @@
(* Copyright (C) 2023--2024 Petter A. Urkedal <paurkedal@gmail.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version, with the LGPL-3.0 Linking Exception.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* and the LGPL-3.0 Linking Exception along with this library. If not, see
* <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively.
*)
open Lwt.Infix
type Caqti_error.msg += Msg_unix of Unix.error * string * string
let () =
let pp ppf = function
| Msg_unix (err, func, arg) ->
Format.fprintf ppf "%s in %s(%S)" (Unix.error_message err) func arg
| _ -> assert false
in
Caqti_error.define_msg ~pp [%extension_constructor Msg_unix]
module System_core = struct
include Caqti_lwt.System_core
type stdenv = unit
end
include System_core
module Alarm = struct
type t = {cancel: unit -> unit}
let schedule ~sw:_ ~stdenv:() t f =
let t_now = Mtime_clock.now () in
let delay =
if Mtime.is_later t ~than:t_now then
Lwt.pause ()
else
Lwt_unix.sleep (Mtime.Span.to_float_ns (Mtime.span t t_now) *. 1e-9)
in
let task = delay >|= f in
{cancel = (fun () -> Lwt.cancel task)}
let unschedule alarm = alarm.cancel ()
end
module Stream = Caqti_lwt.Stream
module Pool = Caqti_platform.Pool.Make (System_core) (Alarm)
module Net = struct
module type SOCKET_OPS = Caqti_platform.System_sig.SOCKET_OPS
with type 'a fiber := 'a Lwt.t
and type t = Lwt_io.input_channel * Lwt_io.output_channel
module Sockaddr = struct
type t = Unix.sockaddr
let unix s = Unix.ADDR_UNIX s
let tcp (addr, port) =
Unix.ADDR_INET (Unix.inet_addr_of_string (Ipaddr.to_string addr), port)
end
let getaddrinfo ~stdenv:() host port =
Lwt.catch
(fun () ->
let opts = Unix.[AI_SOCKTYPE SOCK_STREAM] in
Lwt_unix.getaddrinfo
(Domain_name.to_string host) (string_of_int port) opts
>|= List.map (fun ai -> ai.Unix.ai_addr) >|= Result.ok)
(function
| Not_found -> Lwt.return_ok []
| Unix.Unix_error (code, _, _) ->
Lwt.return_error
(`Msg ("Cannot resolve host name: " ^ Unix.error_message code))
| exn -> Lwt.fail exn)
let convert_io_exception = function
| Unix.Unix_error (err, fn, arg) -> Some (Msg_unix (err, fn, arg))
| _ -> None
type socket = {
fd: Lwt_unix.file_descr option;
ic: Lwt_io.input_channel;
oc: Lwt_io.output_channel;
}
module Socket = struct
type t = socket
let output_char {oc; _} data = Lwt_io.write_char oc data
let output_string {oc; _} data = Lwt_io.write oc data
let flush {oc; _} = Lwt_io.flush oc
let input_char {ic; _} = Lwt_io.read_char ic
let really_input {ic; _} data offset length =
Lwt_io.read_into_exactly ic data offset length
let close {oc; _} = Lwt_io.close oc (* CHECKME *)
end
type tcp_flow = Lwt_unix.file_descr
type tls_flow = Lwt_io.input_channel * Lwt_io.output_channel
let connect_tcp ~sw:_ ~stdenv:() sockaddr =
let domain = Unix.domain_of_sockaddr sockaddr in
let fd = Lwt_unix.socket domain Unix.SOCK_STREAM 0 in
Lwt.catch
(fun () ->
(try Lwt_unix.set_close_on_exec fd with _ -> ());
Lwt_unix.connect fd sockaddr >|= fun () ->
let ic = Lwt_io.(of_fd ~mode:input) fd in
let oc = Lwt_io.(of_fd ~mode:output) fd in
Ok {fd = Some fd; ic; oc})
(function
| Unix.Unix_error (err, fn, arg) ->
Lwt_unix.close fd >|= fun () ->
Error (Msg_unix (err, fn, arg))
| exn ->
Lwt_unix.close fd >>= fun () ->
Lwt.fail exn)
let tcp_flow_of_socket {fd; _} = fd
let socket_of_tls_flow ~sw:_ (ic, oc) = {fd = None; ic; oc}
module type TLS_PROVIDER = Caqti_platform.System_sig.TLS_PROVIDER
with type 'a fiber := 'a Lwt.t
and type tcp_flow := tcp_flow
and type tls_flow := tls_flow
let tls_providers_r : (module TLS_PROVIDER) list ref = ref []
let tls_providers config =
if Caqti_connect_config.mem_name "tls" config then
(match Caqti_platform.Connector.load_library "caqti-tls-lwt.unix" with
| Ok () -> ()
| Error msg ->
Logs.warn ~src:Caqti_platform.Logging.default_log_src (fun p ->
p "TLS configured, but missing caqti-tls-lwt.unix: %s" msg));
!tls_providers_r
let register_tls_provider p = tls_providers_r := p :: !tls_providers_r
end

View file

@ -0,0 +1,35 @@
(* Copyright (C) 2023 Petter A. Urkedal <paurkedal@gmail.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version, with the LGPL-3.0 Linking Exception.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* and the LGPL-3.0 Linking Exception along with this library. If not, see
* <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively.
*)
(**/**)
include Caqti_platform.System_sig.S
with type 'a Fiber.t = 'a Lwt.t
and type stdenv = unit
and module Stream = Caqti_lwt.Stream
and type Switch.t = Caqti_lwt.Switch.t
and type Net.tcp_flow = Lwt_unix.file_descr
and type Net.tls_flow = Lwt_io.input_channel * Lwt_io.output_channel
module Alarm : Caqti_platform.Pool.ALARM
with type switch := Switch.t
and type stdenv := unit
module Pool : Caqti_platform.Pool.S
with type 'a fiber := 'a Lwt.t
and type switch := Switch.t
and type stdenv := unit

View file

@ -0,0 +1,44 @@
(* Copyright (C) 2023 Petter A. Urkedal <paurkedal@gmail.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version, with the LGPL-3.0 Linking Exception.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* and the LGPL-3.0 Linking Exception along with this library. If not, see
* <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively.
*)
open Lwt.Infix
module Preemptive = Lwt_preemptive
module Unix = struct
type file_descr = Lwt_unix.file_descr
let wrap_fd f fd = f (Lwt_unix.of_unix_file_descr fd)
let poll ~stdenv:() ?(read = false) ?(write = false) ?timeout fd =
let choices = []
|> (fun acc -> if read then Lwt_unix.wait_read fd :: acc else acc)
|> (fun acc -> if write then Lwt_unix.wait_write fd :: acc else acc)
|> Option.fold
~none:Fun.id ~some:(fun t acc -> Lwt_unix.timeout t :: acc) timeout
in
if choices = [] then
Lwt.fail_invalid_arg "Caqti_lwt.Unix.poll: No operation specified."
else
Lwt.catch
(fun () -> Lwt.choose choices >|= fun _ -> false)
(function
| Lwt_unix.Timeout -> Lwt.return_true
| exn -> Lwt.fail exn)
>|= fun timed_out ->
(Lwt_unix.readable fd, Lwt_unix.writable fd, timed_out)
end