ocamlnet-4.1.2/0000755000175000017500000000000012731530351011744 5ustar gerdgerdocamlnet-4.1.2/Makefile0000644000175000017500000000531012731530350013402 0ustar gerdgerd# make all: compiles the configured packages with ocamlc # make opt: compiles the configured packages with ocamlopt # make install: installs the configured packages # make clean: cleans everything up # Inclusion of Makefile.conf may fail when cleaning up: -include Makefile.conf NAME=ocamlnet TOP_DIR=. # PKGLIST: should be set in Makefile.conf. It contains the packages to # compile and to install. The following assignment sets it to its # default value if no Makefile.conf exists. PKGLIST ?= netstring cgi .PHONY: build build: all if ocamlopt 2>/dev/null; then $(MAKE) opt; fi .PHONY: all all: tools for pkg in $(PKGLIST); do \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre generate ) || exit; \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre depend ) || exit; \ ( cd src/$$pkg && $(MAKE) all ) || exit; \ done .PHONY: opt opt: tools for pkg in $(PKGLIST); do \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre generate ) || exit; \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre depend ) || exit; \ ( cd src/$$pkg && $(MAKE) opt ) || exit; \ done .PHONY: doc doc: for pkg in src/*/.; do \ test ! -f $$pkg/Makefile -o -f $$pkg/doc-ignore || \ { ( cd $$pkg && $(MAKE) -f Makefile.pre generate ) || exit; \ ( cd $$pkg && $(MAKE) -f Makefile.pre depend ) || exit; \ ( cd $$pkg && $(MAKE) doc-dump ) || exit; \ }; \ done cd doc; $(MAKE) doc .PHONY: tools tools: ( cd tools/cppo-$(CPPO_VERSION) && $(MAKE) all ) ( cd tools/unimap_to_ocaml && $(MAKE) all ) # The following PHONY rule is important for Cygwin: .PHONY: install install: for pkg in $(PKGLIST); do \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre install ) || exit; \ done .PHONY: uninstall uninstall: for pkg in src/*/.; do \ test ! -f $$pkg/Makefile || \ ( cd $$pkg && $(MAKE) -f Makefile.pre uninstall); \ done .PHONY: clean clean: for pkg in src/*/.; do \ test ! -f $$pkg/Makefile || \ ( cd $$pkg && $(MAKE) -f Makefile.pre clean); \ done if test -f doc/Makefile; then cd doc && $(MAKE) clean; fi ( cd tools/cppo-$(CPPO_VERSION) && $(MAKE) clean ) ( cd tools/unimap_to_ocaml && $(MAKE) clean ) .PHONY: clean-doc clean-doc: for pkg in src/*/.; do \ test ! -f $$pkg/Makefile -o -f $$pkg/doc-ignore || \ ( cd $$pkg && $(MAKE) -f Makefile.pre clean-doc); \ done cd doc && $(MAKE) clean-doc .PHONY: CLEAN CLEAN: clean .PHONY: distclean distclean: rm -f Makefile.conf rm -rf tmp for pkg in src/*/.; do \ test ! -f $$pkg/Makefile || \ ( cd $$pkg && $(MAKE) -f Makefile.pre distclean); \ done # That one is for oasis .PHONY: postconf postconf: cat setup.save >>setup.data # phony because VERSION may also change .PHONY: _oasis _oasis: _oasis.in v=`./configure -version`; sed -e 's/@VERSION@/'"$$v/" _oasis.in >_oasis oasis setup ocamlnet-4.1.2/setup.ml0000644000175000017500000054543712731530350013457 0ustar gerdgerd(* setup.ml generated for the first time by OASIS v0.4.6 *) (* OASIS_START *) (* DO NOT EDIT (digest: f3549f7d54539ea3870e83a029fcda6f) *) (* Regenerated by OASIS v0.4.6 Visit http://oasis.forge.ocamlcore.org for more information and documentation about functions used in this file. *) module OASISGettext = struct (* # 22 "src/oasis/OASISGettext.ml" *) let ns_ str = str let s_ str = str let f_ (str: ('a, 'b, 'c, 'd) format4) = str let fn_ fmt1 fmt2 n = if n = 1 then fmt1^^"" else fmt2^^"" let init = [] end module OASISContext = struct (* # 22 "src/oasis/OASISContext.ml" *) open OASISGettext type level = [ `Debug | `Info | `Warning | `Error] type t = { (* TODO: replace this by a proplist. *) quiet: bool; info: bool; debug: bool; ignore_plugins: bool; ignore_unknown_fields: bool; printf: level -> string -> unit; } let printf lvl str = let beg = match lvl with | `Error -> s_ "E: " | `Warning -> s_ "W: " | `Info -> s_ "I: " | `Debug -> s_ "D: " in prerr_endline (beg^str) let default = ref { quiet = false; info = false; debug = false; ignore_plugins = false; ignore_unknown_fields = false; printf = printf; } let quiet = {!default with quiet = true} let fspecs () = (* TODO: don't act on default. *) let ignore_plugins = ref false in ["-quiet", Arg.Unit (fun () -> default := {!default with quiet = true}), s_ " Run quietly"; "-info", Arg.Unit (fun () -> default := {!default with info = true}), s_ " Display information message"; "-debug", Arg.Unit (fun () -> default := {!default with debug = true}), s_ " Output debug message"; "-ignore-plugins", Arg.Set ignore_plugins, s_ " Ignore plugin's field."; "-C", Arg.String (fun str -> Sys.chdir str), s_ "dir Change directory before running (affects setup.{data,log})."], fun () -> {!default with ignore_plugins = !ignore_plugins} end module OASISString = struct (* # 22 "src/oasis/OASISString.ml" *) (** Various string utilities. Mostly inspired by extlib and batteries ExtString and BatString libraries. @author Sylvain Le Gall *) let nsplitf str f = if str = "" then [] else let buf = Buffer.create 13 in let lst = ref [] in let push () = lst := Buffer.contents buf :: !lst; Buffer.clear buf in let str_len = String.length str in for i = 0 to str_len - 1 do if f str.[i] then push () else Buffer.add_char buf str.[i] done; push (); List.rev !lst (** [nsplit c s] Split the string [s] at char [c]. It doesn't include the separator. *) let nsplit str c = nsplitf str ((=) c) let find ~what ?(offset=0) str = let what_idx = ref 0 in let str_idx = ref offset in while !str_idx < String.length str && !what_idx < String.length what do if str.[!str_idx] = what.[!what_idx] then incr what_idx else what_idx := 0; incr str_idx done; if !what_idx <> String.length what then raise Not_found else !str_idx - !what_idx let sub_start str len = let str_len = String.length str in if len >= str_len then "" else String.sub str len (str_len - len) let sub_end ?(offset=0) str len = let str_len = String.length str in if len >= str_len then "" else String.sub str 0 (str_len - len) let starts_with ~what ?(offset=0) str = let what_idx = ref 0 in let str_idx = ref offset in let ok = ref true in while !ok && !str_idx < String.length str && !what_idx < String.length what do if str.[!str_idx] = what.[!what_idx] then incr what_idx else ok := false; incr str_idx done; if !what_idx = String.length what then true else false let strip_starts_with ~what str = if starts_with ~what str then sub_start str (String.length what) else raise Not_found let ends_with ~what ?(offset=0) str = let what_idx = ref ((String.length what) - 1) in let str_idx = ref ((String.length str) - 1) in let ok = ref true in while !ok && offset <= !str_idx && 0 <= !what_idx do if str.[!str_idx] = what.[!what_idx] then decr what_idx else ok := false; decr str_idx done; if !what_idx = -1 then true else false let strip_ends_with ~what str = if ends_with ~what str then sub_end str (String.length what) else raise Not_found let replace_chars f s = let buf = Buffer.create (String.length s) in String.iter (fun c -> Buffer.add_char buf (f c)) s; Buffer.contents buf end module OASISUtils = struct (* # 22 "src/oasis/OASISUtils.ml" *) open OASISGettext module MapExt = struct module type S = sig include Map.S val add_list: 'a t -> (key * 'a) list -> 'a t val of_list: (key * 'a) list -> 'a t val to_list: 'a t -> (key * 'a) list end module Make (Ord: Map.OrderedType) = struct include Map.Make(Ord) let rec add_list t = function | (k, v) :: tl -> add_list (add k v t) tl | [] -> t let of_list lst = add_list empty lst let to_list t = fold (fun k v acc -> (k, v) :: acc) t [] end end module MapString = MapExt.Make(String) module SetExt = struct module type S = sig include Set.S val add_list: t -> elt list -> t val of_list: elt list -> t val to_list: t -> elt list end module Make (Ord: Set.OrderedType) = struct include Set.Make(Ord) let rec add_list t = function | e :: tl -> add_list (add e t) tl | [] -> t let of_list lst = add_list empty lst let to_list = elements end end module SetString = SetExt.Make(String) let compare_csl s1 s2 = String.compare (String.lowercase s1) (String.lowercase s2) module HashStringCsl = Hashtbl.Make (struct type t = string let equal s1 s2 = (String.lowercase s1) = (String.lowercase s2) let hash s = Hashtbl.hash (String.lowercase s) end) module SetStringCsl = SetExt.Make (struct type t = string let compare = compare_csl end) let varname_of_string ?(hyphen='_') s = if String.length s = 0 then begin invalid_arg "varname_of_string" end else begin let buf = OASISString.replace_chars (fun c -> if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') then c else hyphen) s; in let buf = (* Start with a _ if digit *) if '0' <= s.[0] && s.[0] <= '9' then "_"^buf else buf in String.lowercase buf end let varname_concat ?(hyphen='_') p s = let what = String.make 1 hyphen in let p = try OASISString.strip_ends_with ~what p with Not_found -> p in let s = try OASISString.strip_starts_with ~what s with Not_found -> s in p^what^s let is_varname str = str = varname_of_string str let failwithf fmt = Printf.ksprintf failwith fmt end module PropList = struct (* # 22 "src/oasis/PropList.ml" *) open OASISGettext type name = string exception Not_set of name * string option exception No_printer of name exception Unknown_field of name * name let () = Printexc.register_printer (function | Not_set (nm, Some rsn) -> Some (Printf.sprintf (f_ "Field '%s' is not set: %s") nm rsn) | Not_set (nm, None) -> Some (Printf.sprintf (f_ "Field '%s' is not set") nm) | No_printer nm -> Some (Printf.sprintf (f_ "No default printer for value %s") nm) | Unknown_field (nm, schm) -> Some (Printf.sprintf (f_ "Field %s is not defined in schema %s") nm schm) | _ -> None) module Data = struct type t = (name, unit -> unit) Hashtbl.t let create () = Hashtbl.create 13 let clear t = Hashtbl.clear t (* # 78 "src/oasis/PropList.ml" *) end module Schema = struct type ('ctxt, 'extra) value = { get: Data.t -> string; set: Data.t -> ?context:'ctxt -> string -> unit; help: (unit -> string) option; extra: 'extra; } type ('ctxt, 'extra) t = { name: name; fields: (name, ('ctxt, 'extra) value) Hashtbl.t; order: name Queue.t; name_norm: string -> string; } let create ?(case_insensitive=false) nm = { name = nm; fields = Hashtbl.create 13; order = Queue.create (); name_norm = (if case_insensitive then String.lowercase else fun s -> s); } let add t nm set get extra help = let key = t.name_norm nm in if Hashtbl.mem t.fields key then failwith (Printf.sprintf (f_ "Field '%s' is already defined in schema '%s'") nm t.name); Hashtbl.add t.fields key { set = set; get = get; help = help; extra = extra; }; Queue.add nm t.order let mem t nm = Hashtbl.mem t.fields nm let find t nm = try Hashtbl.find t.fields (t.name_norm nm) with Not_found -> raise (Unknown_field (nm, t.name)) let get t data nm = (find t nm).get data let set t data nm ?context x = (find t nm).set data ?context x let fold f acc t = Queue.fold (fun acc k -> let v = find t k in f acc k v.extra v.help) acc t.order let iter f t = fold (fun () -> f) () t let name t = t.name end module Field = struct type ('ctxt, 'value, 'extra) t = { set: Data.t -> ?context:'ctxt -> 'value -> unit; get: Data.t -> 'value; sets: Data.t -> ?context:'ctxt -> string -> unit; gets: Data.t -> string; help: (unit -> string) option; extra: 'extra; } let new_id = let last_id = ref 0 in fun () -> incr last_id; !last_id let create ?schema ?name ?parse ?print ?default ?update ?help extra = (* Default value container *) let v = ref None in (* If name is not given, create unique one *) let nm = match name with | Some s -> s | None -> Printf.sprintf "_anon_%d" (new_id ()) in (* Last chance to get a value: the default *) let default () = match default with | Some d -> d | None -> raise (Not_set (nm, Some (s_ "no default value"))) in (* Get data *) let get data = (* Get value *) try (Hashtbl.find data nm) (); match !v with | Some x -> x | None -> default () with Not_found -> default () in (* Set data *) let set data ?context x = let x = match update with | Some f -> begin try f ?context (get data) x with Not_set _ -> x end | None -> x in Hashtbl.replace data nm (fun () -> v := Some x) in (* Parse string value, if possible *) let parse = match parse with | Some f -> f | None -> fun ?context s -> failwith (Printf.sprintf (f_ "Cannot parse field '%s' when setting value %S") nm s) in (* Set data, from string *) let sets data ?context s = set ?context data (parse ?context s) in (* Output value as string, if possible *) let print = match print with | Some f -> f | None -> fun _ -> raise (No_printer nm) in (* Get data, as a string *) let gets data = print (get data) in begin match schema with | Some t -> Schema.add t nm sets gets extra help | None -> () end; { set = set; get = get; sets = sets; gets = gets; help = help; extra = extra; } let fset data t ?context x = t.set data ?context x let fget data t = t.get data let fsets data t ?context s = t.sets data ?context s let fgets data t = t.gets data end module FieldRO = struct let create ?schema ?name ?parse ?print ?default ?update ?help extra = let fld = Field.create ?schema ?name ?parse ?print ?default ?update ?help extra in fun data -> Field.fget data fld end end module OASISMessage = struct (* # 22 "src/oasis/OASISMessage.ml" *) open OASISGettext open OASISContext let generic_message ~ctxt lvl fmt = let cond = if ctxt.quiet then false else match lvl with | `Debug -> ctxt.debug | `Info -> ctxt.info | _ -> true in Printf.ksprintf (fun str -> if cond then begin ctxt.printf lvl str end) fmt let debug ~ctxt fmt = generic_message ~ctxt `Debug fmt let info ~ctxt fmt = generic_message ~ctxt `Info fmt let warning ~ctxt fmt = generic_message ~ctxt `Warning fmt let error ~ctxt fmt = generic_message ~ctxt `Error fmt end module OASISVersion = struct (* # 22 "src/oasis/OASISVersion.ml" *) open OASISGettext type s = string type t = string type comparator = | VGreater of t | VGreaterEqual of t | VEqual of t | VLesser of t | VLesserEqual of t | VOr of comparator * comparator | VAnd of comparator * comparator (* Range of allowed characters *) let is_digit c = '0' <= c && c <= '9' let is_alpha c = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') let is_special = function | '.' | '+' | '-' | '~' -> true | _ -> false let rec version_compare v1 v2 = if v1 <> "" || v2 <> "" then begin (* Compare ascii string, using special meaning for version * related char *) let val_ascii c = if c = '~' then -1 else if is_digit c then 0 else if c = '\000' then 0 else if is_alpha c then Char.code c else (Char.code c) + 256 in let len1 = String.length v1 in let len2 = String.length v2 in let p = ref 0 in (** Compare ascii part *) let compare_vascii () = let cmp = ref 0 in while !cmp = 0 && !p < len1 && !p < len2 && not (is_digit v1.[!p] && is_digit v2.[!p]) do cmp := (val_ascii v1.[!p]) - (val_ascii v2.[!p]); incr p done; if !cmp = 0 && !p < len1 && !p = len2 then val_ascii v1.[!p] else if !cmp = 0 && !p = len1 && !p < len2 then - (val_ascii v2.[!p]) else !cmp in (** Compare digit part *) let compare_digit () = let extract_int v p = let start_p = !p in while !p < String.length v && is_digit v.[!p] do incr p done; let substr = String.sub v !p ((String.length v) - !p) in let res = match String.sub v start_p (!p - start_p) with | "" -> 0 | s -> int_of_string s in res, substr in let i1, tl1 = extract_int v1 (ref !p) in let i2, tl2 = extract_int v2 (ref !p) in i1 - i2, tl1, tl2 in match compare_vascii () with | 0 -> begin match compare_digit () with | 0, tl1, tl2 -> if tl1 <> "" && is_digit tl1.[0] then 1 else if tl2 <> "" && is_digit tl2.[0] then -1 else version_compare tl1 tl2 | n, _, _ -> n end | n -> n end else begin 0 end let version_of_string str = str let string_of_version t = t let version_compare_string s1 s2 = version_compare (version_of_string s1) (version_of_string s2) let chop t = try let pos = String.rindex t '.' in String.sub t 0 pos with Not_found -> t let rec comparator_apply v op = match op with | VGreater cv -> (version_compare v cv) > 0 | VGreaterEqual cv -> (version_compare v cv) >= 0 | VLesser cv -> (version_compare v cv) < 0 | VLesserEqual cv -> (version_compare v cv) <= 0 | VEqual cv -> (version_compare v cv) = 0 | VOr (op1, op2) -> (comparator_apply v op1) || (comparator_apply v op2) | VAnd (op1, op2) -> (comparator_apply v op1) && (comparator_apply v op2) let rec string_of_comparator = function | VGreater v -> "> "^(string_of_version v) | VEqual v -> "= "^(string_of_version v) | VLesser v -> "< "^(string_of_version v) | VGreaterEqual v -> ">= "^(string_of_version v) | VLesserEqual v -> "<= "^(string_of_version v) | VOr (c1, c2) -> (string_of_comparator c1)^" || "^(string_of_comparator c2) | VAnd (c1, c2) -> (string_of_comparator c1)^" && "^(string_of_comparator c2) let rec varname_of_comparator = let concat p v = OASISUtils.varname_concat p (OASISUtils.varname_of_string (string_of_version v)) in function | VGreater v -> concat "gt" v | VLesser v -> concat "lt" v | VEqual v -> concat "eq" v | VGreaterEqual v -> concat "ge" v | VLesserEqual v -> concat "le" v | VOr (c1, c2) -> (varname_of_comparator c1)^"_or_"^(varname_of_comparator c2) | VAnd (c1, c2) -> (varname_of_comparator c1)^"_and_"^(varname_of_comparator c2) let rec comparator_ge v' = let cmp v = version_compare v v' >= 0 in function | VEqual v | VGreaterEqual v | VGreater v -> cmp v | VLesserEqual _ | VLesser _ -> false | VOr (c1, c2) -> comparator_ge v' c1 || comparator_ge v' c2 | VAnd (c1, c2) -> comparator_ge v' c1 && comparator_ge v' c2 end module OASISLicense = struct (* # 22 "src/oasis/OASISLicense.ml" *) (** License for _oasis fields @author Sylvain Le Gall *) type license = string type license_exception = string type license_version = | Version of OASISVersion.t | VersionOrLater of OASISVersion.t | NoVersion type license_dep_5_unit = { license: license; excption: license_exception option; version: license_version; } type license_dep_5 = | DEP5Unit of license_dep_5_unit | DEP5Or of license_dep_5 list | DEP5And of license_dep_5 list type t = | DEP5License of license_dep_5 | OtherLicense of string (* URL *) end module OASISExpr = struct (* # 22 "src/oasis/OASISExpr.ml" *) open OASISGettext type test = string type flag = string type t = | EBool of bool | ENot of t | EAnd of t * t | EOr of t * t | EFlag of flag | ETest of test * string type 'a choices = (t * 'a) list let eval var_get t = let rec eval' = function | EBool b -> b | ENot e -> not (eval' e) | EAnd (e1, e2) -> (eval' e1) && (eval' e2) | EOr (e1, e2) -> (eval' e1) || (eval' e2) | EFlag nm -> let v = var_get nm in assert(v = "true" || v = "false"); (v = "true") | ETest (nm, vl) -> let v = var_get nm in (v = vl) in eval' t let choose ?printer ?name var_get lst = let rec choose_aux = function | (cond, vl) :: tl -> if eval var_get cond then vl else choose_aux tl | [] -> let str_lst = if lst = [] then s_ "" else String.concat (s_ ", ") (List.map (fun (cond, vl) -> match printer with | Some p -> p vl | None -> s_ "") lst) in match name with | Some nm -> failwith (Printf.sprintf (f_ "No result for the choice list '%s': %s") nm str_lst) | None -> failwith (Printf.sprintf (f_ "No result for a choice list: %s") str_lst) in choose_aux (List.rev lst) end module OASISText = struct (* # 22 "src/oasis/OASISText.ml" *) type elt = | Para of string | Verbatim of string | BlankLine type t = elt list end module OASISTypes = struct (* # 22 "src/oasis/OASISTypes.ml" *) type name = string type package_name = string type url = string type unix_dirname = string type unix_filename = string type host_dirname = string type host_filename = string type prog = string type arg = string type args = string list type command_line = (prog * arg list) type findlib_name = string type findlib_full = string type compiled_object = | Byte | Native | Best type dependency = | FindlibPackage of findlib_full * OASISVersion.comparator option | InternalLibrary of name type tool = | ExternalTool of name | InternalExecutable of name type vcs = | Darcs | Git | Svn | Cvs | Hg | Bzr | Arch | Monotone | OtherVCS of url type plugin_kind = [ `Configure | `Build | `Doc | `Test | `Install | `Extra ] type plugin_data_purpose = [ `Configure | `Build | `Install | `Clean | `Distclean | `Install | `Uninstall | `Test | `Doc | `Extra | `Other of string ] type 'a plugin = 'a * name * OASISVersion.t option type all_plugin = plugin_kind plugin type plugin_data = (all_plugin * plugin_data_purpose * (unit -> unit)) list (* # 115 "src/oasis/OASISTypes.ml" *) type 'a conditional = 'a OASISExpr.choices type custom = { pre_command: (command_line option) conditional; post_command: (command_line option) conditional; } type common_section = { cs_name: name; cs_data: PropList.Data.t; cs_plugin_data: plugin_data; } type build_section = { bs_build: bool conditional; bs_install: bool conditional; bs_path: unix_dirname; bs_compiled_object: compiled_object; bs_build_depends: dependency list; bs_build_tools: tool list; bs_c_sources: unix_filename list; bs_data_files: (unix_filename * unix_filename option) list; bs_ccopt: args conditional; bs_cclib: args conditional; bs_dlllib: args conditional; bs_dllpath: args conditional; bs_byteopt: args conditional; bs_nativeopt: args conditional; } type library = { lib_modules: string list; lib_pack: bool; lib_internal_modules: string list; lib_findlib_parent: findlib_name option; lib_findlib_name: findlib_name option; lib_findlib_containers: findlib_name list; } type object_ = { obj_modules: string list; obj_findlib_fullname: findlib_name list option; } type executable = { exec_custom: bool; exec_main_is: unix_filename; } type flag = { flag_description: string option; flag_default: bool conditional; } type source_repository = { src_repo_type: vcs; src_repo_location: url; src_repo_browser: url option; src_repo_module: string option; src_repo_branch: string option; src_repo_tag: string option; src_repo_subdir: unix_filename option; } type test = { test_type: [`Test] plugin; test_command: command_line conditional; test_custom: custom; test_working_directory: unix_filename option; test_run: bool conditional; test_tools: tool list; } type doc_format = | HTML of unix_filename | DocText | PDF | PostScript | Info of unix_filename | DVI | OtherDoc type doc = { doc_type: [`Doc] plugin; doc_custom: custom; doc_build: bool conditional; doc_install: bool conditional; doc_install_dir: unix_filename; doc_title: string; doc_authors: string list; doc_abstract: string option; doc_format: doc_format; doc_data_files: (unix_filename * unix_filename option) list; doc_build_tools: tool list; } type section = | Library of common_section * build_section * library | Object of common_section * build_section * object_ | Executable of common_section * build_section * executable | Flag of common_section * flag | SrcRepo of common_section * source_repository | Test of common_section * test | Doc of common_section * doc type section_kind = [ `Library | `Object | `Executable | `Flag | `SrcRepo | `Test | `Doc ] type package = { oasis_version: OASISVersion.t; ocaml_version: OASISVersion.comparator option; findlib_version: OASISVersion.comparator option; alpha_features: string list; beta_features: string list; name: package_name; version: OASISVersion.t; license: OASISLicense.t; license_file: unix_filename option; copyrights: string list; maintainers: string list; authors: string list; homepage: url option; bugreports: url option; synopsis: string; description: OASISText.t option; tags: string list; categories: url list; conf_type: [`Configure] plugin; conf_custom: custom; build_type: [`Build] plugin; build_custom: custom; install_type: [`Install] plugin; install_custom: custom; uninstall_custom: custom; clean_custom: custom; distclean_custom: custom; files_ab: unix_filename list; sections: section list; plugins: [`Extra] plugin list; disable_oasis_section: unix_filename list; schema_data: PropList.Data.t; plugin_data: plugin_data; } end module OASISFeatures = struct (* # 22 "src/oasis/OASISFeatures.ml" *) open OASISTypes open OASISUtils open OASISGettext open OASISVersion module MapPlugin = Map.Make (struct type t = plugin_kind * name let compare = Pervasives.compare end) module Data = struct type t = { oasis_version: OASISVersion.t; plugin_versions: OASISVersion.t option MapPlugin.t; alpha_features: string list; beta_features: string list; } let create oasis_version alpha_features beta_features = { oasis_version = oasis_version; plugin_versions = MapPlugin.empty; alpha_features = alpha_features; beta_features = beta_features } let of_package pkg = create pkg.OASISTypes.oasis_version pkg.OASISTypes.alpha_features pkg.OASISTypes.beta_features let add_plugin (plugin_kind, plugin_name, plugin_version) t = {t with plugin_versions = MapPlugin.add (plugin_kind, plugin_name) plugin_version t.plugin_versions} let plugin_version plugin_kind plugin_name t = MapPlugin.find (plugin_kind, plugin_name) t.plugin_versions let to_string t = Printf.sprintf "oasis_version: %s; alpha_features: %s; beta_features: %s; \ plugins_version: %s" (OASISVersion.string_of_version t.oasis_version) (String.concat ", " t.alpha_features) (String.concat ", " t.beta_features) (String.concat ", " (MapPlugin.fold (fun (_, plg) ver_opt acc -> (plg^ (match ver_opt with | Some v -> " "^(OASISVersion.string_of_version v) | None -> "")) :: acc) t.plugin_versions [])) end type origin = | Field of string * string | Section of string | NoOrigin type stage = Alpha | Beta let string_of_stage = function | Alpha -> "alpha" | Beta -> "beta" let field_of_stage = function | Alpha -> "AlphaFeatures" | Beta -> "BetaFeatures" type publication = InDev of stage | SinceVersion of OASISVersion.t type t = { name: string; plugin: all_plugin option; publication: publication; description: unit -> string; } (* TODO: mutex protect this. *) let all_features = Hashtbl.create 13 let since_version ver_str = SinceVersion (version_of_string ver_str) let alpha = InDev Alpha let beta = InDev Beta let to_string t = Printf.sprintf "feature: %s; plugin: %s; publication: %s" t.name (match t.plugin with | None -> "" | Some (_, nm, _) -> nm) (match t.publication with | InDev stage -> string_of_stage stage | SinceVersion ver -> ">= "^(OASISVersion.string_of_version ver)) let data_check t data origin = let no_message = "no message" in let check_feature features stage = let has_feature = List.mem t.name features in if not has_feature then match origin with | Field (fld, where) -> Some (Printf.sprintf (f_ "Field %s in %s is only available when feature %s \ is in field %s.") fld where t.name (field_of_stage stage)) | Section sct -> Some (Printf.sprintf (f_ "Section %s is only available when features %s \ is in field %s.") sct t.name (field_of_stage stage)) | NoOrigin -> Some no_message else None in let version_is_good ~min_version version fmt = let version_is_good = OASISVersion.comparator_apply version (OASISVersion.VGreaterEqual min_version) in Printf.ksprintf (fun str -> if version_is_good then None else Some str) fmt in match origin, t.plugin, t.publication with | _, _, InDev Alpha -> check_feature data.Data.alpha_features Alpha | _, _, InDev Beta -> check_feature data.Data.beta_features Beta | Field(fld, where), None, SinceVersion min_version -> version_is_good ~min_version data.Data.oasis_version (f_ "Field %s in %s is only valid since OASIS v%s, update \ OASISFormat field from '%s' to '%s' after checking \ OASIS changelog.") fld where (string_of_version min_version) (string_of_version data.Data.oasis_version) (string_of_version min_version) | Field(fld, where), Some(plugin_knd, plugin_name, _), SinceVersion min_version -> begin try let plugin_version_current = try match Data.plugin_version plugin_knd plugin_name data with | Some ver -> ver | None -> failwithf (f_ "Field %s in %s is only valid for the OASIS \ plugin %s since v%s, but no plugin version is \ defined in the _oasis file, change '%s' to \ '%s (%s)' in your _oasis file.") fld where plugin_name (string_of_version min_version) plugin_name plugin_name (string_of_version min_version) with Not_found -> failwithf (f_ "Field %s in %s is only valid when the OASIS plugin %s \ is defined.") fld where plugin_name in version_is_good ~min_version plugin_version_current (f_ "Field %s in %s is only valid for the OASIS plugin %s \ since v%s, update your plugin from '%s (%s)' to \ '%s (%s)' after checking the plugin's changelog.") fld where plugin_name (string_of_version min_version) plugin_name (string_of_version plugin_version_current) plugin_name (string_of_version min_version) with Failure msg -> Some msg end | Section sct, None, SinceVersion min_version -> version_is_good ~min_version data.Data.oasis_version (f_ "Section %s is only valid for since OASIS v%s, update \ OASISFormat field from '%s' to '%s' after checking OASIS \ changelog.") sct (string_of_version min_version) (string_of_version data.Data.oasis_version) (string_of_version min_version) | Section sct, Some(plugin_knd, plugin_name, _), SinceVersion min_version -> begin try let plugin_version_current = try match Data.plugin_version plugin_knd plugin_name data with | Some ver -> ver | None -> failwithf (f_ "Section %s is only valid for the OASIS \ plugin %s since v%s, but no plugin version is \ defined in the _oasis file, change '%s' to \ '%s (%s)' in your _oasis file.") sct plugin_name (string_of_version min_version) plugin_name plugin_name (string_of_version min_version) with Not_found -> failwithf (f_ "Section %s is only valid when the OASIS plugin %s \ is defined.") sct plugin_name in version_is_good ~min_version plugin_version_current (f_ "Section %s is only valid for the OASIS plugin %s \ since v%s, update your plugin from '%s (%s)' to \ '%s (%s)' after checking the plugin's changelog.") sct plugin_name (string_of_version min_version) plugin_name (string_of_version plugin_version_current) plugin_name (string_of_version min_version) with Failure msg -> Some msg end | NoOrigin, None, SinceVersion min_version -> version_is_good ~min_version data.Data.oasis_version "%s" no_message | NoOrigin, Some(plugin_knd, plugin_name, _), SinceVersion min_version -> begin try let plugin_version_current = match Data.plugin_version plugin_knd plugin_name data with | Some ver -> ver | None -> raise Not_found in version_is_good ~min_version plugin_version_current "%s" no_message with Not_found -> Some no_message end let data_assert t data origin = match data_check t data origin with | None -> () | Some str -> failwith str let data_test t data = match data_check t data NoOrigin with | None -> true | Some str -> false let package_test t pkg = data_test t (Data.of_package pkg) let create ?plugin name publication description = let () = if Hashtbl.mem all_features name then failwithf "Feature '%s' is already declared." name in let t = { name = name; plugin = plugin; publication = publication; description = description; } in Hashtbl.add all_features name t; t let get_stage name = try (Hashtbl.find all_features name).publication with Not_found -> failwithf (f_ "Feature %s doesn't exist.") name let list () = Hashtbl.fold (fun _ v acc -> v :: acc) all_features [] (* * Real flags. *) let features = create "features_fields" (since_version "0.4") (fun () -> s_ "Enable to experiment not yet official features.") let flag_docs = create "flag_docs" (since_version "0.3") (fun () -> s_ "Building docs require '-docs' flag at configure.") let flag_tests = create "flag_tests" (since_version "0.3") (fun () -> s_ "Running tests require '-tests' flag at configure.") let pack = create "pack" (since_version "0.3") (fun () -> s_ "Allow to create packed library.") let section_object = create "section_object" beta (fun () -> s_ "Implement an object section.") let dynrun_for_release = create "dynrun_for_release" alpha (fun () -> s_ "Make '-setup-update dynamic' suitable for releasing project.") let compiled_setup_ml = create "compiled_setup_ml" alpha (fun () -> s_ "It compiles the setup.ml and speed-up actions done with it.") let disable_oasis_section = create "disable_oasis_section" alpha (fun () -> s_ "Allows the OASIS section comments and digest to be omitted in \ generated files.") let no_automatic_syntax = create "no_automatic_syntax" alpha (fun () -> s_ "Disable the automatic inclusion of -syntax camlp4o for packages \ that matches the internal heuristic (if a dependency ends with \ a .syntax or is a well known syntax).") end module OASISUnixPath = struct (* # 22 "src/oasis/OASISUnixPath.ml" *) type unix_filename = string type unix_dirname = string type host_filename = string type host_dirname = string let current_dir_name = "." let parent_dir_name = ".." let is_current_dir fn = fn = current_dir_name || fn = "" let concat f1 f2 = if is_current_dir f1 then f2 else let f1' = try OASISString.strip_ends_with ~what:"/" f1 with Not_found -> f1 in f1'^"/"^f2 let make = function | hd :: tl -> List.fold_left (fun f p -> concat f p) hd tl | [] -> invalid_arg "OASISUnixPath.make" let dirname f = try String.sub f 0 (String.rindex f '/') with Not_found -> current_dir_name let basename f = try let pos_start = (String.rindex f '/') + 1 in String.sub f pos_start ((String.length f) - pos_start) with Not_found -> f let chop_extension f = try let last_dot = String.rindex f '.' in let sub = String.sub f 0 last_dot in try let last_slash = String.rindex f '/' in if last_slash < last_dot then sub else f with Not_found -> sub with Not_found -> f let capitalize_file f = let dir = dirname f in let base = basename f in concat dir (String.capitalize base) let uncapitalize_file f = let dir = dirname f in let base = basename f in concat dir (String.uncapitalize base) end module OASISHostPath = struct (* # 22 "src/oasis/OASISHostPath.ml" *) open Filename module Unix = OASISUnixPath let make = function | [] -> invalid_arg "OASISHostPath.make" | hd :: tl -> List.fold_left Filename.concat hd tl let of_unix ufn = if Sys.os_type = "Unix" then ufn else make (List.map (fun p -> if p = Unix.current_dir_name then current_dir_name else if p = Unix.parent_dir_name then parent_dir_name else p) (OASISString.nsplit ufn '/')) end module OASISSection = struct (* # 22 "src/oasis/OASISSection.ml" *) open OASISTypes let section_kind_common = function | Library (cs, _, _) -> `Library, cs | Object (cs, _, _) -> `Object, cs | Executable (cs, _, _) -> `Executable, cs | Flag (cs, _) -> `Flag, cs | SrcRepo (cs, _) -> `SrcRepo, cs | Test (cs, _) -> `Test, cs | Doc (cs, _) -> `Doc, cs let section_common sct = snd (section_kind_common sct) let section_common_set cs = function | Library (_, bs, lib) -> Library (cs, bs, lib) | Object (_, bs, obj) -> Object (cs, bs, obj) | Executable (_, bs, exec) -> Executable (cs, bs, exec) | Flag (_, flg) -> Flag (cs, flg) | SrcRepo (_, src_repo) -> SrcRepo (cs, src_repo) | Test (_, tst) -> Test (cs, tst) | Doc (_, doc) -> Doc (cs, doc) (** Key used to identify section *) let section_id sct = let k, cs = section_kind_common sct in k, cs.cs_name let string_of_section sct = let k, nm = section_id sct in (match k with | `Library -> "library" | `Object -> "object" | `Executable -> "executable" | `Flag -> "flag" | `SrcRepo -> "src repository" | `Test -> "test" | `Doc -> "doc") ^" "^nm let section_find id scts = List.find (fun sct -> id = section_id sct) scts module CSection = struct type t = section let id = section_id let compare t1 t2 = compare (id t1) (id t2) let equal t1 t2 = (id t1) = (id t2) let hash t = Hashtbl.hash (id t) end module MapSection = Map.Make(CSection) module SetSection = Set.Make(CSection) end module OASISBuildSection = struct (* # 22 "src/oasis/OASISBuildSection.ml" *) end module OASISExecutable = struct (* # 22 "src/oasis/OASISExecutable.ml" *) open OASISTypes let unix_exec_is (cs, bs, exec) is_native ext_dll suffix_program = let dir = OASISUnixPath.concat bs.bs_path (OASISUnixPath.dirname exec.exec_main_is) in let is_native_exec = match bs.bs_compiled_object with | Native -> true | Best -> is_native () | Byte -> false in OASISUnixPath.concat dir (cs.cs_name^(suffix_program ())), if not is_native_exec && not exec.exec_custom && bs.bs_c_sources <> [] then Some (dir^"/dll"^cs.cs_name^"_stubs"^(ext_dll ())) else None end module OASISLibrary = struct (* # 22 "src/oasis/OASISLibrary.ml" *) open OASISTypes open OASISUtils open OASISGettext open OASISSection (* Look for a module file, considering capitalization or not. *) let find_module source_file_exists bs modul = let possible_base_fn = List.map (OASISUnixPath.concat bs.bs_path) [modul; OASISUnixPath.uncapitalize_file modul; OASISUnixPath.capitalize_file modul] in (* TODO: we should be able to be able to determine the source for every * files. Hence we should introduce a Module(source: fn) for the fields * Modules and InternalModules *) List.fold_left (fun acc base_fn -> match acc with | `No_sources _ -> begin let file_found = List.fold_left (fun acc ext -> if source_file_exists (base_fn^ext) then (base_fn^ext) :: acc else acc) [] [".ml"; ".mli"; ".mll"; ".mly"] in match file_found with | [] -> acc | lst -> `Sources (base_fn, lst) end | `Sources _ -> acc) (`No_sources possible_base_fn) possible_base_fn let source_unix_files ~ctxt (cs, bs, lib) source_file_exists = List.fold_left (fun acc modul -> match find_module source_file_exists bs modul with | `Sources (base_fn, lst) -> (base_fn, lst) :: acc | `No_sources _ -> OASISMessage.warning ~ctxt (f_ "Cannot find source file matching \ module '%s' in library %s") modul cs.cs_name; acc) [] (lib.lib_modules @ lib.lib_internal_modules) let generated_unix_files ~ctxt ~is_native ~has_native_dynlink ~ext_lib ~ext_dll ~source_file_exists (cs, bs, lib) = let find_modules lst ext = let find_module modul = match find_module source_file_exists bs modul with | `Sources (base_fn, [fn]) when ext <> "cmi" && Filename.check_suffix fn ".mli" -> None (* No implementation files for pure interface. *) | `Sources (base_fn, _) -> Some [base_fn] | `No_sources lst -> OASISMessage.warning ~ctxt (f_ "Cannot find source file matching \ module '%s' in library %s") modul cs.cs_name; Some lst in List.fold_left (fun acc nm -> match find_module nm with | None -> acc | Some base_fns -> List.map (fun base_fn -> base_fn ^"."^ext) base_fns :: acc) [] lst in (* The .cmx that be compiled along *) let cmxs = let should_be_built = match bs.bs_compiled_object with | Native -> true | Best -> is_native | Byte -> false in if should_be_built then if lib.lib_pack then find_modules [cs.cs_name] "cmx" else find_modules (lib.lib_modules @ lib.lib_internal_modules) "cmx" else [] in let acc_nopath = [] in (* The headers and annot/cmt files that should be compiled along *) let headers = let sufx = if lib.lib_pack then [".cmti"; ".cmt"; ".annot"] else [".cmi"; ".cmti"; ".cmt"; ".annot"] in List.map begin List.fold_left begin fun accu s -> let dot = String.rindex s '.' in let base = String.sub s 0 dot in List.map ((^) base) sufx @ accu end [] end (find_modules lib.lib_modules "cmi") in (* Compute what libraries should be built *) let acc_nopath = (* Add the packed header file if required *) let add_pack_header acc = if lib.lib_pack then [cs.cs_name^".cmi"; cs.cs_name^".cmti"; cs.cs_name^".cmt"] :: acc else acc in let byte acc = add_pack_header ([cs.cs_name^".cma"] :: acc) in let native acc = let acc = add_pack_header (if has_native_dynlink then [cs.cs_name^".cmxs"] :: acc else acc) in [cs.cs_name^".cmxa"] :: [cs.cs_name^ext_lib] :: acc in match bs.bs_compiled_object with | Native -> byte (native acc_nopath) | Best when is_native -> byte (native acc_nopath) | Byte | Best -> byte acc_nopath in (* Add C library to be built *) let acc_nopath = if bs.bs_c_sources <> [] then begin ["lib"^cs.cs_name^"_stubs"^ext_lib] :: ["dll"^cs.cs_name^"_stubs"^ext_dll] :: acc_nopath end else acc_nopath in (* All the files generated *) List.rev_append (List.rev_map (List.rev_map (OASISUnixPath.concat bs.bs_path)) acc_nopath) (headers @ cmxs) end module OASISObject = struct (* # 22 "src/oasis/OASISObject.ml" *) open OASISTypes open OASISGettext let source_unix_files ~ctxt (cs, bs, obj) source_file_exists = List.fold_left (fun acc modul -> match OASISLibrary.find_module source_file_exists bs modul with | `Sources (base_fn, lst) -> (base_fn, lst) :: acc | `No_sources _ -> OASISMessage.warning ~ctxt (f_ "Cannot find source file matching \ module '%s' in object %s") modul cs.cs_name; acc) [] obj.obj_modules let generated_unix_files ~ctxt ~is_native ~source_file_exists (cs, bs, obj) = let find_module ext modul = match OASISLibrary.find_module source_file_exists bs modul with | `Sources (base_fn, _) -> [base_fn ^ ext] | `No_sources lst -> OASISMessage.warning ~ctxt (f_ "Cannot find source file matching \ module '%s' in object %s") modul cs.cs_name ; lst in let header, byte, native, c_object, f = match obj.obj_modules with | [ m ] -> (find_module ".cmi" m, find_module ".cmo" m, find_module ".cmx" m, find_module ".o" m, fun x -> x) | _ -> ([cs.cs_name ^ ".cmi"], [cs.cs_name ^ ".cmo"], [cs.cs_name ^ ".cmx"], [cs.cs_name ^ ".o"], OASISUnixPath.concat bs.bs_path) in List.map (List.map f) ( match bs.bs_compiled_object with | Native -> native :: c_object :: byte :: header :: [] | Best when is_native -> native :: c_object :: byte :: header :: [] | Byte | Best -> byte :: header :: []) end module OASISFindlib = struct (* # 22 "src/oasis/OASISFindlib.ml" *) open OASISTypes open OASISUtils open OASISGettext open OASISSection type library_name = name type findlib_part_name = name type 'a map_of_findlib_part_name = 'a OASISUtils.MapString.t exception InternalLibraryNotFound of library_name exception FindlibPackageNotFound of findlib_name type group_t = | Container of findlib_name * group_t list | Package of (findlib_name * common_section * build_section * [`Library of library | `Object of object_] * group_t list) type data = common_section * build_section * [`Library of library | `Object of object_] type tree = | Node of (data option) * (tree MapString.t) | Leaf of data let findlib_mapping pkg = (* Map from library name to either full findlib name or parts + parent. *) let fndlb_parts_of_lib_name = let fndlb_parts cs lib = let name = match lib.lib_findlib_name with | Some nm -> nm | None -> cs.cs_name in let name = String.concat "." (lib.lib_findlib_containers @ [name]) in name in List.fold_left (fun mp -> function | Library (cs, _, lib) -> begin let lib_name = cs.cs_name in let fndlb_parts = fndlb_parts cs lib in if MapString.mem lib_name mp then failwithf (f_ "The library name '%s' is used more than once.") lib_name; match lib.lib_findlib_parent with | Some lib_name_parent -> MapString.add lib_name (`Unsolved (lib_name_parent, fndlb_parts)) mp | None -> MapString.add lib_name (`Solved fndlb_parts) mp end | Object (cs, _, obj) -> begin let obj_name = cs.cs_name in if MapString.mem obj_name mp then failwithf (f_ "The object name '%s' is used more than once.") obj_name; let findlib_full_name = match obj.obj_findlib_fullname with | Some ns -> String.concat "." ns | None -> obj_name in MapString.add obj_name (`Solved findlib_full_name) mp end | Executable _ | Test _ | Flag _ | SrcRepo _ | Doc _ -> mp) MapString.empty pkg.sections in (* Solve the above graph to be only library name to full findlib name. *) let fndlb_name_of_lib_name = let rec solve visited mp lib_name lib_name_child = if SetString.mem lib_name visited then failwithf (f_ "Library '%s' is involved in a cycle \ with regard to findlib naming.") lib_name; let visited = SetString.add lib_name visited in try match MapString.find lib_name mp with | `Solved fndlb_nm -> fndlb_nm, mp | `Unsolved (lib_nm_parent, post_fndlb_nm) -> let pre_fndlb_nm, mp = solve visited mp lib_nm_parent lib_name in let fndlb_nm = pre_fndlb_nm^"."^post_fndlb_nm in fndlb_nm, MapString.add lib_name (`Solved fndlb_nm) mp with Not_found -> failwithf (f_ "Library '%s', which is defined as the findlib parent of \ library '%s', doesn't exist.") lib_name lib_name_child in let mp = MapString.fold (fun lib_name status mp -> match status with | `Solved _ -> (* Solved initialy, no need to go further *) mp | `Unsolved _ -> let _, mp = solve SetString.empty mp lib_name "" in mp) fndlb_parts_of_lib_name fndlb_parts_of_lib_name in MapString.map (function | `Solved fndlb_nm -> fndlb_nm | `Unsolved _ -> assert false) mp in (* Convert an internal library name to a findlib name. *) let findlib_name_of_library_name lib_nm = try MapString.find lib_nm fndlb_name_of_lib_name with Not_found -> raise (InternalLibraryNotFound lib_nm) in (* Add a library to the tree. *) let add sct mp = let fndlb_fullname = let cs, _, _ = sct in let lib_name = cs.cs_name in findlib_name_of_library_name lib_name in let rec add_children nm_lst (children: tree MapString.t) = match nm_lst with | (hd :: tl) -> begin let node = try add_node tl (MapString.find hd children) with Not_found -> (* New node *) new_node tl in MapString.add hd node children end | [] -> (* Should not have a nameless library. *) assert false and add_node tl node = if tl = [] then begin match node with | Node (None, children) -> Node (Some sct, children) | Leaf (cs', _, _) | Node (Some (cs', _, _), _) -> (* TODO: allow to merge Package, i.e. * archive(byte) = "foo.cma foo_init.cmo" *) let cs, _, _ = sct in failwithf (f_ "Library '%s' and '%s' have the same findlib name '%s'") cs.cs_name cs'.cs_name fndlb_fullname end else begin match node with | Leaf data -> Node (Some data, add_children tl MapString.empty) | Node (data_opt, children) -> Node (data_opt, add_children tl children) end and new_node = function | [] -> Leaf sct | hd :: tl -> Node (None, MapString.add hd (new_node tl) MapString.empty) in add_children (OASISString.nsplit fndlb_fullname '.') mp in let rec group_of_tree mp = MapString.fold (fun nm node acc -> let cur = match node with | Node (Some (cs, bs, lib), children) -> Package (nm, cs, bs, lib, group_of_tree children) | Node (None, children) -> Container (nm, group_of_tree children) | Leaf (cs, bs, lib) -> Package (nm, cs, bs, lib, []) in cur :: acc) mp [] in let group_mp = List.fold_left (fun mp -> function | Library (cs, bs, lib) -> add (cs, bs, `Library lib) mp | Object (cs, bs, obj) -> add (cs, bs, `Object obj) mp | _ -> mp) MapString.empty pkg.sections in let groups = group_of_tree group_mp in let library_name_of_findlib_name = lazy begin (* Revert findlib_name_of_library_name. *) MapString.fold (fun k v mp -> MapString.add v k mp) fndlb_name_of_lib_name MapString.empty end in let library_name_of_findlib_name fndlb_nm = try MapString.find fndlb_nm (Lazy.force library_name_of_findlib_name) with Not_found -> raise (FindlibPackageNotFound fndlb_nm) in groups, findlib_name_of_library_name, library_name_of_findlib_name let findlib_of_group = function | Container (fndlb_nm, _) | Package (fndlb_nm, _, _, _, _) -> fndlb_nm let root_of_group grp = let rec root_lib_aux = (* We do a DFS in the group. *) function | Container (_, children) -> List.fold_left (fun res grp -> if res = None then root_lib_aux grp else res) None children | Package (_, cs, bs, lib, _) -> Some (cs, bs, lib) in match root_lib_aux grp with | Some res -> res | None -> failwithf (f_ "Unable to determine root library of findlib library '%s'") (findlib_of_group grp) end module OASISFlag = struct (* # 22 "src/oasis/OASISFlag.ml" *) end module OASISPackage = struct (* # 22 "src/oasis/OASISPackage.ml" *) end module OASISSourceRepository = struct (* # 22 "src/oasis/OASISSourceRepository.ml" *) end module OASISTest = struct (* # 22 "src/oasis/OASISTest.ml" *) end module OASISDocument = struct (* # 22 "src/oasis/OASISDocument.ml" *) end module OASISExec = struct (* # 22 "src/oasis/OASISExec.ml" *) open OASISGettext open OASISUtils open OASISMessage (* TODO: I don't like this quote, it is there because $(rm) foo expands to * 'rm -f' foo... *) let run ~ctxt ?f_exit_code ?(quote=true) cmd args = let cmd = if quote then if Sys.os_type = "Win32" then if String.contains cmd ' ' then (* Double the 1st double quote... win32... sigh *) "\""^(Filename.quote cmd) else cmd else Filename.quote cmd else cmd in let cmdline = String.concat " " (cmd :: args) in info ~ctxt (f_ "Running command '%s'") cmdline; match f_exit_code, Sys.command cmdline with | None, 0 -> () | None, i -> failwithf (f_ "Command '%s' terminated with error code %d") cmdline i | Some f, i -> f i let run_read_output ~ctxt ?f_exit_code cmd args = let fn = Filename.temp_file "oasis-" ".txt" in try begin let () = run ~ctxt ?f_exit_code cmd (args @ [">"; Filename.quote fn]) in let chn = open_in fn in let routput = ref [] in begin try while true do routput := (input_line chn) :: !routput done with End_of_file -> () end; close_in chn; Sys.remove fn; List.rev !routput end with e -> (try Sys.remove fn with _ -> ()); raise e let run_read_one_line ~ctxt ?f_exit_code cmd args = match run_read_output ~ctxt ?f_exit_code cmd args with | [fst] -> fst | lst -> failwithf (f_ "Command return unexpected output %S") (String.concat "\n" lst) end module OASISFileUtil = struct (* # 22 "src/oasis/OASISFileUtil.ml" *) open OASISGettext let file_exists_case fn = let dirname = Filename.dirname fn in let basename = Filename.basename fn in if Sys.file_exists dirname then if basename = Filename.current_dir_name then true else List.mem basename (Array.to_list (Sys.readdir dirname)) else false let find_file ?(case_sensitive=true) paths exts = (* Cardinal product of two list *) let ( * ) lst1 lst2 = List.flatten (List.map (fun a -> List.map (fun b -> a, b) lst2) lst1) in let rec combined_paths lst = match lst with | p1 :: p2 :: tl -> let acc = (List.map (fun (a, b) -> Filename.concat a b) (p1 * p2)) in combined_paths (acc :: tl) | [e] -> e | [] -> [] in let alternatives = List.map (fun (p, e) -> if String.length e > 0 && e.[0] <> '.' then p ^ "." ^ e else p ^ e) ((combined_paths paths) * exts) in List.find (fun file -> (if case_sensitive then file_exists_case file else Sys.file_exists file) && not (Sys.is_directory file) ) alternatives let which ~ctxt prg = let path_sep = match Sys.os_type with | "Win32" -> ';' | _ -> ':' in let path_lst = OASISString.nsplit (Sys.getenv "PATH") path_sep in let exec_ext = match Sys.os_type with | "Win32" -> "" :: (OASISString.nsplit (Sys.getenv "PATHEXT") path_sep) | _ -> [""] in find_file ~case_sensitive:false [path_lst; [prg]] exec_ext (**/**) let rec fix_dir dn = (* Windows hack because Sys.file_exists "src\\" = false when * Sys.file_exists "src" = true *) let ln = String.length dn in if Sys.os_type = "Win32" && ln > 0 && dn.[ln - 1] = '\\' then fix_dir (String.sub dn 0 (ln - 1)) else dn let q = Filename.quote (**/**) let cp ~ctxt ?(recurse=false) src tgt = if recurse then match Sys.os_type with | "Win32" -> OASISExec.run ~ctxt "xcopy" [q src; q tgt; "/E"] | _ -> OASISExec.run ~ctxt "cp" ["-r"; q src; q tgt] else OASISExec.run ~ctxt (match Sys.os_type with | "Win32" -> "copy" | _ -> "cp") [q src; q tgt] let mkdir ~ctxt tgt = OASISExec.run ~ctxt (match Sys.os_type with | "Win32" -> "md" | _ -> "mkdir") [q tgt] let rec mkdir_parent ~ctxt f tgt = let tgt = fix_dir tgt in if Sys.file_exists tgt then begin if not (Sys.is_directory tgt) then OASISUtils.failwithf (f_ "Cannot create directory '%s', a file of the same name already \ exists") tgt end else begin mkdir_parent ~ctxt f (Filename.dirname tgt); if not (Sys.file_exists tgt) then begin f tgt; mkdir ~ctxt tgt end end let rmdir ~ctxt tgt = if Sys.readdir tgt = [||] then begin match Sys.os_type with | "Win32" -> OASISExec.run ~ctxt "rd" [q tgt] | _ -> OASISExec.run ~ctxt "rm" ["-r"; q tgt] end else begin OASISMessage.error ~ctxt (f_ "Cannot remove directory '%s': not empty.") tgt end let glob ~ctxt fn = let basename = Filename.basename fn in if String.length basename >= 2 && basename.[0] = '*' && basename.[1] = '.' then begin let ext_len = (String.length basename) - 2 in let ext = String.sub basename 2 ext_len in let dirname = Filename.dirname fn in Array.fold_left (fun acc fn -> try let fn_ext = String.sub fn ((String.length fn) - ext_len) ext_len in if fn_ext = ext then (Filename.concat dirname fn) :: acc else acc with Invalid_argument _ -> acc) [] (Sys.readdir dirname) end else begin if file_exists_case fn then [fn] else [] end end # 2894 "setup.ml" module BaseEnvLight = struct (* # 22 "src/base/BaseEnvLight.ml" *) module MapString = Map.Make(String) type t = string MapString.t let default_filename = lazy (Filename.concat (Sys.getcwd ()) "setup.data") let load ?(allow_empty=false) ?(filename=Lazy.force default_filename) () = if Sys.file_exists filename then begin let chn = open_in_bin filename in let st = Stream.of_channel chn in let line = ref 1 in let st_line = Stream.from (fun _ -> try match Stream.next st with | '\n' -> incr line; Some '\n' | c -> Some c with Stream.Failure -> None) in let lexer = Genlex.make_lexer ["="] st_line in let rec read_file mp = match Stream.npeek 3 lexer with | [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] -> Stream.junk lexer; Stream.junk lexer; Stream.junk lexer; read_file (MapString.add nm value mp) | [] -> mp | _ -> failwith (Printf.sprintf "Malformed data file '%s' line %d" filename !line) in let mp = read_file MapString.empty in close_in chn; mp end else if allow_empty then begin MapString.empty end else begin failwith (Printf.sprintf "Unable to load environment, the file '%s' doesn't exist." filename) end let rec var_expand str env = let buff = Buffer.create ((String.length str) * 2) in Buffer.add_substitute buff (fun var -> try var_expand (MapString.find var env) env with Not_found -> failwith (Printf.sprintf "No variable %s defined when trying to expand %S." var str)) str; Buffer.contents buff let var_get name env = var_expand (MapString.find name env) env let var_choose lst env = OASISExpr.choose (fun nm -> var_get nm env) lst end # 2997 "setup.ml" module BaseContext = struct (* # 22 "src/base/BaseContext.ml" *) (* TODO: get rid of this module. *) open OASISContext let args () = fst (fspecs ()) let default = default end module BaseMessage = struct (* # 22 "src/base/BaseMessage.ml" *) (** Message to user, overrid for Base @author Sylvain Le Gall *) open OASISMessage open BaseContext let debug fmt = debug ~ctxt:!default fmt let info fmt = info ~ctxt:!default fmt let warning fmt = warning ~ctxt:!default fmt let error fmt = error ~ctxt:!default fmt end module BaseEnv = struct (* # 22 "src/base/BaseEnv.ml" *) open OASISGettext open OASISUtils open PropList module MapString = BaseEnvLight.MapString type origin_t = | ODefault | OGetEnv | OFileLoad | OCommandLine type cli_handle_t = | CLINone | CLIAuto | CLIWith | CLIEnable | CLIUser of (Arg.key * Arg.spec * Arg.doc) list type definition_t = { hide: bool; dump: bool; cli: cli_handle_t; arg_help: string option; group: string option; } let schema = Schema.create "environment" (* Environment data *) let env = Data.create () (* Environment data from file *) let env_from_file = ref MapString.empty (* Lexer for var *) let var_lxr = Genlex.make_lexer [] let rec var_expand str = let buff = Buffer.create ((String.length str) * 2) in Buffer.add_substitute buff (fun var -> try (* TODO: this is a quick hack to allow calling Test.Command * without defining executable name really. I.e. if there is * an exec Executable toto, then $(toto) should be replace * by its real name. It is however useful to have this function * for other variable that depend on the host and should be * written better than that. *) let st = var_lxr (Stream.of_string var) in match Stream.npeek 3 st with | [Genlex.Ident "utoh"; Genlex.Ident nm] -> OASISHostPath.of_unix (var_get nm) | [Genlex.Ident "utoh"; Genlex.String s] -> OASISHostPath.of_unix s | [Genlex.Ident "ocaml_escaped"; Genlex.Ident nm] -> String.escaped (var_get nm) | [Genlex.Ident "ocaml_escaped"; Genlex.String s] -> String.escaped s | [Genlex.Ident nm] -> var_get nm | _ -> failwithf (f_ "Unknown expression '%s' in variable expansion of %s.") var str with | Unknown_field (_, _) -> failwithf (f_ "No variable %s defined when trying to expand %S.") var str | Stream.Error e -> failwithf (f_ "Syntax error when parsing '%s' when trying to \ expand %S: %s") var str e) str; Buffer.contents buff and var_get name = let vl = try Schema.get schema env name with Unknown_field _ as e -> begin try MapString.find name !env_from_file with Not_found -> raise e end in var_expand vl let var_choose ?printer ?name lst = OASISExpr.choose ?printer ?name var_get lst let var_protect vl = let buff = Buffer.create (String.length vl) in String.iter (function | '$' -> Buffer.add_string buff "\\$" | c -> Buffer.add_char buff c) vl; Buffer.contents buff let var_define ?(hide=false) ?(dump=true) ?short_desc ?(cli=CLINone) ?arg_help ?group name (* TODO: type constraint on the fact that name must be a valid OCaml id *) dflt = let default = [ OFileLoad, (fun () -> MapString.find name !env_from_file); ODefault, dflt; OGetEnv, (fun () -> Sys.getenv name); ] in let extra = { hide = hide; dump = dump; cli = cli; arg_help = arg_help; group = group; } in (* Try to find a value that can be defined *) let var_get_low lst = let errors, res = List.fold_left (fun (errors, res) (o, v) -> if res = None then begin try errors, Some (v ()) with | Not_found -> errors, res | Failure rsn -> (rsn :: errors), res | e -> (Printexc.to_string e) :: errors, res end else errors, res) ([], None) (List.sort (fun (o1, _) (o2, _) -> Pervasives.compare o2 o1) lst) in match res, errors with | Some v, _ -> v | None, [] -> raise (Not_set (name, None)) | None, lst -> raise (Not_set (name, Some (String.concat (s_ ", ") lst))) in let help = match short_desc with | Some fs -> Some fs | None -> None in let var_get_lst = FieldRO.create ~schema ~name ~parse:(fun ?(context=ODefault) s -> [context, fun () -> s]) ~print:var_get_low ~default ~update:(fun ?context x old_x -> x @ old_x) ?help extra in fun () -> var_expand (var_get_low (var_get_lst env)) let var_redefine ?hide ?dump ?short_desc ?cli ?arg_help ?group name dflt = if Schema.mem schema name then begin (* TODO: look suspsicious, we want to memorize dflt not dflt () *) Schema.set schema env ~context:ODefault name (dflt ()); fun () -> var_get name end else begin var_define ?hide ?dump ?short_desc ?cli ?arg_help ?group name dflt end let var_ignore (e: unit -> string) = () let print_hidden = var_define ~hide:true ~dump:false ~cli:CLIAuto ~arg_help:"Print even non-printable variable. (debug)" "print_hidden" (fun () -> "false") let var_all () = List.rev (Schema.fold (fun acc nm def _ -> if not def.hide || bool_of_string (print_hidden ()) then nm :: acc else acc) [] schema) let default_filename = BaseEnvLight.default_filename let load ?allow_empty ?filename () = env_from_file := BaseEnvLight.load ?allow_empty ?filename () let unload () = env_from_file := MapString.empty; Data.clear env let dump ?(filename=Lazy.force default_filename) () = let chn = open_out_bin filename in let output nm value = Printf.fprintf chn "%s=%S\n" nm value in let mp_todo = (* Dump data from schema *) Schema.fold (fun mp_todo nm def _ -> if def.dump then begin try let value = Schema.get schema env nm in output nm value with Not_set _ -> () end; MapString.remove nm mp_todo) !env_from_file schema in (* Dump data defined outside of schema *) MapString.iter output mp_todo; (* End of the dump *) close_out chn let print () = let printable_vars = Schema.fold (fun acc nm def short_descr_opt -> if not def.hide || bool_of_string (print_hidden ()) then begin try let value = Schema.get schema env nm in let txt = match short_descr_opt with | Some s -> s () | None -> nm in (txt, value) :: acc with Not_set _ -> acc end else acc) [] schema in let max_length = List.fold_left max 0 (List.rev_map String.length (List.rev_map fst printable_vars)) in let dot_pad str = String.make ((max_length - (String.length str)) + 3) '.' in Printf.printf "\nConfiguration: \n"; List.iter (fun (name, value) -> Printf.printf "%s: %s %s\n" name (dot_pad name) value) (List.rev printable_vars); Printf.printf "\n%!" let args () = let arg_concat = OASISUtils.varname_concat ~hyphen:'-' in [ "--override", Arg.Tuple ( let rvr = ref "" in let rvl = ref "" in [ Arg.Set_string rvr; Arg.Set_string rvl; Arg.Unit (fun () -> Schema.set schema env ~context:OCommandLine !rvr !rvl) ] ), "var+val Override any configuration variable."; ] @ List.flatten (Schema.fold (fun acc name def short_descr_opt -> let var_set s = Schema.set schema env ~context:OCommandLine name s in let arg_name = OASISUtils.varname_of_string ~hyphen:'-' name in let hlp = match short_descr_opt with | Some txt -> txt () | None -> "" in let arg_hlp = match def.arg_help with | Some s -> s | None -> "str" in let default_value = try Printf.sprintf (f_ " [%s]") (Schema.get schema env name) with Not_set _ -> "" in let args = match def.cli with | CLINone -> [] | CLIAuto -> [ arg_concat "--" arg_name, Arg.String var_set, Printf.sprintf (f_ "%s %s%s") arg_hlp hlp default_value ] | CLIWith -> [ arg_concat "--with-" arg_name, Arg.String var_set, Printf.sprintf (f_ "%s %s%s") arg_hlp hlp default_value ] | CLIEnable -> let dflt = if default_value = " [true]" then s_ " [default: enabled]" else s_ " [default: disabled]" in [ arg_concat "--enable-" arg_name, Arg.Unit (fun () -> var_set "true"), Printf.sprintf (f_ " %s%s") hlp dflt; arg_concat "--disable-" arg_name, Arg.Unit (fun () -> var_set "false"), Printf.sprintf (f_ " %s%s") hlp dflt ] | CLIUser lst -> lst in args :: acc) [] schema) end module BaseArgExt = struct (* # 22 "src/base/BaseArgExt.ml" *) open OASISUtils open OASISGettext let parse argv args = (* Simulate command line for Arg *) let current = ref 0 in try Arg.parse_argv ~current:current (Array.concat [[|"none"|]; argv]) (Arg.align args) (failwithf (f_ "Don't know what to do with arguments: '%s'")) (s_ "configure options:") with | Arg.Help txt -> print_endline txt; exit 0 | Arg.Bad txt -> prerr_endline txt; exit 1 end module BaseCheck = struct (* # 22 "src/base/BaseCheck.ml" *) open BaseEnv open BaseMessage open OASISUtils open OASISGettext let prog_best prg prg_lst = var_redefine prg (fun () -> let alternate = List.fold_left (fun res e -> match res with | Some _ -> res | None -> try Some (OASISFileUtil.which ~ctxt:!BaseContext.default e) with Not_found -> None) None prg_lst in match alternate with | Some prg -> prg | None -> raise Not_found) let prog prg = prog_best prg [prg] let prog_opt prg = prog_best prg [prg^".opt"; prg] let ocamlfind = prog "ocamlfind" let version var_prefix cmp fversion () = (* Really compare version provided *) let var = var_prefix^"_version_"^(OASISVersion.varname_of_comparator cmp) in var_redefine ~hide:true var (fun () -> let version_str = match fversion () with | "[Distributed with OCaml]" -> begin try (var_get "ocaml_version") with Not_found -> warning (f_ "Variable ocaml_version not defined, fallback \ to default"); Sys.ocaml_version end | res -> res in let version = OASISVersion.version_of_string version_str in if OASISVersion.comparator_apply version cmp then version_str else failwithf (f_ "Cannot satisfy version constraint on %s: %s (version: %s)") var_prefix (OASISVersion.string_of_comparator cmp) version_str) () let package_version pkg = OASISExec.run_read_one_line ~ctxt:!BaseContext.default (ocamlfind ()) ["query"; "-format"; "%v"; pkg] let package ?version_comparator pkg () = let var = OASISUtils.varname_concat "pkg_" (OASISUtils.varname_of_string pkg) in let findlib_dir pkg = let dir = OASISExec.run_read_one_line ~ctxt:!BaseContext.default (ocamlfind ()) ["query"; "-format"; "%d"; pkg] in if Sys.file_exists dir && Sys.is_directory dir then dir else failwithf (f_ "When looking for findlib package %s, \ directory %s return doesn't exist") pkg dir in let vl = var_redefine var (fun () -> findlib_dir pkg) () in ( match version_comparator with | Some ver_cmp -> ignore (version var ver_cmp (fun _ -> package_version pkg) ()) | None -> () ); vl end module BaseOCamlcConfig = struct (* # 22 "src/base/BaseOCamlcConfig.ml" *) open BaseEnv open OASISUtils open OASISGettext module SMap = Map.Make(String) let ocamlc = BaseCheck.prog_opt "ocamlc" let ocamlc_config_map = (* Map name to value for ocamlc -config output (name ^": "^value) *) let rec split_field mp lst = match lst with | line :: tl -> let mp = try let pos_semicolon = String.index line ':' in if pos_semicolon > 1 then ( let name = String.sub line 0 pos_semicolon in let linelen = String.length line in let value = if linelen > pos_semicolon + 2 then String.sub line (pos_semicolon + 2) (linelen - pos_semicolon - 2) else "" in SMap.add name value mp ) else ( mp ) with Not_found -> ( mp ) in split_field mp tl | [] -> mp in let cache = lazy (var_protect (Marshal.to_string (split_field SMap.empty (OASISExec.run_read_output ~ctxt:!BaseContext.default (ocamlc ()) ["-config"])) [])) in var_redefine "ocamlc_config_map" ~hide:true ~dump:false (fun () -> (* TODO: update if ocamlc change !!! *) Lazy.force cache) let var_define nm = (* Extract data from ocamlc -config *) let avlbl_config_get () = Marshal.from_string (ocamlc_config_map ()) 0 in let chop_version_suffix s = try String.sub s 0 (String.index s '+') with _ -> s in let nm_config, value_config = match nm with | "ocaml_version" -> "version", chop_version_suffix | _ -> nm, (fun x -> x) in var_redefine nm (fun () -> try let map = avlbl_config_get () in let value = SMap.find nm_config map in value_config value with Not_found -> failwithf (f_ "Cannot find field '%s' in '%s -config' output") nm (ocamlc ())) end module BaseStandardVar = struct (* # 22 "src/base/BaseStandardVar.ml" *) open OASISGettext open OASISTypes open OASISExpr open BaseCheck open BaseEnv let ocamlfind = BaseCheck.ocamlfind let ocamlc = BaseOCamlcConfig.ocamlc let ocamlopt = prog_opt "ocamlopt" let ocamlbuild = prog "ocamlbuild" (**/**) let rpkg = ref None let pkg_get () = match !rpkg with | Some pkg -> pkg | None -> failwith (s_ "OASIS Package is not set") let var_cond = ref [] let var_define_cond ~since_version f dflt = let holder = ref (fun () -> dflt) in let since_version = OASISVersion.VGreaterEqual (OASISVersion.version_of_string since_version) in var_cond := (fun ver -> if OASISVersion.comparator_apply ver since_version then holder := f ()) :: !var_cond; fun () -> !holder () (**/**) let pkg_name = var_define ~short_desc:(fun () -> s_ "Package name") "pkg_name" (fun () -> (pkg_get ()).name) let pkg_version = var_define ~short_desc:(fun () -> s_ "Package version") "pkg_version" (fun () -> (OASISVersion.string_of_version (pkg_get ()).version)) let c = BaseOCamlcConfig.var_define let os_type = c "os_type" let system = c "system" let architecture = c "architecture" let ccomp_type = c "ccomp_type" let ocaml_version = c "ocaml_version" (* TODO: Check standard variable presence at runtime *) let standard_library_default = c "standard_library_default" let standard_library = c "standard_library" let standard_runtime = c "standard_runtime" let bytecomp_c_compiler = c "bytecomp_c_compiler" let native_c_compiler = c "native_c_compiler" let model = c "model" let ext_obj = c "ext_obj" let ext_asm = c "ext_asm" let ext_lib = c "ext_lib" let ext_dll = c "ext_dll" let default_executable_name = c "default_executable_name" let systhread_supported = c "systhread_supported" let flexlink = BaseCheck.prog "flexlink" let flexdll_version = var_define ~short_desc:(fun () -> "FlexDLL version (Win32)") "flexdll_version" (fun () -> let lst = OASISExec.run_read_output ~ctxt:!BaseContext.default (flexlink ()) ["-help"] in match lst with | line :: _ -> Scanf.sscanf line "FlexDLL version %s" (fun ver -> ver) | [] -> raise Not_found) (**/**) let p name hlp dflt = var_define ~short_desc:hlp ~cli:CLIAuto ~arg_help:"dir" name dflt let (/) a b = if os_type () = Sys.os_type then Filename.concat a b else if os_type () = "Unix" then OASISUnixPath.concat a b else OASISUtils.failwithf (f_ "Cannot handle os_type %s filename concat") (os_type ()) (**/**) let prefix = p "prefix" (fun () -> s_ "Install architecture-independent files dir") (fun () -> match os_type () with | "Win32" -> let program_files = Sys.getenv "PROGRAMFILES" in program_files/(pkg_name ()) | _ -> "/usr/local") let exec_prefix = p "exec_prefix" (fun () -> s_ "Install architecture-dependent files in dir") (fun () -> "$prefix") let bindir = p "bindir" (fun () -> s_ "User executables") (fun () -> "$exec_prefix"/"bin") let sbindir = p "sbindir" (fun () -> s_ "System admin executables") (fun () -> "$exec_prefix"/"sbin") let libexecdir = p "libexecdir" (fun () -> s_ "Program executables") (fun () -> "$exec_prefix"/"libexec") let sysconfdir = p "sysconfdir" (fun () -> s_ "Read-only single-machine data") (fun () -> "$prefix"/"etc") let sharedstatedir = p "sharedstatedir" (fun () -> s_ "Modifiable architecture-independent data") (fun () -> "$prefix"/"com") let localstatedir = p "localstatedir" (fun () -> s_ "Modifiable single-machine data") (fun () -> "$prefix"/"var") let libdir = p "libdir" (fun () -> s_ "Object code libraries") (fun () -> "$exec_prefix"/"lib") let datarootdir = p "datarootdir" (fun () -> s_ "Read-only arch-independent data root") (fun () -> "$prefix"/"share") let datadir = p "datadir" (fun () -> s_ "Read-only architecture-independent data") (fun () -> "$datarootdir") let infodir = p "infodir" (fun () -> s_ "Info documentation") (fun () -> "$datarootdir"/"info") let localedir = p "localedir" (fun () -> s_ "Locale-dependent data") (fun () -> "$datarootdir"/"locale") let mandir = p "mandir" (fun () -> s_ "Man documentation") (fun () -> "$datarootdir"/"man") let docdir = p "docdir" (fun () -> s_ "Documentation root") (fun () -> "$datarootdir"/"doc"/"$pkg_name") let htmldir = p "htmldir" (fun () -> s_ "HTML documentation") (fun () -> "$docdir") let dvidir = p "dvidir" (fun () -> s_ "DVI documentation") (fun () -> "$docdir") let pdfdir = p "pdfdir" (fun () -> s_ "PDF documentation") (fun () -> "$docdir") let psdir = p "psdir" (fun () -> s_ "PS documentation") (fun () -> "$docdir") let destdir = p "destdir" (fun () -> s_ "Prepend a path when installing package") (fun () -> raise (PropList.Not_set ("destdir", Some (s_ "undefined by construct")))) let findlib_version = var_define "findlib_version" (fun () -> BaseCheck.package_version "findlib") let is_native = var_define "is_native" (fun () -> try let _s: string = ocamlopt () in "true" with PropList.Not_set _ -> let _s: string = ocamlc () in "false") let ext_program = var_define "suffix_program" (fun () -> match os_type () with | "Win32" | "Cygwin" -> ".exe" | _ -> "") let rm = var_define ~short_desc:(fun () -> s_ "Remove a file.") "rm" (fun () -> match os_type () with | "Win32" -> "del" | _ -> "rm -f") let rmdir = var_define ~short_desc:(fun () -> s_ "Remove a directory.") "rmdir" (fun () -> match os_type () with | "Win32" -> "rd" | _ -> "rm -rf") let debug = var_define ~short_desc:(fun () -> s_ "Turn ocaml debug flag on") ~cli:CLIEnable "debug" (fun () -> "true") let profile = var_define ~short_desc:(fun () -> s_ "Turn ocaml profile flag on") ~cli:CLIEnable "profile" (fun () -> "false") let tests = var_define_cond ~since_version:"0.3" (fun () -> var_define ~short_desc:(fun () -> s_ "Compile tests executable and library and run them") ~cli:CLIEnable "tests" (fun () -> "false")) "true" let docs = var_define_cond ~since_version:"0.3" (fun () -> var_define ~short_desc:(fun () -> s_ "Create documentations") ~cli:CLIEnable "docs" (fun () -> "true")) "true" let native_dynlink = var_define ~short_desc:(fun () -> s_ "Compiler support generation of .cmxs.") ~cli:CLINone "native_dynlink" (fun () -> let res = let ocaml_lt_312 () = OASISVersion.comparator_apply (OASISVersion.version_of_string (ocaml_version ())) (OASISVersion.VLesser (OASISVersion.version_of_string "3.12.0")) in let flexdll_lt_030 () = OASISVersion.comparator_apply (OASISVersion.version_of_string (flexdll_version ())) (OASISVersion.VLesser (OASISVersion.version_of_string "0.30")) in let has_native_dynlink = let ocamlfind = ocamlfind () in try let fn = OASISExec.run_read_one_line ~ctxt:!BaseContext.default ocamlfind ["query"; "-predicates"; "native"; "dynlink"; "-format"; "%d/%a"] in Sys.file_exists fn with _ -> false in if not has_native_dynlink then false else if ocaml_lt_312 () then false else if (os_type () = "Win32" || os_type () = "Cygwin") && flexdll_lt_030 () then begin BaseMessage.warning (f_ ".cmxs generation disabled because FlexDLL needs to be \ at least 0.30. Please upgrade FlexDLL from %s to 0.30.") (flexdll_version ()); false end else true in string_of_bool res) let init pkg = rpkg := Some pkg; List.iter (fun f -> f pkg.oasis_version) !var_cond end module BaseFileAB = struct (* # 22 "src/base/BaseFileAB.ml" *) open BaseEnv open OASISGettext open BaseMessage let to_filename fn = let fn = OASISHostPath.of_unix fn in if not (Filename.check_suffix fn ".ab") then warning (f_ "File '%s' doesn't have '.ab' extension") fn; Filename.chop_extension fn let replace fn_lst = let buff = Buffer.create 13 in List.iter (fun fn -> let fn = OASISHostPath.of_unix fn in let chn_in = open_in fn in let chn_out = open_out (to_filename fn) in ( try while true do Buffer.add_string buff (var_expand (input_line chn_in)); Buffer.add_char buff '\n' done with End_of_file -> () ); Buffer.output_buffer chn_out buff; Buffer.clear buff; close_in chn_in; close_out chn_out) fn_lst end module BaseLog = struct (* # 22 "src/base/BaseLog.ml" *) open OASISUtils let default_filename = lazy (Filename.concat (Filename.dirname (Lazy.force BaseEnv.default_filename)) "setup.log") module SetTupleString = Set.Make (struct type t = string * string let compare (s11, s12) (s21, s22) = match String.compare s11 s21 with | 0 -> String.compare s12 s22 | n -> n end) let load () = let default_filename = Lazy.force default_filename in if Sys.file_exists default_filename then begin let chn = open_in default_filename in let scbuf = Scanf.Scanning.from_file default_filename in let rec read_aux (st, lst) = if not (Scanf.Scanning.end_of_input scbuf) then begin let acc = try Scanf.bscanf scbuf "%S %S\n" (fun e d -> let t = e, d in if SetTupleString.mem t st then st, lst else SetTupleString.add t st, t :: lst) with Scanf.Scan_failure _ -> failwith (Scanf.bscanf scbuf "%l" (fun line -> Printf.sprintf "Malformed log file '%s' at line %d" default_filename line)) in read_aux acc end else begin close_in chn; List.rev lst end in read_aux (SetTupleString.empty, []) end else begin [] end let register event data = let chn_out = open_out_gen [Open_append; Open_creat; Open_text] 0o644 (Lazy.force default_filename) in Printf.fprintf chn_out "%S %S\n" event data; close_out chn_out let unregister event data = let default_filename = Lazy.force default_filename in if Sys.file_exists default_filename then begin let lst = load () in let chn_out = open_out default_filename in let write_something = ref false in List.iter (fun (e, d) -> if e <> event || d <> data then begin write_something := true; Printf.fprintf chn_out "%S %S\n" e d end) lst; close_out chn_out; if not !write_something then Sys.remove default_filename end let filter events = let st_events = List.fold_left (fun st e -> SetString.add e st) SetString.empty events in List.filter (fun (e, _) -> SetString.mem e st_events) (load ()) let exists event data = List.exists (fun v -> (event, data) = v) (load ()) end module BaseBuilt = struct (* # 22 "src/base/BaseBuilt.ml" *) open OASISTypes open OASISGettext open BaseStandardVar open BaseMessage type t = | BExec (* Executable *) | BExecLib (* Library coming with executable *) | BLib (* Library *) | BObj (* Library *) | BDoc (* Document *) let to_log_event_file t nm = "built_"^ (match t with | BExec -> "exec" | BExecLib -> "exec_lib" | BLib -> "lib" | BObj -> "obj" | BDoc -> "doc")^ "_"^nm let to_log_event_done t nm = "is_"^(to_log_event_file t nm) let register t nm lst = BaseLog.register (to_log_event_done t nm) "true"; List.iter (fun alt -> let registered = List.fold_left (fun registered fn -> if OASISFileUtil.file_exists_case fn then begin BaseLog.register (to_log_event_file t nm) (if Filename.is_relative fn then Filename.concat (Sys.getcwd ()) fn else fn); true end else registered) false alt in if not registered then warning (f_ "Cannot find an existing alternative files among: %s") (String.concat (s_ ", ") alt)) lst let unregister t nm = List.iter (fun (e, d) -> BaseLog.unregister e d) (BaseLog.filter [to_log_event_file t nm; to_log_event_done t nm]) let fold t nm f acc = List.fold_left (fun acc (_, fn) -> if OASISFileUtil.file_exists_case fn then begin f acc fn end else begin warning (f_ "File '%s' has been marked as built \ for %s but doesn't exist") fn (Printf.sprintf (match t with | BExec | BExecLib -> (f_ "executable %s") | BLib -> (f_ "library %s") | BObj -> (f_ "object %s") | BDoc -> (f_ "documentation %s")) nm); acc end) acc (BaseLog.filter [to_log_event_file t nm]) let is_built t nm = List.fold_left (fun is_built (_, d) -> (try bool_of_string d with _ -> false)) false (BaseLog.filter [to_log_event_done t nm]) let of_executable ffn (cs, bs, exec) = let unix_exec_is, unix_dll_opt = OASISExecutable.unix_exec_is (cs, bs, exec) (fun () -> bool_of_string (is_native ())) ext_dll ext_program in let evs = (BExec, cs.cs_name, [[ffn unix_exec_is]]) :: (match unix_dll_opt with | Some fn -> [BExecLib, cs.cs_name, [[ffn fn]]] | None -> []) in evs, unix_exec_is, unix_dll_opt let of_library ffn (cs, bs, lib) = let unix_lst = OASISLibrary.generated_unix_files ~ctxt:!BaseContext.default ~source_file_exists:(fun fn -> OASISFileUtil.file_exists_case (OASISHostPath.of_unix fn)) ~is_native:(bool_of_string (is_native ())) ~has_native_dynlink:(bool_of_string (native_dynlink ())) ~ext_lib:(ext_lib ()) ~ext_dll:(ext_dll ()) (cs, bs, lib) in let evs = [BLib, cs.cs_name, List.map (List.map ffn) unix_lst] in evs, unix_lst let of_object ffn (cs, bs, obj) = let unix_lst = OASISObject.generated_unix_files ~ctxt:!BaseContext.default ~source_file_exists:(fun fn -> OASISFileUtil.file_exists_case (OASISHostPath.of_unix fn)) ~is_native:(bool_of_string (is_native ())) (cs, bs, obj) in let evs = [BObj, cs.cs_name, List.map (List.map ffn) unix_lst] in evs, unix_lst end module BaseCustom = struct (* # 22 "src/base/BaseCustom.ml" *) open BaseEnv open BaseMessage open OASISTypes open OASISGettext let run cmd args extra_args = OASISExec.run ~ctxt:!BaseContext.default ~quote:false (var_expand cmd) (List.map var_expand (args @ (Array.to_list extra_args))) let hook ?(failsafe=false) cstm f e = let optional_command lst = let printer = function | Some (cmd, args) -> String.concat " " (cmd :: args) | None -> s_ "No command" in match var_choose ~name:(s_ "Pre/Post Command") ~printer lst with | Some (cmd, args) -> begin try run cmd args [||] with e when failsafe -> warning (f_ "Command '%s' fail with error: %s") (String.concat " " (cmd :: args)) (match e with | Failure msg -> msg | e -> Printexc.to_string e) end | None -> () in let res = optional_command cstm.pre_command; f e in optional_command cstm.post_command; res end module BaseDynVar = struct (* # 22 "src/base/BaseDynVar.ml" *) open OASISTypes open OASISGettext open BaseEnv open BaseBuilt let init pkg = (* TODO: disambiguate exec vs other variable by adding exec_VARNAME. *) (* TODO: provide compile option for library libary_byte_args_VARNAME... *) List.iter (function | Executable (cs, bs, exec) -> if var_choose bs.bs_build then var_ignore (var_redefine (* We don't save this variable *) ~dump:false ~short_desc:(fun () -> Printf.sprintf (f_ "Filename of executable '%s'") cs.cs_name) (OASISUtils.varname_of_string cs.cs_name) (fun () -> let fn_opt = fold BExec cs.cs_name (fun _ fn -> Some fn) None in match fn_opt with | Some fn -> fn | None -> raise (PropList.Not_set (cs.cs_name, Some (Printf.sprintf (f_ "Executable '%s' not yet built.") cs.cs_name))))) | Library _ | Object _ | Flag _ | Test _ | SrcRepo _ | Doc _ -> ()) pkg.sections end module BaseTest = struct (* # 22 "src/base/BaseTest.ml" *) open BaseEnv open BaseMessage open OASISTypes open OASISExpr open OASISGettext let test lst pkg extra_args = let one_test (failure, n) (test_plugin, cs, test) = if var_choose ~name:(Printf.sprintf (f_ "test %s run") cs.cs_name) ~printer:string_of_bool test.test_run then begin let () = info (f_ "Running test '%s'") cs.cs_name in let back_cwd = match test.test_working_directory with | Some dir -> let cwd = Sys.getcwd () in let chdir d = info (f_ "Changing directory to '%s'") d; Sys.chdir d in chdir dir; fun () -> chdir cwd | None -> fun () -> () in try let failure_percent = BaseCustom.hook test.test_custom (test_plugin pkg (cs, test)) extra_args in back_cwd (); (failure_percent +. failure, n + 1) with e -> begin back_cwd (); raise e end end else begin info (f_ "Skipping test '%s'") cs.cs_name; (failure, n) end in let failed, n = List.fold_left one_test (0.0, 0) lst in let failure_percent = if n = 0 then 0.0 else failed /. (float_of_int n) in let msg = Printf.sprintf (f_ "Tests had a %.2f%% failure rate") (100. *. failure_percent) in if failure_percent > 0.0 then failwith msg else info "%s" msg; (* Possible explanation why the tests where not run. *) if OASISFeatures.package_test OASISFeatures.flag_tests pkg && not (bool_of_string (BaseStandardVar.tests ())) && lst <> [] then BaseMessage.warning "Tests are turned off, consider enabling with \ 'ocaml setup.ml -configure --enable-tests'" end module BaseDoc = struct (* # 22 "src/base/BaseDoc.ml" *) open BaseEnv open BaseMessage open OASISTypes open OASISGettext let doc lst pkg extra_args = let one_doc (doc_plugin, cs, doc) = if var_choose ~name:(Printf.sprintf (f_ "documentation %s build") cs.cs_name) ~printer:string_of_bool doc.doc_build then begin info (f_ "Building documentation '%s'") cs.cs_name; BaseCustom.hook doc.doc_custom (doc_plugin pkg (cs, doc)) extra_args end in List.iter one_doc lst; if OASISFeatures.package_test OASISFeatures.flag_docs pkg && not (bool_of_string (BaseStandardVar.docs ())) && lst <> [] then BaseMessage.warning "Docs are turned off, consider enabling with \ 'ocaml setup.ml -configure --enable-docs'" end module BaseSetup = struct (* # 22 "src/base/BaseSetup.ml" *) open BaseEnv open BaseMessage open OASISTypes open OASISSection open OASISGettext open OASISUtils type std_args_fun = package -> string array -> unit type ('a, 'b) section_args_fun = name * (package -> (common_section * 'a) -> string array -> 'b) type t = { configure: std_args_fun; build: std_args_fun; doc: ((doc, unit) section_args_fun) list; test: ((test, float) section_args_fun) list; install: std_args_fun; uninstall: std_args_fun; clean: std_args_fun list; clean_doc: (doc, unit) section_args_fun list; clean_test: (test, unit) section_args_fun list; distclean: std_args_fun list; distclean_doc: (doc, unit) section_args_fun list; distclean_test: (test, unit) section_args_fun list; package: package; oasis_fn: string option; oasis_version: string; oasis_digest: Digest.t option; oasis_exec: string option; oasis_setup_args: string list; setup_update: bool; } (* Associate a plugin function with data from package *) let join_plugin_sections filter_map lst = List.rev (List.fold_left (fun acc sct -> match filter_map sct with | Some e -> e :: acc | None -> acc) [] lst) (* Search for plugin data associated with a section name *) let lookup_plugin_section plugin action nm lst = try List.assoc nm lst with Not_found -> failwithf (f_ "Cannot find plugin %s matching section %s for %s action") plugin nm action let configure t args = (* Run configure *) BaseCustom.hook t.package.conf_custom (fun () -> (* Reload if preconf has changed it *) begin try unload (); load (); with _ -> () end; (* Run plugin's configure *) t.configure t.package args; (* Dump to allow postconf to change it *) dump ()) (); (* Reload environment *) unload (); load (); (* Save environment *) print (); (* Replace data in file *) BaseFileAB.replace t.package.files_ab let build t args = BaseCustom.hook t.package.build_custom (t.build t.package) args let doc t args = BaseDoc.doc (join_plugin_sections (function | Doc (cs, e) -> Some (lookup_plugin_section "documentation" (s_ "build") cs.cs_name t.doc, cs, e) | _ -> None) t.package.sections) t.package args let test t args = BaseTest.test (join_plugin_sections (function | Test (cs, e) -> Some (lookup_plugin_section "test" (s_ "run") cs.cs_name t.test, cs, e) | _ -> None) t.package.sections) t.package args let all t args = let rno_doc = ref false in let rno_test = ref false in let arg_rest = ref [] in Arg.parse_argv ~current:(ref 0) (Array.of_list ((Sys.executable_name^" all") :: (Array.to_list args))) [ "-no-doc", Arg.Set rno_doc, s_ "Don't run doc target"; "-no-test", Arg.Set rno_test, s_ "Don't run test target"; "--", Arg.Rest (fun arg -> arg_rest := arg :: !arg_rest), s_ "All arguments for configure."; ] (failwithf (f_ "Don't know what to do with '%s'")) ""; info "Running configure step"; configure t (Array.of_list (List.rev !arg_rest)); info "Running build step"; build t [||]; (* Load setup.log dynamic variables *) BaseDynVar.init t.package; if not !rno_doc then begin info "Running doc step"; doc t [||]; end else begin info "Skipping doc step" end; if not !rno_test then begin info "Running test step"; test t [||] end else begin info "Skipping test step" end let install t args = BaseCustom.hook t.package.install_custom (t.install t.package) args let uninstall t args = BaseCustom.hook t.package.uninstall_custom (t.uninstall t.package) args let reinstall t args = uninstall t args; install t args let clean, distclean = let failsafe f a = try f a with e -> warning (f_ "Action fail with error: %s") (match e with | Failure msg -> msg | e -> Printexc.to_string e) in let generic_clean t cstm mains docs tests args = BaseCustom.hook ~failsafe:true cstm (fun () -> (* Clean section *) List.iter (function | Test (cs, test) -> let f = try List.assoc cs.cs_name tests with Not_found -> fun _ _ _ -> () in failsafe (f t.package (cs, test)) args | Doc (cs, doc) -> let f = try List.assoc cs.cs_name docs with Not_found -> fun _ _ _ -> () in failsafe (f t.package (cs, doc)) args | Library _ | Object _ | Executable _ | Flag _ | SrcRepo _ -> ()) t.package.sections; (* Clean whole package *) List.iter (fun f -> failsafe (f t.package) args) mains) () in let clean t args = generic_clean t t.package.clean_custom t.clean t.clean_doc t.clean_test args in let distclean t args = (* Call clean *) clean t args; (* Call distclean code *) generic_clean t t.package.distclean_custom t.distclean t.distclean_doc t.distclean_test args; (* Remove generated file *) List.iter (fun fn -> if Sys.file_exists fn then begin info (f_ "Remove '%s'") fn; Sys.remove fn end) (Lazy.force BaseEnv.default_filename :: Lazy.force BaseLog.default_filename :: (List.rev_map BaseFileAB.to_filename t.package.files_ab)) in clean, distclean let version t _ = print_endline t.oasis_version let update_setup_ml, no_update_setup_ml_cli = let b = ref true in b, ("-no-update-setup-ml", Arg.Clear b, s_ " Don't try to update setup.ml, even if _oasis has changed.") let default_oasis_fn = "_oasis" let update_setup_ml t = let oasis_fn = match t.oasis_fn with | Some fn -> fn | None -> default_oasis_fn in let oasis_exec = match t.oasis_exec with | Some fn -> fn | None -> "oasis" in let ocaml = Sys.executable_name in let setup_ml, args = match Array.to_list Sys.argv with | setup_ml :: args -> setup_ml, args | [] -> failwith (s_ "Expecting non-empty command line arguments.") in let ocaml, setup_ml = if Sys.executable_name = Sys.argv.(0) then (* We are not running in standard mode, probably the script * is precompiled. *) "ocaml", "setup.ml" else ocaml, setup_ml in let no_update_setup_ml_cli, _, _ = no_update_setup_ml_cli in let do_update () = let oasis_exec_version = OASISExec.run_read_one_line ~ctxt:!BaseContext.default ~f_exit_code: (function | 0 -> () | 1 -> failwithf (f_ "Executable '%s' is probably an old version \ of oasis (< 0.3.0), please update to version \ v%s.") oasis_exec t.oasis_version | 127 -> failwithf (f_ "Cannot find executable '%s', please install \ oasis v%s.") oasis_exec t.oasis_version | n -> failwithf (f_ "Command '%s version' exited with code %d.") oasis_exec n) oasis_exec ["version"] in if OASISVersion.comparator_apply (OASISVersion.version_of_string oasis_exec_version) (OASISVersion.VGreaterEqual (OASISVersion.version_of_string t.oasis_version)) then begin (* We have a version >= for the executable oasis, proceed with * update. *) (* TODO: delegate this check to 'oasis setup'. *) if Sys.os_type = "Win32" then failwithf (f_ "It is not possible to update the running script \ setup.ml on Windows. Please update setup.ml by \ running '%s'.") (String.concat " " (oasis_exec :: "setup" :: t.oasis_setup_args)) else begin OASISExec.run ~ctxt:!BaseContext.default ~f_exit_code: (function | 0 -> () | n -> failwithf (f_ "Unable to update setup.ml using '%s', \ please fix the problem and retry.") oasis_exec) oasis_exec ("setup" :: t.oasis_setup_args); OASISExec.run ~ctxt:!BaseContext.default ocaml (setup_ml :: args) end end else failwithf (f_ "The version of '%s' (v%s) doesn't match the version of \ oasis used to generate the %s file. Please install at \ least oasis v%s.") oasis_exec oasis_exec_version setup_ml t.oasis_version in if !update_setup_ml then begin try match t.oasis_digest with | Some dgst -> if Sys.file_exists oasis_fn && dgst <> Digest.file default_oasis_fn then begin do_update (); true end else false | None -> false with e -> error (f_ "Error when updating setup.ml. If you want to avoid this error, \ you can bypass the update of %s by running '%s %s %s %s'") setup_ml ocaml setup_ml no_update_setup_ml_cli (String.concat " " args); raise e end else false let setup t = let catch_exn = ref true in try let act_ref = ref (fun _ -> failwithf (f_ "No action defined, run '%s %s -help'") Sys.executable_name Sys.argv.(0)) in let extra_args_ref = ref [] in let allow_empty_env_ref = ref false in let arg_handle ?(allow_empty_env=false) act = Arg.Tuple [ Arg.Rest (fun str -> extra_args_ref := str :: !extra_args_ref); Arg.Unit (fun () -> allow_empty_env_ref := allow_empty_env; act_ref := act); ] in Arg.parse (Arg.align ([ "-configure", arg_handle ~allow_empty_env:true configure, s_ "[options*] Configure the whole build process."; "-build", arg_handle build, s_ "[options*] Build executables and libraries."; "-doc", arg_handle doc, s_ "[options*] Build documents."; "-test", arg_handle test, s_ "[options*] Run tests."; "-all", arg_handle ~allow_empty_env:true all, s_ "[options*] Run configure, build, doc and test targets."; "-install", arg_handle install, s_ "[options*] Install libraries, data, executables \ and documents."; "-uninstall", arg_handle uninstall, s_ "[options*] Uninstall libraries, data, executables \ and documents."; "-reinstall", arg_handle reinstall, s_ "[options*] Uninstall and install libraries, data, \ executables and documents."; "-clean", arg_handle ~allow_empty_env:true clean, s_ "[options*] Clean files generated by a build."; "-distclean", arg_handle ~allow_empty_env:true distclean, s_ "[options*] Clean files generated by a build and configure."; "-version", arg_handle ~allow_empty_env:true version, s_ " Display version of OASIS used to generate this setup.ml."; "-no-catch-exn", Arg.Clear catch_exn, s_ " Don't catch exception, useful for debugging."; ] @ (if t.setup_update then [no_update_setup_ml_cli] else []) @ (BaseContext.args ()))) (failwithf (f_ "Don't know what to do with '%s'")) (s_ "Setup and run build process current package\n"); (* Build initial environment *) load ~allow_empty:!allow_empty_env_ref (); (** Initialize flags *) List.iter (function | Flag (cs, {flag_description = hlp; flag_default = choices}) -> begin let apply ?short_desc () = var_ignore (var_define ~cli:CLIEnable ?short_desc (OASISUtils.varname_of_string cs.cs_name) (fun () -> string_of_bool (var_choose ~name:(Printf.sprintf (f_ "default value of flag %s") cs.cs_name) ~printer:string_of_bool choices))) in match hlp with | Some hlp -> apply ~short_desc:(fun () -> hlp) () | None -> apply () end | _ -> ()) t.package.sections; BaseStandardVar.init t.package; BaseDynVar.init t.package; if t.setup_update && update_setup_ml t then () else !act_ref t (Array.of_list (List.rev !extra_args_ref)) with e when !catch_exn -> error "%s" (Printexc.to_string e); exit 1 end # 5410 "setup.ml" module CustomPlugin = struct (* # 22 "src/plugins/custom/CustomPlugin.ml" *) (** Generate custom configure/build/doc/test/install system @author *) open BaseEnv open OASISGettext open OASISTypes type t = { cmd_main: command_line conditional; cmd_clean: (command_line option) conditional; cmd_distclean: (command_line option) conditional; } let run = BaseCustom.run let main t _ extra_args = let cmd, args = var_choose ~name:(s_ "main command") t.cmd_main in run cmd args extra_args let clean t pkg extra_args = match var_choose t.cmd_clean with | Some (cmd, args) -> run cmd args extra_args | _ -> () let distclean t pkg extra_args = match var_choose t.cmd_distclean with | Some (cmd, args) -> run cmd args extra_args | _ -> () module Build = struct let main t pkg extra_args = main t pkg extra_args; List.iter (fun sct -> let evs = match sct with | Library (cs, bs, lib) when var_choose bs.bs_build -> begin let evs, _ = BaseBuilt.of_library OASISHostPath.of_unix (cs, bs, lib) in evs end | Executable (cs, bs, exec) when var_choose bs.bs_build -> begin let evs, _, _ = BaseBuilt.of_executable OASISHostPath.of_unix (cs, bs, exec) in evs end | _ -> [] in List.iter (fun (bt, bnm, lst) -> BaseBuilt.register bt bnm lst) evs) pkg.sections let clean t pkg extra_args = clean t pkg extra_args; (* TODO: this seems to be pretty generic (at least wrt to ocamlbuild * considering moving this to BaseSetup? *) List.iter (function | Library (cs, _, _) -> BaseBuilt.unregister BaseBuilt.BLib cs.cs_name | Executable (cs, _, _) -> BaseBuilt.unregister BaseBuilt.BExec cs.cs_name; BaseBuilt.unregister BaseBuilt.BExecLib cs.cs_name | _ -> ()) pkg.sections let distclean t pkg extra_args = distclean t pkg extra_args end module Test = struct let main t pkg (cs, test) extra_args = try main t pkg extra_args; 0.0 with Failure s -> BaseMessage.warning (f_ "Test '%s' fails: %s") cs.cs_name s; 1.0 let clean t pkg (cs, test) extra_args = clean t pkg extra_args let distclean t pkg (cs, test) extra_args = distclean t pkg extra_args end module Doc = struct let main t pkg (cs, _) extra_args = main t pkg extra_args; BaseBuilt.register BaseBuilt.BDoc cs.cs_name [] let clean t pkg (cs, _) extra_args = clean t pkg extra_args; BaseBuilt.unregister BaseBuilt.BDoc cs.cs_name let distclean t pkg (cs, _) extra_args = distclean t pkg extra_args end end # 5558 "setup.ml" open OASISTypes;; let setup_t = { BaseSetup.configure = CustomPlugin.main { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("./configure", []))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; build = CustomPlugin.Build.main { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("make", ["build"]))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; test = []; doc = []; install = CustomPlugin.main { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("make", ["install"]))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; uninstall = CustomPlugin.main { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("make", ["uninstall"]))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; clean = [ CustomPlugin.clean { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("./configure", []))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; CustomPlugin.Build.clean { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("make", ["build"]))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; CustomPlugin.clean { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("make", ["install"]))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; CustomPlugin.clean { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("make", ["uninstall"]))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] } ]; clean_test = []; clean_doc = []; distclean = [ CustomPlugin.distclean { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("./configure", []))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; CustomPlugin.Build.distclean { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("make", ["build"]))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; CustomPlugin.distclean { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("make", ["install"]))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] }; CustomPlugin.distclean { CustomPlugin.cmd_main = [(OASISExpr.EBool true, ("make", ["uninstall"]))]; cmd_clean = [(OASISExpr.EBool true, None)]; cmd_distclean = [(OASISExpr.EBool true, None)] } ]; distclean_test = []; distclean_doc = []; package = { oasis_version = "0.4"; ocaml_version = Some (OASISVersion.VGreaterEqual "4.00.0"); findlib_version = None; alpha_features = []; beta_features = []; name = "ocamlnet"; version = "4.1.2"; license = OASISLicense.OtherLicense "http://download.camlcity.org/download/licenses/ocamlnet"; license_file = None; copyrights = []; maintainers = []; authors = ["Gerd Stolpmann et al."]; homepage = Some "http://projects.camlcity.org/projects/ocamlnet"; bugreports = None; synopsis = "Internet protocols and helper data structures"; description = None; tags = []; categories = []; conf_type = (`Configure, "custom", Some "0.4"); conf_custom = { pre_command = [(OASISExpr.EBool true, None)]; post_command = [(OASISExpr.EBool true, Some (("make", ["-s"; "postconf"]))) ] }; build_type = (`Build, "custom", Some "0.4"); build_custom = { pre_command = [(OASISExpr.EBool true, None)]; post_command = [(OASISExpr.EBool true, None)] }; install_type = (`Install, "custom", Some "0.4"); install_custom = { pre_command = [(OASISExpr.EBool true, None)]; post_command = [(OASISExpr.EBool true, None)] }; uninstall_custom = { pre_command = [(OASISExpr.EBool true, None)]; post_command = [(OASISExpr.EBool true, None)] }; clean_custom = { pre_command = [(OASISExpr.EBool true, None)]; post_command = [(OASISExpr.EBool true, None)] }; distclean_custom = { pre_command = [(OASISExpr.EBool true, None)]; post_command = [(OASISExpr.EBool true, None)] }; files_ab = []; sections = [ Flag ({ cs_name = "gtk2"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { flag_description = Some "gtk2: Support for gtk2 event loops"; flag_default = [(OASISExpr.EBool true, false)] }); Flag ({ cs_name = "tcl"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { flag_description = Some "tcl: Support for Tcl/Tk event loops"; flag_default = [(OASISExpr.EBool true, false)] }); Flag ({ cs_name = "zlib"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { flag_description = Some "zlib: Support for compression"; flag_default = [(OASISExpr.EBool true, false)] }); Flag ({ cs_name = "apache"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { flag_description = Some "apache: Build the Apache module"; flag_default = [(OASISExpr.EBool true, false)] }); Flag ({ cs_name = "gnutls"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { flag_description = Some "gnutls: Enable (Gnu) TLS"; flag_default = [(OASISExpr.EBool true, false)] }); Flag ({ cs_name = "gssapi"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { flag_description = Some "gssapi: Enable GSSAPI"; flag_default = [(OASISExpr.EBool true, false)] }); Flag ({ cs_name = "pcre"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { flag_description = Some "pcre: Build netstring-pcre library"; flag_default = [(OASISExpr.EBool true, false)] }); Flag ({ cs_name = "full_pcre"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { flag_description = Some "full_pcre: Use pcre for all regular expressions"; flag_default = [(OASISExpr.EBool true, false)] }); Flag ({ cs_name = "nethttpd"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { flag_description = Some "nethttpd: Build the webserver nethttpd"; flag_default = [(OASISExpr.EBool true, false)] }); Library ({ cs_name = "equeue"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/equeue"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "equeue-gtk2"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [ (OASISExpr.EBool true, false); (OASISExpr.EFlag "gtk2", true) ]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/equeue-gtk2"; bs_compiled_object = Best; bs_build_depends = [FindlibPackage ("lablgtk2", None)]; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "equeue-tcl"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [ (OASISExpr.EBool true, false); (OASISExpr.EFlag "tcl", true) ]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/equeue-tcl"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netcamlbox"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netcamlbox"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netcgi2"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netcgi2"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netcgi2-plex"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netcgi2-plex"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netcgi2-apache"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [ (OASISExpr.EBool true, false); (OASISExpr.EFlag "apache", true) ]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netcgi2-apache"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netclient"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netclient"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netgss-system"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [ (OASISExpr.EBool true, false); (OASISExpr.EFlag "gssapi", true) ]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netgss-system"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "nethttpd"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [ (OASISExpr.EBool true, false); (OASISExpr.EFlag "nethttpd", true) ]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/nethttpd"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netmulticore"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netmulticore"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netplex"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netplex"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netshm"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netshm"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netstring"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netstring"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netstring-pcre"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [ (OASISExpr.EBool true, false); (OASISExpr.EOr (OASISExpr.EFlag "pcre", OASISExpr.EFlag "full_pcre"), true) ]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netstring-pcre"; bs_compiled_object = Best; bs_build_depends = [FindlibPackage ("pcre", None)]; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netsys"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netsys"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "nettls-gnutls"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [ (OASISExpr.EBool true, false); (OASISExpr.EFlag "gnutls", true) ]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netsys-gnutls"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netunidata"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netunidata"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "netzip"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [ (OASISExpr.EBool true, false); (OASISExpr.EFlag "zlib", true) ]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netzip"; bs_compiled_object = Best; bs_build_depends = [FindlibPackage ("zip", None)]; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "rpc"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/rpc"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "rpc-auth-local"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/rpc-auth-local"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "rpc-generator"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/rpc-generator"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "rpc-xti"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [ (OASISExpr.EBool true, false); (OASISExpr.EOr (OASISExpr.ETest ("system", "sunos"), OASISExpr.ETest ("system", "solaris")), true) ]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/rpc-xti"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Library ({ cs_name = "shell"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/shell"; bs_compiled_object = Best; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, { lib_modules = []; lib_pack = false; lib_internal_modules = []; lib_findlib_parent = None; lib_findlib_name = None; lib_findlib_containers = [] }); Executable ({ cs_name = "ocamlrpcgen"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/rpc-generator"; bs_compiled_object = Byte; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, {exec_custom = false; exec_main_is = "main.ml"}); Executable ({ cs_name = "netplex-admin"; cs_data = PropList.Data.create (); cs_plugin_data = [] }, { bs_build = [(OASISExpr.EBool true, true)]; bs_install = [(OASISExpr.EBool true, true)]; bs_path = "src/netplex"; bs_compiled_object = Byte; bs_build_depends = []; bs_build_tools = [ExternalTool "make"]; bs_c_sources = []; bs_data_files = []; bs_ccopt = [(OASISExpr.EBool true, [])]; bs_cclib = [(OASISExpr.EBool true, [])]; bs_dlllib = [(OASISExpr.EBool true, [])]; bs_dllpath = [(OASISExpr.EBool true, [])]; bs_byteopt = [(OASISExpr.EBool true, [])]; bs_nativeopt = [(OASISExpr.EBool true, [])] }, {exec_custom = false; exec_main_is = "netplex_admin.ml"}) ]; plugins = []; disable_oasis_section = []; schema_data = PropList.Data.create (); plugin_data = [] }; oasis_fn = Some "_oasis"; oasis_version = "0.4.6"; oasis_digest = Some "\204K\148\155ut\148\185\208]Q\145\177\129\005."; oasis_exec = None; oasis_setup_args = []; setup_update = false };; let setup () = BaseSetup.setup setup_t;; # 6645 "setup.ml" (* OASIS_STOP *) let () = setup ();; ocamlnet-4.1.2/configure0000755000175000017500000007515212731530350013664 0ustar gerdgerd#! /bin/sh # $Id$ ####################################################################### # Constants: cppo_version=0.9.4 # Helpers: # Split $PATH into words: oldifs="$IFS" IFS=" :" spacepath=`echo $PATH` IFS="$oldifs" in_path () { # Does $1 exist in $PATH? for d in $spacepath; do if test -x "$d/$1"; then return 0 fi done return 1 } get_path () { for d in $spacepath; do if test -x "$d/$1"; then echo "$d/$1" return fi done } ####################################################################### # Defaults #--- Options --- # value 0: off # value 1: on # defaults: set_defaults () { enable_gtk=0 enable_gtk2=0 enable_tcl=0 enable_zip=0 enable_apache=0 enable_gnutls=0 enable_gssapi=0 enable_pcre=0 enable_full_pcre=0 compat_pcre=0 enable_nethttpd=0 bindir=`dirname "$ocamlc"` tcl_defs="" tcl_libs="" disable_core=0 apxs="" apache="" cpp=cpp cpp_set=0 gnutls_cflags="" gnutls_libs="" gnutls_system_trust_file="" gssapi_cflags="" gssapi_libs="" destdir="" } ocamlc=`get_path ocamlc` set_defaults version="4.1.2" exec_suffix="" path_sep=":" ####################################################################### # Option parsing ehelp_gtk="Enable/disable parts that depend on lablgtk" ehelp_gtk2="Enable/disable parts that depend on lablgtk2" ehelp_tcl="Enable/disable parts that depend on tcl/tk" ehelp_gnutls="Enable/disable parts that depend on GnuTLS" ehelp_gssapi="Enable/disable parts that depend on GSSAPI/Kerberos" ehelp_zip="Enable/disable parts that depend on camlzip" ehelp_apache="Enable/disable Apache mod connector (EXPERIMENTAL)" ehelp_pcre="Enable/disable the build against pcre-ocaml" ehelp_full_pcre="Enable/disable the build against pcre-ocaml (no Str)" ehelp_nethttpd="Enable/disable nethttpd web server component (GPL!)" # Which options exist? eoptions for enable/disable eoptions="pcre full_pcre gtk gtk2 tcl gnutls gssapi zip apache nethttpd" # Packages to include anyway: requires="bytes unix" # Directory where to install data files: net_db_dir="" net_db_dir_set=0 check_library () { # $1: the name of the library (findlib) # # $2: a typical file in $incdirs # if [ "$enable_findlib" -gt 0 ]; then ocamlfind query "$1" >/dev/null 2>/dev/null return # else # stdlib=`ocamlc -where` # for dir in $incdirs; do # case "$dir" in # +*) # dir=`echo "$dir" | sed -e "s|^\+|$stdlib/|"` ;; # esac # if [ -f "$dir/$2" ]; then # return 0 # fi # done return 1 # not found # fi } print_options () { for opt in $eoptions; do e="o=\$enable_$opt" eval "$e" uopt=`echo $opt | sed -e 's/_/-/g'` if [ $o -gt 0 ]; then echo " -enable-$uopt" else echo " -disable-$uopt" fi done echo " -bindir $bindir" echo " -datadir $net_db_dir" if [ $enable_tcl -gt 0 ]; then echo " -equeue-tcl-defs \"$tcl_defs\"" echo " -equeue-tcl-libs \"$tcl_libs\"" fi if [ -n "$apxs" ]; then echo " -apxs $apxs" fi if [ -n "$apache" ]; then echo " -apache $apache" fi if [ -n "$gnutls_cflags" ]; then echo " -gnutls-cflags $gnutls_cflags" fi if [ -n "$gnutls_libs" ]; then echo " -gnutls-libs $gnutls_libs" fi if [ -n "$gnutls_system_trust_file" ]; then echo " -gnutls-system-trust-file $gnutls_system_trust_file" fi if [ -n "$gssapi_cflags" ]; then echo " -gssapi-cflags $gssapi_cflags" fi if [ -n "$gssapi_libs" ]; then echo " -gssapi-libs $gssapi_libs" fi echo " -cpp $cpp" } usage () { set_defaults cat <<_EOF_ >&2 usage: ./configure [ options ] _EOF_ for opt in $eoptions; do e="help=\$ehelp_$opt" eval "$e" uopt=`echo $opt | sed -e 's/_/-/g'` echo "-enable-$uopt:" >&2 echo "-disable-$uopt:" >&2 echo " $help" >&2 done cat <<_EOF_ >&2 -bindir dir Install binaries into this directory -datadir dir Install the run-time data file into this directory -equeue-tcl-defs Set C compiler options to find tcl.h (for -enable-tcl) -equeue-tcl-libs Set C compiler options to link against libtcl (for -enable-tcl) -apxs /path/to/apxs Set which apxs to use for -enable-apache -apache /path/to/apache Set which apache executable to use for -enable-apache -gnutls-cflags Flags for the C compiler for GnuTLS -gnutls-libs Libraries for GnuTLS -gnutls-system-trust-file /path/to/certificates.crt File with the certificates that are trusted by default -gssapi-cflags Flags for the C compiler for GSSAPI -gssapi-libs Libraries for GSSAPI -prefer-netcgi2 This option is ignored for compatibility with older versions -cpp Use this C preprocessor program for ocamlrpcgen -compat-pcre Makes the netstring library dependent on netstring-pcre, for better compatibility with old versions of Ocamlnet Defaults are: _EOF_ print_options >&2 exit 1 } check_eopt () { for x in $eoptions; do if [ "$x" = "$1" ]; then return 0 fi done echo "Unknown option: $1" >&2 exit 1 } echo "Welcome to Ocamlnet version $version" >&2 while [ "$#" -gt 0 ]; do case "$1" in -enable-*|--enable-*) opt=`echo "$1" | sed -e 's/--\{0,1\}enable-//' -e 's/-/_/g'` check_eopt "$opt" eval "enable_$opt=2" shift ;; -disable-core|--disable-core) # Intentionally undocumented. disable_core=1 shift ;; -disable-*|--disable-*) opt=`echo "$1" | sed -e 's/--\{0,1\}disable-//' -e 's/-/_/g'` check_eopt "$opt" eval "enable_$opt=-1" shift ;; -with-*|--with*) opt=`echo "$1" | sed -e 's/--\{0,1\}with-//' -e 's/-/_/g'` check_eopt "$opt" eval "enable_$opt=2" shift ;; -without-*|--without*) opt=`echo "$1" | sed -e 's/--\{0,1\}without-//' -e 's/-/_/g'` check_eopt "$opt" eval "enable_$opt=-1" shift ;; -prefix|--prefix) bindir="$2/bin"; shift 2 ;; --prefix=*) p=`echo "$1" | set -e 's/--prefix=//'` bindir="$p/bin"; shift ;; -bindir|--bindir) bindir="$2" shift shift ;; --bindir=*) bindir=`echo "$1" | set -e 's/--bindir=//'` shift ;; -datadir|--datadir) net_db_dir="$2" net_db_dir_set=1 shift; shift ;; --datadir=*) net_db_dir=`echo "$1" | set -e 's/--datadir=//'` net_db_dir_set=1 shift ;; -equeue-tcl-defs|--equeue-tcl-defs) tcl_defs="$tcl_defs $2" shift shift ;; --equeue-tcl-defs=*) tcl_defs=`echo "$1" | set -e 's/--equeue-tcl-defs=//'`" $2" shift ;; -equeue-tcl-libs|--equeue-tcl-libs) tcl_libs="$tcl_libs $2" shift shift ;; --equeue-tcl-libs=*) tcl_libs=`echo "$1" | set -e 's/--equeue-tcl-libs=//'`" $2" shift ;; -apxs|--apxs) apxs="$2" shift shift ;; --apxs=*) apxs=`echo "$1" | set -e 's/--apxs=//'` shift ;; -apache|--apache) apache="$2" shift shift ;; --apache=*) apache=`echo "$1" | set -e 's/--apache=//'` shift ;; -gnutls-cflags|--gnutls-cflags) gnutls_cflags="$2" shift shift ;; --gnutls-cflags=*) gnutls_cflags=`echo "$1" | set -e 's/--gnutls-cflags=//'` shift ;; -gnutls-libs|--gnutls-libs) gnutls_libs="$2" shift shift ;; --gnutls-libs=*) gnutls_libs=`echo "$1" | set -e 's/--gnutls-libs=//'` shift ;; -gnutls-system-trust-file|--gnutls-system-trust-file) gnutls_system_trust_file="$2" shift 2 ;; --gnutls-system-trust-file=*) gnutls_system_trust_file=`echo "$1" | set -e 's/--gnutls-system-trust-file=//'` shift ;; -gssapi-cflags|--gssapi-cflags) gssapi_cflags="$2" shift shift ;; --gssapi-cflags=*) gssapi_cflags=`echo "$1" | set -e 's/--gssapi-cflags=//'` shift ;; -gssapi-libs|--gssapi-libs) gssapi_libs="$2" shift shift ;; --gssapi-libs=*) gssapi_libs=`echo "$1" | set -e 's/--gssapi-libs=//'` shift ;; -prefer-netcgi2|--prefer-netcgi2) # ignore! shift ;; -cpp|--cpp) cpp="$2" cpp_set=1 shift shift ;; --cpp=*) cpp=`echo "$1" | set -e 's/--cpp=//'` cpp_set=1 shift ;; -version|--version) echo "$version" exit 0 ;; -compat-pcre|--compat-pcre) compat_pcre=1 shift ;; -destdir|--destdir) destdir="$2"; shift 2;; --destdir=*) destdir=`echo "$1" | set -e 's/--destdir=//'`; shift;; *) usage esac done ###################################################################### # cleanup rm -f config.cppo ###################################################################### # Check OS with_rpc_xti=0 with_cppo_tweak=0 printf "%s" "Checking operating system... " u=`uname` case "$u" in CYGWIN*) printf "Cygwin, and target is: " exec_suffix=".exe" path_sep=";" # this is only for OCAMLPATH, ";" is correct for Cygwin case `ocamlc -config | grep os_type` in *Win32*) with_cppo_tweak=1 if [ $cpp_set = 0 ]; then cpp=`realpath /bin/cpp | cygpath -m -f -` fi echo "Win32" ;; *) echo "Cygwin" ;; esac ;; MINGW*) echo "MinGW" exec_suffix=".exe" with_cppo_tweak=2 path_sep=";" mingw_lib=`get_path gcc` mingw_lib=`dirname "$mingw_lib"`/../lib OCAMLOPTFLAGS="-ccopt -L\"${mingw_lib}\"" ;; Linux) echo "Linux" ;; *FreeBSD) # also GNU/kFreeBSD echo "FreeBSD" echo echo "*** Note that you might need to load the 'sem' kernel" echo "*** module to make semaphores work: kldload sem" echo ;; NetBSD) echo "NetBSD" ;; SunOS) case `uname -r` in [1234]*) echo "SunOS" ;; *) echo "Solaris" with_rpc_xti=1 ;; esac ;; *) echo "Generic" ;; esac if [ $with_rpc_xti -gt 0 ]; then echo " This OS supports XTI networking" echo " Building rpc-xti" fi ###################################################################### # Check ocamlfind printf "%s" "Checking for findlib... " if ocamlfind query stdlib >/dev/null 2>/dev/null; then echo "found" if [ "$net_db_dir_set" -eq 0 ]; then net_db_dir=`ocamlfind printconf destdir | tr -d '\\r'`/netunidata net_db_dir_set=1 fi else echo "not found" echo "Make sure that ocamlfind is in your PATH, or download findlib" echo "from www.ocaml-programming.de" exit 1 fi if [ "$net_db_dir_set" -eq 0 ]; then net_db_dir="$libdir" net_db_dir_set=1 fi ###################################################################### # Does ocamlopt support multi-threading? printf "%s" "Checking multi-threading support... " mt_type=vm mt_switch="-vmthread" mt_comment="(unsupported)" rm -rf tmp mkdir -p tmp cat <<_EOF_ >tmp/t.ml let _ = Mutex.create();; _EOF_ if ocamlopt -thread -o tmp/t${exec_suffix} ${OCAMLOPTFLAGS} unix.cmxa threads.cmxa tmp/t.ml 2>/dev/null || ocamlc -thread -o tmp/t${exec_suffix} unix.cma threads.cma tmp/t.ml 2>/dev/null; then if tmp/t${exec_suffix} 2>/dev/null; then mt_type=posix mt_switch="-thread" mt_comment="(ok)" fi fi echo "$mt_type $mt_comment" ###################################################################### # Check word size at al printf "%s" "Checking word size... " cat <<_EOF_ >tmp/t.ml print_endline(string_of_int(Sys.word_size)) _EOF_ word_size="$(ocaml tmp/t.ml | tr -d '\r')" echo "$word_size bit" printf "%s" "Checking endianess... " cat <<_EOF_ >tmp/tend.c /* new check from Matías Giovannini */ #include "caml/mlvalues.h" value check(value d) { int i = 1; char *s = (char*) &i; return (s[0] == 0 ? Val_true : Val_false); } _EOF_ cat <<_EOF_ >tmp/t.ml external check : unit -> bool = "check";; let () = exit (if check() then 0 else 1) _EOF_ ( cd tmp ocamlc -custom -o t tend.c t.ml ) || exit if tmp/t; then echo "big" endianess="BIG_ENDIAN" else echo "little" endianess="LITTLE_ENDIAN" fi ###################################################################### printf "Checking for GPROF... " stdlib=`ocamlc -where | tr -d '\r'` if [ -f $stdlib/std_exit.p.cmx ]; then echo "found" have_gprof=1 else echo "not found" have_gprof=0 fi ###################################################################### printf "Checking for attributes... " case `ocamlc -version` in [123].*) echo "no" attrs=0 ;; 4.0[01].*) echo "no" attrs=0 ;; *) echo "yes" attrs=1 ;; esac if [ $attrs -gt 0 ]; then cat <>config.cppo #define DEPRECATED(arg) [@@deprecated arg] \(** @deprecated arg *) EOF else cat <>config.cppo #define DEPRECATED(arg) EOF fi ###################################################################### printf "Checking for immutable strings... " if ocamlc -safe-string >/dev/null 2>/dev/null; then istring=1 echo "yes" else istring=0 echo "no" fi if [ $istring -gt 0 ]; then string_opts="-safe-string" pp_bytes="-D HAVE_BYTES" else string_opts="" pp_bytes="-U HAVE_BYTES" fi ###################################################################### printf "Checking for extensible variants... " cat <tmp/extvariant.ml type t = .. type t += X EOF if ocamlc -c tmp/extvariant.ml >/dev/null 2>/dev/null; then echo "yes" echo "#define HAVE_EXTENSIBLE_VARIANTS" >> config.cppo else echo "no" echo "#undef HAVE_EXTENSIBLE_VARIANTS" >> config.cppo fi ###################################################################### # Check that pcre is available: if [ $enable_pcre -gt 0 -o $enable_full_pcre -gt 0 ]; then printf "%s" "Checking for PCRE... " if check_library pcre pcre.cmi; then echo "found" # This means to build netstring-pcre have_pcre=1 if [ $enable_full_pcre -gt 0 ]; then # In netstring: Netstring_str uses PCRE as backend regexp_defs="-D HAVE_PCRE" regexp_provider="netstring-pcre" # which again depends on pcre regexp_provider_make="pcre" # also solved via -I to netstring-pcre else # In netstring: Netstring_str uses Str as backend regexp_defs="-D ENABLE_STR_EXTERNALS -D HAVE_PCRE" regexp_provider="str" regexp_provider_make="str" fi else echo "not found" echo "Sorry, PCRE was requested." echo "Get the PCRE-OCaml library from:" echo "http://www.ocaml.info/home/ocaml_sources.html," echo "or disable the build against PCRE-Ocaml (not recommended)". exit 1 fi else # ENABLE_STR_EXTERNALS works for all recent OCaml versions have_pcre=0 regexp_defs="-D ENABLE_STR_EXTERNALS" regexp_provider="str" regexp_provider_make="str" fi compat_pcre_provider="" if [ $compat_pcre -gt 0 ]; then # in this case, netstring is dependent on netstring-pcre for # better compatibility with OCamlnet-3.5 and older. Even if we # did NOT -enable-pcre. compat_pcre_provider="netstring-pcre" fi ###################################################################### # Netsys ( cd src/netsys; ./configure ) ( cd src/rpc-auth-local; ./configure ) ###################################################################### # whether we can support camlboxes and multicore support_outofheap=0 if grep 'OOH_OBJECT = .' src/netsys/Makefile.conf >/dev/null 2>/dev/null; then support_outofheap=1 fi support_semaphores=0 if grep '#define HAVE_POSIX_SEM_NAMED' src/netsys/config.h \ >/dev/null 2>/dev/null; then support_semaphores=1 fi enable_camlbox=0 enable_multicore=0 printf "Checking whether netcamlbox and netmulticore are supported... " if [ $support_outofheap -gt 0 -a $support_semaphores -gt 0 ]; then echo "yes" enable_camlbox=1 enable_multicore=1 else echo "no" fi ###################################################################### # TCL with_equeue_tcl=0 if [ $enable_tcl -gt 0 ]; then printf "%s" "Checking switches for tcl.h... " tcl_defs_1="" for d in $tcl_defs; do tcl_defs_1="$tcl_defs_1 -ccopt '$d'" done rm -rf tmp mkdir -p tmp cat <tmp/t.c #include "tcl.h" main () { } EOF if ( cd tmp; ocamlc $tcl_defs_1 -c t.c >/dev/null 2>/dev/null ) then echo "ok" else echo "not ok" echo echo "Please check -equeue-tcl-defs!" exit 1 fi printf "%s" "Checking switches to link libtcl... " cat <tmp/t.c #include #include #include "tcl.h" do_something () { void (*x)(int); x = Tcl_Exit; exit(0); } EOF cat <tmp/t.ml exit 0 EOF if ( cd tmp ocamlc $tcl_defs_1 -c t.c >/dev/null 2>/dev/null && ocamlc -c t.ml >/dev/null 2>/dev/null && ocamlc -o t -custom t.o t.cmo -cclib "$tcl_libs" ) then if tmp/t; then echo "ok" else echo "not ok (check ldd output of tmp/t)" echo echo "Please check -equeue-tcl-libs!" exit 1 fi else echo "not ok" echo echo "Please check -equeue-tcl-libs!" exit 1 fi with_equeue_tcl=1 fi ###################################################################### # Check lablgtk with_equeue_gtk1=0 if [ $enable_gtk -gt 0 ]; then printf "%s" "Checking for lablgtk... " if ocamlfind query lablgtk >/dev/null 2>/dev/null; then echo "found" with_equeue_gtk1=1 else echo "not found" echo "Required library lablgtk not found!" exit 1 fi fi ###################################################################### # Check lablgtk2 with_equeue_gtk2=0 gtk2_io_add_watch_supports_lists="" if [ $enable_gtk2 -gt 0 ]; then printf "%s" "Checking for lablgtk2... " if ocamlfind query lablgtk2 >/dev/null 2>/dev/null; then echo "found" else echo "not found" echo "Required library lablgtk2 not found!" exit 1 fi printf "%s" "Checking whether lablgtk2 has GMain.Io.remove... " mkdir -p tmp cat <tmp/gtktest.ml let _ = GMain.Io.remove;; EOF if ocamlfind ocamlc -package lablgtk2 -c tmp/gtktest.ml >/dev/null 2>/dev/null; then echo "yes" else echo "no" echo "Your version of lablgtk2 is too old!" exit 1 fi printf "%s" "Checking whether lablgtk2 has GMain.Io.add_watch with list support... " mkdir -p tmp cat <<'EOF' >tmp/gtktest.ml open GMain.Io let _ = (add_watch : cond:condition list -> callback:(condition list -> bool) -> ?prio:int -> channel -> id);; exit 0 EOF # Note: this newer API is never broken in the sense checked below, i.e. # such lablgtk2 versions do not exist. if ocamlfind ocamlc -package unix,lablgtk2 -linkpkg -o tmp/gtk tmp/gtktest.ml >/dev/null 2>/dev/null && tmp/gtk; then echo "yes" gtk2_io_add_watch_supports_lists="-D GTK2_IO_ADD_WATCH_SUPPORTS_LISTS" else echo "no" printf "%s" "Checking whether lablgtk2's GMain.Io.add_watch is broken... " mkdir -p tmp cat <<'EOF' >tmp/gtktest.ml GMain.Main.init();; let ch = GMain.Io.channel_of_descr (Unix.stdout) in let w = GMain.Io.add_watch ~cond:`OUT ~callback:(fun () -> true) ch in (* add_watch is broken when it just returns Val_unit, and ok when it * returns a positive int *) if (Obj.magic w : int) > 0 then exit 0 else exit 1 EOF if ocamlfind ocamlc -package unix,lablgtk2 -linkpkg -o tmp/gtk tmp/gtktest.ml >/dev/null 2>/dev/null && tmp/gtk; then echo "no" else echo "yes" echo "You should apply the patch-ab-ml_glib.c to lablgtk2 to fix this!" exit 1 fi fi for f in Makefile uq_gtk.ml uq_gtk.mli uq_gtk_helper.ml; do rm -f src/equeue-gtk2/$f ln -s ../equeue-gtk1/$f src/equeue-gtk2 done with_equeue_gtk2=1 fi ###################################################################### # GnuTLS with_gnutls=0 if [ $enable_gnutls -gt 0 ]; then ( cd src/nettls-gnutls GNUTLS_CFLAGS="$gnutls_cflags" GNUTLS_LIBS="$gnutls_libs" GNUTLS_SYSTEM_TRUST_FILE="$gnutls_system_trust_file" ./configure ) if [ $? -eq 0 ]; then with_gnutls=1 # There is now also src/nettls-gnutls/config.mk, which needs to be # appended to Makefile.conf else echo "Required library GnuTLS not found!" exit 1 fi fi ###################################################################### # GSSAPI with_gssapi=0 if [ $enable_gssapi -gt 0 ]; then ( cd src/netgss-system GSSAPI_CFLAGS="$gssapi_cflags" GSSAPI_LIBS="$gssapi_libs" ./configure ) if [ $? -eq 0 ]; then with_gssapi=1 # There is now also src/netgss-system/config.mk, which needs to be # appended to Makefile.conf else echo "Required library for GSSAPI (probably -lkrb5) not found!" exit 1 fi fi ###################################################################### # Check camlzip with_netzip=0 if [ $enable_zip -gt 0 ]; then printf "%s" "Checking for zip/camlzip... " if ocamlfind query zip >/dev/null 2>/dev/null; then echo "found" with_netzip=1 zip_provider=zip else if ocamlfind query camlzip >/dev/null 2>/dev/null; then echo "found" with_netzip=1 zip_provider=camlzip else echo "not found" echo "Required library camlzip not found!" exit 1 fi fi fi ###################################################################### # Check Apache apache_major=0 # otherwise syntax error if [ $enable_apache -gt 0 ]; then printf "Apache mod connector... " # echo "CURRENTLY BROKEN - disabling for now" # enable_apache=0 if [ -z "$apxs" ]; then # guess apxs=`get_path apxs` fi if [ -z "$apache" ]; then # guess apache=`get_path apache` fi if [ -x "$apxs" ] && [ -x "$apache" ]; then apache_major=`$apache -v | head -n1 | sed -e "s,.*/\([1-9]\).*,\1,"` apache_libdir="`$apxs -q LIBEXECDIR`" apache_incdir="`$apxs -q INCLUDEDIR`" apache_confdir="`$apxs -q SYSCONFDIR`" apache_ldflags_shlib="`$apxs -q LDFLAGS_SHLIB`" apache_cc="`$apxs -q CC`" apache_cflags="-I \$(APACHE_INCDIR) \ `$apxs -q CFLAGS` `$apxs -q CFLAGS_SHLIB`" # This is to allow modules residing in the standard ocaml library # directory to be loaded with relative paths. #apache_ocamllibdir=`ocamlfind printconf destdir` apache_ocamllibdir=`ocamlc -where` # The apache module requires the construction of a shared library # embedding the ocaml runtime. On platforms where PIC code differs # from non-PIC, it requires a shared camlrun. Check whether it is # available. See http://caml.inria.fr/mantis/view.php?id=3866 apache_camlrun=camlrun if [ -f "$apache_ocamllibdir/libcamlrun_shared.so" ]; then apache_camlrun=camlrun_shared echo "enabled (Apache $apache_major)" else echo "enabled (Apache $apache_major)" echo -e " WARNING: libcamlrun_shared.so was not found. That \ may prevent the build\n of the apache module on platforms \ where PIC code differs from non-PIC\n such as x86_64, hppa,..." fi # at some point libstr.a was renamed to libcamlstr.a libstr="str" if [ -f "$apache_ocamllibdir/libcamlstr.a" ]; then libstr="camlstr" fi else enable_apache=0 echo "apxs or apache not found" echo " Maybe you need to use the -apache option?" exit 1 fi fi ###################################################################### # cpp echo "Preprocessor for ocamlrpcgen: $cpp" ###################################################################### # Summary echo echo "Effective options:" print_options echo pkglist="netsys netshm netstring netunidata equeue shell rpc-generator rpc rpc-auth-local netclient netcgi2 netplex netcgi2-plex" full_pkglist="$pkglist netstring-pcre rpc-auth-local rpc-xti equeue-tcl equeue-gtk1 equeue-gtk2 nethttpd netzip netcgi2-apache nettls-gnutls netgss-system" if [ $enable_camlbox -gt 0 ]; then pkglist="$pkglist netcamlbox" fi if [ $enable_multicore -gt 0 ]; then pkglist="$pkglist netmulticore" fi if [ $enable_nethttpd -gt 0 ]; then pkglist="$pkglist nethttpd" fi if [ $disable_core -gt 0 ]; then # Omit the core packages: pkglist="" with_rpc_xti=0 fi for opt in rpc_xti $woptions equeue_tcl equeue_gtk1 equeue_gtk2 netzip; do e="o=\$with_$opt" eval "$e" if [ $o -gt 0 ]; then uopt=`echo "$opt" | sed -e 's/_/-/g'` pkglist="$pkglist $uopt" fi done if [ $enable_pcre -gt 0 -o $enable_full_pcre -gt 0 ]; then pkglist="netstring-pcre $pkglist" fi if [ $enable_apache -gt 0 ]; then pkglist="$pkglist netcgi2-apache" fi if [ $enable_gnutls -gt 0 ]; then pkglist="$pkglist nettls-gnutls" fi if [ $enable_gssapi -gt 0 ]; then pkglist="$pkglist netgss-system" fi ###################################################################### # Write Makefile.conf if [ $with_cppo_tweak -ne 0 ]; then # Under Windows, calling cppo by relative path is difficult. If we # use forward slashes, we need to escape these for cmd.exe. If we # use backward slashes, the escaping is difficult for sh+make. # The workaround is to call cppo implicitly by PATH search. xdir="$(readlink -f "$(dirname "$0")")" if [ $with_cppo_tweak -eq 1 ]; then xdir="$(cygpath "${xdir}")" fi xdir="${xdir}/tools/cppo-${cppo_version}" export_path="export PATH:=${xdir}:\$(PATH)" cppo="cppo-ocamlnet.exe" else export_path="" cppo="\$(TOP_DIR)/tools/cppo-${cppo_version}/cppo" fi echo "Writing Makefile.conf" cat <<_EOF_ >Makefile.conf # Makefike.conf written by configure # The Ocamlnet version VERSION = $version # The packages to build in the right order: PKGLIST = $pkglist # All packages: FULL_PKGLIST = $full_pkglist # Whether the OS needs an .exe suffix for executables: EXEC_SUFFIX = $exec_suffix PATH_SEP = $path_sep # Required packages (findlib): REQUIRES += $requires # zip: ZIP_PROVIDER = $zip_provider # Additional options only for ocamlc: OCAMLC_OPTIONS = # Additional options only for ocamlopt: OCAMLOPT_OPTIONS = # Where the ocamlnet lookup tables are to be installed (both findlib # and non-findlib): NET_DB_DIR = $net_db_dir # Where binaries are installed: BINDIR = $bindir # Method of installation: INSTMETHOD = findlib # Multi-threading type: MT_TYPE = $mt_type # word size: WORD_SIZE = $word_size # endianess ENDIANESS = $endianess # gprof: HAVE_GPROF = $have_gprof # definition of the DEPRECATED macro PP_DEPRECATED = # strings STRING_OPTS = $string_opts PP_BYTES = $pp_bytes # REGEXP support: REGEXP_DEFS = $regexp_defs HAVE_PCRE = $have_pcre REGEXP_PROVIDER = $regexp_provider REGEXP_PROVIDER_MAKE = $regexp_provider_make COMPAT_PCRE_PROVIDER = $compat_pcre_provider # Compiler switch to enable multi-threading: THREAD = $mt_switch # For -enable-tcl: EQUEUE_TCL_DEFS = $tcl_defs_1 EQUEUE_TCL_LIBS = $tcl_libs # For -enable-gtk2: GTK_EXTRA_DEFINES = $gtk2_io_add_watch_supports_lists # For -enable-apache APACHE_MAJOR = $apache_major APACHE_LIBDIR = $apache_libdir APACHE_OCAMLLIBS = -l$apache_camlrun -ltermcap -lunix -l$libstr APACHE_INCDIR = $apache_incdir APACHE_CONFDIR = $apache_confdir APACHE_LDFLAGS_SHLIB = $apache_ldflags_shlib APACHE_CC = $apache_cc APACHE_CFLAGS = $apache_cflags APACHE_OCAMLLIBDIR = $apache_ocamllibdir APXS = $apxs # ocamlrpcgen OCAMLRPCGEN_CPP = $cpp # cppo: CPPO = $cppo -include \$(TOP_DIR)/config.cppo CPPO_VERSION = $cppo_version $export_path _EOF_ if [ $with_gnutls -gt 0 ]; then cat src/nettls-gnutls/config.mk >>Makefile.conf fi if [ $with_gssapi -gt 0 ]; then cat src/netgss-system/config.mk >>Makefile.conf fi if [ -n "$destdir" ]; then echo "DESTDIR = $destdir" >>Makefile.conf fi rm -f src/netcgi2-apache/config.h ###################################################################### # make oasis happy: setup.save will be picked up by "make postconf" # and will be appended to setup.data. That way the config update # will reach oasis. rm -f setup.save echo "pkg_version=\"$version\"" >>setup.save echo "bindir= \"$bindir\"" >>setup.save echo "datadir=\"$net_db_dir\"" >>setup.save echo "prefix=\"\"" >>setup.save echo "destdir=\"$destdir\"" >>setup.save for opt in $eoptions; do e="o=\$enable_$opt" eval "$e" if [ $o -gt 0 ]; then echo "$opt=\"true\"" >>setup.save else echo "$opt=\"false\"" >>setup.save fi done ###################################################################### # Finish echo echo "Please check Makefile.conf." echo echo "You can now compile Ocamlnet by invoking" echo " make all" echo "for the bytecode compiler, and optionally by invoking" echo " make opt" echo "for the native-code compiler (if supported on your architecture)." echo "Finally, a" echo " make install" echo "will install the package(s)." ocamlnet-4.1.2/doc/0000755000175000017500000000000012731530351012511 5ustar gerdgerdocamlnet-4.1.2/doc/html-main/0000755000175000017500000000000012731530354014402 5ustar gerdgerdocamlnet-4.1.2/doc/html-main/type_Netunichar.html0000644000175000017500000004142012731530351020427 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netunichar sig
  val to_lower : int -> int
  val to_upper : int -> int
  val to_title : int -> int
end
ocamlnet-4.1.2/doc/html-main/Netmech_digest_http.Make_digest.html0000644000175000017500000007310412731530351023466 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http.Make_digest

Functor Netmech_digest_http.Make_digest

module Make_digest: 
Create a custom version of the digest mechanism
Parameters:
P : PROFILE

val mechanism_name : string
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
val restart_supported : bool
Whether the mechanism supports quick restarts (re-authentication)
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

The password is encoded in UTF-8. However, note that not all protocols are able to transmit all of UTF-8. If a non-transmittable character is found, the authentication will fail.

The password can have parameters:

  • "realm": the password is only applicable to this realm. The realm parameter should only occur once.
  • "domain-uri": the password is only applicable to this URI space. The URI must include the protocol scheme, the host name, and "/" as path. The port number is optional. Example: "http://localhost/". The domain-uri parameter can occur several times.

val client_match : params:(string * string * bool) list ->
Nethttp.Header.auth_challenge -> Nethttp.match_result
Checks whether this mechanism can accept the initial authentication challenge (i.e. the first challenge sent from the server to the client. The params are as for create_client_session. On success, returns `Accept(realm,id_opt). On failure, returns `Reject. This function usually does not raise exceptions.

If the mechanism does not support the notion of realms, a dummy realm should be returned.

The id_opt is the session ID (if supported). Session IDs can be used to bind reauthentications to the original session.

The challenge is from a www-authenticate or a proxy-authenticate header.

There is also the result `Reroute(realm, trans_id), meaning that the request would be acceptable if it came over the transport identified by trans_id. `Accept_reroute is the combination of accepting and rerouting, i.e. the auth protocol can start, but the second request should go over the other transport. Both `Reroute and `Accept_reroute are only allowed for initial challenges.

type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user. The credentials are creds.

user must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

Available parameters:

  • "realm"
  • "id" (if client_match returns a session ID)
  • "trans_id": the Nethttp_client.transport_layer_id of the current HTTP request
  • "conn_id": an identifier for the TCP connection
  • "https": is set to "true" if the current connection is TLS-secured
  • "target-host": the hostname from the HTTP request
  • "target-uri": the URL from the HTTP request

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : params:(string * string * bool) list ->
client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK. After the restart the session will be in state `Emit.

The params are the same as for create_client_session, but updated where needed.

val client_process_challenge : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
Nethttp.Header.auth_challenge -> client_session
client_process_challenge cs method uri header challenge:

Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.

method is the request method. uri is the request URI

val client_emit_response : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
client_session *
Nethttp.Header.auth_credentials * (string * string) list
let (creds,new_headers) = client_emit_response cs method uri header:

Emit a new response as a pair (creds,new_headers). The state must be `Emit. The creds either go into the authorization or proxy-authorization header. The new_headers are additional headers to modify.

val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_domain : client_session -> string list
After successful authentication, this function may return the URIs defining the authentication space.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. Commonly supported keys:
  • "realm"
  • "domain-uri"

val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Returns the GSSAPI props if available, or raise Not_found
ocamlnet-4.1.2/doc/html-main/type_Netencoding.QuotedPrintable.html0000644000175000017500000004630012731530351023667 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.QuotedPrintable sig
  val encode : ?crlf:bool -> ?pos:int -> ?len:int -> string -> string
  val encode_tstring :
    ?crlf:bool -> ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
  val encode_poly :
    ?crlf:bool ->
    ?pos:int -> ?len:int -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
  val decode : ?pos:int -> ?len:int -> string -> string
  val decode_tstring :
    ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
  val decode_poly :
    ?pos:int -> ?len:int -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
  class encoding_pipe : ?crlf:bool -> unit -> Netchannels.pipe
  class decoding_pipe : unit -> Netchannels.pipe
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.post_raw.html0000644000175000017500000004076512731530351023163 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.post_raw string -> string -> Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Uq_engines.output_engine-c.html0000644000175000017500000004475312731530351022503 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.output_engine

Class Uq_engines.output_engine

class ['a] output_engine : (Unix.file_descr -> 'a) -> Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
Generic output engine for writing to a file descriptor: let e = new output_engine f fd tmo - Waits until the file descriptor becomes writable, and calls then let x = f fd to write to the descriptor. The result x is the result of the engine.

If the file descriptor does not become writable within tmo seconds, the resulting engine transitions to `Error Timeout.

Use this class to construct engines writing via Unix.single_write or comparable I/O functions:

      let write_engine fd s tmo esys =
        new output_engine (fun fd ->
                             Unix.single_write fd s 0 (String.length s)
                          )
                          fd tmo esys
      

This engine returns the number of written bytes.

See also Uq_io.output_e for a more generic way of writing with engines.


ocamlnet-4.1.2/doc/html-main/type_Netpop.Debug.html0000644000175000017500000004077712731530351020637 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpop.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netgss.System.html0000644000175000017500000004063012731530351021057 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgss.System Netsys_gssapi.GSSAPIocamlnet-4.1.2/doc/html-main/Uq_multiplex.html0000644000175000017500000005630612731530351017767 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_multiplex

Module Uq_multiplex

module Uq_multiplex: sig .. end

Multiplex Controllers



class type multiplex_controller = object .. end
A multiplex_controller is a quite low-level device to abstract bidirectional socket connections.
class type datagram_multiplex_controller = object .. end
Additional methods for unconnected datagram handling
exception Mem_not_supported
May be raised by multiplex controller methods start_mem_reading and start_mem_writing if these methods are not supported for the kind of file descriptor
val create_multiplex_controller_for_connected_socket : ?close_inactive_descr:bool ->
?preclose:(unit -> unit) ->
?supports_half_open_connection:bool ->
?timeout:float * exn ->
Unix.file_descr ->
Unixqueue.unix_event_system -> multiplex_controller
Creates a multiplex controller for a bidirectional socket (e.g. a TCP socket). It is essential that the socket is in connected state. This function also supports Win32 named pipes.

Note that the file descriptor is not closed when the attached engines are terminated. One can call inactivate manually to do that.

close_inactive_descr: Whether inactivate closes the descriptor. True by default.

preclose: This function is called just before the descriptor is closed.

supports_half_open_connection: This implementation does not know how to find out whether the socket supports half-open connections. You can simply set this boolean because of this. Defaults to false. You can set it to true for TCP connections and for Unix-domain connections with stream semantics.

timeout: If set to (t, x), a general timeout of t is set. When an operation has been started, and there is no I/O activity within t seconds, neither by the started operation nor by another operation, the connection times out. In this case, the operation returns the exception x.

val create_multiplex_controller_for_datagram_socket : ?close_inactive_descr:bool ->
?preclose:(unit -> unit) ->
?timeout:float * exn ->
Unix.file_descr ->
Unixqueue.unix_event_system -> datagram_multiplex_controller
Creates a multiplex controller for datagram sockets (e.g. UDP socket).

Note that the file descriptor is not closed when the attached engines are terminated. One can call inactivate manually to do that.

close_inactive_descr: Whether inactivate closes the descriptor. True by default.

preclose: This function is called just before the descriptor is closed.

timeout: If set to (t, x), a general timeout of t is set. When an operation has been started, and there is no I/O activity within t seconds, neither by the started operation nor by another operation, the connection times out. In this case, the operation returns the exception x.

val tls_multiplex_controller : ?resume:string ->
?on_handshake:(multiplex_controller -> unit) ->
role:[ `Client | `Server ] ->
peer_name:string option ->
(module Netsys_crypto_types.TLS_CONFIG) ->
multiplex_controller -> multiplex_controller
Creates a new multiplex controller on top of an existing controller, and configures the new controller for running the TLS protocol.

resume: The endpoint resumes an old session whose data are passed here. This is only possible for client endpoints.

on_handshake: called back when the handshake is done

val restore_tls_multiplex_controller : ?on_handshake:(multiplex_controller -> unit) ->
exn ->
(module Netsys_crypto_types.TLS_CONFIG) ->
multiplex_controller -> multiplex_controller
Like tls_multiplex_controller, but this function does not create a new TLS endpoint. Instead the exn value is assumed to be a stashed old endpoint.
ocamlnet-4.1.2/doc/html-main/type_Netplex_workload.html0000644000175000017500000004547112731530351021662 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_workload sig
  val create_constant_workload_manager :
    ?restart:bool ->
    ?greedy_accepts:bool ->
    ?max_jobs_per_thread:int -> int -> Netplex_types.workload_manager
  val constant_workload_manager_factory :
    Netplex_types.workload_manager_factory
  class type dynamic_workload_config =
    object
      method greedy_accepts : bool
      method inactivity_timeout : int
      method max_free_job_capacity : int
      method max_jobs_per_thread : int
      method max_threads : int
      method min_free_job_capacity : int
      method recommended_jobs_per_thread : int
    end
  val create_dynamic_workload_manager :
    Netplex_workload.dynamic_workload_config ->
    Netplex_types.workload_manager
  val dynamic_workload_manager_factory :
    Netplex_types.workload_manager_factory
  val workload_manager_factories :
    Netplex_types.workload_manager_factory list
end
ocamlnet-4.1.2/doc/html-main/Regexp.html0000644000175000017500000005442212731530351016526 0ustar gerdgerd Ocamlnet 4 Reference Manual : Regexp

Regexp


Regular Expression Backends

Unfortunately, there is a bit of confusion about the regular expression backend used by Ocamlnet. Traditionally, this was always PCRE, and not the Str library coming with the OCaml distribution. The reason was that Str did not have a thread-safe API, but it was required to make Ocamlnet thread-safe.

However, recent OCaml releases ship with a version of Str that can be easily made thread-safe. Because of this, the default regexp backend is now Str, with an option to use PCRE instead.

Current Solution

So we have now by default:

  • Library netstring, module Netstring_str: This is a thread-safe API around Str. All uses of regular expressions inside the OCamlnet code base call functions of this module only.
You can enable PCRE in the configure script with -enable-pcre or -enable-full-pcre. The effects are as follows:

  • Library netstring, module Netstring_str: If only -enable-pcre is configured, this is still an API around Str. If, however, -enable-full-pcre is configured, the module maps the functions to PCRE calls. Note that the regular expressions still use Str-compatible syntax, so this switch of the backend is normally invisible to the caller.
  • Library netstring-pcre, module Netstring_pcre: This module is now available for both configure options. Netstring_pcre provides the same API, but uses PCRE-style regular expression syntax. We provide this module solely for backward compatibility with older versions of Ocamlnet. Note that previous versions of Ocamlnet added this module to the netstring library, but it is now in the new netstring-pcre library.
The meanings of the configuration options are thus:

  • -enable-pcre: The default regexp engine is still Str, and Netstring_pcre is available in the separate library netstring-pcre
  • -enable-full-pcre: The regexp engine is changed to PCRE, and Netstring_pcre is also available in the separate library netstring-pcre
OPAM users: Note that the OPAM package for OCamlnet does not build with PCRE support by default. The trigger for this is the presence of the pcre OPAM package, i.e. do opam install pcre to include netstring-pcre in a rebuild.

Previous Solutions

Actually, Ocamlnet stepped away from PCRE in several phases.

  • Before release 3.3: Ocamlnet always used PCRE as backend. Netstring_str used Str syntax, but mapped this to PCRE syntax.
  • Release 3.3.1: Optionally, Netstring_str can now use Str as backend. There are still thread-safety issues, so this was not made the default, and only active after -disable-pcre.
  • Release 3.6: This version fixed the thread-safety problems, and Str was now the default backend. The option -enable-pcre reverted to the previous behavior: PCRE backed Netstring_str, and Netstring_pcre was built. The latter module was moved to its own library netstring-pcre.
  • Release 3.6.4 (current): Adding -enable-full-pcre with the meaning that PCRE becomes the backend, and -enable-pcre has now the weaker meaning that netstring-pcre is built.

Recommendations

For packagers of Ocamlnet, the recommendation is to build Ocamlnet with Str as default engine, and to offer PCRE as option (i.e. -enable-pcre). The latter allows it to easily port other software to the new Ocamlnet style.

It is discouraged to switch completely to PCRE (-enable-full-pcre).

For users of Ocamlnet, the recommendations are:

  • Use Str as regular expression engine, and if thread-safety is an issue, prefer Netstring_str over the default Str API.
  • If there are still good reasons to use PCRE, you have either the choice to use PCRE directly, or via Netstring_pcre. This module will not go away (it is not deprecated).

ocamlnet-4.1.2/doc/html-main/Netchannels.buffered_raw_in_channel-c.html0000644000175000017500000004514012731530351024563 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.buffered_raw_in_channel

Class Netchannels.buffered_raw_in_channel

class buffered_raw_in_channel : ?eol:string list -> ?buffer_size:int -> ?pass_through:int -> raw_in_channel -> enhanced_raw_in_channel
This class adds a buffer to the underlying raw_in_channel. As additional feature, the method enhanced_input_line is a fast version of input_line that profits from the buffer.


eol : The accepted end-of-line delimiters. The method enhanced_input_line recognizes any of the passed strings as EOL delimiters. When more than one delimiter matches, the longest is taken. Defaults to ["\n"] . Note that input_line always only recognizes "\n" as EOL character, this cannot be changed. The delimiter strings must neither be empty, nor longer than buffer_size.
buffer_size : The size of the buffer, by default 4096.
pass_through : If the read request has at least this size, and the buffer is currently empty, the buffer will be bypassed. Defaults to max_int, i.e. it is off.

ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.generic_call.html0000644000175000017500000006241212731530351023725 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.generic_call object
  method assoc_multi_req_header : string -> string list
  method assoc_multi_resp_header : string -> string list
  method assoc_req_header : string -> string
  method assoc_resp_header : string -> string
  method auth_status : unit auth_status
  method private virtual def_empty_path_replacement : string
  method private virtual def_has_req_body : bool
  method private virtual def_has_resp_body : bool
  method private virtual def_is_idempotent : bool
  method private virtual def_request_method : string
  method dest_status : unit -> string * int * string
  method effective_request_uri : string
  method empty_path_replacement : string
  method private virtual fixup_request : unit -> unit
  method get_host : unit -> string
  method get_path : unit -> string
  method get_port : unit -> int
  method get_reconnect_mode : http_call how_to_reconnect
  method get_redirect_mode : http_call how_to_redirect
  method get_req_body : unit -> string
  method get_req_header : unit -> (string * string) list
  method get_req_method : unit -> string
  method get_resp_body : unit -> string
  method get_resp_header : unit -> (string * string) list
  method get_uri : unit -> string
  method gssapi_props : Netsys_gssapi.client_props option
  method has_req_body : bool
  method has_resp_body : bool
  method is_idempotent : bool
  method is_proxy_allowed : unit -> bool
  method is_served : bool
  method max_response_body_length : int64
  method no_proxy : unit -> unit
  method private_api : private_api
  method proxy_enabled : bool
  method proxy_use_connect : bool
  method request_body : Netmime.mime_body
  method request_header : header_kind -> Netmime.mime_header
  method request_method : string
  method request_uri : string
  method response_body : Netmime.mime_body
  method response_body_storage : response_body_storage
  method response_header : Netmime.mime_header
  method response_protocol : string
  method response_status : Nethttp.http_status
  method response_status_code : int
  method response_status_text : string
  method same_call : unit -> http_call
  method set_accept_encoding : unit -> unit
  method set_chunked_request : unit -> unit
  method set_expect_handshake : unit -> unit
  method set_max_response_body_length : int64 -> unit
  method set_proxy_enabled : bool -> unit
  method set_reconnect_mode : http_call how_to_reconnect -> unit
  method set_redirect_mode : http_call how_to_redirect -> unit
  method set_req_header : string -> string -> unit
  method set_request_body : Netmime.mime_body -> unit
  method set_request_device : (unit -> Uq_io.in_device) -> unit
  method set_request_header : Netmime.mime_header -> unit
  method set_request_uri : string -> unit
  method set_response_body_storage : response_body_storage -> unit
  method set_transport_layer : transport_layer_id -> unit
  method status : status
  method tls_session_props : Nettls_support.tls_session_props option
end
ocamlnet-4.1.2/doc/html-main/type_Shell.html0000644000175000017500000006131512731530351017403 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell sig
  exception Subprocess_error of (string * Unix.process_status) list
  type producer
  type consumer
  type assignment
  val command :
    ?cmdname:string ->
    ?arguments:string array ->
    ?chdir:string ->
    ?environment:Shell_sys.environment ->
    ?descriptors:Unix.file_descr list ->
    ?assignments:Shell.assignment list -> string -> Shell_sys.command
  val cmd :
    ?cmdname:string ->
    ?chdir:string ->
    ?environment:Shell_sys.environment ->
    ?descriptors:Unix.file_descr list ->
    ?assignments:Shell.assignment list ->
    string -> string list -> Shell_sys.command
  val call :
    ?ignore_error_code:bool ->
    ?mode:Shell_sys.group_mode ->
    ?stdin:Shell.producer ->
    ?stdout:Shell.consumer ->
    ?stderr:Shell.consumer -> Shell_sys.command list -> unit
  val setup_job :
    ?stdin:Shell.producer ->
    ?stdout:Shell.consumer ->
    ?stderr:Shell.consumer ->
    Shell_sys.command list -> Shell_sys.job * Unix.file_descr list
  val postprocess_job :
    ?ignore_error_code:bool -> Shell_sys.job_instance -> unit
  val assign :
    src:Unix.file_descr -> target:Unix.file_descr -> Shell.assignment
  val ( >& ) : Unix.file_descr -> Unix.file_descr -> Shell.assignment
  val ( <& ) : Unix.file_descr -> Unix.file_descr -> Shell.assignment
  val assigned_pair : Shell.assignment -> Unix.file_descr * Unix.file_descr
  val stdin : Unix.file_descr
  val stdout : Unix.file_descr
  val stderr : Unix.file_descr
  val from_string :
    ?pos:int -> ?len:int -> ?epipe:(unit -> unit) -> string -> Shell.producer
  val from_stream :
    ?epipe:(unit -> unit) -> string Stream.t -> Shell.producer
  val from_function :
    producer:(Unix.file_descr -> bool) -> unit -> Shell.producer
  val from_file : string -> Shell.producer
  val from_fd : Unix.file_descr -> Shell.producer
  val from_dev_null : Shell.producer
  val to_buffer : Buffer.t -> Shell.consumer
  val to_function :
    consumer:(Unix.file_descr -> bool) -> unit -> Shell.consumer
  val to_file : ?append:bool -> string -> Shell.consumer
  val to_fd : Unix.file_descr -> Shell.consumer
  val to_dev_null : Shell.consumer
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_plex.html0000644000175000017500000012504112731530351020112 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_plex

Module Nethttpd_plex

module Nethttpd_plex: sig .. end

Netplex support




The important function is nethttpd_factory, see below. The other functions are only needed for special effects.

An example is explained here: Example - A Simple Web Server

type config_log_error = Nethttpd_types.request_info -> string -> unit 
type config_log_access = Nethttpd_types.full_info -> unit 
type config_error_response = Nethttpd_types.error_response_params -> string 
Three type abbreviations for logging functions
val std_log_error : Netplex_types.container -> config_log_error
Returns a function that logs errors using the log_subch method of the passed container
val std_log_access : ?debug:bool -> Netplex_types.container -> config_log_access
Returns a function that logs accesses using the log_subch method of the passed container

If debug is set, additional debug log messages are printed that dump the whole access (incl. header and all available information)

val std_error_response : config_error_response
A sample error response function
val restrict_file_service_config : Netplex_types.config_file -> Netplex_types.address -> unit
Restricts the subsections and paremeters in the service configuration section of type "file" to the allowed ones.
val read_file_service_config : Netplex_types.config_file ->
Netplex_types.address -> string -> Nethttpd_services.file_service
read_file_service_config cfg addr uri_path: Reads the service configuration section of type "file" from config file cfg at address addr. uri_path is the default value put into the file_uri component of the returned record if no "uri" configuration parameter exists. (In other words, this is the path of the enclosing "uri" section, or "/" if there is only a "host" section.) All other parameters are only taken from the configuration section.

See below at nethttpd_factory how a file service needs to be configured.

val restrict_dynamic_service_config : Netplex_types.config_file -> Netplex_types.address -> unit
Restricts the subsections and paremeters in the service configuration section of type "dynamic" to the allowed ones.
val read_dynamic_service_config : (string *
(Netplex_types.config_file ->
Netplex_types.address ->
string -> (#Netcgi.cgi_activation as 'a) Nethttpd_services.dynamic_service))
list ->
Netplex_types.config_file ->
Netplex_types.address -> string -> 'a Nethttpd_services.dynamic_service
read_dynamic_service_config handlers cfg addr uri_path: Reads the service configuration section of type "dynamic" from config file cfg at address addr. The alist handlers defines the available handlers. Every handler h is called like h cfg addr uri_path. uri_path is like in read_file_service_config, i.e. the path of the enclosing "uri" section, or "/" by default.

The h function has to return the dynamic service to use, which is also returned by read_dynamic_service_config.

See below at nethttpd_factory how a dynamic service needs to be configured.

type encap = [ `Engine | `Reactor ] 
val nethttpd_processor : ?hooks:Netplex_types.processor_hooks ->
?encap:encap ->
(Netplex_types.container -> #Nethttpd_reactor.http_reactor_config) ->
'a Nethttpd_types.http_service -> Netplex_types.processor
netplex_processor mk_config http_service: Creates a Netplex processor for Nethttpd.

mk_config determines the nethttpd config for a container. This is especially useful for setting the logging functions.

The resulting processor must be turned into a full Netplex service by Netplex_sockserv.create_socket_service which can then be added by calling the controller's method add_service.

hooks: One can pass a Netplex hook object to set the hooks of the processor.

encap: Selects the encapsulation, `Reactor or `Engine. The default is `Reactor. Each encapsulation has specific strengths and weaknesses:

  • `Reactor is simpler code. Also, the request and response bodies need not to be buffered up, and are directly connected with the underlying socket (low memory requirement). The disadvantage is that a reactor processes TCP connections serially (important to know when there is only a single Unix process)
  • `Engine: The request body needs to be completely buffered up. If pipelining is enabled, the response bodies are also buffered (FIXME). The advantage of this encapsulation is that the engine can process multiple TCP connections simultaneously, even in a single process/thread.

type (#Netcgi.cgi_activation
, [ `Dynamic_service of
(#Netcgi.cgi_activation as 'a) Nethttpd_services.dynamic_service
| `File_service of Nethttpd_services.file_service ])
service_factory
= (string * 'a Nethttpd_services.dynamic_service) list ->
Netplex_types.config_file ->
Netplex_types.address ->
string ->
[ `Dynamic_service of 'a Nethttpd_services.dynamic_service
| `File_service of Nethttpd_services.file_service ]
Nethttpd_types.http_service
The service factory function is called when a service configuration section of a certain type needs to be read. The function has args handlers, cfg, addr, and uri_path. It needs to return the http_service.

Such a function is usually read_file_service_config, or read_dynamic_service_config, or a derivative, whose return value is turned into a http_service. This can be done with Nethttpd_services.file_service and Nethttpd_services.dynamic_service.

val default_services : (string *
(#Netcgi.cgi_activation as 'a,
[ `Dynamic_service of 'a Nethttpd_services.dynamic_service
| `File_service of Nethttpd_services.file_service ])
service_factory)
list
The default services
type httpd_factory = {
   httpd_factory : 'a.
(Netplex_types.container -> Nethttpd_reactor.http_reactor_config) ->
'a Nethttpd_types.http_service -> Netplex_types.processor
;
}
The type of the nethttpd_processor function
val nethttpd_factory : ?name:string ->
?hooks:Netplex_types.processor_hooks ->
?encap:encap ->
?config_cgi:Netcgi.config ->
?handlers:(string *
(#Netcgi.cgi_activation as 'a) Nethttpd_services.dynamic_service)
list ->
?services:(string *
('a,
[ `Dynamic_service of 'a Nethttpd_services.dynamic_service
| `File_service of Nethttpd_services.file_service ])
service_factory)
list ->
?log_error:(Netplex_types.container -> config_log_error) ->
?log_access:(?debug:bool ->
Netplex_types.container -> config_log_access) ->
?error_response:config_error_response ->
?processor_factory:httpd_factory ->
?tls:(module Netsys_crypto_types.TLS_PROVIDER) ->
unit -> Netplex_types.processor_factory
Factory for a web server component.

Configuration file. See below.

The services optional argument can be used to change the service types understood. If not passed, it defaults to default_services. The default includes "file" and "dynamic".

Arguments.

  • name: The processor name. Defaults to "nethttpd". This name can be referenced by the "type" parameters in the processor section of the config file.
  • hooks: One can pass a Netplex hook object to set the hooks of the processor. (This argument is ignored if a processor_factory is passed to this function.)
  • encap: See Nethttpd_plex.nethttpd_processor. (This argument is ignored if a processor_factory is passed to this function.)
  • config_cgi: The CGI configuration to use
  • handlers: a list of handler function. These functions can be referenced from a service section in the config file where type="dynamic" (see example above). Defaults to the empty list.
  • services: A list of service handlers that can be used by service sections in the config files. Defaults to Nethttpd_plex.default_services which defines "file" and "dynamic".
  • log_error: The error logger. Defaults to Nethttpd_plex.std_log_error.
  • log_access: The access logger. Defaults to Nethttpd_plex.std_log_access.
  • error_response: a handler which is invoked to generate error responses. Defaults to Nethttpd_plex.std_error_response.
  • processor_factory: the function creating the processor. Default is nethttpd_processor.
  • tls: the TLS provider to use. By default, Netsys_crypto.current_tls_opt is used.


Configuration files

The configuration file understood by nethttpd_factory looks like:

    processor {
      type = "nethttpd";          (* or what is passed as "name" arg *)
      timeout = 300.0;
      timeout_next_request = 15.0;
      access_log = "enabled";
      suppress_broken_pipe = true;
      host {
        pref_name = "myhost";     (* optional *)
        pref_port = 80;           (* optional *)
        names = "myhost:80 yourhost:81";  (* use *:0 for any name *)
        uri {
          path = "/the/path";
          method {
            allow = "GET POST";
            (* or: deny = "..." *)
            service {
              type = "...";
              ...
            }
          }
        }
        uri {
          ...
        }
      }
      host {
        ...
      }
    }
 

The access_log parameter can be set to off, enabled, or debug. The default is off. Access messages go to the "access" subchannel of the component logger. If enabled, one line is printed with the most important data. If debug is set, all access data are printed.

If suppress_broken_pipe the error "Broken pipe" is not logged in the error log. This error occurs frequently, and may be regarded as a normal condition.

The sections host, uri and method can be nested to any depth. However, on every nesting level only one of these section types must be used. For example, if a host section already contains uri subsections, it is not allowed to add method subsections. Furthermore, the outermost section must be host.

The service section may be one of (at least if the services parameter is not overridden):

    service {
      type = "file";
      docroot = "/a/path/in/the/filesystem";
      uri = "/the/uri/prefix/corresponding/to/docroot";
      media_types_file = "/etc/mime.types";
      media_type {
        type = "application/foo";
        suffix = "foo"
      }
      default_media_type = "text/plain";
      enable_gzip = true;   (* see doc in nethttpd_services.mli *)
      index_files = "index.html";
      enable_listings = true;
      hide_from_listings = "README";   (* list of PCRE regexps *)
    }
 

Note that uri is taken from the surrounding uri section (or assumed to be "/" if there is none) if omitted.

    service {
      type = "dynamic";
      handler = "name_of_handler";
    }
 

Binds the passed handler here.

Any of host, uri, and method sections may contain one or several access sections (which are AND-connected):

    access {
      type = "host";
      allow = "host1 host2 ...";
      (* or deny = "host1 host2 ..."; *)
    }
 

Other access control methods are not yet available.

Configuration files

The configuration file understood by nethttpd_factory looks like:

    processor {
      type = "nethttpd";          (* or what is passed as "name" arg *)
      timeout = 300.0;
      timeout_next_request = 15.0;
      access_log = "enabled";
      suppress_broken_pipe = true;
      host {
        pref_name = "myhost";     (* optional *)
        pref_port = 80;           (* optional *)
        names = "myhost:80 yourhost:81";  (* use *:0 for any name *)
        uri {
          path = "/the/path";
          method {
            allow = "GET POST";
            (* or: deny = "..." *)
            service {
              type = "...";
              ...
            }
          }
        }
        uri {
          ...
        }
      }
      host {
        ...
      }
    }
 

The access_log parameter can be set to off, enabled, or debug. The default is off. Access messages go to the "access" subchannel of the component logger. If enabled, one line is printed with the most important data. If debug is set, all access data are printed.

If suppress_broken_pipe the error "Broken pipe" is not logged in the error log. This error occurs frequently, and may be regarded as a normal condition.

The sections host, uri and method can be nested to any depth. However, on every nesting level only one of these section types must be used. For example, if a host section already contains uri subsections, it is not allowed to add method subsections. Furthermore, the outermost section must be host.

The service section may be one of (at least if the services parameter is not overridden):

    service {
      type = "file";
      docroot = "/a/path/in/the/filesystem";
      uri = "/the/uri/prefix/corresponding/to/docroot";
      media_types_file = "/etc/mime.types";
      media_type {
        type = "application/foo";
        suffix = "foo"
      }
      default_media_type = "text/plain";
      enable_gzip = true;   (* see doc in nethttpd_services.mli *)
      index_files = "index.html";
      enable_listings = true;
      hide_from_listings = "README";   (* list of PCRE regexps *)
    }
 

Note that uri is taken from the surrounding uri section (or assumed to be "/" if there is none) if omitted.

    service {
      type = "dynamic";
      handler = "name_of_handler";
    }
 

Binds the passed handler here.

Any of host, uri, and method sections may contain one or several access sections (which are AND-connected):

    access {
      type = "host";
      allow = "host1 host2 ...";
      (* or deny = "host1 host2 ..."; *)
    }
 

Other access control methods are not yet available.

Configuring TLS

First of all, there needs to be a TLS provider. See Tls for more information how to get one.

If the TLS provider is initialized, you can have a tls subsection inside processor, like:

processor {
  ...
  tls {
    x509 {
      trust {
        crt_file = "ca.pem";
      }
      key {
        crt_file = "server.crt";
        key_file = "server.key";
      }
    }
  }
}

All of the files, ca.pem, server.crt and server.key need to be PEM-encoded. You can have several key sub-sections when you want to do name-based virtual hosting. Note, however, that this relies on the SNI extension of the TLS protocol, and not all clients support this extension.

Further parameters inside tls:

  • algorithms: This is a string describing the cipher suites and protocol options that are in effect. This string is provider-specific. (GnuTLS calls this string the "priority string".) Example:
    tls {
       ...
       algorithms = "SECURE-128 !ARCFOUR-128";
    }
       
  • dh_params: This sub-section may set DH parameters. Example:
    tls {
      ...
      dh_params {
        pkcs3_file = "/path/to/pkcs3_file";
      }
    }
       
  • peer_auth: This string parameter may enable client certificates. Set it to "required" to enforce such a certificate.
    tls {
      ...
      peer_auth = "required";
    }
       

ocamlnet-4.1.2/doc/html-main/Netchannels_crypto.tls_channel-c.html0000644000175000017500000004302712731530351023646 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.tls_channel

Class type Netchannels_crypto.tls_channel

class type tls_channel = object .. end
A TLS channel is a layer on top of a bidirectional channel that adds the TLS protocol.
Inherits
method tls_endpoint : Netsys_crypto_types.tls_endpoint
ocamlnet-4.1.2/doc/html-main/type_Uq_socks5.html0000644000175000017500000004501212731530351020204 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_socks5 sig
  exception Socks_error of string
  class proxy_client :
    Uq_engines.connect_address ->
    object
      method connect :
        Uq_engines.connect_address ->
        Unixqueue.event_system -> Uq_engines.connect_status Uq_engines.engine
      method create_datagram_socket :
        Uq_engines.datagram_type ->
        Unixqueue.event_system ->
        Uq_engines.wrapped_datagram_socket Uq_engines.engine
      method listen :
        Uq_engines.listen_address ->
        Unixqueue.event_system ->
        Uq_engines.server_endpoint_acceptor Uq_engines.engine
    end
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.http_environment.html0000644000175000017500000004401112731530351025241 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_environment #Nethttpd_reactor.http_processor_config ->
string ->
string ->
Nethttp.protocol ->
Nethttp.http_header ->
Unix.sockaddr ->
Unix.sockaddr ->
Netchannels.in_obj_channel ->
int64 Pervasives.ref ->
Netchannels.out_obj_channel ->
Nethttpd_types.output_state Pervasives.ref ->
Nethttpd_kernel.http_response ->
(unit -> unit) ->
bool Pervasives.ref ->
int64 ->
Nettls_support.tls_session_props option ->
Nethttpd_reactor.internal_environment
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.TLS_ENDPOINT.TLS.html0000644000175000017500000004060612731530351025047 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_ENDPOINT.TLS TLS_PROVIDERocamlnet-4.1.2/doc/html-main/type_Uq_transfer.async_out_channel.html0000644000175000017500000004246112731530351024321 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.async_out_channel object
  method can_output : bool
  method close_out : unit -> unit
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method pos_out : int
  method request_notification : (unit -> bool) -> unit
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.wrapped_datagram_socket-c.html0000644000175000017500000004530312731530351024460 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.wrapped_datagram_socket

Class type Uq_engines.wrapped_datagram_socket

class type wrapped_datagram_socket = object .. end

method descriptor : Unix.file_descr
method sendto : Bytes.t -> int -> int -> Unix.msg_flag list -> sockspec -> int
method recvfrom : Bytes.t -> int -> int -> Unix.msg_flag list -> int * sockspec
method shut_down : unit -> unit
method datagram_type : datagram_type
method socket_domain : Unix.socket_domain
method socket_type : Unix.socket_type
method socket_protocol : int
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.server_endpoint_listener-c.html0000644000175000017500000004337112731530351026267 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.server_endpoint_listener

Class type Uq_engines_compat.server_endpoint_listener

class type server_endpoint_listener = object .. end

method listen : listen_address ->
Unixqueue.event_system ->
server_endpoint_acceptor engine
ocamlnet-4.1.2/doc/html-main/type_Uq_multiplex.multiplex_controller.html0000644000175000017500000005213112731530351025305 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_multiplex.multiplex_controller object
  method alive : bool
  method cancel_reading : unit -> unit
  method cancel_shutting_down : unit -> unit
  method cancel_writing : unit -> unit
  method event_system : Unixqueue.event_system
  method inactivate : unit -> unit
  method mem_supported : bool
  method read_eof : bool
  method reading : bool
  method shutting_down : bool
  method start_mem_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_mem_writing :
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_shutting_down :
    ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
  method start_writing :
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit
  method supports_half_open_connection : bool
  method tls_session : (string * string) option
  method tls_session_props : Nettls_support.tls_session_props option
  method tls_stashed_endpoint : unit -> exn
  method writing : bool
  method wrote_eof : bool
end
ocamlnet-4.1.2/doc/html-main/Netsys_polypipe.Debug.html0000644000175000017500000004200212731530351021516 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_polypipe.Debug

Module Netsys_polypipe.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.stream_seq_engine.html0000644000175000017500000004166412731530351025470 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.stream_seq_engine '->
('-> '#Uq_engines_compat.engine) Stream.t ->
Unixqueue.event_system -> ['a] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/type_Netcgi_apache.Apache.Request.html0000644000175000017500000012315512731530351023656 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache.Request sig
  type t
  external connection :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Connection.t
    = "netcgi2_apache_request_connection"
  external server :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Server.t
    = "netcgi2_apache_request_server"
  external next :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Request.t
    = "netcgi2_apache_request_next"
  external prev :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Request.t
    = "netcgi2_apache_request_prev"
  external main :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Request.t
    = "netcgi2_apache_request_main"
  external the_request : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_the_request"
  external assbackwards : Netcgi_apache.Apache.Request.t -> bool
    = "netcgi2_apache_request_assbackwards"
  external header_only : Netcgi_apache.Apache.Request.t -> bool
    = "netcgi2_apache_request_header_only"
  external protocol : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_protocol"
  external proto_num : Netcgi_apache.Apache.Request.t -> int
    = "netcgi2_apache_request_proto_num"
  external hostname : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_hostname"
  external request_time : Netcgi_apache.Apache.Request.t -> float
    = "netcgi2_apache_request_request_time"
  external status_line : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_status_line"
  external set_status_line : Netcgi_apache.Apache.Request.t -> string -> unit
    = "netcgi2_apache_request_set_status_line"
  external status : Netcgi_apache.Apache.Request.t -> int
    = "netcgi2_apache_request_status"
  external set_status : Netcgi_apache.Apache.Request.t -> int -> unit
    = "netcgi2_apache_request_set_status"
  external method_name : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_method"
  val method_number :
    Netcgi_apache.Apache.Request.t ->
    [ `CONNECT
    | `COPY
    | `DELETE
    | `GET
    | `INVALID
    | `LOCK
    | `MKCOL
    | `MOVE
    | `OPTIONS
    | `PATCH
    | `POST
    | `PROPFIND
    | `PROPPATCH
    | `PUT
    | `TRACE
    | `UNLOCK ]
  external headers_in :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
    = "netcgi2_apache_request_headers_in"
  external headers_out :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
    = "netcgi2_apache_request_headers_out"
  external err_headers_out :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
    = "netcgi2_apache_request_err_headers_out"
  external subprocess_env :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
    = "netcgi2_apache_request_subprocess_env"
  external notes :
    Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
    = "netcgi2_apache_request_notes"
  external content_type : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_content_type"
  external set_content_type :
    Netcgi_apache.Apache.Request.t -> string -> unit
    = "netcgi2_apache_request_set_content_type"
  external uri : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_uri"
  external port : Netcgi_apache.Apache.Request.t -> int
    = "netcgi2_apache_request_port"
  external set_uri : Netcgi_apache.Apache.Request.t -> string -> unit
    = "netcgi2_apache_request_set_uri"
  external filename : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_filename"
  external set_filename : Netcgi_apache.Apache.Request.t -> string -> unit
    = "netcgi2_apache_request_set_filename"
  external path_info : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_path_info"
  external set_path_info : Netcgi_apache.Apache.Request.t -> string -> unit
    = "netcgi2_apache_request_set_path_info"
  external args : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_args"
  external set_args : Netcgi_apache.Apache.Request.t -> string -> unit
    = "netcgi2_apache_request_set_args"
  external finfo : Netcgi_apache.Apache.Request.t -> Unix.stats option
    = "netcgi2_apache_request_finfo"
  type read_policy = NO_BODY | CHUNKED_ERROR | CHUNKED_DECHUNK | CHUNKED_PASS
  val setup_client_block :
    Netcgi_apache.Apache.Request.t ->
    Netcgi_apache.Apache.Request.read_policy -> unit
  external should_client_block : Netcgi_apache.Apache.Request.t -> bool
    = "netcgi2_apache_request_should_client_block"
  val get_client_block : Netcgi_apache.Apache.Request.t -> string
  val get_client_block_buf :
    Netcgi_apache.Apache.Request.t -> Bytes.t -> int -> int -> int
  val discard_request_body : Netcgi_apache.Apache.Request.t -> unit
  external user : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_request_user"
  external auth_type : Netcgi_apache.Apache.Request.t -> string
    = "netcgi2_apache_auth_type"
  external note_auth_failure : Netcgi_apache.Apache.Request.t -> unit
    = "netcgi2_apache_request_note_auth_failure"
  external note_basic_auth_failure : Netcgi_apache.Apache.Request.t -> unit
    = "netcgi2_apache_request_note_basic_auth_failure"
  external note_digest_auth_failure : Netcgi_apache.Apache.Request.t -> unit
    = "netcgi2_apache_request_note_digest_auth_failure"
  val get_basic_auth_pw : Netcgi_apache.Apache.Request.t -> string option
  external internal_redirect :
    string -> Netcgi_apache.Apache.Request.t -> unit
    = "netcgi2_apache_request_internal_redirect"
  external internal_redirect_handler :
    string -> Netcgi_apache.Apache.Request.t -> unit
    = "netcgi2_apache_request_internal_redirect_handler"
  external send_http_header : Netcgi_apache.Apache.Request.t -> unit
    = "netcgi2_apache_request_send_http_header"
  val rflush : Netcgi_apache.Apache.Request.t -> unit
  external print_char : Netcgi_apache.Apache.Request.t -> char -> unit
    = "netcgi2_apache_request_print_char"
  val print_string : Netcgi_apache.Apache.Request.t -> string -> unit
  val output : Netcgi_apache.Apache.Request.t -> Bytes.t -> int -> int -> int
  val print_int : Netcgi_apache.Apache.Request.t -> int -> unit
  val print_float : Netcgi_apache.Apache.Request.t -> float -> unit
  val print_newline : Netcgi_apache.Apache.Request.t -> unit
  val print_endline : Netcgi_apache.Apache.Request.t -> string -> unit
  external register_cleanup :
    Netcgi_apache.Apache.Request.t -> (unit -> unit) -> unit
    = "netcgi2_apache_request_register_cleanup"
end
ocamlnet-4.1.2/doc/html-main/Rpc_server.auth_details-c.html0000644000175000017500000004541512731530351022275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.auth_details

Class type Rpc_server.auth_details

class type auth_details = object .. end

method server_addr : Unix.sockaddr option
method client_addr : Unix.sockaddr option
method program : Netnumber.uint4
method version : Netnumber.uint4
method procedure : Netnumber.uint4
method xid : Netnumber.uint4
method credential : string * string
method verifier : string * string
method frame_len : int
method message : Rpc_packer.packed_value
method transport_user : string option
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.input_async_descr.html0000644000175000017500000004136112731530351025506 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.input_async_descr src:Unix.file_descr ->
?buffer_size:int ->
?close_src:bool ->
Unixqueue.event_system -> Uq_engines_compat.async_in_channel_engine
ocamlnet-4.1.2/doc/html-main/Netgzip.input_deflate-c.html0000644000175000017500000004305512731530351021756 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.input_deflate

Class Netgzip.input_deflate

class input_deflate : ?level:int -> Netchannels.in_obj_channel -> Netchannels.in_obj_channel
let ch' = new input_deflate ch: Reading data from ch' deflates data read from ch. Use this for compressing data while reading.

Note that ch isn't closed when ch' is closed.


ocamlnet-4.1.2/doc/html-main/Uq_engines.watchdog-c.html0000644000175000017500000004437712731530351021420 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.watchdog

Class Uq_engines.watchdog

class watchdog : float -> 'a #engine -> [unit] engine
A watchdog engine checks whether the argument engine makes progress, and if there is no progress for the passed number of seconds, the engine is aborted, and the watchdog state changes to `Error Watchdog_timeout.

The current implementation is not very exact, and it may take a little longer than the passed period of inactivity until the watchdog recognizes inactivity.

If the argument engine terminates, the watchdog changes its state to `Done ()

Important note: The watchdog assumes that the `Working state of the target engine really counts events that indicate progress. This does not work for:

  • poll_process_engine: there is no way to check whether a subprocess makes progress
  • connector: It is usually not possible to reflect the progress on packet level
  • listener: It is usually not possible to reflect the progress on packet level


ocamlnet-4.1.2/doc/html-main/Netplex_cenv.Make_lever.html0000644000175000017500000004720712731530351022002 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.Make_lever

Functor Netplex_cenv.Make_lever

module Make_lever: 
functor (T : FUN_TYPE) -> LEVER with type s=T.s and type r=T.r
Creates a LEVER module from a function type as specified in FUN_TYPE
Parameters:
T : FUN_TYPE

type s 
argument type
type r 
result type
type t = s -> r 
val register : Netplex_types.controller ->
(Netplex_types.controller -> t) -> t
let reg_lever = register ctrl raw_lever: Registers raw_lever in the controller ctrl, so one can call reg_lever to activate it. For example:

 
           module LT = struct type s = unit type r = int end
           module L = Make_lever(LT)
         
           let get_num_services =
             L.register ctrl (fun ctrl () -> List.length ctrl#services)
        

The registration must be done in controller context, e.g. in the pre_start_hook of a container.

From the running container, one can now call:

 get_num_services() 

to get the current length of the ctrl#services list.

ocamlnet-4.1.2/doc/html-main/type_Netcgi_common.simple_arg.html0000644000175000017500000004106512731530351023236 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.simple_arg ?ro:bool -> string -> string -> Netcgi_common.rw_cgi_argumentocamlnet-4.1.2/doc/html-main/type_Nethttp_client.tls_cache.html0000644000175000017500000004251712731530351023247 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.tls_cache object
  method clear : unit -> unit
  method get :
    domain:string ->
    port:int -> trans:Nethttp_client.transport_layer_id -> string
  method set :
    domain:string ->
    port:int ->
    trans:Nethttp_client.transport_layer_id -> data:string -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_cenv.html0000644000175000017500000007462112731530351020772 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv sig
  exception Not_in_container_thread
  val log : Netplex_types.level -> string -> unit
  val logf :
    Netplex_types.level -> ('a, unit, string, unit) Pervasives.format4 -> 'a
  val report_connection_string : Unix.file_descr -> string -> string
  type timer
  val create_timer :
    (Netplex_cenv.timer -> bool) -> float -> Netplex_cenv.timer
  val cancel_timer : Netplex_cenv.timer -> unit
  val cancel_all_timers : unit -> unit
  val timer_id : Netplex_cenv.timer -> int
  exception Container_variable_not_found of string
  exception Container_variable_type_mismatch of string
  val int_var : string -> int
  val string_var : string -> string
  val float_var : string -> float
  val bool_var : string -> bool
  val set_int_var : string -> int -> unit
  val set_string_var : string -> string -> unit
  val set_float_var : string -> float -> unit
  val set_bool_var : string -> bool -> unit
  val make_var_type :
    ('-> Netplex_types.encap) ->
    (Netplex_types.encap -> 'a) -> (string -> 'a) * (string -> '-> unit)
  module type TYPE = sig type t end
  module type VAR_TYPE =
    sig
      type t
      val get : string -> Netplex_cenv.VAR_TYPE.t
      val set : string -> Netplex_cenv.VAR_TYPE.t -> unit
    end
  module Make_var_type :
    functor (T : TYPE->
      sig
        type t = T.t
        val get : string -> t
        val set : string -> t -> unit
      end
  val system_shutdown : unit -> unit
  val system_restart : unit -> unit
  val send_message : string -> string -> string array -> unit
  val lookup : string -> string -> string option
  val lookup_container_sockets : string -> string -> string array
  val self_cont : unit -> Netplex_types.container
  val self_obj :
    unit ->
    [ `Container of Netplex_types.container
    | `Controller of Netplex_types.controller ]
  val current_sys_id : unit -> [ `Process of int | `Thread of int ]
  val admin_connector : unit -> Rpc_client.mode2
  val run_in_controller_context :
    Netplex_types.controller -> (unit -> unit) -> unit
  val run_in_container_context :
    Netplex_types.container -> (unit -> unit) -> unit
  module type FUN_TYPE = sig type s type r end
  module type LEVER =
    sig
      type s
      type r
      type t = Netplex_cenv.LEVER.s -> Netplex_cenv.LEVER.r
      val register :
        Netplex_types.controller ->
        (Netplex_types.controller -> Netplex_cenv.LEVER.t) ->
        Netplex_cenv.LEVER.t
    end
  module Make_lever :
    functor (T : FUN_TYPE->
      sig
        type s = T.s
        type r = T.r
        type t = s -> r
        val register :
          Netplex_types.controller -> (Netplex_types.controller -> t) -> t
      end
  val pmanage : unit -> Netsys_pmanage.pmanage
  module Debug : sig val enable : bool Pervasives.ref end
  val register_par : Netplex_types.parallelizer -> unit
  val register_cont :
    Netplex_types.container -> Netplex_types.par_thread -> unit
  val unregister_cont :
    Netplex_types.container -> Netplex_types.par_thread -> unit
  val register_ctrl : Netplex_types.controller -> unit
  val unregister_ctrl : Netplex_types.controller -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.meta_engine.html0000644000175000017500000004125712731530351024251 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.meta_engine '#Uq_engines_compat.engine ->
['Uq_engines_compat.final_state] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/Netsys_sasl_types.html0000644000175000017500000005153012731530351021024 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl_types

Module Netsys_sasl_types

module Netsys_sasl_types: sig .. end
Possible channel bindings:
  • `None: this is the default
  • `SASL_none_but_advertise: the client supports channel binding and advertises this. For this time, the SCRAM protocol is run without channel binding, though. (Only available in the SASL profile.)
  • `SASL_require(type,data): Require channel binding. E.g. type="tls-unique", and data is set to the channel identifier (RFC 5929). (Only available in the SASL profile.)
  • `GSSAPI data: use this channel binding for GSS-API
This type is shared by SASL and GSSAPI providers.

type cb = [ `GSSAPI of string
| `None
| `SASL_none_but_advertise
| `SASL_require of string * string ]
Possible channel bindings:
  • `None: this is the default
  • `SASL_none_but_advertise: the client supports channel binding and advertises this. For this time, the SCRAM protocol is run without channel binding, though. (Only available in the SASL profile.)
  • `SASL_require(type,data): Require channel binding. E.g. type="tls-unique", and data is set to the channel identifier (RFC 5929). (Only available in the SASL profile.)
  • `GSSAPI data: use this channel binding for GSS-API
This type is shared by SASL and GSSAPI providers.
type server_state = [ `Auth_error of string | `Emit | `OK | `Restart of string | `Wait ] 
The state of the server session:
  • `Wait: it is waited for the client response.
  • `Emit: a new server challenge can be emitted.
  • `OK: the authentication protocol succeeded
  • `Auth_error: authentication error (it is unspecified which; the string may be used for logging)
  • `Restart session_id: this state can be entered after getting the first client response. It means that the saved session session_id may be restarted by calling server_process_response_restart with the client response.

type client_state = [ `Auth_error of string | `Emit | `OK | `Stale | `Wait ] 
The state of the client session:
  • `Wait: it is waited for the server challenge.
  • `Emit: a new client response can be emitted.
  • `OK: the authentication protocol succeeded
  • `Auth_error: authentication error (it is unspecified which); the string may be used for logging)
  • `Stale: The client session is refused as too old. The password, though, is correct. Otherwise this is the same as `Emit, i.e. the authentication process can continue.

module type SASL_MECHANISM = sig .. end
ocamlnet-4.1.2/doc/html-main/Netchannels.raw_out_channel_delegation-c.html0000644000175000017500000004255612731530351025325 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_out_channel_delegation

Class Netchannels.raw_out_channel_delegation

class raw_out_channel_delegation : ?close:bool -> raw_out_channel -> raw_out_channel

ocamlnet-4.1.2/doc/html-main/type_Netplex_types.controller_config.html0000644000175000017500000004205712731530351024710 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.controller_config object
  method create_logger : Netplex_types.controller -> Netplex_types.logger
  method max_level : Netplex_types.level
  method set_max_level : Netplex_types.level -> unit
  method socket_directory : string
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.output_null.html0000644000175000017500000004106512731530351023167 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_null ?onclose:(unit -> unit) -> unit -> Netchannels.out_obj_channelocamlnet-4.1.2/doc/html-main/type_Netplex_kit.processor_hooks_delegation.html0000644000175000017500000004101112731530351026225 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.processor_hooks_delegation Netplex_types.processor_hooks -> Netplex_types.processor_hooksocamlnet-4.1.2/doc/html-main/Netsys_pollset_posix.html0000644000175000017500000004542612731530351021551 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset_posix

Module Netsys_pollset_posix

module Netsys_pollset_posix: sig .. end
Pollsets for POSIX operating systems

val poll_based_pollset : unit -> Netsys_pollset.pollset
Returns a poll set whose implementation is based on the poll system call.

Win32: On Win32 this implementation works, but only for sockets, and is not cancellable in multi-threaded programs. (This is a restriction because we have to map it to the select call of the WinSock layer.)

val reset : unit -> unit
This module may keep some global state. This function resets this state. As the state may contain file descriptors, it is advisable to reset after calling fork to free these descriptors.
val accelerated_pollset : unit -> Netsys_pollset.pollset
Returns a pollset using a "fast" poll mechanism, if available. Otherwise this is the same as poll_based_pollset.

Fast poll mechanisms are:

  • epoll on Linux
Generally, these mechanisms are not 100% compatible with the standard poll. In particular, the poll events may be slightly differently interpreted. Also, there are many, many reports about buggy implementations in the OS.
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.Debug.html0000644000175000017500000004210412731530351021753 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.Debug

Module Uq_engines_compat.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/type_Netplex_log.generic_config.html0000644000175000017500000004145312731530351023555 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_log.generic_config object
  method log_component : string
  method log_format : string
  method log_max_level : Netplex_types.level
  method log_subchannel : string
end
ocamlnet-4.1.2/doc/html-main/type_Intro.html0000644000175000017500000004060612731530351017427 0ustar gerdgerd Ocamlnet 4 Reference Manual : Intro sig  endocamlnet-4.1.2/doc/html-main/type_Netchannels.lift_raw_out_channel.html0000644000175000017500000004077712731530351024774 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.lift_raw_out_channel Netchannels.raw_out_channel -> Netchannels.out_obj_channelocamlnet-4.1.2/doc/html-main/type_Netencoding.QuotedPrintable.encoding_pipe.html0000644000175000017500000004100112731530351026462 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.QuotedPrintable.encoding_pipe ?crlf:bool -> unit -> Netchannels.pipeocamlnet-4.1.2/doc/html-main/Unixqueue_pollset.pollset_event_system-c.html0000644000175000017500000004166312731530351025537 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_pollset.pollset_event_system

Class Unixqueue_pollset.pollset_event_system

class pollset_event_system : Netsys_pollset.pollset -> Unixqueue_util.event_system

ocamlnet-4.1.2/doc/html-main/Unixqueue_select.html0000644000175000017500000004502412731530351020621 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_select

Module Unixqueue_select

module Unixqueue_select: sig .. end
This the old Unix.select-based imeplementation of event systems which was the default one until Ocamlnet-2.2.

Please avoid in new code. This module merely exists to allow comparisons between the old implementation and the new one.

Note that this class definition also includes some private methods. These are required in some other Unixqueue implementations inheriting from this class.


class type sb_event_system = object .. end
class select_based_event_system : unit -> sb_event_system
This the old Unix.select-based imeplementation of event systems which was the default one until Ocamlnet-2.2.
val select_based_event_system : unit -> Unixqueue.event_system
Create a new Unix.select-based event system
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.container.html0000644000175000017500000005123612731530351023161 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.container object
  method activate_lever : int -> Netplex_types.encap -> Netplex_types.encap
  method call_plugin :
    Netplex_types.plugin -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
  method container_id : Netplex_types.container_id
  method event_system : Unixqueue.unix_event_system
  method log : Netplex_types.level -> string -> unit
  method log_subch : string -> Netplex_types.level -> string -> unit
  method lookup : string -> string -> string option
  method lookup_container_sockets : string -> string -> string array
  method n_connections : int
  method n_total : int
  method owned_container_sockets : (string * string) list
  method ptype : Netplex_types.parallelization_type
  method send_message : string -> string -> string array -> unit
  method set_var : string -> Netplex_types.param_value_or_any -> unit
  method shutdown : unit -> unit
  method socket_service : Netplex_types.socket_service
  method socket_service_name : string
  method start : Netplex_types.extfd -> Netplex_types.extfd -> unit
  method startup_directory : string
  method system : Rpc_client.t
  method system_monitor : Uq_mt.monitor
  method update_detail : Unix.file_descr -> string -> unit
  method var : string -> Netplex_types.param_value_or_any
end
ocamlnet-4.1.2/doc/html-main/style.css0000644000175000017500000000610712731530351016255 0ustar gerdgerda:visited {color : #416DFF; text-decoration : none; } a:link {color : #416DFF; text-decoration : none;} a:hover {color : Red; text-decoration : none; background-color: #5FFF88} a:active {color : Red; text-decoration : underline; } .keyword { font-weight : bold ; color : Red } .keywordsign { color : #C04600 } .superscript { font-size : 4 } .subscript { font-size : 4 } .comment { color : Green } .constructor { color : Blue } .type { color : #5C6585 } .string { color : Maroon } .warning { color : Red ; font-weight : bold } .info { margin-left : 1cm; margin-right : 2cm } .param_info { margin-top: 4px; margin-left : 1cm; margin-right : 2cm } .code { color : #465F91 ; } h1 { font-size : 20pt ; margin-top: 50pt; margin-bottom: 25pt; text-align: center; padding: 5px; border: 1px solid #000000; background-color: #c0c0c0; } h2 { font-size : 20pt ; margin-top: 20pt; margin-bottom: 8pt; text-align: left; padding: 2px; margin-left: 1cm; border-bottom: 1px solid #777777; } h3 { font-size : 16pt ; margin-top: 20pt; margin-bottom: 8pt; text-align: left; padding: 2px; padding-left: 1cm; } h4 { font-size : 12pt ; margin-top: 12pt; margin-bottom: 6pt; text-align: left; padding: 2px; } h5 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90FDFF ;padding: 2px; } h6 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #C0FFFF ; padding: 2px; } div.h7 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #E0FFFF ; padding: 2px; } div.h8 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #F0FFFF ; padding: 2px; } div.h9 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #FFFFFF ; padding: 2px; } .typetable { border-style : hidden } .indextable { border-style : hidden } .paramstable { border-style : hidden ; padding: 5pt 5pt} body { background-color : White } tr { background-color : White } td.typefieldcomment { background-color : #FFFFFF ; font-size: smaller ;} pre { margin-bottom: 4px } div.sig_block {margin-left: 1cm} li { margin-top: 1ex } li p { margin-top: 1ex; margin-bottom: 1ex } .remark { margin-left: 1cm; font-style: italic } .guide { background-color: #F0E4C1 } table.t1 { padding: 5px; border: 1px solid black; border-collapse:collapse; } td.t1 { empty-cells: show; border-top: 1px solid black; border-bottom: 1px solid black; padding-left: 5px; padding-right: 5px; } tr.t1head { background-color: #D0D0D0; } table.intro { padding: 5px; border: 1px solid black; border-collapse:collapse; } td.intro { empty-cells: show; border-top: 1px solid black; border-bottom: 1px solid black; padding-left: 5px; padding-right: 5px; } tr.intro { background-color: #bcdefb; } ocamlnet-4.1.2/doc/html-main/type_Netplex_container.html0000644000175000017500000004347712731530351022026 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_container sig
  val create_container :
    Netplex_types.parallelization_type ->
    Netplex_types.socket_service -> Netplex_types.container
  val create_admin_container :
    Unixqueue.unix_event_system ->
    Netplex_types.parallelization_type ->
    Netplex_types.socket_service -> Netplex_types.container
  module Debug : sig val enable : bool Pervasives.ref end
  val string_of_event : Netplex_ctrl_aux.event -> string
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.http_service_receiver-c.html0000644000175000017500000004463712731530351025123 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.http_service_receiver

Class type Nethttpd_types.http_service_receiver

class type http_service_receiver = object .. end

method process_body : extended_environment -> http_service_generator
Second stage of HTTP processing: This method is called when the body is expected to be arriving. Note that the main difference to process_header is that this method can be called from a different thread. It is allowed (and expected) that this method blocks while reading the input. Of course, the input and output channels of the environment are unlocked, and can be used.

When the method returns, the request processing continues with stage 3. Any body data not read is dropped.

It is allowed that this method generates a response (or part of it), although this should be better done in stage 3.

The method may raise Standard_response to generate one of the standard messages.

One way of implementing this method is to instantiate Netcgi.std_activation.

ocamlnet-4.1.2/doc/html-main/type_Netmech_krb5_sasl.Krb5_gs2_profile.html0000644000175000017500000004066112731530351024762 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_krb5_sasl.Krb5_gs2_profile Netmech_gs2_sasl.PROFILEocamlnet-4.1.2/doc/html-main/type_Netdn.DN_string_generic.html0000644000175000017500000004105512731530351022765 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdn.DN_string_generic functor (L : AT_LOOKUP-> DN_stringocamlnet-4.1.2/doc/html-main/Rpc_client.socket_config-c.html0000644000175000017500000004415412731530351022413 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.socket_config

Class type Rpc_client.socket_config

class type socket_config = object .. end
Configuration for `Socket (see below).

method non_blocking_connect : bool
non_blocking_connect: Whether the remote service is connected in the background. In this case, create2 immediately returns, and it is already possible to add procedure calls. However, these calls are deferred until the connection is established.
method multiplexing : dbg_name:string Pervasives.ref ->
close_inactive_descr:bool ->
peer_name:string option ->
Rpc.protocol ->
Unix.file_descr ->
Unixqueue.event_system ->
Rpc_transport.rpc_multiplex_controller Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Unixqueue_pollset.pollset_event_system.html0000644000175000017500000004100012731530351026341 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_pollset.pollset_event_system Netsys_pollset.pollset -> Unixqueue_util.event_systemocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.html0000644000175000017500000006353112731530351020606 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor

Module Nethttpd_reactor

module Nethttpd_reactor: sig .. end

The reactive encapsulation of the HTTP daemon

This is a user-friendlier encapsulation of the HTTP daemon. It uses a "pull model": One pulls HTTP requests from the "reactor" one after the other. Request/response pairs have a common environment that represents the input and output facilities. Input and output are realised by Netchannels, and the implementation details are completely hidden.

This encapsulation can be easily used in a multi-threaded environment when for every arriving HTTP connection a separate thread is used.


class type http_processor_config = object .. end
val default_http_processor_config : http_processor_config
Default configuration: Extends Nethttpd_kernel.default_http_protocol_config with
class modify_http_processor_config : ?modify_http_protocol_config:Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config -> ?config_timeout_next_request:float -> ?config_timeout:float -> ?config_cgi:Netcgi.config -> ?config_error_response:Nethttpd_types.error_response_params -> string -> ?config_log_error:Nethttpd_types.request_info -> string -> unit -> ?config_log_access:Nethttpd_types.full_info -> unit -> ?config_tls_cert_props:bool -> ?config_tls_remote_user:bool -> http_processor_config -> http_processor_config
Modifies the passed config object as specified by the optional arguments.
class type http_reactor_config = object .. end
val default_http_reactor_config : http_reactor_config
Default configuration: Extends Nethttpd_reactor.default_http_processor_config with
  • config_reactor_synch = `Write

class modify_http_reactor_config : ?modify_http_protocol_config:Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config -> ?modify_http_processor_config:http_processor_config ->
http_processor_config -> ?config_reactor_synch:[ `Close | `Connection | `Flush | `Write ] -> http_reactor_config ->
http_reactor_config
Modifies the passed config object as specified by the optional arguments.
class type internal_environment = object .. end
For private use only
class http_environment : #http_processor_config -> string -> string -> Nethttp.protocol -> Nethttp.http_header -> Unix.sockaddr -> Unix.sockaddr -> Netchannels.in_obj_channel -> int64 Pervasives.ref -> Netchannels.out_obj_channel -> Nethttpd_types.output_state Pervasives.ref -> Nethttpd_kernel.http_response -> (unit -> unit) -> bool Pervasives.ref -> int64 -> Nettls_support.tls_session_props option -> internal_environment
For private use only
class type http_reactive_request = object .. end
class http_reactor : ?config_hooks:Nethttpd_kernel.http_protocol_hooks -> unit -> #http_reactor_config -> Unix.file_descr -> object .. end
The http_reactor allows one to pull the next request from a connected client, and to deliver the response to the protocol engine.
val process_connection : ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) ->
#http_reactor_config ->
Unix.file_descr -> 'a Nethttpd_types.http_service -> unit
Processes all HTTP requests in turn arriving at the file descriptor, and calls the service provider for every request. Finally, the descriptor is closed.

All stages of HTTP processing, as defined by the service provider, are executed in the current thread.

Any exceptions are caught and logged. The connection is immediately closed in this case.


Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netstring_str.html0000644000175000017500000010027112731530351020133 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstring_str

Module Netstring_str

module Netstring_str: sig .. end
Wrapper for regexps with Str syntax

This module was written at a time when we had only the Str module for regular expressions. However, Str has an interface that does not work for multi-threaded programs, because the state of the module is visible to the outside. The module Netstring_str is similar to Str, but has a thread-compatible interface.

For an explanation why we need this module, please read Regexp.



Supported regexp syntax

 .             matches every character but newline
 e*            matches e several times
 e+            matches e several times but at least once
 e?            matches e optionally
 e{m,n}        matches e at least m times and at most n times
 e1\|e2        matches e1 or e2
 [set]         matches the characters from set
 [^set]        matches the characters except from set
 \(...\)       group paranthesis
 \n            back reference (n is digit)
 ^             matches at beginning of line
 $             matches at end of line
 

This is exactly what Str supports. Character classes are not implemented.

type regexp 
The type of regular expressions
type split_result = Str.split_result = 
| Text of string
| Delim of string (*
Here we keep compatibility with Str
*)
type result 
The type of matching results
val regexp : string -> regexp
Parses a regexp
val regexp_case_fold : string -> regexp
Parses a case-insensitive regexp
val quote : string -> string
Quotes a string such that it can be included in a regexp
val regexp_string : string -> regexp
Returns a regexp that matches exactly the string
val regexp_string_case_fold : string -> regexp
Returns a case-insensitive regexp that matches exactly the string
val quote_set : string -> string
Returns a regexp (as string) that matches any of the characters in the argument. The argument must be non-empty
val string_match : regexp -> string -> int -> result option
Matches the string at the position with the regexp. Returns None if no match is found. Returns Some r on success, and r describes the match.
val bytes_match : regexp -> Bytes.t -> int -> result option
Same for bytes
val search_forward : regexp -> string -> int -> int * result
Searches a match of the string with the regexp, starting at the position and in forward direction. Raises Not_found if no match could be found. Returns (p,r) when a match at position p is found, described by r.
val search_forward_bytes : regexp -> Bytes.t -> int -> int * result
Same for bytes
val search_backward : regexp -> string -> int -> int * result
Searches a match of the string with the regexp, starting at the position and in backward direction. Raises Not_found if no match could be found. Returns (p,r) when a match at position p is found, described by r.
val search_backward_bytes : regexp -> Bytes.t -> int -> int * result
Same for bytes
val matched_string : result -> string -> string
Extracts the matched part from the string. The string argument must be the same string passed to string_match or the search functions, and the result argument must be the corresponding result.
val matched_bytes : result -> Bytes.t -> Bytes.t
Same for bytes
val match_beginning : result -> int
Returns the position where the matched part begins
val match_end : result -> int
Returns the position where the matched part ends
val matched_group : result -> int -> string -> string
Extracts the substring the nth group matches from the whole string. The string argument must be the same string passed to string_match or the search functions, and the result argument must be the corresponding result.
val matched_group_bytes : result -> int -> Bytes.t -> Bytes.t
Same for bytes
val group_beginning : result -> int -> int
Returns the position where the substring matching the nth group begins
val group_end : result -> int -> int
Returns the position where the substring matching the nth group ends
val global_replace : regexp -> string -> string -> string
global_replace re templ s: Replaces all matchings of re in s by templ.

In templ one can refer to matched groups by the backslash notation: \1 refers to the first group, \2 to the second etc. \0 is the whole match. \\ is the backslash character.

val replace_first : regexp -> string -> string -> string
replace_first re templ s: Replaces the first match of re in s by templ.

In templ one can refer to matched groups by the backslash notation: \1 refers to the first group, \2 to the second etc. \0 is the whole match. \\ is the backslash character.

val global_substitute : regexp ->
(result -> string -> string) -> string -> string
global_substitute re subst s: Applies the substitution function subst to all matchings of re in s, and returns the transformed string. subst is called with the current result of the match and the whole string s.
val substitute_first : regexp ->
(result -> string -> string) -> string -> string
substitute_first re subst s: Applies the substitution function subst to the first matching of re in s, and returns the transformed string. subst is called with the current result of the match and the whole string s.
val split : regexp -> string -> string list
Splits the string according to the regexp in substrings. Occurrences of the delimiter at the beginning and the end are ignored.
val bounded_split : regexp -> string -> int -> string list
Splits into at most n substrings, based on split
val split_delim : regexp -> string -> string list
Same as split, but occurrences of the delimiter at the beginning and the end are returned as empty strings
val bounded_split_delim : regexp -> string -> int -> string list
Splits into at most n substrings, based on split_delim
val full_split : regexp -> string -> split_result list
Like split_delim, but returns the delimiters in the result
val bounded_full_split : regexp -> string -> int -> split_result list
Splits into at most n substrings, based on full_split
val string_before : string -> int -> string
The first n characters of a string
val string_after : string -> int -> string
The last n characters of a string
val first_chars : string -> int -> string
Same as string_before
val last_chars : string -> int -> string
Same as string_after
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netconversion.html0000644000175000017500000023403712731530351021173 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netconversion sig
  exception Malformed_code
  exception Cannot_represent of int
  type encoding =
      [ `Enc_adobe_standard_encoding
      | `Enc_adobe_symbol_encoding
      | `Enc_adobe_zapf_dingbats_encoding
      | `Enc_asn1_T61
      | `Enc_asn1_iso646
      | `Enc_asn1_printable
      | `Enc_cp037
      | `Enc_cp1006
      | `Enc_cp1026
      | `Enc_cp1047
      | `Enc_cp424
      | `Enc_cp437
      | `Enc_cp500
      | `Enc_cp737
      | `Enc_cp775
      | `Enc_cp850
      | `Enc_cp852
      | `Enc_cp855
      | `Enc_cp856
      | `Enc_cp857
      | `Enc_cp860
      | `Enc_cp861
      | `Enc_cp862
      | `Enc_cp863
      | `Enc_cp864
      | `Enc_cp865
      | `Enc_cp866
      | `Enc_cp869
      | `Enc_cp874
      | `Enc_cp875
      | `Enc_empty
      | `Enc_eucjp
      | `Enc_euckr
      | `Enc_iso88591
      | `Enc_iso885910
      | `Enc_iso885911
      | `Enc_iso885913
      | `Enc_iso885914
      | `Enc_iso885915
      | `Enc_iso885916
      | `Enc_iso88592
      | `Enc_iso88593
      | `Enc_iso88594
      | `Enc_iso88595
      | `Enc_iso88596
      | `Enc_iso88597
      | `Enc_iso88598
      | `Enc_iso88599
      | `Enc_java
      | `Enc_jis0201
      | `Enc_koi8r
      | `Enc_macroman
      | `Enc_subset of Netconversion.encoding * (int -> bool)
      | `Enc_usascii
      | `Enc_utf16
      | `Enc_utf16_be
      | `Enc_utf16_le
      | `Enc_utf32
      | `Enc_utf32_be
      | `Enc_utf32_le
      | `Enc_utf8
      | `Enc_utf8_opt_bom
      | `Enc_windows1250
      | `Enc_windows1251
      | `Enc_windows1252
      | `Enc_windows1253
      | `Enc_windows1254
      | `Enc_windows1255
      | `Enc_windows1256
      | `Enc_windows1257
      | `Enc_windows1258 ]
  type charset =
      [ `Set_adobe_standard_encoding
      | `Set_adobe_symbol_encoding
      | `Set_adobe_zapf_dingbats_encoding
      | `Set_asn1_T61
      | `Set_asn1_iso646
      | `Set_asn1_printable
      | `Set_cp037
      | `Set_cp1006
      | `Set_cp1026
      | `Set_cp1047
      | `Set_cp424
      | `Set_cp437
      | `Set_cp500
      | `Set_cp737
      | `Set_cp775
      | `Set_cp850
      | `Set_cp852
      | `Set_cp855
      | `Set_cp856
      | `Set_cp857
      | `Set_cp860
      | `Set_cp861
      | `Set_cp862
      | `Set_cp863
      | `Set_cp864
      | `Set_cp865
      | `Set_cp866
      | `Set_cp869
      | `Set_cp874
      | `Set_cp875
      | `Set_iso88591
      | `Set_iso885910
      | `Set_iso885911
      | `Set_iso885913
      | `Set_iso885914
      | `Set_iso885915
      | `Set_iso885916
      | `Set_iso88592
      | `Set_iso88593
      | `Set_iso88594
      | `Set_iso88595
      | `Set_iso88596
      | `Set_iso88597
      | `Set_iso88598
      | `Set_iso88599
      | `Set_jis0201
      | `Set_jis0208
      | `Set_jis0212
      | `Set_koi8r
      | `Set_ks1001
      | `Set_macroman
      | `Set_unicode
      | `Set_usascii
      | `Set_windows1250
      | `Set_windows1251
      | `Set_windows1252
      | `Set_windows1253
      | `Set_windows1254
      | `Set_windows1255
      | `Set_windows1256
      | `Set_windows1257
      | `Set_windows1258 ]
  val encoding_of_string : string -> Netconversion.encoding
  val string_of_encoding : Netconversion.encoding -> string
  val is_ascii_compatible : Netconversion.encoding -> bool
  val is_single_byte : Netconversion.encoding -> bool
  val same_encoding :
    Netconversion.encoding -> Netconversion.encoding -> bool
  val byte_order_mark : Netconversion.encoding -> string
  val makechar : Netconversion.encoding -> int -> string
  val ustring_of_uchar : Netconversion.encoding -> int -> string
  val to_unicode : Netconversion.charset -> int -> int
  val from_unicode : Netconversion.charset -> int -> int
  val available_input_encodings : unit -> Netconversion.encoding list
  val available_output_encodings : unit -> Netconversion.encoding list
  val user_encoding : unit -> Netconversion.encoding option
  val win32_code_pages : (int * Netconversion.encoding) list
  val convert :
    ?subst:(int -> string) ->
    in_enc:Netconversion.encoding ->
    out_enc:Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> string -> string
  val convert_tstring :
    ?subst:(int -> string) ->
    in_enc:Netconversion.encoding ->
    out_enc:Netconversion.encoding ->
    out_kind:'Netstring_tstring.tstring_kind ->
    ?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> 's
  val convert_poly :
    in_ops:'s1 Netstring_tstring.tstring_ops ->
    out_kind:'s2 Netstring_tstring.tstring_kind ->
    ?subst:(int -> string) ->
    in_enc:Netconversion.encoding ->
    out_enc:Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> 's1 -> 's2
  val recode :
    in_enc:Netconversion.encoding ->
    in_buf:string ->
    in_pos:int ->
    in_len:int ->
    out_enc:Netconversion.encoding ->
    out_buf:Bytes.t ->
    out_pos:int ->
    out_len:int ->
    max_chars:int ->
    subst:(int -> string) -> int * int * Netconversion.encoding
  val recode_tstring :
    in_enc:Netconversion.encoding ->
    in_buf:Netsys_types.tstring ->
    in_pos:int ->
    in_len:int ->
    out_enc:Netconversion.encoding ->
    out_buf:Bytes.t ->
    out_pos:int ->
    out_len:int ->
    max_chars:int ->
    subst:(int -> string) -> int * int * Netconversion.encoding
  val recode_poly :
    in_ops:'Netstring_tstring.tstring_ops ->
    in_enc:Netconversion.encoding ->
    in_buf:'->
    in_pos:int ->
    in_len:int ->
    out_enc:Netconversion.encoding ->
    out_buf:Bytes.t ->
    out_pos:int ->
    out_len:int ->
    max_chars:int ->
    subst:(int -> string) -> int * int * Netconversion.encoding
  class conversion_pipe :
    ?subst:(int -> string) ->
    in_enc:Netconversion.encoding ->
    out_enc:Netconversion.encoding -> unit -> Netchannels.io_obj_channel
  type 's poly_cursor
  type cursor = string Netconversion.poly_cursor
  exception End_of_string
  exception Cursor_out_of_range
  exception Partial_character
  exception Byte_order_mark
  val create_cursor :
    ?range_pos:int ->
    ?range_len:int ->
    ?initial_rel_pos:int ->
    Netconversion.encoding -> string -> Netconversion.cursor
  val create_poly_cursor :
    ?range_pos:int ->
    ?range_len:int ->
    ?initial_rel_pos:int ->
    Netconversion.encoding ->
    'Netstring_tstring.tstring_ops -> '-> 'Netconversion.poly_cursor
  type 'a with_cursor_fun = {
    with_cursor_fun :
      's.
        'Netstring_tstring.tstring_ops ->
        'Netconversion.poly_cursor -> 'a;
  }
  val with_tstring_cursor :
    ?range_pos:int ->
    ?range_len:int ->
    ?initial_rel_pos:int ->
    Netconversion.encoding ->
    Netsys_types.tstring -> 'Netconversion.with_cursor_fun -> 'a
  val reinit_cursor :
    ?range_pos:int ->
    ?range_len:int ->
    ?initial_rel_pos:int ->
    ?enc:Netconversion.encoding -> '-> 'Netconversion.poly_cursor -> unit
  val copy_cursor :
    ?enc:Netconversion.encoding ->
    'Netconversion.poly_cursor -> 'Netconversion.poly_cursor
  val cursor_target : 'Netconversion.poly_cursor -> 's
  val cursor_range : 'Netconversion.poly_cursor -> int * int
  val cursor_initial_rel_pos : 'Netconversion.poly_cursor -> int
  val cursor_char_count : 'Netconversion.poly_cursor -> int
  val cursor_pos : 'Netconversion.poly_cursor -> int
  val uchar_at : 'Netconversion.poly_cursor -> int
  val cursor_byte_length : 'Netconversion.poly_cursor -> int
  val cursor_at_end : 'Netconversion.poly_cursor -> bool
  val move : ?num:int -> 'Netconversion.poly_cursor -> unit
  val cursor_encoding :
    'Netconversion.poly_cursor -> Netconversion.encoding
  val cursor_blit :
    'Netconversion.poly_cursor -> int array -> int -> int -> int
  val cursor_blit_maxlen : 'Netconversion.poly_cursor -> int
  val cursor_blit_positions :
    'Netconversion.poly_cursor -> int array -> int -> int -> int
  val ustring_length :
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> string -> int
  val ustring_length_ts :
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> int
  val ustring_length_poly :
    'Netstring_tstring.tstring_ops ->
    Netconversion.encoding -> ?range_pos:int -> ?range_len:int -> '-> int
  val ustring_iter :
    Netconversion.encoding ->
    (int -> unit) -> ?range_pos:int -> ?range_len:int -> string -> unit
  val ustring_iter_ts :
    Netconversion.encoding ->
    (int -> unit) ->
    ?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> unit
  val ustring_iter_poly :
    'Netstring_tstring.tstring_ops ->
    Netconversion.encoding ->
    (int -> unit) -> ?range_pos:int -> ?range_len:int -> '-> unit
  val ustring_map :
    Netconversion.encoding ->
    (int -> int list) -> ?range_pos:int -> ?range_len:int -> string -> string
  val ustring_map_ts :
    Netconversion.encoding ->
    (int -> int list) ->
    ?range_pos:int ->
    ?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
  val ustring_map_poly :
    'Netstring_tstring.tstring_ops ->
    'Netstring_tstring.tstring_kind ->
    Netconversion.encoding ->
    (int -> int list) -> ?range_pos:int -> ?range_len:int -> '-> 't
  val ustring_to_lower :
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> string -> string
  val ustring_to_lower_ts :
    Netconversion.encoding ->
    ?range_pos:int ->
    ?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
  val ustring_to_lower_poly :
    'Netstring_tstring.tstring_ops ->
    'Netstring_tstring.tstring_kind ->
    Netconversion.encoding -> ?range_pos:int -> ?range_len:int -> '-> 't
  val ustring_to_upper :
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> string -> string
  val ustring_to_upper_ts :
    Netconversion.encoding ->
    ?range_pos:int ->
    ?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
  val ustring_to_upper_poly :
    'Netstring_tstring.tstring_ops ->
    'Netstring_tstring.tstring_kind ->
    Netconversion.encoding -> ?range_pos:int -> ?range_len:int -> '-> 't
  val ustring_to_title :
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> string -> string
  val ustring_to_title_ts :
    Netconversion.encoding ->
    ?range_pos:int ->
    ?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
  val ustring_to_title_poly :
    'Netstring_tstring.tstring_ops ->
    'Netstring_tstring.tstring_kind ->
    Netconversion.encoding -> ?range_pos:int -> ?range_len:int -> '-> 't
  val ustring_sub :
    Netconversion.encoding ->
    int -> int -> ?range_pos:int -> ?range_len:int -> string -> string
  val ustring_sub_ts :
    Netconversion.encoding ->
    int ->
    int ->
    ?range_pos:int ->
    ?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
  val ustring_sub_poly :
    'Netstring_tstring.tstring_ops ->
    'Netstring_tstring.tstring_kind ->
    Netconversion.encoding ->
    int -> int -> ?range_pos:int -> ?range_len:int -> '-> 't
  val ustring_compare :
    Netconversion.encoding ->
    (int -> int -> int) ->
    ?range_pos:int ->
    ?range_len:int ->
    string -> ?range_pos:int -> ?range_len:int -> string -> int
  val ustring_compare_ts :
    Netconversion.encoding ->
    (int -> int -> int) ->
    ?range_pos:int ->
    ?range_len:int ->
    Netsys_types.tstring ->
    ?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> int
  val ustring_compare_poly :
    's1 Netstring_tstring.tstring_ops ->
    's2 Netstring_tstring.tstring_ops ->
    Netconversion.encoding ->
    (int -> int -> int) ->
    ?range_pos:int ->
    ?range_len:int -> 's1 -> ?range_pos:int -> ?range_len:int -> 's2 -> int
  val code_cmp : int -> int -> int
  val ci_code_cmp : int -> int -> int
  val uarray_of_ustring :
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> string -> int array
  val uarray_of_ustring_ts :
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> int array
  val uarray_of_ustring_poly :
    'Netstring_tstring.tstring_ops ->
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> '-> int array
  val ustring_of_uarray :
    ?subst:(int -> string) ->
    Netconversion.encoding -> ?pos:int -> ?len:int -> int array -> string
  exception Malformed_code_at of int
  val verify :
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> string -> unit
  val verify_ts :
    Netconversion.encoding ->
    ?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> unit
  val verify_poly :
    'Netstring_tstring.tstring_ops ->
    Netconversion.encoding -> ?range_pos:int -> ?range_len:int -> '-> unit
  val big_slice : int
  type poly_reader = {
    read :
      's.
        'Netstring_tstring.tstring_ops ->
        int array ->
        int array -> '-> int -> int -> int * int * Netconversion.encoding;
  }
  val read_iso88591_ref :
    (int -> Netconversion.encoding -> Netconversion.poly_reader)
    Pervasives.ref
  val read_iso88591 :
    int -> Netconversion.encoding -> Netconversion.poly_reader
  val read_utf8_ref : (bool -> Netconversion.poly_reader) Pervasives.ref
  val read_utf8 : bool -> Netconversion.poly_reader
  val internal_name : Netconversion.charset -> string
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.http_environment-c.html0000644000175000017500000004411512731530351024425 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_environment

Class Nethttpd_reactor.http_environment

class http_environment : #http_processor_config -> string -> string -> Nethttp.protocol -> Nethttp.http_header -> Unix.sockaddr -> Unix.sockaddr -> Netchannels.in_obj_channel -> int64 Pervasives.ref -> Netchannels.out_obj_channel -> Nethttpd_types.output_state Pervasives.ref -> Nethttpd_kernel.http_response -> (unit -> unit) -> bool Pervasives.ref -> int64 -> Nettls_support.tls_session_props option -> internal_environment
For private use only

ocamlnet-4.1.2/doc/html-main/type_Netsys_pollset.html0000644000175000017500000004434712731530351021371 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset sig
  class type pollset =
    object
      method add : Unix.file_descr -> Netsys_posix.poll_req_events -> unit
      method cancel_wait : bool -> unit
      method dispose : unit -> unit
      method find : Unix.file_descr -> Netsys_posix.poll_req_events
      method remove : Unix.file_descr -> unit
      method wait :
        float ->
        (Unix.file_descr * Netsys_posix.poll_req_events *
         Netsys_posix.poll_act_events)
        list
    end
end
ocamlnet-4.1.2/doc/html-main/Netfs.local_file-c.html0000644000175000017500000004237512731530351020667 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netfs.local_file

Class type Netfs.local_file

class type local_file = object .. end

method filename : string
The filename
method close : unit -> unit
Indicate that we are done with the file
ocamlnet-4.1.2/doc/html-main/Rpc_client.auth_protocol-c.html0000644000175000017500000005133112731530351022453 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.auth_protocol

Class type Rpc_client.auth_protocol

class type auth_protocol = object .. end
An authentication protocol is used for creating an authentication session.

method state : [ `Done of auth_session
| `Emit
| `Error
| `Receive of Netnumber.uint4 ]
The state of the authentication protocol:
  • `Emit: The client needs to emit another token
  • `Receive xid: The client waits for another token (with session identifier xid)
  • `Done session: The protocol is finished and session can be used for authenticating
  • `Error: Something went wrong.

method emit : Netnumber.uint4 ->
Netnumber.uint4 -> Netnumber.uint4 -> Rpc_packer.packed_value
Emits a token for this xid, prog_nr and vers_nr. The returned packed value should have been created with Rpc_packer.pack_value. It is possible that emit is called several times with different xid values. In this case, the returned packed value should be identical except that the new xid is included in the message.

After emission, the state must change to `Receive.

method receive : Rpc_packer.packed_value -> unit
Receive a token for the xid announced in state. The passed packed value is the full RPC message. The message may also contain a server error - which may be processed by the protocol, or which may cause the reaction that receive raises an Rpc.Rpc_server exception.

After receive, the state can change to `Emit, `Done or `Error. The latter is obligatory when receive raises an exception. It is also possible not to raise an exception but silently switch to `Error.

Design limitation: there is right now no way to indicate that the next authentication method should be used instead.

method gssapi_props : Netsys_gssapi.client_props option
Properties of the GSSAPI session (if existing)
method destroy : unit -> unit
Destroys the session (e.g. delete the GSSAPI context)
method auth_method : auth_method
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.delete.html0000644000175000017500000004067312731530351022565 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.delete string -> Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.async_in_channel_engine.html0000644000175000017500000004340412731530351026612 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.async_in_channel_engine object
  method abort : unit -> unit
  method can_input : bool
  method close_in : unit -> unit
  method event_system : Unixqueue.event_system
  method input : Bytes.t -> int -> int -> int
  method pos_in : int
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : (unit engine -> bool) -> unit
  method state : unit engine_state
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.multiplex_controller-c.html0000644000175000017500000005172412731530351025443 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.multiplex_controller

Class type Uq_engines_compat.multiplex_controller

class type multiplex_controller = object .. end

method alive : bool
method mem_supported : bool
method event_system : Unixqueue.event_system
method tls_session_props : Nettls_support.tls_session_props option
method tls_session : (string * string) option
method tls_stashed_endpoint : unit -> exn
method reading : bool
method start_reading : ?peek:(unit -> unit) ->
when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
method start_mem_reading : ?peek:(unit -> unit) ->
when_done:(exn option -> int -> unit) ->
Netsys_mem.memory -> int -> int -> unit
method cancel_reading : unit -> unit
method writing : bool
method start_writing : when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
method start_mem_writing : when_done:(exn option -> int -> unit) ->
Netsys_mem.memory -> int -> int -> unit
method supports_half_open_connection : bool
method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit
method cancel_writing : unit -> unit
method read_eof : bool
method wrote_eof : bool
method shutting_down : bool
method start_shutting_down : ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
method cancel_shutting_down : unit -> unit
method inactivate : unit -> unit
ocamlnet-4.1.2/doc/html-main/type_Netmime.wrap_mime_body_ro.html0000644000175000017500000004101112731530351023415 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.wrap_mime_body_ro #Netmime.mime_body_ro -> Netmime.mime_bodyocamlnet-4.1.2/doc/html-main/type_Uq_engines.client_endpoint_connector.html0000644000175000017500000004154512731530351025663 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.client_endpoint_connector object
  method connect :
    Uq_engines.connect_address ->
    Unixqueue.event_system -> Uq_engines.connect_status Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/Netchannels_crypto.html0000644000175000017500000005454712731530351021146 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto

Module Netchannels_crypto

module Netchannels_crypto: sig .. end
Crypto extensions for Netchannels


TLS


class type tls_channel = object .. end
A TLS channel is a layer on top of a bidirectional channel that adds the TLS protocol.
class tls_layer : ?start_pos_in:int -> ?start_pos_out:int -> ?resume:string -> role:[ `Client | `Server ] -> rd:Netchannels.raw_in_channel -> wr:Netchannels.raw_out_channel -> peer_name:string option -> Netsys_crypto_types.tls_config -> tls_channel
Adds TLS security to an already established connection, here made available as separate channels for input and output.
class tls_endpoint : ?start_pos_in:int -> ?start_pos_out:int -> ?resume:string -> role:[ `Client | `Server ] -> peer_name:string option -> Unix.file_descr -> Netsys_crypto_types.tls_config -> tls_channel
This class is slightly more efficient than tls_layer, and to preferred if you have direct access to the file descriptors.

Symmetric Cryptography


class type crypto_out_filter = object .. end
Encrypt or decrypt data while writing to a channel
class type crypto_in_filter = object .. end
Encrypt or decrypt data while reading from a channel
val encrypt_out : Netsys_ciphers.cipher_ctx ->
Netchannels.out_obj_channel -> crypto_out_filter
let ch2 = encrypt_out ctx ch1: Writing to ch2 encrypts the data and writes the ciphertext to ch1. Closing ch2 will flush data and close ch1.
val encrypt_in : Netsys_ciphers.cipher_ctx ->
Netchannels.in_obj_channel -> crypto_in_filter
let ch2 = encrypt_in ctx ch1: Reading from ch2 encrypts the data from ch1. Closing ch2 will close ch1.
val decrypt_out : Netsys_ciphers.cipher_ctx ->
Netchannels.out_obj_channel -> crypto_out_filter
let ch2 = decrypt_out ctx ch1: Writing to ch2 decrypts the data and writes the plaintext to ch1. Closing ch2 will flush data and close ch1.
val decrypt_in : Netsys_ciphers.cipher_ctx ->
Netchannels.in_obj_channel -> crypto_in_filter
let ch2 = decrypt_in ctx ch1: Reading from ch2 decrypts the data from ch1. Closing ch2 will close ch1.
ocamlnet-4.1.2/doc/html-main/type_Uq_multiplex.html0000644000175000017500000010001012731530351021006 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_multiplex sig
  class type multiplex_controller =
    object
      method alive : bool
      method cancel_reading : unit -> unit
      method cancel_shutting_down : unit -> unit
      method cancel_writing : unit -> unit
      method event_system : Unixqueue.event_system
      method inactivate : unit -> unit
      method mem_supported : bool
      method read_eof : bool
      method reading : bool
      method shutting_down : bool
      method start_mem_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_mem_writing :
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_shutting_down :
        ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
      method start_writing :
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_writing_eof :
        when_done:(exn option -> unit) -> unit -> unit
      method supports_half_open_connection : bool
      method tls_session : (string * string) option
      method tls_session_props : Nettls_support.tls_session_props option
      method tls_stashed_endpoint : unit -> exn
      method writing : bool
      method wrote_eof : bool
    end
  class type datagram_multiplex_controller =
    object
      method alive : bool
      method cancel_reading : unit -> unit
      method cancel_shutting_down : unit -> unit
      method cancel_writing : unit -> unit
      method event_system : Unixqueue.event_system
      method inactivate : unit -> unit
      method mem_supported : bool
      method read_eof : bool
      method reading : bool
      method received_from : Unix.sockaddr
      method send_to : Unix.sockaddr -> unit
      method shutting_down : bool
      method start_mem_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_mem_writing :
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_shutting_down :
        ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
      method start_writing :
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_writing_eof :
        when_done:(exn option -> unit) -> unit -> unit
      method supports_half_open_connection : bool
      method tls_session : (string * string) option
      method tls_session_props : Nettls_support.tls_session_props option
      method tls_stashed_endpoint : unit -> exn
      method writing : bool
      method wrote_eof : bool
    end
  exception Mem_not_supported
  val create_multiplex_controller_for_connected_socket :
    ?close_inactive_descr:bool ->
    ?preclose:(unit -> unit) ->
    ?supports_half_open_connection:bool ->
    ?timeout:float * exn ->
    Unix.file_descr ->
    Unixqueue.unix_event_system -> Uq_multiplex.multiplex_controller
  val create_multiplex_controller_for_datagram_socket :
    ?close_inactive_descr:bool ->
    ?preclose:(unit -> unit) ->
    ?timeout:float * exn ->
    Unix.file_descr ->
    Unixqueue.unix_event_system -> Uq_multiplex.datagram_multiplex_controller
  val tls_multiplex_controller :
    ?resume:string ->
    ?on_handshake:(Uq_multiplex.multiplex_controller -> unit) ->
    role:[ `Client | `Server ] ->
    peer_name:string option ->
    (module Netsys_crypto_types.TLS_CONFIG->
    Uq_multiplex.multiplex_controller -> Uq_multiplex.multiplex_controller
  val restore_tls_multiplex_controller :
    ?on_handshake:(Uq_multiplex.multiplex_controller -> unit) ->
    exn ->
    (module Netsys_crypto_types.TLS_CONFIG->
    Uq_multiplex.multiplex_controller -> Uq_multiplex.multiplex_controller
end
ocamlnet-4.1.2/doc/html-main/Netplex_cenv.VAR_TYPE.html0000644000175000017500000004325512731530351021220 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.VAR_TYPE

Module type Netplex_cenv.VAR_TYPE

module type VAR_TYPE = sig .. end
A (monomorphic) type t with two functions get and set accessing the container variables

type t 
val get : string -> t
val set : string -> t -> unit
ocamlnet-4.1.2/doc/html-main/Netx509.directory_name-c.html0000644000175000017500000004471212731530351021674 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.directory_name

Class type Netx509.directory_name

class type directory_name = object .. end
Directory names are also known as distinguished names. These are the o=foo,ou=foounit,c=country strings that are used to name certificates.

method name : (oid * Netasn1.Value.value) list list
This is the raw version of the DN: a sequence of relative DNs, and a relative DN is a set of (type,value) pairs. The types are things like cn, country, organization, ...
method eq_name : (oid * Netasn1.Value.value) list list
The name normalized for equality comparisons. In particular, PrintableString values are converted to uppercase, as well as emailAddress attributes. Also, the inner list is sorted by oid.
method string : string
The DN as string (RFC 4514)
method eq_string : string
The eq_name converted to string
ocamlnet-4.1.2/doc/html-main/type_Netglob.local_user_info.html0000644000175000017500000004066412731530351023074 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.local_user_info unit -> Netglob.user_infoocamlnet-4.1.2/doc/html-main/Netcgi.simple_argument-c.html0000644000175000017500000004230512731530351022114 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.simple_argument

Class Netcgi.simple_argument

class simple_argument : ?ro:bool -> string -> string -> rw_cgi_argument
Deprecated.Use Netcgi.Argument.simple instead.
Old deprecated simple argument class.

ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.fmap_engine.html0000644000175000017500000004163612731530351024247 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.fmap_engine '#Uq_engines_compat.engine ->
('Uq_engines_compat.final_state -> 'Uq_engines_compat.final_state) ->
['b] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/type_Rpc_server.html0000644000175000017500000012774112731530351020454 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server sig
  exception Connection_lost
  type t
  type session
  type connection_id
  type connector =
      Localhost of int
    | Portmapped
    | Internet of (Unix.inet_addr * int)
    | Unix of string
    | W32_pipe of string
    | Descriptor of Unix.file_descr
    | Dynamic_descriptor of (unit -> Unix.file_descr)
  type binding_sync = {
    sync_name : string;
    sync_proc : Rpc_server.t -> Netxdr.xdr_value -> Netxdr.xdr_value;
  }
  type binding_async = {
    async_name : string;
    async_invoke :
      Rpc_server.t -> Rpc_server.session -> Netxdr.xdr_value -> unit;
  }
  type binding =
      Sync of Rpc_server.binding_sync
    | Async of Rpc_server.binding_async
  val connector_of_sockaddr : Unix.sockaddr -> Rpc_server.connector
  val connector_of_socksymbol :
    Netsockaddr.socksymbol -> Rpc_server.connector
  val create :
    ?program_number:Netnumber.uint4 ->
    ?version_number:Netnumber.uint4 ->
    Unixqueue.event_system ->
    Rpc_server.connector ->
    Rpc.protocol ->
    Rpc.mode ->
    Rpc_program.t -> Rpc_server.binding list -> int -> Rpc_server.t
  class type socket_config =
    object
      method listen_options : Uq_engines.listen_options
      method multiplexing :
        dbg_name:string Pervasives.ref ->
        close_inactive_descr:bool ->
        Rpc.protocol ->
        Unix.file_descr ->
        Unixqueue.event_system ->
        Rpc_transport.rpc_multiplex_controller Uq_engines.engine
    end
  val default_socket_config : Rpc_server.socket_config
  class default_socket_config : socket_config
  val tls_socket_config :
    (module Netsys_crypto_types.TLS_CONFIG-> Rpc_server.socket_config
  class tls_socket_config :
    (module Netsys_crypto_types.TLS_CONFIG-> socket_config
  type internal_pipe = Netxdr.xdr_value Netsys_polypipe.polypipe
  type internal_socket = Netxdr.xdr_value Netsys_polysocket.polyserver
  type mode2 =
      [ `Dummy of Rpc.protocol
      | `Internal_endpoint of
          Rpc_server.internal_pipe * Rpc_server.internal_pipe
      | `Internal_socket of Rpc_server.internal_socket
      | `Multiplexer_endpoint of Rpc_transport.rpc_multiplex_controller
      | `Socket of
          Rpc.protocol * Rpc_server.connector * Rpc_server.socket_config
      | `Socket_endpoint of Rpc.protocol * Unix.file_descr ]
  val create2 : Rpc_server.mode2 -> Unixqueue.event_system -> Rpc_server.t
  val bind :
    ?program_number:Netnumber.uint4 ->
    ?version_number:Netnumber.uint4 ->
    ?pm_continue:bool ->
    Rpc_program.t -> Rpc_server.binding list -> Rpc_server.t -> unit
  val unbind :
    ?program_number:Netnumber.uint4 ->
    ?version_number:Netnumber.uint4 -> Rpc_program.t -> Rpc_server.t -> unit
  val bound_programs : Rpc_server.t -> Rpc_program.t list
  val get_event_system : Rpc_server.session -> Unixqueue.event_system
  val get_connection_id : Rpc_server.session -> Rpc_server.connection_id
  val get_xid : Rpc_server.session -> Netnumber.uint4
  val get_socket_name : Rpc_server.session -> Unix.sockaddr
  val get_peer_name : Rpc_server.session -> Unix.sockaddr
  val get_conn_socket_name : Rpc_server.connection_id -> Unix.sockaddr
  val get_conn_peer_name : Rpc_server.connection_id -> Unix.sockaddr
  val get_server : Rpc_server.session -> Rpc_server.t
  val get_main_socket_name : Rpc_server.t -> Unix.sockaddr
  val get_protocol : Rpc_server.t -> Rpc.protocol
  val get_srv_event_system : Rpc_server.t -> Unixqueue.unix_event_system
  val get_last_proc_info : Rpc_server.t -> string
  val is_dummy : Rpc_server.t -> bool
  val get_tls_session_props :
    Rpc_server.session -> Nettls_support.tls_session_props option
  val get_gssapi_props :
    Rpc_server.session -> Netsys_gssapi.server_props option
  type rule =
      [ `Accept
      | `Accept_limit_length of int * Rpc_server.rule
      | `Deny
      | `Drop
      | `Reject
      | `Reject_with of Rpc.server_error ]
  val set_session_filter :
    Rpc_server.t -> (Rpc_transport.sockaddr -> Rpc_server.rule) -> unit
  val set_session_filter_2 :
    Rpc_server.t ->
    (Rpc_transport.sockaddr -> Rpc_server.connection_id -> Rpc_server.rule) ->
    unit
  val set_mstring_factories :
    Rpc_server.t -> Netxdr_mstring.named_mstring_factories -> unit
  val reply : Rpc_server.session -> Netxdr.xdr_value -> unit
  val reply_error : Rpc_server.session -> Rpc.server_error -> unit
  val set_exception_handler : Rpc_server.t -> (exn -> string -> unit) -> unit
  val set_onclose_action :
    Rpc_server.t -> (Rpc_server.connection_id -> unit) -> unit
  val set_timeout : Rpc_server.t -> float -> unit
  val stop_server : ?graceful:bool -> Rpc_server.t -> unit
  val stop_connection : Rpc_server.t -> Rpc_server.connection_id -> unit
  type auth_result =
      Auth_positive of
        (string * string * string * Netxdr.encoder option *
         Netxdr.decoder option * Netsys_gssapi.server_props option)
    | Auth_negative of Rpc.server_error
    | Auth_reply of (Netxdr_mstring.mstring list * string * string)
    | Auth_drop
  exception Late_drop
  type auth_peeker =
      [ `None
      | `Peek_descriptor of Unix.file_descr -> string option
      | `Peek_multiplexer of
          Rpc_transport.rpc_multiplex_controller -> string option ]
  class type auth_details =
    object
      method client_addr : Unix.sockaddr option
      method credential : string * string
      method frame_len : int
      method message : Rpc_packer.packed_value
      method procedure : Netnumber.uint4
      method program : Netnumber.uint4
      method server_addr : Unix.sockaddr option
      method transport_user : string option
      method verifier : string * string
      method version : Netnumber.uint4
      method xid : Netnumber.uint4
    end
  class type auth_method =
    object
      method authenticate :
        Rpc_server.t ->
        Rpc_server.connection_id ->
        Rpc_server.auth_details -> (Rpc_server.auth_result -> unit) -> unit
      method flavors : string list
      method invalidate : unit -> unit
      method invalidate_connection : Rpc_server.connection_id -> unit
      method name : string
      method peek : Rpc_server.auth_peeker
    end
  val set_auth_methods : Rpc_server.t -> Rpc_server.auth_method list -> unit
  val auth_none : Rpc_server.auth_method
  val auth_too_weak : Rpc_server.auth_method
  val auth_transport : Rpc_server.auth_method
  val get_user : Rpc_server.session -> string
  val get_auth_method : Rpc_server.session -> Rpc_server.auth_method
  val xdr_ctx : Rpc_server.t -> Netxdr.ctx
  val verbose : bool -> unit
  val detach : Rpc_server.t -> unit
  val set_debug_name : Rpc_server.t -> string -> unit
  val get_debug_name : Rpc_server.t -> string
  module Debug :
    sig
      val enable : bool Pervasives.ref
      val enable_ctrace : bool Pervasives.ref
      val enable_ptrace : bool Pervasives.ref
      val ptrace_verbosity : Rpc_util.verbosity Pervasives.ref
      val disable_for_server : Rpc_server.t -> unit
    end
end
ocamlnet-4.1.2/doc/html-main/Netsys_sasl.html0000644000175000017500000004466012731530351017606 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl

Module Netsys_sasl

module Netsys_sasl: sig .. end
User interface for SASL mechanisms

type sasl_mechanism = (module Netsys_sasl_types.SASL_MECHANISM) 
type credentials = (string * string * (string * string) list) list 
Credentials are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

        [ "password", "ThE sEcReT", [] ]
      

module Info: sig .. end
module Client: sig .. end
module Server: sig .. end
ocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.modify_http_processor_config-c.html0000644000175000017500000004524412731530351027000 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.modify_http_processor_config

Class Nethttpd_reactor.modify_http_processor_config

class modify_http_processor_config : ?modify_http_protocol_config:Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config -> ?config_timeout_next_request:float -> ?config_timeout:float -> ?config_cgi:Netcgi.config -> ?config_error_response:Nethttpd_types.error_response_params -> string -> ?config_log_error:Nethttpd_types.request_info -> string -> unit -> ?config_log_access:Nethttpd_types.full_info -> unit -> ?config_tls_cert_props:bool -> ?config_tls_remote_user:bool -> http_processor_config -> http_processor_config
Modifies the passed config object as specified by the optional arguments.

modify_http_protocol_config: This function can be used to modify the parts of the config object that are inherited from http_protocol_config. For example:

        let new_cfg =
          new modify_http_processor_config
            ~modify_http_protocol_config:
               (new Nethttpd_kernel.modify_http_protocol_config
                  ~config_suppress_broken_pipe:true)
            ~config_timeout:15.0
            old_cfg
      


ocamlnet-4.1.2/doc/html-main/type_Nethttpd_kernel.lingering_close.html0000644000175000017500000004200412731530351024622 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.lingering_close ?preclose:(unit -> unit) ->
Unix.file_descr ->
object
  method cycle : ?block:bool -> unit -> unit
  method fd : Unix.file_descr
  method lingering : bool
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.SHA1_PLUS.html0000644000175000017500000004057112731530351023465 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SHA1_PLUS PROFILEocamlnet-4.1.2/doc/html-main/Uq_transfer.output_async_mplex-c.html0000644000175000017500000004567312731530351023756 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.output_async_mplex

Class Uq_transfer.output_async_mplex

class output_async_mplex : ?onclose:[ `Ignore | `Write_eof ] -> ?onshutdown:onshutdown_out_spec -> ?buffer_size:int -> Uq_engines.multiplex_controller -> async_out_channel_engine
Creates an asynchronous output channel writing to the multiplex controller (see also output_async_descr for the corresponding class writing to a single descriptor).

onclose: What to do when the close_out method is invoked. Defaults to `Ignore. `Write_eof means to write the EOF marker. Anyway, after doing the close action, the multiplex controller is shutdown.

onshutdown: What to do when all data (and optionally, the EOF marker) have been written. It is also invoked in case of I/O errors. The default is `Ignore. The value `Initiate_shutdown means that it is started to shutdown the socket. The success of this action is not waited upon, however. One can also pass `Action f in which case the function f is called with this object, the multiplex controller, and the proposed next state as arguments. By checking the proposed next state the function can see why the shutdown function was called.

buffer_size: The size of the internal buffer. By default unlimited.

Note that the engine is done when the output channel is closed. The socket is not shut down, and the underlying file descriptor is not closed! You can define the shutdown callback to do something in this case.


ocamlnet-4.1.2/doc/html-main/type_Netchannels.raw_in_channel_delegation.html0000644000175000017500000004107712731530351025742 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_in_channel_delegation ?close:bool -> Netchannels.raw_in_channel -> Netchannels.raw_in_channelocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi_env.cgi_environment.html0000644000175000017500000005525112731530351026440 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_env.cgi_environment object
  method cgi_auth_type : string
  method cgi_gateway_interface : string
  method cgi_https : bool
  method cgi_path_info : string
  method cgi_path_translated : string
  method cgi_properties : (string * string) list
  method cgi_property : ?default:string -> string -> string
  method cgi_query_string : string
  method cgi_remote_addr : string
  method cgi_remote_host : string
  method cgi_remote_ident : string
  method cgi_remote_user : string
  method cgi_request_method : string
  method cgi_request_uri : string
  method cgi_script_name : string
  method cgi_server_name : string
  method cgi_server_port : int option
  method cgi_server_protocol : string
  method cgi_server_software : string
  method config : Netcgi1_compat.Netcgi_env.cgi_config
  method cookies : (string * string) list
  method input_ch : Netchannels.in_obj_channel
  method input_content_length : int
  method input_content_type : string * (string * Netmime_string.s_param) list
  method input_content_type_string : string
  method input_header : Netmime.mime_header
  method input_header_field : ?default:string -> string -> string
  method input_header_fields : (string * string) list
  method input_state : Netcgi1_compat.Netcgi_env.input_state
  method log_error : string -> unit
  method multiple_input_header_field : string -> string list
  method multiple_output_header_field : string -> string list
  method output_ch : Netchannels.out_obj_channel
  method output_header : Netmime.mime_header
  method output_header_field : ?default:string -> string -> string
  method output_header_fields : (string * string) list
  method output_state : Netcgi1_compat.Netcgi_env.output_state
  method protocol : Netcgi1_compat.Netcgi_env.protocol
  method send_output_header : unit -> unit
  method set_input_state : Netcgi1_compat.Netcgi_env.input_state -> unit
  method set_multiple_output_header_field : string -> string list -> unit
  method set_output_header_field : string -> string -> unit
  method set_output_header_fields : (string * string) list -> unit
  method set_output_state : Netcgi1_compat.Netcgi_env.output_state -> unit
  method set_status : Nethttp.http_status -> unit
  method user_agent : string
end
ocamlnet-4.1.2/doc/html-main/type_Netasn1.Type_name.html0000644000175000017500000004674412731530351021576 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netasn1.Type_name sig
  type type_name =
      Bool
    | Integer
    | Enum
    | Real
    | Bitstring
    | Octetstring
    | Null
    | Seq
    | Set
    | OID
    | ROID
    | ObjectDescriptor
    | External
    | Embedded_PDV
    | NumericString
    | PrintableString
    | TeletexString
    | VideotexString
    | VisibleString
    | IA5String
    | GraphicString
    | GeneralString
    | UniversalString
    | BMPString
    | UTF8String
    | CharString
    | UTCTime
    | GeneralizedTime
end
ocamlnet-4.1.2/doc/html-main/Netxdr_mstring.mstring_factory-c.html0000644000175000017500000004567512731530351023746 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netxdr_mstring.mstring_factory

Class type Netxdr_mstring.mstring_factory

class type mstring_factory = object .. end
The object creating new mstring objects

method create_from_string : string -> int -> int -> bool -> mstring
create_from_string s pos len must_copy: Creates the mstring from the sub string of s starting at pos with length len

The must_copy flag is ignored (and exists for backwards compatibility).

method create_from_bytes : Bytes.t -> int -> int -> bool -> mstring
create_from_string s pos len must_copy: Creates the mstring from the sub string of s starting at pos with length len

If must_copy the mstring object must create a copy. Otherwise it can just keep the string passed in.

method create_from_memory : Netsys_mem.memory -> int -> int -> bool -> mstring
create_from_memory m pos len must_copy: Creates the mstring from the sub string of m starting at pos with length len

If must_copy the mstring object must create a copy. Otherwise it can just keep the memory passed in.

ocamlnet-4.1.2/doc/html-main/Netmech_plain_sasl.PLAIN.html0000644000175000017500000011042012731530351021715 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_plain_sasl.PLAIN

Module Netmech_plain_sasl.PLAIN

module PLAIN: Netsys_sasl_types.SASL_MECHANISM 
The PLAIN SASL mechanism (RFC 4616).

Key facts:

  • This mechanism sends user name, authorization name and password as cleartext
  • There is no support for channel binding within the mechanism.
  • It is insecure, and should only be used over channels that are otherwise secured.
Parameters:
  • Both create_client_session and create_server_session accept the boolean parameter "mutual". If true, however, authentication fails immediately, as mutual authentication cannot be supported.
  • The same is true for the boolean parameter "secure", because PLAIN is insecure.
As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of PLAIN should pass user names and passwords through Netsaslprep.saslprep.

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.options.html0000644000175000017500000004067412731530351023017 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.options string -> Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Uq_engines_compat.engine-c.html0000644000175000017500000004362212731530351022420 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.engine

Class type Uq_engines_compat.engine

class type ['t] engine = object .. end

method state : 't engine_state
method abort : unit -> unit
method request_notification : (unit -> bool) -> unit
method request_proxy_notification : ('t engine -> bool) -> unit
method event_system : Unixqueue.event_system
ocamlnet-4.1.2/doc/html-main/Uq_io.html0000644000175000017500000012643112731530351016350 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_io

Module Uq_io

module Uq_io: sig .. end
Unified engines for stream I/O

type in_buffer 
type out_buffer 
Buffers that can be attached to a device to get buffered I/O
type in_device = [ `Async_in of Uq_engines.async_in_channel * Unixqueue.event_system
| `Buffer_in of in_buffer
| `Count_in of (int -> unit) * in_device
| `Multiplex of Uq_engines.multiplex_controller
| `Polldescr of Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ]
Currently supported devices for input:
  • `Polldescr(st,fd,esys): The poll system call is used with file descriptor fd to wait for incoming data. The event system esys is the underlying event queue. This works well for pipes, sockets etc. but not for normal files. The style st can be obtained from fd via Netsys.get_fd_style.
  • `Multiplex mplex: The multiplex controller mplex is used as device.
  • `Buffer buf: Data comes from the buffer buf (which in turn is connected with a second device)
  • `Count_in(f,d): Data is read from d, and every time a few bytes n are read the function f n is called (which may raise an exception)
Generally, it is not well supported to read in parallel several times from the same device.
type out_device = [ `Async_out of Uq_engines.async_out_channel * Unixqueue.event_system
| `Buffer_out of out_buffer
| `Count_out of (int -> unit) * out_device
| `Multiplex of Uq_engines.multiplex_controller
| `Polldescr of Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ]
Currently supported devices for output:
  • `Polldescr(fd,esys): The poll system call is used with file descriptor fd to wait until data can be output. The event system esys is the underlying event queue. This works well for pipes, sockets etc. but not for normal files.
  • `Multiplex mplex: The multiplex controller mplex is used as device.
  • `Buffer buf: Data is written to the buffer buf (which in turn is connected with a second device)
  • `Count_out(f,d): Data is written to d, and every time a few bytes n are written the function f n is called (which may raise an exception)
Generally, it is not well supported to write in parallel several times to the same device.
type in_bdevice = [ `Buffer_in of in_buffer ] 
Devices with look-ahead
type io_device = [ `Multiplex of Uq_engines.multiplex_controller
| `Polldescr of Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ]
Bidirectional devices
type string_like = Netsys_types.tbuffer 
The user can pass data buffers that base either on bytes or on bigarrays of char (memory). Note that `Memory is not supported for all devices or device configurations.
val device_supports_memory : [ `Async_in of Uq_engines.async_in_channel * Unixqueue.event_system
| `Async_out of Uq_engines.async_out_channel * Unixqueue.event_system
| `Buffer_in of in_buffer
| `Buffer_out of out_buffer
| `Count_in of (int -> unit) * in_device
| `Count_out of (int -> unit) * out_device
| `Multiplex of Uq_engines.multiplex_controller
| `Polldescr of Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ] ->
bool
Returns whether `Memory buffers are supported
exception Line_too_long
May be raised by Uq_io.input_line_e

Input


val input_e : [< in_device ] ->
Netsys_types.tbuffer -> int -> int -> int Uq_engines.engine
let e = input_e d s pos len: Reads data from d and puts it into the string s starting at pos and with maximum length len. When data is available, the engine e transitions to `Done n where n is the number of actually read bytes.

If len>0 and no bytes can be read because the end is reached, the engine transitions to `Error End_of_file.

val really_input_e : [< in_device ] ->
Netsys_types.tbuffer -> int -> int -> unit Uq_engines.engine
let e = input_e d s pos len: Reads data from d and puts it into the string s starting at pos and with length len. Exactly len bytes are read, and when done, the engine e transitions to `Done ().

If the end of the file is reached before len bytes are read, the engine transitions to `Error End_of_file.

val input_line_e : ?max_len:int -> in_bdevice -> string Uq_engines.engine
let e = input_line_e d: Reads the next line from d and transitions to `Done line when done. Note that this is only supported for a buffered device!

If the end of the file is already reached when this function is called, the engine transitions to `Error End_of_file.

If max_len is set, this is the maximum length of the line (including LF). If exceeded, the engine transitions to `Error Line_too_long.

val input_lines_e : ?max_len:int -> in_bdevice -> string list Uq_engines.engine
let e = input_lines_e d: Reads as many lines from d as can be found in the buffer of d, and transitions to `Done lines. If no complete line is in the buffer, the function extends the buffer and waits until at least one line is added to the buffer (if necessary, this process is repeated).

If the end of the file is already reached when this function is called, the engine transitions to `Error End_of_file. The function never returns an empty list of lines.

input_lines_e is just an optimized version of input_line_e that requires fewer and cheaper blitting operations.

If max_len is set, this is the maximum length of the line (including LF). If exceeded, the engine transitions to `Error Line_too_long.

val eof_as_none : 'a Uq_engines.final_state -> 'a option Uq_engines.final_state
Represents EOF as None. Useful in the combination
 input_e d s p l >> eof_as_none 
and
 input_line_e d >> eof_as_none 
where >> is from Uq_engines.Operators
val in_obj_channel : [< in_device ] -> float -> Netchannels.in_obj_channel
in_obj_channel d timeout: Creates a synchronous channel from the input device.

If the timeout is encountered, this function raises Uq_engines.Timeout.


Output


val output_e : [< out_device ] ->
Netsys_types.tbuffer -> int -> int -> int Uq_engines.engine
let e = output_e d s pos len: Outputs data to d and takes it from the string s starting at pos and with maximum length len. When data is written, the engine e transitions to `Done n where n is the number of actually written bytes.
val really_output_e : [< out_device ] ->
Netsys_types.tbuffer -> int -> int -> unit Uq_engines.engine
let e = really_output_e d s pos len: Outputs data to d and takes it from the string s starting at pos and with length len. When all data is written, the engine e transitions to `Done ().
val output_string_e : [< out_device ] -> string -> unit Uq_engines.engine
let e = output_string_e d s: Outputs the string s to d, and transitions to `Done() when done.
val output_bytes_e : [< out_device ] -> Bytes.t -> unit Uq_engines.engine
let e = output_bytes_e d s: Outputs the bytes s to d, and transitions to `Done() when done.
val output_memory_e : [< out_device ] -> Netsys_mem.memory -> unit Uq_engines.engine
let e = output_string_e d m: Outputs the bigarray m to d, and transitions to `Done() when done.
val output_netbuffer_e : [< out_device ] -> Netbuffer.t -> unit Uq_engines.engine
let e = output_string_e d b: Outputs the contents of b to d, and transitions to `Done() when done.
val write_eof_e : [< out_device ] -> bool Uq_engines.engine
let e = write_eof_e d: For devices supporting half-open connections, this engine writes the EOF marker and transitions to `Done true. For other devices nothing happens, and the engine transitions to `Done false. (In the latter case, the only way to signal EOF is to shut down the device, see below.)

Note that the effect of write_eof_e cannot be buffered. Because of this, the io_buffer flushes all data first (i.e. write_eof_e implies the effect of flush_e).

val copy_e : ?small_buffer:bool ->
?len:int ->
?len64:int64 ->
[< in_device ] -> [< out_device ] -> int64 Uq_engines.engine
let e = copy_e d_in d_out: Copies data from d_in to d_out, and transitions to `Done n when all data is copied (where n are the number of copied bytes). By default, d_in is read until end of file. If len is passed, at most this number of bytes are copied. The length can also be given as int64 in len64.

By setting small_buffer, the copy buffer consists only of a single page. Normally, a bigger buffer is allocated.

val flush_e : [< out_device ] -> unit Uq_engines.engine
let e = flush_e d: If d has an internal buffer, all data is written out to d. If there is no such buffer, this is a no-op. When done, the engine transitions to `Done().
val out_obj_channel : [< out_device ] -> float -> Netchannels.out_obj_channel
out_obj_channel d timeout: Creates a synchronous channel from the output device.

If the timeout is encountered, this function raises Uq_engines.Timeout.

val io_obj_channel : ?start_pos_in:int ->
?start_pos_out:int ->
[< io_device ] -> float -> Netchannels.raw_io_channel
io_obj_channel d timeout: Creates a bidirectional synch channel from d. This channel can be half-closed, and a close_out without close_in triggers write_eof_e on the device.

Shutdown



Shutdown



The shutdown is the last part of the protocol. Although it is often done autonomously by the kernel, this interface supports user-implemented shutdowns (e.g. for SSL).

The shutdown can be skipped, and the device can be inactivated immediately. For some devices, the other side of the I/O stream will then see an error, though.

The shutdown is always for both the input and the output circuit of the device.

val shutdown_e : ?linger:float ->
[< `Async_in of Uq_engines.async_in_channel * Unixqueue.event_system
| `Async_out of Uq_engines.async_out_channel * Unixqueue.event_system
| `Buffer_in of in_buffer
| `Buffer_out of out_buffer
| `Count_in of (int -> unit) * in_device
| `Count_out of (int -> unit) * out_device
| `Multiplex of Uq_engines.multiplex_controller
| `Polldescr of Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ] ->
unit Uq_engines.engine
Performs a regular shutdown of the device. The linger argument may be used to configure a non-default linger timeout. The engine transitions to `Done() when done.

The shutdown also releases the OS resources (closes the descriptor etc.), but only if successful.

Note that the effect of shutdown_e cannot be buffered. Because of this, the io_buffer flushes all data first (i.e. shutdown_e implies the effect of flush_e). Input data available in the buffer can still be read after the shutdown.

val inactivate : [< `Async_in of Uq_engines.async_in_channel * Unixqueue.event_system
| `Async_out of Uq_engines.async_out_channel * Unixqueue.event_system
| `Buffer_in of in_buffer
| `Buffer_out of out_buffer
| `Count_in of (int -> unit) * in_device
| `Count_out of (int -> unit) * out_device
| `Multiplex of Uq_engines.multiplex_controller
| `Polldescr of Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ] ->
unit
Releases the OS resources immediately. This is the right thing to do when aborting the communication, or for cleanup after an I/O error. It is wrong to inactivate after a successful shutdown, because the shutdown already includes the inactivation.

Buffers


val create_in_buffer : ?small_buffer:bool -> [< in_device ] -> in_buffer
Provides a buffered version of the in_device.

By setting small_buffer, the initial input buffer consists only of a single page. Normally, a bigger buffer is allocated.

val in_buffer_length : in_buffer -> int
The length
val in_buffer_blit : in_buffer -> int -> Netsys_types.tbuffer -> int -> int -> unit
Blit to a string or memory buffer
val in_buffer_fill_e : in_buffer -> bool Uq_engines.engine
Requests that the buffer is filled more than currently, and transitions to `Done eof when there is more data, or the EOF is reached (eof=true).
val create_out_buffer : ?small_buffer:bool ->
max:int option -> [< out_device ] -> out_buffer
Provides a buffered version of the out_device. The argument max is the maximum number of bytes to buffer. This can also be set to None meaning no limit.

By setting small_buffer, the initial output buffer consists only of a single page. Normally, a bigger buffer is allocated.

val filter_out_buffer : max:int option ->
Netchannels.io_obj_channel -> [< out_device ] -> out_buffer
filter_out_buffer ~max p d: The data written to this device is redirected via pipe p and finally written to d.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.server_socket_listener.html0000644000175000017500000004065012731530351026555 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.server_socket_listener Uq_engines_compat.server_endpoint_listenerocamlnet-4.1.2/doc/html-main/Nethttp_client.tls_cache-c.html0000644000175000017500000004420312731530351022420 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.tls_cache

Class type Nethttp_client.tls_cache

class type tls_cache = object .. end
A cache object for storing TLS session data

method set : domain:string ->
port:int -> trans:transport_layer_id -> data:string -> unit
This is called by the client to store a new session in the cache. It is up to the cache for how long the session is remembered.
method get : domain:string ->
port:int -> trans:transport_layer_id -> string
Get a cached session (data string)
method clear : unit -> unit
Clear the cache
ocamlnet-4.1.2/doc/html-main/type_Netmcore.Debug.html0000644000175000017500000004100112731530351021123 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netcgi.rw_cgi_argument.html0000644000175000017500000004503712731530351022723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.rw_cgi_argument object
  method charset : string
  method content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method filename : string option
  method finalize : unit -> unit
  method name : string
  method open_value_rd : unit -> Netchannels.in_obj_channel
  method open_value_wr : unit -> Netchannels.out_obj_channel
  method representation :
    [ `MIME of Netmime.mime_message | `Simple of Netmime.mime_body ]
  method ro : bool
  method set_value : string -> unit
  method store : [ `File of string | `Memory ]
  method value : string
end
ocamlnet-4.1.2/doc/html-main/Netx509.x509_certificate_from_DER-c.html0000644000175000017500000004223612731530351023453 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_certificate_from_DER

Class Netx509.x509_certificate_from_DER

class x509_certificate_from_DER : string -> x509_certificate
Parses the passed DER string and returns the certificate object

ocamlnet-4.1.2/doc/html-main/Rpc_server.auth_method-c.html0000644000175000017500000004673612731530351022137 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.auth_method

Class type Rpc_server.auth_method

class type auth_method = object .. end

method name : string
The name of the authentication method
method flavors : string list
Which credential flavors are handled by this method
method peek : auth_peeker
If available, this function is called for every accepted connection. It may return the user name. Notes:
  • peeked user names override authenticate
  • peek is only called once after the stream connection has been accepted

method authenticate : t ->
connection_id ->
auth_details -> (auth_result -> unit) -> unit
authenticate srv conn_id details f: This method is called when a remote call has arrived. Its task is to determine the client user and pass the user name (and the verifier) back. If the user cannot be authenticated, the call must be rejected. When the method has done the authentication, it calls the passed function f with the auth_result. This function can be called immediately or asynchronously.

Changed in Ocamlnet-3.3: the arguments program, version, procedure, and xid are new. Added new auth_result of Auth_reply.

method invalidate_connection : connection_id -> unit
Removes all auth sessions for this connection
method invalidate : unit -> unit
Remove all auth sessions
ocamlnet-4.1.2/doc/html-main/Netsys_xdr.html0000644000175000017500000004551012731530351017434 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_xdr

Module Netsys_xdr

module Netsys_xdr: sig .. end
Some helpers for en/decoding XDR faster

val s_read_int4_64_unsafe : Bytes.t -> int -> int
For 64 bit platforms only: Decodes 4 bytes at this string position as a signed 32 bit int in network byte order

There is no index bounds check!

val s_write_int4_64_unsafe : Bytes.t -> int -> int -> unit
For 64 bit platforms only: Encodes 4 bytes at this string position as a signed 32 bit int in network byte order

There is no index bounds check!

val s_read_string_array_unsafe : Bytes.t -> int -> int -> int32 -> string array -> int
let pos' = s_read_string_array s pos len max a: Decodes the XDR repr of an array of strings without length field. The array must start at pos in s, and may have up to len bytes. The array is passed in a, and the elements are set by this routine. Returns in pos' the position of the first byte after the array. It is checked whether the array is represented within the allowed len bytes. If not, pos'=-1 will be returned, together with an empty array.

max is the maximum length of the string elements. max is unsigned. If this is violated, pos'=-2 will be returned.

ocamlnet-4.1.2/doc/html-main/Shell_sys.job_handler_engine_type-c.html0000644000175000017500000004315312731530351024314 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_sys.job_handler_engine_type

Class type Shell_sys.job_handler_engine_type

class type ['t] job_handler_engine_type = object .. end
This type of engine also returns the job and the job_instance.
Inherits
method job : job
Returns the called job
method job_instance : job_instance
Returns the job instance
ocamlnet-4.1.2/doc/html-main/type_Netcgi_scgi.html0000644000175000017500000004673212731530351020560 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_scgi sig
  val run :
    ?config:Netcgi.config ->
    ?allow:(Unix.sockaddr -> bool) ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?exn_handler:Netcgi.exn_handler ->
    ?socket:Unix.file_descr ->
    ?sockaddr:Unix.sockaddr -> ?port:int -> (Netcgi.cgi -> unit) -> unit
  val handle_request :
    Netcgi.config ->
    Netcgi.output_type ->
    Netcgi.arg_store ->
    Netcgi.exn_handler ->
    (Netcgi.cgi -> unit) ->
    log:(string -> unit) option ->
    Unix.file_descr -> Netcgi.connection_directive
  val handle_connection :
    Netcgi.config ->
    Netcgi.output_type ->
    Netcgi.arg_store ->
    Netcgi.exn_handler -> (Netcgi.cgi -> unit) -> Unix.file_descr -> unit
end
ocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.PROFILE.html0000644000175000017500000004366612731530351022175 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.PROFILE

Module type Netmech_scram_sasl.PROFILE

module type PROFILE = sig .. end
The profile sets some basic parameters. The common profile to use is Netmech_scram_sasl.SHA1

val hash_function : Netsys_digests.iana_hash_fn
The hash function. We only allow functions where IANA registered an official name. Note that SCRAM is currently only specified for SHA1, although the hash function is easily exchangable.
val iteration_count_limit : int
The maximum iteration count supported
val announce_channel_binding : bool
Whether servers announce the availability of channel binding by adding "-PLUS" to the mechanism name.
ocamlnet-4.1.2/doc/html-main/Netmech_scram_http.html0000644000175000017500000004400612731530351021100 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_http

Module Netmech_scram_http

module Netmech_scram_http: sig .. end
SCRAM for HTTP (prerelease)


Implements SCRAM-SHA-256 and SCRAM-SHA-1 as described in https://tools.ietf.org/html/draft-ietf-httpauth-scram-auth-15

Restarts are not yet covered.

As long as the RFC isn't released yet, this should be considered as experimental work.

module type PROFILE = sig .. end
module Make_SCRAM: 
ocamlnet-4.1.2/doc/html-main/Netcgi_common.cgi-c.html0000644000175000017500000005545212731530351021042 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.cgi

Class Netcgi_common.cgi

class cgi : cgi_environment -> output_type -> request_method -> cgi_argument list -> object .. end
cgi env op meth args constructs Netcgi.cgi objects. The environment #out_channel is wrapped into a transactional channel or a discarding channel according to op (`Direct or `Transactional) and request_method (`HEAD requests must only return a header). For standard cases, when POST and PUT arguments are available through a Netchannels.in_obj_channel, we recommend you use Netcgi_common.cgi_with_args that will parse the arguments for you and check preconditions.

Remark: You may think that the argument meth is superfluous as it can be deduced from env#cgi_request_method. While it is true for `DELETE, `GET, `HEAD and `POST, the `PUT takes a Netcgi_common.cgi_argument parameter. Setting correctly this parameter and decoding env#cgi_request_method is done for you by Netcgi_common.cgi_with_args.


method argument : string -> cgi_argument
method argument_value : ?default:string -> string -> string
method argument_exists : string -> bool
method multiple_argument : string -> cgi_argument list
method arguments : cgi_argument list
method environment : cgi_environment
method request_method : request_method
method finalize : unit -> unit
method url : ?protocol:Nethttp.protocol ->
?with_authority:other_url_spec ->
?with_script_name:other_url_spec ->
?with_path_info:other_url_spec ->
?with_query_string:query_string_spec -> unit -> string
The following environment properties must be available for this method to work properly (please make sure your connector provides them; the CGI spec make them compulsory anyway):
  • cgi_server_name
  • cgi_server_port
  • cgi_script_name
  • cgi_path_info

method set_header : ?status:Nethttp.http_status ->
?content_type:string ->
?content_length:int ->
?set_cookie:Nethttp.cookie list ->
?set_cookies:Cookie.t list ->
?cache:cache_control ->
?filename:string ->
?language:string ->
?script_type:string ->
?style_type:string -> ?fields:(string * string list) list -> unit -> unit
method set_redirection_header : ?set_cookies:Cookie.t list ->
?fields:(string * string list) list -> string -> unit
method output : Netchannels.trans_out_obj_channel
Deprecated.Use #out_channel instead.
method out_channel : Netchannels.trans_out_obj_channel
method at_exit : (unit -> unit) -> unit
ocamlnet-4.1.2/doc/html-main/Netmcore_condition.Debug.html0000644000175000017500000004164512731530351022146 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_condition.Debug

Module Netmcore_condition.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/Uq_transfer.output_async_descr-c.html0000644000175000017500000004605412731530351023723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.output_async_descr

Class Uq_transfer.output_async_descr

class output_async_descr : dst:Unix.file_descr -> ?buffer_size:int -> ?close_dst:bool -> Unixqueue.event_system -> async_out_channel_engine
This engine implements an async_out_channel for the output descriptor dst. The engine provides an internal buffer to reduce the number of blocked output operations; by default there is even no limit for the growth of the buffer, and because of this the channel never blocks (can_output is always true).

The engine attaches immediately to the event system, and detaches automatically. By default, the file descriptor is closed when the engine stops operation, either successfully or because of an error.

If the buffer is full, the class accepts no more data until there is again free space in the buffer. This means that writers must be prepared that can_output returns false, and that the output method returns 0. The buffer can only get "full" if the buffer_size argument is passed.

The notification mechanism is shared by the "engine nature" and by the "channel nature" of this class: If either the state or can_output change their values, the notification callbacks are invoked.

The semantics of the engine is undefined if dst is not a stream-oriented descriptor.

TODO: This class cannot yet cope with Win32 named piped.


buffer_size : Limits the size of the buffer
close_dst : Whether to close dst when the engine stops (default: true)

ocamlnet-4.1.2/doc/html-main/type_Netplex_encap.Make_encap.html0000644000175000017500000004163312731530351023144 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_encap.Make_encap functor (T : TYPE->
  sig type t = T.t val wrap : t -> encap val unwrap : encap -> t end
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.http_service_generator-c.html0000644000175000017500000004405212731530351025274 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.http_service_generator

Class type Nethttpd_types.http_service_generator

class type http_service_generator = object .. end

method generate_response : extended_environment -> unit
Third stage of HTTP processing: This method is called when the HTTP request has been completely received, and the response is going to be generated. This method can again be called from a different thread than the previous stages. It is allowed to spend any necessary time to compute the response.

When the method returns, the request processing is finished. No more data is allowed to be written to the output channel past this moment.

The method may raise Standard_response to generate one of the standard messages.

ocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.SCRAM_SHA256.html0000644000175000017500000010735612731530351022667 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM_SHA256

Module Netmech_scram_sasl.SCRAM_SHA256

module SCRAM_SHA256: Netsys_sasl_types.SASL_MECHANISM 
SCRAM with SHA256 profile

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/Netchannels.out_obj_channel-c.html0000644000175000017500000004304012731530351023100 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.out_obj_channel

Class type Netchannels.out_obj_channel

class type out_obj_channel = object .. end
The application-level output channel supports raw and complemented methods
Inherits
ocamlnet-4.1.2/doc/html-main/type_Netsys_ciphers.html0000644000175000017500000006016012731530351021333 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_ciphers sig
  type padding = [ `CTS | `Length | `None | `_8000 ]
  class type cipher_ctx =
    object
      method block_constraint : int
      method decrypt :
        last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int
      method decrypt_bytes : Bytes.t -> Bytes.t
      method decrypt_string : string -> string
      method encrypt :
        last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int
      method encrypt_bytes : Bytes.t -> Bytes.t
      method encrypt_string : string -> string
      method mac : unit -> string
      method padding : Netsys_ciphers.padding
      method set_header : string -> unit
      method set_iv : string -> unit
      method supports_aead : bool
    end
  class type cipher =
    object
      method block_constraint : int
      method create :
        string -> Netsys_ciphers.padding -> Netsys_ciphers.cipher_ctx
      method iv_lengths : (int * int) list
      method key_lengths : (int * int) list
      method mode : string
      method name : string
      method supports_aead : bool
    end
  val ciphers :
    ?impl:(module Netsys_crypto_types.SYMMETRIC_CRYPTO->
    unit -> Netsys_ciphers.cipher list
  val find :
    ?impl:(module Netsys_crypto_types.SYMMETRIC_CRYPTO->
    string * string -> Netsys_ciphers.cipher
  val process_subbytes :
    (last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int) ->
    Bytes.t -> int -> int -> Bytes.t
  val process_substring :
    (last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int) ->
    string -> int -> int -> string
  val process_bytes :
    (last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int) ->
    Bytes.t -> Bytes.t
  val process_string :
    (last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int) ->
    string -> string
end
ocamlnet-4.1.2/doc/html-main/Netcgi_common.Cookie.html0000644000175000017500000005606012731530351021265 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.Cookie

Module Netcgi_common.Cookie

module Cookie: sig .. end

type t = Nethttp.Cookie.t 
val make : ?max_age:int ->
?domain:string ->
?path:string ->
?secure:bool ->
?comment:string ->
?comment_url:string ->
?ports:int list -> string -> string -> t
val name : t -> string
val value : t -> string
val max_age : t -> int option
The expiration time of the cookie, in seconds. None means that the cookie will be discarded when the browser exits. This information is not returned by the browser.
val domain : t -> string option
val path : t -> string option
val secure : t -> bool
Tells whether the cookie is secure. This information is not returned by the browser.
val comment : t -> string
Returns the comment associated to the cookie or "" if it does not exists. This information is not returned by the browser.
val comment_url : t -> string
Returns the comment URL associated to the cookie or "" if it does not exists. This information is not returned by the browser.
val ports : t -> int list option
val set_value : t -> string -> unit
val set_max_age : t -> int option -> unit
val set_domain : t -> string option -> unit
val set_path : t -> string option -> unit
val set_secure : t -> bool -> unit
val set_comment : t -> string -> unit
val set_comment_url : t -> string -> unit
val set_ports : t -> int list option -> unit
val set : #Netmime.mime_header -> t list -> unit
set http_header cookies sets the cookies in http_header using version 0 or version 1 depending on whether version 1 fields are used. For better browser compatibility, if "Set-cookie2" (RFC 2965) is issued, then a "Set-cookie" precedes (declaring the same cookie with a limited number of options).

Deprecated name. Use Nethttp.Header.set_set_cookie_ct.

val get : #Netmime.mime_header -> t list
Decode the cookie header, may they be version 0 or 1.

Deprecated name. Use Nethttp.Header.get_cookie_ct.

val of_record : Nethttp.cookie -> t
Conversion from the deprecated style of cookie.

Deprecated name. Use Nethttp.Cookie.of_netscape_cookie.

val to_record : t -> Nethttp.cookie
Conversion to the deprecated style of cookie (some parameters are dropped).

Deprecated name. Use Nethttp.Cookie.to_netscape_cookie.

ocamlnet-4.1.2/doc/html-main/type_Rpc_auth_gssapi.html0000644000175000017500000004710312731530351021446 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_auth_gssapi sig
  type user_name_format = [ `Exported_name | `Plain_name | `Prefixed_name ]
  val server_auth_method :
    ?shared_context:bool ->
    ?user_name_format:Rpc_auth_gssapi.user_name_format ->
    ?seq_number_window:int ->
    ?max_age:float ->
    (module Netsys_gssapi.GSSAPI->
    Netsys_gssapi.server_config -> Rpc_server.auth_method
  type support_level = [ `If_possible | `None | `Required ]
  type user_name_interpretation =
      [ `Exported_name | `Plain_name of Netsys_gssapi.oid | `Prefixed_name ]
  val client_auth_method :
    ?user_name_interpretation:Rpc_auth_gssapi.user_name_interpretation ->
    (module Netsys_gssapi.GSSAPI->
    Netsys_gssapi.client_config -> Rpc_client.auth_method
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Netpop.connect-c.html0000644000175000017500000004310312731530351020403 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpop.connect

Class Netpop.connect

class connect : ?proxy:#Uq_engines.client_endpoint_connector -> Uq_engines.connect_address -> float -> client
connect addr timeout: Connects with the server at addr, and configure that I/O operations time out after timeout seconds of waiting.

Example:

  let addr =
    `Socket(`Sock_inet_byname(Unix.SOCK_STREAM, "www.domain.com", 110),
            Uq_client.default_connect_options) in
  let client =
    new Netpop.connect addr 60.0


ocamlnet-4.1.2/doc/html-main/Netgzip.deflating_pipe-c.html0000644000175000017500000004236012731530351022103 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.deflating_pipe

Class Netgzip.deflating_pipe

class deflating_pipe : ?level:int -> unit -> Netchannels.io_obj_channel
A deflating (compressing) pipe for gzip data, to be used in filters

ocamlnet-4.1.2/doc/html-main/Netxdr_mstring.mstring-c.html0000644000175000017500000004713112731530351022204 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netxdr_mstring.mstring

Class type Netxdr_mstring.mstring

class type mstring = object .. end
The object holding the string value

method length : int
The length of the managed string
method blit_to_bytes : int -> Bytes.t -> int -> int -> unit
blit_to_bytes mpos s spos len: Copies the substring of the managed string from mpos to mpos+len-1 to the substring of s from spos to spos+len-1
method blit_to_string : int -> Bytes.t -> int -> int -> unit
method blit_to_memory : int -> Netsys_mem.memory -> int -> int -> unit
blit_to_string mpos mem mempos len: Copies the substring of the managed string from mpos to mpos+len-1 to the substring of mem from mempos to mempos+len-1
method as_bytes : Bytes.t * int
Returns the contents as bytes. It is undefined whether the returned string is a copy or the underlying buffer. The int is the position where the contents start
method as_string : string * int
Returns the contents as string (this is always a copy)
method as_memory : Netsys_mem.memory * int
Returns the contents as memory. It is undefined whether the returned memory is a copy or the underlying buffer. The int is the position where the contents start
method preferred : [ `Bytes | `Memory ]
Whether as_memory or as_bytes is cheaper
ocamlnet-4.1.2/doc/html-main/type_Nettls_gnutls.GNUTLS_ENDPOINT.TLS.html0000644000175000017500000004060612731530351024155 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.GNUTLS_ENDPOINT.TLS GNUTLS_PROVIDERocamlnet-4.1.2/doc/html-main/Netcgi1_compat.html0000644000175000017500000004525612731530351020136 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat

Module Netcgi1_compat

module Netcgi1_compat: sig .. end
Deprecated.Use the new API instead.
Compatibility module with the previous version of Netcgi.

Opening this module allows a project using the old Netcgi_env and Netcgi_types to compile with minor changes. For documentation, please see the original modules (in the netcgi1 directory). If you are a first time user or start a new project, do not use this module.

Functions that are useful to migrate a project are emphasized with "Portage:". Some comments accompany the functions that changed to give some motivation for the new API. (It is useful to refer to the old documentation to understand everything.)


Version: $Id: netcgi_compat.mli,v 1.7 2005/11/04 00:53:05 chris_77 Exp $


exception Not_implemented of string
Raised by some functions/exceptions when a feature of the old model cannot be implemented in the new model or vice versa
module Netcgi_env: sig .. end
module Netcgi_types: sig .. end
module Netcgi: sig .. end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.delete-c.html0000644000175000017500000004222712731530351021741 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.delete

Class Nethttp_client.delete

class delete : string -> http_call
Argument: URI

ocamlnet-4.1.2/doc/html-main/type_Netchannels.compl_in_channel.html0000644000175000017500000004235312731530351024066 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.compl_in_channel object
  method input_byte : unit -> int
  method input_char : unit -> char
  method input_line : unit -> string
  method really_input : Bytes.t -> int -> int -> unit
  method really_input_string : int -> string
end
ocamlnet-4.1.2/doc/html-main/Netchannels.pipe-c.html0000644000175000017500000004577312731530351020723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.pipe

Class Netchannels.pipe

class pipe : ?conv:Netbuffer.t -> bool -> Netbuffer.t -> unit -> ?buffer_size:int -> unit -> io_obj_channel
A pipe has two internal buffers (realized by Netbuffer). The output methods of the class write to the incoming buffer. When new data are appended to the incoming buffer, the conversion function conv is called; the arguments are the incoming buffer and the outgoing buffer. The conversion function must convert the data available in the incoming buffer and append the result to the outgoing buffer. Finally, the input methods of the class return the data found in the outgoing buffer.

The conversion function is called as follows: conv incoming_buffer at_eof outgoing_buffer

The conversion function is allowed to do nothing if the incoming data are not complete enough to be converted. It is also allowed to convert only the beginning of the incoming buffer.

If the outgoing buffer is empty, the input methods will raise Buffer_underrun.

If close_out is invoked, the end of the data stream will be recorded. In this case, the conversion function is called with at_eof = true, and it is expected that this function converts the whole data found in the incoming buffer.

close_in implies close_out.

The conversion function may raise exceptions. The exceptions will fall through to the caller of the input methods. (The output methods and close_in, close_out never fail because of such exceptions.)

The default conversion function copies everything from the incoming buffer to the outgoing buffer without modification.


ocamlnet-4.1.2/doc/html-main/type_Netx509.CE.html0000644000175000017500000004557312731530351020006 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.CE sig
  val ce_authority_key_identifier : Netx509.oid
  val ce_subject_key_identifier : Netx509.oid
  val ce_key_usage : Netx509.oid
  val ce_certificate_policies : Netx509.oid
  val ce_any_policy : Netx509.oid
  val ce_policy_mappings : Netx509.oid
  val ce_subject_alt_name : Netx509.oid
  val ce_issuer_alt_name : Netx509.oid
  val ce_subject_directory_attributes : Netx509.oid
  val ce_basic_constraints : Netx509.oid
  val ce_name_constraints : Netx509.oid
  val ce_policy_constraints : Netx509.oid
  val ce_ext_key_usage : Netx509.oid
  val ce_crl_distribution_points : Netx509.oid
  val ce_inhibit_any_policy : Netx509.oid
  val ce_freshest_crl : Netx509.oid
  val ce_authority_info_access : Netx509.oid
  val ce_subject_info_access : Netx509.oid
  val certificate_extensions : (Netx509.oid * string) list
end
ocamlnet-4.1.2/doc/html-main/type_Netftp_client.Debug.html0000644000175000017500000004100612731530351022152 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_client.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netpop.client-c.html0000644000175000017500000006106512731530351020237 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpop.client

Class Netpop.client

class client : Netchannels.in_obj_channel -> Netchannels.out_obj_channel -> object .. end
The class client implements the POP3 protocol. Client objects are created by
 new client in_ch out_ch 
where in_ch is an input channel representing the input direction of the TCP stream, and where out_ch is an output channel representing the output direction of the TCP stream.

method state : state
Current state of this session.
method capabilities : (string * string list) list
The result of the last capa command
method capa : unit -> (string * string list) list
Requests a list of capabilities (RFC 2449). Returns the empty list if capa is not understood.
method quit : unit -> unit
Requests the server to end this session. If the session is currently in the `Transaction state, the server will attempt to remove all messages marked as deleted before closing its side of the connection.
method close : unit -> unit
Closes the file descriptors
method user : user:string -> unit
Specifies the name of the mailbox the client would like to open using plain-text authentication. Normal completion of this function should be followed by the pass command.
method pass : pass:string -> unit
Authenticates a user with the plain-text password pass.
method apop : user:string -> pass:string -> unit
Specifies the user and password using APOP authentication. APOP is a more secure method of authentication than what is provided by the user/pass command sequence.
method auth : Netsys_sasl.sasl_mechanism ->
string ->
string -> Netsys_sasl.credentials -> (string * string * bool) list -> unit
auth mech user authz creds params: Performs a SASL authentication using the AUTH command (RFC 5034). See Netsys_sasl.Client.create_session for details about SASL.

Example:

client # auth
  (module Netmech_digest_sasl.DIGEST_MD5)
  "user"
  ""
  [ "password", "sEcReT", [] ]
  []
   

method stat : unit -> int * int * string
Returns information about the current mailbox as tuple (count,size,ext) where count is the number of messages in the mailbox, size is the size of the mailbox in octets, and ext is any server extension data.
method list : ?msgno:int -> unit -> (int, int * string) Hashtbl.t
Returns the scan listing for an optional message number or for all messages in the current mailbox. The result is a hash table that maps a message number to a tuple (size,ext) where size is the size of the message in octets, and ext is any server extension data.
method retr : msgno:int -> Netchannels.in_obj_channel
Retrieves a message from the server.
method dele : msgno:int -> unit
Marks the message number of the current mailbox for deletion.
method noop : unit -> unit
Pings the server to keep the session alive.
method rset : unit -> unit
Unmarks any messages that have previously been marked as deleted.
method top : ?lines:int -> msgno:int -> unit -> Netchannels.in_obj_channel
Returns the message header plus a limited number of lines of the message body. The default body length is 0 lines.
method uidl : ?msgno:int -> unit -> (int, string) Hashtbl.t
Returns the unique identifier(s) for an optional message number or for all messages in the current mailbox. The result is a hash table that maps a message number to its unique id.
method stls : peer_name:string option -> Netsys_crypto_types.tls_config -> unit
Sends STLS (STARTTLS), and negotiates a secure connection. Raises Err_state if TLS is unavailable on the server.

STLS is specified in RFC 2595.

method tls_endpoint : Netsys_crypto_types.tls_endpoint option
Returns the TLS endpoint (after STARTTLS)
method tls_session_props : Nettls_support.tls_session_props option
Returns the TLS session properties (after STARTTLS)
method gssapi_props : Netsys_gssapi.client_props option
Returns GSSAPI properties, if available
ocamlnet-4.1.2/doc/html-main/type_Unixqueue.html0000644000175000017500000007755212731530351020336 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue sig
  type group = Unixqueue_util.group
  exception Abort of (Unixqueue.group * exn)
  type wait_id = Unixqueue_util.wait_id
  type operation =
    Unixqueue_util.operation =
      Wait_in of Unix.file_descr
    | Wait_out of Unix.file_descr
    | Wait_oob of Unix.file_descr
    | Wait of Unixqueue.wait_id
  type event =
    Unixqueue_util.event =
      Input_arrived of (Unixqueue.group * Unix.file_descr)
    | Output_readiness of (Unixqueue.group * Unix.file_descr)
    | Out_of_band of (Unixqueue.group * Unix.file_descr)
    | Timeout of (Unixqueue.group * Unixqueue.operation)
    | Signal
    | Extra of exn
    | Immediate of (Unixqueue.group * (unit -> unit))
  class type event_system =
    object
      method add_abort_action :
        Unixqueue.group -> (Unixqueue.group -> exn -> unit) -> unit
      method add_close_action :
        Unixqueue.group ->
        Unix.file_descr * (Unix.file_descr -> unit) -> unit
      method add_event : Unixqueue.event -> unit
      method add_handler :
        Unixqueue.group ->
        (Unixqueue.event_system ->
         Unixqueue.event Equeue.t -> Unixqueue.event -> unit) ->
        unit
      method add_resource :
        Unixqueue.group -> Unixqueue.operation * float -> unit
      method add_weak_resource :
        Unixqueue.group -> Unixqueue.operation * float -> unit
      method clear : Unixqueue.group -> unit
      method exists_resource : Unixqueue.operation -> bool
      method is_running : bool
      method new_group : unit -> Unixqueue.group
      method new_wait_id : unit -> Unixqueue.wait_id
      method remove_resource : Unixqueue.group -> Unixqueue.operation -> unit
      method run : unit -> unit
      method when_blocking : (unit -> unit) -> unit
    end
  class standard_event_system : unit -> event_system
  val standard_event_system : unit -> Unixqueue.event_system
  class unix_event_system : unit -> event_system
  val create_unix_event_system : unit -> Unixqueue.event_system
  class performance_event_system : unit -> event_system
  val performance_event_system : unit -> Unixqueue.event_system
  val new_group : Unixqueue.event_system -> Unixqueue.group
  val new_wait_id : Unixqueue.event_system -> Unixqueue.wait_id
  val exists_resource : Unixqueue.event_system -> Unixqueue.operation -> bool
  val add_resource :
    Unixqueue.event_system ->
    Unixqueue.group -> Unixqueue.operation * float -> unit
  val add_weak_resource :
    Unixqueue.event_system ->
    Unixqueue.group -> Unixqueue.operation * float -> unit
  val add_close_action :
    Unixqueue.event_system ->
    Unixqueue.group -> Unix.file_descr * (Unix.file_descr -> unit) -> unit
  val add_abort_action :
    Unixqueue.event_system ->
    Unixqueue.group -> (Unixqueue.group -> exn -> unit) -> unit
  val remove_resource :
    Unixqueue.event_system -> Unixqueue.group -> Unixqueue.operation -> unit
  val add_handler :
    Unixqueue.event_system ->
    Unixqueue.group ->
    (Unixqueue.event_system ->
     Unixqueue.event Equeue.t -> Unixqueue.event -> unit) ->
    unit
  val add_event : Unixqueue.event_system -> Unixqueue.event -> unit
  val clear : Unixqueue.event_system -> Unixqueue.group -> unit
  val run : Unixqueue.event_system -> unit
  val is_running : Unixqueue.event_system -> bool
  val once :
    Unixqueue.event_system ->
    Unixqueue.group -> float -> (unit -> unit) -> unit
  val weak_once :
    Unixqueue.event_system ->
    Unixqueue.group -> float -> (unit -> unit) -> unit
  val epsilon : Unixqueue.event_system -> (unit -> unit) -> unit
  module Debug :
    sig
      val enable : bool Pervasives.ref
      val set_debug_mode : bool -> unit
      val set_debug_target : Equeue.Debug.debug_target -> unit
    end
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_engine.html0000644000175000017500000005675412731530351020425 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine

Module Nethttpd_engine

module Nethttpd_engine: sig .. end

The event-based encapsulation of the HTTP daemon

This is a user-friendlier encapsulation of the HTTP daemon. It uses the engine module defined in Uq_engines.


type engine_req_state = [ `Finishing | `Received_header | `Received_request | `Receiving_body ] 
class type http_engine_config = object .. end
val default_http_engine_config : http_engine_config
The default config:
  • config_input_flow_control=false
  • config_output_flow_control=true

class modify_http_engine_config : ?modify_http_protocol_config:Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config -> ?modify_http_processor_config:Nethttpd_reactor.http_processor_config ->
Nethttpd_reactor.http_processor_config -> ?config_input_flow_control:bool -> ?config_output_flow_control:bool -> http_engine_config ->
http_engine_config
Modifies the passed config object as specified by the optional arguments.
class type extended_async_environment = object .. end
class type http_request_header_notification = object .. end
class type http_request_notification = object .. end
class http_engine : ?config_hooks:Nethttpd_kernel.http_protocol_hooks -> unit -> on_request_header:(http_request_header_notification -> unit) -> unit -> #http_engine_config -> Unix.file_descr -> Unixqueue.unix_event_system -> [unit] Uq_engines.engine
This engine processes the requests arriving on the file descriptor using the Unix event system.
class type http_engine_processing_config = object .. end
class buffering_engine_processing_config : http_engine_processing_config
Implements the synchronisation by buffering
class type http_engine_processing_context = object .. end
val process_connection : ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) ->
#Nethttpd_reactor.http_processor_config ->
#http_engine_processing_config ->
Unix.file_descr ->
Unixqueue.unix_event_system ->
'a Nethttpd_types.http_service ->
http_engine_processing_context
Sets up an engine that processes all requests using the service description. This function returns immediately, one needs to Unixqueue.run the event system to start the engine.

The passed http_engine_processing_config is crucial for good performance. XXX


Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.prioritizer_t-c.html0000644000175000017500000004305712731530351024062 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.prioritizer_t

Class type Uq_engines_compat.prioritizer_t

class type ['a] prioritizer_t = object .. end

method prioritized : (Unixqueue.event_system -> 'a engine) ->
int -> 'a engine
ocamlnet-4.1.2/doc/html-main/Netchannels.rec_out_channel-c.html0000644000175000017500000004602712731530351023107 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.rec_out_channel

Class type Netchannels.rec_out_channel

class type rec_out_channel = object .. end
Recommended output class type for library interoperability.

Description

This class type is defined in "Basic I/O class types" as collaborative effort of several library creators.

method output : Bytes.t -> int -> int -> int
Takes octets from the string and writes them into the channel. The first int argument is the position of the substring, and the second int argument is the length of the substring where the data can be found. The method returns the number of octets actually written.

The implementation may choose to collect written octets in a buffer before they actually delivered to the underlying resource.

When the channel is non-blocking, and there are currently no bytes to write, the number 0 will be returned. This has been changed in ocamlnet-0.97! In previous releases this behaviour was undefined.

When the channel is closed, the exception Closed_channel will be raised if an ocamlnet implementation is used. For implementations of other libraries there is no standard for this case.

method flush : unit -> unit
If there is a write buffer, it will be flushed. Otherwise, nothing happens.
method close_out : unit -> unit
Flushes the buffer, if any, and closes the channel for output.

When the channel is already closed, this is a no-op.

ocamlnet-4.1.2/doc/html-main/type_Netchannels_crypto.crypto_out_filter.html0000644000175000017500000004543412731530351025755 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.crypto_out_filter object
  method close_out : unit -> unit
  method flush : unit -> unit
  method mac : unit -> string
  method output : Bytes.t -> int -> int -> int
  method output_buffer : Buffer.t -> unit
  method output_byte : int -> unit
  method output_bytes : Bytes.t -> unit
  method output_channel : ?len:int -> Netchannels.in_obj_channel -> unit
  method output_char : char -> unit
  method output_string : string -> unit
  method pos_out : int
  method really_output : Bytes.t -> int -> int -> unit
  method really_output_string : string -> int -> int -> unit
  method supports_aead : bool
end
ocamlnet-4.1.2/doc/html-main/type_Netmime.mime_header.html0000644000175000017500000004312212731530351022164 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.mime_header object
  method delete_field : string -> unit
  method field : string -> string
  method fields : (string * string) list
  method multiple_field : string -> string list
  method ro : bool
  method set_fields : (string * string) list -> unit
  method update_field : string -> string -> unit
  method update_multiple_field : string -> string list -> unit
end
ocamlnet-4.1.2/doc/html-main/Unixqueue.performance_event_system-c.html0000644000175000017500000004235012731530351024606 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.performance_event_system

Class Unixqueue.performance_event_system

class performance_event_system : unit -> event_system
The implementation using Netsys_pollset_generic.performance_pollset.

ocamlnet-4.1.2/doc/html-main/Nethttp_client.delete_call-c.html0000644000175000017500000004216012731530351022730 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.delete_call

Class Nethttp_client.delete_call

class delete_call : http_call

ocamlnet-4.1.2/doc/html-main/type_Netgss.html0000644000175000017500000004107212731530351017575 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgss sig module System : Netsys_gssapi.GSSAPI endocamlnet-4.1.2/doc/html-main/type_Rpc_client.blocking_socket_config.html0000644000175000017500000004061712731530351025104 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.blocking_socket_config Rpc_client.socket_configocamlnet-4.1.2/doc/html-main/Nethttp_client.unified_auth_handler-c.html0000644000175000017500000004377212731530351024646 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.unified_auth_handler

Class Nethttp_client.unified_auth_handler

class unified_auth_handler : ?insecure:bool -> #key_handler -> auth_handler
Support both digest and basic authentication, with preference to digest. By default, basic authentication is only enabled over TLS connections. You can enable basic authentication for normal connections with the insecure option.

In the future this class will also enable other secure authentication methods such as SCRAM or Digest with more secure hash functions. (The RFCs for these methods are not yet published.)

Note that there is no way of enabling the skip_challenge mode, as it is not known in advance which mechanism will be used.


ocamlnet-4.1.2/doc/html-main/type_Netglob.glob_fsys.html0000644000175000017500000004173012731530351021713 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.glob_fsys object
  method file_exists : string -> bool
  method file_is_dir : string -> bool
  method path_encoding : Netconversion.encoding option
  method read_dir : string -> string list
end
ocamlnet-4.1.2/doc/html-main/Netcgi_common.cgi_argument-c.html0000644000175000017500000004501212731530351022733 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.cgi_argument

Class type Netcgi_common.cgi_argument

class type cgi_argument = object .. end

method name : string
method value : string
method open_value_rd : unit -> Netchannels.in_obj_channel
method store : store
method content_type : unit -> string * (string * Netmime_string.s_param) list
method charset : string
method filename : string option
method representation : representation
method finalize : unit -> unit
ocamlnet-4.1.2/doc/html-main/Netcgi_apache.Handler.html0000644000175000017500000005112712731530351021361 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Handler

Module Netcgi_apache.Handler

module Handler: sig .. end
Registering Apache handlers.

type result = 
| OK (*
This stage of request processing was handled successfully.
*)
| DECLINED (*
No erroneous condition exists, but the module declines to handle the phase; the server tries to find another.
*)
| DONE (*
The request is completely satisfied.
*)
| HTTP of int (*
The request returns the HTTP status code given as argument.
*)
type t = Netcgi_apache.Apache.Request.t -> result 
The type of handler functions. The exception Exit is considered as a normal way of terminating early. All other exceptions are logged and result in an Internal_server_error response by Apache.
val register : t -> string -> unit
Modules may call register fn name to register one or more handler functions. The handler functions are then referred to in the Netcgi*Handler configuration commands as Module_name.name where Module_name is derived from the filename (given to the NetcgiLoad directive) and name is the string passed here.
ocamlnet-4.1.2/doc/html-main/Netmech_krb5_sasl.Krb5_gs2.html0000644000175000017500000011115212731530351022173 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_krb5_sasl.Krb5_gs2

Functor Netmech_krb5_sasl.Krb5_gs2

module Krb5_gs2: 
This is the other adapter turning the Kerberos 5 GSSAPI mechanism into a SASL mechanism. This follows the specification in RFC 5801 ("gs2").

The usage is the same as Netmech_krb5_sasl.Krb5_gs1.

This adapter doesn't announce channel bindings.

Parameters:
GSS : Netsys_gssapi.GSSAPI

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.controller.html0000644000175000017500000005121712731530351023361 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.controller object
  method activate_lever : int -> Netplex_types.encap -> Netplex_types.encap
  method add_admin : (Rpc_server.t -> unit) -> unit
  method add_message_receiver : Netplex_types.ctrl_message_receiver -> unit
  method add_plugin : Netplex_types.plugin -> unit
  method add_service :
    Netplex_types.socket_service -> Netplex_types.workload_manager -> unit
  method container_count : string -> int
  method containers : Netplex_types.container_id list
  method containers_for : string -> Netplex_types.container_id list
  method controller_config : Netplex_types.controller_config
  method event_system : Unixqueue.unix_event_system
  method free_resources : unit -> unit
  method logger : Netplex_types.logger
  method ptype : Netplex_types.parallelization_type
  method register_lever :
    (Netplex_types.controller -> Netplex_types.encap -> Netplex_types.encap) ->
    int
  method restart : unit -> unit
  method send_admin_message : string -> string -> string array -> unit
  method send_message : string -> string -> string array -> unit
  method services :
    (Netplex_types.socket_service * Netplex_types.socket_controller *
     Netplex_types.workload_manager)
    list
  method shutdown : unit -> unit
  method startup_directory : string
  method sys_id : Netplex_types.thread_sys_id
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels_crypto.crypto_in_filter.html0000644000175000017500000004367412731530351025560 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.crypto_in_filter object
  method close_in : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method input_byte : unit -> int
  method input_char : unit -> char
  method input_line : unit -> string
  method mac : unit -> string
  method pos_in : int
  method really_input : Bytes.t -> int -> int -> unit
  method really_input_string : int -> string
  method supports_aead : bool
end
ocamlnet-4.1.2/doc/html-main/Netcgi.html0000644000175000017500000012251312731530351016502 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi

Module Netcgi

module Netcgi: sig .. end
Common data-structures for CGI-like connectors.

This library tries to minimize the use of unsafe practices. It cannot be bullet proof however and you should read about security.

REMARK: It happens frequently that hard to predict random numbers are needed in Web applications. The previous version of this library used to include some facilities for that (in the Netcgi_jserv module). They have been dropped in favor of Cryptokit.



Arguments


class type cgi_argument = object .. end
Represent a key-value pair of data passed to the script (including file uploads).
module Argument: sig .. end
Operations on arguments and lists of thereof.
class type rw_cgi_argument = object .. end
Old deprecated writable argument type.
class simple_argument : ?ro:bool -> string -> string -> rw_cgi_argument
Old deprecated simple argument class.
class mime_argument : ?work_around_backslash_bug:bool -> string -> Netmime.mime_message -> rw_cgi_argument
Old deprecated MIME argument class.

Cookies


module Cookie: sig .. end
Functions to manipulate cookies.

The environment of a request


type http_method = [ `DELETE | `GET | `HEAD | `POST | `PUT ] 
type config = Netcgi_common.config = {
   tmp_directory : string; (*
The directory where to create temporary files. This should be an absolute path name.
*)
   tmp_prefix : string; (*
The name prefix for temporary files. This must be a non-empty string. It must not contain '/'.
*)
   permitted_http_methods : http_method list; (*
The list of accepted HTTP methods
*)
   permitted_input_content_types : string list; (*
The list of accepted content types in requests. Content type parameters (like "charset") are ignored. If the list is empty, all content types are allowed.
*)
   input_content_length_limit : int; (*
The maximum size of the request, in bytes.
*)
   max_arguments : int; (*
The maximum number of CGI arguments
*)
   workarounds : [ `Backslash_bug
| `MSIE_Content_type_bug
| `Work_around_MSIE_Content_type_bug
| `Work_around_backslash_bug ] list
;
(*
The list of enabled workarounds.

  • `MSIE_Content_type_bug
  • `Backslash_bug A common error in MIME implementations is not to escape backslashes in quoted string and comments. This workaround mandates that backslashes are handled as normal characters. This is important for e.g. DOS filenames because, in the absence of this, the wrongly encoded "C:\dir\file" will be decoded as "C:dirfile".
Remark: `Work_around_MSIE_Content_type_bug and `Work_around_backslash_bug are deprecated versions of, respectively, `MSIE_Content_type_bug and `Backslash_bug.
*)
   default_exn_handler : bool; (*
Whether to catch exceptions raised by the script and display an error page. This will keep the connector running even if your program has bugs in some of its components. This will however also prevent a stack trace to be printed; if you want this turn this option off.
*)
}
val default_config : config
The default configuration is:
  • tmp_directory: Netsys_tmp.tmp_directory()
  • tmp_prefix: "netcgi"
  • permitted_http_methods: `GET, `HEAD, `POST.
  • permitted_input_content_types: "multipart/form-data", "application/x-www-form-urlencoded".
  • input_content_length_limit: maxint (i.e., no limit).
  • max_arguments = 10000 (for security reasons)
  • workarounds: all of them.
  • default_exn_handler: set to true.
To create a custom configuration, it is recommended to use this syntax:
      let custom_config = { default_config with tmp_prefix = "my_prefix" }
      
(This syntax is also robust w.r.t. the possible addition of new config flields.)
class type cgi_environment = object .. end
The environment of a request consists of the information available besides the data sent by the user (as key-value pairs).

CGI object


type other_url_spec = [ `Env | `None | `This of string ] 
Determines how an URL part is generated:
  • `Env: Take the value from the environment.
  • `This v: Use this value v. It must already be URL-encoded.
  • `None: Do not include this part into the URL.

type query_string_spec = [ `Args of rw_cgi_argument list
| `Env
| `None
| `This of cgi_argument list ]
Determines how the query part of URLs is generated:
  • `Env: The query string of the current request.
  • `This l: The query string is created from the specified argument list l.
  • `None: The query string is omitted.
  • `Args: deprecated, use `This (left for backward compatibility).

type cache_control = [ `Max_age of int | `No_cache | `Unspecified ] 
This is only a small subset of the HTTP 1.1 cache control features, but they are usually sufficient, and they work for HTTP/1.0 as well. The directives mean:

  • `No_cache: Caches are disabled. The following headers are sent: Cache-control: no-cache, Pragma: no-cache, Expires: (now - 1 second). Note that many versions of Internet Explorer have problems to process non-cached contents when TLS/SSL is used to transfer the file. Use `Max_age in such cases (see http://support.microsoft.com/kb/316431).
  • `Max_age n: Caches are allowed to store a copy of the response for n seconds. After that, the response must be revalidated. The following headers are sent: Cache-control: max-age n, Cache-control: must-revalidate, Expires: (now + n seconds)
  • `Unspecified: No cache control header is added to the response.
Notes:
  • Cache control directives only apply to GET requests; POST requests are never cached.
  • Not only proxies are considered as cache, but also the local disk cache of the browser.
  • HTTP/1.0 did not specify cache behaviour as strictly as HTTP/1.1 does. Because of this the Pragma and Expires headers are sent, too. These fields are not interpreted by HTTP/1.1 clients because Cache-control has higher precedence.

class type cgi = object .. end
Object symbolizing a CGI-like request/response cycle.
class type cgi_activation = cgi
Alternate, more descriptive name for cgi

Connectors


type output_type = [ `Direct of string
| `Transactional of
config ->
Netchannels.out_obj_channel -> Netchannels.trans_out_obj_channel ]
The ouput type determines how generated data is buffered.
  • `Direct sep: Data written to the output channel of the activation object is not collected in a transaction buffer, but directly sent to the browser (the normal I/O buffering is still active, however, so call #flush to ensure that data is really sent). The method #commit_work of the output channel is the same as #flush. The method #rollback_work causes that the string sep is sent, meant as a separator between the already generated output, and the now following error message.
  • `Transactional f: A transactional channel tc is created from the real output channel ch by calling f cfg ch (here, cfg is the CGI configuration). The channel tc is propagated as the output channel of the activation object. This means that the methods commit_work and rollback_work are implemented by tc, and the intended behaviour is that data is buffered in a special transaction buffer until commit_work is called. This invocation forces the buffered data to be sent to the browser. If, however, rollback_work is called, the buffer is cleared.
Two important examples for `Transactional are:
  • The transaction buffer is implemented in memory:
          let buffered _ ch = new Netchannels.buffered_trans_channel ch in
          `Transactional buffered
          
  • The transaction buffer is implemented as an external file:
          `Transactional(fun _ ch -> new Netchannels.tempfile_output_channel ch)
          

val buffered_transactional_outtype : output_type
The output_type implementing transactions with a RAM-based buffer
val buffered_transactional_optype : output_type
Deprecated name for buffered_transactional_outtype
val tempfile_transactional_outtype : output_type
The output_type implementing transactions with a tempfile-based buffer
val tempfile_transactional_optype : output_type
Deprecated name for tempfile_transactional_outtype
type arg_store = cgi_environment ->
string ->
Netmime.mime_header_ro ->
[ `Automatic
| `Automatic_max of float
| `Discard
| `File
| `File_max of float
| `Memory
| `Memory_max of float ]
This is the type of functions arg_store so that arg_store env name header tells whether to `Discard the argument or to store it into a `File or in `Memory. The parameters passed to arg_store are as follows:

  • env is the CGI environment. Thus, for example, you can have different policies for different cgi_path_info.
  • name is the name of the argument.
  • header is the MIME header of the argument (if any).
Any exception raised by arg_store will be treated like if it returned `Discard. Note that the `File will be treated like `Memory except for `POST "multipart/form-data" and `PUT queries.

`Automatic means to store it into a file if the header contains a file name and otherwise in memory (strictly speaking `Automatic is not necessary since arg_store can check the header but is provided for your convenience).

`Memory_max (resp. `File_max, resp. `Automatic_max) is the same as `Memory (resp. `File, resp. `Automatic) except that the parameter indicates the maximum size in kB of the argument value. If the size is bigger, the Netcgi.cgi_argument methods #value and #open_value_rd methods will raise Netcgi.Argument.Oversized.

Remark: this allows for fine grained size constraints while Netcgi.config.input_content_length_limit option is a limit on the size of the entire request.

type exn_handler = cgi_environment -> (unit -> unit) -> unit 
A function of type exn_handler allows to define a custom handler of uncaught exceptions raised by the unit -> unit parameter. A typical example of exn_handler is as follows:
      let exn_handler env f =
        try f()
        with
        | Exn1 -> (* generate error page *)
            env#set_output_header_fields [...];
            env#send_output_header();
            env#out_channel#output_string "...";
            env#out_channel#close_out()
        | ...
      

type connection_directive = [ `Conn_close | `Conn_close_linger | `Conn_error of exn | `Conn_keep_alive ] 
Directive how to go on with the current connection:
  • `Conn_close: Just shut down and close descriptor
  • `Conn_close_linger: Linger, shut down, and close descriptor
  • `Conn_keep_alive: Check for another request on the same connection
  • `Conn_error e: Shut down and close descriptor, and handle the exception e


Specific connectors can be found in separate modules. For example:

A typical use is as follows:
    open Netcgi

    let main (cgi:cgi) =
       let arg = cgi#argument_value "name" in
       ...
       cgi#out_channel#commit_work()

    let () =
      let buffered _ ch = new Netchannels.buffered_trans_channel ch in
      Netcgi_cgi.run ~output_type:(`Transactional buffered) main
    

ocamlnet-4.1.2/doc/html-main/Uq_engines.async_out_channel-c.html0000644000175000017500000004413112731530351023300 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.async_out_channel

Class type Uq_engines.async_out_channel

class type async_out_channel = object .. end

method output : Bytes.t -> int -> int -> int
method close_out : unit -> unit
method pos_out : int
method flush : unit -> unit
method can_output : bool
method request_notification : (unit -> bool) -> unit
ocamlnet-4.1.2/doc/html-main/type_Netplex_kit.v_processor.html0000644000175000017500000005304312731530351023164 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.v_processor object
  method config_internal : (string * Netplex_types.polysocket_kind_box) list
  method container_event_system : unit -> Unixqueue.event_system
  method container_run : Unixqueue.event_system -> unit
  method global_exception_handler : exn -> bool
  method post_add_hook :
    Netplex_types.socket_service -> Netplex_types.controller -> unit
  method post_finish_hook :
    Netplex_types.socket_service ->
    Netplex_types.controller -> Netplex_types.container_id -> unit
  method post_rm_hook :
    Netplex_types.socket_service -> Netplex_types.controller -> unit
  method post_start_hook : Netplex_types.container -> unit
  method pre_finish_hook : Netplex_types.container -> unit
  method pre_start_hook :
    Netplex_types.socket_service ->
    Netplex_types.controller -> Netplex_types.container_id -> unit
  method virtual process :
    when_done:(unit -> unit) ->
    Netplex_types.container -> Unix.file_descr -> string -> unit
  method process_internal :
    when_done:(unit -> unit) ->
    Netplex_types.container -> Netplex_types.polyserver_box -> string -> unit
  method receive_admin_message :
    Netplex_types.container -> string -> string array -> unit
  method receive_message :
    Netplex_types.container -> string -> string array -> unit
  method shutdown : unit -> unit
  method virtual supported_ptypes : Netplex_types.parallelization_type list
  method system_shutdown : unit -> unit
  method workload_hook : Netplex_types.container -> bool -> int -> unit
end
ocamlnet-4.1.2/doc/html-main/Rpc_intro.html0000644000175000017500000020175412731530351017235 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_intro

Rpc_intro


Contents

Introduction to ocamlrpcgen

The tool ocamlrpcgen generates O'Caml modules which greatly simplify the creation and invocation of remote procedures. For example, if we have an XDR definition file calculate.x

program P {
  version V {
    int add(int,int) = 1;
  } = 2;
} = 3;

the generation of a corresponding RPC client is done by issuing the command

ocamlrpcgen -aux -clnt calculate.x

and the tool will generate an RPC server by calling

ocamlrpcgen -aux -srv calculate.x

The flag -aux causes ocamlrpcgen to create a module Calculate_aux containing types, and constants from the XDR definition, and containing conversion functions doing the language mapping from XDR to O'Caml and vice versa.

Calculate_aux defines the types for the arguments of the procedure and the result as follows:

type t_P'V'add'arg =                      (* Arguments *)
      ( Netnumber.int4 * Netnumber.int4 )
and t_P'V'add'res =                       (* Result *)
      Netnumber.int4

Note that the XDR integer type is mapped to Netnumber.int4 which is an opaque type representing 4-byte signed integers. Netnumber defines conversion functions for int4 to/from other O'Caml types. If Netnumber.int4 is not what you want, you can select a different integer mapping on the command line of ocamlrpcgen. For example, -int int32 selects that you want the built-in int32 integer type, and -int unboxed selects that you want the built-in int integer type. Note (1) that you can also select the integer mapping case-by-case (see below), and (2) that there is a corresponding switch for the XDR hyper type (8-byte integers).

Calculate_aux also defines constants (none in our example), conversion functions, XDR type terms, and RPC programs. These other kinds of definitions can be ignored for the moment.

Generating clients with ocamlrpcgen

The flag -clnt causes ocamlrpcgen to generate the module Calculate_clnt containing functions necessary to contact a remote program as client. Here, Calculate_clnt has the signature:

module P : sig
  module V : sig
    open Calculate_aux
    val create_client :
            ?esys:Unixqueue.event_system ->
            Rpc_client.connector ->
            Rpc.protocol ->
            Rpc_client.t
    val create_portmapped_client :
            ?esys:Unixqueue.event_system ->
            string ->
            Rpc.protocol ->
            Rpc_client.t
    val add : Rpc_client.t -> t_P'V'add'arg -> t_P'V'add'res
    val add'async :
            Rpc_client.t ->
            t_P'V'add'arg ->
            ((unit -> t_P'V'add'res) -> unit) ->
            unit
  end
end

(Note: Depending on the version of ocamlrpcgen your are using, another function create_client2 may also be generated.)

Normally, the function P.V.create_portmapped_client is the preferred function to contact the RPC program. For example, to call the add procedure running on host moon, the following statements suffice:

let m1 = 42 in
let m2 = 36 in
let client = Calculator_clnt.P.V.create_portmapped_client "moon" Rpc.Tcp in
let n = Calculator_clnt.P.V.add client (m1,m2) in
Rpc_client.shut_down client;

That's all for a simple client!

The invocation of P.V.create_portmapped_client first asks the portmapper on "moon" for the TCP instance of the program P.V, and stores the resulting internet port. Because we wanted TCP, the TCP connection is opened, too. When P.V.add is called, the values m1 and m2 are XDR-encoded and sent over the TCP connection to the remote procedure; the answer is XDR-decoded and returned, here n. Finally, the function Rpc_client.shut_down closes the TCP connection.

Of course, this works for UDP transports, too; simply pass Rpc.Udp instead of Rpc.Tcp.

The function P.V.create_client does not contact the portmapper to find out the internet port; you must already know the port and pass it as connector argument (see Rpc_client for details).

You could have also invoked add in an asynchronous way by using P.V.add'async. This function does not wait until the result of the RPC call arrives; it returns immediately. When the result value has been received, the function passed as third argument is called back, and can process the value. An application of asynchronous calls is to invoke two remote procedures at the same time:

let esys = Unixqueue.create_event_system() in
let client1 = Calculator_clnt.P.V.create_portmapped_client 
                ~esys:esys "moon" Rpc.Tcp in
let client2 = Calculator_clnt.P.V.create_portmapped_client 
                ~esys:esys "mars" Rpc.Tcp in
let got_answer1 get_value =
  let v = get_value() in
  print_endline "moon has replied!"; ... in
let got_answer2 get_value =
  let v = get_value() in
  print_endline "mars has replied!"; ... in
Calculator_clnt.P.V.add'async client1 (m1,m2) got_answer1;
Calculator_clnt.P.V.add'async client2 (m3,m4) got_answer1;
Unixqueue.run esys

Here, the two clients can coexist because they share the same event system (see the Unixqueue module); this system manages it that every network event on the connection to "moon" will be forwarded to client1 and that the network events on the connection to "mars" will be forwarded to client2. The add'async calls do not block; they only register themselves with the event system and return immediately. Unixqueue.run starts the event system: The XDR-encoded values (m1,m2) are sent to "moon", and (m3,m4) to "mars"; replies are recorded. Once the reply of "moon" is complete, got_answer1 is called; once the reply of "mars" has been fully received, got_answer2 is called. These functions can now query the received values by invoking get_value; note that get_value will either return the value or raise an exception if something went wrong. When both answers have been received and processed, Unixqueue.run will return.

Obviously, asynchronous clients are a bit more complicated than synchronous ones; however it is still rather simple to program them. For more information on how the event handling works, see Equeue_intro.

Note that clients have only a limited lifetime: After a shutdown or an error they become unusable. Since Ocamlnet version 3 there is another flavor of client, the so-called proxies. See The Rpc_proxy tutorial for an introduction. In particular, proxies can reconnect the connection to the server after a shutdown, and they can even manage several connections to the same server, or to different servers that are seen as equivalent.

Generating servers with ocamlrpcgen

The flag -srv causes ocamlrpcgen to generate the module Calculate_srv containing functions which can act as RPC servers. (Note: Recent versions of ocamlrpcgen also support a switch -srv2 that generates slightly better server stubs where one can bind several programs/versions to the same server port.) Here, Calculate_srv has the signature:

module P : sig
  module V : sig
    open Calculate_aux
    val create_server :
            ?limit:int ->
            proc_add : (t_P'V'add'arg -> t_P'V'add'res) ->
            Rpc_server.connector ->
            Rpc.protocol ->
            Rpc.mode ->
            Unixqueue.event_system ->
            Rpc_server.t
    val create_async_server :
            ?limit:int ->
            proc_add : (Rpc_server.session ->
                        t_P'V'add'arg ->
                        (t_P'V'add'res -> unit) ->
                        unit) ->
            Rpc_server.connector ->
            Rpc.protocol ->
            Rpc.mode ->
            Unixqueue.event_system ->
            Rpc_server.t
    end
end

There are two functions: P.V.create_server acts as a synchronous server, and P.V.create_async_server works as asynchronous server. Let's first explain the simpler synchronous case.

P.V.create_server accepts a number of labeled arguments and a number of anonymous arguments. There is always an optional limit parameter limiting the number of pending connections accepted by the server (default: 20); this is the second parameter of the Unix.listen system call. For every procedure p realized by the server there is a labeled argument proc_p passing the function actually computing the procedure. For synchronous servers, this function simply gets the argument of the procedure and must return the result of the procedure. In this example, we only want to realize the add procedure, and so there is only a proc_add argument. The anonymous Rpc_server.connector argument specifies the internet port (or the file descriptor) on which the server will listen for incoming connections. The Rpc.protocol argument defines whether this is a TCP-like (stream-oriented) or a UDP-like (datagram-oriented) service. The Rpc.mode parameter selects how the connector must be handled: Whether it acts like a socket or whether is behaves like an already existing bidirectional pipeline. Finally, the function expects the event system to be passed as last argument.

For example, to define a server accepting connections on the local loopback interface on TCP port 6789, the following statement creates such a server:

let esys = Unixqueue.create_event_system in
let server = 
  Calculate_srv.P.V.create_server
    ~proc_add: add
    (Rpc_server.Localhost 6789)            (* connector *)
    Rpc.Tcp                                (* protocol *)
    Rpc.Socket                             (* mode *)
    esys

Note that this statement creates the server, but actually does not serve the incoming connections. You need an additionally

Unixqueue.run esys

to start the service. (Note: If the server raises an exception, it will fall through to the caller of Unixqueue.run. The recommended way of handling this is to log the exception, and call Unixqueue.run again in a loop. If too many exceptions occur in very short time the program should terminate.)

Not all combinations of connectors, protocols, and modes are sensible. Especially the following values work:

  • TCP internet servers: One of the connectors Localhost or Portmapped; the protocol Rpc.Tcp; the mode Rpc.Socket
  • UDP internet servers: One of the connectors Localhost or Portmapped; the protocol Rpc.Udp; the mode Rpc.Socket
  • Stream-based Unix domain socket servers: The connector Unix, the protocol Rpc.Tcp; the mode Rpc.Socket
  • Datagram-based Unix domain socket servers: These are not supported
  • Serving an already accepted (inetd) stream connection: The connector Descriptor; the protocol Rpc.Tcp; the mode Rpc.BiPipe
The connector Portmapped registers the service at the local portmapper, and is the connector of choice.

Note that servers with mode=Socket never terminate; they wait forever for service requests. On the contrary, servers with mode=BiPipe process only the current (next) request, and terminate then.

The resulting server is synchronous because the next request is only accepted after the previous request has been finished. This means that the calls are processed in a strictly serialized way (one after another); however, the network traffic caused by the current and by previous calls can overlap (to maximize network performance).

In contrast to this, an asynchronous server needs not respond immediately to an RPC call. Once the call has been registered, the server is free to reply whenever it likes to, even after other calls have been received. For example, you can synchronize several clients: Only after both clients A and B have called the procedure sync, the replies of the procedures are sent back:

let client_a_sync = ref None
let client_b_sync = ref None

let sync s arg send_result =
  if arg.name_of_client = "A" then
    client_a_sync := Some send_result;
  if arg.name_of_client = "B" then
    client_b_sync := Some send_result;
  if !client_a_sync <> None && !client_b_sync <> None then (
    let Some send_result_to_a = !client_a_sync in
    let Some send_result_to_b = !client_b_sync in
    send_result_to_a "Synchronized";
    send_result_to_b "Synchronized";
  )

let server =
  Sync.V.create_async_server
    ~proc_sync: sync
    ...

Here, the variables client_a_sync and client_b_sync store whether one of the clients have already called the sync service, and if so, the variables store also the function that needs to be called to pass the result back. For example, if A calls sync first, it is only recorded that there was such a call; because send_result is not invoked, A will not get a reply. However, the function send_result is stored in client_a_sync such that it can be invoked later. If B calls the sync procedure next, client_b_sync is updated, too. Because now both clients have called the service, synchronization has happed, and the answers to the procedure calls can be sent back to the clients. This is done by invoking the functions that have been remembered in client_a_sync and client_b_sync; the arguments of these functions are the return values of the sync procedure.

It is even possible for an asynchronous server not to respond at all; for example to implement batching (the server receives a large number of calls on a TCP connection and replies only to the last call; the reply to the last call implicitly commits that all previous calls have been received, too).

To create multi-port servers, several servers can share the same event system; e.g.

let esys = Unixqueue.create_event_system in
let tcp_server = 
  P.V.create_server ... Rpc.Tcp ... esys in
let udp_server = 
  P.V.create_server ... Rpc.Udp ... esys in
Unixqueue.run esys

(Note: To create servers that implement several program or version definitions, look for what the -srv2 switch of ocamlrpcgen generated.)

Debugging aids

There are some built-in debugging aids for developing RPC clients and servers. Debug messages can be enabled by setting certain variables to true:

The messages are output via Netlog.Debug, and have a `Debug log level.

In Netplex context, the messages are redirected to the current Netplex logger, so that they appear in the normal log file. Also, messages are suppressed when they refer to the internally used RPC clients and servers.

Command line arguments of ocamlrpcgen

The tool accepts the following options:

usage: ocamlrpcgen [-aux] [-clnt] [-srv] [-srv2]
                   [-int   (abstract | int32 | unboxed) ]
                   [-hyper (abstract | int64 | unboxed) ]  
                   [-cpp   (/path/to/cpp | none) ]
                   [-D var=value]
                   [-U var]
                   [-direct]
                   file.xdr ...

  • -aux: Creates for every XDR file the auxiliary module containing the type and constant definitions as O'Caml expressions, and containing the conversion functions implementing the language mapping.
  • -clnt: Creates for every XDR file a client module.
  • -srv: Creates for every XDR file a server module.
  • -srv2: Creates for every XDR file a new-style server module.
  • -int abstract: Uses Netnumber.int4 for signed ints and Netnumber.uint4 for unsigned ints as default integer representation. This is the default.
  • -int int32: Uses int32 for both signed and unsigned ints as default integer representation. Note that overflows are ignored for unsigned ints; i.e. large unsigned XDR integers are mapped to negative int32 values.
  • -int unboxed: Uses Pervasives.int for both signed and unsigned ints as default integer representation. XDR values outside the range of O'Camls 31 bit signed ints are rejected (raise an exception).
  • -hyper abstract: Uses Netnumber.int8 for signed ints and Netnumber.uint8 for unsigned ints as default hyper (64 bit integer) representation. This is the default.
  • -hyper int64: Uses int64 for both signed and unsigned ints as default hyper representation. Note that overflows are ignored for unsigned ints; i.e. large unsigned XDR hypers are mapped to negative int64 values.
  • -hyper unboxed: Uses Pervasives.int for both signed and unsigned ints as default hyper representation. XDR values outside the range of O'Camls 31 bit signed ints are rejected (raise an exception).
  • -cpp /path/to/cpp: Applies the C preprocessor found under /path/to/cpp on the XDR files before these are processed. The default is -cpp cpp (i.e. look up the cpp command in the command search path).
  • -cpp none: Does not call the C preprocessor.
  • -D var=value: Defines the C preprocessor variable var with the given value.
  • -U var: Undefines the C preprocessor variable var.
  • -direct: The effect of this switch is that ocamlrpcgen generates different code that directly maps the XDR byte representation to the final OCaml values, and bypasses Netxdr.xdr_value as much as possible. This is the same style the traditional rpcgen preferred. The code is faster (up to 50% for certain large values), but also much longer. As a rule of thumb, this style is only a win if you have arrays of structs, and these structs have many elements, and there are not many strings (because there is no acceleration for strings). For example, a numerical RPC interface would definetely profit from this alternate code generation scheme. Except generating more code, there is no downside of this scheme. (Available since Ocamlnet-3.5.)

The language mapping underlying ocamlrpcgen

The language mapping determines how the XDR types are mapped to O'Caml types. See also Rpc_mapping_ref.

The XDR syntax

From RFC 1832:

      declaration:
           type-specifier identifier
         | type-specifier identifier "[" value "]"
         | type-specifier identifier "<" [ value ] ">"
         | "opaque" identifier "[" value "]"
         | "opaque" identifier "<" [ value ] ">"
         | "string" identifier "<" [ value ] ">"
         | type-specifier "*" identifier
         | "void"

      value:
           constant
         | identifier

      type-specifier:
           [ "unsigned" ] "int"
         | [ "unsigned" ] "hyper"
         | "float"
         | "double"
         | "quadruple"
         | "bool"
         | enum-type-spec
         | struct-type-spec
         | union-type-spec
         | identifier

      enum-type-spec:
         "enum" enum-body

      enum-body:
         "{"
            ( identifier "=" value )
            ( "," identifier "=" value )*
         "}"

      struct-type-spec:
         "struct" struct-body

      struct-body:
         "{"
            ( declaration ";" )
            ( declaration ";" )*
         "}"

      union-type-spec:
         "union" union-body

      union-body:
         "switch" "(" declaration ")" "{"
            ( "case" value ":" declaration ";" )
            ( "case" value ":" declaration ";" )*
            [ "default" ":" declaration ";" ]
         "}"

      constant-def:
         "const" identifier "=" constant ";"

      type-def:
           "typedef" declaration ";"
         | "enum" identifier enum-body ";"
         | "struct" identifier struct-body ";"
         | "union" identifier union-body ";"

      definition:
           type-def
         | constant-def

      specification:
           definition *

ocamlrpcgen supports a few extensions to this standard, see below.

Syntax of RPC programs

From RFC 1831:

   program-def:
      "program" identifier "{"
         version-def
         version-def *
      "}" "=" constant ";"

   version-def:
      "version" identifier "{"
          procedure-def
          procedure-def *
      "}" "=" constant ";"

   procedure-def:
      type-specifier identifier "(" type-specifier
        ("," type-specifier )* ")" "=" constant ";"

Mapping names

Because XDR has a different naming concept than O'Caml, sometimes identifiers must be renamed. For example, if you have two structs with equally named components

struct a {
  t1 c;
  ...;
}

struct b {
  t2 c;
  ...;
}

the corresponding O'Caml types will be

type a = { c : t1; ... }
type b = { c' : t2; ... }

i.e. the second occurrence of c has been renamed to c'. Note that ocamlrpcgen prints always a warning for such renamings that are hard to predict.

Another reason to rename an identifier is that the first letter has the wrong case. In O'Caml, the case of the first letter must be compatible with its namespace. For example, a module name must be uppercase. Because RPC programs are mapped to O'Caml modules, the names of RPC programs must begin with an uppercase letter. If this is not the case, the identifier is (quietly) renamed, too.

You can specify the O'Caml name of every XDR/RPC identifier manually: Simply add after the definition of the identifier the phrase => ocaml_id where ocaml_id is the preferred name for O'Caml. Example:

struct a {
  t1 c => a_c;
  ...;
}

struct b {
  t2 c => b_c;
  ...;
}

Now the generated O'Caml types are

type a = { a_c : t1; ... }
type b = { b_c : t2; ... }

This works wherever a name is defined in the XDR file.

Directives for name mapping

Since Ocamlnet-3.6.7, there are now also a few directives influencing the name mapping for structs, unions, and enums:

  • _lowercase: the XDR name is lowercased
  • _uppercase: the XDR name is uppercased
  • _capitalize: the XDR name is capitalized
  • _prefix "p": this prefix is prepended to the XDR name
It is possible to specify several directives, which are then applied one after the other.

  • For structs, these directives control the name mapping of the elements. Place the directives before the left brace, e.g.
         struct a _lowercase _prefix "a_" {
           T1 string;
           T2 float;
         };
       
    This would generate the record type type a = { a_t1 : string; a_t2 : float } .
  • For enums, these directives control the name mapping of the generated constants. Again, place the directives before the left brace, e.g.
         enum x _lowercase {
           ONE = 1,
           TWO = 2
         };
       
    The generated OCaml constants have here names one and two.
  • For unions, the directives control the name mapping of the discriminating cases (when an enum is used for that). Place the directives before the switch keyword, e.g.
         union u _lowercase _capitalize switch (x discr) {
           case ONE: void;
           case TWO: double x;
         };
       
    This would generate the variant type [`One | `Two of float] in the Ocaml mapping.

Mapping integer types

XDR defines 32 bit and 64 bit integers, each in a signed and unsigned variant. As O'Caml does only know 31 bit signed integers (type int; the so-called unboxed integers), 32 bit signed integers (type int32), and 64 bit signed integers (type int64), it is unclear how to map the XDR integers to O'Caml integers.

The module Netnumber defines the opaque types int4, uint4, int8, and uint8 which exactly correspond to the XDR types. These are useful to pass integer values through to other applications, and for simple identification of things. However, you cannot compute directly with the Netnumber integers. Of course, Netnumber also provides conversion functions to the basic O'Caml integer types int, int32, and int64, but it would be very inconvenient to call these conversions for every integer individually.

Because of this, ocamlrpcgen has the possibility to specify the O'Caml integer variant for every integer value (and it generates the necessary conversion invocations automatically). The new keywords _abstract, _int32, _int64, and _unboxed select the variant to use:

  • _abstract int: A signed 32 bit integer mapped to Netnumber.int4
  • _int32 int: A signed 32 bit integer mapped to int32
  • _int64 int: A signed 32 bit integer mapped to int64
  • _unboxed int: A signed 32 bit integer mapped to int
  • unsigned _abstract int: An unsigned 32 bit integer mapped to Netnumber.uint4
  • unsigned _int32 int: An unsigned 32 bit integer mapped to int32 (ignoring overflows)
  • unsigned _int64 int: An unsigned 32 bit integer mapped to int64
  • unsigned _unboxed int: An unsigned 32 bit integer mapped to int
Note that the 32 bits of the unsigned integer are simply casted to the 32 bits of int32 in the case of unsigned _int32 int (the meaning of the sign is ignored). In contrast to this, the _unboxed specifier causes a language mapping rejecting too small or too big values.

A similar mapping can be specified for the 64 bit integers (hypers):

  • _abstract hyper: A signed 64 bit integer mapped to Netnumber.int8
  • _int64 hyper: A signed 64 bit integer mapped to int64
  • _unboxed hyper: A signed 64 bit integer mapped to int
  • unsigned _abstract hyper: An unsigned 64 bit integer mapped to Netnumber.uint8
  • unsigned _int64 hyper: An unsigned 64 bit integer mapped to int64
  • unsigned _unboxed hyper: An unsigned 64 bit integer mapped to int
Again, unsigned _int64 hyper causes that the 64 bits of the XDR values are casted to int64.

If the keyword specifying the kind of language mapping is omitted, the default mapping applies. Unless changed on the command line (options -int and -hyper), the default mapping is _abstract.

Mapping floating-point types

The XDR types single and double are supported and both mapped to the O'Caml type float. The XDR type quadruple is not supported.

The code for double assumes that the CPU represents floating-point numbers according to the IEEE standards.

Mapping string and opaque types

Strings and opaque values are mapped to O'Caml strings. If strings have a fixed length or a maximum length, this constraint is checked when the conversion is performed.

Since Ocamlnet-3, strings can be declared as "managed" in the XDR file, e.g.

typedef _managed string s<>;

A managed string is mapped to the object type Netxdr_mstring.mstring. The idea of managed strings is to avoid data copies as much as possible, and to introduce some freedom of representation. In particular, managed strings can be backed by normal strings or by bigarrays of char. The RPC library chooses the representation that works best, and avoids copying so far possible.

Mapping array types

Arrays are mapped to O'Caml arrays. If arrays have a fixed length or a maximum length, this constraint is checked when the conversion is performed.

Mapping record types (structs)

Structs are mapped to O'Caml records by default. The elements are mutable.

Since Ocamlnet-3.6.7 it is possible to add an equality constraint, e.g.

struct x _equals "MyModule.x" {
  ...
};

would generate

type x = MyModule.x = { ... }

Another option since 3.6.7 is to request a tuple instead of a record:

struct x _tuple { ... }

Mapping enumerated types (enums)

Enumerated types are mapped to Netnumber.int4 (always, regardless of what the -int option specifies). The enumerated constants are mapped to let-bound values of the same name. Example: The XDR definition

enum e {
  A = 1;
  B = 2;
}

generates the following lines of code in the auxiliary module:

type e = Netnumber.int4;;
val a : Netnumber.int4;;
val b : Netnumber.int4;;

However, when the XDR conversion is performed, it is checked whether values of enumerators are contained in the set of allowed values.

The special enumerator bool is mapped to the O'Caml type bool.

Mapping union types discriminated by enumerations

Often, XDR unions are discriminated by enumerations, so this case is handled specially. For every case of the enumerator, a polymorphic variant is generated that contains the selected arm of the union. Example:

enum e {
  A = 1;
  B = 2;
  C = 3;
  D = 4;
}

union u (e discr) {
  case A: 
    int x;
  case B:
    hyper y;
  default:
    string z;
}

This is mapped to the O'Caml type definitions:

type e = Netnumber.int4;;
type u =
  [ `a of Netnumber.int4
  | `b of Netnumber.int8
  | `c of string
  | `d of string
  ]

Note that the identifiers of the components (discr, x, y, z) have vanished; they are simply not necessary in a sound typing environment. Also note that the default case has been expanded; because the cases of the enumerator are known it is possible to determine the missing cases meant by default and to define these cases explicitly.

Mapping union types discriminated by integers

If the discriminant has integer type, a different mapping scheme is used. For every case occuring in the union definition a separate polymorphic variant is defined; if necessary, an extra default variant is added. Example:

union u (int discr) {
  case -1: 
    int x;
  case 1:
    hyper y;
  default:
    string z;
}

This is mapped to the O'Caml type definition:

type u = 
  [ `__1 of Netnumber.int4
  | `_1  of Netnumber.int8
  | `default of (Netnumber.int4 * string)
  ]

Note that positive cases get variant tags of the form "_n" and that negative cases get variant tags of the form "__n". The default case is mapped to the tag `default with two arguments: First the value of the discriminant, second the value of the default component.

This type of mapping is not recommended, and only provided for completeness.

Mapping option types (*)

The XDR * type is mapped to the O'Caml option type. Example:

typedef string *s;

is mapped to

type s = string option

Mapping recursive types

Recursive types are fully supported. Unlike in the C language, you can recursively refer to types defined before or after the current type definition. Example:

typedef intlistbody *intlist;   /* Forward reference */
typedef struct {
  int value;
  intlist next;
} intlistbody;

This is mapped to:

type intlist = intlistbody option
and intlistbody = 
  { value : Netnumber.int4;
    next : intlist;
  }

However, it is not checked whether there is a finite fixpoint of the recursion. The O'Caml compiler will do this check anyway, so it not really needed within ocamlrpcgen.

Overview over the RPC library

Normally, only the following modules are of interest:

  • Netnumber: Supports serialization/deserialization of the basic integer and fp types
  • Rpc: Contains some types needed everyhwere
  • Rpc_client: Contains the functions supporting RPC clients
  • Rpc_server: Contains the functions supporting RPC servers
  • Rpc_portmapper: Functions to contact the portmapper service
  • Rpc_auth_sys: AUTH_SYS style authentication.

Netplex RPC systems

If you need multi-processing for your RPC program, the Netplex library might be a good solution (see Netplex_intro). It is limited to stream connections (TCP), however. With Netplex it is possible to develop systems of RPC services that connect to each other to do a certain job. Effectively, Netplex supports a component-based approach comparable to Corba, DCOM or Java Beans, but much more lightweight and efficient. In the following we call our technology Netplex RPC systems.

In this section it is assumed that you are familiar with the Netplex concepts (see Netplex_intro for an introduction).

The module Rpc_netplex (part of the netplex findlib library) allows us to encapsulate RPC servers as Netplex services. For instance, to turn the calculate.x example of above into a service we can do

let factory =
  Rpc_netplex.rpc_factory
    ~name:"Calculate"
    ~configure:(fun _ _ -> ())
    ~setup:(fun srv () ->
             Calculate_srv.bind
	        ~proc_add: add
                srv
           )
    ()

and pass this factory to Netplex_main.startup. Note that we have to generate calculate_srv.ml with the -srv2 switch of ocamlrpcgen, otherwise Calculate_srv.bind is not available.

In the netplex config file we can refer to (and enable) this service by a section like

    service {
        name = "Calculate_service"            (* An arbitrary service name *)
        protocol {
	    name = "Calculate_proto"          (* An arbitrary protocol name *)
            address {
	        type = "internet";
                bind = "0.0.0.0:2123"
            }
        };
        processor {
            type = "Calculate"                (* The ~name from above *)
        };
        workload_manager {
            type = "constant";
            threads = 1;                      (* Run in 1 process/thread *)
        };
    }

The interesting points of this technology are:

  • You can bundle several services into one program. The services can be RPC-implemented or by using other protocol modules that are compatible with Netplex like the Nethttpd_plex web server.
  • You can profit from multi-processing or multi-threading.
  • Netplex provides a framework for logging, a message bus, and start/stop.
Currently, there is no directory service where one can register services by name and look them up. Such a service is under development, however, and will be released once the major functions work.

Restrictions of the current implementation

The authentication styles AUTH_DH and AUTH_LOCAL are not yet supported on all platforms.

The implementation uses an intermediate, symbolic representation of the values to transport over the network. This may restrict the performance.

Quadruple-precision fp numbers are not supported.

RPC broadcasts are not supported.

TI-RPC and rpcbind versions 3 and 4 are not supported. (Note: There is some restricted support to contact existing TI-RPC servers over local transport in the Rpc_xti module.)
ocamlnet-4.1.2/doc/html-main/Netx509_pubkey.Encryption.html0000644000175000017500000004637012731530351022163 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey.Encryption

Module Netx509_pubkey.Encryption

module Encryption: sig .. end


These algorithms are used for encryption/decryption
val rsa : Netx509_pubkey.encrypt_alg
alias RSAES-PKCS1-v1_5
val rsaes_oaep : hash_function:Netx509_pubkey.hash_function ->
maskgen_function:Netx509_pubkey.maskgen_function ->
psource_function:string -> Netx509_pubkey.encrypt_alg
RSAES-OAEP
val catalog : (string * string list * Netx509_pubkey.encrypt_alg * Netx509_pubkey.oid) list
(name, aliases, oid, pubkey_oid)
val encrypt_alg_of_pubkey : Netx509_pubkey.pubkey -> Netx509_pubkey.encrypt_alg
Normally use the algorithm that is present in the public key
val alg_id_of_encrypt_alg : Netx509_pubkey.encrypt_alg -> Netx509_pubkey.alg_id
Get the alg_id of an encryption alg
val key_oid_of_encrypt_alg : Netx509_pubkey.encrypt_alg -> Netx509_pubkey.oid
The OID public keys need to have
ocamlnet-4.1.2/doc/html-main/Netplex_kit.processor_base-c.html0000644000175000017500000004431112731530351023006 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.processor_base

Class virtual Netplex_kit.processor_base

class virtual processor_base : Netplex_types.processor_hooks -> v_processor
A virtual (incomplete) base class for processors. As argument the user-supplied hooks are passed in. Use this class as in:

    class my_processor hooks =
    object(self)
      inherit Netplex_kit.processor_base hooks
      method process ~when_done container fd proto_name = ...
      method supported_ptypes = ...
    end
 

In order to run actions from hooks, redefine the hook methods as in:

    class my_processor hooks =
    object(self)
      inherit Netplex_kit.processor_base hooks as super
      method process ~when_done container fd proto_name = ...
      method supported_ptypes = ...
      method post_start_hook container =
        ... (* my action *);
        super # post_start_hook container
    end
 


ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.Operators.html0000644000175000017500000004440312731530351023750 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.Operators sig
  val ( ++ ) :
    '#Uq_engines_compat.engine ->
    ('-> '#Uq_engines_compat.engine) -> 'Uq_engines_compat.engine
  val ( >> ) :
    '#Uq_engines_compat.engine ->
    ('Uq_engines_compat.final_state -> 'Uq_engines_compat.final_state) ->
    'Uq_engines_compat.engine
  val eps_e :
    'Uq_engines_compat.engine_state ->
    Unixqueue.event_system -> 'Uq_engines_compat.engine
end
ocamlnet-4.1.2/doc/html-main/Neturl_tut.html0000644000175000017500000006753412731530351017451 0ustar gerdgerd Ocamlnet 4 Reference Manual : Neturl_tut

Neturl_tut


Neturl Tutorial

This module is a quite flexible parser for various kinds of URLs occuring in practice. The syntax is configurable such that one URL module can handle a lot of URL types in a generic way.

Generic Parsing

In order to parse an absolute URL (beginning with a scheme identifier like "http:...") of unknown type just call

 
let url = parse_url "http://me@server/directory"

By default, this function can parse all URL types listed at Neturl.common_url_syntax. However, the default configuration implies also that

  • relative URLs cannot be parsed
  • fragment identifiers are rejected (i.e. the part after the hash mark like in "http://server/document#location")
  • characters are rejected when the most significant bit (MSB) is set
The latter two features can be simply enabled by passing the arguments ~enable_fragment:true and ~accept_8bits:true, respectively.

The restriction that relative URLs are rejected has to do with the problem that context information is missing. Because the scheme identifier (like "http") is not available, the function does not know which syntax the relative URL should have. For example, the relative URL dir/file?x=1 is differently parsed when it is taken relative to an http URL and when it is interpreted relative to an ftp URL. In the first case, the path component of the URL is "dir/file" and the query component is "?x=1", but in the latter case the path component is "dir/file?x=1", and a query component is not allowed.

The solution is that the syntax of the base URL, relative to which the URL is seen, must be passed as additional argument. Under the assumption that base_url is the base URL, use

let url = parse_url 
            ~base_syntax:(url_syntax_of_url base_url) 
            "/dir/file?x=1"
Of course, this assumes that the base URL is known when the url is parsed.

Parsing For a Certain Syntax

The function url_of_string is also a parser, but you must pass the URL syntax as argument, e.g.

let url = url_of_string syntax "ipp://server/printer"
Pass as syntax one of the elements of Neturl.common_url_syntax, e.g.
 let syntax = Hashtbl.find common_url_syntax "ipp" 
or a self-defined syntax.

Printing URLs

This is much easier, just call string_of_url to convert an URL to a string. It is ensured that every URL always has an unambiguous representation as string.

URL Components

Internally, the parsed URL is decomposed into its components. This module supports two ways of decomposition:

  1. scheme://user;userparams:password@host:port/path;params?query#fragment
  2. scheme:other;params?query#fragment
The first form is used for services that directly connect to a certain service running on a certain host. The second form can be used for everything else not falling under this category.

Examples:

  • http://me:abrakadabra@server/dir?x=5#section1

    scheme="http", user="me", password="abrakadabra", host="server", path="/dir", query="x=5", fragment="section1"

  • pop://you;auth=digest-md5@mail

    scheme="pop", user="you", user_params=["auth=digest-md5"], host="mail"

  • mailto:gerd@gerd-stolpmann.de?cc=you@domain.com

    scheme="mailto", other="gerd@gerd-stolpmann.de", query="cc=you@domain.com"

It is important to mention that the decomposition is not fully performed, but only down to a certain level. For example, the query "x=5" could be further analysed and be split into the syntactic parts "x" and "5". However, this is not done, just because the author seeked a compromise between the depth of analysis and the genericy of application.

URL Escaping

In order to represent the so-called unsafe characters, one can use %-escaping in URLs. For example, this URL contains a password with @, an unsafe character encoded as %40:

 http://user:!$%40?@server 
The question is how this module handles such escapings.

It is surprising that the URL parser does not decode these escaped forms (it checks, however, whether they are syntactically correct). Internally, the components are stored as parsed, and one can even retrieve them in their original form. The function url_password returns the password component. Applied to the above URL, one can get the password in its original, "encoded" form, or as decoded string:

  • url_password ~encoded:true url returns "!$%40?"
  • url_password url returns "!$@?"

Representation of URL Components

The URL components can be retrieved with the functions

  • url_scheme
  • url_user
  • url_user_param
  • url_password
  • url_host
  • url_port
  • url_path
  • url_param
  • url_query
  • url_fragment
  • url_other
Most components are just strings. Of course, the port number is an integer.

The path component (url_path) has a non-obvious representation. The path is represented as string list, e.g. "a/b/c" is represented as ["a";"b";"c"] . Note, however, that absolute paths have an empty string at the beginning of the list, e.g. "/a/b/" is [""; "a"; "b"; "" ] . In most cases, the paths found in URLs are absolute, and because of this it is quite common to find this empty string at the beginning of the path list. The corner cases are:

  • [] is used when the path is missing in the URL
  • [ "" ] is "/"
  • [ ""; "" ] is considered as illegal
The last two cases are somewhat arbitrary.

There is the helper function split_path to convert the string representation of paths into the list representation.

The parameters (url_user_param and url_param) are lists, too. A parameter starts with a semicolon as delimiter and runs until the next component, which can be another parameter. The contents, i.e. the values after the semicolons are put into the list. For example, the parameter ";auth=unix;type=i" is represented as ["auth=unix"; "type=i"] .

Hint: Getting Query Arguments

The query component is represented as a single string. When queries use the standard syntax "name1=value1&name2=value2&...", one can parse this string using

let args = Netencoding.Url.dest_url_encoded_parameters
             (url_query ~encoded:true url)
Note that encoded:true is needed.

Creating and Modifying URLs

In order to create a URL for a certain syntax, call make_url:

let url = make_url 
            ~scheme:"http"
            ~user:"user"
            ~password:"!$@?"
            ~host:"server"
            syntax
It is checked whether the URL conforms to the passed syntax. By default, the components are passed in decoded form, and make_url automatically encodes them if necessary (here, for example, the at sign in the password). Alternatively, one can set ~encoded:true, and pass the already escaped components. In this case, make_url checks whether the encoding is sufficient to represent the URL as string.

The functions modify_url, default_url, undefault_url, and remove_from_url can be used to modify an existing URL.

Relative URLs

A URL is relative when the scheme identifier at the beginning is omitted. In this case, the URL can be transformed to an absolute URL when the base URL is known. The algorithm for this is defined in RFC 1808, and quite complicated. It is implemented in apply_relative_url, but usually Neturl.ensure_absolute_url is the more convenient function. Just call

 let url' = ensure_absolute_url ~base url 
to convert url to its absolute counterpart url' when it is relative, and to pass the URL unchanged when it is already absolute.


ocamlnet-4.1.2/doc/html-main/type_Netaux.ArrayAux.html0000644000175000017500000004415612731530352021340 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaux.ArrayAux sig
  val int_blit : int array -> int -> int array -> int -> int -> unit
  val int_series : int array -> int -> int array -> int -> int -> int -> unit
  val int_blit_ref :
    (int array -> int -> int array -> int -> int -> unit) Pervasives.ref
  val int_series_ref :
    (int array -> int -> int array -> int -> int -> int -> unit)
    Pervasives.ref
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_pollset_posix.html0000644000175000017500000004163012731530352022604 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset_posix sig
  val poll_based_pollset : unit -> Netsys_pollset.pollset
  val reset : unit -> unit
  val accelerated_pollset : unit -> Netsys_pollset.pollset
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.PUBKEY_CRYPTO.html0000644000175000017500000005414512731530352024547 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.PUBKEY_CRYPTO sig
  type public_key
  type private_key
  type pin_callback
  type algorithm
  val supported_x509 : int array list
  val algorithm_x509 :
    int array -> string option -> Netsys_crypto_types.PUBKEY_CRYPTO.algorithm
  val import_public_key_x509 :
    string -> Netsys_crypto_types.PUBKEY_CRYPTO.public_key
  val import_public_key_uri :
    string -> Netsys_crypto_types.PUBKEY_CRYPTO.public_key
  val import_public_key_uri_with_pin :
    Netsys_crypto_types.PUBKEY_CRYPTO.pin_callback ->
    string -> Netsys_crypto_types.PUBKEY_CRYPTO.public_key
  type x509_private_key = string * string
  val import_private_key_x509 :
    Netsys_crypto_types.PUBKEY_CRYPTO.x509_private_key ->
    Netsys_crypto_types.PUBKEY_CRYPTO.private_key
  val import_private_key_uri :
    string -> Netsys_crypto_types.PUBKEY_CRYPTO.private_key
  val import_private_key_uri_with_pin :
    Netsys_crypto_types.PUBKEY_CRYPTO.pin_callback ->
    string -> Netsys_crypto_types.PUBKEY_CRYPTO.private_key
  val import_public_key_from_private :
    Netsys_crypto_types.PUBKEY_CRYPTO.private_key ->
    Netsys_crypto_types.PUBKEY_CRYPTO.public_key
  val simple_pin_callback :
    (unit -> string) -> Netsys_crypto_types.PUBKEY_CRYPTO.pin_callback
  val encrypt :
    Netsys_crypto_types.PUBKEY_CRYPTO.algorithm ->
    Netsys_crypto_types.PUBKEY_CRYPTO.public_key -> string -> string
  val decrypt :
    Netsys_crypto_types.PUBKEY_CRYPTO.algorithm ->
    Netsys_crypto_types.PUBKEY_CRYPTO.private_key -> string -> string
  val verify :
    Netsys_crypto_types.PUBKEY_CRYPTO.algorithm ->
    Netsys_crypto_types.PUBKEY_CRYPTO.public_key -> string -> string -> bool
  val sign :
    Netsys_crypto_types.PUBKEY_CRYPTO.algorithm ->
    Netsys_crypto_types.PUBKEY_CRYPTO.private_key -> string -> string
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client_conncache.restrictive_cache.html0000644000175000017500000004073712731530352027014 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client_conncache.restrictive_cache unit -> Nethttp_client_conncache.connection_cacheocamlnet-4.1.2/doc/html-main/type_Netchannels.rec_in_channel_delegation.html0000644000175000017500000004107712731530352025723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.rec_in_channel_delegation ?close:bool -> Netchannels.rec_in_channel -> Netchannels.rec_in_channelocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.SCRAM_SHA256.html0000644000175000017500000004066612731530352023731 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM_SHA256 Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/Netmcore_ref.html0000644000175000017500000005123012731530352017677 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_ref

Module Netmcore_ref

module Netmcore_ref: sig .. end
Shared mutable variables

type 't sref 
type 't sref_descr 
The marshallable descriptor of a reference
val sref : Netmcore.res_id -> 't -> 't sref
The shared version of ref: Creates a mutable shared variable in the given memory pool
val assign : 't sref -> 't -> unit
assign sr x: Sets the contents of sr to a deep copy of x. While performing the assignment the heap is write-locked, and no other assign can run.
val deref_ro : 't sref -> 't
Dereferences the variable and returns the contents, comparable to !. Note that this returns a value that lives in shared memory, and there is no guarantee that this value still exists if assign operations are done in parallel, and old version are garbage-collected. If such values are accessed the program may crash!
val deref_p : 't sref -> ('t -> 'a) -> 'a
deref_p sr f: Runs f with the contents of sr, and returns the result of f. While f is being executed, the current contents are specially protected so that they cannot be garbage collected, even if a parallel assign changes the current value of the variable. (Suffix "_p" = pinning version.)
val deref_c : 't sref -> 't
deref_c sr: Returns a copy of the contents of sr. The copy is created in normal memory. (Suffix "_c" = copying version.)
val heap : 't sref -> Obj.t Netmcore_heap.heap
Returns the backing heap structure
val descr_of_sref : 't sref -> 't sref_descr
Returns the descriptor
val sref_of_descr : Netmcore.res_id -> 't sref_descr -> 't sref
Look up the reference for this descriptor
ocamlnet-4.1.2/doc/html-main/Netaccel.html0000644000175000017500000004350712731530352017015 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaccel

Module Netaccel

module Netaccel: sig .. end
Accelerators for bytecode

This module can be linked with executables to accelerate certain functions. In particular, the following functions will run faster:

It is not recommended to install the accelerators for native code, however (and with the distributed build rules, this is not done).

To link this module, you must name both netaccel.cma and netaccel_link.cmo explicitly on the ocamlc command line (after netstring.cma). If you use findlib, this is done automatically.


ocamlnet-4.1.2/doc/html-main/type_Uq_resolver.html0000644000175000017500000005175512731530352020652 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_resolver sig
  type 't engine_state =
      [ `Aborted | `Done of '| `Error of exn | `Working of int ]
  class type ['t] engine =
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        ('Uq_resolver.engine -> bool) -> unit
      method state : 'Uq_resolver.engine_state
    end
  exception Host_not_found of string
  class type resolver =
    object
      method host_by_name :
        string ->
        Unixqueue.event_system -> Unix.host_entry Uq_resolver.engine
      method ipv6 : bool
    end
  val get_host_by_name :
    ?resolver:Uq_resolver.resolver -> string -> Unix.host_entry
  val sockaddr_of_socksymbol :
    ?resolver:Uq_resolver.resolver -> Netsockaddr.socksymbol -> Unix.sockaddr
  val default_resolver : unit -> Uq_resolver.resolver
  val gai_resolver : ?ipv4:bool -> ?ipv6:bool -> unit -> Uq_resolver.resolver
  val current_resolver : unit -> Uq_resolver.resolver
  val set_current_resolver : Uq_resolver.resolver -> unit
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_engine.buffering_engine_processing_config-c.html0000644000175000017500000004235212731530352027707 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.buffering_engine_processing_config

Class Nethttpd_engine.buffering_engine_processing_config

class buffering_engine_processing_config : http_engine_processing_config
Implements the synchronisation by buffering

ocamlnet-4.1.2/doc/html-main/Uq_engines.delay_engine-c.html0000644000175000017500000004314112731530352022230 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.delay_engine

Class Uq_engines.delay_engine

class ['a] delay_engine : float -> (unit -> 'a #engine) -> Unixqueue.event_system -> ['a] engine
let de = delay_engine d f esys: The engine e = f() is created after d seconds, and the result of e becomes the result of de.

ocamlnet-4.1.2/doc/html-main/Netx509.x509_certificate_from_ASN1-c.html0000644000175000017500000004257412731530352023551 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_certificate_from_ASN1

Class Netx509.x509_certificate_from_ASN1

class x509_certificate_from_ASN1 : Netasn1.Value.value -> x509_certificate
Parses the passed ASN.1 value and returns the certificate object

ocamlnet-4.1.2/doc/html-main/Netconversion.html0000644000175000017500000035314312731530352020133 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netconversion

Module Netconversion

module Netconversion: sig .. end


Preliminaries

A character set is a set of characters where every character is identified by a code point. An encoding is a way of representing characters from a set in byte strings. For example, the Unicode character set has more than 96000 characters, and the code points have values from 0 to 0x10ffff (not all code points are assigned yet). The UTF-8 encoding represents the code points by sequences of 1 to 4 bytes. There are also encodings that represent code points from several sets, e.g EUC-JP covers four sets.

Encodings are enumerated by the type encoding, and names follow the convention `Enc_*, e.g. `Enc_utf8. Character sets are enumerated by the type charset, and names follow the convention `Set_*, e.g. `Set_unicode.

This module deals mainly with encodings. It is important to know that the same character set may have several encodings. For example, the Unicode character set can be encoded as UTF-8 or UTF-16. For the 8 bit character sets, however, there is usually only one encoding, e.g `Set_iso88591 is always encoded as `Enc_iso88591.

In a single-byte encoding every code point is represented by one byte. This is what many programmers are accustomed at, and what the OCaml language specially supports: A string is a sequence of chars, where char means an 8 bit quantity interpreted as character. For example, the following piece of code allocates a string of four chars, and assigns them individually:

 let s = String.create 4 in
 s.[0] <- 'G';
 s.[1] <- 'e';
 s.[2] <- 'r';
 s.[3] <- 'd';
 

In a multi-byte encoding there are code points that are represented by several bytes. As we still represent such text as string, the problem arises that a single char, actually a byte, often represents only a fraction of a full multi-byte character. There are two solutions:

  • Give up the principle that text is represented by string. This is, for example, the approach chosen by Camomile, another OCaml library dealing with Unicode. Instead, text is represented as int array. This way, the algorithms processing the text can remain the same.
  • Give up the principle that individual characters can be directly accessed in a text. This is the primary way chosen by Ocamlnet. This means that there is not any longer the possibility to read or write the nth character of a text. One can, however, still compose texts by just concatenating the strings representing individual characters. Furthermore, it is possible to define a cursor for a text that moves sequentially along the text. The consequence is that programmers are restricted to sequential algorithms. Note that the majority of text processing falls into this class.
The corresponding piece of code for Ocamlnet's Unicode implementation is:
 let b = Buffer.create 80 in
 Buffer.add b (ustring_of_uchar `Enc_utf8 71);  (* 71 = code point of 'G' *)
 Buffer.add b (ustring_of_uchar `Enc_utf8 101); (* 101 = code point of 'e' *)
 Buffer.add b (ustring_of_uchar `Enc_utf8 114); (* 114 = code point of 'r' *)
 Buffer.add b (ustring_of_uchar `Enc_utf8 100); (* 100 = code point of 'd' *)
 let s = Buffer.contents b
 

It is important to always remember that a char is no longer a character but simply a byte. In many of the following explanations, we strictly distinguish between byte positions or byte counts, and character positions or character counts.

There a number of special effects that usually only occur in multi-byte encodings:

  • Bad encodings: Not every byte sequence is legal. When scanning such text, the functions will raise the exception Malformed_code when they find illegal bytes.
  • Unassigned code points: It may happen that a byte sequence is a correct representation for a code point, but that the code point is unassigned in the character set. When scanning, this is also covered by the exception Malformed_code. When converting from one encoding to another, it is also possible that the code point is only unassigned in the target character set. This case is usually handled by a substitution function subst, and if no such function is defined, by the exception Cannot_represent.
  • Incomplete characters: The trailing bytes of a string may be the correct beginning of a byte sequence for a character, but not a complete sequence. Of course, if that string is the end of a text, this is just illegal, and also a case for Malformed_code. However, when text is processed chunk by chunk, this phenomenon may happen legally for all chunks but the last. For this reason, some of the functions below handle this case specially.
  • Byte order marks: Some encodings have both big and little endian variants. A byte order mark at the beginning of the text declares which variant is actually used. This byte order mark is a declaration written like a character, but actually not a character.
There is a special class of encodings known as ASCII-compatible. They are important because there are lots of programs and protocols that only interpret bytes from 0 to 127, and treat the bytes from 128 to 255 as data. These programs can process texts as long as the bytes from 0 to 127 are used as in ASCII. Fortunately, many encodings are ASCII-compatible, including UTF-8.

Unicode

Netconversion is centred around Unicode. The conversion from one encoding to another works by finding the Unicode code point of the character to convert, and by representing the code point in the target encoding, even if neither encodings have to do with Unicode. Of course, this approach requires that all character sets handled by Netconversion are subsets of Unicode.

The supported range of Unicode code points: 0 to 0xd7ff, 0xe000 to 0xfffd, 0x10000 to 0x10ffff. All these code points can be represented in UTF-8 and UTF-16. Netconversion does not know which of the code points are assigned and which not, and because of this, it simply allows all code points of the mentioned ranges (but for other character sets, the necessary lookup tables exist).

UTF-8: The UTF-8 representation can have one to four bytes. Malformed byte sequences are always rejected, even those that want to cheat the reader like "0xc0 0x80" for the code point 0. There is special support for the Java variant of UTF-8 (`Enc_java). `Enc_utf8 strings must not have a byte order mark (it would be interpreted as "zero-width space" character). However, the Unicode standard allows byte order marks at the very beginning of texts; use `Enc_utf8_opt_bom in this case.

UTF-16: When reading from a string encoded as `Enc_utf16, a byte order mark is expected at the beginning. The detected variant (`Enc_utf16_le or `Enc_utf16_be) is usually returned by the parsing function. The byte order mark is not included into the output string. - Some functions of this module cannot cope with `Enc_utf16 (i.e. UTF-16 without endianess annotation), and will fail.

Once the endianess is determined, the code point 0xfeff is no longer interpreted as byte order mark, but as "zero-width non-breakable space".

Some code points are represented by pairs of 16 bit values, these are the so-called "surrogate pairs". They can only occur in UTF-16.

UTF-32: This is very much the same as for UTF-16. There is a little endian version `Enc_utf32_le and a big endian version `Enc_utf32_be.

Subsets of Unicode

The non-Unicode character sets are subsets of Unicode. Here, it may happen that a Unicode code point does not have a corresponding code point. In this case, certain rules are applied to handle this (see below). It is, however, ensured that every non-Unicode code point has a corresponding Unicode code point. (In other words, character sets cannot be supported for which this property does not hold.)

It is even possible to create further subsets artificially. The encoding `Enc_subset(e,def) means to derive a new encoding from the existing one e, but to only accept the code points for which the definition function def yields the value true. For example, the encoding

 `Enc_subset(`Enc_usascii, 
             fun i -> i <> 34 && i <> 38 && i <> 60 && i <> 62) 
is ASCII without the bracket angles, the quotation mark, and the ampersand character, i.e. the subset of ASCII that can be included in HTML text without escaping.

If a code point is not defined by the encoding but found in a text, the reader will raise the exception Malformed_code. When text is output, however, the subst function will be called for undefined code points (which raises Cannot_represent by default). The subst function is an optional argument of many conversion functions that allows it to insert a substitution text for undefined code points. Note, however, that the substitution text is restricted to at most 50 characters (because unlimited length would lead to difficult problems we would like to avoid).

Linking this module

Many encodings require lookup tables. The following encodings are built-in and always supported:

  • Unicode: `Enc_utf8, `Enc_java, `Enc_utf16, `Enc_utf16_le, `Enc_utf16_be, `Enc_utf32, `Enc_utf32_le, `Enc_utf32_be
  • Other: `Enc_usascii, `Enc_iso88591, `Enc_empty
The lookup tables for the other encodings are usually loaded at runtime, but it is also possible to embed them in the generated binary executable. See Netunidata for details. The functions available_input_encodings and available_output_encodings can be invoked to find out which encodings can be loaded, or are available otherwise.

Supported Encodings, Restrictions

I took the mappings from www.unicode.org, and the standard names of the character sets from IANA. Obviously, many character sets are missing that can be supported; especially ISO646 character sets, and many EBCDIC code pages. Stateful encodings like generic ISO-2022 have been omitted (stateless subsets of ISO-2022 like EUC can be supported, however; currently we support EUC-JP and EUC-KR).

Because of the copyright statement from Unicode, I cannot put the source tables that describe the mappings into the distribution. They are publicly available from www.unicode.org.

Known Problems

  • The following charsets do not have a bijective mapping to Unicode: adobe_standard_encoding, adobe_symbol_encoding, adobe_zapf_dingbats_encoding, cp1002 (0xFEBE). The current implementation simply removes one of the conflicting code point pairs - this might not what you want.
  • Japanese encodings: JIS X 0208: The character 1/32 is mapped to 0xFF3C, and not to 0x005C.


Preliminaries

A character set is a set of characters where every character is identified by a code point. An encoding is a way of representing characters from a set in byte strings. For example, the Unicode character set has more than 96000 characters, and the code points have values from 0 to 0x10ffff (not all code points are assigned yet). The UTF-8 encoding represents the code points by sequences of 1 to 4 bytes. There are also encodings that represent code points from several sets, e.g EUC-JP covers four sets.

Encodings are enumerated by the type encoding, and names follow the convention `Enc_*, e.g. `Enc_utf8. Character sets are enumerated by the type charset, and names follow the convention `Set_*, e.g. `Set_unicode.

This module deals mainly with encodings. It is important to know that the same character set may have several encodings. For example, the Unicode character set can be encoded as UTF-8 or UTF-16. For the 8 bit character sets, however, there is usually only one encoding, e.g `Set_iso88591 is always encoded as `Enc_iso88591.

In a single-byte encoding every code point is represented by one byte. This is what many programmers are accustomed at, and what the OCaml language specially supports: A string is a sequence of chars, where char means an 8 bit quantity interpreted as character. For example, the following piece of code allocates a string of four chars, and assigns them individually:

 let s = String.create 4 in
 s.[0] <- 'G';
 s.[1] <- 'e';
 s.[2] <- 'r';
 s.[3] <- 'd';
 

In a multi-byte encoding there are code points that are represented by several bytes. As we still represent such text as string, the problem arises that a single char, actually a byte, often represents only a fraction of a full multi-byte character. There are two solutions:

  • Give up the principle that text is represented by string. This is, for example, the approach chosen by Camomile, another OCaml library dealing with Unicode. Instead, text is represented as int array. This way, the algorithms processing the text can remain the same.
  • Give up the principle that individual characters can be directly accessed in a text. This is the primary way chosen by Ocamlnet. This means that there is not any longer the possibility to read or write the nth character of a text. One can, however, still compose texts by just concatenating the strings representing individual characters. Furthermore, it is possible to define a cursor for a text that moves sequentially along the text. The consequence is that programmers are restricted to sequential algorithms. Note that the majority of text processing falls into this class.
The corresponding piece of code for Ocamlnet's Unicode implementation is:
 let b = Buffer.create 80 in
 Buffer.add b (ustring_of_uchar `Enc_utf8 71);  (* 71 = code point of 'G' *)
 Buffer.add b (ustring_of_uchar `Enc_utf8 101); (* 101 = code point of 'e' *)
 Buffer.add b (ustring_of_uchar `Enc_utf8 114); (* 114 = code point of 'r' *)
 Buffer.add b (ustring_of_uchar `Enc_utf8 100); (* 100 = code point of 'd' *)
 let s = Buffer.contents b
 

It is important to always remember that a char is no longer a character but simply a byte. In many of the following explanations, we strictly distinguish between byte positions or byte counts, and character positions or character counts.

There a number of special effects that usually only occur in multi-byte encodings:

  • Bad encodings: Not every byte sequence is legal. When scanning such text, the functions will raise the exception Malformed_code when they find illegal bytes.
  • Unassigned code points: It may happen that a byte sequence is a correct representation for a code point, but that the code point is unassigned in the character set. When scanning, this is also covered by the exception Malformed_code. When converting from one encoding to another, it is also possible that the code point is only unassigned in the target character set. This case is usually handled by a substitution function subst, and if no such function is defined, by the exception Cannot_represent.
  • Incomplete characters: The trailing bytes of a string may be the correct beginning of a byte sequence for a character, but not a complete sequence. Of course, if that string is the end of a text, this is just illegal, and also a case for Malformed_code. However, when text is processed chunk by chunk, this phenomenon may happen legally for all chunks but the last. For this reason, some of the functions below handle this case specially.
  • Byte order marks: Some encodings have both big and little endian variants. A byte order mark at the beginning of the text declares which variant is actually used. This byte order mark is a declaration written like a character, but actually not a character.
There is a special class of encodings known as ASCII-compatible. They are important because there are lots of programs and protocols that only interpret bytes from 0 to 127, and treat the bytes from 128 to 255 as data. These programs can process texts as long as the bytes from 0 to 127 are used as in ASCII. Fortunately, many encodings are ASCII-compatible, including UTF-8.

Unicode

Netconversion is centred around Unicode. The conversion from one encoding to another works by finding the Unicode code point of the character to convert, and by representing the code point in the target encoding, even if neither encodings have to do with Unicode. Of course, this approach requires that all character sets handled by Netconversion are subsets of Unicode.

The supported range of Unicode code points: 0 to 0xd7ff, 0xe000 to 0xfffd, 0x10000 to 0x10ffff. All these code points can be represented in UTF-8 and UTF-16. Netconversion does not know which of the code points are assigned and which not, and because of this, it simply allows all code points of the mentioned ranges (but for other character sets, the necessary lookup tables exist).

UTF-8: The UTF-8 representation can have one to four bytes. Malformed byte sequences are always rejected, even those that want to cheat the reader like "0xc0 0x80" for the code point 0. There is special support for the Java variant of UTF-8 (`Enc_java). `Enc_utf8 strings must not have a byte order mark (it would be interpreted as "zero-width space" character). However, the Unicode standard allows byte order marks at the very beginning of texts; use `Enc_utf8_opt_bom in this case.

UTF-16: When reading from a string encoded as `Enc_utf16, a byte order mark is expected at the beginning. The detected variant (`Enc_utf16_le or `Enc_utf16_be) is usually returned by the parsing function. The byte order mark is not included into the output string. - Some functions of this module cannot cope with `Enc_utf16 (i.e. UTF-16 without endianess annotation), and will fail.

Once the endianess is determined, the code point 0xfeff is no longer interpreted as byte order mark, but as "zero-width non-breakable space".

Some code points are represented by pairs of 16 bit values, these are the so-called "surrogate pairs". They can only occur in UTF-16.

UTF-32: This is very much the same as for UTF-16. There is a little endian version `Enc_utf32_le and a big endian version `Enc_utf32_be.

Subsets of Unicode

The non-Unicode character sets are subsets of Unicode. Here, it may happen that a Unicode code point does not have a corresponding code point. In this case, certain rules are applied to handle this (see below). It is, however, ensured that every non-Unicode code point has a corresponding Unicode code point. (In other words, character sets cannot be supported for which this property does not hold.)

It is even possible to create further subsets artificially. The encoding `Enc_subset(e,def) means to derive a new encoding from the existing one e, but to only accept the code points for which the definition function def yields the value true. For example, the encoding

 `Enc_subset(`Enc_usascii, 
             fun i -> i <> 34 && i <> 38 && i <> 60 && i <> 62) 
is ASCII without the bracket angles, the quotation mark, and the ampersand character, i.e. the subset of ASCII that can be included in HTML text without escaping.

If a code point is not defined by the encoding but found in a text, the reader will raise the exception Malformed_code. When text is output, however, the subst function will be called for undefined code points (which raises Cannot_represent by default). The subst function is an optional argument of many conversion functions that allows it to insert a substitution text for undefined code points. Note, however, that the substitution text is restricted to at most 50 characters (because unlimited length would lead to difficult problems we would like to avoid).

Linking this module

Many encodings require lookup tables. The following encodings are built-in and always supported:

  • Unicode: `Enc_utf8, `Enc_java, `Enc_utf16, `Enc_utf16_le, `Enc_utf16_be, `Enc_utf32, `Enc_utf32_le, `Enc_utf32_be
  • Other: `Enc_usascii, `Enc_iso88591, `Enc_empty
The lookup tables for the other encodings are usually loaded at runtime, but it is also possible to embed them in the generated binary executable. See Netunidata for details. The functions available_input_encodings and available_output_encodings can be invoked to find out which encodings can be loaded, or are available otherwise.

Supported Encodings, Restrictions

I took the mappings from www.unicode.org, and the standard names of the character sets from IANA. Obviously, many character sets are missing that can be supported; especially ISO646 character sets, and many EBCDIC code pages. Stateful encodings like generic ISO-2022 have been omitted (stateless subsets of ISO-2022 like EUC can be supported, however; currently we support EUC-JP and EUC-KR).

Because of the copyright statement from Unicode, I cannot put the source tables that describe the mappings into the distribution. They are publicly available from www.unicode.org.

Known Problems

  • The following charsets do not have a bijective mapping to Unicode: adobe_standard_encoding, adobe_symbol_encoding, adobe_zapf_dingbats_encoding, cp1002 (0xFEBE). The current implementation simply removes one of the conflicting code point pairs - this might not what you want.
  • Japanese encodings: JIS X 0208: The character 1/32 is mapped to 0xFF3C, and not to 0x005C.


Interface

Naming conventions:

As it is possible to refer to substrings by either giving a byte offset or by counting whole characters, these naming conventions are helpful:

  • Labels called range_pos and range_len refer to byte positions of characters, or substrings
  • Labels called count refer to positions given as the number of characters relative to an origin
Furthermore:

  • A uchar is a single Unicode code point represented as int
  • A ustring is a string of encoded characters
  • A uarray is an array of int representing a string

exception Malformed_code
Raised when an illegal byte sequence is found
exception Cannot_represent of int
Raised when a certain Unicode code point cannot be represented in the selected output encoding
type encoding = [ `Enc_adobe_standard_encoding
| `Enc_adobe_symbol_encoding
| `Enc_adobe_zapf_dingbats_encoding
| `Enc_asn1_T61
| `Enc_asn1_iso646
| `Enc_asn1_printable
| `Enc_cp037
| `Enc_cp1006
| `Enc_cp1026
| `Enc_cp1047
| `Enc_cp424
| `Enc_cp437
| `Enc_cp500
| `Enc_cp737
| `Enc_cp775
| `Enc_cp850
| `Enc_cp852
| `Enc_cp855
| `Enc_cp856
| `Enc_cp857
| `Enc_cp860
| `Enc_cp861
| `Enc_cp862
| `Enc_cp863
| `Enc_cp864
| `Enc_cp865
| `Enc_cp866
| `Enc_cp869
| `Enc_cp874
| `Enc_cp875
| `Enc_empty
| `Enc_eucjp
| `Enc_euckr
| `Enc_iso88591
| `Enc_iso885910
| `Enc_iso885911
| `Enc_iso885913
| `Enc_iso885914
| `Enc_iso885915
| `Enc_iso885916
| `Enc_iso88592
| `Enc_iso88593
| `Enc_iso88594
| `Enc_iso88595
| `Enc_iso88596
| `Enc_iso88597
| `Enc_iso88598
| `Enc_iso88599
| `Enc_java
| `Enc_jis0201
| `Enc_koi8r
| `Enc_macroman
| `Enc_subset of encoding * (int -> bool)
| `Enc_usascii
| `Enc_utf16
| `Enc_utf16_be
| `Enc_utf16_le
| `Enc_utf32
| `Enc_utf32_be
| `Enc_utf32_le
| `Enc_utf8
| `Enc_utf8_opt_bom
| `Enc_windows1250
| `Enc_windows1251
| `Enc_windows1252
| `Enc_windows1253
| `Enc_windows1254
| `Enc_windows1255
| `Enc_windows1256
| `Enc_windows1257
| `Enc_windows1258 ]
The polymorphic variant enumerating the supported encodings. We have:
  • `Enc_utf8: UTF-8
  • `Enc_utf8_opt_bom: UTF-8 with an optional byte order mark at the beginning of the text
  • `Enc_java: The UTF-8 variant used by Java (the only difference is the representation of NUL)
  • `Enc_utf16: UTF-16 with unspecified endianess (restricted)
  • `Enc_utf16_le: UTF-16 little endian
  • `Enc_utf16_be: UTF-16 big endian
  • `Enc_utf32: UTF-32 with unspecified endianess (restricted)
  • `Enc_utf32_le: UTF-32 little endian
  • `Enc_utf32_be: UTF-32 big endian
  • `Enc_usascii: US-ASCII (7 bits)
  • `Enc_iso8859n: ISO-8859-n
  • `Enc_koi8r: KOI8-R
  • `Enc_jis0201: JIS-X-0201 (Roman and Katakana)
  • `Enc_eucjp: EUC-JP (code points from US-ASCII, JIS-X-0202, -0208, and -0212)
  • `Enc_euckr: EUC-KR (code points from US-ASCII, KS-X-1001)
  • `Enc_windowsn: WINDOWS-n
  • `Enc_cpn: IBM code page n. Note that there are both ASCII- and EBCDIC-based code pages
  • `Enc_adobe_*: Adobe-specific encodings, e.g. used in Adobe fonts
  • `Enc_mac*: Macintosh-specific encodings
  • `Enc_subset(e,def): The subset of e by applying the definition function def
  • `Enc_empty: The empty encoding (does not represent any character)

type charset = [ `Set_adobe_standard_encoding
| `Set_adobe_symbol_encoding
| `Set_adobe_zapf_dingbats_encoding
| `Set_asn1_T61
| `Set_asn1_iso646
| `Set_asn1_printable
| `Set_cp037
| `Set_cp1006
| `Set_cp1026
| `Set_cp1047
| `Set_cp424
| `Set_cp437
| `Set_cp500
| `Set_cp737
| `Set_cp775
| `Set_cp850
| `Set_cp852
| `Set_cp855
| `Set_cp856
| `Set_cp857
| `Set_cp860
| `Set_cp861
| `Set_cp862
| `Set_cp863
| `Set_cp864
| `Set_cp865
| `Set_cp866
| `Set_cp869
| `Set_cp874
| `Set_cp875
| `Set_iso88591
| `Set_iso885910
| `Set_iso885911
| `Set_iso885913
| `Set_iso885914
| `Set_iso885915
| `Set_iso885916
| `Set_iso88592
| `Set_iso88593
| `Set_iso88594
| `Set_iso88595
| `Set_iso88596
| `Set_iso88597
| `Set_iso88598
| `Set_iso88599
| `Set_jis0201
| `Set_jis0208
| `Set_jis0212
| `Set_koi8r
| `Set_ks1001
| `Set_macroman
| `Set_unicode
| `Set_usascii
| `Set_windows1250
| `Set_windows1251
| `Set_windows1252
| `Set_windows1253
| `Set_windows1254
| `Set_windows1255
| `Set_windows1256
| `Set_windows1257
| `Set_windows1258 ]
A charset is simply a set of code points. It does not say how the code points are encoded as bytes. Every encoding implies a certain charset (or several charsets) that can be encoded, but the reverse is not true.

Pre-evaluation of the encoding argument:

A number of the following functions can be made run faster if they are called several times for the same encoding. In this case, it is recommended to apply the function once partially with the encoding argument, and to call the resulting closure instead. For example, ustring_of_uchar supports this technique:

   let my_ustring_of_uchar = ustring_of_uchar my_enc in
   let s1 = my_ustring_of_uchar u1 ...
   let s2 = my_ustring_of_uchar u2 ... 

This is much faster than

   let s1 = ustring_of_uchar my_enc u1 ...
   let s2 = ustring_of_uchar my_enc u2 ... 

The availability of this optimization is indicated by the predicate PRE_EVAL(arg) where arg identifies the encoding argument.

Inlining

When a function can be inlined across module/library boundaries, this is indicated by the predicate INLINED. Of course, this works only for the ocamlopt compiler.

val encoding_of_string : string -> encoding
Returns the encoding of the name of the encoding. Fails if the encoding is unknown. E.g. encoding_of_string "iso-8859-1" = `Enc_iso88591

Punctuation characters (e.g. "-") and year suffixes (e.g. ":1991") are ignored.

val string_of_encoding : encoding -> string
Returns the name of the encoding.
val is_ascii_compatible : encoding -> bool
"ASCII compatible" means: The bytes 1 to 127 represent the ASCII codes 1 to 127, and no other representation of a character contains the bytes 1 to 127.

For example, ISO-8859-1 is ASCII-compatible because the byte 1 to 127 mean the same as in ASCII, and all other characters use bytes greater than 127. UTF-8 is ASCII-compatible for the same reasons, it does not matter that there are multi-byte characters. EBCDIC is not ASCII-compatible because the bytes 1 to 127 do not mean the same as in ASCII. UTF-16 is not ASCII-compatible because the bytes 1 to 127 can occur in multi-byte representations of non-ASCII characters.

The byte 0 has been excluded from this definition because the C language uses it with a special meaning that has nothing to do with characters, so it is questionable to interpret the byte 0 anyway.

val is_single_byte : encoding -> bool
Returns whether the encoding is a single-byte encoding
val same_encoding : encoding -> encoding -> bool
Whether both encodings are the same. `Enc_subset encodings are only considered as equal when the definition functions are physically the same.

Warning: Don't use ( = ) to compare encodings because this may fail.

val byte_order_mark : encoding -> string
Returns the byte order mark that must occur at the beginning of files to indicate whether "little endian" or "big endian" is used. If this does not apply to the encoding, an empty string is returned.

See also the section about "Byte Order Marks" below.

val makechar : encoding -> int -> string
Deprecated.This function is deprecated since ocamlnet-0.96. Use ustring_of_uchar instead.
makechar enc i: Creates the string representing the Unicode code point i in encoding enc. Raises Not_found if the character is legal but cannot be represented in enc.

Possible encodings: everything but `Enc_utf16 and `Enc_utf32

Evaluation hints:

  • PRE_EVAL(encoding)

val ustring_of_uchar : encoding -> int -> string
ustring_of_uchar enc i: Creates the string representing the Unicode code point i in encoding enc. Raises Cannot_represent i if the character is legal but cannot be represented in enc.

Possible encodings: everything but `Enc_utf16 and `Enc_utf32.

Evaluation hints:

  • PRE_EVAL(encoding)

val to_unicode : charset -> int -> int
Maps the code point of the charset to the corresponding Unicode code point, or raises Malformed_code, when the input number does not correspond to a code point.

Note `Set_jis0208 and `Set_jis0212: Code points are usually given by a row and column number. The numeric code point returned by this function is computed by multiplying the row number (1..94) with 96, and by adding the column number (1..94), i.e. row*96+column.

Evaluation hints:

  • PRE_EVAL(charset)

val from_unicode : charset -> int -> int
Maps the Unicode code point to the corresponding code point of the charset, or raises Cannot_represent when there is no such corresponding code point.

Note `Set_jis0208 and `Set_jis0212: Code points are usually given by a row and column number. The numeric code point returned by this function is computed by multiplying the row number (1..94) with 96, and by adding the column number (1..94), i.e. row*96+column.

Evaluation hints:

  • PRE_EVAL(charset)

val available_input_encodings : unit -> encoding list
Returns the list of all available encodings that can be used for input strings. The list reflects the set of loadable/linked Netmapping modules.
val available_output_encodings : unit -> encoding list
Returns the list of all available encodings that can be used for output strings. The list reflects the set of loadable/linked Netmapping modules.
val user_encoding : unit -> encoding option
Determines the preferred user encoding:

  • Unix: This is the character set from the current locale
  • Win32: This is derived from the current ANSI code page
If an error occurs while determining the result, the value None is returned.
val win32_code_pages : (int * encoding) list
Mapping between Win32 code page numbers and Ocamlnet encodings. This is incomplete. The official list: http://msdn.microsoft.com/en-us/library/dd317756%28v=VS.85%29.aspx

Direct Conversion



Direct Conversion



In order to convert a string from one encoding to another, call convert like in

 let s_utf8 = 
    convert ~in_enc:`Enc_iso88591 ~out_enc:`Enc_utf8 s_latin1 

which converts the ISO-8859-1 string s_latin1 to the UTF-8 string s_utf8.

It is also possible to convert while reading from or writing to a file. This use case is effectively handled by the class Netconversion.conversion_pipe. See the explanations of this class for examples.

val convert : ?subst:(int -> string) ->
in_enc:encoding ->
out_enc:encoding ->
?range_pos:int -> ?range_len:int -> string -> string
Converts the string from in_enc to out_enc, and returns it. The string must consist of a whole number of characters. If it ends with an incomplete multi-byte character, however, this is detected, and the exception Malformed_code will be raised. This exception is also raised for other encoding errors in the input string.


subst : This function is invoked for code points of in_enc that cannot be represented in out_enc, and the result of the function invocation is substituted (directly, without any further conversion). Restriction: The string returned by subst must not be longer than 50 bytes. If subst is missing, Cannot_represent is raised in this case.
range_pos : Selects a substring for conversion. range_pos is the byte position of the first character of the substring. (Default: 0)
range_len : Selects a substring for conversion. range_len is the length of the substring in bytes (Default: Length of the input string minus range_pos)
val convert_tstring : ?subst:(int -> string) ->
in_enc:encoding ->
out_enc:encoding ->
out_kind:'s Netstring_tstring.tstring_kind ->
?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> 's
Same for tagged strings
val convert_poly : in_ops:'s1 Netstring_tstring.tstring_ops ->
out_kind:'s2 Netstring_tstring.tstring_kind ->
?subst:(int -> string) ->
in_enc:encoding ->
out_enc:encoding ->
?range_pos:int -> ?range_len:int -> 's1 -> 's2
Polymorphic version
val recode : in_enc:encoding ->
in_buf:string ->
in_pos:int ->
in_len:int ->
out_enc:encoding ->
out_buf:Bytes.t ->
out_pos:int ->
out_len:int ->
max_chars:int -> subst:(int -> string) -> int * int * encoding
Converts the character sequence contained in the at most in_len bytes of in_buf starting at byte position in_pos, and writes the result into at most out_len bytes of out_buf starting at byte position out_pos. At most max_chars characters are converted from in_buf to out_buf.

The characters in in_buf are assumed to be encoded as in_enc, and the characters in out_buf will be encoded as out_enc. The case in_enc = out_enc is not handled specially, and is carried out as fast as any other conversion.

If there is a code point which cannot be represented in out_enc, the function subst is called with the code point as argument, and the resulting string (which must already be encoded as out_enc) is inserted instead. It is possible that subst is called several times for the same character. Restriction: The string returned by subst must not be longer than 50 bytes.

It is allowed that the input buffer ends with an incomplete multi-byte character. This character is not converted, i.e. the conversion ends just before this character. This special condition is not indicated to the caller.


Returns The triple (in_n, out_n, in_enc') is returned:

  • in_n is the actual number of bytes that have been converted from in_buf; in_n may be smaller than in_len because of incomplete multi-byte characters, or because the output buffer has less space for characters than the input buffer, or because of a change of the encoding variant.
  • out_n is the actual number of bytes written into out_buf.
  • in_enc' is normally identical to in_enc. However, there are cases where the encoding can be refined when looking at the byte sequence; for example whether a little endian or big endian variant of the encoding is used. in_enc' is the variant of in_enc that was used for the last converted character.
If there is at least one complete character in in_buf, and at least space for one complete character in out_buf, and max_chars >= 1, it is guaranteed that in_n > 0 && out_n > 0.
val recode_tstring : in_enc:encoding ->
in_buf:Netsys_types.tstring ->
in_pos:int ->
in_len:int ->
out_enc:encoding ->
out_buf:Bytes.t ->
out_pos:int ->
out_len:int ->
max_chars:int -> subst:(int -> string) -> int * int * encoding
A version of recode for tagged strings
val recode_poly : in_ops:'s Netstring_tstring.tstring_ops ->
in_enc:encoding ->
in_buf:'s ->
in_pos:int ->
in_len:int ->
out_enc:encoding ->
out_buf:Bytes.t ->
out_pos:int ->
out_len:int ->
max_chars:int -> subst:(int -> string) -> int * int * encoding
A polymorphic version of recode
class conversion_pipe : ?subst:int -> string -> in_enc:encoding -> out_enc:encoding -> unit -> Netchannels.io_obj_channel
This pipeline class (see Netchannels for more information) can be used to recode a netchannel while reading or writing.

Reading Text Using Cursors

A cursor is a reference to a character in an encoded string. The properties of the current character can be obtained, and the cursor can be moved relative to its current position.

For example, the following loop outputs the Unicode code points of all characters of the UTF-8 input string s:

 let cs = create_cursor `Enc_utf8 s in
 while not (cursor_at_end cs) do
   let n = cursor_char_count cs in
   let ch = uchar_at cs in
   printf "At position %d: %d\n" n ch;
   move cs;
 done
 

For a more exact definition, cursors are modeled as follows: The reference to the encoded string is contained in the cursor. This can be a complete string, or an arbitrary substring (denoted by a range of valid byte positions). The cursor position can be initially set to an arbitrary byte position of the encoded string.

Cursor positions can be denoted by

  • byte positions p in the encoded string, or by
  • character counts n relative to the initial position.
Valid cursor positions are:
  • n=0: This is always the initial cursor position
  • n>0: Positive char counts refer to characters right to the initial character. The rightmost position is the position n_max past the rightmost character. The rightmost position does not have a code point.
  • n<0: Negative char counts refer to characters left to the initial character. The leftmost position is the position n_min of the leftmost character.
For the empty string we have n_min = n_max = 0, complementing the above definition.

Cursors are moved to the left or right of their current position by a whole number of characters. When it is tried to move them past the leftmost or rightmost position, the cursor is placed to the leftmost or rightmost position, respectively, and the exception Cursor_out_of_range is raised.

There are two cases of illegal encodings:

  • When the last byte sequence of the encoded string is an incomplete multi-byte character, this is detected, and the special exception Partial_character is raised when the code point of this character is read. Note that this can only happen at position n_max-1. It is allowed to move beyond this character to n_max.
  • When an illegal byte sequence occurs in the encoded string (including an incomplete multi-byte character at the beginning of the string), it is not possible to move the cursor to this character, or across this character. When it is tried to do so, the cursor stops just before the bad sequence, and the exception Malformed_code is raised.
It is undefined what happens when the encoded string is modified while a cursor is in use referring to it.
type 's poly_cursor 
A cursor denotes a character position in an encoded string. The parameter 's is the string type, e.g. string or bytes.
type cursor = string poly_cursor 
exception End_of_string
Raised when it is tried to access the character after the end of the string (at position n_max)
exception Cursor_out_of_range
Raised when it is tried to move the cursor beyond the beginning of the string or beyond the end of the string. In the latter case, it is legal to move the cursor to the position following the last character, but it is not possible to move it further.
exception Partial_character
Raised when the last character of the string is an incomplete multi-byte character, and it is tried to get the code point (using uchar_at).
exception Byte_order_mark
Raised when it is tried to get the code point of the BOM at the beginning of the string
val create_cursor : ?range_pos:int ->
?range_len:int ->
?initial_rel_pos:int ->
encoding -> string -> cursor
Creates a new cursor for the passed string and the passed encoding. By default, the allowed range of the cursor is the whole string, and the cursor is intially positioned at the beginning of the string. The range is the part of the string the cursor can move within.

Special behaviour for `Enc_utf16/`Enc_utf32: UTF with unspecified endianess is handled specially. First, this encoding is only accepted when initial_rel_pos=0. Second, the first two bytes must be a byte order mark (BOM) (if the string has a length of two bytes or more). The BOM counts as character without code point. The function uchar_at raises the exception Byte_order_mark when the BOM is accessed. Third, when the cursor is moved to the next character, the encoding as returned by cursor_encoding is changed to either `Enc_utf16_le or `Enc_utf16_be according to the BOM. The encoding changes back to `Enc_utf16 when the cursor is moved back to the initial position.

Special behavior for `Enc_utf8_opt_bom: Here, a byte order mark at the beginning of the text is recognized, and uchar_at will raise Byte_order_mark. Unlike in the UTF-16 and 32 cases, the BOM is optional. The function cursor_encoding returns `Enc_utf8 if the cursor is moved away from the BOM, and changes back to `Enc_utf8_opt_bom if moved back to the first character.


range_pos : Restricts the range of the cursor to a substring. The argument range_pos is the byte position of the beginning of the range. (Defaults to 0)
range_len : Restricts the range of the cursor to a substring. The argument range_len is the length of the range. (Default: Length of the input string minus range_pos)
initial_rel_pos : The initial position of the cursor, given as bytes relative to range_pos. The character at this position is considered as the zeroth character of the string (as reported by cursor_char_count)
val create_poly_cursor : ?range_pos:int ->
?range_len:int ->
?initial_rel_pos:int ->
encoding ->
's Netstring_tstring.tstring_ops -> 's -> 's poly_cursor
Polymorphic version
type 'a with_cursor_fun = {
   with_cursor_fun : 's. 's Netstring_tstring.tstring_ops -> 's poly_cursor -> 'a;
}
val with_tstring_cursor : ?range_pos:int ->
?range_len:int ->
?initial_rel_pos:int ->
encoding ->
Netsys_types.tstring -> 'a with_cursor_fun -> 'a
Creates a cursor like create_cursor and calls with_cursor_fun with the cursor, returning any result unchanged.

Note that there cannot be a "create_tstring_cursor" for typing reasons, and this is the closest approximation.

val reinit_cursor : ?range_pos:int ->
?range_len:int ->
?initial_rel_pos:int ->
?enc:encoding -> 's -> 's poly_cursor -> unit
Reuses an existing cursor for a new purpose. The arguments are as in create_cursor.
val copy_cursor : ?enc:encoding ->
's poly_cursor -> 's poly_cursor
Copies the cursor. The copy can be moved independently of the original cursor, but is applied to the same string. The copy starts at the byte position of the string where the original cursor is currently positioned.


enc : Optionally, the assumed encoding can be changed to a different one by passing enc.
val cursor_target : 's poly_cursor -> 's
Returns the string of the cursor

Evaluation hints:

  • INLINED

val cursor_range : 'a poly_cursor -> int * int
Returns the valid range of the cursor as pair (range_pos, range_len)

Evaluation hints:

  • INLINED

val cursor_initial_rel_pos : 'a poly_cursor -> int
Returns the initial relative byte position of the cursor

Evaluation hints:

  • INLINED

val cursor_char_count : 'a poly_cursor -> int
Returns the character count of the cursor. The initial position (when create_cursor was called) has the number 0, positions to the right denote positive numbers, and positions to the left negative numbers.

Evaluation hints:

  • INLINED

val cursor_pos : 'a poly_cursor -> int
Returns the byte position of the cursor, i.e. the byte index of the string that corresponds to the cursor position. The function returns the absolute position (i.e. NOT relative to cursor_range).

Evaluation hints:

  • INLINED

val uchar_at : 'a poly_cursor -> int
Returns the Unicode code point of the character at the cursor. Raises End_of_string if the cursor is positioned past the last character. Raises Partial_character if the last character of the analysed string range is an incomplete multi-byte character. Raises Byte_order_mark if the first character of the string is a BOM (when the encoding has BOMs).

Evaluation hints:

  • INLINED

val cursor_byte_length : 'a poly_cursor -> int
Returns the byte length of the representation of the character at the cursor. This works also for incomplete multi-byte characters and BOMs. Raises End_of_string if the cursor is positioned past the last character.

Evaluation hints:

  • INLINED

val cursor_at_end : 'a poly_cursor -> bool
Returns whether the cursor is positioned past the last character.

Evaluation hints:

  • INLINED

val move : ?num:int -> 'a poly_cursor -> unit
Moves the cursor one character to the right, or if num is passed, this number of characters to the right. num can be negative in which case the cursor is moved to the left.

If the cursor were placed outside the valid range, the cursor would go into an illegal state, and because of this, this is handled as follows: the cursor moves to the leftmost or rightmost position (depending on the direction), and the exception Cursor_out_of_range is raised.

val cursor_encoding : 'a poly_cursor -> encoding
Returns the encoding of the cursor. For some encodings, the returned encoding depends on the position of the cursor (see the note about UTF-8 in create_cursor)

Evaluation hints:

  • INLINED

val cursor_blit : 'a poly_cursor -> int array -> int -> int -> int
cursor_blit cs ua pos len: Copies at most len characters as code points from the cursor position and the following positions to the array ua at index pos. The number of copied characters is returned. If the cursor is already at the end of the string when this function is called, the exception End_of_string will be raised instead, and no characters are copied. The cursor positions containing byte order marks and partial characters are never copied; this is ensured by stopping the copying procedure just before these positions. This may even make the function return the number 0.

The function tries to copy as many characters as currently available in the already decoded part of the string the cursor is attached to. In the current implementation, this number is not higher than 250. You can call cursor_blit_maxlen to get an upper limit.

The function does not move the cursor.

val cursor_blit_maxlen : 'a poly_cursor -> int
Returns the maximum number of characters cursor_blit can copy at the current cursor position. This is the number of characters cursor_blit would copy if the len argument were arbitrarily large.

Note that the value depends on the cursor position and on the contents of the cursor string.

This function raises End_of_string if the cursor is positioned at the end of the string.

val cursor_blit_positions : 'a poly_cursor -> int array -> int -> int -> int
Works like cursor_blit, but copies the byte positions of the characters into ua instead of the code points.

When called directly after cursor_blit for the same cursor and with the same value of len, this function copies as many characters and thus returns the same number:

let n1 = cursor_blit     cs ua ua_pos len in
 let n2 = cursor_blit_pos cs pa pa_pos len in
 assert (n1 = n2)


Byte Order Marks

Because UTF-16 allows both little and big endian, files and other permanent representations of UTF-16 text are usually prepended by a byte order mark (BOM). There is confusion about the BOM among Unicode users, so the following explanations may be helpful.

Of course, the BOM is only used for external representations like files, as the endianess is always known for in-memory representations by the running program. This module has six encoding identifiers:

  • `Enc_utf16: UTF-16 where the endianess is unknown
  • `Enc_utf16_le: UTF-16 little endian
  • `Enc_utf16_be: UTF-16 big endian
  • `Enc_utf32: UTF-32 where the endianess is unknown
  • `Enc_utf32_le: UTF-32 little endian
  • `Enc_utf32_be: UTF-32 big endian
When a file is read, the endianess is unknown at the beginning. This is expressed by e.g. `Enc_utf16. When the BOM is read, the encoding is refined to either `Enc_utf16_le or `Enc_utf16_be, whatever the BOM says. This works as follows: The BOM is the representation of the code point 0xfeff as little or big endian, i.e. as byte sequences "0xfe 0xff" (big endian) or "0xff 0xfe" (little endian). As the "wrong" code point 0xfffe is intentionally unused, the reader can determine the endianess.

There is one problem, though. Unfortunately, the code point 0xfeff is also used for the normal "zero width non-breakable space" character. When this code point occurs later in the text, it is interpreted as this character. Of course, this means that one must know whether there is a BOM at the beginning, and if not, one must know the endianess. One cannot program in the style "well, let's see what is coming and guess".

Unicode also allows a BOM for UTF-8 although it is meaningless to specify the endianess. If you create the cursor with the encoding `Enc_utf8 nothing is done about this, and you get the BOM as normal character. If you create the cursor with `Enc_utf8_opt_bom, the BOM is treated specially like in the UTF-16 and -32 cases (with the only difference that it is optional for UTF-8).

The functions of this module can all deal with BOMs when reading encoded text. In most cases, the BOM is hidden from the caller, and just handled automatically. Cursors, however, treat BOMs as special characters outside of the code set (exception Byte_order_mark is raised). The writing functions of this module do not generate BOMs, however, as there is no way to tell them that a BOM is needed. The function byte_order_mark can be used to output the BOM manually.

Examples for Cursors

Create the cursor:

let cs = create_cursor `Enc_utf8 "B\195\164r";;

The cursor is now positioned at the 'B':

uchar_at cs returns 66 (i.e. B)

Move the cursor one character to the right. In UTF-8, this is a two-byte character consisting of the bytes 195 and 164:

move cs ;;

uchar_at cs returns 228 (i.e. a-Umlaut)

One can easily move the cursor to the end of the string:

move ~num:max_int cs ;;

This raises Cursor_out_of_range, but places the cursor at the end. This is the position past the last letter 'r':

uchar_at cs raises End_of_string

Go one character to the left:

move ~num:(-1) cs ;;

uchar_at cs returns 114 (i.e. r)

Cursors can only move relative to their current position. Of course, one can easily write a function that moves to an absolute position, like

 let move_abs n cs = 
    let delta = n - cursor_pos cs in
    move ~num:delta cs 

However, this operation is expensive (O(string length)), and should be avoided for efficient algorithms. Cursors are not arrays, and an algorithm should only be based on cursors when it is possible to iterate over the characters of the string one after another.

Byte Order Marks

Because UTF-16 allows both little and big endian, files and other permanent representations of UTF-16 text are usually prepended by a byte order mark (BOM). There is confusion about the BOM among Unicode users, so the following explanations may be helpful.

Of course, the BOM is only used for external representations like files, as the endianess is always known for in-memory representations by the running program. This module has six encoding identifiers:

  • `Enc_utf16: UTF-16 where the endianess is unknown
  • `Enc_utf16_le: UTF-16 little endian
  • `Enc_utf16_be: UTF-16 big endian
  • `Enc_utf32: UTF-32 where the endianess is unknown
  • `Enc_utf32_le: UTF-32 little endian
  • `Enc_utf32_be: UTF-32 big endian
When a file is read, the endianess is unknown at the beginning. This is expressed by e.g. `Enc_utf16. When the BOM is read, the encoding is refined to either `Enc_utf16_le or `Enc_utf16_be, whatever the BOM says. This works as follows: The BOM is the representation of the code point 0xfeff as little or big endian, i.e. as byte sequences "0xfe 0xff" (big endian) or "0xff 0xfe" (little endian). As the "wrong" code point 0xfffe is intentionally unused, the reader can determine the endianess.

There is one problem, though. Unfortunately, the code point 0xfeff is also used for the normal "zero width non-breakable space" character. When this code point occurs later in the text, it is interpreted as this character. Of course, this means that one must know whether there is a BOM at the beginning, and if not, one must know the endianess. One cannot program in the style "well, let's see what is coming and guess".

Unicode also allows a BOM for UTF-8 although it is meaningless to specify the endianess. If you create the cursor with the encoding `Enc_utf8 nothing is done about this, and you get the BOM as normal character. If you create the cursor with `Enc_utf8_opt_bom, the BOM is treated specially like in the UTF-16 and -32 cases (with the only difference that it is optional for UTF-8).

The functions of this module can all deal with BOMs when reading encoded text. In most cases, the BOM is hidden from the caller, and just handled automatically. Cursors, however, treat BOMs as special characters outside of the code set (exception Byte_order_mark is raised). The writing functions of this module do not generate BOMs, however, as there is no way to tell them that a BOM is needed. The function byte_order_mark can be used to output the BOM manually.

Examples for Cursors

Create the cursor:

let cs = create_cursor `Enc_utf8 "B\195\164r";;

The cursor is now positioned at the 'B':

uchar_at cs returns 66 (i.e. B)

Move the cursor one character to the right. In UTF-8, this is a two-byte character consisting of the bytes 195 and 164:

move cs ;;

uchar_at cs returns 228 (i.e. a-Umlaut)

One can easily move the cursor to the end of the string:

move ~num:max_int cs ;;

This raises Cursor_out_of_range, but places the cursor at the end. This is the position past the last letter 'r':

uchar_at cs raises End_of_string

Go one character to the left:

move ~num:(-1) cs ;;

uchar_at cs returns 114 (i.e. r)

Cursors can only move relative to their current position. Of course, one can easily write a function that moves to an absolute position, like

 let move_abs n cs = 
    let delta = n - cursor_pos cs in
    move ~num:delta cs 

However, this operation is expensive (O(string length)), and should be avoided for efficient algorithms. Cursors are not arrays, and an algorithm should only be based on cursors when it is possible to iterate over the characters of the string one after another.

Unicode String Functions


val ustring_length : encoding -> ?range_pos:int -> ?range_len:int -> string -> int
Returns the length of the string in characters. The function fails when illegal byte sequences or incomplete characters are found in the string with Malformed_code.

Evaluation hints:

  • PRE_EVAL(encoding)

range_pos : The byte position of the substring to measure (default: 0)
range_len : The byte length of the substring to measure (default: byte length of the input string minus range_pos)
val ustring_length_ts : encoding ->
?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> int
Same for tagged strings
val ustring_length_poly : 's Netstring_tstring.tstring_ops ->
encoding -> ?range_pos:int -> ?range_len:int -> 's -> int
Polymorphic version
val ustring_iter : encoding ->
(int -> unit) -> ?range_pos:int -> ?range_len:int -> string -> unit
Iterates over the characters of a string, and calls the passed function for every code point. The function raises Malformed_code when illegal byte sequences or incomplete characters are found.


range_pos : The byte position of the substring to iterate over (default: 0)
range_len : The byte length of the substring to iterate over (default: byte length of the input string minus range_pos)
val ustring_iter_ts : encoding ->
(int -> unit) ->
?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> unit
Same for tagged strings
val ustring_iter_poly : 's Netstring_tstring.tstring_ops ->
encoding ->
(int -> unit) -> ?range_pos:int -> ?range_len:int -> 's -> unit
Polymorphic version
val ustring_map : encoding ->
(int -> int list) -> ?range_pos:int -> ?range_len:int -> string -> string
Maps every character of a string to a list of characters, and returns the concatenated string. The encoding argument determines the encoding of both the argument and the result string. The map function gets every character as its Unicode code point, and must return the list of code points to map to.

The function raises Malformed_code when illegal byte sequences or incomplete characters are found.


range_pos : The byte position of the substring to map (default: 0)
range_len : The byte length of the substring to map (default: byte length of the input string minus range_pos)
val ustring_map_ts : encoding ->
(int -> int list) ->
?range_pos:int ->
?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
Same for tagged strings. The output representation is the same as for the input
val ustring_map_poly : 's Netstring_tstring.tstring_ops ->
't Netstring_tstring.tstring_kind ->
encoding ->
(int -> int list) -> ?range_pos:int -> ?range_len:int -> 's -> 't
Polymorphic version
val ustring_to_lower : encoding ->
?range_pos:int -> ?range_len:int -> string -> string
Converts the input string to lowercase.

The encoding, range_pos, and range_len arguments work as for ustring_map. The exception Malformed_code is raised when illegal byte sequences are found.

val ustring_to_lower_ts : encoding ->
?range_pos:int ->
?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
Same for tagged strings. The output representation is the same as for the input
val ustring_to_lower_poly : 's Netstring_tstring.tstring_ops ->
't Netstring_tstring.tstring_kind ->
encoding -> ?range_pos:int -> ?range_len:int -> 's -> 't
Polymorphic version
val ustring_to_upper : encoding ->
?range_pos:int -> ?range_len:int -> string -> string
Converts the input string to uppercase.

The encoding, range_pos, and range_len arguments work as for ustring_map. The exception Malformed_code is raised when illegal byte sequences are found.

val ustring_to_upper_ts : encoding ->
?range_pos:int ->
?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
Same for tagged strings. The output representation is the same as for the input
val ustring_to_upper_poly : 's Netstring_tstring.tstring_ops ->
't Netstring_tstring.tstring_kind ->
encoding -> ?range_pos:int -> ?range_len:int -> 's -> 't
Polymorphic version
val ustring_to_title : encoding ->
?range_pos:int -> ?range_len:int -> string -> string
Converts the input string to titlecase.

The encoding, range_pos, and range_len arguments work as for ustring_map. The exception Malformed_code is raised when illegal byte sequences are found.

val ustring_to_title_ts : encoding ->
?range_pos:int ->
?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
Same for tagged strings. The output representation is the same as for the input
val ustring_to_title_poly : 's Netstring_tstring.tstring_ops ->
't Netstring_tstring.tstring_kind ->
encoding -> ?range_pos:int -> ?range_len:int -> 's -> 't
Polymorphic version
val ustring_sub : encoding ->
int -> int -> ?range_pos:int -> ?range_len:int -> string -> string
ustring_sub enc start length s: Returns the substring of s starting at character count start and consisting of length characters. Note that start and length select the substring by multiples of (usually multibyte) characters, not bytes.

If the optional byte-based range_pos and range_len arguments are present, these arguments are taken to determine a first substring before start and length are applied to extract the final substring.

The function raises Malformed_code when illegal byte sequences or incomplete characters are found.


range_pos : The byte position of the substring to extract (default: 0)
range_len : The byte length of the substring to extract (default: byte length of the input string minus range_pos)
val ustring_sub_ts : encoding ->
int ->
int ->
?range_pos:int ->
?range_len:int -> Netsys_types.tstring -> Netsys_types.tstring
Same for tagged strings. The output representation is the same as for the input
val ustring_sub_poly : 's Netstring_tstring.tstring_ops ->
't Netstring_tstring.tstring_kind ->
encoding ->
int -> int -> ?range_pos:int -> ?range_len:int -> 's -> 't
Polymorphic version
val ustring_compare : encoding ->
(int -> int -> int) ->
?range_pos:int ->
?range_len:int -> string -> ?range_pos:int -> ?range_len:int -> string -> int
Compares two strings lexicographically. The first argument is the encoding of both strings (which must be the same). The second argument is the function that compares two Unicode code points. It must return 0 if both characters are the same, a negative value if the first character is the smaller one, and a positive value if the second character is the smaller one.

The function raises Malformed_code when illegal byte sequences or incomplete characters are found.


range_pos : The byte position of the substring to compare (default: 0), referring to the following string argument
range_len : The byte length of the substring to compare (default: byte length of the input string minus range_pos), referring to the following string argument
range_pos : The byte position of the substring to compare (default: 0), referring to the following string argument
range_len : The byte length of the substring to compare (default: byte length of the input string minus range_pos), referring to the following string argument
val ustring_compare_ts : encoding ->
(int -> int -> int) ->
?range_pos:int ->
?range_len:int ->
Netsys_types.tstring ->
?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> int
Same for tagged strings
val ustring_compare_poly : 's1 Netstring_tstring.tstring_ops ->
's2 Netstring_tstring.tstring_ops ->
encoding ->
(int -> int -> int) ->
?range_pos:int ->
?range_len:int -> 's1 -> ?range_pos:int -> ?range_len:int -> 's2 -> int
Polymorphic version
val code_cmp : int -> int -> int
A compare function for ustring_compare: Normal string comparison: This function compares by code point
val ci_code_cmp : int -> int -> int
A compare function for ustring_compare: Case-insensitive comparison: This function compares by the lowercase code point if it exists, and the untransformed code point otherwise.

NB. This bases on the lowercase transformation that maps one char to only one char, and not to many.

val uarray_of_ustring : encoding ->
?range_pos:int -> ?range_len:int -> string -> int array
Returns the characters of the string as array of Unicode code points.


range_pos : The byte position of the substring to extract (default: 0)
range_len : The byte length of the substring to extract (default: byte length of the input string minus range_pos)
val uarray_of_ustring_ts : encoding ->
?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> int array
Same for tagged strings
val uarray_of_ustring_poly : 's Netstring_tstring.tstring_ops ->
encoding -> ?range_pos:int -> ?range_len:int -> 's -> int array
Polymorphic version
val ustring_of_uarray : ?subst:(int -> string) ->
encoding -> ?pos:int -> ?len:int -> int array -> string
Returns the array of Unicode code points as encoded string.


subst : This function is called when a code point cannot be represented in the chosen character encoding. It must returns the (already encoded) string to substitute for this code point. By default (if ~subst is not passed), the exception Cannot_represent will be raised in this case.
pos : Selects a subarray: pos is the first array position to encode (default: 0)
len : Selects a subarray: len is the length of the subarray to encode (default: array length minus pos)
exception Malformed_code_at of int
An illegal byte sequence is found at this byte position
val verify : encoding -> ?range_pos:int -> ?range_len:int -> string -> unit
Checks whether the string is properly encoded. If so, () is returned. If not, the exception Malformed_code_at will be raised indicating the byte position where the problem occurs.


range_pos : The byte position of the substring to verify (default: 0)
range_len : The byte length of the substring to verify (default: byte length of the input string minus range_pos)
val verify_ts : encoding ->
?range_pos:int -> ?range_len:int -> Netsys_types.tstring -> unit
Same for tagged strings
val verify_poly : 's Netstring_tstring.tstring_ops ->
encoding -> ?range_pos:int -> ?range_len:int -> 's -> unit
Polymorphic version
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.server_endpoint_listener.html0000644000175000017500000004160312731530352025542 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.server_endpoint_listener object
  method listen :
    Uq_engines.listen_address ->
    Unixqueue.event_system ->
    Uq_engines.server_endpoint_acceptor Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_gs2_sasl.GS2.html0000644000175000017500000004137212731530352022110 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_gs2_sasl.GS2 functor (P : PROFILE) (GSS : Netsys_gssapi.GSSAPI->
  Netsys_sasl_types.SASL_MECHANISM
ocamlnet-4.1.2/doc/html-main/Netshm.html0000644000175000017500000011403512731530352016530 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm

Module Netshm

module Netshm: sig .. end
Shared memory for O'Caml programs using multi-processing


Shared Memory Descriptors


type shm_descr 
A shared memory descriptor refers to a shared memory object. Such a descriptor must only be opened once for every process.
type shm_type = [ `File | `POSIX ] 
val supported_types : shm_type list
The types supported for this OS
type shm_name = [ `File of string | `POSIX of string * string ] 
A shm_name is a name for a shared memory object.
val shm_type_of_name : shm_name -> shm_type
val open_shm : ?unique:bool ->
shm_name -> Unix.open_flag list -> int -> shm_descr
Opens the shared memory object.

For POSIX_shm not all open flags can be specified. The flags are limited to O_RDONLY, O_RDWR, O_CREAT, O_EXCL and O_TRUNC.

unique: Unique file generation as in create_unique_shm.

val create_unique_shm : shm_name -> int -> shm_descr
Create a shared memory object under a name that is derived from the passed shm_name. The actual name can be queried with name_of_shm (below).

For POSIX and File names, deriving works by replacing the 'X' letters in the file name by random digits and letters. For example, if the name is File "/my/directory/ocaml.XXXXXX" six random characters are generated and replace the 'X' letters such that the file is unique.

The integer is the file permission.

val name_of_shm : shm_descr -> shm_name
Returns the name of an object
val close_shm : shm_descr -> unit
Closes the object. The object remains existent and can be opened again.
val unlink_shm : shm_name -> unit
Removes the name permanently from the system
val chmod_shm : shm_descr -> int -> unit
val chown_shm : shm_descr -> int -> int -> unit
Set file permission bits, user and group ownership of the object
type locking_method = [ `No_locking | `Record_locking ] 
The locking method is used to ensure that parallel read and write operations to the memory object do not interfer with each other. If No_locking is selected, such protection is not done - this is ok if only read accesses occur or if the user can ensure that never a write access is done in parallel with another access. The locking method must be compatible with the type of shared memory.
val best_locking_method : shm_type -> locking_method
Return the best locking method other than No_locking

Shared Memory Tables



Shared Memory Tables



This is a quite basic data structure implemented for shared memory: hash tables with int32 as key and one-dimensional int32 bigarray as values.

Shared Memory Tables



This is a quite basic data structure implemented for shared memory: hash tables with int32 as key and one-dimensional int32 bigarray as values.

The semantics resembles the Hashtbl of stdlib
type shm_table 
type int32_array = (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array1.t 
exception Corrupt_file of string
Raised when a violation of the object format is detected
exception Deadlock
Raised when a deadlock situation was detected. Deadlocks can occur when the group function is used
val manage : ?pagesize:int ->
?init:int -> locking_method -> shm_descr -> shm_table
Starts managing an open shared memory object as shm_table. If the object is empty, it is automatically enlarged to the minimum size and initialized. If the object is non-empty it is expected that it already contains a valid shm_table structure.

The object automatically grows in size when new elements are added to the object. By removing elements, however, the object is never shrinked. Unused memory is held back for later reallocation by the same shm_table.

By default, the table uses a page size of 256 bytes. The page size is the unit of memory allocation. The parameter pagesize overrides this default. The page size must be at least 160 and divisible by 4. The page size must be the same when the table was created.

By passing init it is enforced that the table is re-initialized (deleted and again created). The argument of init is a hint for the number of elements the table will contain. The data structure is then created such that this many elements can be added without needing expensive data reorganization.

Special note for using shm_table with multiple processes: Every process must create its own shm_descr, and every process must call manage to manage it. It is not sufficient to just fork a new process, and to keep using the already existing shm_descr or shm_table in the subprocess. (This doesn't work because the underlying file descriptor would be shared.)

val group : shm_table -> ('a -> 'b) -> 'a -> 'b
Execute a sequence of operations in a group:

 let r =
    group table
      (fun arg ->
         operation1; operation2; ...)
      arg
 

Operations can be any reading or writing functions from below. The effect is that the locking requirements of the operations are merged, so that no operation of another process can interfer with the grouped sequence. Note, however, that this gives no real atomicity as there is no way to roll back half-executed sequences.

Groups can be nested.

An example of group is to set a binding depending on the previous value of the binding. Here, we add 1:

 let add_one table =
    group table
      (fun key ->
        let ba =
          try find table key 
          with Not_found -> 
            Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout 1 in
        ba.{ 0 } <- Int32.succ ba.{ 0 };
        replace table key ba
      )
 

Grouping protects the update from modifications done by other processes at the same time. In particular, without grouping it can happen that another process also modifies the same value between find and replace.

val add : shm_table -> int32 -> int32_array -> unit
add tbl key value: Adds the binding of key to value to the table. Previous bindings are not removed, but simply hidden.
val find : shm_table -> int32 -> int32_array
find tbl key: Finds the current binding of key in tbl or raises Not_found if no such binding exists.
val find_all : shm_table -> int32 -> int32_array list
find_all tbl key returns the list of all data associated with key in tbl. The current binding is returned first, then the previous bindings, in reverse order of introduction in the table.
val mem : shm_table -> int32 -> bool
mem tbl key checks if key is bound in tbl.
val remove : shm_table -> int32 -> unit
remove tbl key removes the current binding of key in tbl, restoring the previous binding if it exists. It does nothing if key is not bound in tbl.
val replace : shm_table -> int32 -> int32_array -> unit
replace tbl key value replaces the current binding of key in tbl by a binding of key to value. If key is unbound in tbl, a binding of key to value is added to tbl.
val iter : (int32 -> int32_array -> unit) -> shm_table -> unit
iter f tbl applies f to all bindings in table tbl. f receives the key as first argument, and the associated value as second argument. Each binding is presented exactly once to f. The order in which the bindings are passed to f is unspecified. However, if the table contains several bindings for the same key, they are passed to f in reverse order of introduction, that is, the most recent binding is passed first.

While the iteration is in progress, the table is read-locked. That means you cannot modify it during the iteration.

val iter_keys : (int32 -> unit) -> shm_table -> unit
iter_keys f tbl applies f to all keys in table tbl. If there are several bindings for a key, f is only called once.

While the iteration is in progress, the table is locked. That means you cannot modify it during the iteration.

val fold : (int32 -> int32_array -> 'a -> 'a) -> shm_table -> 'a -> 'a
fold f tbl init computes (f kN dN ... (f k1 d1 init)...), where k1 ... kN are the keys of all bindings in tbl, and d1 ... dN are the associated values. Each binding is presented exactly once to f. The order in which the bindings are passed to f is unspecified. However, if the table contains several bindings for the same key, they are passed to f in reverse order of introduction, that is, the most recent binding is passed first.

While the iteration is in progress, the table is locked. That means you cannot modify it during the iteration.

val length : shm_table -> int
length tbl returns the number of bindings in tbl. Multiple bindings are counted multiply, so length gives the number of times iter calls its first argument.

Enhanced API to shared memory tables


exception Next
exception Break
val read_blocks : shm_table -> int32 -> (int32_array option -> unit) -> unit
find_blocks tbl key f: The values may be stored in several disk blocks. This interface allows one to access the values block by block. As find_all, all bindings for key in tbl are determined in reverse order, i.e. the newest binding first, the oldest last. For every binding value, the function f is invoked in a sequence f (Some v1), f (Some v2), ..., f (Some vN), f None where value is the array concatenation of v1, v2, ..., vN. The function f may raise the exception Next to go directly to the start of the next binding of key. The exception Break stops the iteration immediately.

Note that the int32_array fragments vK point to shared memory. Any assignment would modify the shared memory object directly! The binding is at that time, however, only read-locked, so this should be avoided.

type write_op = [ `Remove_binding ] 
type ctrl_op = [ `Nop | `Remove_binding ] 
val write_blocks : shm_table ->
write_op list ->
int32 -> (int32_array option -> ctrl_op) -> unit
write_blocks tbl ops key f: Like read_blocks this function iterates over the blocks of all bindings for key. For every binding value, the function f is invoked in a sequence f (Some v1), f (Some v2), ..., f (Some vN), f None. Unlike read_blocks the function f returns a value. The last non-`Nop result value in this sequence determines the modification to carry out for the binding:

  • `Remove_binding: The whole binding is removed from the table.
If all invocations of f just return `Nop, no further modification is done.

The modifications must be announced in the ops argument. It is not allowed that f returns a value not being a member of ops (except `Nop).

It is possible to raise the special exceptions Next and Break just as for read_blocks.

Note that the int32_array fragments vK point to shared memory. Any assignment will modify the shared memory object directly! The binding is at that time write-locked, so such assignments are protected against concurrent writes.

val dump : shm_table -> unit
val bigarray : int array -> int32_array
val memory : shm_table ->
(int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array2.t
ocamlnet-4.1.2/doc/html-main/Netchannels.html0000644000175000017500000016115712731530352017543 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels

Module Netchannels

module Netchannels: sig .. end


Types



Types



There are three levels of class types for channels:
  • rec_in_channel and rec_out_channel: Primitive, but standardized level
  • raw_in_channel and raw_out_channel: Unix level
  • in_obj_channel and out_obj_channel: Application level
The "rec" level has been recently introduced to improve interoperability with other libraries (e.g. camomile). The idea is to standardize the real core methods of I/O, so they have the same meaning in all libraries. Read "Basic I/O class types" for more.

The "raw" level represents the level of Unix file descriptors.

The application level is what should be used in programs. In addition to the "raw" level one can find a number of convenience methods, e.g. input_line to read a line from the channel. The downside is that these methods usually work only for blocking I/O.

One can lower the level by coercion, e.g. to turn an in_obj_channel into a rec_in_channel, apply the function

(fun ch -> (ch : in_obj_channel :> rec_in_channel))

To higher the level, apply lift_in or lift_out, defined below.

Types



There are three levels of class types for channels:
  • rec_in_channel and rec_out_channel: Primitive, but standardized level
  • raw_in_channel and raw_out_channel: Unix level
  • in_obj_channel and out_obj_channel: Application level
The "rec" level has been recently introduced to improve interoperability with other libraries (e.g. camomile). The idea is to standardize the real core methods of I/O, so they have the same meaning in all libraries. Read "Basic I/O class types" for more.

The "raw" level represents the level of Unix file descriptors.

The application level is what should be used in programs. In addition to the "raw" level one can find a number of convenience methods, e.g. input_line to read a line from the channel. The downside is that these methods usually work only for blocking I/O.

One can lower the level by coercion, e.g. to turn an in_obj_channel into a rec_in_channel, apply the function

(fun ch -> (ch : in_obj_channel :> rec_in_channel))

To higher the level, apply lift_in or lift_out, defined below.

Interface changes: Since ocamlnet-0.98, the semantics of the methods input and output has slightly changed. When the end of the channel is reached, input raises now End_of_file. In previous releases of ocamlnet, the value 0 was returned. When the channel cannot process data, but is in non-blocking mode, both methods now return the value 0. In previous releases of ocamlnet, the behaviour was not defined.

Ocamlnet-3.0 changed the behavior of close_out. Errors are no longer reported - instead, the exception is logged to Netlog. For a stricter error handling, it is suggested to call flush first. Also, close_in and close_out no longer raise Closed_channel when the channel is already closed. Read more about this in the section Netchannels.rec_out_channel.close_error.

exception Closed_channel
Raised when channel operations are called when the channel is closed
exception Buffer_underrun
Raised by input methods if the internal buffer of the channel is too empty to read even one byte of data. This exception is only used by certain implementations of channel classes.
exception Command_failure of Unix.process_status
Raised by close_in or close_out if the channel is connected with another process, and the execution of that process fails.
class type rec_in_channel = object .. end
Recommended input class type for library interoperability.
class type raw_in_channel = object .. end
Basic Unix-level class type for input channels as used by ocamlnet.
class type rec_out_channel = object .. end
Recommended output class type for library interoperability.
class type raw_out_channel = object .. end
Basic Unix-level class type for output channels as used by ocamlnet.
class type raw_io_channel = object .. end
A channel supporting both input and output.
class type compl_in_channel = object .. end
Further methods usually supported by ocamlnet channel implementations.
class type in_obj_channel = object .. end
The application-level input channel supports raw and complemented methods
class type compl_out_channel = object .. end
Further methods usually supported by ocamlnet channel implementations.
class type out_obj_channel = object .. end
The application-level output channel supports raw and complemented methods
class type io_obj_channel = object .. end
A channel supporting both input and output.
class type trans_out_obj_channel = object .. end
A transactional output channel has a buffer for uncommitted data.

Input channels


class input_channel : ?onclose:unit -> unit -> Pervasives.in_channel -> in_obj_channel
Creates an input channel from an in_channel, which must be open.
val input_channel : ?onclose:(unit -> unit) ->
Pervasives.in_channel -> in_obj_channel
Same as function
class input_command : string -> in_obj_channel
Runs the command with /bin/sh, and reads the data the command prints to stdout.
val input_command : string -> in_obj_channel
Same as function
class input_string : ?pos:int -> ?len:int -> string -> in_obj_channel
Creates an input channel from a (constant) string.
val input_string : ?pos:int -> ?len:int -> string -> in_obj_channel
Same as function
class input_bytes : ?pos:int -> ?len:int -> Bytes.t -> in_obj_channel
Same for constant bytes
val input_bytes : ?pos:int -> ?len:int -> Bytes.t -> in_obj_channel
Same as function
class input_memory : ?pos:int -> ?len:int -> Netsys_types.memory -> in_obj_channel
Same for constant memory
val input_memory : ?pos:int -> ?len:int -> Netsys_types.memory -> in_obj_channel
Same as function
val input_tstring : ?pos:int -> ?len:int -> Netsys_types.tstring -> in_obj_channel
Same for tagged strings (only as function)
val create_input_netbuffer : ?keep_data:bool -> Netbuffer.t -> in_obj_channel * (unit -> unit)
Creates an input channel and a shutdown function for a netbuffer. This is a destructive implementation: Every time data is read, the octets are taken from the beginning of the netbuffer, and they are deleted from the netbuffer (recall that a netbuffer works like a queue of characters).

Conversely, the user of this class may add new data to the netbuffer at any time. When the shutdown function is called, the EOF condition is recorded, and no further data must be added.

If the netbuffer becomes empty, the input methods raise Buffer_underrun when the EOF condition has not yet been set, and they raise End_of_file when the EOF condition has been recorded.

keep_data: do not delete read data from the buffer

val lexbuf_of_in_obj_channel : in_obj_channel -> Lexing.lexbuf
Creates a lexical buffer from an input channel. The input channel is not closed when the end is reached

This function does not work for non-blocking channels.

val string_of_in_obj_channel : in_obj_channel -> string
Reads from the input channel until EOF and returns the characters as string. The input channel is not closed.

This function does not work for non-blocking channels.

val bytes_of_in_obj_channel : in_obj_channel -> Bytes.t
Same for bytes
val lines_of_in_obj_channel : in_obj_channel -> string list
Reads from the input channel until EOF and returns the lines as string list. The input channel is not closed.

This function does not work for non-blocking channels.

val with_in_obj_channel : (#in_obj_channel as 'a) -> ('a -> 'b) -> 'b
with_in_obj_channel ch f: Computes f ch and closes ch. If an exception happens, the channel is closed, too.

Output channels


class output_channel : ?onclose:unit -> unit -> Pervasives.out_channel -> out_obj_channel
Creates an output channel writing into an out_channel.
class output_command : ?onclose:unit -> unit -> string -> out_obj_channel
Runs the command with /bin/sh, and data written to the channel is piped to stdin of the command.
class output_buffer : ?onclose:unit -> unit -> Buffer.t -> out_obj_channel
This output channel writes the data into the passed buffer.
class output_netbuffer : ?onclose:unit -> unit -> Netbuffer.t -> out_obj_channel
This output channel writes the data into the passed netbuffer.
class output_null : ?onclose:unit -> unit -> unit -> out_obj_channel
This output channel discards all written data.
val with_out_obj_channel : (#out_obj_channel as 'a) -> ('a -> 'b) -> 'b
with_out_obj_channel ch f: Computes f ch and closes ch. If an exception happens, the channel is closed, too.

Delegation classes



Delegation classes



Delegation classes just forward method calls to an parameter object, i.e. when method m of the delegation class is called, the definition of m is just to call the method with the same name m of the parameter object. This is very useful in order to redefine methods individually.

For example, to redefine the method pos_in of an in_obj_channel, use

 class my_channel = object(self)
   inherit in_obj_channel_delegation ...
   method pos_in = ...
 end
 

As a special feature, the following delegation classes can suppress the delegation of close_in or close_out, whatever applies. Just pass close:false to get this effect, e.g.

 class input_channel_don't_close c =
   in_obj_channel_delegation ~close:false (new input_channel c)
 
This class does not close c : in_channel when the close_in method is called.
class rec_in_channel_delegation : ?close:bool -> rec_in_channel -> rec_in_channel
class raw_in_channel_delegation : ?close:bool -> raw_in_channel -> raw_in_channel
class in_obj_channel_delegation : ?close:bool -> in_obj_channel -> in_obj_channel
class rec_out_channel_delegation : ?close:bool -> rec_out_channel -> rec_out_channel
class raw_out_channel_delegation : ?close:bool -> raw_out_channel -> raw_out_channel
class out_obj_channel_delegation : ?close:bool -> out_obj_channel -> out_obj_channel

Lifting channels



Lifting channels



The following classes and functions add missing methods to reach a higher level in the hierarchy of channel class types. For most uses, the lift_in and lift_out functions work best.
val lift_in : ?eol:string list ->
?buffered:bool ->
?buffer_size:int ->
?pass_through:int ->
[ `Raw of raw_in_channel | `Rec of rec_in_channel ] ->
in_obj_channel
Turns a rec_in_channel or raw_in_channel, depending on the passed variant, into a full in_obj_channel object. (This is a convenience function, you can also use the classes below directly.) If you want to define a class for the lifted object, use
 class lifted_ch ... =
   in_obj_channel_delegation (lift_in ...)
 


eol : The accepted end-of-line delimiters. The method input_line recognizes any of the passed strings as EOL delimiters. When more than one delimiter matches, the longest is taken. Defaults to ["\n"] . The default cannot be changed when buffered=false (would raise Invalid_argument). The delimiter strings must neither be empty, nor longer than buffer_size.
buffered : Whether a buffer is added, by default true
buffer_size : The size of the buffer, if any, by default 4096
pass_through : If the read request has at least this size, and the buffer is currently empty, the buffer will be bypassed. Defaults to max_int, i.e. it is off.
val lift_out : ?buffered:bool ->
?buffer_size:int ->
?pass_through:int ->
[ `Raw of raw_out_channel | `Rec of rec_out_channel ] ->
out_obj_channel
Turns a rec_out_channel or raw_out_channel, depending on the passed variant, into a full out_obj_channel object. (This is a convenience function, you can also use the classes below directly.) If you want to define a class for the lifted object, use
 class lifted_ch ... =
   out_obj_channel_delegation (lift_out ...)
 


buffered : Whether a buffer is added, by default true
buffer_size : The size of the buffer, if any, by default 4096
pass_through : If the write request has at least this size, and the buffer is currently empty, the buffer will be bypassed. Defaults to max_int, i.e. it is off.
class virtual augment_raw_in_channel : object .. end
This class implements the methods from compl_in_channel by calling the methods of raw_in_channel.
class lift_rec_in_channel : ?start_pos_in:int -> rec_in_channel -> in_obj_channel
This class implements pos_in and the methods from compl_in_channel by calling the methods of rec_in_channel.
class virtual augment_raw_out_channel : object .. end
This class implements the methods from compl_out_channel by calling the methods of raw_out_channel.
class lift_raw_out_channel : raw_out_channel -> out_obj_channel
This class implements the methods from compl_out_channel by calling the methods of raw_out_channel.
class lift_rec_out_channel : ?start_pos_out:int -> rec_out_channel -> out_obj_channel
This class implements pos_out and the methods from compl_out_channel by calling the methods of rec_out_channel.
type input_result = [ `Data of int | `Separator of string ] 
This type is for the method enhanced_input of enhanced_raw_in_channel.
  • `Data n means that n bytes have been copied to the target string
  • `Separator s means that no bytes have been copied, but that an end-of-line separator s has been found

class type enhanced_raw_in_channel = object .. end
Defines private methods reading text line by line
class buffered_raw_in_channel : ?eol:string list -> ?buffer_size:int -> ?pass_through:int -> raw_in_channel -> enhanced_raw_in_channel
This class adds a buffer to the underlying raw_in_channel.
class buffered_raw_out_channel : ?buffer_size:int -> ?pass_through:int -> raw_out_channel -> raw_out_channel
This class adds a buffer to the underlying raw_out_channel.

Channels over descriptors


class input_descr : ?blocking:bool -> ?start_pos_in:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_in_channel
Creates a raw_in_channel for the passed file descriptor, which must be open for reading.
class output_descr : ?blocking:bool -> ?start_pos_out:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_out_channel
Creates a raw_out_channel for the passed file descriptor, which must be open for writing.
class socket_descr : ?blocking:bool -> ?start_pos_in:int -> ?start_pos_out:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_io_channel
Creates a raw_io_channel for the passed socket descriptor, which must be open for reading and writing, and not yet shut down in either direction.

Transactional channels


type close_mode = [ `Commit | `Rollback ] 
Whether a close_out implies a commit or rollback operation
class buffered_trans_channel : ?close_mode:close_mode -> out_obj_channel -> trans_out_obj_channel
A transactional output channel with a transaction buffer implemented in memory
val make_temporary_file : ?mode:int ->
?limit:int ->
?tmp_directory:string ->
?tmp_prefix:string ->
unit -> string * Pervasives.in_channel * Pervasives.out_channel
Creates a temporary file in the directory tmp_directory with a name prefix tmp_prefix and a unique suffix. The function returns the triple (name, inch, outch) containing the file name, the file opened as in_channel inch and as out_channel outch.


mode : The creation mask of the file; defaults to 0o600, i.e. the file is private for the current user
limit : Limits the number of trials to find the unique suffix. Defaults to 1000.
tmp_directory : Defaults to Netsys_tmp.tmp_directory()
tmp_prefix : By default "netstring". This needs not to be unique, but just descriptive.
class tempfile_trans_channel : ?close_mode:close_mode -> ?tmp_directory:string -> ?tmp_prefix:string -> out_obj_channel -> trans_out_obj_channel
A transactional output channel with a transaction buffer implemented as temporary file

Pipes and Filters



Pipes and Filters



Note that this has nothing to do with "pipes" on the Unix level. It is, however, the same idea: Connecting two I/O resources with an intermediate buffer.
class pipe : ?conv:Netbuffer.t -> bool -> Netbuffer.t -> unit -> ?buffer_size:int -> unit -> io_obj_channel
A pipe has two internal buffers (realized by Netbuffer).
class output_filter : io_obj_channel -> out_obj_channel -> out_obj_channel
An output_filter filters the data written to it through the io_obj_channel (usually a pipe), and writes the filtered data to the passed out_obj_channel.
class input_filter : in_obj_channel -> io_obj_channel -> in_obj_channel
An input_filter filters the data read from it through the io_obj_channel (usually a pipe after the data have been retrieved from the passed in_obj_channel.

Notes, Examples



Notes, Examples



If you have the choice, prefer output_filter over input_filter. The latter is slower.

The primary application of filters is to encode or decode a channel on the fly. For example, the following lines write a BASE64-encoded file:

let ch = new output_channel (open_out "file.b64") in
 let encoder = new Netencoding.Base64.encoding_pipe ~linelength:76 () in
 let ch' = new output_filter encoder ch in
 ... (* write to ch' *)
 ch' # close_out();
 ch  # close_out();  (* you must close both channels! *)
 

All bytes written to ch' are BASE64-encoded and the encoded bytes are written to ch.

There are also pipes to decode BASE64, and to encode and decode the "Quoted printable" format. Encoding and decoding work even if the data is delivered in disadvantageous chunks, because the data is "re-chunked" if needed. For example, BASE64 would require that data arrive in multiples of three bytes, and to cope with that, the BASE64 pipe only processes the prefix of the input buffer that is a multiple of three, and defers the encoding of the extra bytes till the next opportunity.
ocamlnet-4.1.2/doc/html-main/Netmech_digest_sasl.html0000644000175000017500000004665312731530352021250 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_sasl

Module Netmech_digest_sasl

module Netmech_digest_sasl: sig .. end
The DIGEST-MD5 SASL mechanism (RFC 2831).

This mechanism is only provided to connect to old services; it shouldn't be used otherwise.

Key facts:

  • The password is not sent in the clear
  • Not only authenticates the client to the server, but the client can also find out whether the server knew the password, i.e. the server is also authenticated.
  • DIGEST-MD5 is vulnerable to man-in-the-middle attacks.
  • The MD5 hash is broken (too weak)
Only "auth" mode is supported (no integrity or privacy protection).

This implementation rejects servers that offer multiple realms.

This implementation supports both server_session_id (which is the nonce) and the client_session_id (the cnonce).

Parameters:

  • create_server_session understands: "realm" (optional), "nonce" (optional)
  • server_prop will return: "realm" (the realm selected by the client), "nonce", "digest-uri" (once known), "cnonce" (once known), "nc" (once known).
  • create_client_session understands: "realm" (optional), "cnonce" (optional), "digest-uri" (optional). If the digest-uri is not set, it defaults to "generic/generic".
  • client_prop will return: "cnonce", "realm" (once known; this is always the server realm), "nonce" (once known), "nc" (after sending the response).
  • The parameters mutual and secure are understood but ignored (there is mutual authentication anyway, and DIGEST is considered as secure method)
As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of DIGEST-MD5 should pass user names and passwords through Netsaslprep.saslprep.

module DIGEST_MD5: Netsys_sasl_types.SASL_MECHANISM 
The DIGEST-MD5 SASL mechanism (RFC 2831).
ocamlnet-4.1.2/doc/html-main/type_Netmcore_sem.html0000644000175000017500000004334612731530352020761 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_sem sig
  type semaphore
  val dummy : unit -> Netmcore_sem.semaphore
  val create : Netmcore_heap.mutator -> int -> Netmcore_sem.semaphore
  val destroy : Netmcore_sem.semaphore -> unit
  val getvalue : Netmcore_sem.semaphore -> int
  val post : Netmcore_sem.semaphore -> unit
  val wait : Netmcore_sem.semaphore -> Netsys_posix.sem_wait_behavior -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netauth.html0000644000175000017500000004530312731530352017744 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netauth sig
  val hmac :
    h:(string -> string) ->
    b:int -> l:int -> k:string -> message:string -> string
  type key_type = [ `Kc | `Ke | `Ki ]
  val derive_key_rfc3961_simplified :
    encrypt:(string -> string) ->
    random_to_key:(string -> string) ->
    block_size:int ->
    k:int -> usage:int -> key_type:Netauth.key_type -> string
  val xor_s : string -> string -> string
  val add_1_complement : string -> string -> string
  val rotate_right : int -> string -> string
  val n_fold : int -> string -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netmcore_camlbox.html0000644000175000017500000004250312731530352021614 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_camlbox sig
  val create_camlbox :
    string -> int -> int -> 'Netcamlbox.camlbox * Netmcore.res_id
  val lookup_camlbox_address : Netmcore.res_id -> Netcamlbox.camlbox_address
  val lookup_camlbox_sender : Netmcore.res_id -> 'Netcamlbox.camlbox_sender
end
ocamlnet-4.1.2/doc/html-main/Rpc_portmapper_clnt.Make'PMAP.html0000644000175000017500000004377512731530352022724 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt.Make'PMAP

Functor Rpc_portmapper_clnt.Make'PMAP

module Make'PMAP: 
functor (U'C : Rpc_client_pre.USE_CLIENT) -> sig .. end
Parameters:
U'C : Rpc_client_pre.USE_CLIENT

module V2: sig .. end
module V3: sig .. end
module V4: sig .. end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.input_async_descr-c.html0000644000175000017500000004257412731530352024675 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.input_async_descr

Class Uq_engines_compat.input_async_descr

class input_async_descr : src:Unix.file_descr -> ?buffer_size:int -> ?close_src:bool -> Unixqueue.event_system -> async_in_channel_engine

ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.TLS_PROVIDER.html0000644000175000017500000013537712731530352023372 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_PROVIDER

Module type Netsys_crypto_types.TLS_PROVIDER

module type TLS_PROVIDER = sig .. end


Provides TLS functionality.

Users should not call functions of the provider directly, but use Netsys_tls, or another higher-level layer.

type config 
type credentials 
type endpoint 
module Exc: Netsys_crypto_types.TLS_EXCEPTIONS 
Access to exceptions
val error_message : string -> string
Returns the message for humans (display, log files etc.) when called with an error or warning symbol.
type dh_params = [ `Generate of int | `PKCS3_DER of string | `PKCS3_PEM_file of string ] 
Diffie-Hellman parameters:

  • `PKCS3_PEM_file name: points to a PEM-encoded PKCS3-file ("BEGIN DH PARAMETERS")
  • `PKCS3_DER data: the parameters are in a DER-encoded PKCS3 structure
  • `Generate bits: the parameters are generated with the passed number of bits

val create_config : ?algorithms:string ->
?dh_params:dh_params ->
?verify:(endpoint -> bool -> bool -> bool) ->
peer_auth:[ `None | `Optional | `Required ] ->
credentials:credentials ->
unit -> config
The configuration includes:

  • algorithms: a string specifying which cryptographic algorithms, protocols and protocol options are enabled, and in which priority they are used in the negotiation. (GnuTLS calls this "priority string".) The syntax is implementation-defined.
  • dh_params: parameters for Diffie-Hellman key exchange (used for DH-based authentication, but only on the server side)
  • peer_auth: controls whether the peer is requested to authenticate. This can be set to `None meaning not to request authentication and to ignore credentials, or to `Optional meaning not to request authentication but to check credentials if they are sent nevertheless, or to `Required meaning to request and check credentials. For "standard clients" you should set this to `Required, and for "standard servers" to `None or `Required.
  • credentials describes our own credentials, and the accepted credentials of the peer.
  • verify is a function called to verify the peer certificate in addition to the actions of peer_auth. The function must return true in order to be successful. The arguments of the function are the TLS endpoint, and two bools indicating the success of previous checks. The first bool says whether the certificate is trusted (based on peer_auth, trust and system_trust), and the second bool says whether the host name of the peer matches the name in the certificate. If not passed, verify defaults to (fun _ cert_ok name_ok -> cert_ok && name_ok), i.e. both bools must be true.
A configuration is read-only once created, and can be used for several endpoints. In particular, it does not cache TLS sessions.
type crt_list = [ `DER of string list | `PEM_file of string ] 
Certificates are given either as:

  • `PEM_file name: The certs are stored in this file, and are PEM-encoded.
  • `DER l: The certs are given directly in their DER-encoded form
See also Credentials for TLS.
type crl_list = [ `DER of string list | `PEM_file of string ] 
Certificate revocation lists are given either as:

  • `PEM_file name: The CRLs are stored in this file, and are PEM-encoded.
  • `DER l: The CRLs are given directly in their DER-encoded form
See also Credentials for TLS.
type private_key = [ `DSA of string
| `EC of string
| `PEM_file of string
| `PKCS8 of string
| `PKCS8_encrypted of string
| `RSA of string ]
Private keys are given either as:

  • `PEM_file name: The key is stored PEM-encoded in this file. The PEM header indicates the format.
  • `RSA data: The key is a PKCS1 RSA key
  • `DSA data: The key is a DSA key
  • `EC data: The key is for an elliptic curve
  • `PKCS8 data: The key is in a PKCS8 data structure
  • `PKCS8_encrypted data: The key is in a PKCS8 data structure, and is additionally encrypted.
See also Credentials for TLS.
val create_x509_credentials : ?system_trust:bool ->
?trust:crt_list list ->
?revoke:crl_list list ->
?keys:(crt_list *
private_key * string option)
list ->
unit -> credentials
Create X.509 credentials from individual objects:
  • system_trust: if set, the system certificates are trusted
  • trust specifies the CAs of peers to trust (default: empty)
  • revoke specifies CRLs for revocation of peer certificates (default: empty)
  • keys are our own certificates, as triples (cert_path, private_key, password) (default: empty)
A client should set trust to the list of CAs it can accept on the server side. It is not required to specify a key.

A server must specify a key (but can also specify several keys). If a server requests authentication from the client, it must also set trust.

The keys must include the certificate path cert_path, starting with the endpoint certificate, and followed by all middle certificates, but omitting the certificate of the CA. The private_key is the key of the endpoint. If it is password-encrypted, the password must be given.

val create_endpoint : role:[ `Client | `Server ] ->
recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
endpoint
Creates a new endpoint for this configuration.

peer_name is the expected common name or DNS name of the peer. peer_name has an option type as it is not always required to pass it. However, keep in mind that clients normally authenticate servers (peer_auth=`Required). In order to do so, they need to check whether the name in the server certificate equals the DNS name of the service they are connected to. This check is done by comparing peer_name with the name in the certificate.

peer_name is also used for the SNI extension.

Servers normally need not to set peer_name. You can also omit it when there is no name-driven authentication at all.

The endpoint will use the functions recv and send for I/O, which must be user-supplied. recv buf is expected to read data into the buffer, and to return the number of bytes, or 0 for EOF. send buf n is expected to send the n first bytes in buf.

Both functions may raise Unix_error. The codes Unix.EAGAIN and Unix.EINTR are specially interpreted.

val stash_endpoint : endpoint -> exn
The endpoint in "stashed" form, encapsulated as an exception. This form is intended for keeping the session alive in RAM, but without keeping references to the recv and send functions.

The endpoint passed in to stash_endpoint must no longer be used!

val restore_endpoint : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
exn -> endpoint
Reconnect the stashed endpoint with recv and send functions
val resume_client : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
string -> endpoint
Creates a new endpoint that will resume an old session. This implies the client role.

The session data is passed as string, which must have been retrieved with get_session_data.

type state = [ `Accepting
| `Data_r
| `Data_rs
| `Data_rw
| `Data_w
| `End
| `Handshake
| `Refusing
| `Start
| `Switching ]
The state of a session:

  • `Start: Before the session is started
  • `Handshake: The handshake is being done (and hello needs to be called again)
  • `Data_rw: The connection exists, and is read/write
  • `Data_r: The connection exists, and is read-only
  • `Data_w: The connection exists, and is write-only
  • `Data_rs: The connection exists, and data can be read. There was a switch request (initiated by us), and a response is awaited. No data can be sent in the moment.
  • `Switching: A rehandshake is being negotiated (and switch needs to be called again)
  • `Accepting: A rehandshake is being accepted (and accept_switch needs to be called again)
  • `Refusing: A rehandshake is being refused (and refuse_switch needs to be called again)
  • `End: After finishing the session

val get_state : endpoint ->
state
Return the recorded state
type raw_credentials = [ `Anonymous | `X509 of string ] 
The encoded credentials:
  • `X509 s: The X509 certificate in DER encoding
  • `Anonymous: no certificate or other key is available

val at_transport_eof : endpoint -> bool
Whether the underlying transport channel has seen the end of input. Use this after recv or mem_recv returned 0 to check whether only the TLS enf-of-input message has been read, or the underlying channel (usually the file descriptor) has indicated EOF.
val hello : endpoint -> unit
Performs the initial handshake (exchanges credentials and establishes a session).

hello doesn't verify the peer. Use verify for that.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val bye : endpoint -> Unix.shutdown_command -> unit
Performs the final handshake (exchanges close requests).

If SHUTDOWN_SEND is set, the close request is sent to the peer, and the TLS tunnel is considered as closed for writing. The application can receive further data until recv returns zero bytes meaning that the peer responded with another close request.

If SHUTDOWN_ALL is passed, it is additionally waited until the peer responds with a close request.

A simple SHUTDOWN_RECEIVE is unimplemented and ignored.

In no case the underlying transport is closed or shut down!

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val verify : endpoint -> unit
verify ep peer_name: Checks that:
  • there is a trust chain for the peer's certificate
  • that peer_name is the common name of the certificate subject, or an alternate name
These checks are not performed if peer_auth=`None is set in the configuration!

Additionally, the verify function in the endpoint configuration is called back, and a failure is indicated if this function returns false. This callback is useful to get the certificate of the peer and to perform further checks.

The verify function will raise Failure on failed checks (and Error for internal processing errors).

val get_config : endpoint ->
config
Get the current config (possibly modified because of a rehandshake)
val get_endpoint_creds : endpoint ->
raw_credentials
Get the credentials that was actually used in the handshake, in raw format.
val get_peer_creds : endpoint ->
raw_credentials
Get the credentials of the peer, in raw format. Raises Not_found if not applicable/no credentials present.
val get_peer_creds_list : endpoint ->
raw_credentials list
Get the chain that was actually used in the handshake.
val switch : endpoint ->
config -> unit
The server can use this to request a rehandshake and to use the new configuration for cert verification. This function sends the request, and expects a soon response from the client. The state enters `Data_rs meaning that we can still read data, and at some point recv will raise TLS_switch_response.

On the client side, the request will by returned as exception TLS_switch_request by recv. The client should respond with accept_switch if it accepts the handshake, or refuse_switch if not.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val accept_switch : endpoint ->
config -> unit
On the client: Enter another handshake round with new configuration data.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val refuse_switch : endpoint -> unit
On the client: Refuse a handshake

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val send : endpoint ->
Netsys_types.memory -> int -> int
send ep buffer n: Sends the first n bytes in the buffer over the endpoint, and returns the actual number of processed bytes.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val recv : endpoint -> Netsys_types.memory -> int
recv ep buffer n: Receives data, and puts them into the memory buffer, and returns the actual number of received bytes. If 0 is returned, a close request was received by the peer. For closing the tunnel properly this request should be responded by another close request with bye (unless this has already been done).

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

The exception TLS_switch_request can only occur on the client side, and should be responded by accept_switch or refuse_switch.

The exception TLS_switch_response can only occur on the server side.

val recv_will_not_block : endpoint -> bool
If there is still unprocessed data in the endpoint buffer, recv is guaranteed not to block or raise EAGAIN.
val get_session_id : endpoint -> string
The (non-printable) session ID
val get_session_data : endpoint -> string
Get the (non-printable) marshalled session data, for later resumption with resume_client
val get_cipher_suite_type : endpoint -> string
The type of the cipher suite:
  • "X509": X509 certificates are used
  • "OPENPGP": OpenPGP certificates are used
  • "ANON": anonymous credentials
  • "SRP": SRP credentials
  • "PSK": PSK credentials

val get_cipher_algo : endpoint -> string
Get the name of the cipher
val get_kx_algo : endpoint -> string
Get the name of the key exchange method
val get_mac_algo : endpoint -> string
Get the name of the message authentication code
val get_compression_algo : endpoint -> string
Get the name of the record-level compression method
val get_cert_type : endpoint -> string
Get the type of the certificate
val get_protocol : endpoint -> string
Get the name of the tunnel protocol
type server_name = [ `Domain of string ] 
val get_addressed_servers : endpoint ->
server_name list
To be used in servers: The client can address one of several virtual servers with the SNI extension, and this function returns which was requested. Raises Not_found if there is nothing appropriate. This information is only available after a handshake, and if the client submitted it.
val set_session_cache : store:(string -> string -> unit) ->
remove:(string -> unit) ->
retrieve:(string -> string) ->
endpoint -> unit
Sets the three callbacks for storing, removing and retrieving sessions (on the server side)
val implementation_name : string
String name of the implementation. By convention this is the full OCaml module path, e.g. "Nettls_gnutls.TLS"
val implementation : unit -> exn
Implementation-defined additional functionality
ocamlnet-4.1.2/doc/html-main/Netplex_mp.html0000644000175000017500000004344212731530352017410 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mp

Module Netplex_mp

module Netplex_mp: sig .. end
Multi-processing provider

class mp : ?keep_fd_open:bool -> ?terminate_tmo:int -> unit -> Netplex_types.parallelizer
Uses Unix.fork to create new threads.
val mp : ?keep_fd_open:bool ->
?terminate_tmo:int -> unit -> Netplex_types.parallelizer
Uses Unix.fork to create new threads. See Netplex_mp.mp for details.
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.pseudo_async_in_channel-c.html0000644000175000017500000004255712731530352026034 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.pseudo_async_in_channel

Class Uq_engines_compat.pseudo_async_in_channel

class pseudo_async_in_channel : #Netchannels.raw_in_channel -> async_in_channel

ocamlnet-4.1.2/doc/html-main/type_Rpc_server.auth_method.html0000644000175000017500000004321312731530352022744 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.auth_method object
  method authenticate :
    Rpc_server.t ->
    Rpc_server.connection_id ->
    Rpc_server.auth_details -> (Rpc_server.auth_result -> unit) -> unit
  method flavors : string list
  method invalidate : unit -> unit
  method invalidate_connection : Rpc_server.connection_id -> unit
  method name : string
  method peek : Rpc_server.auth_peeker
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.sync_engine-c.html0000644000175000017500000004372512731530352022116 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.sync_engine

Class Uq_engines.sync_engine

class [['a, 'b]] sync_engine : 'a #engine -> 'b #engine -> [('a * 'b)] engine
This engine runs two engines in parallel, and waits until both are `Done (synchronization). The product of the two `Done arguments is taken as the combined result.

If one of the engines goes to the states `Aborted or `Error, the combined engine will follow this transition. The other, non-aborted and non-errorneous engine is aborted in this case. `Error has higher precedence than `Aborted.

If the combined engine is aborted, this request is forwarded to both member engines.


ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.datagram_socket_provider.html0000644000175000017500000004165512731530352027043 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.datagram_socket_provider object
  method create_datagram_socket :
    Uq_engines_compat.datagram_type ->
    Unixqueue.event_system ->
    Uq_engines_compat.wrapped_datagram_socket Uq_engines_compat.engine
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.http_reactor_config-c.html0000644000175000017500000004470612731530352025054 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_reactor_config

Class type Nethttpd_reactor.http_reactor_config

class type http_reactor_config = object .. end
Inherits
method config_reactor_synch : [ `Close | `Connection | `Flush | `Write ]
Specifies when to synchronize output, i.e. force that all channel data are actually transmitted to the client:
  • `Connection means only at the end of the connection. This means that the channels of all pending requests may be buffered - needs a huge amount of memory
  • `Close means only when closing the output channel (after every response). This means that the whole response may be buffered - needs a lot of memory.
  • `Flush means only when the flush method is called. This is a good idea when one can control that.
  • `Write means every time the internal output buffer overflows. This is the recommended setting in general.

ocamlnet-4.1.2/doc/html-main/Netsys_sem.html0000644000175000017500000006471412731530352017433 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sem

Module Netsys_sem

module Netsys_sem: sig .. end

Generic anonymous semaphores




This module purely exists to also support "kind of anonymous" sempahores on MacOS X (which only has named semaphores). On other OS, it is just a wrapper for the functions in Netsys_posix.

Note that on OS X named semaphores have a max name length of 31 characters (including the / at the beginning), and that Netsys_sem uses 9 characters for its own purposes, leaving 22 characters for the prefix. (On other OS this is less restricted.)

val have_anon_semaphores : unit -> bool
Returns true if anonymous semaphores are supported on this system, either natively or emulated via named semaphores.

Constants.
val sem_value_max : int
The maximum value of a semaphore, but at most max_int
val sem_size : int
The size of an anonymous semaphore in bytes (sizeof(sem_t))

Types.
type container 
The container of the semaphore is the shared memory object
type prefix = string 
A name starting with a slash. Must not contain further slashes
type anon_semaphore 
type sem_open_flag = Netsys_posix.sem_open_flag = 
| SEM_O_CREAT
| SEM_O_EXCL

Container functions.
val container : prefix -> container
container prefix: The prefix shall identify the container uniquely. Once can e.g. use the path of the shared memory object. The prefix is used to construct names for persistent objects.

Note that containers have kernel persistence! They are not automatically deleted when the process finishes. Call drop to delete containers, or create_container to force their creation as fresh objects.

If the container does not exist yet, it is created. Otherwise the container is just opened.

val create_container : prefix -> container
create_container prefix: Like container, but the container is always created. A previous instance is first deleted.
val prefix : container -> prefix
Return the prefix
val drop : container -> unit
Drop the semaphores in this container, and delete the container.

This function is a no-op if the OS supports anonymous semaphores directly (because in this case the deletion of the container will automatically destroy the semaphores).


Note that there is a general problem when a container is deleted or dropped by a process while it is still being used by another one. This will generally not generate errors, but can cause a lot of confusion, because the processes will partly access the same semaphores, and partly different semaphores.
val unlink : prefix -> unit
Unlinks the identified container if it exists, and unlinks all possible named semaphores.

Semaphore functions.
val sem_init : container ->
Netsys_types.memory -> int -> bool -> int -> anon_semaphore
sem_init cont mem pos pshared init_value: Initializes the memory at position pos to pos + sem_size() - 1 as anonymous semaphore. If pshared the semaphore is shared between processes. init_value is the initial non-negative value (max is sem_value_max).
val sem_destroy : container -> anon_semaphore -> unit
Destroys the anonymous semaphore
val as_sem : container ->
Netsys_types.memory -> int -> anon_semaphore
as_sem mem pos: Interprets the memory at position pos to pos + sem_size() - 1 as anonymous semaphore. The memory region must already have been initialized.
val sem_getvalue : anon_semaphore -> int
Returns the value of the semaphore. If the value is bigger than what can be represented as int, an EINVAL error is returned.

The returned value is non-negative - if the underlying POSIX function reports a negative value zero is returned instead.

Unavailable on MacOS.

val sem_post : anon_semaphore -> unit
Unlocks the semaphore (increases the value by 1)
type sem_wait_behavior = Netsys_posix.sem_wait_behavior = 
| SEM_WAIT_BLOCK
| SEM_WAIT_NONBLOCK
val sem_wait : anon_semaphore -> sem_wait_behavior -> unit
Locks the semaphore (decreases the value by 1). If the semaphore value is already zero, and SEM_WAIT_BLOCK is given, the function waits until another process or thread posts. If SEM_WAIT_NONBLOCK the error EAGAIN is returned.

sem_wait may be interrupted by signals.

module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netnumber.html0000644000175000017500000012332612731530352020275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber sig
  type int4
  type int8
  type uint4
  type uint8
  type fp4
  type fp8
  exception Cannot_represent of string
  exception Out_of_range
  val mk_int4 : char * char * char * char -> Netnumber.int4
  val mk_int8 :
    char * char * char * char * char * char * char * char -> Netnumber.int8
  val mk_uint4 : char * char * char * char -> Netnumber.uint4
  val mk_uint8 :
    char * char * char * char * char * char * char * char -> Netnumber.uint8
  val dest_int4 : Netnumber.int4 -> char * char * char * char
  val dest_int8 :
    Netnumber.int8 -> char * char * char * char * char * char * char * char
  val dest_uint4 : Netnumber.uint4 -> char * char * char * char
  val dest_uint8 :
    Netnumber.uint8 -> char * char * char * char * char * char * char * char
  val mk_fp4 : char * char * char * char -> Netnumber.fp4
  val mk_fp8 :
    char * char * char * char * char * char * char * char -> Netnumber.fp8
  val dest_fp4 : Netnumber.fp4 -> char * char * char * char
  val dest_fp8 :
    Netnumber.fp8 -> char * char * char * char * char * char * char * char
  val int_of_int4 : Netnumber.int4 -> int
  val int_of_uint4 : Netnumber.uint4 -> int
  val int_of_int8 : Netnumber.int8 -> int
  val int_of_uint8 : Netnumber.uint8 -> int
  val int4_of_int : int -> Netnumber.int4
  val uint4_of_int : int -> Netnumber.uint4
  val int8_of_int : int -> Netnumber.int8
  val uint8_of_int : int -> Netnumber.uint8
  val int32_of_int4 : Netnumber.int4 -> int32
  val int32_of_uint4 : Netnumber.uint4 -> int32
  val int32_of_int8 : Netnumber.int8 -> int32
  val int32_of_uint8 : Netnumber.uint8 -> int32
  val int4_of_int32 : int32 -> Netnumber.int4
  val uint4_of_int32 : int32 -> Netnumber.uint4
  val int8_of_int32 : int32 -> Netnumber.int8
  val uint8_of_int32 : int32 -> Netnumber.uint8
  val int64_of_int4 : Netnumber.int4 -> int64
  val int64_of_uint4 : Netnumber.uint4 -> int64
  val int64_of_int8 : Netnumber.int8 -> int64
  val int64_of_uint8 : Netnumber.uint8 -> int64
  val int4_of_int64 : int64 -> Netnumber.int4
  val uint4_of_int64 : int64 -> Netnumber.uint4
  val int8_of_int64 : int64 -> Netnumber.int8
  val uint8_of_int64 : int64 -> Netnumber.uint8
  val logical_uint4_of_int32 : int32 -> Netnumber.uint4
  val logical_int32_of_uint4 : Netnumber.uint4 -> int32
  val logical_uint8_of_int64 : int64 -> Netnumber.uint8
  val logical_int64_of_uint8 : Netnumber.uint8 -> int64
  val fp8_of_fp4 : Netnumber.fp4 -> Netnumber.fp8
  val fp4_of_fp8 : Netnumber.fp8 -> Netnumber.fp4
  val float_of_fp4 : Netnumber.fp4 -> float
  val float_of_fp8 : Netnumber.fp8 -> float
  val fp4_of_float : float -> Netnumber.fp4
  val fp8_of_float : float -> Netnumber.fp8
  val lt_uint4 : Netnumber.uint4 -> Netnumber.uint4 -> bool
  val le_uint4 : Netnumber.uint4 -> Netnumber.uint4 -> bool
  val gt_uint4 : Netnumber.uint4 -> Netnumber.uint4 -> bool
  val ge_uint4 : Netnumber.uint4 -> Netnumber.uint4 -> bool
  val lt_uint8 : Netnumber.uint8 -> Netnumber.uint8 -> bool
  val le_uint8 : Netnumber.uint8 -> Netnumber.uint8 -> bool
  val gt_uint8 : Netnumber.uint8 -> Netnumber.uint8 -> bool
  val ge_uint8 : Netnumber.uint8 -> Netnumber.uint8 -> bool
  val min_int4 : Netnumber.int4
  val min_uint4 : Netnumber.uint4
  val min_int8 : Netnumber.int8
  val min_uint8 : Netnumber.uint8
  val max_int4 : Netnumber.int4
  val max_uint4 : Netnumber.uint4
  val max_int8 : Netnumber.int8
  val max_uint8 : Netnumber.uint8
  module type ENCDEC =
    sig
      val read_int4 : Bytes.t -> int -> Netnumber.int4
      val read_int8 : Bytes.t -> int -> Netnumber.int8
      val read_uint4 : Bytes.t -> int -> Netnumber.uint4
      val read_uint8 : Bytes.t -> int -> Netnumber.uint8
      val read_int4_unsafe : Bytes.t -> int -> Netnumber.int4
      val read_int8_unsafe : Bytes.t -> int -> Netnumber.int8
      val read_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4
      val read_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8
      val read_string_int4 : string -> int -> Netnumber.int4
      val read_string_int8 : string -> int -> Netnumber.int8
      val read_string_uint4 : string -> int -> Netnumber.uint4
      val read_string_uint8 : string -> int -> Netnumber.uint8
      val read_string_int4_unsafe : string -> int -> Netnumber.int4
      val read_string_int8_unsafe : string -> int -> Netnumber.int8
      val read_string_uint4_unsafe : string -> int -> Netnumber.uint4
      val read_string_uint8_unsafe : string -> int -> Netnumber.uint8
      val write_int4 : Bytes.t -> int -> Netnumber.int4 -> unit
      val write_int8 : Bytes.t -> int -> Netnumber.int8 -> unit
      val write_uint4 : Bytes.t -> int -> Netnumber.uint4 -> unit
      val write_uint8 : Bytes.t -> int -> Netnumber.uint8 -> unit
      val write_int4_unsafe : Bytes.t -> int -> Netnumber.int4 -> unit
      val write_int8_unsafe : Bytes.t -> int -> Netnumber.int8 -> unit
      val write_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4 -> unit
      val write_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8 -> unit
      val int4_as_bytes : Netnumber.int4 -> Bytes.t
      val int8_as_bytes : Netnumber.int8 -> Bytes.t
      val uint4_as_bytes : Netnumber.uint4 -> Bytes.t
      val uint8_as_bytes : Netnumber.uint8 -> Bytes.t
      val int4_as_string : Netnumber.int4 -> string
      val int8_as_string : Netnumber.int8 -> string
      val uint4_as_string : Netnumber.uint4 -> string
      val uint8_as_string : Netnumber.uint8 -> string
      val write_fp4 : Bytes.t -> int -> Netnumber.fp4 -> unit
      val write_fp8 : Bytes.t -> int -> Netnumber.fp8 -> unit
      val fp4_as_string : Netnumber.fp4 -> string
      val fp8_as_string : Netnumber.fp8 -> string
      val fp4_as_bytes : Netnumber.fp4 -> Bytes.t
      val fp8_as_bytes : Netnumber.fp8 -> Bytes.t
      val read_fp4 : Bytes.t -> int -> Netnumber.fp4
      val read_fp8 : Bytes.t -> int -> Netnumber.fp8
      val read_string_fp4 : string -> int -> Netnumber.fp4
      val read_string_fp8 : string -> int -> Netnumber.fp8
    end
  module BE : ENCDEC
  module LE : ENCDEC
  module HO : ENCDEC
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_oothr.mtprovider.html0000644000175000017500000004277412731530352023237 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr.mtprovider object
  method create_condition : unit -> Netsys_oothr.condition
  method create_mutex : unit -> Netsys_oothr.mutex
  method create_thread : ('-> 't) -> '-> Netsys_oothr.thread
  method self : Netsys_oothr.thread
  method single_threaded : bool
  method yield : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi.mime_argument.html0000644000175000017500000004115712731530352022400 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.mime_argument ?work_around_backslash_bug:bool ->
string -> Netmime.mime_message -> Netcgi.rw_cgi_argument
ocamlnet-4.1.2/doc/html-main/type_Netsys_gssapi.html0000644000175000017500000023677512731530352021206 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi sig
  type oid = int array
  type oid_set = Netsys_gssapi.oid list
  type token = string
  type interprocess_token = string
  type calling_error =
      [ `Bad_structure | `Inaccessible_read | `Inaccessible_write | `None ]
  type routine_error =
      [ `Bad_QOP
      | `Bad_bindings
      | `Bad_mech
      | `Bad_mic
      | `Bad_name
      | `Bad_nametype
      | `Bad_status
      | `Context_expired
      | `Credentials_expired
      | `Defective_credential
      | `Defective_token
      | `Duplicate_element
      | `Failure
      | `Name_not_mn
      | `No_context
      | `No_cred
      | `None
      | `Unauthorized
      | `Unavailable ]
  type suppl_status =
      [ `Continue_needed
      | `Duplicate_token
      | `Gap_token
      | `Old_token
      | `Unseq_token ]
  type major_status =
      Netsys_gssapi.calling_error * Netsys_gssapi.routine_error *
      Netsys_gssapi.suppl_status list
  type minor_status = int32
  type address =
      [ `Inet of Unix.inet_addr
      | `Local of string
      | `Nulladdr
      | `Other of int32 * string
      | `Unspecified of string ]
  type channel_bindings =
      Netsys_gssapi.address * Netsys_gssapi.address * string
  type cred_usage = [ `Accept | `Both | `Initiate ]
  type qop = int32
  type message = Netsys_types.mstring list
  type ret_flag =
      [ `Anon_flag
      | `Conf_flag
      | `Deleg_flag
      | `Integ_flag
      | `Mutual_flag
      | `Prot_ready_flag
      | `Replay_flag
      | `Sequence_flag
      | `Trans_flag ]
  type req_flag =
      [ `Anon_flag
      | `Conf_flag
      | `Deleg_flag
      | `Integ_flag
      | `Mutual_flag
      | `Replay_flag
      | `Sequence_flag ]
  type time = [ `Indefinite | `This of float ]
  class type ['credential, 'name, 'context] poly_gss_api =
    object
      method accept_sec_context :
        context:'context option ->
        acceptor_cred:'credential ->
        input_token:Netsys_gssapi.token ->
        chan_bindings:Netsys_gssapi.channel_bindings option ->
        out:(src_name:'name ->
             mech_type:Netsys_gssapi.oid ->
             output_context:'context option ->
             output_token:Netsys_gssapi.token ->
             ret_flags:Netsys_gssapi.ret_flag list ->
             time_rec:Netsys_gssapi.time ->
             delegated_cred:'credential ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method acquire_cred :
        desired_name:'name ->
        time_req:Netsys_gssapi.time ->
        desired_mechs:Netsys_gssapi.oid_set ->
        cred_usage:Netsys_gssapi.cred_usage ->
        out:(cred:'credential ->
             actual_mechs:Netsys_gssapi.oid_set ->
             time_rec:Netsys_gssapi.time ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method add_cred :
        input_cred:'credential ->
        desired_name:'name ->
        desired_mech:Netsys_gssapi.oid ->
        cred_usage:Netsys_gssapi.cred_usage ->
        initiator_time_req:Netsys_gssapi.time ->
        acceptor_time_req:Netsys_gssapi.time ->
        out:(output_cred:'credential ->
             actual_mechs:Netsys_gssapi.oid_set ->
             initiator_time_rec:Netsys_gssapi.time ->
             acceptor_time_rec:Netsys_gssapi.time ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method canonicalize_name :
        input_name:'name ->
        mech_type:Netsys_gssapi.oid ->
        out:(output_name:'name ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method compare_name :
        name1:'name ->
        name2:'name ->
        out:(name_equal:bool ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method context_time :
        context:'context ->
        out:(time_rec:Netsys_gssapi.time ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method delete_sec_context :
        context:'context ->
        out:(minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method display_minor_status :
        status_value:Netsys_gssapi.minor_status ->
        mech_type:Netsys_gssapi.oid ->
        out:(status_strings:string list ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method display_name :
        input_name:'name ->
        out:(output_name:string ->
             output_name_type:Netsys_gssapi.oid ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method duplicate_name :
        name:'name ->
        out:(dest_name:'name ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method export_name :
        name:'name ->
        out:(exported_name:string ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method export_sec_context :
        context:'context ->
        out:(interprocess_token:Netsys_gssapi.interprocess_token ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method get_mic :
        context:'context ->
        qop_req:Netsys_gssapi.qop ->
        message:Netsys_gssapi.message ->
        out:(msg_token:Netsys_gssapi.token ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method import_name :
        input_name:string ->
        input_name_type:Netsys_gssapi.oid ->
        out:(output_name:'name ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method import_sec_context :
        interprocess_token:Netsys_gssapi.interprocess_token ->
        out:(context:'context option ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method indicate_mechs :
        out:(mech_set:Netsys_gssapi.oid_set ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method init_sec_context :
        initiator_cred:'credential ->
        context:'context option ->
        target_name:'name ->
        mech_type:Netsys_gssapi.oid ->
        req_flags:Netsys_gssapi.req_flag list ->
        time_req:float option ->
        chan_bindings:Netsys_gssapi.channel_bindings option ->
        input_token:Netsys_gssapi.token option ->
        out:(actual_mech_type:Netsys_gssapi.oid ->
             output_context:'context option ->
             output_token:Netsys_gssapi.token ->
             ret_flags:Netsys_gssapi.ret_flag list ->
             time_rec:Netsys_gssapi.time ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method inquire_context :
        context:'context ->
        out:(src_name:'name ->
             targ_name:'name ->
             lifetime_req:Netsys_gssapi.time ->
             mech_type:Netsys_gssapi.oid ->
             ctx_flags:Netsys_gssapi.ret_flag list ->
             locally_initiated:bool ->
             is_open:bool ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method inquire_cred :
        cred:'credential ->
        out:(name:'name ->
             lifetime:Netsys_gssapi.time ->
             cred_usage:Netsys_gssapi.cred_usage ->
             mechanisms:Netsys_gssapi.oid_set ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method inquire_cred_by_mech :
        cred:'credential ->
        mech_type:Netsys_gssapi.oid ->
        out:(name:'name ->
             initiator_lifetime:Netsys_gssapi.time ->
             acceptor_lifetime:Netsys_gssapi.time ->
             cred_usage:Netsys_gssapi.cred_usage ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method inquire_mechs_for_name :
        name:'name ->
        out:(mech_types:Netsys_gssapi.oid_set ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method inquire_names_for_mech :
        mechanism:Netsys_gssapi.oid ->
        out:(name_types:Netsys_gssapi.oid_set ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method is_no_credential : 'credential -> bool
      method is_no_name : 'name -> bool
      method no_credential : 'credential
      method no_name : 'name
      method process_context_token :
        context:'context ->
        token:Netsys_gssapi.token ->
        out:(minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method provider : string
      method unwrap :
        context:'context ->
        input_message:Netsys_gssapi.message ->
        output_message_preferred_type:[ `Bytes | `Memory ] ->
        out:(output_message:Netsys_gssapi.message ->
             conf_state:bool ->
             qop_state:Netsys_gssapi.qop ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method verify_mic :
        context:'context ->
        message:Netsys_gssapi.message ->
        token:Netsys_gssapi.token ->
        out:(qop_state:Netsys_gssapi.qop ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method wrap :
        context:'context ->
        conf_req:bool ->
        qop_req:Netsys_gssapi.qop ->
        input_message:Netsys_gssapi.message ->
        output_message_preferred_type:[ `Bytes | `Memory ] ->
        out:(conf_state:bool ->
             output_message:Netsys_gssapi.message ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
      method wrap_size_limit :
        context:'context ->
        conf_req:bool ->
        qop_req:Netsys_gssapi.qop ->
        req_output_size:int ->
        out:(max_input_size:int ->
             minor_status:Netsys_gssapi.minor_status ->
             major_status:Netsys_gssapi.major_status -> unit -> 't) ->
        unit -> 't
    end
  module type GSSAPI =
    sig
      type credential
      type context
      type name
      exception Credential of Netsys_gssapi.GSSAPI.credential
      exception Context of Netsys_gssapi.GSSAPI.context
      exception Name of Netsys_gssapi.GSSAPI.name
      class type gss_api =
        [Netsys_gssapi.GSSAPI.credential, Netsys_gssapi.GSSAPI.name,
         Netsys_gssapi.GSSAPI.context]
        poly_gss_api
      val interface : Netsys_gssapi.GSSAPI.gss_api
    end
  val string_of_calling_error : Netsys_gssapi.calling_error -> string
  val string_of_routine_error : Netsys_gssapi.routine_error -> string
  val string_of_suppl_status : Netsys_gssapi.suppl_status -> string
  val string_of_major_status : Netsys_gssapi.major_status -> string
  val string_of_flag : Netsys_gssapi.ret_flag -> string
  val nt_hostbased_service : Netsys_gssapi.oid
  val nt_hostbased_service_alt : Netsys_gssapi.oid
  val nt_user_name : Netsys_gssapi.oid
  val nt_machine_uid_name : Netsys_gssapi.oid
  val nt_string_uid_name : Netsys_gssapi.oid
  val nt_anonymous : Netsys_gssapi.oid
  val nt_export_name : Netsys_gssapi.oid
  val nt_krb5_principal_name : Netsys_gssapi.oid
  val parse_hostbased_service : string -> string * string
  type support_level = [ `If_possible | `None | `Required ]
  class type client_config =
    object
      method flags :
        (Netsys_gssapi.req_flag * Netsys_gssapi.support_level) list
      method initiator_cred : exn option
      method initiator_name : (string * Netsys_gssapi.oid) option
      method integrity : Netsys_gssapi.support_level
      method mech_type : Netsys_gssapi.oid
      method privacy : Netsys_gssapi.support_level
      method target_name : (string * Netsys_gssapi.oid) option
    end
  val create_client_config :
    ?mech_type:Netsys_gssapi.oid ->
    ?initiator_name:string * Netsys_gssapi.oid ->
    ?initiator_cred:exn ->
    ?target_name:string * Netsys_gssapi.oid ->
    ?privacy:Netsys_gssapi.support_level ->
    ?integrity:Netsys_gssapi.support_level ->
    ?flags:(Netsys_gssapi.req_flag * Netsys_gssapi.support_level) list ->
    unit -> Netsys_gssapi.client_config
  class type client_props =
    object
      method flags : Netsys_gssapi.ret_flag list
      method mech_type : Netsys_gssapi.oid
      method time : Netsys_gssapi.time
    end
  val marshal_client_props : Netsys_gssapi.client_props -> string
  val unmarshal_client_props : string -> Netsys_gssapi.client_props
  class type server_config =
    object
      method acceptor_name : (string * Netsys_gssapi.oid) option
      method flags :
        (Netsys_gssapi.req_flag * Netsys_gssapi.support_level) list
      method integrity : Netsys_gssapi.support_level
      method mech_types : Netsys_gssapi.oid list
      method privacy : Netsys_gssapi.support_level
    end
  val create_server_config :
    ?mech_types:Netsys_gssapi.oid list ->
    ?acceptor_name:string * Netsys_gssapi.oid ->
    ?privacy:Netsys_gssapi.support_level ->
    ?integrity:Netsys_gssapi.support_level ->
    ?flags:(Netsys_gssapi.req_flag * Netsys_gssapi.support_level) list ->
    unit -> Netsys_gssapi.server_config
  class type server_props =
    object
      method deleg_credential : (exn * Netsys_gssapi.time) option
      method flags : Netsys_gssapi.ret_flag list
      method initiator_name : string * Netsys_gssapi.oid
      method initiator_name_exported : string
      method mech_type : Netsys_gssapi.oid
      method time : Netsys_gssapi.time
    end
  val marshal_server_props : Netsys_gssapi.server_props -> string
  val unmarshal_server_props : string -> Netsys_gssapi.server_props
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.logger_factory.html0000644000175000017500000004174012731530352024205 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.logger_factory object
  method create_logger :
    Netplex_types.config_file ->
    Netplex_types.address -> Netplex_types.controller -> Netplex_types.logger
  method name : string
end
ocamlnet-4.1.2/doc/html-main/type_Netgssapi_auth.Manage.html0000644000175000017500000004244012731530352022500 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_auth.Manage functor (G : Netsys_gssapi.GSSAPI->
  sig
    val delete_context : G.context option -> unit -> unit
    val format_status :
      ?fn:string ->
      ?minor_status:int32 -> Netsys_gssapi.major_status -> string
  end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.serializer_t.html0000644000175000017500000004151712731530352023127 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.serializer_t object
  method serialized :
    (Unixqueue.event_system -> 'Uq_engines.engine) -> 'Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/type_Netsmtp.client.html0000644000175000017500000004740612731530352021251 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsmtp.client Netchannels.in_obj_channel ->
Netchannels.out_obj_channel ->
object
  method auth :
    Netsys_sasl.sasl_mechanism ->
    string ->
    string ->
    Netsys_sasl.credentials -> (string * string * bool) list -> unit
  method authenticated : bool
  method close : unit -> unit
  method command : string -> int * string list
  method data : Netchannels.in_obj_channel -> unit
  method expn : string -> string list option
  method gssapi_props : Netsys_gssapi.client_props option
  method helo : ?host:string -> unit -> string list
  method helo_response : string list
  method help : unit -> string list
  method mail : string -> unit
  method noop : unit -> unit
  method quit : unit -> unit
  method rcpt : string -> unit
  method rset : unit -> unit
  method starttls :
    peer_name:string option -> Netsys_crypto_types.tls_config -> unit
  method tls_endpoint : Netsys_crypto_types.tls_endpoint option
  method tls_session_props : Nettls_support.tls_session_props option
end
ocamlnet-4.1.2/doc/html-main/type_Netx509.X509_DN_string.html0000644000175000017500000004063412731530352022125 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.X509_DN_string Netdn.DN_stringocamlnet-4.1.2/doc/html-main/Nethttp_client.put_call-c.html0000644000175000017500000004217412731530352022304 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.put_call

Class Nethttp_client.put_call

class put_call : http_call

ocamlnet-4.1.2/doc/html-main/Netmcore.Debug.html0000644000175000017500000004153712731530352020101 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore.Debug

Module Netmcore.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/Shell_fs.html0000644000175000017500000007172012731530352017034 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_fs

Module Shell_fs

module Shell_fs: sig .. end
Shell filesystem


This module emulates a filesystem by submitting shell commands. For example, a directory listing is retrieved via the ls utility instead of opening the directory directly. This also works when logging in to a remote machine, e.g. via ssh.

The following standard POSIX commands are used:

  • dd with options if, of, bs, skip, conv=notrunc, and optionally excl (the latter is a GNU extension)
  • test with options -d, -e, -f, -r, -s, -w, -x
  • ls with options -1, -n, -d, -a, -L
  • rm with options -r and -f
  • mv with option -f
  • ln with option -s
  • mkdir with options -p
  • rmdir
  • cp with option -p
In addition to this, the commands may be embedded in one-line shell scripts.

Filenames with leading minus chars are not supported.

Error reporting is less accurate than for a local filesystem.

Example. List a directory on a remote system:

      let fs = 
        Shell_fs.shell_fs 
          (Shell_fs.ssh_interpreter ~host:"moon" ())
      let files =
        fs # readdir [] "/this/is/a/directory/on/moon"
    

type command_context = {
   sfs_command : string; (*
The command line
*)
   sfs_stdin : Shell.producer; (*
stdin from here
*)
   sfs_stdout : Shell.consumer; (*
stdout goes here
*)
   sfs_stderr : Shell.consumer; (*
stderr goes here
*)
   mutable sfs_status : Unix.process_status option; (*
The exit code is put here
*)
}
type command_interpreter 
The interpreter runs the command, and fills in sfs_status
val local_interpreter : unit -> command_interpreter
Executes commands on the local machine
val cmd_interpreter : (command_context -> Shell_sys.command list) ->
command_interpreter
Creates a command interpreter from a function that creates the real command (as pipeline) to execute
val ssh_interpreter : ?options:string list ->
?user:string -> host:string -> unit -> command_interpreter
Executes commands via ssh on the machine host as user (defaults to current user). options are further command-line options. By default, only -o BatchMode yes is passed.
class type shell_stream_fs = object .. end
class shell_fs : ?encoding:Netconversion.encoding -> ?root:string -> ?dd_has_excl:bool -> ?tmp_directory:string -> ?tmp_prefix:string -> command_interpreter -> shell_stream_fs
val shell_fs : ?encoding:Netconversion.encoding ->
?root:string ->
?dd_has_excl:bool ->
?tmp_directory:string ->
?tmp_prefix:string ->
command_interpreter -> shell_stream_fs
The shell filesystem.

  • encoding: the assumed character encoding of the filenames. None by default.
  • root: the root of the file tree that is accessed. This can be an absolute path, or a relative path.
  • dd_has_excl: whether the dd command support "conv=excl". Default is false; this is a GNU extension.
  • tmp_directory and tmp_prefix are only meaningful for the write_file method which creates a temporary file. See Netchannels.make_temporary_file for more information.


Utility functions for developing other implementations of shell_stream_fs


val execute : command_interpreter -> command_context -> unit
Starts this command. It is not waited until the command is finished. One can either call wait for this, or one of the adapter functions below.

One can only start one command at a time.

val wait : command_interpreter -> unit
Waits until the running command is finished
val output_stream_adapter : ci:command_interpreter ->
close_in:(unit -> unit) ->
skip:int64 -> Shell.consumer * Netchannels.in_obj_channel
Arranges that the output of a shell command is made available as an in_obj_channel:

 let (c, ch) = output_stream_adapter ~ci ~close_in ~skip 

The consumer p can be used in a command_context for either sfs_stdout or sfs_stderr. The channel ch is an input channel, and when reading from it will return the bytes of stdout or stderr.

close_in is called as post-hook when the close_in method of ch is called.

skip bytes of stdout/stderr are skipped at the beginning of the stream.

val input_stream_adapter : ci:command_interpreter ->
close_out:(unit -> unit) -> Shell.producer * Netchannels.out_obj_channel
Arranges that the input of a shell command is made available as an out_obj_channel:

 let (p, ch) = input_stream_adapter ~ci ~close_in 

The producer p can be used in a command_context for sfs_stdin. The channel ch is an output channel, and bytes written to it will appear in stdin of the executed command.

close_out is called as post-hook when the close_out method of ch is called.

ocamlnet-4.1.2/doc/html-main/type_Neturl_tut.html0000644000175000017500000004061312731530352020500 0ustar gerdgerd Ocamlnet 4 Reference Manual : Neturl_tut sig  endocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.SHA256.html0000644000175000017500000004056612731530352023003 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SHA256 PROFILEocamlnet-4.1.2/doc/html-main/type_Netsys_sasl_types.SASL_MECHANISM.html0000644000175000017500000007142512731530352024220 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl_types.SASL_MECHANISM sig
  val mechanism_name : string
  val client_first : [ `No | `Optional | `Required ]
  val server_sends_final_data : bool
  val supports_authz : bool
  val available : unit -> bool
  type credentials
  val init_credentials :
    (string * string * (string * string) list) list ->
    Netsys_sasl_types.SASL_MECHANISM.credentials
  type server_session
  val server_state :
    Netsys_sasl_types.SASL_MECHANISM.server_session ->
    Netsys_sasl_types.server_state
  val create_server_session :
    lookup:(string ->
            string -> Netsys_sasl_types.SASL_MECHANISM.credentials option) ->
    params:(string * string * bool) list ->
    unit -> Netsys_sasl_types.SASL_MECHANISM.server_session
  val server_configure_channel_binding :
    Netsys_sasl_types.SASL_MECHANISM.server_session ->
    (string * string) list -> Netsys_sasl_types.SASL_MECHANISM.server_session
  val server_process_response :
    Netsys_sasl_types.SASL_MECHANISM.server_session ->
    string -> Netsys_sasl_types.SASL_MECHANISM.server_session
  val server_process_response_restart :
    Netsys_sasl_types.SASL_MECHANISM.server_session ->
    string -> bool -> Netsys_sasl_types.SASL_MECHANISM.server_session * bool
  val server_emit_challenge :
    Netsys_sasl_types.SASL_MECHANISM.server_session ->
    Netsys_sasl_types.SASL_MECHANISM.server_session * string
  val server_stash_session :
    Netsys_sasl_types.SASL_MECHANISM.server_session -> string
  val server_resume_session :
    lookup:(string ->
            string -> Netsys_sasl_types.SASL_MECHANISM.credentials option) ->
    string -> Netsys_sasl_types.SASL_MECHANISM.server_session
  val server_session_id :
    Netsys_sasl_types.SASL_MECHANISM.server_session -> string option
  val server_prop :
    Netsys_sasl_types.SASL_MECHANISM.server_session -> string -> string
  val server_user_name :
    Netsys_sasl_types.SASL_MECHANISM.server_session -> string
  val server_authz_name :
    Netsys_sasl_types.SASL_MECHANISM.server_session -> string
  val server_channel_binding :
    Netsys_sasl_types.SASL_MECHANISM.server_session -> Netsys_sasl_types.cb
  val server_gssapi_props :
    Netsys_sasl_types.SASL_MECHANISM.server_session ->
    Netsys_gssapi.server_props
  type client_session
  val client_state :
    Netsys_sasl_types.SASL_MECHANISM.client_session ->
    Netsys_sasl_types.client_state
  val create_client_session :
    user:string ->
    authz:string ->
    creds:Netsys_sasl_types.SASL_MECHANISM.credentials ->
    params:(string * string * bool) list ->
    unit -> Netsys_sasl_types.SASL_MECHANISM.client_session
  val client_configure_channel_binding :
    Netsys_sasl_types.SASL_MECHANISM.client_session ->
    Netsys_sasl_types.cb -> Netsys_sasl_types.SASL_MECHANISM.client_session
  val client_restart :
    Netsys_sasl_types.SASL_MECHANISM.client_session ->
    Netsys_sasl_types.SASL_MECHANISM.client_session
  val client_process_challenge :
    Netsys_sasl_types.SASL_MECHANISM.client_session ->
    string -> Netsys_sasl_types.SASL_MECHANISM.client_session
  val client_emit_response :
    Netsys_sasl_types.SASL_MECHANISM.client_session ->
    Netsys_sasl_types.SASL_MECHANISM.client_session * string
  val client_channel_binding :
    Netsys_sasl_types.SASL_MECHANISM.client_session -> Netsys_sasl_types.cb
  val client_user_name :
    Netsys_sasl_types.SASL_MECHANISM.client_session -> string
  val client_authz_name :
    Netsys_sasl_types.SASL_MECHANISM.client_session -> string
  val client_stash_session :
    Netsys_sasl_types.SASL_MECHANISM.client_session -> string
  val client_resume_session :
    string -> Netsys_sasl_types.SASL_MECHANISM.client_session
  val client_session_id :
    Netsys_sasl_types.SASL_MECHANISM.client_session -> string option
  val client_prop :
    Netsys_sasl_types.SASL_MECHANISM.client_session -> string -> string
  val client_gssapi_props :
    Netsys_sasl_types.SASL_MECHANISM.client_session ->
    Netsys_gssapi.client_props
end
ocamlnet-4.1.2/doc/html-main/Netnumber.HO.html0000644000175000017500000006436712731530352017552 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber.HO

Module Netnumber.HO

module HO: ENCDEC 
Encoders/decoders for host byte order - which is either little endian or big endian, depending on the CPU (or CPU mode)


Encode/decode numbers as strings. These functions exist in two flavors:
val read_int4 : Bytes.t -> int -> Netnumber.int4
val read_int8 : Bytes.t -> int -> Netnumber.int8
val read_uint4 : Bytes.t -> int -> Netnumber.uint4
val read_uint8 : Bytes.t -> int -> Netnumber.uint8
read_<t> create integer values from the characters found at a certain position in the string. Raises Out_of_range if the position is bad
val read_int4_unsafe : Bytes.t -> int -> Netnumber.int4
val read_int8_unsafe : Bytes.t -> int -> Netnumber.int8
val read_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4
val read_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8
Same, but no index check
val read_string_int4 : string -> int -> Netnumber.int4
val read_string_int8 : string -> int -> Netnumber.int8
val read_string_uint4 : string -> int -> Netnumber.uint4
val read_string_uint8 : string -> int -> Netnumber.uint8
val read_string_int4_unsafe : string -> int -> Netnumber.int4
val read_string_int8_unsafe : string -> int -> Netnumber.int8
val read_string_uint4_unsafe : string -> int -> Netnumber.uint4
val read_string_uint8_unsafe : string -> int -> Netnumber.uint8
For immutable strings
val write_int4 : Bytes.t -> int -> Netnumber.int4 -> unit
val write_int8 : Bytes.t -> int -> Netnumber.int8 -> unit
val write_uint4 : Bytes.t -> int -> Netnumber.uint4 -> unit
val write_uint8 : Bytes.t -> int -> Netnumber.uint8 -> unit
write_<t> copies the characters corresponding to the integer values into the string at the given positions. Raises Out_of_range if the position is bad.
val write_int4_unsafe : Bytes.t -> int -> Netnumber.int4 -> unit
val write_int8_unsafe : Bytes.t -> int -> Netnumber.int8 -> unit
val write_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4 -> unit
val write_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8 -> unit
write_<t>_unsafe: Same, but no index check.
val int4_as_bytes : Netnumber.int4 -> Bytes.t
val int8_as_bytes : Netnumber.int8 -> Bytes.t
val uint4_as_bytes : Netnumber.uint4 -> Bytes.t
val uint8_as_bytes : Netnumber.uint8 -> Bytes.t
<t>_as_bytes: Returns the corresponding bytes for an integer value
val int4_as_string : Netnumber.int4 -> string
val int8_as_string : Netnumber.int8 -> string
val uint4_as_string : Netnumber.uint4 -> string
val uint8_as_string : Netnumber.uint8 -> string
<t>_as_string: Returns the corresponding string for an integer value
val write_fp4 : Bytes.t -> int -> Netnumber.fp4 -> unit
val write_fp8 : Bytes.t -> int -> Netnumber.fp8 -> unit
val fp4_as_string : Netnumber.fp4 -> string
val fp8_as_string : Netnumber.fp8 -> string
val fp4_as_bytes : Netnumber.fp4 -> Bytes.t
val fp8_as_bytes : Netnumber.fp8 -> Bytes.t
val read_fp4 : Bytes.t -> int -> Netnumber.fp4
val read_fp8 : Bytes.t -> int -> Netnumber.fp8
val read_string_fp4 : string -> int -> Netnumber.fp4
val read_string_fp8 : string -> int -> Netnumber.fp8
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.Debug.html0000644000175000017500000004101212731530352023012 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netmime_header.html0000644000175000017500000004312112731530352021236 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime_header sig
  val get_content_length : #Netmime.mime_header_ro -> int
  val get_content_type :
    #Netmime.mime_header_ro ->
    string * (string * Netmime_string.s_param) list
  val get_content_disposition :
    #Netmime.mime_header_ro ->
    string * (string * Netmime_string.s_param) list
  val get_content_transfer_encoding : #Netmime.mime_header_ro -> string
end
ocamlnet-4.1.2/doc/html-main/Netplex_encap.TYPE.html0000644000175000017500000004212412731530352020636 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_encap.TYPE

Module type Netplex_encap.TYPE

module type TYPE = sig .. end
Just a (monomorphic) type t

type t 
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.auth_session.html0000644000175000017500000004274412731530352024031 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.auth_session object
  method auth_domain : Neturl.url list * int
  method auth_realm : string
  method auth_scheme : string
  method auth_session_id : string option
  method auth_user : string
  method authenticate :
    Nethttp_client.http_call ->
    bool -> (string * string) list Nethttp_client.auth_status
  method invalidate : Nethttp_client.http_call -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_sasl.Client.html0000644000175000017500000005214212731530352022057 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl.Client sig
  type session
  val create_session :
    mech:Netsys_sasl.sasl_mechanism ->
    user:string ->
    authz:string ->
    creds:Netsys_sasl.credentials ->
    params:(string * string * bool) list ->
    unit -> Netsys_sasl.Client.session
  val state : Netsys_sasl.Client.session -> Netsys_sasl_types.client_state
  val configure_channel_binding :
    Netsys_sasl.Client.session ->
    Netsys_sasl_types.cb -> Netsys_sasl.Client.session
  val restart : Netsys_sasl.Client.session -> Netsys_sasl.Client.session
  val process_challenge :
    Netsys_sasl.Client.session -> string -> Netsys_sasl.Client.session
  val emit_response :
    Netsys_sasl.Client.session -> Netsys_sasl.Client.session * string
  val channel_binding : Netsys_sasl.Client.session -> Netsys_sasl_types.cb
  val user_name : Netsys_sasl.Client.session -> string
  val authz_name : Netsys_sasl.Client.session -> string
  val stash_session : Netsys_sasl.Client.session -> string
  val resume_session :
    Netsys_sasl.sasl_mechanism -> string -> Netsys_sasl.Client.session
  val session_id : Netsys_sasl.Client.session -> string option
  val prop : Netsys_sasl.Client.session -> string -> string
  val gssapi_props : Netsys_sasl.Client.session -> Netsys_gssapi.client_props
end
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.TLS_CONFIG.html0000644000175000017500000004303612731530352023073 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_CONFIG

Module type Netsys_crypto_types.TLS_CONFIG

module type TLS_CONFIG = sig .. end

module TLS: Netsys_crypto_types.TLS_PROVIDER 
val config : TLS.config
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.http_engine.html0000644000175000017500000004226012731530352023755 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_engine ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) ->
on_request_header:(Nethttpd_engine.http_request_header_notification -> unit) ->
unit ->
#Nethttpd_engine.http_engine_config ->
Unix.file_descr -> Unixqueue.unix_event_system -> [unit] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.serializer_t.html0000644000175000017500000004157312731530352024474 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.serializer_t object
  method serialized :
    (Unixqueue.event_system -> 'Uq_engines_compat.engine) ->
    'Uq_engines_compat.engine
end
ocamlnet-4.1.2/doc/html-main/Netftp_fs.ftp_fs-c.html0000644000175000017500000005452712731530352020733 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_fs.ftp_fs

Class Netftp_fs.ftp_fs

class ftp_fs : ?config_client:Netftp_client.ftp_client -> unit -> ?tmp_directory:string -> ?tmp_prefix:string -> ?get_password:string -> string -> ?get_account:string -> string -> ?keep_open:bool -> ?tls_config:(module Netsys_crypto_types.TLS_CONFIG) -> ?tls_enabled:bool -> ?tls_required:bool -> ?gssapi_provider:(module Netsys_gssapi.GSSAPI) -> ?gssapi_config:Netsys_gssapi.client_config -> ?gssapi_required:bool -> string -> ftp_stream_fs
ftp_fs base_url: Access the FTP file system rooted at base_url.

The base_url must follow the ftp://user@host:port/path scheme. Passwords in base_url are ignored.

The following access methods are supported (compare with Netfs.stream_fs). Note that not all FTP servers can perform all operations:

  • path_encoding: If the FTP server announces that it uses UTF-8 as path encoding, this is returned here; else None.
  • path_exclusions: is just 0,0; 47,47
  • nominal_dot_dot is true. "." and ".." are resolved by the client before sending paths to the server.
  • read: is supported. Note that FTP distinguishes between text and binary mode, so don't forget to pass the `Binary flag if needed. The `Skip flag is only emulated - the full file is retrieved first, and only the first bytes are hidden from the user. There is no support for streaming mode; the `Streaming flag is ignored. This means that the file is first downloaded to a temporary file, and the returned object is just a handle for this file.
  • write: is supported, but - depending on the server - not all flag combinations. The flag list [`Create; `Truncate] should always work. For other flag lists, the server needs to support the MLST command for checking whether the file already exists. If this support is missing, an FTP error is raised. It is not supported to omit both `Create and `Truncate. Also, the `Exclusive flag is not supported. As for read, there is no streaming mode, and a temporary file is used as container.
  • size: works only if the server supports the SIZE command (otherwise ENOSYS).
  • test and test_list: works only if the server supports the MLST command (otherwise ENOSYS). The tests `N, `E, `D, `F, `S, `R, `W, and `X should work. Files are never recognized as symlinks.
  • remove: works, but the `Recursive flag is not supported (and an emulation is considered as too dangerous)
  • readdir: works
  • rename: works
  • mkdir: works, but the flags are ignored
  • rmdir: works
There is no support for symlink, readlink, and copy.

Options:

  • config_client: one can enable further features on the client object (e.g. proxies)
  • tmp_directory: directory for temporary files
  • tmp_prefix: file prefix for temporary files (w/o directory)
  • get_password: This function should return the password for the user (passed in as argument). Defaults to "".
  • get_account: This function should return the account name for the user (passed in as argument). Defaults to "".
  • keep_open: By default, a new FTP connection is started for each operation, and it is shut down afterward. By setting keep_open the connection is kept open. The user has to call close when done.
  • tls_config: The TLS configuration to use. (If not set, a reasonable default is used.)
  • tls_enabled: whether TLS is enabled
  • tls_required: whether TLS is required
  • gssapi_provider: The GSSAPI provider to use, e.g. Netgss.System. Note that there is no default, and GSSAPI remains disabled if this option is not set.
  • gssapi_config: the client configuration (with a reasonable default)
  • gssapi_required: whether GSSAPI is required


ocamlnet-4.1.2/doc/html-main/Netcgi_apache.html0000644000175000017500000005733212731530352020012 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache

Module Netcgi_apache

module Netcgi_apache: sig .. end
Netcgi Apache "mod" connector.

See the Netcgi_mod.setup section at the end of this file to know how to configure Apache.


module Apache: sig .. end
Interface to Apache API.
module Handler: sig .. end
Registering Apache handlers.
class type cgi = object .. end
The usual cgi class with an additional method to access Apache specificities.
val run : ?config:Netcgi.config ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?exn_handler:Netcgi.exn_handler -> (cgi -> unit) -> unit
run f register the function f as a main function of the script. Each call to the script will execute f cgi. The code outside f will be executed only once (when the script is loaded into memory) which allows to cache database connections, etc. (The code stays in memory unless you restart the server or the file changes on disk.)
config : Default: Netcgi.default_config
output_type : Default: `Direct ""
arg_store : Default: `Automatic for all arguments.
exn_handler : See Netcgi.exn_handler. Default: delegate all exceptions to the default handler.

Setup

Apache 1.3

You need to put in an Apache configuration file (we recommend /etc/apache/conf.d/netcgi_apache.conf) the following lines:

    LoadModule netcgi_module /usr/lib/apache/1.3/mod_netcgi_apache.so
    NetcgiRequire netcgi2-apache
   

Apache 2.2 or later

You need to put in an Apache configuration file (we recommend /etc/apache2/mods-available/netcgi_apache.load) the following line:

    LoadModule netcgi_module /usr/lib/apache2/modules/mod_netcgi_apache.so
    NetcgiRequire netcgi2-apache
   
and make a symbolic link from /etc/apache2/mods-enabled/ to it to actually enable it. Subsequent configuration is recommended to be in /etc/apache2/mods-available/netcgi_apache.conf (also to be linked to /etc/apache2/mods-enabled/).

Loading libraries

If your scripts depend on other libraries, you need to load them using NetcgiLoad. More specifically, if your library is x.cma and is in the subdirectory y of standard OCaml directory (given by `ocamlc -where`), use

    NetcgiLoad y/x.cma
   
If x.cma is not in a subdirectory of `ocamlc -where`, you need to specify the full path.

Interaction with findlib

Libraries managed with findlib are specially supported. In order to load a library "lib" just use

    NetcgiRequire lib
   
Findlib-managed libraries are automatically found.

For special configurations one can also set Findlib predicates:

    NetcgiPredicates p1,p2,p3,...
   

Multi-threading

If you need multi-threading call

    NetcgiThread
   
as the very first directive after LoadModule, even before NetcgiRequire netcgi2-apache (otherwise a number of critical sections remain unprotected in Ocamlnet, and you'll experience crashes).

Installing scripts

You need also to tell Apache how to detect whether a script is to be handled by netcgi_apache, either by putting them in a special directory (here /caml-bin/):

    Alias /caml-bin/ /path/to/your/scripts/
    <Location /caml-bin>
      SetHandler ocaml-bytecode
      NetcgiHandler Netcgi_apache.bytecode
      Options ExecCGI
      Allow from all
    </Location>
   
or by distinguishing them by their extension (here .cma):
    NetcgiHandler Netcgi_apache.bytecode
    AddHandler ocaml-bytecode .cma
   

Compiling scripts

If your script reside in the file x.ml, compile it to x.cmo or x.cma. If your script depends on other libraries, you may either load them with NetcgiLoad (see above) or include them in x.cma. You need not include the netcgi_apache.cma, netcgi.cma, netstring.cma, netsys.cma, or pcre.cma modules as these are already loaded into Apache (see above).
ocamlnet-4.1.2/doc/html-main/type_Netfs.local_file.html0000644000175000017500000004112312731530352021477 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netfs.local_file object method close : unit -> unit method filename : string endocamlnet-4.1.2/doc/html-main/Netplex_intro.html0000644000175000017500000016664512731530352020142 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_intro

Netplex_intro


Introduction into Netplex

Contents

Netplex is a generic (stream) server framework. This means, Netplex does a lot of things for a network service that are always the same, regardless of the kind of service:

  • Creation of server sockets
  • Accepting new network connections
  • Organizing multiple threads of execution - either by multiple processes, multiple POSIX threads, or multiplexing
  • Workload management
  • Writing log files
  • Broadcasting messages to all server components
  • Support for a configuration file format
Netplex currently only supports stream sockets (TCP or Unix Domain).

Ocamlnet already includes Netplex adapters for Nethttpd (the HTTP daemon), and RPC servers. It is likely that more adapters for other network protocols will follow.

Netplex can bundle several network services into a single system of components. For example, you could have an RPC service that can be managed over a web interface provided by Nethttpd. Actually, Netplex focuses on such systems of interconnected components. RPC plays a special role in such systems because this is the network protocol the components use to talk to each other. It is also internally used by Netplex for its administrative tasks.

Terminology

In the Netplex world the following words are preferred to refer to the parts of a Netplex system:

  • The Netplex controller is the core component of Netplex. The controller opens sockets and manages how new connections are accepted. For every socket, the controller determines which Netplex container will accept the next connection that is tried to be established. Furthermore, the controller manages the startup and shutdown of the Netplex system.
  • The Netplex services are the user-defined components of a Netplex system. Every service runs in its own process(es) (if multi-processing is selected) or in its own thread(s) (for POSIX multi-threading). It is up to the user to define what a service is.
  • The Netplex protocols are the languages spoken by the services. A protocol is bound to one or more sockets. This means that a service is implemented by a number of protocols.
  • The Netplex containers are processes or threads that may execute a certain service. Every container is bound to a specific service. It is possible that only one container is used for a particular service, but one can also configure that containers are dynamically started and stopped as the workload of the system changes.

Example - A Simple Web Server

In order to create a web server, this main program and the following configuration file are sufficient. (You find an extended example in the "examples/nethttpd" directory of the Ocamlnet tarball.)

let main() =
  (* Create a parser for the standard Netplex command-line arguments: *)
  let (opt_list, cmdline_cfg) = Netplex_main.args() in

  (* Parse the command-line arguments: *)
  Arg.parse
    opt_list
    (fun s -> raise (Arg.Bad ("Don't know what to do with: " ^ s)))
    "usage: netplex [options]";

  (* Select multi-processing: *)
  let parallelizer = Netplex_mp.mp() in  

  (* Start the Netplex system: *)
  Netplex_main.startup
    parallelizer
    Netplex_log.logger_factories
    Netplex_workload.workload_manager_factories
    [ Nethttpd_plex.nethttpd_factory() ]
    cmdline_cfg
;;

Sys.set_signal Sys.sigpipe Sys.Signal_ignore;
main();;

The configuration file:

netplex {
  controller {
    max_level = "debug";    (* Log level *)
    logging {
      type = "stderr";      (* Log to stderr *)
    }
  };
  service {
    name = "My HTTP file service";
    protocol {
      (* This section creates the socket *)
      name = "http";
      address {
        type = "internet";
        bind = "0.0.0.0:80";  (* Port 80 on all interfaces *)
      };
    };
    processor {
      (* This section specifies how to process data of the socket *)
      type = "nethttpd";
      host {
        (* Think of Apache's "virtual hosts" *)
        pref_name = "localhost";
        pref_port = 80;
        names = "*:0";   (* Which requests are matched here: all *)
        uri {
          path = "/";
          service {
            type = "file";
            docroot = "/usr";
            media_types_file = "/etc/mime.types";
            enable_listings = true;
          }
        };
      };
    };
    workload_manager {
      type = "dynamic";
      max_jobs_per_thread = 1;  (* Everything else is senseless *)
      min_free_jobs_capacity = 1;
      max_free_jobs_capacity = 1;
      max_threads = 20;
    };
  }
}

As you can see, the main program is extremely simple. Netplex includes support for command-line parsing, and the rest deals with the question which Netplex modules are made accessible for the configuration file. Note that detailed information about the config file is available in the Netplex Administration Guide.

Here, we have:

The configuration file consists of nested sections whose extents are denoted by curly braces. The sections are partly defined by Netplex itself (e.g. the controller section and the workload manager section), and partly by the service provider (almost everything inside "processor"). That means that the components of a Netplex system pick "their" part from the configuration file, and that, depending on which components are linked into this system, the config files may look very different.

Here, we have:

  • The controller section sets the log level and the logging method. The latter is done by naming one of the logger factories as logging type. If the factory needs more parameters to create the logger, these can be set inside the logging section.
  • For every service there is a name (can be freely chosen), one or several protocols, a processor, and a workload_manager. The protocol section declare which protocols are available and to which sockets they are bound. Here, the "http" protocol (name can again be freely chosen) is reachable over TCP port 80 on all network interfaces. By having multiple address sections, one can bind the same protocol to multiple sockets.
  • The processor section specifies the type and optionally a lot of parameters (which may be structured into several sections). By setting type to "nethttpd" we select the Nethttpd_plex.nethttpd_factory to create the processor (because "nethttpd" is the default name for this factory). This factory now interprets the other parameters of the processor section. Here, a static HTTP server is defined that uses /usr as document root.
  • Finally, the workload_manager section says how to deal with parallely arriving requests. The type selects the dynamic workload manager which is configured by the other parameters. Roughly said, one container (i.e. process) is created in advance for the next network connection ("pre-fork"), and the upper limit of containers is 20.

Running This Example

If you start this program without any arguments, it will immediately fail because it wants to open /etc/netplex.conf - this is the default name for the configuration file. Use -conf to pass the real name of the above file.

Netplex creates a directory for its internal processing, and this is by default /tmp/netplex-<id> (where id is a hex sequence derived from the file location of the configuration). You can change this directory by setting the socket_directory parameter in the controller section. In this directory, you can find:

  • A directory netplex.controller which refers to the controller component.
  • For every service another directory containing local run-time files. The directory has the same name as the service.
Netplex comes with a generic administration command called netplex-admin. You can use it to send control messages to Netplex systems. For example,

 netplex-admin -list 

outputs the list of services. A more detailed list can be obtained with

 netplex-admin -containers 

The command

 netplex-admin -shutdown 

shuts the system (gracefully) down. It is also possible to broadcast messages to all components:

 netplex-admin name arg1 arg2 ... 

It is up to the components to interpret these messages.

The Process Model

Netplex uses a generalized pre-fork process model. Let me explain this model a bit, as it is important to know it in order to understand Netplex fully.

The most trivial form of a multi-process Unix server is the post-fork model. Although it is not used by Netplex, it is the model explained in many books, and it is what many people think a Unix server has to look like. Actually, the post-fork model has lots of limitations, and is not suited for high-performance servers.

In the post-fork model, the master process accepts new network connections in an endless loop, and whenever a new connection is established, a sub process (container process) is spawned that processes the network traffic. There is a serious logical limitation, and a performance limitation:

  • In the post-fork model every container process can only deal with one connection at a time. The reason is that at the time of spawning the container there is only one connection, and one cannot assign the container another connection later.
  • The post-fork model spawns the container processes at a bad moment. Spawning is a very expensive operation, and doing it just after connection establishment is bad because this means that the client has to wait longer for a response. Furthermore, spawning for every connection wastes system resources.
In the pre-fork model, these disadvantages can be avoided. Here, one or several processes are spawned in advance. Furthermore, these processes cannot only manage one connection but any number, and this can happen sequentially (one connection is processed after the other) or in parallel (using multiplexing).

This is achieved by letting the containers themselves accept the new connections instead of the master process. In the Unix process model it is possible that server sockets are shared by several processes, and every container is allowed to accept the next connection. However, the containers should cooperate, and avoid that several containers call Unix.accept at the same time (as this leads to performance problems when a container must be able to watch several ports for new connections - a problem we do not discuss here). There are many ways to organize such cooperation, and for simplicity, Netplex implements this by exchanging RPC messages with the master process, the controller. Effectively, the controller has the task of scheduling which of the containers accepts the next arriving network connection.

What actually happens is the following. We assume here that we have a number of idle container processes that could accept the next connection.

  • The controller selects one of the containers as the one that will get the next connection.
  • The selected container watches the ports for incoming connections. Note that this is done in a Unixqueue, so that if there are already connections to be processed, this can be done in a multiplexed way in parallel with watching for new connections.
  • When the next connection arrives, the container accepts it, and invokes the service component to process it.
  • Immediately after connection establishment, the container tells the controller what happened, so the controller can watch out for another container to take over the role of accepting further connections.
  • When the connection is fully processed, another control message is sent to the controller because the controller must know at all times how many connections are being processed by which containers. This is simply an important load parameter.
The details of this mechanism are not very interesting for using it. However, one must know that

  • connections are accepted by the sub processes and not by the master process,
  • the sub processes can accept as many connections as they want to, either one after the other, or even several at once,
  • the controller schedules tasks and determines which connection is accepted by which container,
  • there is a certain protocol between controller and container, and although the details are hidden from the user, this has consequences for the user interface. In particular, the reason why the when_done function must be called upon connection termination is that a control message must be sent to the controller.
Another implication of the pre-fork model is that one needs workload management. As processes are created in advance, the question arises how many are created, and when the processes are terminated to free resources. Netplex comes with two workload managers: One manager simply creates a fixed number of processes which are never terminated, and the other manager tries to adapt the number to the load by dynamically starting and stopping processes. This is discussed below in detail.

Creating Sockets

The server sockets are always created by the controller at program startup. This is a strict requirement because only this ensures that the created container processes share the same sockets.

The sockets are descibed in the protocol section of the configuration file. For an Internet socket this section looks like

    protocol {
      name = "<name>";
      address {
        type = "internet";
        bind = "<address>:<port>";
      };
    };

The <name> is only important when there are several protocols in order to distinguish between them. The <address> can be:

  • An IP address of a network interface to bind the socket to this particular interface. Both IPv4 and IPv6 addresses are supported. IPv4 addresses are simply given in "dotted quad" notation (e.g. 192.168.76.23), and IPv6 addresses must be enclosed in brackets (e.g. [fe80::250:56ff:fec0:1]).
  • The special IPv4 address 0.0.0.0 to bind the socket to all IPv4 network interfaces, or the special IPv6 address [::0] to bind it to all IPv6 network interfaces.
  • A resolvable host name which is the same as using the corresponding IP address.
The <port> must be the port number or 0 to use an anonymous port.

For a local (Unix domain) socket, the protocol section looks like

    protocol {
      name = "<name>";
      address {
        type = "local";
        path = "<path>";
      };
    };

where the <path> is the filename of the socket.

One can have several address sections to create several sockets for the same protocol.

For detailed documentation, see The protocol subsection.

Services And Processors

A Netplex system consists of exactly the services that are enumerated in the config file. This means it is not sufficient to build in support for a service into the program, one must also activate it in the config file. This gives the end user of the program a lot of flexibility when running the system: By simply changing the config file one can enable or disable services. It is also possible to run the same program binary several times with different config files.

The services are implemented by processors, which are user-defined objects that handle the network connection after it is accepted by the component. The processor section of the service selects the processor by name, and optionally passes configuration parameters to it:

    processor {
        type = "<name>";
        ... further parameters allowed ...
    }

The mentioned name of the processor type is used to find the so-called factory for the processor (an object with a create_processor method). All factories must be available at Netplex startup so the library knows which factories exist when the config file is interpreted (the factories are an argument of Netplex_main.startup).

Processor objects are somewhat strange in so far as they exist both in the controller and in the container processes. In particular, these objects are created by the controller, and they are duplicated once for all container processes when these are actually created.

The processor objects (of type Netplex_types.processor) consist of a number of methods. We have already seen one of them, process, which is called in the container process when a new connection is accepted. The other methods are called at other points of interest (see Netplex_types.processor_hooks for more details):

Methods called on the controller instance of the processor

  • post_add_hook is immediately called after the addtion of the service to the controller.
  • post_rm_hook is immediately called after the removal of the service from the controller.
  • pre_start_hook is called just before the next container process is spawned.
  • post_finish_hook is called after termination of the container.
Methods called on the container instance of the processor

  • post_start_hook is called just after the container process has been created, but now for the copy of the processor object that lives in the container process. This is a very useful hook method, because one can initialize the container process (e.g. prepare database accesses etc.).
  • pre_finish_hook is called just before the container process will (regularly) terminated.
  • receive_message is called when a message from another container arrives.
  • receive_admin_message is called when a message from the administrator arrives.
  • shutdown is called when the shutdown notification arrives. The shutdown will lead to the termination of the process when all network connections managed by Unixqueue are finished. This method must terminate such connections if they have been created in addition to those Netplex manages. The shutdown notification is generated whenever a container needs to be stopped, for example when it has been idle for too long and is probably not needed right now (workload-induced shutdown), or when the whole system is stopped (administrative shutdown).
  • system_shutdown is another shutdown-related notification. It is only emitted if the whole Netplex system is going to be stopped. In this case, all containers first receive the system_shutdown notifications, so they can prepare the real shutdown that will happen soon. At the time the system_shutdown is emitted, the whole system is still up and running, and so every action is still possible. Only after all containers have finished their system_shutdown callbacks, the real shutdown begins, i.e. shutdown notifications are sent out.
  • global_exception_handler is called for exceptions falling through to the container, and is the last chance to catch them.
Because of the instances in the controller and the containers it is usually a bad idea to store state in the processor object.

If multi-threading is used instead of multi-processing, there is only one instance of the processor that is used in the controller and all containers.

Defining Custom Processors

Using predefined processor factories like Nethttpd_plex.nethttpd_factory is very easy. Fortunately, it is not very complicated to define a custom adapter that makes an arbitrary network service available as Netplex processor.

In principle, you must define a class for the type Netplex_types.processor and the corresponding factory implementing the type Netplex_types.processor_factory. To do the first, simply inherit from Netplex_kit.processor_base and override the methods that should do something instead of nothing. For example, to define a service that outputs the line "Hello world" on the TCP connection, define:

 
class hello_world_processor : processor =
  let empty_hooks = new Netplex_kit.empty_processor_hooks() in
object(self)
  inherit Netplex_kit.processor_base empty_hooks

  method process ~when_done container fd proto_name =
    Unix.clear_nonblock fd;
    let ch = Unix.out_channel_of_descr fd in
    output_string ch "Hello world\n";
    close_out ch;
    when_done()

  method supported_ptypes = [ `Multi_processing; `Multi_threading ]
end

The method process is called whenever a new connection is made. The container is the object representing the container where the execution happens (process is always called from the container). In fd the file descriptor is passed that is the (already accepted) connection. In proto_name the protocol name is passed - here it is unused, but it is possible to process the connection in a way that depends on the name of the protocol.

Note that the file descriptors created by Netplex are in non-blocking mode. It is, however, possible to switch to blocking mode when this is more appropriate (Unix.clear_nonblock).

The argument when_done is very important. It must be called by process! For a synchronous processor like this one it is simply called before process returns to the caller.

For an asynchronous processor (i.e. a processor that handles several connections in parallel in the same process/thread), when_done must be called when the connection is fully processed. This may be at any time in the future.

The class hello_world_processor can now be turned into a factory:

class hello_world_factory : processor_factory =
object(self) 
  method name = "hello_world"
  method create_processor ctrl_cfg cfg_file cfg_addr =
    new hello_world_processor
end

As you see, one can simply choose a name. This is the type of the processor section in the configuration file, i.e. you need

  ...
  service {
    name = "hello world sample";
    ...
    processor {
      type = "hello_world"
    };
    ...
  }
  ...

to activate this factory for a certain service definition. Of course, the instantiated hello_world_factory must also be passed to Netplex_main.startup in order to be available at runtime.

The create_processor method simply creates an object of your class. The argument ctrl_cfg is the configuration of the controller (e.g. you find there the name of the socket directory). In cfg_file the object is passed that accesses the configuration file as tree of parameters. In cfg_addr the address of the processor section is made available, so you can look for additional configuration parameters.

You may wonder why it is necessary to first create empty_hooks. The hook methods are often overridden by the user of processor classes. In order to simplify this, it is common to allow the user to pass a hook object to the processor object:

 
class hello_world_processor hooks : processor =
object(self)
  inherit Netplex_kit.processor_base hooks

  method process ~when_done container fd proto_name = ...
  method supported_ptypes = ...
end

Now, the user can simply define hooks as in

class my_hooks =
object(self)
  inherit Netplex_kit.empty_processor_hooks()

  method post_start_hook container = ...
end

and pass such a hook object into the factory.

Workload Management

Workload managers decide when to start new containers and when to stop useless ones. The simplest manager is created by the Netplex_workload.constant_workload_manager_factory. The user simply defines how many containers are to be started. In the config file this is written as

    workload_manager {
        type = "constant";
        threads = <n>;
    }

where <n> is the number of containers > 0. Often this manager is used to achieve n=1, i.e. to have exactly one container. An example would be a stateful RPC server where it is important that all network connections are handled by the same process. (N.B. n=1 for RPC servers does not enforce that the connections are serialized because Ocamlnet RPC servers can handle multiple connections in parallel, but of course it is enforced that the remote procedures are invoked in a strictly sequential way.)

If n>1, it is tried to achieve that all containers get approximately the same load.

If processes die unexpectedly, the constant workload manager starts new components until the configured number of processes is again reached.

The dynamic workload manager (created by Netplex_workload.dynamic_workload_manager_factory) is able to start and stop containers dynamically. There are a few parameters that control the manager. A "thread" is here another word for a started container. A "job" is an established network connection. Using this terms, the task of the workload manager is to decide how many threads are needed to do a varying number of jobs. The parameters now set how many jobs every thread may execute, and how quickly new threads are created or destroyed to adapt the available thread capacity to the current job load.

If the service processor can only accept one network connection after the other (like Nethttpd_plex), the only reasonable setting is that there is at most one job per thread. If one configures a higher number in this case, unaccepted network connections will queue up resulting in poor performance.

If the service processor can handle several connections in parallel it is possible to allow more than one job per thread. There is no general rule how many jobs per thread are reasonable, one has to experiment to find it out. In this mode of having more than one job per thread, Netplex even allows two service qualities, "normal" and "overload". If possible, Netplex tries to achieve that all containers deliver normal quality, but if the load goes beyond that, it is allowed that containers accept more connections than that. This is called an overload situation. Often it is better to allow overload than to refuse new connections.

The dynamic workload manager is enabled by the section

    workload_manager {
        type = "dynamic";
	... parameters, see below ...
    }

The required parameters are:

  • max_threads: How many containers can be created at maximum for this service.
  • max_jobs_per_thread: How many jobs every container can execute at maximum. The upper limit for the number of jobs is thus max_threads * max_jobs_per_thread.
  • min_free_job_capacity: This parameter controls how quickly new containers are started when the load goes up. It is tried to ensure that there are as many containers so this number of jobs can be additionally performed. This parameter must be at least 1.
  • max_free_job_capacity: This parameter controls how quickly containers are stopped when the load goes down. It is tried to ensure that unused containers are stopped so the capacity for additional jobs is not higher than this parameter. This parameter must be greater or equal than min_free_job_capacity.
In order to configure the overload mode:

  • recommended_jobs_per_thread: The number of jobs a container can do with normal service quality. A higher number is considered as overload.
The effect of this parameter is that it is avoided that a container gets more jobs than recommended as long as possible.

Another parameter is:

  • inactivity_timeout: If a container idles longer than this number of seconds and is not needed to ensure min_free_job_capacity it is shut down. Defaults to 15 seconds.
More documentation is available in Configuration: The workload_manager section.

Messaging

There are two kinds of messages one can send to Netplex containers: normal messages come from another Netplex container, and admin messages are sent using the netplex-admin command.

Messages have a name and a (possibly empty) list of string parameters. They can be sent to an individual receiver container, or to a number of containers, even to all. The sender does not get an acknowledgment when the messages are delivered.

Messages can e.g. be used

  • to signal that internal state is output to log files in order to debug a special situation
  • to enable or disable special features of the running system
  • to flush caches
and for other comparably simple communication needs.

In order to receive a normal message, one must define the receive_message method in the processor object, and to receive an admin message, one must define the receive_admin_message method.

A normal message is sent by the container method send_message. The receiver is identified by the service name, i.e. all containers with the passed name get the message. The name may even contain the wildcard * to select the containers by a name pattern.

An admin message is sent using the netplex-admin command.

There are a few predefined messages understood by all containers. See The netplex-admin command for a list.

In general, messages starting with "netplex." are reserved for Netplex itself.

Logging

Log messages can be written in the containers. The messages are first sent to the controller where they are written to stderr, to files, or to any object of the type Netplex_types.logger. That the messages are first sent to the controller has a lot of advantages: The messages are implicitly serialized, no locking is needed, and it is easy to support log file rotation.

In order to write a log message, one needs the container object. The module Netplex_cenv always knows the container object of the caller, to get it:

let cont = Netplex_cenv.self_cont()

If you call self_conf outside a container, the exception Netplex_cenv.Not_in_container_thread is raised. This is e.g. the case if you call it from the pre_start or post_finish callbacks.

Logging is now done by

let cont = Netplex_cenv.self_cont() in
cont # log level message

where level is one of `Debug, `Info, `Notice, `Warning, `Err, `Crit, `Alert, `Emerg, and message is a string. The levels are the same as for syslog.

You can also call Netplex_cenv.log and Netplex_cenv.logf, which simply use self_cont to get the container and call its log method to write the message.

The config file controls what to do with the log messages. The easiest way is to send all messages to stderr:

  controller {
    max_level = "debug";    (* Log level *)
    logging {
      type = "stderr";      (* Log to stderr *)
    }
  };

Further types of logging are documented in Configuration: The controller section.

Debug logging

There are various built-in debug logging streams:

  • Netplex_container.Debug.enable: Logs the perspective of the container. Logged events are e.g. when connections are accepted, and when user-defined hook functions are invoked. These messages are quite interesting for debugging user programs.
  • Netplex_controller.Debug.enable: Logs the perspective of the controller. The events are e.g. state changes, when containers are started, and scheduling decisions. This is less interesting to users, but might nevertheless worth activating it.
  • Netplex_workload.Debug.enable: Outputs messages from the workload manager.
For these messages, the mechanism of Netlog.Debug is used - which has the advantage that messages can also be generated when no Netplex logger is available.

Compatibility with multi-threading

As already noted above, it is possible to use Netplex with two concurrency models, namely multi-threading and multi-processing. In the first case, for every container a new thread is started, and in the second case, a new process.

You should know that multi-threading in OCaml has some limitations. In particular, it is not possible to exploit more than one CPU core of the system (although the threads are real kernel threads). Because of this, multi-processing is also supported by Netplex. It does not have this deficiency, because every process executes an independent OCaml runtime.

Nevertheless, it can be quite useful to just start helper threads, even if the main concurrency model is multi-processing. The question is how to do, and where the traps are.

First, one warning ahead: Once you have started threads, it is no longer safe to spawn new processes. This is a general difficulty of the POSIX system API, and cannot be worked around in OCaml programs (to some extent it is possible in C). The immediate consequence is that you must not start threads in the controller process (assumed you have multi-processing). The controller process continuously forks new container processes, and having threads could be deadly for it. For the API exposed by Netplex this means that doing such is not supported at all - all controller-specific APIs assume that they are only called from the same thread.

Ok, so you just don't this. However, is it allowed to have additional threads in containers? This is in deed not problematic. Just be sure that you start these threads after the container process has been created, e.g. from post_start_hook. In order to make life simpler, a number of APIs have now been made thread-safe (since Ocamlnet-3.5):

This means you can call these methods and functions without any additional synchronization effort.

Note that all extra threads are implicitly killed when the container process finishes. If you don't like this and want to terminate them in a more controlled manner, you can do this from the pre_finish_hook. If your main concurrency model is multi-threading, though, no such killing will occur - your helper threads will simply continue running when the container is finished. (Unfortunately, this difference between the two models is unavoidable.)

Netplex RPC systems

A short description how to build systems of RPC services is given in Netplex RPC systems.
ocamlnet-4.1.2/doc/html-main/Netencoding.QuotedPrintable.decoding_pipe-c.html0000644000175000017500000004232712731530352025644 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.QuotedPrintable.decoding_pipe

Class Netencoding.QuotedPrintable.decoding_pipe

class decoding_pipe : unit -> Netchannels.pipe
This pipe decodes the data written into the pipe.

ocamlnet-4.1.2/doc/html-main/Netstream.input_stream-c.html0000644000175000017500000004300712731530352022165 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstream.input_stream

Class Netstream.input_stream

class input_stream : ?len:int -> ?block_size:int -> Netchannels.in_obj_channel -> in_obj_stream
Make an in_obj_stream on top of an in_obj_channel. The block_size can be specified; it defaults to 4096.

If len is passed, this parameter limits the length of the channel: Only the first len bytes are read from the input channel, then an EOF is simulated even if the input channel is longer.


ocamlnet-4.1.2/doc/html-main/Netsys_rng.html0000644000175000017500000004345012731530352017427 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_rng

Module Netsys_rng

module Netsys_rng: sig .. end
Random-number generator


This is an interface to an OS-provided RNG that is fast and nevertheless secure enough for creating session keys. Note that it should not be used for creating long-term keys.

On Unix, the /dev/urandom device is used. If it is not available, the functions fail.

On Win32, an RNG is obtained using CryptAcquireContext.

val set_rng : (Bytes.t -> unit) -> unit
Sets the globally used RNG
val fill_random : Bytes.t -> unit
Fills this string with random bytes
ocamlnet-4.1.2/doc/html-main/type_Netftp_client.html0000644000175000017500000017020012731530352021125 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_client sig
  exception FTP_error of exn
  exception FTP_protocol_violation of string
  exception FTP_timeout of string
  exception GSSAPI_error of string
  type cmd_state =
      [ `Auth_data
      | `Init
      | `Not_connected
      | `Pass_acct_seq
      | `Perm_failure
      | `Preliminary
      | `Proto_error
      | `Rename_seq
      | `Restart_seq
      | `Success
      | `Temp_failure
      | `User_acct_seq
      | `User_pass_seq ]
  type port =
      [ `Active of string * int * Unix.file_descr
      | `Ext_active of string * int * Unix.file_descr
      | `Ext_passive of int
      | `Passive of string * int
      | `Unspecified ]
  type form_code = [ `ASA | `Non_print | `Telnet ]
  type representation =
      [ `ASCII of Netftp_client.form_code option
      | `EBCDIC of Netftp_client.form_code option
      | `Image ]
  type structure = [ `File_structure | `Record_structure ]
  type transmission_mode = [ `Block_mode | `Stream_mode ]
  type ftp_auth = [ `GSSAPI | `None | `TLS ]
  type ftp_data_prot = [ `C | `E | `P | `S ]
  type support_level = [ `If_possible | `None | `Required ]
  type ftp_state = {
    cmd_state : Netftp_client.cmd_state;
    ftp_connected : bool;
    ftp_data_conn : bool;
    ftp_user : string option;
    ftp_password : string option;
    ftp_account : string option;
    ftp_logged_in : bool;
    ftp_host : string;
    ftp_port : Netftp_client.port;
    ftp_repr : Netftp_client.representation;
    ftp_structure : Netftp_client.structure;
    ftp_trans : Netftp_client.transmission_mode;
    ftp_dir : string list;
    ftp_features : (string * string option) list option;
    ftp_options : (string * string option) list;
    ftp_auth : Netftp_client.ftp_auth;
    ftp_auth_data : string option;
    ftp_data_prot : Netftp_client.ftp_data_prot;
    ftp_data_pbsz : int;
    ftp_prot : Netftp_data_endpoint.ftp_protector option;
  }
  type cmd =
      [ `ACCT of string
      | `ADAT of string
      | `ALLO of int * int option
      | `APPE of
          string *
          (Netftp_client.ftp_state -> Netftp_data_endpoint.local_sender)
      | `AUTH of string
      | `CDUP
      | `CWD of string
      | `Connect of string * int
      | `DELE of string
      | `Disconnect
      | `Dummy
      | `EPRT
      | `EPSV of [ `AF of Unix.socket_domain | `ALL ] option
      | `FEAT
      | `HELP of string option
      | `LANG of string option
      | `LIST of
          string option *
          (Netftp_client.ftp_state -> Netftp_data_endpoint.local_receiver)
      | `MDTM of string
      | `MKD of string
      | `MLSD of
          string option *
          (Netftp_client.ftp_state -> Netftp_data_endpoint.local_receiver)
      | `MLST of string option
      | `MODE of Netftp_client.transmission_mode
      | `NLST of
          string option *
          (Netftp_client.ftp_state -> Netftp_data_endpoint.local_receiver)
      | `NOOP
      | `OPTS of string * string option
      | `PASS of string
      | `PASV
      | `PBSZ of int
      | `PORT
      | `PROT of Netftp_client.ftp_data_prot
      | `PWD
      | `QUIT
      | `REIN
      | `REST of string
      | `RETR of
          string *
          (Netftp_client.ftp_state -> Netftp_data_endpoint.local_receiver)
      | `RMD of string
      | `RNFR of string
      | `RNTO of string
      | `SITE of string
      | `SIZE of string
      | `SMNT of string
      | `STAT of string option
      | `STOR of
          string *
          (Netftp_client.ftp_state -> Netftp_data_endpoint.local_sender)
      | `STOU of Netftp_client.ftp_state -> Netftp_data_endpoint.local_sender
      | `STRU of Netftp_client.structure
      | `SYST
      | `Start_TLS of (module Netsys_crypto_types.TLS_CONFIG)
      | `Start_protection of Netftp_data_endpoint.ftp_protector
      | `TYPE of Netftp_client.representation
      | `USER of string ]
  type reply = int * string
  class type ftp_client_pi =
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method exec_e :
        ?prelim:(Netftp_client.ftp_state -> Netftp_client.reply -> unit) ->
        Netftp_client.cmd ->
        (Netftp_client.ftp_state * Netftp_client.reply) Uq_engines.engine
      method ftp_state : Netftp_client.ftp_state
      method gssapi_props : Netsys_gssapi.client_props option
      method is_empty : bool
      method mlst_enabled_facts : string list
      method mlst_facts : string list
      method need_ip6 : bool
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        (unit Uq_engines.engine -> bool) -> unit
      method run : unit -> unit
      method send_abort : unit -> unit
      method state : unit Uq_engines.engine_state
      method supports_mdtm : bool
      method supports_mlst : bool
      method supports_size : bool
      method supports_tls : bool
      method supports_tvfs : bool
      method supports_utf8 : bool
    end
  type ftp_method = Netftp_client.ftp_client_pi -> unit Uq_engines.engine
  exception FTP_method_temp_failure of int * string
  exception FTP_method_perm_failure of int * string
  exception FTP_method_unexpected_reply of int * string
  val connect_method :
    host:string -> ?port:int -> unit -> Netftp_client.ftp_method
  val login_method :
    user:string ->
    get_password:(unit -> string) ->
    get_account:(unit -> string) -> unit -> Netftp_client.ftp_method
  val quit_method : unit -> Netftp_client.ftp_method
  val tls_method :
    config:(module Netsys_crypto_types.TLS_CONFIG->
    required:bool -> unit -> Netftp_client.ftp_method
  val gssapi_method :
    config:Netsys_gssapi.client_config ->
    required:bool ->
    (module Netsys_gssapi.GSSAPI-> Netftp_client.ftp_method
  val walk_method :
    [ `Dir of string | `File of string | `Stay ] -> Netftp_client.ftp_method
  type filename = [ `NVFS of string | `TVFS of string | `Verbatim of string ]
  val get_method :
    file:Netftp_client.filename ->
    representation:Netftp_client.representation ->
    store:(Netftp_client.ftp_state -> Netftp_data_endpoint.local_receiver) ->
    unit -> Netftp_client.ftp_method
  val put_method :
    ?meth:[ `APPE | `STOR ] ->
    file:Netftp_client.filename ->
    representation:Netftp_client.representation ->
    store:(Netftp_client.ftp_state -> Netftp_data_endpoint.local_sender) ->
    unit -> Netftp_client.ftp_method
  val invoke_method :
    command:Netftp_client.cmd -> unit -> Netftp_client.ftp_method
  val set_structure_method :
    Netftp_client.structure -> Netftp_client.ftp_method
  val set_mode_method :
    Netftp_client.transmission_mode -> Netftp_client.ftp_method
  val rename_method :
    file_from:Netftp_client.filename ->
    file_to:Netftp_client.filename -> unit -> Netftp_client.ftp_method
  val mkdir_method : Netftp_client.filename -> Netftp_client.ftp_method
  val rmdir_method : Netftp_client.filename -> Netftp_client.ftp_method
  val delete_method : Netftp_client.filename -> Netftp_client.ftp_method
  val list_method :
    dir:Netftp_client.filename ->
    representation:Netftp_client.representation ->
    store:(Netftp_client.ftp_state -> Netftp_data_endpoint.local_receiver) ->
    unit -> Netftp_client.ftp_method
  val nlst_method :
    dir:Netftp_client.filename ->
    representation:Netftp_client.representation ->
    store:(Netftp_client.ftp_state -> Netftp_data_endpoint.local_receiver) ->
    unit -> Netftp_client.ftp_method
  val parse_nlst_document : string -> string list
  val mdtm_method :
    file:Netftp_client.filename ->
    process_result:(float -> unit) -> unit -> Netftp_client.ftp_method
  val size_method :
    file:Netftp_client.filename ->
    representation:Netftp_client.representation ->
    process_result:(int64 -> unit) -> unit -> Netftp_client.ftp_method
  val feat_method :
    ?process_result:((string * string option) list -> unit) ->
    unit -> Netftp_client.ftp_method
  type entry = string * (string * string) list
  val mlst_method :
    file:Netftp_client.filename ->
    process_result:(Netftp_client.entry list -> unit) ->
    unit -> Netftp_client.ftp_method
  val mlsd_method :
    dir:Netftp_client.filename ->
    store:(Netftp_client.ftp_state -> Netftp_data_endpoint.local_receiver) ->
    unit -> Netftp_client.ftp_method
  val parse_mlsd_document : string -> Netftp_client.entry list
  type entry_type = [ `Cdir | `Dir | `File | `Other | `Pdir ]
  type entry_perm =
      [ `Append
      | `Create
      | `Delete
      | `Delete_member
      | `Enter
      | `List
      | `Mkdir
      | `Read
      | `Rename
      | `Write ]
  val get_name : Netftp_client.entry -> string
  val get_size : Netftp_client.entry -> int64
  val get_modify : Netftp_client.entry -> float
  val get_create : Netftp_client.entry -> float
  val get_type : Netftp_client.entry -> Netftp_client.entry_type
  val get_unique : Netftp_client.entry -> string
  val get_perm : Netftp_client.entry -> Netftp_client.entry_perm list
  val get_lang : Netftp_client.entry -> string
  val get_media_type : Netftp_client.entry -> string
  val get_charset : Netftp_client.entry -> string
  val get_unix_mode : Netftp_client.entry -> int
  val get_unix_uid : Netftp_client.entry -> string
  val get_unix_gid : Netftp_client.entry -> string
  class ftp_client :
    ?event_system:Unixqueue.event_system ->
    unit ->
    object
      method configure_timeout : float -> unit
      method event_system : Unixqueue.event_system
      method exec : Netftp_client.ftp_method -> unit
      method exec_e : Netftp_client.ftp_method -> unit Uq_engines.engine
      method pi : Netftp_client.ftp_client_pi
      method reset : unit -> unit
      method run : unit -> unit
      method set_socks5_proxy : string -> int -> unit
    end
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Netcgi.cgi_activation-c.html0000644000175000017500000004212212731530352021702 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.cgi_activation

Class type Netcgi.cgi_activation

class type cgi_activation = cgi
Alternate, more descriptive name for cgi

ocamlnet-4.1.2/doc/html-main/Netmime_tut.html0000644000175000017500000011034212731530352017561 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime_tut

Netmime_tut


Netmime Tutorial

Structure of Mail Messages

Nowadays mail messages are in MIME format. This format allows us to attach files to messages, and to encode the main text in markup languages like HTML. In principle, mail messages have only one header block (with fields like "Subject", sender and receiver addresses, etc.) and one body block. However, this is only one view on the mail format, e.g. as seen by MTAs (mail transfer agents). The MIME format adds the possibility to structure the body block into "parts" by additional encoding sequences. The MTAs can simply ignore this additional stuff, but software creating and analyzing mails can usually not. In Netmime, one can control whether one wants to see the parts or not.

Logically, the parts of the mail body are small mail messages themselves. This means that every part has again a header and a body. The header can, in principal, contain any number of fields, and any kind of field, but in practice only a small subset of the possible fields are used, in particular only those fields that are necessary to describe the body of the part. The body can be a normal text or data block, but it is explicitly also allowed that the body is again structured into a sequence of parts. Thus complex mail messages are recursive data structures (to be exact, they are trees).

For example, a message with two attachments usually looks like:

  (mail_header, mail_body)
                 |
                 +-- (main_text_header, main_text_body)
                 +-- (att1_header, att1_body)
                 +-- (att2_header, att2_body)

The headers contains two crucial fields that control the structure of the message:

  • The Content-type describes the kind of data found in the body, e.g. "text/html". When the Content-type has the major type "multipart" (e.g. "multipart/mixed"), the body is composed of subparts. For all other types, the body is a leaf of the message tree. (To be exact, there is another major type that opens a further dimension of "message-in-message" composition: "message". This type is usually used when it is not clear whether the inner message is syntactically correct. Netmime handles this type always as leaf, but users of Netmime can try to parse these inner messages themselves.)
  • The Content-transfer-encoding describes how the body data is encoded as ASCII text. It is usually only set for leaves. Recommended values are "quoted-printable" for bodies that contain some kind of ASCII text, and "base64" for binary data.

Messages in Netmime

In Netmime, the types of mail headers and mail bodies are defined before and independent of their implementations: We have the types

  • class type mime_header: Specification of possible header implementations
  • class type mime_body: Specification of possible body implementations
  • type complex_mime_message: The type of a message tree
and the implementations

  • class basic_mime_header: A basic header implementation
  • class memory_mime_body: A body implementation storing the contents in an O'Caml string in-memory
  • class file_mime_body: A second body implementation storing the contents in an external file
Of course, the implementation classes fulfill the specifications of the corresponding class types. For completeness, there are also reduced read-only class types that maybe helpful for signatures to indicate that a function does not modify a header or body. In principal, one can also define further implementations provided they fit to the class types.

The type complex_mime_message represents the message as a tree. We have:

type complex_mime_message = mime_header * complex_mime_body
and complex_mime_body =
  [ `Body of mime_body
  | `Parts of complex_mime_message list
  ]
For example, the above mentioned mail with two attachments has the following representation:

let tree =
  (mail_header, `Parts [ (main_text_header, `Body main_text_body);
                         (att1_header, `Body att1_body);
                         (att2_header, `Body att2_body) ] )

Here, *_header are objects of type mime_header, and *_body are objects of type mime_body. It is obvious how to create the tree once one has these objects: Just use the syntax in this expression. Beginners of O'Caml should recall that it is as easy to decompose such structured values by using the pattern matching feature of the language. For example, to get the main_text_header of tree, use

let main_text_header =
  match tree with
      (_, `Parts ( (mth, _) :: _ )) -> mth
    | _ -> failwith "Message has unexpected structure"

(Note that [x1;x2;...] is just an abbreviation for x1 :: x2 :: ... :: [] ; by switching to the "::" syntax the message may have any number of parts in order to be matching.) At the first glance, it looks a bit strange to access the inner parts of mail messages in this way, but pattern matching is a very powerful sword once one gets accustomed to it.

Another hint: Because complex_mime_message is a quite challanging type for the compiler, it is often necessary to give type annotations, such as

(tree : complex_mime_message)

before passing such values to functions, otherwise you get compiler errors.

Accessing Headers

It is easy to get and set the fields of headers, e.g. mail_header # field "subject" returns the "Subject" header field as string (or raises Not_found). The names of header fields are case-insensitive. To set a field, use update_field, e.g. mail_header # update_field "subject" "Ocamlnet is great" .

The methods field and update_field process the field value as unparsed string (the parsers do only very little preprocessing, e.g. one can configure to remove all linefeeds). The module Netmime_string has a lot functions to parse and generate field values with a certain syntax. For example, "Subject" may contain so-called encoded words to express text written in a character set other than ASCII. To parse this, use

let subject = mail_header # field "subject" in
let word_list = Netmime_string.scan_encoded_text_value subject in
Now, the words contained in word_list can be accessed with a number of functions, e.g.
let word_val = Netmime_string.get_decoded_word word in
let word_cset = Netmime_string.get_charset word
Here, the string word_val is the word written in the character set word_cset.

For example, for the "Subject" field

=?iso-8859-1?q?this=20is=20some=20text?=

this method returns a word_list with one word, and for this word word_val = "this is some text" and word_cset = "iso-8859-1".

To create such structured header values, there is the function write_value in Netmime_string. This function requires some more background beyond the scope of this tutorial. As this function also supports folding of header fields, we explain only this particular application.

Folding means that long header values must be split into several lines. There is a soft limit of 78 bytes and a hard limit of 998 bytes (not counting the end-of-line sequence). The soft limit only ensures that values can be displayed in usual terminals or windows without needing horizontal scrolling. Values exceeding the hard limit may be truncated in mail transport, however. To fold a string s composed of words, first split it into its words, make atoms of them, format them with write_value, and put the result into the header field (note: this example can be programmed better, see below):

let name = "Subject" in
let words = Str.split (Str.regexp "[ \t]+") s in
let atoms = List.map (fun w -> Netmime_string.Atom w) in
let buf = Buffer.create 100 in
let ch = new Netchannels.output_buffer buf in
Netmime_string.write_value 
  ~maxlen1:(78 - String.length name - 2)
  ~maxlen:78
  ~hardmaxlen1:(998 - String.length name - 2)
  ~hardmaxlen:998
  ch;
mail_header # update_field name (Buffer.contents buf)

Unfortunately, there is no general method that can fold any kind of string. The problem is that folding is only allowed at certain places in the string, but this depends on the type of the header field. The shown method works only for informational texts like "Subject". For other fields, like "Received", the method would have to be varied, especially how the list atoms is determined. The syntax of the field must be known to compute atoms.

In the module Netsendmail you can find formatting and folding functions for informational texts like "Subject", and for mail addresses. With these functions, the "Subject" field could also be set by

let atoms = Netsendmail.create_text_tokens s in
mail_header # update_field 
  name (Netsendmail.format_field_value name atoms)

Accessing Bodies

Both types of bodies (in-memory, and file) support the following two ways of accessing:

  • Get/set the value as O'Caml string
  • Read/write the value as object channel (see Netchannels)
Note that when the value of a file-based body is changed, the file is overwritten, independently of which of the two ways is taken.

The string access is very simple: To get the value, just call value:

let s = body # value

To set the value, just call set_value:

body # set_value s

The string returned by value is not transfer-encoded, or better, all such encodings (e.g. BASE-64) are decoded. Of course, set_value expects that the passed string is not decoded, too.

Note that using value may be dangerous (or even fail) when the body is stored in a file and is very large. value forces that the file is completely read into memory. You may run into serious problems when there is not enough memory, or when the value is larger than Sys.max_string_length (16MB on 32 bit platforms).

Fortunately, there is the channel-based access method. It does not need much memory, even when large bodies are accessed. However, one does not get access to the completely body at once, but only chunk by chunk. For example, to read a body line by line, use:

let ch = body # open_value_rd() in
let line1 = ch # input_line() in
let line2 = ch # input_line() in
...
ch # close_in()

As for value, there are no transfer encodings in the returned lines.

The channel ch can be used whereever an Ocamlnet function allows it, i.e. it is a full implementation. For example, one can pass it to the HTML parser:

let ch = body # open_value_rd() in
let html_doc = Nethtml.parse ch in
ch # close_in()

To set the value using a channel, a body can also be opened for writing:

 
let ch = body # open_value_wr() in
ch # output_string "First line\n";
ch # output_string "Second line\n";
...
ch # close_out()

Parsing mail messages

The message to parse must be available as an object channel. Recall that you can create an object channel from a string with

let ch = new Netchannels.input_string s

and from a file with

let ch = new Netchannels.input_channel (open_in "filename")

so one can parse mail messages coming from any source. As only sequential access is needed, it is even possible to read directly from a Unix pipe.

Now, it is required to create a so-called netstream from ch:

let nstr = new Netstream.input_stream ch

A netstream is an object channel with additional look-ahead features. We need it here because the parser can then recognize certain patterns in the message in a simpler manner, for example the escape sequences separating the parts of a structured body.

Finally, one can invoke the parser:

let tree = Netmime_channels.read_mime_message nstr

There are a number of optional arguments for this function that can modify the way the message tree is generated. By default, all bodies are created in memory, and the tree is deeply parsed (i.e. inner multipart bodies are represented in tree form).

When bodies should be written to disk, the argument storage_style can be passed: It is a function that is called whenever a header has been parsed, but before the corresponding body. The function must return the body object for representation and the output channel connected to the body object. For example, to write the bodies into numbered files:

let n = ref 1
let ext_storage_style header =
  let body = new file_mime_body ("file" ^ string_of_int !n) in
  incr n;
  (body, body#open_out_wr())
let tree = read_mime_message ~storage_style:ext_storage_style nstr 

There is also the auxiliary function storage to create such a storage style argument.

The header can be used to generate the file name from it. Often, the filename argument of the Content-disposition field is the original file name before the attachment was appended to the mail message. To get this name:

let filename =
  try
    let disp, disp_params = header # content_disposition() in
    (* disp is usually "attachment", but we don't check *)
    List.assoc "filename" disp_params
  with
    Not_found ->
       ...  (* No such paramater, use other method to gen filename *)

It is usually a good idea to check for dangerous characters in this name ("/", "..") before constructing the name of the disk file.

A final remark: Don't forget to close nstr after parsing (this implicitly closes ch).

Creating Mail Messages

For simple applications, the Netsendmail module has a Netsendmail.compose function. It can create a mail message with attachments, and performs all the encoding details. This function is well explained in its module mli.

Of course, you can also do this yourself: Create the required headers and bodies, and put them together to the resulting tree.

Example:

 
let date =
  Netdate.mk_mail_date ~zone:Netdate.localzone (Unix.time()) in
let mail_header =
  new basic_mime_header [ "MIME-version", "1.0";
                          "Subject", "Sample mail";
                          "To", "recipient\@domain.net";
                          "From", "sender\@domain.net";
                          "Date", date;
                          "Content-type", "multipart/mixed" ] in
let main_text_header =
  new basic_mime_header [ "Content-type", "text/plain;charset=ISO-8859-1";
                          "Content-transfer-encoding", "quoted-printable";
                        ] in
let main_text_body =
  new memory_mime_body "Hello world!\nThis is a sample mail.\n" in
let att_header =
  new basic_mime_header [ "Content-type", "image/jpeg";
                          "Content-transfer-encoding", "base64";
                          "Content-disposition", "inline;description=\"My photo\"";
                        ] in
let att_body =
  new file_mime_body "photo.jpeg" in
let tree =
  (mail_header, `Parts [ (main_text_header, `Body main_text_body);
                         (att_header, `Body att_body) ] )

Printing Mail Messages

In order to print tree to the object channel ch, simply call

Netmime_channels.write_mime_message ch tree

Before invoking this function, ensure the following:

  • The Content-type field of all leaves should be set
  • The Content-transfer-encoding field of all leaves should be set (in doubt use "base64"; if missing, the default is "7bit" - probably not what you want)
  • The Content-type field of multipart nodes should be set (it defaults to "multipart/mixed" if missing)
  • The Content-transfer-encoding fields of multipart nodes should not be set - this is done by the function
If the boundary parameter is missing, the function will invent one; you don't need to deal with this.

The MIME message is written according to the found transfer encodings and the multi-part boundaries.

Don't forget to close ch after writing!


ocamlnet-4.1.2/doc/html-main/Netglob.user_info-c.html0000644000175000017500000004313012731530352021071 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.user_info

Class type Netglob.user_info

class type user_info = object .. end
Access to the user database

method path_encoding : Netconversion.encoding option
Paths of filesystems may be encoded
method home_directory : string -> string
Returns the home directory of the passed user, or the home directory of the current user for the empty string. Raises Not_found if the lookup fails.
ocamlnet-4.1.2/doc/html-main/type_Netmech_crammd5_sasl.html0000644000175000017500000004136212731530352022352 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_crammd5_sasl sig
  module CRAM_MD5 : Netsys_sasl_types.SASL_MECHANISM
  val override_challenge : string -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.generic_auth_handler.html0000644000175000017500000004135012731530352025447 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.generic_auth_handler #Nethttp_client.key_handler ->
(module Nethttp.HTTP_CLIENT_MECHANISM) list -> Nethttp_client.auth_handler
ocamlnet-4.1.2/doc/html-main/Uq_engines.poll_engine-c.html0000644000175000017500000004633112731530352022104 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.poll_engine

Class Uq_engines.poll_engine

class poll_engine : ?extra_match:exn -> bool -> (Unixqueue.operation * float) list -> Unixqueue.event_system -> object .. end
This engine waits until one of the passed operations can be carried out, or until one of the operations times out. In these cases, the state of the engine changes to `Done ev, where ev is the corresponding event.

The argument list enumerates the operations to watch for. For every operation there may be a positive timeout value, or a negative number to indicate that no timeout is specified.

After one event has been caught, the engine terminates operation. The method restart can be called to activate it again (with the same event condition, and the same notification list). See the description of restart for possible problems.


extra_match : This function is called when an Extra event is found. If the function returns true for the argument exception of Extra, the event is caught; otherwise it is rejected.
Inherits
method restart : unit -> unit
Activate the engine again when it is already in a final state. This method violates the engine protocol, and should be used with care; it is not allowed to leave a final state.

The notification lists are kept, but note that observers often detach when final states are reached. This may cause problems.

method group : Unixqueue.group
Returns the group the engine is member of
ocamlnet-4.1.2/doc/html-main/Nettls_gnutls.Digests.html0000644000175000017500000004741712731530352021551 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.Digests

Module Nettls_gnutls.Digests

module Digests: Netsys_crypto_types.DIGESTS 
Cryptographic digests


Cryptographic digests.

Users should not call functions of the provider directly, but use Netsys_digests, or another higher-level layer.

type digest 
Describes a digest
val digests : digest list
returns digests
val find : string -> digest
Returns the digest of this name, or raises Not_found
val name : digest -> string
returns the name of the digest. The name follows the format <uppercasename>-<size>, e.g. "MD5-128", "SHA1-160", "SHA2-256".
val size : digest -> int
returns the size of the hash output (in bytes)
val block_length : digest -> int
the block length (in bytes)
type digest_ctx 
A digest context stores state while digesting data
val create : digest -> digest_ctx
Creates a fresh context
val add : digest_ctx -> Netsys_types.memory -> unit
Adds data
val finish : digest_ctx -> string
Returns the digest
ocamlnet-4.1.2/doc/html-main/Netulex.html0000644000175000017500000004507012731530352016720 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netulex

Module Netulex

module Netulex: sig .. end
Support module for Alain Frisch's ulex lexer generator

The sub module ULB is a Unicode-based lexing buffer that reads encoded strings and makes them available to the lexer as both Unicode arrays and UTF-8 strings.

The sub module Ulexing is a replacement for the module in ulex with the same name. It uses ULB to represent the main lexing buffer. It is much faster than the original Ulexing implementation when the scanned text is UTF-8 encoded and Ulexing.utf8_lexeme is frequently called to get the lexeme strings. Furthermore, it can process input data of all encodings available to Netconversion. It is, however, no drop-in replacement as it has a different signature.

To enable this version of Ulexing, simply put an open Netulex before using the ulex lexers.

Note that the tutorial has been moved to Netulex_tut.



Modules


module ULB: sig .. end
module Ulexing: sig .. end
ocamlnet-4.1.2/doc/html-main/Rpc.html0000644000175000017500000007207712731530352016027 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc

Module Rpc

module Rpc: sig .. end
Common types and exceptions

type protocol = 
| Tcp (*
means: stream-oriented connection
*)
| Udp (*
means: datagram exchange
*)
type mode = 
| Socket (*
classical server socket
*)
| BiPipe (*
server is endpoint of a bidirectional pipe
*)
type server_error = 
| Unavailable_program (*
accepted call!
*)
| Unavailable_version of (Netnumber.uint4 * Netnumber.uint4) (*
accepted call
*)
| Unavailable_procedure (*
accepted call
*)
| Garbage (*
accepted call
*)
| System_err (*
accepted call
*)
| Rpc_mismatch of (Netnumber.uint4 * Netnumber.uint4) (*
rejected call
*)
| Auth_bad_cred (*
rejected call
*)
| Auth_rejected_cred (*
rejected call
*)
| Auth_bad_verf (*
rejected call
*)
| Auth_rejected_verf (*
rejected call
*)
| Auth_too_weak (*
rejected call
*)
| Auth_invalid_resp (*
rejected call
*)
| Auth_failed (*
rejected call
*)
| RPCSEC_GSS_credproblem (*
rejected call
*)
| RPCSEC_GSS_ctxproblem (*
rejected call
*)
val string_of_server_error : server_error -> string
returns a string for debug purposes
exception Rpc_server of server_error
an exception generated by the RPC server
exception Rpc_cannot_unpack of string
RPC protocol error (bad data)
val create_inet_uaddr : Unix.inet_addr -> int -> string
Create an universal address from an internet addr and a port
val parse_inet_uaddr : string -> Unix.inet_addr * int
Parses an universal address and returns internet addr and port. Failure if not parsable.
val netid_of_inet_addr : Unix.inet_addr -> protocol -> string
Get the netid for an Internet address
val sockaddr_of_uaddr : string -> string -> (Unix.sockaddr * protocol) option
sockaddr_of_uaddr netid uaddr. Returns None for unknown netid
ocamlnet-4.1.2/doc/html-main/type_Netasn1_encode.html0000644000175000017500000004226212731530352021163 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netasn1_encode sig
  val encode_ber : Netbuffer.t -> Netasn1.Value.value -> Netasn1.Value.pc
  val encode_ber_contents :
    Netbuffer.t -> Netasn1.Value.value -> Netasn1.Value.pc
end
ocamlnet-4.1.2/doc/html-main/Netchannels.output_descr-c.html0000644000175000017500000004445312731530352022501 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_descr

Class Netchannels.output_descr

class output_descr : ?blocking:bool -> ?start_pos_out:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_out_channel
Creates a raw_out_channel for the passed file descriptor, which must be open for writing.

The pos_out method returns logical positions, i.e. it counts the number of written octets. It is not tried to determine the real file position.

The method close_out also closes the file descriptor.

This class also supports Win32 proxy descriptors referring to an output channel.


blocking : Whether the channel waits until it can output if it is not possible to write to the (non-blocking) descriptor. Defaults to true.
start_pos_out : The position to which pos_out is initialized when the channel is created, by default 0
fd_style : The descriptor style. If omitted, it is automatically determined if possible.

ocamlnet-4.1.2/doc/html-main/type_Netexn.html0000644000175000017500000004140412731530352017573 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netexn sig
  val register_printer : exn -> (exn -> string) -> unit
  val to_string : exn -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netascii_armor.html0000644000175000017500000004615712731530352021303 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netascii_armor sig
  type armor_type = [ `Base64 | `OpenPGP | `Plain ]
  type armored_message =
      [ `Base64 of Netmime.mime_body
      | `OpenPGP of Netmime.mime_header * Netmime.mime_body * int
      | `Plain of Netmime.mime_body ]
  type armored_message_ro =
      [ `Base64 of Netmime.mime_body_ro
      | `OpenPGP of Netmime.mime_header_ro * Netmime.mime_body_ro * int
      | `Plain of Netmime.mime_body_ro ]
  type armor_spec = (string * Netascii_armor.armor_type) list
  val parse :
    Netascii_armor.armor_spec ->
    Netchannels.in_obj_channel ->
    (string * Netascii_armor.armored_message_ro) list
end
ocamlnet-4.1.2/doc/html-main/Netmcore_buffer.html0000644000175000017500000006341612731530352020405 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_buffer

Module Netmcore_buffer

module Netmcore_buffer: sig .. end
Shared buffer

One can add more data to the end of the buffer, and one can remove data from the beginning of the buffer.

Additions and deletions of data are atomic, and are strictly serialized. Read accesses can occur in parallel, and can even overlap with modifications (to some degree). It is, however, ensured that reads do not see the parallel modification, i.e. reads always base on the state from the beginning of the read operation.

It is not excluded that additions can be executed in parallel. If done this way, it is guaranteed that the effects of parallel additions are the same as if they were executed in a serial way. In particular, if an addition operation returns, this addition and all parallel additions affecting preceding index positions must be done. (The current implementation does not attempt this optimization.)

Index positions are "eternal", i.e. the index position of a byte does not change when preceding bytes are deleted. Instead, a deletion merely advances the start index of the valid data (which is not necessarily 0). This model is more consistent with parallel modifications.

On 32 bit platforms it can happen that index positions wrap around (at 1G). The position following max_int is 0. The length is restricted to max_int-bsize on these platforms.


type 'h buffer 
A buffer with a header of type 'h
type 'h buffer_descr 
The marshallable buffer descriptor
val create : Netmcore.res_id -> int -> 'h -> 'h buffer
create pool bsize h: Creates a buffer in pool with a block size of bsize. The block size can be an arbitrary positive integer which is always rounded up to the next multiple of the page size of the operating system. Blocks are the units of allocation of memory.
val destroy : 'h buffer -> unit
Destroys the buffer

The valid index positions (e.g. for sub) are start to start+length-1:
val start : 'h buffer -> int
Returns the start index
val length : 'h buffer -> int
Returns the length
val contents : 'h buffer -> string
Returns the full contents
val sub : 'h buffer -> int -> int -> string
Returns a substring
val blit_to_bytes : 'h buffer -> int -> Bytes.t -> int -> int -> unit
Blits contents to a string
val blit_to_string : 'h buffer -> int -> Bytes.t -> int -> int -> unit
Deprecated."Use blit_to_bytes instead."
val blit_to_memory : 'h buffer -> int -> Netsys_mem.memory -> int -> int -> unit
Blits contents to a memory buffer
val access : 'h buffer -> int -> (Bytes.t -> int -> int -> 'a) -> 'a
access b pos f: Gets access to the internal string backing the byte at position pos. The function f is called as f s k n so that s.[k] is the requested byte at pos. The number n is the number of valid bytes in the string.

During the execution of f the string s is pinned and cannot be deleted by the garbage collector.

val add_string : 'h buffer -> string -> unit
Adds a string to the end of the buffer
val add_substring : 'h buffer -> string -> int -> int -> unit
Adds a sub string to the end of the buffer
val add_sub_string : 'h buffer -> string -> int -> int -> unit
Deprecated."Use add_substring instead."
val add_submemory : 'h buffer -> Netsys_mem.memory -> int -> int -> unit
Adds a sub memory buffer to the end of the buffer
val add_sub_memory : 'h buffer -> Netsys_mem.memory -> int -> int -> unit
Deprecated."Use add_submemory instead."
val delete_hd : 'h buffer -> int -> unit
delete_hd b n: Deletes n bytes from the beginning of the buffer. This means that the start index is increased by n.
val clear : 'h buffer -> unit
Deletes all contents of the buffer
val header : 'h buffer -> 'h
Returns the header
val descr_of_buffer : 'h buffer -> 'h buffer_descr
Returns the descriptor
val buffer_of_descr : Netmcore.res_id ->
'h buffer_descr -> 'h buffer
Look up the buffer for this descriptor
val heap : 'a buffer -> Obj.t Netmcore_heap.heap
Returns the underlying heap
ocamlnet-4.1.2/doc/html-main/type_Nettelnet_client.html0000644000175000017500000007351312731530352021640 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettelnet_client sig
  exception Telnet_protocol of exn
  type telnet_command =
      Telnet_data of string
    | Telnet_nop
    | Telnet_dm
    | Telnet_brk
    | Telnet_ip
    | Telnet_ao
    | Telnet_ayt
    | Telnet_ec
    | Telnet_el
    | Telnet_ga
    | Telnet_sb of char
    | Telnet_se
    | Telnet_will of char
    | Telnet_wont of char
    | Telnet_do of char
    | Telnet_dont of char
    | Telnet_unknown of char
    | Telnet_eof
    | Telnet_timeout
  type telnet_options = {
    connection_timeout : float;
    verbose_input : bool;
    verbose_output : bool;
  }
  type telnet_negotiated_option =
      Telnet_binary
    | Telnet_echo
    | Telnet_suppress_GA
    | Telnet_status
    | Telnet_timing_mark
    | Telnet_ext_opt_list
    | Telnet_end_of_rec
    | Telnet_window_size
    | Telnet_term_speed
    | Telnet_term_type
    | Telnet_X_display
    | Telnet_linemode
    | Telnet_flow_ctrl
    | Telnet_auth
    | Telnet_new_environ
    | Telnet_option of int
  type telnet_option_state = Not_negotiated | Accepted | Rejected
  val char_of_option : Nettelnet_client.telnet_negotiated_option -> char
  val option_of_char : char -> Nettelnet_client.telnet_negotiated_option
  type telnet_connector =
      Telnet_connect of (string * int)
    | Telnet_socket of Unix.file_descr
  class telnet_session :
    object
      method attach : unit -> unit
      method disable_local_option :
        Nettelnet_client.telnet_negotiated_option -> unit
      method disable_remote_option :
        Nettelnet_client.telnet_negotiated_option -> unit
      method enable_local_option :
        Nettelnet_client.telnet_negotiated_option -> unit
      method enable_remote_option :
        Nettelnet_client.telnet_negotiated_option -> unit
      method expect_input : bool -> unit
      method fetch_subnegotiation : string option
      method get_local_option :
        Nettelnet_client.telnet_negotiated_option ->
        Nettelnet_client.telnet_option_state
      method get_options : Nettelnet_client.telnet_options
      method get_remote_option :
        Nettelnet_client.telnet_negotiated_option ->
        Nettelnet_client.telnet_option_state
      method input_queue : Nettelnet_client.telnet_command Queue.t
      method offer_local_option :
        Nettelnet_client.telnet_negotiated_option -> unit
      method option_negotiation_is_over : bool
      method output_queue : Nettelnet_client.telnet_command Queue.t
      method process_option_command : Nettelnet_client.telnet_command -> unit
      method request_remote_option :
        Nettelnet_client.telnet_negotiated_option -> unit
      method reset : unit -> unit
      method reset_local_option :
        Nettelnet_client.telnet_negotiated_option -> unit
      method reset_remote_option :
        Nettelnet_client.telnet_negotiated_option -> unit
      method run : unit -> unit
      method send_synch : Nettelnet_client.telnet_command list -> unit
      method set_callback : (bool -> unit) -> unit
      method set_connection : Nettelnet_client.telnet_connector -> unit
      method set_event_system : Unixqueue.event_system -> unit
      method set_exception_handler : (exn -> unit) -> unit
      method set_options : Nettelnet_client.telnet_options -> unit
      method start_tls :
        (module Netsys_crypto_types.TLS_CONFIG->
        peer_name:string option -> unit
      method tls_session_data : string option
      method tls_session_props : Nettls_support.tls_session_props option
      method update : unit -> unit
    end
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.Operators.html0000644000175000017500000004427512731530352022415 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.Operators sig
  val ( ++ ) :
    '#Uq_engines.engine ->
    ('-> '#Uq_engines.engine) -> 'Uq_engines.engine
  val ( >> ) :
    '#Uq_engines.engine ->
    ('Uq_engines.final_state -> 'Uq_engines.final_state) ->
    'Uq_engines.engine
  val eps_e :
    'Uq_engines.engine_state ->
    Unixqueue.event_system -> 'Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_controller.Debug.html0000644000175000017500000004101312731530352023235 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_controller.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netsys.html0000644000175000017500000011340012731530352017613 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys sig
  type fd_style =
      [ `Read_write
      | `Recv_send of Unix.sockaddr * Unix.sockaddr
      | `Recv_send_implied
      | `Recvfrom_sendto
      | `TLS of Netsys_crypto_types.file_tls_endpoint
      | `W32_event
      | `W32_input_thread
      | `W32_output_thread
      | `W32_pipe
      | `W32_pipe_server
      | `W32_process ]
  val get_fd_style : Unix.file_descr -> Netsys.fd_style
  val gread :
    Netsys.fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> int
  val gread_tbuf :
    Netsys.fd_style ->
    Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> int
  val blocking_gread :
    Netsys.fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> int
  val blocking_gread_tbuf :
    Netsys.fd_style ->
    Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> int
  val really_gread :
    Netsys.fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> unit
  val really_gread_tbuf :
    Netsys.fd_style ->
    Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> unit
  val gwrite :
    Netsys.fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> int
  val gwrite_tstr :
    Netsys.fd_style ->
    Unix.file_descr -> Netsys_types.tstring -> int -> int -> int
  val gwrite_tbuf :
    Netsys.fd_style ->
    Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> int
  val really_gwrite :
    Netsys.fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> unit
  val really_gwrite_tstr :
    Netsys.fd_style ->
    Unix.file_descr -> Netsys_types.tstring -> int -> int -> unit
  val really_gwrite_tbuf :
    Netsys.fd_style ->
    Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> unit
  exception Shutdown_not_supported
  val gshutdown :
    Netsys.fd_style -> Unix.file_descr -> Unix.shutdown_command -> unit
  val is_readable : Netsys.fd_style -> Unix.file_descr -> bool
  val is_writable : Netsys.fd_style -> Unix.file_descr -> bool
  val is_prird : Netsys.fd_style -> Unix.file_descr -> bool
  val wait_until_readable :
    Netsys.fd_style -> Unix.file_descr -> float -> bool
  val wait_until_writable :
    Netsys.fd_style -> Unix.file_descr -> float -> bool
  val wait_until_prird : Netsys.fd_style -> Unix.file_descr -> float -> bool
  val gclose : Netsys.fd_style -> Unix.file_descr -> unit
  val wait_until_connected : Unix.file_descr -> float -> bool
  val connect_check : Unix.file_descr -> unit
  val domain_of_inet_addr : Unix.inet_addr -> Unix.socket_domain
  val protostring_of_inet_addr : Unix.inet_addr -> string
  val inet_addr_of_protostring : string -> Unix.inet_addr
  val getpeername : Unix.file_descr -> Unix.sockaddr
  val is_absolute : string -> bool
  val abspath : string -> string
  val restart : ('-> 'b) -> '-> 'b
  val restart_tmo : (float -> 'b) -> float -> 'b
  val restarting_select :
    Unix.file_descr list ->
    Unix.file_descr list ->
    Unix.file_descr list ->
    float ->
    Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
  val restart_wait :
    [ `R | `W ] ->
    Netsys.fd_style -> Unix.file_descr -> ('-> 'b) -> '-> 'b
  val sleep : float -> unit
  val restarting_sleep : float -> unit
  val unix_error_of_code : int -> Unix.error
  val int64_of_file_descr : Unix.file_descr -> int64
  val string_of_fd : Unix.file_descr -> string
  val string_of_sockaddr : ?norm:bool -> Unix.sockaddr -> string
  val string_of_fd_style : Netsys.fd_style -> string
  val is_stdin : Unix.file_descr -> bool
  val is_stdout : Unix.file_descr -> bool
  val is_stderr : Unix.file_descr -> bool
  val set_close_on_exec : Unix.file_descr -> unit
  val clear_close_on_exec : Unix.file_descr -> unit
  external _exit : int -> unit = "netsys__exit"
  val is_ipv6_system : unit -> bool
  val set_ipv6_system : bool -> unit
  val logand_inet_addr : Unix.inet_addr -> Unix.inet_addr -> Unix.inet_addr
  val logor_inet_addr : Unix.inet_addr -> Unix.inet_addr -> Unix.inet_addr
  val logxor_inet_addr : Unix.inet_addr -> Unix.inet_addr -> Unix.inet_addr
  val lognot_inet_addr : Unix.inet_addr -> Unix.inet_addr
  val norm_inet_addr : Unix.inet_addr -> Unix.inet_addr
  val ipv6_inet_addr : Unix.inet_addr -> Unix.inet_addr
  val is_ipv4_inet_addr : Unix.inet_addr -> bool
  val is_ipv6_inet_addr : Unix.inet_addr -> bool
  val is_multicast_inet_addr : Unix.inet_addr -> bool
  val mcast_set_loop : Unix.file_descr -> bool -> unit
  val mcast_set_ttl : Unix.file_descr -> int -> unit
  val mcast_add_membership :
    Unix.file_descr -> Unix.inet_addr -> Unix.inet_addr -> unit
  val mcast_drop_membership :
    Unix.file_descr -> Unix.inet_addr -> Unix.inet_addr -> unit
  val moncontrol : bool -> unit
  module Debug : sig val enable : bool Pervasives.ref end
  val set_moncontrol : (bool -> unit) -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netgssapi_auth.html0000644000175000017500000006477112731530352021324 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_auth sig
  module type CONFIG = sig val raise_error : string -> 'end
  module Manage :
    functor (G : Netsys_gssapi.GSSAPI->
      sig
        val delete_context : G.context option -> unit -> unit
        val format_status :
          ?fn:string ->
          ?minor_status:int32 -> Netsys_gssapi.major_status -> string
      end
  module Auth :
    functor (G : Netsys_gssapi.GSSAPI) (C : CONFIG->
      sig
        val check_status :
          ?fn:string ->
          ?minor_status:int32 -> Netsys_gssapi.major_status -> unit
        val get_initiator_name : Netsys_gssapi.client_config -> G.name
        val get_initiator_cred :
          initiator_name:G.name ->
          Netsys_gssapi.client_config -> G.credential
        val acquire_initiator_cred :
          initiator_name:G.name ->
          Netsys_gssapi.client_config -> G.credential
        val get_target_name :
          ?default:string * Netsys_gssapi.oid ->
          Netsys_gssapi.client_config -> G.name
        val get_client_flags :
          Netsys_gssapi.client_config -> Netsys_gssapi.req_flag list
        val check_client_flags :
          Netsys_gssapi.client_config -> Netsys_gssapi.ret_flag list -> unit
        val init_sec_context :
          initiator_cred:G.credential ->
          context:G.context option ->
          target_name:G.name ->
          req_flags:Netsys_gssapi.req_flag list ->
          chan_bindings:Netsys_gssapi.channel_bindings option ->
          input_token:Netsys_gssapi.token option ->
          Netsys_gssapi.client_config ->
          G.context * Netsys_gssapi.token * Netsys_gssapi.ret_flag list *
          Netsys_gssapi.client_props option
        val get_acceptor_name : Netsys_gssapi.server_config -> G.name
        val get_acceptor_cred :
          acceptor_name:G.name -> Netsys_gssapi.server_config -> G.credential
        val get_server_flags :
          Netsys_gssapi.server_config -> Netsys_gssapi.req_flag list
        val check_server_flags :
          Netsys_gssapi.server_config -> Netsys_gssapi.ret_flag list -> unit
        val accept_sec_context :
          acceptor_cred:G.credential ->
          context:G.context option ->
          chan_bindings:Netsys_gssapi.channel_bindings option ->
          input_token:Netsys_gssapi.token ->
          Netsys_gssapi.server_config ->
          G.context * Netsys_gssapi.token * Netsys_gssapi.ret_flag list *
          Netsys_gssapi.server_props option
        val get_display_name : G.name -> string * Netsys_gssapi.oid
        val get_exported_name : G.name -> string
      end
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.post.html0000644000175000017500000004102012731530352022274 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.post string -> (string * string) list -> Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Netplex_types.par_thread-c.html0000644000175000017500000004530212731530352022465 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.par_thread

Class type Netplex_types.par_thread

class type par_thread = object .. end

method ptype : parallelization_type
method sys_id : thread_sys_id
Returns a system-dependent identifier for the thread:
  • `Thread id: The id as returned by Thread.id
  • `Process id: The id is the process ID

method info_string : string
Outputs the process or thread ID
method watch_shutdown : Unixqueue.unix_event_system -> unit
Called by the controller if it thinks the container is down. This method must not be called outside the internal Netplex implementation!
method parallelizer : parallelizer
Returns the parallelizer that created this thread. Can be used to start another thread of the same type.
ocamlnet-4.1.2/doc/html-main/Netmech_gs2_sasl.GS2.html0000644000175000017500000011476412731530352021055 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_gs2_sasl.GS2

Functor Netmech_gs2_sasl.GS2

module GS2: 
This is an adapter turning any GSSAPI mechanism into a SASL mechanism. This is the "GS2" technique as specified in RFC 5801. (Note that in particular for Kerberos there is the other specification RFC 4752 which is implemented in Netmech_krb5_sasl.)

Create the final module like

module P = struct
  let mechanism_name = "FOO"
  let announce_channel_binding = false
  let mechanism_oid = [| 1; ... |]
  let mechanism_acceptable_oid_set = [ [| 1; ... |]; ... ]
  ...
end

module S = Netmech_gs2_sasl.GS2(P)(Netgss.System)
      

Remarks for clients:

The profile specifies how user name strings are mapped to GSSAPI names. authz names are passed to the server as-is.

Remarks for servers:

The profile specifies how GSSAPI names are mapped to user name strings. The lookup callback is then invoked with this user name, and the unaltered authz name.

If lookup returns Some c for any c the user is accepted. If it returns None the user is declined.

Parameters:

  • The parameter mutual is understood but ignored. Mutual authentication is always requested from the GSSAPI mechanism.
  • The parameter secure is understood but ignored (GSSAPI is considered as secure method)
Statefulness:

The GSSAPI is stateful. Our SASL interface is stateless. We cannot hide the statefulness of the GSSAPI, and because of this old versions of sessions are invalidated. E.g. this does not work

let s1 = S.server_process_response s0 "some message"
let s2 = S.server_process_response s0 "another message"
      

and the second attempt to continue with the old session s0 will fail.

Parameters:
P : PROFILE
GSS : Netsys_gssapi.GSSAPI

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/Uq_engines.msync_engine-c.html0000644000175000017500000004455712731530352022277 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.msync_engine

Class Uq_engines.msync_engine

class [['a, 'b]] msync_engine : 'a #engine list -> ('a -> 'b -> 'b) -> 'b -> Unixqueue.event_system -> ['b] engine
Multiple synchronization: let me = new msync_engine el f x0 esys - Runs the engines in el in parallel, and waits until all are `Done. The result of me is then computed by folding the results of the part engines using f, with an initial accumulator x0.

If one of the engines goes to the states `Aborted or `Error, the combined engine will follow this transition. The other, non-aborted and non-errorneous engines are aborted in this case. `Error has higher precedence than `Aborted.

If calling f results in an exception, this is handled as if the part engine signals an error.

If the combined engine is aborted, this request is forwarded to all member engines.


ocamlnet-4.1.2/doc/html-main/type_Netsys_pollset_generic.html0000644000175000017500000004323712731530352023063 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset_generic sig
  val standard_pollset : unit -> Netsys_pollset.pollset
  val performance_pollset : unit -> Netsys_pollset.pollset
  val select_emulation :
    Netsys_pollset.pollset ->
    Unix.file_descr list ->
    Unix.file_descr list ->
    Unix.file_descr list ->
    float ->
    Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.full_info-c.html0000644000175000017500000004423612731530352022511 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.full_info

Class type Nethttpd_types.full_info

class type full_info = object .. end
Inherits
method response_status_code : int
The HTTP status code to response
method request_body_rejected : bool
Whether the request body was rejected
method output_header : Nethttp.http_header
The response header
method output_body_size : int64
The size of the output body.
ocamlnet-4.1.2/doc/html-main/Netpop.html0000644000175000017500000005425012731530352016541 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpop

Module Netpop

module Netpop: sig .. end
This is an interface for the Post Office Protocol - Version 3 (POP3) as specifed by RFC 1939. The protocol is intended to permit a workstation to dynamically access a maildrop on a server host in a useful fashion.

type state = [ `Authorization | `Transaction | `Update ] 
exception Protocol_error
exception Authentication_error
exception Err_status of string
exception Bad_state
val tcp_port : int
Default TCP port for POP version 3
class client : Netchannels.in_obj_channel -> Netchannels.out_obj_channel -> object .. end
The class client implements the POP3 protocol.
class connect : ?proxy:#Uq_engines.client_endpoint_connector -> Uq_engines.connect_address -> float -> client
connect addr timeout: Connects with the server at addr, and configure that I/O operations time out after timeout seconds of waiting.
val authenticate : ?tls_config:Netsys_crypto_types.tls_config ->
?tls_required:bool ->
?tls_peer:string ->
?sasl_mechs:Netsys_sasl.sasl_mechanism list ->
?sasl_params:(string * string * bool) list ->
?user:string ->
?authz:string -> ?creds:Netsys_sasl.credentials -> client -> unit
Authenticates the session:

  • requests capabilitlies
  • if the server supports TLS, and tls_config is set, the TLS session is started, and the capabilities are refreshed.
  • if SASL support is announced by the server, one of the sasl_mechs is taken and used for authentication. If sasl_mechs is empty, this authentication step is skipped.
Options:

  • tls_config: if set, TLS is tried on the connection
  • tls_required: if set, it is even required that TLS is supported. If not, a Netsys_types.TLS_error exception is raised.
  • tls_peer: the host name of the server (only needed for TLS, and only needed if the TLS configuration authenticates the server, or if the SNI extension is active)
  • sasl_mechs: available SASL mechanisms (in order of preference). If you pass mechanisms, you'll normally also need to pass user and creds.
  • sasl_params: parameters for SASL. A "digest-uri" parameter is always generated, and need not to be set
  • user: the user name to authenticate as
  • authz: the identity to act as (authorization name)
  • creds: credentials
You can get a simple TLS configuration with:

let tls_config =
  Netsys_tls.create_x509_config
    ~system_trust:true
    ~peer_auth:`Required
    (Netsys_crypto.current_tls())
     

SASL example:

Netpop.authenticate
  ~sasl_mechs:[ (module Netmech_scram_sasl.SCRAM_SHA1);
                (module Netmech_digest_sasl.DIGEST_MD5);
              ]
  ~user:"tom"
  ~creds:[ "password", "sEcReT", [] ]
  client


Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netnumber.ENCDEC.html0000644000175000017500000006567612731530352021232 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber.ENCDEC sig
  val read_int4 : Bytes.t -> int -> Netnumber.int4
  val read_int8 : Bytes.t -> int -> Netnumber.int8
  val read_uint4 : Bytes.t -> int -> Netnumber.uint4
  val read_uint8 : Bytes.t -> int -> Netnumber.uint8
  val read_int4_unsafe : Bytes.t -> int -> Netnumber.int4
  val read_int8_unsafe : Bytes.t -> int -> Netnumber.int8
  val read_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4
  val read_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8
  val read_string_int4 : string -> int -> Netnumber.int4
  val read_string_int8 : string -> int -> Netnumber.int8
  val read_string_uint4 : string -> int -> Netnumber.uint4
  val read_string_uint8 : string -> int -> Netnumber.uint8
  val read_string_int4_unsafe : string -> int -> Netnumber.int4
  val read_string_int8_unsafe : string -> int -> Netnumber.int8
  val read_string_uint4_unsafe : string -> int -> Netnumber.uint4
  val read_string_uint8_unsafe : string -> int -> Netnumber.uint8
  val write_int4 : Bytes.t -> int -> Netnumber.int4 -> unit
  val write_int8 : Bytes.t -> int -> Netnumber.int8 -> unit
  val write_uint4 : Bytes.t -> int -> Netnumber.uint4 -> unit
  val write_uint8 : Bytes.t -> int -> Netnumber.uint8 -> unit
  val write_int4_unsafe : Bytes.t -> int -> Netnumber.int4 -> unit
  val write_int8_unsafe : Bytes.t -> int -> Netnumber.int8 -> unit
  val write_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4 -> unit
  val write_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8 -> unit
  val int4_as_bytes : Netnumber.int4 -> Bytes.t
  val int8_as_bytes : Netnumber.int8 -> Bytes.t
  val uint4_as_bytes : Netnumber.uint4 -> Bytes.t
  val uint8_as_bytes : Netnumber.uint8 -> Bytes.t
  val int4_as_string : Netnumber.int4 -> string
  val int8_as_string : Netnumber.int8 -> string
  val uint4_as_string : Netnumber.uint4 -> string
  val uint8_as_string : Netnumber.uint8 -> string
  val write_fp4 : Bytes.t -> int -> Netnumber.fp4 -> unit
  val write_fp8 : Bytes.t -> int -> Netnumber.fp8 -> unit
  val fp4_as_string : Netnumber.fp4 -> string
  val fp8_as_string : Netnumber.fp8 -> string
  val fp4_as_bytes : Netnumber.fp4 -> Bytes.t
  val fp8_as_bytes : Netnumber.fp8 -> Bytes.t
  val read_fp4 : Bytes.t -> int -> Netnumber.fp4
  val read_fp8 : Bytes.t -> int -> Netnumber.fp8
  val read_string_fp4 : string -> int -> Netnumber.fp4
  val read_string_fp8 : string -> int -> Netnumber.fp8
end
ocamlnet-4.1.2/doc/html-main/Netchannels.output_netbuffer-c.html0000644000175000017500000004316712731530352023362 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_netbuffer

Class Netchannels.output_netbuffer

class output_netbuffer : ?onclose:unit -> unit -> Netbuffer.t -> out_obj_channel
This output channel writes the data into the passed netbuffer.

The method pos_out returns the number of written octets.


onclose : this function is called when the close_out method is invoked, just after the underlying descriptor has been closed.

ocamlnet-4.1.2/doc/html-main/type_Netplex_types.html0000644000175000017500000022371312731530352021202 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types sig
  type encap = Netplex_encap.encap
  type param_value =
      [ `Bool of bool | `Float of float | `Int of int | `String of string ]
  type param_value_or_any =
      [ `Any of exn
      | `Bool of bool
      | `Encap of Netplex_types.encap
      | `Float of float
      | `Int of int
      | `String of string ]
  type level =
      [ `Alert | `Crit | `Debug | `Emerg | `Err | `Info | `Notice | `Warning ]
  class type logger =
    object
      method log :
        component:string ->
        level:Netplex_types.level -> message:string -> unit
      method log_subch :
        component:string ->
        subchannel:string ->
        level:Netplex_types.level -> message:string -> unit
      method reopen : unit -> unit
    end
  type parallelization_type =
      [ `Controller_attached | `Multi_processing | `Multi_threading ]
  type thread_sys_id = [ `Process of int | `Thread of int ]
  type socket_state = [ `Disabled | `Down | `Enabled | `Restarting of bool ]
  type container_id = < socket_service_name : string >
  type container_state =
      [ `Accepting of int * float
      | `Busy
      | `Shutting_down
      | `Starting of float ]
  type capacity =
      [ `Low_quality of int * bool
      | `Normal_quality of int * bool
      | `Unavailable ]
  type extended_address =
      [ `Container of
          string * string * string *
          [ `Any | `Process of int | `Thread of int ]
      | `Internal of string
      | `Socket of Unix.sockaddr
      | `Socket_file of string
      | `W32_pipe of string
      | `W32_pipe_file of string ]
  type (_, _) eq = Equal : ('a, 'a) Netplex_types.eq | Not_equal
  type _ polysocket_kind = ..
  type _ polysocket_kind +=
      Txdr : Netxdr.xdr_value Netplex_types.polysocket_kind
    | Tstring : string Netplex_types.polysocket_kind
  type 'a kind_check = {
    kind_check :
      'b. 'Netplex_types.polysocket_kind -> ('a, 'b) Netplex_types.eq;
  }
  type polysocket_kind_box =
      Polysocket_kind_box :
        'Netplex_types.polysocket_kind -> Netplex_types.polysocket_kind_box
  type polyserver_box =
      Polyserver_box : 'Netplex_types.polysocket_kind *
        'Netsys_polysocket.polyserver -> Netplex_types.polyserver_box
  type polyclient_box =
      Polyclient_box : 'Netplex_types.polysocket_kind *
        'Netsys_polysocket.polyclient -> Netplex_types.polyclient_box
  type extfd =
      OS_descr of Unix.file_descr
    | Poly_endpoint of Netxdr.xdr_value Netsys_polysocket.polyendpoint
  class type controller =
    object
      method activate_lever :
        int -> Netplex_types.encap -> Netplex_types.encap
      method add_admin : (Rpc_server.t -> unit) -> unit
      method add_message_receiver :
        Netplex_types.ctrl_message_receiver -> unit
      method add_plugin : Netplex_types.plugin -> unit
      method add_service :
        Netplex_types.socket_service ->
        Netplex_types.workload_manager -> unit
      method container_count : string -> int
      method containers : Netplex_types.container_id list
      method containers_for : string -> Netplex_types.container_id list
      method controller_config : Netplex_types.controller_config
      method event_system : Unixqueue.unix_event_system
      method free_resources : unit -> unit
      method logger : Netplex_types.logger
      method ptype : Netplex_types.parallelization_type
      method register_lever :
        (Netplex_types.controller ->
         Netplex_types.encap -> Netplex_types.encap) ->
        int
      method restart : unit -> unit
      method send_admin_message : string -> string -> string array -> unit
      method send_message : string -> string -> string array -> unit
      method services :
        (Netplex_types.socket_service * Netplex_types.socket_controller *
         Netplex_types.workload_manager)
        list
      method shutdown : unit -> unit
      method startup_directory : string
      method sys_id : Netplex_types.thread_sys_id
    end
  and controller_config =
    object
      method create_logger : Netplex_types.controller -> Netplex_types.logger
      method max_level : Netplex_types.level
      method set_max_level : Netplex_types.level -> unit
      method socket_directory : string
    end
  and socket_service =
    object
      method create_container :
        Netplex_types.parallelization_type ->
        Netplex_types.socket_service -> Netplex_types.container
      method internal_sockets : (string * Netplex_types.polyserver_box) list
      method name : string
      method on_add : Netplex_types.controller -> unit
      method processor : Netplex_types.processor
      method shutdown : unit -> unit
      method socket_service_config : Netplex_types.socket_service_config
      method sockets : (string * Unix.file_descr array) list
      method startup_directory : string
    end
  and socket_service_config =
    object
      method change_user_to : (int * int) option
      method conn_limit : int option
      method controller_config : Netplex_types.controller_config
      method gc_when_idle : bool
      method name : string
      method protocols : Netplex_types.protocol list
      method startup_timeout : float
    end
  and protocol =
    object
      method addresses : Netplex_types.extended_address array
      method configure_slave_socket : Unix.file_descr -> unit
      method local_chmod : int option
      method local_chown : (int * int) option
      method lstn_backlog : int
      method lstn_reuseaddr : bool
      method name : string
      method so_keepalive : bool
      method tcp_nodelay : bool
    end
  and socket_controller =
    object
      method container_state :
        (Netplex_types.container_id * string *
         Netplex_types.container_state * bool)
        list
      method disable : unit -> unit
      method enable : unit -> unit
      method restart : unit -> unit
      method shutdown : unit -> unit
      method start_containers : int -> int
      method state : Netplex_types.socket_state
      method stop_containers : Netplex_types.container_id list -> unit
    end
  and ctrl_message_receiver =
    object
      method name : string
      method receive_admin_message :
        Netplex_types.controller -> string -> string array -> unit
      method receive_message :
        Netplex_types.controller -> string -> string array -> unit
    end
  and processor_hooks =
    object
      method config_internal :
        (string * Netplex_types.polysocket_kind_box) list
      method container_event_system : unit -> Unixqueue.event_system
      method container_run : Unixqueue.event_system -> unit
      method global_exception_handler : exn -> bool
      method post_add_hook :
        Netplex_types.socket_service -> Netplex_types.controller -> unit
      method post_finish_hook :
        Netplex_types.socket_service ->
        Netplex_types.controller -> Netplex_types.container_id -> unit
      method post_rm_hook :
        Netplex_types.socket_service -> Netplex_types.controller -> unit
      method post_start_hook : Netplex_types.container -> unit
      method pre_finish_hook : Netplex_types.container -> unit
      method pre_start_hook :
        Netplex_types.socket_service ->
        Netplex_types.controller -> Netplex_types.container_id -> unit
      method process_internal :
        when_done:(unit -> unit) ->
        Netplex_types.container ->
        Netplex_types.polyserver_box -> string -> unit
      method receive_admin_message :
        Netplex_types.container -> string -> string array -> unit
      method receive_message :
        Netplex_types.container -> string -> string array -> unit
      method shutdown : unit -> unit
      method system_shutdown : unit -> unit
      method workload_hook : Netplex_types.container -> bool -> int -> unit
    end
  and processor =
    object
      method config_internal :
        (string * Netplex_types.polysocket_kind_box) list
      method container_event_system : unit -> Unixqueue.event_system
      method container_run : Unixqueue.event_system -> unit
      method global_exception_handler : exn -> bool
      method post_add_hook :
        Netplex_types.socket_service -> Netplex_types.controller -> unit
      method post_finish_hook :
        Netplex_types.socket_service ->
        Netplex_types.controller -> Netplex_types.container_id -> unit
      method post_rm_hook :
        Netplex_types.socket_service -> Netplex_types.controller -> unit
      method post_start_hook : Netplex_types.container -> unit
      method pre_finish_hook : Netplex_types.container -> unit
      method pre_start_hook :
        Netplex_types.socket_service ->
        Netplex_types.controller -> Netplex_types.container_id -> unit
      method process :
        when_done:(unit -> unit) ->
        Netplex_types.container -> Unix.file_descr -> string -> unit
      method process_internal :
        when_done:(unit -> unit) ->
        Netplex_types.container ->
        Netplex_types.polyserver_box -> string -> unit
      method receive_admin_message :
        Netplex_types.container -> string -> string array -> unit
      method receive_message :
        Netplex_types.container -> string -> string array -> unit
      method shutdown : unit -> unit
      method supported_ptypes : Netplex_types.parallelization_type list
      method system_shutdown : unit -> unit
      method workload_hook : Netplex_types.container -> bool -> int -> unit
    end
  and container =
    object
      method activate_lever :
        int -> Netplex_types.encap -> Netplex_types.encap
      method call_plugin :
        Netplex_types.plugin ->
        string -> Netxdr.xdr_value -> Netxdr.xdr_value
      method container_id : Netplex_types.container_id
      method event_system : Unixqueue.unix_event_system
      method log : Netplex_types.level -> string -> unit
      method log_subch : string -> Netplex_types.level -> string -> unit
      method lookup : string -> string -> string option
      method lookup_container_sockets : string -> string -> string array
      method n_connections : int
      method n_total : int
      method owned_container_sockets : (string * string) list
      method ptype : Netplex_types.parallelization_type
      method send_message : string -> string -> string array -> unit
      method set_var : string -> Netplex_types.param_value_or_any -> unit
      method shutdown : unit -> unit
      method socket_service : Netplex_types.socket_service
      method socket_service_name : string
      method start : Netplex_types.extfd -> Netplex_types.extfd -> unit
      method startup_directory : string
      method system : Rpc_client.t
      method system_monitor : Uq_mt.monitor
      method update_detail : Unix.file_descr -> string -> unit
      method var : string -> Netplex_types.param_value_or_any
    end
  and workload_manager =
    object
      method adjust :
        Netplex_types.socket_service ->
        Netplex_types.socket_controller -> unit
      method capacity :
        Netplex_types.container_id ->
        Netplex_types.container_state -> Netplex_types.capacity
      method hello : Netplex_types.controller -> unit
      method shutdown : unit -> unit
    end
  and plugin =
    object
      method ctrl_added : Netplex_types.controller -> unit
      method ctrl_container_finished :
        Netplex_types.controller ->
        Netplex_types.container_id -> bool -> unit
      method ctrl_receive_call :
        Netplex_types.controller ->
        Netplex_types.container_id ->
        string ->
        Netxdr.xdr_value -> (Netxdr.xdr_value option -> unit) -> unit
      method ctrl_unplugged : Netplex_types.controller -> unit
      method program : Rpc_program.t
      method required : Netplex_types.plugin list
    end
  class type par_thread =
    object
      method info_string : string
      method parallelizer : Netplex_types.parallelizer
      method ptype : Netplex_types.parallelization_type
      method sys_id : Netplex_types.thread_sys_id
      method watch_shutdown : Unixqueue.unix_event_system -> unit
    end
  and parallelizer =
    object
      method create_mem_mutex : unit -> (unit -> unit) * (unit -> unit)
      method current_sys_id : [ `Process of int | `Thread of int ]
      method init : unit -> unit
      method ptype : Netplex_types.parallelization_type
      method start_thread :
        (Netplex_types.par_thread -> unit) ->
        Unix.file_descr list ->
        Unix.file_descr list ->
        string -> Netplex_types.logger -> Netplex_types.par_thread
    end
  type config_tree =
      [ `Parameter of string * Netplex_types.param_value
      | `Section of string * Netplex_types.config_tree list ]
  and address = <  >
  class type config_file =
    object
      method bool_param : Netplex_types.address -> bool
      method filename : string
      method float_param : Netplex_types.address -> float
      method int_param : Netplex_types.address -> int
      method print : Netplex_types.address -> string
      method resolve_parameter :
        Netplex_types.address -> string -> Netplex_types.address
      method resolve_section :
        Netplex_types.address -> string -> Netplex_types.address list
      method restrict_parameters :
        Netplex_types.address -> string list -> unit
      method restrict_subsections :
        Netplex_types.address -> string list -> unit
      method root_addr : Netplex_types.address
      method root_name : string
      method string_param : Netplex_types.address -> string
      method tree : Netplex_types.config_tree
    end
  class type processor_factory =
    object
      method create_processor :
        Netplex_types.controller_config ->
        Netplex_types.config_file ->
        Netplex_types.address -> Netplex_types.processor
      method name : string
    end
  class type workload_manager_factory =
    object
      method create_workload_manager :
        Netplex_types.controller_config ->
        Netplex_types.config_file ->
        Netplex_types.address -> Netplex_types.workload_manager
      method name : string
    end
  class type logger_factory =
    object
      method create_logger :
        Netplex_types.config_file ->
        Netplex_types.address ->
        Netplex_types.controller -> Netplex_types.logger
      method name : string
    end
  class type netplex_config =
    object
      method controller_config : Netplex_types.controller_config
      method ptype : Netplex_types.parallelization_type
      method services :
        (Netplex_types.socket_service_config *
         (Netplex_types.address * Netplex_types.processor_factory) *
         (Netplex_types.address * Netplex_types.workload_manager_factory))
        list
    end
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram.Debug.html0000644000175000017500000004100612731530352022125 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netsys_digests.digest.html0000644000175000017500000004224512731530352022623 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_digests.digest object
  method block_length : int
  method create : unit -> Netsys_digests.digest_ctx
  method iana_hash_fn : Netsys_digests.iana_hash_fn option
  method iana_name : string option
  method name : string
  method oid : int array option
  method size : int
end
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.html0000644000175000017500000005047512731530352021412 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types

Module Netsys_crypto_types

module Netsys_crypto_types: sig .. end
Types for crypto providers

module type TLS_EXCEPTIONS = sig .. end
The exceptions the TLS provider may use (in addition to OCaml's built-in exception).
module type TLS_PROVIDER = sig .. end
module type TLS_CONFIG = sig .. end
module type TLS_ENDPOINT = sig .. end
module type FILE_TLS_ENDPOINT = sig .. end
module type SYMMETRIC_CRYPTO = sig .. end
module type DIGESTS = sig .. end
module type PUBKEY_CRYPTO = sig .. end
type tls_provider = (module Netsys_crypto_types.TLS_PROVIDER) 
type tls_config = (module Netsys_crypto_types.TLS_CONFIG) 
type tls_endpoint = (module Netsys_crypto_types.TLS_ENDPOINT) 
type file_tls_endpoint = (module Netsys_crypto_types.FILE_TLS_ENDPOINT) 
type symmetric_crypto = (module Netsys_crypto_types.SYMMETRIC_CRYPTO) 
type digests = (module Netsys_crypto_types.DIGESTS) 
type pubkey_crypto = (module Netsys_crypto_types.PUBKEY_CRYPTO) 
ocamlnet-4.1.2/doc/html-main/Netchannels.out_obj_channel_delegation-c.html0000644000175000017500000004254212731530352025302 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.out_obj_channel_delegation

Class Netchannels.out_obj_channel_delegation

class out_obj_channel_delegation : ?close:bool -> out_obj_channel -> out_obj_channel

ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.PUBKEY_CRYPTO.html0000644000175000017500000005442512731530352023507 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.PUBKEY_CRYPTO

Module type Netsys_crypto_types.PUBKEY_CRYPTO

module type PUBKEY_CRYPTO = sig .. end

type public_key 
type private_key 
type pin_callback 
type algorithm 
val supported_x509 : int array list
The supported X509 algorithm types as list of OIDs
val algorithm_x509 : int array -> string option -> algorithm
The algorithm is specified by OID. The parameters - if present - are DER-encoded. The passed parameters override any parameters already contained in the key. Usually, it is only necessary to provide parameters that are not yet contained in the key (e.g. the hash algorithms of RSASSA-PSS when applied to a normal RSA key).
val import_public_key_x509 : string -> public_key
The DER-encoded subjectPublicKeyInfo
val import_public_key_uri : string -> public_key
indirect reference e.g. a PKCS11 URI
val import_public_key_uri_with_pin : pin_callback ->
string -> public_key
type x509_private_key = string * string 
(format,data), using the formats: "RSA", "DSA", "DH", "EC". The data is DER-encoded.
val import_private_key_x509 : x509_private_key ->
private_key
import a private key from DER
val import_private_key_uri : string -> private_key
indirect reference e.g. a PKCS11 URI
val import_private_key_uri_with_pin : pin_callback ->
string -> private_key
val import_public_key_from_private : private_key ->
public_key
val simple_pin_callback : (unit -> string) -> pin_callback
val encrypt : algorithm ->
public_key -> string -> string
val decrypt : algorithm ->
private_key -> string -> string
val verify : algorithm ->
public_key -> string -> string -> bool
val sign : algorithm ->
private_key -> string -> string
ocamlnet-4.1.2/doc/html-main/type_Netplex_cenv.LEVER.html0000644000175000017500000004255112731530352021644 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.LEVER sig
  type s
  type r
  type t = Netplex_cenv.LEVER.s -> Netplex_cenv.LEVER.r
  val register :
    Netplex_types.controller ->
    (Netplex_types.controller -> Netplex_cenv.LEVER.t) ->
    Netplex_cenv.LEVER.t
end
ocamlnet-4.1.2/doc/html-main/Netmech_krb5_sasl.html0000644000175000017500000004517512731530352020632 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_krb5_sasl

Module Netmech_krb5_sasl

module Netmech_krb5_sasl: sig .. end
Kerberos 5 as SASL mechanism

module Krb5_gs1: 
This is an adapter turning the Kerberos 5 GSSAPI mechanism into a SASL mechanism.
module Krb5_gs2: 
This is the other adapter turning the Kerberos 5 GSSAPI mechanism into a SASL mechanism.
module Krb5_gs2_profile: Netmech_gs2_sasl.PROFILE 
This is the profile used for Netmech_krb5_sasl.Krb5_gs2
ocamlnet-4.1.2/doc/html-main/Netsys_ciphers.html0000644000175000017500000005353512731530352020303 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_ciphers

Module Netsys_ciphers

module Netsys_ciphers: sig .. end
Symmetric cryptographic ciphers

type padding = [ `CTS | `Length | `None | `_8000 ] 
Padding schemes:

  • `None: no padding. The text to encrypt/decrypt must be a multiple of block_constraint bytes
  • `Length: Pad the last block with n bytes of code n
  • `_8000: Pad with one byte 0x80 and as many zeros as needed to fill the block (this may add one or two blocks)
  • `CTS: Use "Ciphertext Stealing". There is a minimum length of the message to encrypt of two blocks.

class type cipher_ctx = object .. end
class type cipher = object .. end

The following functions use the current crypto module (as retrieved by Netsys_crypto.current_symmetric_crypto), unless the impl argument is passed.
val ciphers : ?impl:(module Netsys_crypto_types.SYMMETRIC_CRYPTO) ->
unit -> cipher list
List of supported ciphers
val find : ?impl:(module Netsys_crypto_types.SYMMETRIC_CRYPTO) ->
string * string -> cipher
find (name,mode): get the cipher name in the passed mode.

The name conventionally follows the <uppercasestring>-<size> format, e.g. "AES-128" or "TWOFISH-128".

Modes are "ECB", "CBC", "OFB", "CTR", "STREAM", "GCM". Not every cipher is available in every mode.

val process_subbytes : (last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int) ->
Bytes.t -> int -> int -> Bytes.t
process_subbytes p s pos len: If p is encrypt or decrypt from a cipher_ctx, p will be called to submit the data from string s, starting at position pos and length len.

The encrypted or decrypted string is returned.

val process_substring : (last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int) ->
string -> int -> int -> string
process_substring p s pos len: Same for immutable strings.
val process_bytes : (last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int) ->
Bytes.t -> Bytes.t
process_bytes p s: If p is encrypt or decrypt from a cipher_ctx, p will be called to submit the data from string s.

The encrypted or decrypted string is returned.

val process_string : (last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int) ->
string -> string
process_string p s: same for immutable strings.
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.key_handler.html0000644000175000017500000004176312731530352023612 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.key_handler object
  method inquire_key :
    domain:Neturl.url option ->
    realm:string -> auth:string -> Nethttp_client.key
  method invalidate_key : Nethttp_client.key -> unit
end
ocamlnet-4.1.2/doc/html-main/Netplex_main.html0000644000175000017500000006660212731530352017723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_main

Module Netplex_main

module Netplex_main: sig .. end
Main program for Netplex servers

type cmdline_config 
val args : ?defaults:cmdline_config ->
unit -> (Arg.key * Arg.spec * Arg.doc) list * cmdline_config
let (opt_list, cmdline_cfg) = args(): Returns opt_list for inclusion in the Arg.parse option list. The effects made available by the returned cmdline_cfg value.

The defaults (unless overridden by defaults): The config file is derived from the name of the executable (by appending .conf instead of the current extension). There is no config tree.


defaults : The default argument values
val create : ?config_filename:string ->
?config_tree:Netplex_types.config_tree ->
?pidfile:string option ->
?foreground:bool -> unit -> cmdline_config
Creates the command-line configuration object.

By setting config_tree a special configuration can be injected - the file config_filename is not loaded in this case (but may still appear in error messages)

val modify : ?config_filename:string ->
?config_tree:Netplex_types.config_tree ->
?pidfile:string option ->
?foreground:bool ->
cmdline_config -> cmdline_config
Modifies the command-line configuration object
val config_filename : cmdline_config -> string
Returns the filename of the configuration file, or the default if it has not been set on the command-line
val config_filename_opt : cmdline_config -> string option
Returns the filename of the configuration file, or None if it has not been set on the command-line
val config_tree_opt : cmdline_config -> Netplex_types.config_tree option
Returns the tree of the configuration file, or None if it has not been set by create or modify. Note that args never sets the config tree.
val pidfile : cmdline_config -> string option
Returns the location of the PID file (if any)
val foreground : cmdline_config -> bool
Returns whether the daemon runs in the foreground
val startup : ?late_initializer:(Netplex_types.config_file ->
Netplex_types.controller -> unit) ->
?config_parser:(string -> Netplex_types.config_file) ->
Netplex_types.parallelizer ->
Netplex_types.logger_factory list ->
Netplex_types.workload_manager_factory list ->
Netplex_types.processor_factory list -> cmdline_config -> unit
Establishes a configuration and starts the Netplex daemon.

If a ready-made configuration tree is included in the passed configuration it is taken as the configuration. If otherwise only the name of the config file is available, this file is parsed. Fails with Netplex_config.Config_error when an error in the configuration is detected.

The late_initializer is called after the Netplex controller has been fully initialized, and before the main event loop is entered. You can perform here further initializations, e.g. starting helper threads.

The config_parser is by default Netplex_config.read_config_file. You can override it by whatever parser you would like to use. The parser is only used if a configuration tree is unavailable, and the configuration needs to be loaded from a file.

As side-effect, the current logger of the Netlog module is set to selected Netplex logger. Note that this setting remains active even after startup returns to the caller. Also note that log messages submitted via Netlog appear as from component "netplex.other" if they are sent from outside of a container.

It is changed to / as working directory (as required for a daemon).

val run : ?config_parser:(string -> Netplex_types.config_file) ->
late_initializer:(Netplex_types.config_file -> Netplex_types.controller -> 'a) ->
extract_result:(Netplex_types.controller -> 'a -> 'b) ->
Netplex_types.parallelizer ->
Netplex_types.logger_factory list ->
Netplex_types.workload_manager_factory list ->
Netplex_types.processor_factory list -> cmdline_config -> 'b
Similar to startup, but this function is tailored for Netplex systems that compute results (e.g. Netmulticore jobs). In this scenario, it is not sufficient to just fire off child processes, but you also want to return a result to the caller once the processes have finished their tasks. One consequence of this is that you cannot daemonize the program - it always runs in the foreground (no matter whether -fg is given or not).

run expects that the caller passes a function extract_result. This function is invoked once the Netplex system is done, and the user can extract the final result from the controller. The result of extract_result is also the result of run.

At the moment extract_result is invoked, the child processes are already terminated. They should have put their result at a place that is in the controller, or can be reached with the help of the controller. The controller functionality is still fully available.

Note that the controller is shut down as soon as extract_result returns. Further interactions with the controller are not possible.

The late_initializer is now obligatory for typing reasons (so you can get the result of the late_initializer from extract_result). If you don't need it, just return ().

The working directory is left unchanged.


Tutorial

The typical main program for a Netplex server system looks like:

 
   let my_factories = ...

   let start() =
    let opts, cmdconf = Netplex_main.args() in
    Arg.parse 
      opts
      (fun s -> raise(Arg.Bad ("Unknown arg: " ^ s))) 
      "usage: protoserver";
    let par = Netplex_mp.mp() in  (* or Netplex_mt.mt() *)
    Netplex_main.startup
      par
      Netplex_log.logger_factories
      Netplex_workload.workload_manager_factories
      my_factories
      cmdconf

   Sys.set_signal Sys.sigpipe Sys.Signal_ignore;
   start()
 

This main program enables:

  • The standard command-line arguments -conf, -pid and -fg are understood
  • The configuration file is parsed
  • The configuration can refer to all loggers and workload managers coming with Netplex
  • The parallelizer is selected: Here, it is multi-processing (Netplex_mp). One could also select multi-threading (Netplex_mt)
  • The processors defined by my_factories are made available for connection processing

ocamlnet-4.1.2/doc/html-main/Rpc_client.auth_method-c.html0000644000175000017500000004450612731530352022101 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.auth_method

Class type Rpc_client.auth_method

class type auth_method = object .. end
An auth_method object represents a method of authentication. Such an object can be shared by several clients.

method name : string
The name of this method, used for errors etc.
method new_session : t -> string option -> auth_protocol
Request a new session. The 2nd argument is the user name, or None if the default is to be used (whatever this is). Some authenticators only support None.

It is allowed that the returned auth_protocol object is already in state `Done, i.e. that actually no protocol is run.

Changed in Ocamlnet-3.3: different signature. The user name is now an argument, and the method returns auth_protocol instead of auth_session. There can now be a separate session for each user (plus for the default user None).

ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.stream_seq_engine-c.html0000644000175000017500000004264712731530352024652 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.stream_seq_engine

Class Uq_engines_compat.stream_seq_engine

class ['a] stream_seq_engine : 'a -> ('a -> 'a #engine) Stream.t -> Unixqueue.event_system -> ['a] engine

ocamlnet-4.1.2/doc/html-main/Netx509.AD.html0000644000175000017500000004337212731530352016736 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.AD

Module Netx509.AD

module AD: sig .. end

val ad_ca_issuers : Netx509.oid
val ad_ocsp : Netx509.oid
val ad_ca_repository : Netx509.oid
val ad_time_stamping : Netx509.oid
val access_descriptions : (Netx509.oid * Netx509.access_description_flag * string) list
ocamlnet-4.1.2/doc/html-main/Netchannels.augment_raw_out_channel-c.html0000644000175000017500000004517012731530352024646 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.augment_raw_out_channel

Class virtual Netchannels.augment_raw_out_channel

class virtual augment_raw_out_channel : object .. end
This class implements the methods from compl_out_channel by calling the methods of raw_out_channel. There is no additional buffering.
Inherits
method virtual output : Bytes.t -> int -> int -> int
As in raw_out_channel
method virtual close_out : unit -> unit
As in raw_out_channel
method virtual flush : unit -> unit
As in raw_out_channel
method virtual pos_out : int
As in raw_out_channel
ocamlnet-4.1.2/doc/html-main/type_Netplex_log.multi_file_config.html0000644000175000017500000004454612731530352024301 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_log.multi_file_config object
  method log_component : string
  method log_directory : string
  method log_files :
    (string * string *
     [ `Alert
     | `All
     | `Crit
     | `Debug
     | `Emerg
     | `Err
     | `Info
     | `Notice
     | `Warning ] * string * string)
    list
  method log_format : string
  method log_max_level : Netplex_types.level
  method log_subchannel : string
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_krb5_sasl.Krb5_gs1.html0000644000175000017500000004122612731530352023240 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_krb5_sasl.Krb5_gs1 functor (GSS : Netsys_gssapi.GSSAPI-> Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/type_Uq_engines.signal_engine.html0000644000175000017500000004307412731530352023235 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.signal_engine Unixqueue.event_system ->
object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : ('a engine -> bool) -> unit
  method signal : 'Uq_engines.final_state -> unit
  method state : 'a engine_state
end
ocamlnet-4.1.2/doc/html-main/Netsmtp.connect-c.html0000644000175000017500000004311512731530352020574 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsmtp.connect

Class Netsmtp.connect

class connect : ?proxy:#Uq_engines.client_endpoint_connector -> Uq_engines.connect_address -> float -> client
connect addr timeout: Connects with the server at addr, and configure that I/O operations time out after timeout seconds of waiting.

Example:

  let addr =
    `Socket(`Sock_inet_byname(Unix.SOCK_STREAM, "www.domain.com", 25),
            Uq_client.default_connect_options) in
  let client =
    new Netsmtp.connect addr 60.0


ocamlnet-4.1.2/doc/html-main/Netchannels.buffered_trans_channel-c.html0000644000175000017500000004323212731530352024434 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.buffered_trans_channel

Class Netchannels.buffered_trans_channel

class buffered_trans_channel : ?close_mode:close_mode -> out_obj_channel -> trans_out_obj_channel
A transactional output channel with a transaction buffer implemented in memory


close_mode : Specifies the semantics of close_out, by default `Commit

ocamlnet-4.1.2/doc/html-main/type_Neturl_ldap.html0000644000175000017500000004770612731530352020616 0ustar gerdgerd Ocamlnet 4 Reference Manual : Neturl_ldap sig
  val ldap_url_dn : ?encoded:bool -> Neturl.url -> string
  val ldap_url_attributes : ?encoded:bool -> Neturl.url -> string list
  val ldap_url_scope : Neturl.url -> [ `Base | `One | `Sub ]
  val ldap_url_filter : ?encoded:bool -> Neturl.url -> string
  val ldap_url_extensions :
    ?encoded:bool -> Neturl.url -> (bool * string * string option) list
  val ldap_url_provides :
    ?dn:bool ->
    ?attributes:bool ->
    ?scope:bool -> ?filter:bool -> ?extensions:bool -> Neturl.url -> bool
  val make_ldap_url :
    ?encoded:bool ->
    ?host:string ->
    ?addr:Unix.inet_addr ->
    ?port:int ->
    ?socksymbol:Netsockaddr.socksymbol ->
    ?dn:string ->
    ?attributes:string list ->
    ?scope:[ `Base | `One | `Sub ] ->
    ?filter:string ->
    ?extensions:(bool * string * string option) list -> unit -> Neturl.url
end
ocamlnet-4.1.2/doc/html-main/Netmcore_mutex.html0000644000175000017500000005066012731530352020273 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_mutex

Module Netmcore_mutex

module Netmcore_mutex: sig .. end
Mutexes


Mutexes are here defined as values that reside in shared heaps (Netmcore_heap), for example in the header field of Netmcore_array or somewhere else in heap-allocated data structures.

In order to ensure that the mutex is in the heap, the special function create must be used to initialize it there. As create requires a mutator as argument, this is only possible by calling create from the callback of Netmcore_heap.modify.

Mutexes are special values, and cannot be copied or moved.

Mutexes are implemented on top of semaphores. For mutex types with deadlock handling, the process is considered as the owner, and process ID is the identifier.

Only mutexes of type `Normal are thread-safe, i.e. can be used when the worker processes also use threads internally.

type mutex_type = [ `Errorcheck | `Normal | `Recursive ] 
Types:
  • `Normal mutexes have no checks for deadlocks.
  • `Errorcheck mutexes check whether the process locks the mutex again, and fail in this case. Also, only the owning process can unlock a mutex.
  • `Recursive mutexes allow that the owner locks several times. The same number of unlock requests need to be issued to give up the ownership

type mutex 
val dummy : unit -> mutex
A dummy mutex is non-functional, but can be used to put something into mutex-typed variables
val create : Netmcore_heap.mutator -> mutex_type -> mutex
create m t: Creates a mutex of type t, and pushes it to the heap, using the mutator m.

After being pushed to the heap, the mutex can be used. It is nonsense to copy it outside the heap.

val lock : mutex -> unit
Locks the mutex
val unlock : mutex -> unit
Unlocks the mutex
val destroy : mutex -> unit
Destroys the mutex
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.timeout_engine.html0000644000175000017500000004127112731530352025006 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.timeout_engine float -> exn -> 'Uq_engines_compat.engine -> ['a] Uq_engines_compat.engineocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.pseudo_async_in_channel.html0000644000175000017500000004106012731530352026641 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.pseudo_async_in_channel #Netchannels.raw_in_channel -> Uq_engines_compat.async_in_channelocamlnet-4.1.2/doc/html-main/Netnumber.ENCDEC.html0000644000175000017500000006376512731530352020166 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber.ENCDEC

Module type Netnumber.ENCDEC

module type ENCDEC = sig .. end


Encode/decode numbers as strings. These functions exist in two flavors:
val read_int4 : Bytes.t -> int -> Netnumber.int4
val read_int8 : Bytes.t -> int -> Netnumber.int8
val read_uint4 : Bytes.t -> int -> Netnumber.uint4
val read_uint8 : Bytes.t -> int -> Netnumber.uint8
read_<t> create integer values from the characters found at a certain position in the string. Raises Out_of_range if the position is bad
val read_int4_unsafe : Bytes.t -> int -> Netnumber.int4
val read_int8_unsafe : Bytes.t -> int -> Netnumber.int8
val read_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4
val read_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8
Same, but no index check
val read_string_int4 : string -> int -> Netnumber.int4
val read_string_int8 : string -> int -> Netnumber.int8
val read_string_uint4 : string -> int -> Netnumber.uint4
val read_string_uint8 : string -> int -> Netnumber.uint8
val read_string_int4_unsafe : string -> int -> Netnumber.int4
val read_string_int8_unsafe : string -> int -> Netnumber.int8
val read_string_uint4_unsafe : string -> int -> Netnumber.uint4
val read_string_uint8_unsafe : string -> int -> Netnumber.uint8
For immutable strings
val write_int4 : Bytes.t -> int -> Netnumber.int4 -> unit
val write_int8 : Bytes.t -> int -> Netnumber.int8 -> unit
val write_uint4 : Bytes.t -> int -> Netnumber.uint4 -> unit
val write_uint8 : Bytes.t -> int -> Netnumber.uint8 -> unit
write_<t> copies the characters corresponding to the integer values into the string at the given positions. Raises Out_of_range if the position is bad.
val write_int4_unsafe : Bytes.t -> int -> Netnumber.int4 -> unit
val write_int8_unsafe : Bytes.t -> int -> Netnumber.int8 -> unit
val write_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4 -> unit
val write_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8 -> unit
write_<t>_unsafe: Same, but no index check.
val int4_as_bytes : Netnumber.int4 -> Bytes.t
val int8_as_bytes : Netnumber.int8 -> Bytes.t
val uint4_as_bytes : Netnumber.uint4 -> Bytes.t
val uint8_as_bytes : Netnumber.uint8 -> Bytes.t
<t>_as_bytes: Returns the corresponding bytes for an integer value
val int4_as_string : Netnumber.int4 -> string
val int8_as_string : Netnumber.int8 -> string
val uint4_as_string : Netnumber.uint4 -> string
val uint8_as_string : Netnumber.uint8 -> string
<t>_as_string: Returns the corresponding string for an integer value
val write_fp4 : Bytes.t -> int -> Netnumber.fp4 -> unit
val write_fp8 : Bytes.t -> int -> Netnumber.fp8 -> unit
val fp4_as_string : Netnumber.fp4 -> string
val fp8_as_string : Netnumber.fp8 -> string
val fp4_as_bytes : Netnumber.fp4 -> Bytes.t
val fp8_as_bytes : Netnumber.fp8 -> Bytes.t
val read_fp4 : Bytes.t -> int -> Netnumber.fp4
val read_fp8 : Bytes.t -> int -> Netnumber.fp8
val read_string_fp4 : string -> int -> Netnumber.fp4
val read_string_fp8 : string -> int -> Netnumber.fp8
ocamlnet-4.1.2/doc/html-main/Nettls_gnutls.html0000644000175000017500000005170212731530352020140 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls

Module Nettls_gnutls

module Nettls_gnutls: sig .. end
GnuTLS


OPAM users: Note that the OPAM package for OCamlnet does not build with GnuTLS support by default. The trigger for this is the presence of the conf-gnutls OPAM package, i.e. do opam install conf-gnutls to include the nettls-gnutls library in a rebuild.
module type GNUTLS_PROVIDER = sig .. end
module type GNUTLS_ENDPOINT = sig .. end
val make_tls : (module Netsys_crypto_types.TLS_EXCEPTIONS) ->
(module Nettls_gnutls.GNUTLS_PROVIDER)
The implementation of TLS backed by GnuTLS, here for an arbitrary TLS_EXCEPTIONS module
module GNUTLS: GNUTLS_PROVIDER 
The implementation of TLS backed by GnuTLS, here using Netsys_types as TLS_EXCEPTIONS module
module TLS: Netsys_crypto_types.TLS_PROVIDER 
Same as GNUTLS, but without the extra gnutls_* functions
val gnutls : (module Nettls_gnutls.GNUTLS_PROVIDER)
The implementation of TLS backed by GnuTLS, as value
val tls : (module Netsys_crypto_types.TLS_PROVIDER)
The implementation of TLS backed by GnuTLS, as value
val endpoint : GNUTLS.endpoint -> (module Nettls_gnutls.GNUTLS_ENDPOINT)
Wraps an endpoint
val downcast : (module Netsys_crypto_types.TLS_PROVIDER) ->
(module Nettls_gnutls.GNUTLS_PROVIDER)
Attempts a downcast, or raises Not_found
val downcast_endpoint : (module Netsys_crypto_types.TLS_ENDPOINT) ->
(module Nettls_gnutls.GNUTLS_ENDPOINT)
Attempts a downcast, or raises Not_found
module Symmetric_crypto: Netsys_crypto_types.SYMMETRIC_CRYPTO 
Symmetric cryptography as provided by GnuTLS and its helper library Nettle
module Digests: Netsys_crypto_types.DIGESTS 
Cryptographic digests
val init : unit -> unit
Ensure that GnuTLS is initialized
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.error_response_params.html0000644000175000017500000004303312731530352025761 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.error_response_params object
  method cgi_properties : (string * string) list
  method error_message : string
  method input_body_size : int64
  method input_header : Nethttp.http_header
  method remote_socket_addr : Unix.sockaddr
  method request_method : string
  method request_uri : string
  method response_status_code : int
  method server_socket_addr : Unix.sockaddr
  method tls_session_props : Nettls_support.tls_session_props option
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.SCRAM_SHA256_PLUS.html0000644000175000017500000004067312731530352024572 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM_SHA256_PLUS Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/type_Netmech_gs2_sasl.html0000644000175000017500000005055412731530352021520 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_gs2_sasl sig
  module type PROFILE =
    sig
      val mechanism_name : string
      val announce_channel_binding : bool
      val mechanism_oid : Netsys_gssapi.oid
      val client_additional_params : string list
      val server_additional_params : string list
      val client_map_user_name :
        params:(string * string) list -> string -> string * Netsys_gssapi.oid
      val server_map_user_name :
        params:(string * string) list -> string * Netsys_gssapi.oid -> string
      val client_get_target_name :
        params:(string * string) list -> string * Netsys_gssapi.oid
      val server_bind_target_name :
        params:(string * string) list -> (string * Netsys_gssapi.oid) option
      val server_check_target_name :
        params:(string * string) list -> string * Netsys_gssapi.oid -> bool
      val client_flags :
        params:(string * string) list -> (Netsys_gssapi.req_flag * bool) list
      val server_flags :
        params:(string * string) list -> Netsys_gssapi.req_flag list
      val client_credential : exn option
    end
  module GS2 :
    functor (P : PROFILE) (GSS : Netsys_gssapi.GSSAPI->
      Netsys_sasl_types.SASL_MECHANISM
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.pipeline.html0000644000175000017500000005606512731530352023133 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.pipeline object
  method add : Nethttp_client.http_call -> unit
  method add_auth_handler : Nethttp_client.auth_handler -> unit
  method add_e :
    Nethttp_client.http_call -> Nethttp_client.http_call Uq_engines.engine
  method add_with_callback :
    Nethttp_client.http_call -> (Nethttp_client.http_call -> unit) -> unit
  method avoid_proxy_for : string list -> unit
  method cnt_crashed_connections : int
  method cnt_failed_connections : int
  method cnt_new_connections : int
  method cnt_server_eof_connections : int
  method cnt_successful_connections : int
  method cnt_timed_out_connections : int
  method configure_transport :
    Nethttp_client.transport_layer_id ->
    Nethttp_client.transport_channel_type -> unit
  method connection_cache : Nethttp_client.connection_cache
  method connections : (string * int * int) list
  method event_system : Unixqueue.event_system
  method get_options : Nethttp_client.http_options
  method number_of_open_connections : int
  method number_of_open_messages : int
  method proxy_type : string -> Nethttp_client.proxy_type option
  method proxy_type_of_call :
    Nethttp_client.http_call -> Nethttp_client.proxy_type option
  method reset : unit -> unit
  method reset_counters : unit -> unit
  method run : unit -> unit
  method set_connection_cache : Nethttp_client.connection_cache -> unit
  method set_event_system : Unixqueue.event_system -> unit
  method set_options : Nethttp_client.http_options -> unit
  method set_proxy : string -> int -> unit
  method set_proxy_auth : insecure:bool -> string -> string -> unit
  method set_proxy_from_environment : insecure:bool -> unit -> unit
  method set_socks5_proxy : string -> int -> unit
  method set_tls_cache : Nethttp_client.tls_cache -> unit
  method set_transport_proxy :
    Nethttp_client.transport_layer_id ->
    string ->
    int ->
    (string * string * bool) option -> Nethttp_client.proxy_type -> unit
  method set_transport_proxy_from_environment :
    insecure:bool ->
    (string * Nethttp_client.transport_layer_id) list -> unit
  method transport_layer :
    Nethttp_client.http_call -> Nethttp_client.transport_layer_id
end
ocamlnet-4.1.2/doc/html-main/Netplex_types.workload_manager_factory-c.html0000644000175000017500000004343312731530352025422 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.workload_manager_factory

Class type Netplex_types.workload_manager_factory

class type workload_manager_factory = object .. end

method name : string
method create_workload_manager : controller_config ->
config_file ->
address -> workload_manager
ocamlnet-4.1.2/doc/html-main/type_Rpc_mapping_ref.html0000644000175000017500000004062012731530352021424 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_mapping_ref sig  endocamlnet-4.1.2/doc/html-main/type_Rpc_transport.rpc_multiplex_controller.html0000644000175000017500000005050112731530352026321 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_transport.rpc_multiplex_controller object
  method abort_rw : unit -> unit
  method alive : bool
  method cancel_rd_polling : unit -> unit
  method cancel_shutting_down : unit -> unit
  method event_system : Unixqueue.event_system
  method file_descr : Unix.file_descr option
  method getpeername : Rpc_transport.sockaddr
  method getsockname : Rpc_transport.sockaddr
  method inactivate : unit -> unit
  method peer_user_name : string option
  method protocol : Rpc.protocol
  method read_eof : bool
  method reading : bool
  method set_timeout : notify:(unit -> unit) -> float -> unit
  method start_reading :
    ?peek:(unit -> unit) ->
    ?before_record:(int -> Rpc_transport.sockaddr -> Rpc_transport.in_rule) ->
    when_done:((Rpc_transport.in_record * Rpc_transport.sockaddr)
               Rpc_transport.result_eof -> unit) ->
    unit -> unit
  method start_shutting_down :
    when_done:(unit Rpc_transport.result -> unit) -> unit -> unit
  method start_writing :
    when_done:(unit Rpc_transport.result -> unit) ->
    Rpc_packer.packed_value -> Rpc_transport.sockaddr -> unit
  method tls_session_props : Nettls_support.tls_session_props option
  method writing : bool
end
ocamlnet-4.1.2/doc/html-main/Netsys_gssapi.server_config-c.html0000644000175000017500000004441712731530352023205 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.server_config

Class type Netsys_gssapi.server_config

class type server_config = object .. end

method mech_types : oid list
method acceptor_name : (string * oid) option
method privacy : support_level
method integrity : support_level
method flags : (req_flag * support_level) list
ocamlnet-4.1.2/doc/html-main/Netpop.Debug.html0000644000175000017500000004223312731530352017564 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpop.Debug

Module Netpop.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module By default, the exchanged Telnet commands are logged. This can be extended by setting the verbose_input and verbose_output options.
ocamlnet-4.1.2/doc/html-main/type_Uq_libevent.Make.html0000644000175000017500000004104412731530352021463 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_libevent.Make functor (L : LIBOEVENT-> POLLSETocamlnet-4.1.2/doc/html-main/type_Uq_engines.async_out_channel.html0000644000175000017500000004246012731530352024125 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.async_out_channel object
  method can_output : bool
  method close_out : unit -> unit
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method pos_out : int
  method request_notification : (unit -> bool) -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netmime_channels.html0000644000175000017500000005071512731530352021610 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime_channels sig
  val read_mime_header :
    ?unfold:bool ->
    ?strip:bool -> ?ro:bool -> Netstream.in_obj_stream -> Netmime.mime_header
  type multipart_style = [ `Deep | `Flat | `None ]
  val decode_mime_body :
    #Netmime.mime_header_ro ->
    Netchannels.out_obj_channel -> Netchannels.out_obj_channel
  val storage :
    ?fin:bool ->
    Netmime.store -> Netmime.mime_body * Netchannels.out_obj_channel
  val read_mime_message :
    ?unfold:bool ->
    ?strip:bool ->
    ?ro:bool ->
    ?multipart_style:Netmime_channels.multipart_style ->
    ?storage_style:(Netmime.mime_header ->
                    Netmime.mime_body * Netchannels.out_obj_channel) ->
    Netstream.in_obj_stream -> Netmime.complex_mime_message
  val encode_mime_body :
    ?crlf:bool ->
    #Netmime.mime_header_ro ->
    Netchannels.out_obj_channel -> Netchannels.out_obj_channel
  val write_mime_message :
    ?wr_header:bool ->
    ?wr_body:bool ->
    ?nr:int ->
    ?ret_boundary:string Pervasives.ref ->
    ?crlf:bool ->
    Netchannels.out_obj_channel -> Netmime.complex_mime_message -> unit
end
ocamlnet-4.1.2/doc/html-main/Netcgi.cgi-c.html0000644000175000017500000007620612731530352017473 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.cgi

Class type Netcgi.cgi

class type cgi = object .. end
Object symbolizing a CGI-like request/response cycle.

This is the minimal set of services a connector must provide. Additional methods may be defined for specific connectors.


Arguments -- data sent to the script

method argument : string -> cgi_argument
#argument name returns the value of the argument named name. If the argument appears several times, only one of its instances is used.
Raises Not_found if no such argument exists.
method argument_value : ?default:string -> string -> string
#argument_value returns the value of the argument as a string. If the argument does not exist, the default is returned.
default : defaults to "".
method argument_exists : string -> bool
#argument_exists returns false if the named parameter is missing and true otherwise.
method multiple_argument : string -> cgi_argument list
#multiple_argument name returns all the values of the argument named name.
method arguments : cgi_argument list
The complete list of arguments.
method environment : cgi_environment
The environment object. This object is the "outer layer" of the activation object that connects it with real I/O channels.
method request_method : [ `DELETE | `GET | `HEAD | `POST | `PUT of cgi_argument ]
The HTTP method used to make the request.
method finalize : unit -> unit
This method calls #finalize for every CGI argument (including the possible one of PUT) to ensure that all files are deleted. It also executes all functions registered with #at_exit. It does not close the in/out channels, however. This method is not registered in the garbage collector, and it is a bad idea to do so. However, all connectors offered in Netcgi automatically call #finalize at the end of the request cycle (even when its terminated by an uncaught exception when #config.default_exn_handler is true) so you do not have to worry much about calling it yourself.
method url : ?protocol:Nethttp.protocol ->
?with_authority:other_url_spec ->
?with_script_name:other_url_spec ->
?with_path_info:other_url_spec ->
?with_query_string:query_string_spec -> unit -> string
Returns the URL of the current CGI-like script. (Note that it may differ from the actual URL that requested the script if, for example, rewriting rules were specified in the web server configuration.)
protocol : The URL scheme. By default, the URL scheme is used that is described in the environment
with_authority : Whether to include authority part (e.g. http or https) of the URL, and if yes, from which source. Default: `Env.
with_script_name : Whether to include the part of the URL path identifying the CGI script, and if yes, from which source. Default: `Env.
with_path_info : Whether to include the rest of the URL path exceeding the script name, and if yes, from which source. Default: `Env.
with_query_string : Whether to include a query string, and if yes, which one. Only arguments with #store being `Memory will be added. Default: `None, i.e. no query string.
method set_header : ?status:Nethttp.http_status ->
?content_type:string ->
?content_length:int ->
?set_cookie:Nethttp.cookie list ->
?set_cookies:Cookie.t list ->
?cache:cache_control ->
?filename:string ->
?language:string ->
?script_type:string ->
?style_type:string -> ?fields:(string * string list) list -> unit -> unit
Sets the header (removing any previous one). When the output channel supports transactions, it is possible to set the header (possibly several times) until the #out_channel is commited for the first time or #env#send_output_header() is called. When there is no support for transactions, the header must be set before the first byte of output is written.

If #set_header is called a second time, it will overwrite all the header fields.

status : Sets the HTTP status of the reply according to RFC 2616. Defaults to "no status", but the server normally complements an `Ok status in this case.
content_type : Sets the content type. Defaults to "text/html".
content_length : Sets the content length (in bytes). Default: No such field.
set_cookie : Deprecated, use set_cookies.
set_cookies : Sets a number of cookies. Default: []. Remember that the browser may not support more than 20 cookies per web server. You can query the cookies using env#cookies and env#cookie. If you set cookies, you want to think about an appropriate cache setting. You may also want to add a P3P header (Platform for Privacy Preferences) -- otherwise your cookies may be discarded by some browsers.
cache : Sets the cache behavior for replies to GET requests. The default is `Unspecified. It is strongly recommended to specify the caching behaviour!!! You are on the safe side with `No_cache, forcing every page to be regenerated. If your data do not change frequently, `Max_age n tells the caches to store the data at most n seconds.
filename : Sets the filename associated with the page. This filename is taken for the "save as..." dialog. Default: "", i.e. no filename. Note: It is bad practice if the filename contains problematic characters (backslash, double quote, space), or the names of directories. It is recommended that you set content_type to "application/octet-stream" for this feture to work with most browsers and, if possible, to set content_length because that usually improves the download dialog.)
script_type : Sets the language of the script tag (for HTML replies). It is recommended to use this field if there are ONXXX attributes containing scripts before the first <SCRIPT> element, because you cannot specify the script language for the ONXXX attributes otherwise. script_type must be a media type, e.g. "text/javascript". Default: no language is specified.
style_type : Sets the language of the style tag (for HTML replies). It is recommended to use this field if there are STYLE attributes containing scripts before the first <STYLE> element, because you cannot specify the style language for the STYLE attributes otherwise. style_type must be a media type, e.g. "text/css". Default: no language is specified.
fields : Sets additional fields of the header. Default: [].
method set_redirection_header : ?set_cookies:Cookie.t list ->
?fields:(string * string list) list -> string -> unit
Sets the header such that a redirection to the specified URL is performed. If the URL begins with "http:" the redirection directive is passed back to the client, and the client will repeat the request for the new location (with a GET method). If the URL begins with "/", the server performs the redirection, and it is invisible for the client.
method output : Netchannels.trans_out_obj_channel
Deprecated.Use #out_channel instead.
method out_channel : Netchannels.trans_out_obj_channel
The output channel to which the generated content is intended to be written. The header is not stored in this channel, so #pos_out returns the size of the DATA in bytes (useful to set Content-Length). Note that HEAD requests must not send back a message body so, in this case, all data sent to this channel is discarded. This allows your scripts to work unmodified for GET, POST and HEAD requests.

The output channel may have transactional semantics, and because of this, it is an trans_out_obj_channel. Implementations are free to support transactions or not.

After all data have been written, the method #commit_work() must be called, even if there is no support for transactions.

Simple Example:

        cgi # out_channel # output_string "Hello world!\n";
        cgi # out_channel # commit_work()
        

Example for an error handler and a transaction buffer: If an error happens, it is possible to roll the channel back, and to write the error message.

        try
          cgi # set_header ... ();
          cgi # out_channel # output_string "Hello World!"; ...
          cgi # out_channel # commit_work();
        with err ->
          cgi # out_channel # rollback_work();
          cgi # set_header ... ();
          cgi # out_channel # output_string "Software error!"; ...
          cgi # out_channel # commit_work();
        

method at_exit : (unit -> unit) -> unit
#at_exit f registers the function f to be executed when #finalize is called (which is done automatically when the request finishes). The functions are executed in the reverse order in which they were registered.
ocamlnet-4.1.2/doc/html-main/type_Netdn.DN_string.html0000644000175000017500000004131012731530352021264 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdn.DN_string sig val parse : string -> Netdn.dn val print : Netdn.dn -> string endocamlnet-4.1.2/doc/html-main/type_Netstring_tstring.html0000644000175000017500000006546112731530352022072 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstring_tstring sig
  type _ tstring_kind =
      String_kind : string Netstring_tstring.tstring_kind
    | Bytes_kind : Bytes.t Netstring_tstring.tstring_kind
    | Memory_kind : Netsys_types.memory Netstring_tstring.tstring_kind
  type 't tstring_ops = {
    kind : 'Netstring_tstring.tstring_kind option;
    length : '-> int;
    get : '-> int -> char;
    unsafe_get : '-> int -> char;
    unsafe_get3 : '-> int -> int;
    copy : '-> 't;
    string : '-> string;
    bytes : '-> Bytes.t;
    sub : '-> int -> int -> 't;
    substring : '-> int -> int -> string;
    subbytes : '-> int -> int -> Bytes.t;
    subpoly : 'u. 'Netstring_tstring.tstring_kind -> '-> int -> int -> 'u;
    blit_to_bytes : '-> int -> Bytes.t -> int -> int -> unit;
    blit_to_memory : '-> int -> Netsys_types.memory -> int -> int -> unit;
    index_from : '-> int -> char -> int;
    index_from3 : '-> int -> int -> char -> char -> char -> int;
    rindex_from : '-> int -> char -> int;
    rindex_from3 : '-> int -> int -> char -> char -> char -> int;
  }
  type tstring_ops_box =
      Tstring_ops_box : 'Netstring_tstring.tstring_kind *
        'Netstring_tstring.tstring_ops -> Netstring_tstring.tstring_ops_box
  type tstring_box =
      Tstring_box : 'Netstring_tstring.tstring_kind *
        'Netstring_tstring.tstring_ops *
        '-> Netstring_tstring.tstring_box
  type tstring_polybox =
      Tstring_polybox : 'Netstring_tstring.tstring_ops *
        '-> Netstring_tstring.tstring_polybox
  val string_ops : string Netstring_tstring.tstring_ops
  val bytes_ops : Bytes.t Netstring_tstring.tstring_ops
  val memory_ops : Netsys_types.memory Netstring_tstring.tstring_ops
  val ops_of_tstring :
    Netsys_types.tstring -> Netstring_tstring.tstring_ops_box
  type 'a with_fun = {
    with_fun : 's. 'Netstring_tstring.tstring_ops -> '-> 'a;
  }
  val with_tstring :
    'Netstring_tstring.with_fun -> Netsys_types.tstring -> 'a
  val length_tstring : Netsys_types.tstring -> int
  val tstring_of_tbuffer : Netsys_types.tbuffer -> Netsys_types.tstring
  val polymorph_string_transformation :
    (string -> string) ->
    'Netstring_tstring.tstring_ops ->
    'Netstring_tstring.tstring_kind -> '-> 't
  val bytes_subpoly :
    'Netstring_tstring.tstring_kind -> Bytes.t -> int -> int -> 'u
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.get.html0000644000175000017500000004067012731530352022100 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.get string -> Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Netchannels.input_bytes-c.html0000644000175000017500000004233512731530352022323 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_bytes

Class Netchannels.input_bytes

class input_bytes : ?pos:int -> ?len:int -> Bytes.t -> in_obj_channel
Same for constant bytes

ocamlnet-4.1.2/doc/html-main/Netmech_spnego_http.Default.html0000644000175000017500000004562512731530352022662 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_spnego_http.Default

Module Netmech_spnego_http.Default

module Default: PROFILE 
The default profile for Netmech_spnego_http: Use spnego_trans_id for the https transport, and reject any unencrypted transport (empty list). Delegations are off.

val acceptable_transports_http : Nethttp.transport_layer_id list
Which transport IDs are acceptable for authenticated requests on unencrypted connections. For new requests, the first ID of this list is the preferred ID.
val acceptable_transports_https : Nethttp.transport_layer_id list
Which transport IDs are acceptable for authenticated requests on HTTPS-secured connections. For new requests, the first ID of this list is the preferred ID.
val enable_delegation : bool
Whether to allow delegation of the credentials to the server. Enabling this means that the server can impersonate the local identity, so use with care. Also, getting tokens carrying the delegation information can be time-consuming (and the HTTP client will simply block while doing so).
val deleg_credential : exn option
If you already have a credential, you can set this value to the exception Credential c (from the GSSAPI provider).
ocamlnet-4.1.2/doc/html-main/type_Netchannels.input_filter.html0000644000175000017500000004114112731530352023275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_filter Netchannels.in_obj_channel ->
Netchannels.io_obj_channel -> Netchannels.in_obj_channel
ocamlnet-4.1.2/doc/html-main/type_Netdn.AT_LOOKUP.html0000644000175000017500000004205312731530352020777 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdn.AT_LOOKUP sig
  val attribute_types : (Netdn.oid * string * string list) list
  val lookup_attribute_type_by_oid : Netdn.oid -> string * string list
  val lookup_attribute_type_by_name :
    string -> Netdn.oid * string * string list
end
ocamlnet-4.1.2/doc/html-main/type_Netaddress.group.html0000644000175000017500000004137312731530352021566 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaddress.group string ->
Netaddress.mailbox list ->
object method mailboxes : Netaddress.mailbox list method name : string end
ocamlnet-4.1.2/doc/html-main/Netmime.wrap_mime_header_ro-c.html0000644000175000017500000004253612731530352023105 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.wrap_mime_header_ro

Class Netmime.wrap_mime_header_ro

class wrap_mime_header_ro : #mime_header_ro -> mime_header
Wraps the inner header but disallows modifications. In this case, Immutable is raised.

ocamlnet-4.1.2/doc/html-main/type_Netchannels.output_buffer.html0000644000175000017500000004113412731530352023464 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_buffer ?onclose:(unit -> unit) -> Buffer.t -> Netchannels.out_obj_channelocamlnet-4.1.2/doc/html-main/type_Uq_engines.fmap_engine.html0000644000175000017500000004157312731530352022705 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.fmap_engine '#Uq_engines.engine ->
('Uq_engines.final_state -> 'Uq_engines.final_state) ->
['b] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/Netx509_pubkey.Keyagreement.html0000644000175000017500000004617512731530352022455 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey.Keyagreement

Module Netx509_pubkey.Keyagreement

module Keyagreement: sig .. end

val dh : Netx509_pubkey.kex_alg
DH
val ec : Netx509_pubkey.kex_alg
ECDH using unrestricted keys
val ecdh : Netx509_pubkey.kex_alg
ECDH
val ecmqv : Netx509_pubkey.kex_alg
ECMQV
val kea : Netx509_pubkey.kex_alg
KEA
val catalog : (string * string list * Netx509_pubkey.kex_alg * Netx509_pubkey.oid) list
(name, aliases, oid, pubkey_oid)
val alg_id_of_kex_alg : Netx509_pubkey.kex_alg -> Netx509_pubkey.alg_id
Get the alg_id of a key agreement alg
val key_oid_of_kex_alg : Netx509_pubkey.kex_alg -> Netx509_pubkey.oid
The OID public keys need to have
ocamlnet-4.1.2/doc/html-main/type_Netpop.html0000644000175000017500000006042212731530352017600 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpop sig
  type state = [ `Authorization | `Transaction | `Update ]
  exception Protocol_error
  exception Authentication_error
  exception Err_status of string
  exception Bad_state
  val tcp_port : int
  class client :
    Netchannels.in_obj_channel ->
    Netchannels.out_obj_channel ->
    object
      method apop : user:string -> pass:string -> unit
      method auth :
        Netsys_sasl.sasl_mechanism ->
        string ->
        string ->
        Netsys_sasl.credentials -> (string * string * bool) list -> unit
      method capa : unit -> (string * string list) list
      method capabilities : (string * string list) list
      method close : unit -> unit
      method dele : msgno:int -> unit
      method gssapi_props : Netsys_gssapi.client_props option
      method list : ?msgno:int -> unit -> (int, int * string) Hashtbl.t
      method noop : unit -> unit
      method pass : pass:string -> unit
      method quit : unit -> unit
      method retr : msgno:int -> Netchannels.in_obj_channel
      method rset : unit -> unit
      method stat : unit -> int * int * string
      method state : Netpop.state
      method stls :
        peer_name:string option -> Netsys_crypto_types.tls_config -> unit
      method tls_endpoint : Netsys_crypto_types.tls_endpoint option
      method tls_session_props : Nettls_support.tls_session_props option
      method top :
        ?lines:int -> msgno:int -> unit -> Netchannels.in_obj_channel
      method uidl : ?msgno:int -> unit -> (int, string) Hashtbl.t
      method user : user:string -> unit
    end
  class connect :
    ?proxy:#Uq_engines.client_endpoint_connector ->
    Uq_engines.connect_address -> float -> client
  val authenticate :
    ?tls_config:Netsys_crypto_types.tls_config ->
    ?tls_required:bool ->
    ?tls_peer:string ->
    ?sasl_mechs:Netsys_sasl.sasl_mechanism list ->
    ?sasl_params:(string * string * bool) list ->
    ?user:string ->
    ?authz:string -> ?creds:Netsys_sasl.credentials -> Netpop.client -> unit
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_digest_http.html0000644000175000017500000004332512731530352022317 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http sig
  module Digest : Nethttp.HTTP_CLIENT_MECHANISM
  module Digest_mutual : Nethttp.HTTP_CLIENT_MECHANISM
  module type PROFILE =
    sig
      val mutual : bool
      val hash_functions : Netsys_digests.iana_hash_fn list
    end
  module Make_digest : functor (P : PROFILE-> Nethttp.HTTP_CLIENT_MECHANISM
end
ocamlnet-4.1.2/doc/html-main/type_Netldap.ldap_result.html0000644000175000017500000004200012731530352022227 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netldap.ldap_result object
  method code : Netldap.result_code
  method diag_msg : string
  method matched_dn : string
  method partial_value : 'a
  method referral : string list
  method value : 'a
end
ocamlnet-4.1.2/doc/html-main/Netchannels.raw_io_channel-c.html0000644000175000017500000004305212731530352022723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_io_channel

Class type Netchannels.raw_io_channel

class type raw_io_channel = object .. end
A channel supporting both input and output. The input and output aspects are strictly separated
Inherits
ocamlnet-4.1.2/doc/html-main/type_Netcgi.Cookie.html0000644000175000017500000005375412731530352020766 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.Cookie sig
  type t = Nethttp.Cookie.t
  val make :
    ?max_age:int ->
    ?domain:string ->
    ?path:string ->
    ?secure:bool ->
    ?comment:string ->
    ?comment_url:string ->
    ?ports:int list -> string -> string -> Netcgi.Cookie.t
  val name : Netcgi.Cookie.t -> string
  val value : Netcgi.Cookie.t -> string
  val domain : Netcgi.Cookie.t -> string option
  val path : Netcgi.Cookie.t -> string option
  val ports : Netcgi.Cookie.t -> int list option
  val max_age : Netcgi.Cookie.t -> int option
  val secure : Netcgi.Cookie.t -> bool
  val comment : Netcgi.Cookie.t -> string
  val comment_url : Netcgi.Cookie.t -> string
  val set_value : Netcgi.Cookie.t -> string -> unit
  val set_max_age : Netcgi.Cookie.t -> int option -> unit
  val set_domain : Netcgi.Cookie.t -> string option -> unit
  val set_path : Netcgi.Cookie.t -> string option -> unit
  val set_secure : Netcgi.Cookie.t -> bool -> unit
  val set_comment : Netcgi.Cookie.t -> string -> unit
  val set_comment_url : Netcgi.Cookie.t -> string -> unit
  val set_ports : Netcgi.Cookie.t -> int list option -> unit
  val of_netscape_cookie : Nethttp.netscape_cookie -> Netcgi.Cookie.t
  val to_netscape_cookie : Netcgi.Cookie.t -> Nethttp.netscape_cookie
end
ocamlnet-4.1.2/doc/html-main/Netcgi_modtpl.template-c.html0000644000175000017500000004621412731530352022117 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_modtpl.template

Class Netcgi_modtpl.template

class template : ?filename:string -> string -> object .. end
new template ?filename tpl computes a new template from the string tpl. Once the object has been created, it can be used in a single thread.
filename : if set, it is used to determine the base path for ::include():: tags in the template (default: current directory) and to reuse the templates of already compiled files (e.g. headers, footers,...).

method set : string -> string -> unit
Set a variable in the template.
method table : string -> table_row list -> unit
Set a table in the template.
method conditional : string -> bool -> unit
Set a conditional in the template.
method callback : string -> (string list -> string) -> unit
Set a callback in the template.
method to_string : string
Return the template as a string.
method to_channel : Pervasives.out_channel -> unit
Write the template to a channel.
method output : Netcgi.cgi -> unit
output cgi outputs the template to the CGI session cgi.
method source : string
Return the original source code for the template.
ocamlnet-4.1.2/doc/html-main/Netchannels.trans_out_obj_channel-c.html0000644000175000017500000004444712731530352024324 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.trans_out_obj_channel

Class type Netchannels.trans_out_obj_channel

class type trans_out_obj_channel = object .. end
A transactional output channel has a buffer for uncommitted data. This means that all data written to this channel is collected in the buffer until either commit_work or rollback_work is called.

When the channel is closed, the buffer may optionally be committed. This is implementation-defined.

The method flush does not have any effect on the transaction buffer.

Inherits
method commit_work : unit -> unit
Flushes the transaction buffer, and writes its contents to the underlying resource.
method rollback_work : unit -> unit
Empties the transaction buffer
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.request_info.html0000644000175000017500000004253212731530352024055 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.request_info object
  method cgi_properties : (string * string) list
  method input_body_size : int64
  method input_header : Nethttp.http_header
  method remote_socket_addr : Unix.sockaddr
  method request_method : string
  method request_uri : string
  method server_socket_addr : Unix.sockaddr
  method tls_session_props : Nettls_support.tls_session_props option
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_engine.http_engine_processing_config-c.html0000644000175000017500000005127512731530352026723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_engine_processing_config

Class type Nethttpd_engine.http_engine_processing_config

class type http_engine_processing_config = object .. end

method config_synch_input : (Netchannels.in_obj_channel -> unit) -> Uq_engines.async_in_channel -> unit
The "input synchronizer": It is called as obj # config_synch_input f ch to create a synchronous input channel from an asynchronous one, ch. The function f must be called back by the synchronizer when synchronisation is established, and with the synchronous channel ch' as argument. In particular, the task of the synchronizer is to turn blocking reads of ch' into non-blocking reads of ch. In general there are two ways of implementation:
  • Buffer all input from ch until the end of the channel is reached, then call f with a wrapper channel ch' that just reads from the buffer.
  • Run f in a different thread that blocks whenever there is nothing to read from ch.
Both implementations are allowed, i.e. it is allowed that f runs in a different thread.

CHECK: How to handle exceptions raised from f? Idea: f is obliged to close ch' in this case, even if ch is not yet at the end. The rest of exception handling is up to the user. - The complementary must also be true: When there is an error in the engine, ch must be closed to signal the other thread that we have a problem.

method config_synch_output : (Netchannels.out_obj_channel -> unit) -> Uq_engines.async_out_channel -> unit
The "output synchronizer": It is called as obj # config_synch_output f ch to create a synchronous output channel from an asynchronous one, ch. The function f must be called back by the synchronizer when synchronisation is established, and with the synchronous channel ch' as argument. In particular, the task of the synchronizer is to turn blocking writes to ch' into non-blocking writes to ch. In general there are two ways of implementation:
  • Call f, then buffer all output to ch' until the end of the channel is reached, and finally output the contents of the buffer in an asynchronous way.
  • Run f in a different thread that blocks whenever there is no space to write to ch.
Both implementations are allowed, i.e. it is allowed that f runs in a different thread.

CHECK: Exceptions.

ocamlnet-4.1.2/doc/html-main/type_Shell_sys.html0000644000175000017500000011521512731530352020301 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_sys sig
  exception Fatal_error of exn
  type environment
  val create_env : unit -> Shell_sys.environment
  val current_env : unit -> Shell_sys.environment
  val copy_env : Shell_sys.environment -> Shell_sys.environment
  val set_env : Shell_sys.environment -> string array -> unit
  val get_env : Shell_sys.environment -> string array
  val iter_env : f:(string -> unit) -> Shell_sys.environment -> unit
  val set_env_var : Shell_sys.environment -> string -> string -> unit
  val get_env_var : Shell_sys.environment -> string -> string
  val iter_env_vars :
    f:(string -> string -> unit) -> Shell_sys.environment -> unit
  type command
  val command :
    ?cmdname:string ->
    ?arguments:string array ->
    ?chdir:string ->
    ?environment:Shell_sys.environment ->
    ?descriptors:Unix.file_descr list ->
    ?assignments:(Unix.file_descr * Unix.file_descr) list ->
    filename:string -> unit -> Shell_sys.command
  exception Executable_not_found of string
  val lookup_executable : ?path:string list -> string -> string
  val get_cmdname : Shell_sys.command -> string
  val get_arguments : Shell_sys.command -> string array
  val get_chdir : Shell_sys.command -> string option
  val get_environment : Shell_sys.command -> Shell_sys.environment
  val get_descriptors : Shell_sys.command -> Unix.file_descr list
  val get_assignments :
    Shell_sys.command -> (Unix.file_descr * Unix.file_descr) list
  val get_filename : Shell_sys.command -> string
  val set_cmdname : Shell_sys.command -> string -> unit
  val set_arguments : Shell_sys.command -> string array -> unit
  val set_chdir : Shell_sys.command -> string option -> unit
  val set_environment : Shell_sys.command -> Shell_sys.environment -> unit
  val set_descriptors : Shell_sys.command -> Unix.file_descr list -> unit
  val set_assignments :
    Shell_sys.command -> (Unix.file_descr * Unix.file_descr) list -> unit
  val set_filename : Shell_sys.command -> string -> unit
  val copy_command : Shell_sys.command -> Shell_sys.command
  val is_executable : Shell_sys.command -> bool
  type process
  type group_action =
      New_bg_group
    | New_fg_group
    | Join_group of int
    | Current_group
  type fwd_mode = No_forward | Forward_to_process | Forward_to_group
  val run :
    ?group:Shell_sys.group_action ->
    ?forward_mode:Shell_sys.fwd_mode ->
    ?pipe_assignments:(Unix.file_descr * Unix.file_descr) list ->
    Shell_sys.command -> Shell_sys.process
  val process_id : Shell_sys.process -> int
  val status : Shell_sys.process -> Unix.process_status
  val command_of_process : Shell_sys.process -> Shell_sys.command
  val call : Shell_sys.command -> Shell_sys.process
  val kill : ?signal:int -> Shell_sys.process -> unit
  type job
  type job_instance
  val new_job : unit -> Shell_sys.job
  val add_command : Shell_sys.command -> Shell_sys.job -> unit
  val add_pipeline :
    ?bidirectional:bool ->
    ?src_descr:Unix.file_descr ->
    ?dest_descr:Unix.file_descr ->
    src:Shell_sys.command -> dest:Shell_sys.command -> Shell_sys.job -> unit
  val add_producer :
    ?descr:Unix.file_descr ->
    producer:(Unix.file_descr -> bool) ->
    Shell_sys.command -> Shell_sys.job -> unit
  val from_string :
    ?pos:int ->
    ?len:int -> ?epipe:(unit -> unit) -> string -> Unix.file_descr -> bool
  val from_tstring :
    ?pos:int ->
    ?len:int ->
    ?epipe:(unit -> unit) -> Netsys_types.tstring -> Unix.file_descr -> bool
  val from_stream :
    ?epipe:(unit -> unit) -> string Stream.t -> Unix.file_descr -> bool
  val add_consumer :
    ?descr:Unix.file_descr ->
    consumer:(Unix.file_descr -> bool) ->
    Shell_sys.command -> Shell_sys.job -> unit
  val to_buffer : Buffer.t -> Unix.file_descr -> bool
  val to_netbuffer : Netbuffer.t -> Unix.file_descr -> bool
  type group_mode = Same_as_caller | Foreground | Background
  val run_job :
    ?mode:Shell_sys.group_mode ->
    ?forward_signals:bool -> Shell_sys.job -> Shell_sys.job_instance
  class type ['t] job_handler_engine_type =
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method job : Shell_sys.job
      method job_instance : Shell_sys.job_instance
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        ('Uq_engines.engine -> bool) -> unit
      method state : 'Uq_engines.engine_state
    end
  class job_engine :
    Unixqueue.event_system ->
    Shell_sys.job_instance -> [unit] job_handler_engine_type
  val finish_job : Shell_sys.job_instance -> unit
  val call_job :
    ?mode:Shell_sys.group_mode ->
    ?forward_signals:bool ->
    ?onerror:(Shell_sys.job_instance -> unit) ->
    Shell_sys.job -> Shell_sys.job_instance
  val processes : Shell_sys.job_instance -> Shell_sys.process list
  exception No_Unix_process_group
  val process_group_leader : Shell_sys.job_instance -> Shell_sys.process
  val process_group_id : Shell_sys.job_instance -> int
  type job_status =
      Job_running
    | Job_partially_running
    | Job_ok
    | Job_error
    | Job_abandoned
  val job_status : Shell_sys.job_instance -> Shell_sys.job_status
  val kill_process_group : ?signal:int -> Shell_sys.job_instance -> unit
  val kill_processes : ?signal:int -> Shell_sys.job_instance -> unit
  val cancel_job : ?signal:int -> Shell_sys.job_instance -> unit
  val abandon_job : ?signal:int -> Shell_sys.job_instance -> unit
  exception Already_installed
  val configure_job_handlers :
    ?catch_sigint:bool ->
    ?catch_sigquit:bool ->
    ?catch_sigterm:bool ->
    ?catch_sighup:bool -> ?at_exit:bool -> unit -> unit
  val install_job_handlers : unit -> unit
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_fs.http_fs.html0000644000175000017500000004207712731530352022125 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_fs.http_fs ?config_pipeline:(Nethttp_client.pipeline -> unit) ->
?streaming:bool ->
?tmp_directory:string ->
?tmp_prefix:string ->
?path_encoding:Netconversion.encoding ->
?enable_read_for_directories:bool ->
?enable_ftp:bool -> string -> Nethttp_fs.http_stream_fs
ocamlnet-4.1.2/doc/html-main/Netgss.html0000644000175000017500000004315612731530352016542 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgss

Module Netgss

module Netgss: sig .. end
This is the system-wide version of GSSAPI


OPAM users: Note that the OPAM package for OCamlnet does not build with GSSAPI support by default. The trigger for this is the presence of the conf-gssapi OPAM package, i.e. do opam install conf-gssapi to include the netgss-system library in a rebuild.
module System: Netsys_gssapi.GSSAPI 
This is the system-wide version of GSSAPI
ocamlnet-4.1.2/doc/html-main/type_Nethtml.html0000644000175000017500000006236112731530352017752 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethtml sig
  type document =
      Element of (string * (string * string) list * Nethtml.document list)
    | Data of string
  type element_class =
      [ `Block | `Essential_block | `Everywhere | `Inline | `None ]
  type model_constraint =
      [ `Any
      | `Block
      | `Elements of string list
      | `Empty
      | `Except of Nethtml.model_constraint * Nethtml.model_constraint
      | `Flow
      | `Inline
      | `Or of Nethtml.model_constraint * Nethtml.model_constraint
      | `Special
      | `Sub_exclusions of string list * Nethtml.model_constraint ]
  type simplified_dtd =
      (string * (Nethtml.element_class * Nethtml.model_constraint)) list
  val html40_dtd : Nethtml.simplified_dtd
  val relaxed_html40_dtd : Nethtml.simplified_dtd
  val parse_document :
    ?dtd:Nethtml.simplified_dtd ->
    ?return_declarations:bool ->
    ?return_pis:bool ->
    ?return_comments:bool ->
    ?case_sensitive:bool -> Lexing.lexbuf -> Nethtml.document list
  val parse :
    ?dtd:Nethtml.simplified_dtd ->
    ?return_declarations:bool ->
    ?return_pis:bool ->
    ?return_comments:bool ->
    ?case_sensitive:bool ->
    Netchannels.in_obj_channel -> Nethtml.document list
  val decode :
    ?enc:Netconversion.encoding ->
    ?subst:(int -> string) ->
    ?entity_base:[ `Empty | `Html | `Xml ] ->
    ?lookup:(string -> string) ->
    ?dtd:Nethtml.simplified_dtd ->
    Nethtml.document list -> Nethtml.document list
  val encode :
    ?enc:Netconversion.encoding ->
    ?prefer_name:bool ->
    ?dtd:Nethtml.simplified_dtd ->
    Nethtml.document list -> Nethtml.document list
  val map_list :
    (string -> string) -> Nethtml.document list -> Nethtml.document list
  type xmap_value =
      Xmap_attribute of string * string * string
    | Xmap_data of string option * string
  val xmap_list :
    (Nethtml.xmap_value -> string) ->
    string option -> Nethtml.document list -> Nethtml.document list
  val write :
    ?dtd:Nethtml.simplified_dtd ->
    ?xhtml:bool ->
    Netchannels.out_obj_channel -> Nethtml.document list -> unit
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.engine_mixin-c.html0000644000175000017500000004506212731530352022262 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.engine_mixin

Class Uq_engines.engine_mixin

class ['t] engine_mixin : 't engine_state -> Unixqueue.event_system -> object .. end
A useful class fragment that implements state and request_notification.

method state : 't engine_state
method private set_state : 't engine_state -> unit
method request_notification : (unit -> bool) -> unit
method request_proxy_notification : ('t engine -> bool) -> unit
method private notify : unit -> unit
method event_system : Unixqueue.event_system
ocamlnet-4.1.2/doc/html-main/type_Netcgi_apache.Apache.Server.html0000644000175000017500000004300512731530352023470 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache.Server sig
  type t
  external hostname : Netcgi_apache.Apache.Server.t -> string
    = "netcgi2_apache_server_hostname"
  external admin : Netcgi_apache.Apache.Server.t -> string
    = "netcgi2_apache_server_admin"
  external is_virtual : Netcgi_apache.Apache.Server.t -> bool
    = "netcgi2_apache_server_is_virtual"
end
ocamlnet-4.1.2/doc/html-main/Netcgi_modtpl.html0000644000175000017500000005707512731530352020074 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_modtpl

Module Netcgi_modtpl

module Netcgi_modtpl: sig .. end
Deprecated.Mod_caml style of templates. This template module is simple to use. It is here to provide a simple upgrade path from mod_caml. It should not be considered as the default template system of Netcgi.

type var = 
| VarString of string (*
::tag::
*)
| VarTable of table_row list (*
::table(tag)::
*)
| VarConditional of bool (*
::if(tag)::
*)
| VarCallback of (string list -> string) (*
::call(f, x1,...)::
*)
type table_row = (string * var) list 

Variables are either simple string, tables, conditionals or callbacks.

A simple string is set with template#set "name" s where s will be automatically escaped depending on the declaration in the template:

  • ::name:: does no escaping;
  • ::name_url:: escapes for URL encoding, make it suitable in a link <a href="::name_url::">;
  • ::name_html:: escapes for HTML display of the string;
  • ::name_html_tag:: escapes the string to make it suitable to be placed between quotes in an HTML tag, e.g. <input value="::name_html_tag::">;
  • ::name_html_textarea:: escapes the string to make it suitable to be placed between <textarea>...</textarea>.
Tables are declared in the template by ::table(name):: row template ::end::. The row template can contain other variables. Calling template#table "name" rows, where rows is a list [row1, row2,...,rowN], will insert N row templates with each template having its variables set thanks to row1,... each of which is an associative list name -> value (of type Template.table_row).

Conditionals are declared in the template by ::if(name) .. ::else:: .. ::end:: with the "else" clause being optional. Calling template#conditional sets up a conditional value.

Calling template#callback "fname" f sets up the callback function declared by ::call(fname,arg1,...,argN):: replacing the call by the value of f applied to the list [arg1,...,argN]. The string returned by f can be escaped by using suffices in the template as for simple tags: ::call(fname,arg1,...,argN)_html::,...

A template may also include other templates with ::include(filename)::.

class template : ?filename:string -> string -> object .. end
new template ?filename tpl computes a new template from the string tpl.
val template : string -> template
Compile the template from a named file. Not thread safe.
val template_from_string : ?filename:string -> string -> template
Compile the template from a literal string. Not thread safe.
val template_from_channel : ?filename:string -> Pervasives.in_channel -> template
Compile the template from a channel. Not thread safe.
ocamlnet-4.1.2/doc/html-main/Uq_server.server_endpoint_acceptor-c.html0000644000175000017500000005027212731530352024554 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_server.server_endpoint_acceptor

Class type Uq_server.server_endpoint_acceptor

class type server_endpoint_acceptor = object .. end
This class type is for service providers that listen for connections. By calling accept, one gets an engine that waits for the next connection, and establishes it.

There are services that can only accept one connection for a certain contact address. In this case accept must only be called once. Normally, services can accept any number of connections (multiplexing), and it is allowed to call accept again after the previous accept engine was successful.


method server_address : Uq_engines.connect_address
The contact address under which the clients can establish new connections with this server.
method multiple_connections : bool
Whether it is possible to accept multiple connections
method accept : unit -> (Unix.file_descr * Uq_engines.inetspec option) Uq_engines.engine
Instantiates an engine that accepts connections on the listening endpoint.

If the connection is successfully established, the state of the engine changes to `Done(fd,addr) where fd is the connected file descriptor, and where addr (if not-None) is the endpoint address of the connecting client (from the server's perspective). Such addresses are only supported for Internet endpoints. If a proxy is used to accept the connections, the returned address is that from the proxy's view, and usually different from what Unix.getpeername returns.

The close-on-exec flag of the created endpoint descriptor is always set. The endpoint descriptor is always in non-blocking mode.

It is allowed to shut down fd for sending, and it is required to close fd after all data transfers have been performed.

A call of accept allows it only to establish one connection at a time. However, it is allowed to call accept several times to accept several connections, provided the acceptor supports this (returned by multiple_connections). It is only allowed to call accept again when the previous engine was successful.

method shut_down : unit -> unit
The server endpoint is shut down such that no further connections are possible. It is required to call this method even for acceptors that do not support multiple connections. It is also required to call this method when an accept was not successful.

If there is a engine waiting for connections, it is aborted.

ocamlnet-4.1.2/doc/html-main/type_Netencoding.Html.html0000644000175000017500000005615012731530352021476 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Html sig
  val encode_from_latin1 : string -> string
  val decode_to_latin1 : string -> string
  val unsafe_chars_html4 : string
  val encode :
    in_enc:Netconversion.encoding ->
    ?out_enc:Netconversion.encoding ->
    ?prefer_name:bool -> ?unsafe_chars:string -> unit -> string -> string
  val encode_tstring :
    in_enc:Netconversion.encoding ->
    out_kind:'Netstring_tstring.tstring_kind ->
    ?out_enc:Netconversion.encoding ->
    ?prefer_name:bool ->
    ?unsafe_chars:string -> unit -> Netsys_types.tstring -> 's
  val encode_poly :
    in_enc:Netconversion.encoding ->
    in_ops:'Netstring_tstring.tstring_ops ->
    out_kind:'Netstring_tstring.tstring_kind ->
    ?out_enc:Netconversion.encoding ->
    ?prefer_name:bool -> ?unsafe_chars:string -> unit -> '-> 't
  type entity_set = [ `Empty | `Html | `Xml ]
  val decode :
    in_enc:Netconversion.encoding ->
    out_enc:Netconversion.encoding ->
    ?lookup:(string -> string) ->
    ?subst:(int -> string) ->
    ?entity_base:Netencoding.Html.entity_set -> unit -> string -> string
  val decode_tstring :
    in_enc:Netconversion.encoding ->
    out_kind:'Netstring_tstring.tstring_kind ->
    out_enc:Netconversion.encoding ->
    ?lookup:(string -> string) ->
    ?subst:(int -> string) ->
    ?entity_base:Netencoding.Html.entity_set ->
    unit -> Netsys_types.tstring -> 's
  val decode_poly :
    in_enc:Netconversion.encoding ->
    in_ops:'Netstring_tstring.tstring_ops ->
    out_kind:'Netstring_tstring.tstring_kind ->
    out_enc:Netconversion.encoding ->
    ?lookup:(string -> string) ->
    ?subst:(int -> string) ->
    ?entity_base:Netencoding.Html.entity_set -> unit -> '-> 't
end
ocamlnet-4.1.2/doc/html-main/Netplex_log.html0000644000175000017500000010024612731530352017551 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_log

Module Netplex_log

module Netplex_log: sig .. end
Loggers


A logger is usually configured in the config file. The logging section is inside controller, e.g.

 netplex {
         ...
         controller {
           ...
           logging { ... };
           ...
         }
         ...
       }
    

The possible types of logging sections are explained below. If there are several logging sections, the messages are sent to all configured loggers.

Instead of configuring loggers in the config file, one can also create loggers from config objects like generic_config.

See also Logging for more documentation.

class type generic_config = object .. end
val channel_logger : Pervasives.out_channel -> Netplex_types.logger
Outputs messages to the channel
val channel_logger_from_obj : generic_config -> Pervasives.out_channel -> Netplex_types.logger
Outputs messages to the channel
val stderr_logger_factory : Netplex_types.logger_factory
Reads a logging section like

 logging {
       type = "stderr";
       format = "<format string>";
       component = "<name_of_component>";
       subchannel = "<name_of_subchannel>";
       max_level = "<max_level>";
    }
 

  • format: Optional format string. See below.
  • component: Optional component selector. See below.
  • subchannel: Optional subchannel selector. See below.
  • max_level: Optional maximum log level. See below.

val file_logger : string -> Netplex_types.logger
Writes messages to this file
val file_logger_from_obj : generic_config -> string -> Netplex_types.logger
Writes messages to this file
val file_logger_factory : Netplex_types.logger_factory
Reads a logging section like

 logging {
       type = "file";
       file = "/path/to/logfile";
       format = "<format string>";
       component = "<name_of_component>";
       subchannel = "<name_of_subchannel>";
       max_level = "<max_level>";
    }
 

  • file: Log messages are appended to this file.
  • format: Optional format string. See below.
  • component: Optional component selector. See below.
  • subchannel: Optional subchannel selector. See below.
  • max_level: Optional maximum log level. See below.

class type multi_file_config = object .. end
val multi_file_logger : multi_file_config -> Netplex_types.logger
val multi_file_logger_factory : Netplex_types.logger_factory
Reads a logging section like

 logging {
       type = "multi_file";
       directory = "/path/to/logdir";
       format = "<format string>";
       file {
           component = "<name_of_component>";
           subchannel = "<name_of_subchannel>";
           max_level = "<max_level>";
           file = "<logfile>";
           format = "<format string>";
       };
       file { ... }; ...
    }
 

  • format: Optional format string. See below.
  • component: Optional component selector. See below.
  • subchannel: Optional subchannel selector. See below.
  • max_level: Optional maximum log level. See below.

class type syslog_config = object .. end
val syslog_logger : syslog_config -> Netplex_types.logger
Creates a logger writing to syslog
val syslog_logger_factory : Netplex_types.logger_factory
Reads a logging section like

 logging {
       type = "syslog";
       format = "<format string>";
       identifier = "<identifier>";
       facility = "<facility name>";
       component = "<name_of_component>";
       subchannel = "<name_of_subchannel>";
       max_level = "<max_level>";
    }
 

All parameters except type are optional:

  • facility: The faciltiy like LOCAL0, USER, ...
  • identifier: An identifier prefixing every message
  • format: Optional format string. See below.
  • component: Optional component selector. See below.
  • subchannel: Optional subchannel selector. See below.
  • max_level: Optional maximum log level. See below.

val logger_factories : Netplex_types.logger_factory list
All built-in logger factories
val level_weight : Netplex_types.level -> int
An integer corresponding to the level
val level_of_string : string -> Netplex_types.level
Convert a string to a level

Common parameters



Common parameters



Logging parameters that can occur in all logging configurations:

Common parameters



Logging parameters that can occur in all logging configurations:

format

The format string may include variable parts in the syntax $name or ${name}. The following variable specifications are defined:

  • timestamp: the time in standard format (as set in Netlog.current_formatter)
  • timestamp:<format> the time in custom format where <format> is a Netdate format string
  • timestamp:unix: the time in seconds since the epoch
  • component: the name of the component emitting the log message
  • subchannel: the name of the subchannel
  • level: the log level
  • message: the log message


Common parameters



Logging parameters that can occur in all logging configurations:

format

The format string may include variable parts in the syntax $name or ${name}. The following variable specifications are defined:

  • timestamp: the time in standard format (as set in Netlog.current_formatter)
  • timestamp:<format> the time in custom format where <format> is a Netdate format string
  • timestamp:unix: the time in seconds since the epoch
  • component: the name of the component emitting the log message
  • subchannel: the name of the subchannel
  • level: the log level
  • message: the log message


component

The component name restricts logging to the given Netplex component. One can use the wildcard "*".

Common parameters



Logging parameters that can occur in all logging configurations:

format

The format string may include variable parts in the syntax $name or ${name}. The following variable specifications are defined:

  • timestamp: the time in standard format (as set in Netlog.current_formatter)
  • timestamp:<format> the time in custom format where <format> is a Netdate format string
  • timestamp:unix: the time in seconds since the epoch
  • component: the name of the component emitting the log message
  • subchannel: the name of the subchannel
  • level: the log level
  • message: the log message


component

The component name restricts logging to the given Netplex component. One can use the wildcard "*".

subchannel

The subchannel name restricts logging to this subchannel. One can use the wildcard "*".

Common parameters



Logging parameters that can occur in all logging configurations:

format

The format string may include variable parts in the syntax $name or ${name}. The following variable specifications are defined:

  • timestamp: the time in standard format (as set in Netlog.current_formatter)
  • timestamp:<format> the time in custom format where <format> is a Netdate format string
  • timestamp:unix: the time in seconds since the epoch
  • component: the name of the component emitting the log message
  • subchannel: the name of the subchannel
  • level: the log level
  • message: the log message


component

The component name restricts logging to the given Netplex component. One can use the wildcard "*".

subchannel

The subchannel name restricts logging to this subchannel. One can use the wildcard "*".

max_level

The max_level specifier restricts logging to messages with at most this level. Levels are "emerg", "alert", "crit", "err", "warning", "notice", "info", "debug" (in order of increasing level).
ocamlnet-4.1.2/doc/html-main/Netmech_digest_http.PROFILE.html0000644000175000017500000004303712731530352022355 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http.PROFILE

Module type Netmech_digest_http.PROFILE

module type PROFILE = sig .. end

val mutual : bool
If true, the Authentication-Info header is checked. If false, this header is ignored.
val hash_functions : Netsys_digests.iana_hash_fn list
List of enabled hash functions. The mechanism checks whether the function is provided by Netsys_digests, and automatically removed unavailable hashes. MD5 is always supported.
ocamlnet-4.1.2/doc/html-main/type_Netcgi_common.cgi_environment.html0000644000175000017500000005501312731530352024301 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.cgi_environment config:Netcgi_common.config ->
properties:(string * string) list ->
input_header:(string * string) list ->
Netchannels.out_obj_channel ->
object
  val mutable header_not_sent : bool
  method cgi_auth_type : string
  method cgi_gateway_interface : string
  method cgi_https : bool
  method cgi_path_info : string
  method cgi_path_translated : string
  method cgi_properties : (string * string) list
  method cgi_property : ?default:string -> string -> string
  method cgi_query_string : string
  method cgi_remote_addr : string
  method cgi_remote_host : string
  method cgi_remote_ident : string
  method cgi_remote_user : string
  method cgi_request_method : string
  method cgi_script_name : string
  method cgi_server_name : string
  method cgi_server_port : int option
  method cgi_server_protocol : string
  method cgi_server_software : string
  method config : Netcgi_common.config
  method cookie : string -> Netcgi_common.Cookie.t
  method cookies : Netcgi_common.Cookie.t list
  method input_content_length : int
  method input_content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method input_content_type_string : string
  method input_header : Netmime.mime_header
  method input_header_field : ?default:string -> string -> string
  method input_header_fields : (string * string) list
  method log_error : string -> unit
  method multiple_input_header_field : string -> string list
  method multiple_output_header_field : string -> string list
  method out_channel : Netchannels.out_obj_channel
  method output_ch : Netchannels.out_obj_channel
  method output_header : Netmime.mime_header
  method output_header_field : ?default:string -> string -> string
  method output_header_fields : (string * string) list
  method protocol : Nethttp.protocol
  method send_output_header : unit -> unit
  method set_multiple_output_header_field : string -> string list -> unit
  method set_output_header_field : string -> string -> unit
  method set_output_header_fields : (string * string) list -> unit
  method set_status : Nethttp.http_status -> unit
  method user_agent : string
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_apache.html0000644000175000017500000020240612731530352021045 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache sig
  module Apache :
    sig
      module Table :
        sig
          type t
          external get : Netcgi_apache.Apache.Table.t -> string -> string
            = "netcgi2_apache_table_get"
          external get_all :
            Netcgi_apache.Apache.Table.t -> string -> string list
            = "netcgi2_apache_table_get_all"
          external fields :
            Netcgi_apache.Apache.Table.t -> (string * string) list
            = "netcgi2_apache_table_fields"
          external clear : Netcgi_apache.Apache.Table.t -> unit
            = "netcgi2_apache_table_clear"
          external set :
            Netcgi_apache.Apache.Table.t -> string -> string -> unit
            = "netcgi2_apache_table_set"
          external add :
            Netcgi_apache.Apache.Table.t -> string -> string -> unit
            = "netcgi2_apache_table_add"
          external unset : Netcgi_apache.Apache.Table.t -> string -> unit
            = "netcgi2_apache_table_unset"
        end
      module Server :
        sig
          type t
          external hostname : Netcgi_apache.Apache.Server.t -> string
            = "netcgi2_apache_server_hostname"
          external admin : Netcgi_apache.Apache.Server.t -> string
            = "netcgi2_apache_server_admin"
          external is_virtual : Netcgi_apache.Apache.Server.t -> bool
            = "netcgi2_apache_server_is_virtual"
        end
      module Connection :
        sig
          type t
          external remote_ip : Netcgi_apache.Apache.Connection.t -> string
            = "netcgi2_apache_connection_remote_ip"
          external remote_host : Netcgi_apache.Apache.Connection.t -> string
            = "netcgi2_apache_connection_remote_host"
        end
      module Request :
        sig
          type t
          external connection :
            Netcgi_apache.Apache.Request.t ->
            Netcgi_apache.Apache.Connection.t
            = "netcgi2_apache_request_connection"
          external server :
            Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Server.t
            = "netcgi2_apache_request_server"
          external next :
            Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Request.t
            = "netcgi2_apache_request_next"
          external prev :
            Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Request.t
            = "netcgi2_apache_request_prev"
          external main :
            Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Request.t
            = "netcgi2_apache_request_main"
          external the_request : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_the_request"
          external assbackwards : Netcgi_apache.Apache.Request.t -> bool
            = "netcgi2_apache_request_assbackwards"
          external header_only : Netcgi_apache.Apache.Request.t -> bool
            = "netcgi2_apache_request_header_only"
          external protocol : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_protocol"
          external proto_num : Netcgi_apache.Apache.Request.t -> int
            = "netcgi2_apache_request_proto_num"
          external hostname : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_hostname"
          external request_time : Netcgi_apache.Apache.Request.t -> float
            = "netcgi2_apache_request_request_time"
          external status_line : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_status_line"
          external set_status_line :
            Netcgi_apache.Apache.Request.t -> string -> unit
            = "netcgi2_apache_request_set_status_line"
          external status : Netcgi_apache.Apache.Request.t -> int
            = "netcgi2_apache_request_status"
          external set_status : Netcgi_apache.Apache.Request.t -> int -> unit
            = "netcgi2_apache_request_set_status"
          external method_name : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_method"
          val method_number :
            Netcgi_apache.Apache.Request.t ->
            [ `CONNECT
            | `COPY
            | `DELETE
            | `GET
            | `INVALID
            | `LOCK
            | `MKCOL
            | `MOVE
            | `OPTIONS
            | `PATCH
            | `POST
            | `PROPFIND
            | `PROPPATCH
            | `PUT
            | `TRACE
            | `UNLOCK ]
          external headers_in :
            Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
            = "netcgi2_apache_request_headers_in"
          external headers_out :
            Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
            = "netcgi2_apache_request_headers_out"
          external err_headers_out :
            Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
            = "netcgi2_apache_request_err_headers_out"
          external subprocess_env :
            Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
            = "netcgi2_apache_request_subprocess_env"
          external notes :
            Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
            = "netcgi2_apache_request_notes"
          external content_type : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_content_type"
          external set_content_type :
            Netcgi_apache.Apache.Request.t -> string -> unit
            = "netcgi2_apache_request_set_content_type"
          external uri : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_uri"
          external port : Netcgi_apache.Apache.Request.t -> int
            = "netcgi2_apache_request_port"
          external set_uri : Netcgi_apache.Apache.Request.t -> string -> unit
            = "netcgi2_apache_request_set_uri"
          external filename : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_filename"
          external set_filename :
            Netcgi_apache.Apache.Request.t -> string -> unit
            = "netcgi2_apache_request_set_filename"
          external path_info : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_path_info"
          external set_path_info :
            Netcgi_apache.Apache.Request.t -> string -> unit
            = "netcgi2_apache_request_set_path_info"
          external args : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_args"
          external set_args :
            Netcgi_apache.Apache.Request.t -> string -> unit
            = "netcgi2_apache_request_set_args"
          external finfo :
            Netcgi_apache.Apache.Request.t -> Unix.stats option
            = "netcgi2_apache_request_finfo"
          type read_policy =
              NO_BODY
            | CHUNKED_ERROR
            | CHUNKED_DECHUNK
            | CHUNKED_PASS
          val setup_client_block :
            Netcgi_apache.Apache.Request.t ->
            Netcgi_apache.Apache.Request.read_policy -> unit
          external should_client_block :
            Netcgi_apache.Apache.Request.t -> bool
            = "netcgi2_apache_request_should_client_block"
          val get_client_block : Netcgi_apache.Apache.Request.t -> string
          val get_client_block_buf :
            Netcgi_apache.Apache.Request.t -> Bytes.t -> int -> int -> int
          val discard_request_body : Netcgi_apache.Apache.Request.t -> unit
          external user : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_request_user"
          external auth_type : Netcgi_apache.Apache.Request.t -> string
            = "netcgi2_apache_auth_type"
          external note_auth_failure : Netcgi_apache.Apache.Request.t -> unit
            = "netcgi2_apache_request_note_auth_failure"
          external note_basic_auth_failure :
            Netcgi_apache.Apache.Request.t -> unit
            = "netcgi2_apache_request_note_basic_auth_failure"
          external note_digest_auth_failure :
            Netcgi_apache.Apache.Request.t -> unit
            = "netcgi2_apache_request_note_digest_auth_failure"
          val get_basic_auth_pw :
            Netcgi_apache.Apache.Request.t -> string option
          external internal_redirect :
            string -> Netcgi_apache.Apache.Request.t -> unit
            = "netcgi2_apache_request_internal_redirect"
          external internal_redirect_handler :
            string -> Netcgi_apache.Apache.Request.t -> unit
            = "netcgi2_apache_request_internal_redirect_handler"
          external send_http_header : Netcgi_apache.Apache.Request.t -> unit
            = "netcgi2_apache_request_send_http_header"
          val rflush : Netcgi_apache.Apache.Request.t -> unit
          external print_char :
            Netcgi_apache.Apache.Request.t -> char -> unit
            = "netcgi2_apache_request_print_char"
          val print_string : Netcgi_apache.Apache.Request.t -> string -> unit
          val output :
            Netcgi_apache.Apache.Request.t -> Bytes.t -> int -> int -> int
          val print_int : Netcgi_apache.Apache.Request.t -> int -> unit
          val print_float : Netcgi_apache.Apache.Request.t -> float -> unit
          val print_newline : Netcgi_apache.Apache.Request.t -> unit
          val print_endline :
            Netcgi_apache.Apache.Request.t -> string -> unit
          external register_cleanup :
            Netcgi_apache.Apache.Request.t -> (unit -> unit) -> unit
            = "netcgi2_apache_request_register_cleanup"
        end
    end
  module Handler :
    sig
      type result = OK | DECLINED | DONE | HTTP of int
      type t = Netcgi_apache.Apache.Request.t -> Netcgi_apache.Handler.result
      val register : Netcgi_apache.Handler.t -> string -> unit
    end
  class type cgi =
    object
      method argument : string -> Netcgi.cgi_argument
      method argument_exists : string -> bool
      method argument_value : ?default:string -> string -> string
      method arguments : Netcgi.cgi_argument list
      method at_exit : (unit -> unit) -> unit
      method environment : Netcgi.cgi_environment
      method finalize : unit -> unit
      method multiple_argument : string -> Netcgi.cgi_argument list
      method out_channel : Netchannels.trans_out_obj_channel
      method output : Netchannels.trans_out_obj_channel
      method request : Netcgi_apache.Apache.Request.t
      method request_method :
        [ `DELETE | `GET | `HEAD | `POST | `PUT of Netcgi.cgi_argument ]
      method set_header :
        ?status:Nethttp.http_status ->
        ?content_type:string ->
        ?content_length:int ->
        ?set_cookie:Nethttp.cookie list ->
        ?set_cookies:Netcgi.Cookie.t list ->
        ?cache:Netcgi.cache_control ->
        ?filename:string ->
        ?language:string ->
        ?script_type:string ->
        ?style_type:string ->
        ?fields:(string * string list) list -> unit -> unit
      method set_redirection_header :
        ?set_cookies:Netcgi.Cookie.t list ->
        ?fields:(string * string list) list -> string -> unit
      method url :
        ?protocol:Nethttp.protocol ->
        ?with_authority:Netcgi.other_url_spec ->
        ?with_script_name:Netcgi.other_url_spec ->
        ?with_path_info:Netcgi.other_url_spec ->
        ?with_query_string:Netcgi.query_string_spec -> unit -> string
    end
  val run :
    ?config:Netcgi.config ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?exn_handler:Netcgi.exn_handler -> (Netcgi_apache.cgi -> unit) -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_intro.html0000644000175000017500000004061612731530352021170 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_intro sig  endocamlnet-4.1.2/doc/html-main/Netmime.mime_body_ro-c.html0000644000175000017500000004622112731530352021554 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.mime_body_ro

Class type Netmime.mime_body_ro

class type mime_body_ro = object .. end
This is the read-only version of a MIME body. There are only methods to read the body contents.

The value of the body can be returned either as string, or as object channel. Both ways are possible independently of where the value is stored, in-memory, or as external file.


method value : string
The value method returns the _decoded_ body, i.e. transfer encodings are removed before the value is passed back.

When the body is stored in an external file, this method reads the complete file into memory.

method store : store
Where the body is actually stored.
method open_value_rd : unit -> Netchannels.in_obj_channel
Opens the value for reading. This works independently of where the body is stored. For example, to read the body line by line:
 let ch = body # open_value_rd () in
 try
   while true do
     let line = ch # input_line() in
     ... (* do something *)
   done;
   assert false; (* never reached *)
 with
   End_of_file ->
     ch # close_in()
 

As value, this method returns the value in decoded form. This method is quite economical with the resources, and takes only as much memory as needed for the channel operations.

method finalize : unit -> unit
After the body has been finalized, it cannot be accessed any longer. External resources (files) are deallocated, if they are seen as temporary.
ocamlnet-4.1.2/doc/html-main/type_Netsys_pollset_win32.html0000644000175000017500000004224412731530352022406 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset_win32 sig
  exception Too_many_descriptors
  val pollset : unit -> Netsys_pollset.pollset
  val threaded_pollset : unit -> Netsys_pollset.pollset
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Nettls_gnutls_bindings.html0000644000175000017500000046046512731530352023070 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls_bindings sig
  type gnutls_cipher_algorithm_t
  type gnutls_kx_algorithm_t
  type gnutls_mac_algorithm_t
  type gnutls_compression_method_t
  type gnutls_pk_algorithm_t
  type gnutls_sign_algorithm_t
  type gnutls_certificate_type_t
  type gnutls_digest_algorithm_t =
      Nettls_gnutls_bindings.gnutls_mac_algorithm_t
  type gnutls_session_t
  type gnutls_dh_params_t
  type gnutls_priority_t
  type gnutls_cipher_hd_t
  type gnutls_x509_privkey_t
  type gnutls_x509_crl_t
  type gnutls_x509_crt_t
  type gnutls_openpgp_keyring_t
  type gnutls_certificate_credentials_t
  type gnutls_anon_server_credentials_t
  type gnutls_anon_client_credentials_t
  type gnutls_srp_server_credentials_t
  type gnutls_srp_client_credentials_t
  type gnutls_psk_server_credentials_t
  type gnutls_psk_client_credentials_t
  type gnutls_pubkey_t
  type gnutls_privkey_t
  type gnutls_params_type_t = [ `Dh | `Ecdh | `Rsa_export ]
  type gnutls_credentials_type_t =
      [ `Anon | `Certificate | `Ia | `Psk | `Srp ]
  type gnutls_alert_level_t = [ `Fatal | `Warning ]
  type gnutls_alert_description_t =
      [ `Access_denied
      | `Bad_certificate
      | `Bad_record_mac
      | `Certificate_expired
      | `Certificate_revoked
      | `Certificate_unknown
      | `Certificate_unobtainable
      | `Close_notify
      | `Decode_error
      | `Decompression_failure
      | `Decrypt_error
      | `Decryption_failed
      | `Export_restriction
      | `Handshake_failure
      | `Illegal_parameter
      | `Inner_application_failure
      | `Inner_application_verification
      | `Insufficient_security
      | `Internal_error
      | `No_application_protocol
      | `No_renegotiation
      | `Protocol_version
      | `Record_overflow
      | `Ssl3_no_certificate
      | `Unexpected_message
      | `Unknown_ca
      | `Unknown_psk_identity
      | `Unrecognized_name
      | `Unsupported_certificate
      | `Unsupported_extension
      | `User_canceled ]
  type gnutls_handshake_description_t =
      [ `Certificate_pkt
      | `Certificate_request
      | `Certificate_verify
      | `Change_cipher_spec
      | `Client_hello
      | `Client_hello_v2
      | `Client_key_exchange
      | `Finished
      | `Hello_request
      | `Hello_verify_request
      | `New_session_ticket
      | `Server_hello
      | `Server_hello_done
      | `Server_key_exchange
      | `Supplemental ]
  type gnutls_certificate_status_t_flag =
      [ `Expired
      | `Insecure_algorithm
      | `Invalid
      | `Mismatch
      | `Not_activated
      | `Purpose_mismatch
      | `Revocation_data_issued_in_future
      | `Revocation_data_superseded
      | `Revoked
      | `Signature_failure
      | `Signer_constraints_failure
      | `Signer_not_ca
      | `Signer_not_found
      | `Unexpected_owner ]
  type gnutls_certificate_status_t =
      Nettls_gnutls_bindings.gnutls_certificate_status_t_flag list
  type gnutls_certificate_request_t = [ `Ignore | `Request | `Require ]
  type gnutls_certificate_verify_flags_flag =
      [ `Allow_any_x509_v1_ca_crt
      | `Allow_sign_rsa_md2
      | `Allow_sign_rsa_md5
      | `Allow_x509_v1_ca_crt
      | `Disable_ca_sign
      | `Disable_crl_checks
      | `Disable_time_checks
      | `Disable_trusted_time_checks
      | `Do_not_allow_same
      | `Do_not_allow_x509_v1_ca_crt ]
  type gnutls_certificate_verify_flags =
      Nettls_gnutls_bindings.gnutls_certificate_verify_flags_flag list
  type gnutls_openpgp_crt_status_t = [ `Cert | `Cert_fingerprint ]
  type gnutls_close_request_t = [ `Rdwr | `Wr ]
  type gnutls_protocol_t =
      [ `Dtls0_9
      | `Dtls1_0
      | `Dtls1_2
      | `Ssl3
      | `Tls1_0
      | `Tls1_1
      | `Tls1_2
      | `Version_unknown ]
  type gnutls_x509_crt_fmt_t = [ `Der | `Pem ]
  type gnutls_certificate_print_formats_t =
      [ `Compact | `Full | `Full_numbers | `Oneline | `Unsigned_full ]
  type gnutls_ecc_curve_t =
      [ `Invalid
      | `Secp192r1
      | `Secp224r1
      | `Secp256r1
      | `Secp384r1
      | `Secp521r1 ]
  type gnutls_sec_param_t =
      [ `Export
      | `High
      | `Insecure
      | `Legacy
      | `Low
      | `Normal
      | `Ultra
      | `Unknown
      | `Very_weak
      | `Weak ]
  type gnutls_init_flags_flag =
      [ `Client
      | `Datagram
      | `No_extensions
      | `No_replay_protection
      | `Nonblock
      | `Server ]
  type gnutls_init_flags = Nettls_gnutls_bindings.gnutls_init_flags_flag list
  type gnutls_server_name_type_t = [ `Dns ]
  type gnutls_supplemental_data_format_type_t = [ `Unknown ]
  type gnutls_psk_key_flags = [ `Hex | `Raw ]
  type gnutls_x509_subject_alt_name_t =
      [ `Dn
      | `Dnsname
      | `Ipaddress
      | `Othername
      | `Othername_xmpp
      | `Rfc822name
      | `Uri ]
  type gnutls_privkey_type_t = [ `Ext | `Openpgp | `Pkcs11 | `X509 ]
  type key_usage_flag =
      [ `Crl_sign
      | `Data_encipherment
      | `Decipher_only
      | `Digital_signature
      | `Encipher_only
      | `Key_agreement
      | `Key_cert_sign
      | `Key_encipherment
      | `Non_repudiation ]
  type key_usage = Nettls_gnutls_bindings.key_usage_flag list
  type gnutls_channel_binding_t = [ `Tls_unique ]
  type gnutls_info_access_what_t =
      [ `Accesslocation_generalname_type
      | `Accessmethod_oid
      | `Caissuers_uri
      | `Ocsp_uri
      | `Unknown
      | `Uri ]
  type gnutls_certificate_import_flags_flag =
      [ `Fail_if_unsorted | `Import_fail_if_exceed | `Sort ]
  type gnutls_certificate_import_flags =
      Nettls_gnutls_bindings.gnutls_certificate_import_flags_flag list
  type error_code =
      [ `Again
      | `Asn1_der_error
      | `Asn1_der_overflow
      | `Asn1_element_not_found
      | `Asn1_generic_error
      | `Asn1_identifier_not_found
      | `Asn1_syntax_error
      | `Asn1_tag_error
      | `Asn1_tag_implicit
      | `Asn1_type_any_error
      | `Asn1_value_not_found
      | `Asn1_value_not_valid
      | `Auth_error
      | `Bad_cookie
      | `Base64_decoding_error
      | `Base64_encoding_error
      | `Base64_unexpected_header_error
      | `Certificate_error
      | `Certificate_key_mismatch
      | `Certificate_list_unsorted
      | `Channel_binding_not_available
      | `Compression_failed
      | `Constraint_error
      | `Crypto_already_registered
      | `Crypto_init_failed
      | `Cryptodev_device_error
      | `Cryptodev_ioctl_error
      | `Db_error
      | `Decompression_failed
      | `Decryption_failed
      | `Dh_prime_unacceptable
      | `Ecc_no_supported_curves
      | `Ecc_unsupported_curve
      | `Encryption_failed
      | `Error_in_finished_packet
      | `Expired
      | `Fatal_alert_received
      | `File_error
      | `Got_application_data
      | `Handshake_too_large
      | `Hash_failed
      | `Heartbeat_ping_received
      | `Heartbeat_pong_received
      | `Ia_verify_failed
      | `Idna_error
      | `Illegal_parameter
      | `Illegal_srp_username
      | `Incompat_dsa_key_with_tls_protocol
      | `Incompatible_crypto_library
      | `Incompatible_libtasn1_library
      | `Insufficient_credentials
      | `Internal_error
      | `Interrupted
      | `Invalid_password
      | `Invalid_request
      | `Invalid_session
      | `Key_import_failed
      | `Key_usage_violation
      | `Large_packet
      | `Lib_in_error_state
      | `Locking_error
      | `Mac_verify_failed
      | `Memory_error
      | `Mpi_print_failed
      | `Mpi_scan_failed
      | `Need_fallback
      | `No_application_protocol
      | `No_certificate_found
      | `No_certificate_status
      | `No_cipher_suites
      | `No_compression_algorithms
      | `No_priorities_were_set
      | `No_self_test
      | `No_temporary_dh_params
      | `No_temporary_rsa_params
      | `Ocsp_response_error
      | `Openpgp_fingerprint_unsupported
      | `Openpgp_getkey_failed
      | `Openpgp_keyring_error
      | `Openpgp_preferred_key_error
      | `Openpgp_subkey_error
      | `Openpgp_uid_revoked
      | `Parsing_error
      | `Pk_decryption_failed
      | `Pk_encryption_failed
      | `Pk_generation_error
      | `Pk_sig_verify_failed
      | `Pk_sign_failed
      | `Pkcs11_attribute_error
      | `Pkcs11_data_error
      | `Pkcs11_device_error
      | `Pkcs11_error
      | `Pkcs11_key_error
      | `Pkcs11_load_error
      | `Pkcs11_pin_error
      | `Pkcs11_pin_expired
      | `Pkcs11_pin_locked
      | `Pkcs11_requested_object_not_availble
      | `Pkcs11_session_error
      | `Pkcs11_signature_error
      | `Pkcs11_slot_error
      | `Pkcs11_token_error
      | `Pkcs11_unsupported_feature_error
      | `Pkcs11_user_error
      | `Pkcs1_wrong_pad
      | `Premature_termination
      | `Pull_error
      | `Push_error
      | `Random_device_error
      | `Random_failed
      | `Received_illegal_extension
      | `Received_illegal_parameter
      | `Record_limit_reached
      | `Rehandshake
      | `Requested_data_not_available
      | `Safe_renegotiation_failed
      | `Self_test_error
      | `Session_eof
      | `Short_memory_buffer
      | `Sockets_init_error
      | `Srp_pwd_error
      | `Srp_pwd_parsing_error
      | `Success
      | `Timedout
      | `Too_many_empty_packets
      | `Too_many_handshake_packets
      | `Tpm_error
      | `Tpm_key_not_found
      | `Tpm_key_password_error
      | `Tpm_session_error
      | `Tpm_srk_password_error
      | `Tpm_uninitialized
      | `Unexpected_handshake_packet
      | `Unexpected_packet
      | `Unexpected_packet_length
      | `Unimplemented_feature
      | `Unknown_algorithm
      | `Unknown_cipher_suite
      | `Unknown_cipher_type
      | `Unknown_compression_algorithm
      | `Unknown_hash_algorithm
      | `Unknown_pk_algorithm
      | `Unknown_pkcs_bag_type
      | `Unknown_pkcs_content_type
      | `Unknown_srp_username
      | `Unsafe_renegotiation_denied
      | `Unsupported_certificate_type
      | `Unsupported_signature_algorithm
      | `Unsupported_version_packet
      | `Unwanted_algorithm
      | `User_error
      | `Warning_alert_received
      | `Warning_ia_fphf_received
      | `Warning_ia_iphf_received
      | `X509_unknown_san
      | `X509_unsupported_attribute
      | `X509_unsupported_critical_extension
      | `X509_unsupported_extension
      | `X509_unsupported_oid ]
  type gnutls_pkcs_encrypt_flags_t_flag =
      [ `Null_password
      | `Plain
      | `Use_pbes2_3des
      | `Use_pbes2_aes_128
      | `Use_pbes2_aes_192
      | `Use_pbes2_aes_256
      | `Use_pbes2_des
      | `Use_pkcs12_3des
      | `Use_pkcs12_arcfour
      | `Use_pkcs12_rc2_40 ]
  type gnutls_pkcs_encrypt_flags_t =
      Nettls_gnutls_bindings.gnutls_pkcs_encrypt_flags_t_flag list
  type empty_flags_flag = [ `Dummy ]
  type empty_flags = Nettls_gnutls_bindings.empty_flags_flag list
  type str_datum = string
  type str_datum_p = string
  type const_str_datum_p = string
  val nettls_init : unit -> unit
  val nettls_deinit : unit -> unit
  val gnutls_error_is_fatal : Nettls_gnutls_bindings.error_code -> bool
  val gnutls_strerror : Nettls_gnutls_bindings.error_code -> string
  val gnutls_strerror_name : Nettls_gnutls_bindings.error_code -> string
  val gnutls_check_version : unit -> string
  val gnutls_global_set_log_level : int -> unit
  val gnutls_init :
    Nettls_gnutls_bindings.gnutls_init_flags ->
    Nettls_gnutls_bindings.gnutls_session_t
  val gnutls_certificate_server_set_request :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_certificate_request_t -> unit
  val gnutls_certificate_send_x509_rdn_sequence :
    Nettls_gnutls_bindings.gnutls_session_t -> bool -> unit
  val gnutls_certificate_verify_peers2 :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_certificate_status_t
  val gnutls_certificate_get_peers :
    Nettls_gnutls_bindings.gnutls_session_t -> string array
  val gnutls_record_get_direction :
    Nettls_gnutls_bindings.gnutls_session_t -> bool
  val gnutls_handshake : Nettls_gnutls_bindings.gnutls_session_t -> unit
  val gnutls_rehandshake : Nettls_gnutls_bindings.gnutls_session_t -> unit
  val gnutls_record_send :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Netsys_mem.memory -> int -> int
  val gnutls_record_recv :
    Nettls_gnutls_bindings.gnutls_session_t -> Netsys_mem.memory -> int
  val gnutls_record_check_pending :
    Nettls_gnutls_bindings.gnutls_session_t -> int
  val gnutls_bye :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_close_request_t -> unit
  val gnutls_alert_get :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_alert_description_t
  val gnutls_alert_get_name :
    Nettls_gnutls_bindings.gnutls_alert_description_t -> string
  val gnutls_alert_get_strname :
    Nettls_gnutls_bindings.gnutls_alert_description_t -> string
  val gnutls_alert_send :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_alert_level_t ->
    Nettls_gnutls_bindings.gnutls_alert_description_t -> unit
  val gnutls_alert_send_appropriate :
    Nettls_gnutls_bindings.gnutls_session_t -> int -> unit
  val gnutls_error_to_alert :
    Nettls_gnutls_bindings.error_code ->
    Nettls_gnutls_bindings.gnutls_alert_description_t *
    Nettls_gnutls_bindings.gnutls_alert_level_t
  val gnutls_priority_init :
    string -> Nettls_gnutls_bindings.gnutls_priority_t
  val gnutls_priority_get_cipher_suite_index :
    Nettls_gnutls_bindings.gnutls_priority_t -> int -> int
  val gnutls_priority_set :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_priority_t -> unit
  val gnutls_set_default_priority :
    Nettls_gnutls_bindings.gnutls_session_t -> unit
  val gnutls_sec_param_to_pk_bits :
    Nettls_gnutls_bindings.gnutls_pk_algorithm_t ->
    Nettls_gnutls_bindings.gnutls_sec_param_t -> int
  val gnutls_pk_bits_to_sec_param :
    Nettls_gnutls_bindings.gnutls_pk_algorithm_t ->
    int -> Nettls_gnutls_bindings.gnutls_sec_param_t
  val gnutls_sec_param_get_name :
    Nettls_gnutls_bindings.gnutls_sec_param_t -> string
  val gnutls_session_set_data :
    Nettls_gnutls_bindings.gnutls_session_t -> Bytes.t -> unit
  val gnutls_session_get_data :
    Nettls_gnutls_bindings.gnutls_session_t -> Bytes.t
  val gnutls_session_get_id :
    Nettls_gnutls_bindings.gnutls_session_t -> Bytes.t
  val gnutls_session_is_resumed :
    Nettls_gnutls_bindings.gnutls_session_t -> bool
  val gnutls_db_set_cache_expiration :
    Nettls_gnutls_bindings.gnutls_session_t -> int -> unit
  val gnutls_db_remove_session :
    Nettls_gnutls_bindings.gnutls_session_t -> unit
  val gnutls_db_check_entry :
    Nettls_gnutls_bindings.gnutls_session_t -> string -> int
  val gnutls_session_ticket_key_generate : unit -> string
  val gnutls_session_ticket_enable_client :
    Nettls_gnutls_bindings.gnutls_session_t -> unit
  val gnutls_session_ticket_enable_server :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.str_datum_p -> unit
  val gnutls_prf :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Netsys_mem.memory ->
    bool -> Netsys_mem.memory -> Netsys_mem.memory -> unit
  val gnutls_prf_raw :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Netsys_mem.memory -> Netsys_mem.memory -> Netsys_mem.memory -> unit
  val gnutls_session_channel_binding :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_channel_binding_t -> string
  val gnutls_ecc_curve_get_name :
    Nettls_gnutls_bindings.gnutls_ecc_curve_t -> string
  val gnutls_ecc_curve_get_size :
    Nettls_gnutls_bindings.gnutls_ecc_curve_t -> int
  val gnutls_ecc_curve_get :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_ecc_curve_t
  val gnutls_cipher_get :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_cipher_algorithm_t
  val gnutls_kx_get :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_kx_algorithm_t
  val gnutls_mac_get :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_mac_algorithm_t
  val gnutls_compression_get :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_compression_method_t
  val gnutls_certificate_type_get :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_certificate_type_t
  val gnutls_cipher_get_key_size :
    Nettls_gnutls_bindings.gnutls_cipher_algorithm_t -> int
  val gnutls_mac_get_key_size :
    Nettls_gnutls_bindings.gnutls_mac_algorithm_t -> int
  val gnutls_cipher_get_name :
    Nettls_gnutls_bindings.gnutls_cipher_algorithm_t -> string
  val gnutls_mac_get_name :
    Nettls_gnutls_bindings.gnutls_mac_algorithm_t -> string
  val gnutls_compression_get_name :
    Nettls_gnutls_bindings.gnutls_compression_method_t -> string
  val gnutls_kx_get_name :
    Nettls_gnutls_bindings.gnutls_kx_algorithm_t -> string
  val gnutls_certificate_type_get_name :
    Nettls_gnutls_bindings.gnutls_certificate_type_t -> string
  val gnutls_pk_get_name :
    Nettls_gnutls_bindings.gnutls_pk_algorithm_t -> string
  val gnutls_sign_get_name :
    Nettls_gnutls_bindings.gnutls_sign_algorithm_t -> string
  val gnutls_mac_get_id :
    string -> Nettls_gnutls_bindings.gnutls_mac_algorithm_t
  val gnutls_compression_get_id :
    string -> Nettls_gnutls_bindings.gnutls_compression_method_t
  val gnutls_cipher_get_id :
    string -> Nettls_gnutls_bindings.gnutls_cipher_algorithm_t
  val gnutls_kx_get_id :
    string -> Nettls_gnutls_bindings.gnutls_kx_algorithm_t
  val gnutls_protocol_get_id :
    string -> Nettls_gnutls_bindings.gnutls_protocol_t
  val gnutls_certificate_type_get_id :
    string -> Nettls_gnutls_bindings.gnutls_certificate_type_t
  val gnutls_pk_get_id :
    string -> Nettls_gnutls_bindings.gnutls_pk_algorithm_t
  val gnutls_sign_get_id :
    string -> Nettls_gnutls_bindings.gnutls_sign_algorithm_t
  val gnutls_cipher_list :
    unit -> Nettls_gnutls_bindings.gnutls_cipher_algorithm_t list
  val gnutls_mac_list :
    unit -> Nettls_gnutls_bindings.gnutls_mac_algorithm_t list
  val gnutls_compression_list :
    unit -> Nettls_gnutls_bindings.gnutls_compression_method_t list
  val gnutls_protocol_list :
    unit -> Nettls_gnutls_bindings.gnutls_protocol_t list
  val gnutls_certificate_type_list :
    unit -> Nettls_gnutls_bindings.gnutls_certificate_type_t list
  val gnutls_kx_list :
    unit -> Nettls_gnutls_bindings.gnutls_kx_algorithm_t list
  val gnutls_pk_list :
    unit -> Nettls_gnutls_bindings.gnutls_pk_algorithm_t list
  val gnutls_sign_list :
    unit -> Nettls_gnutls_bindings.gnutls_sign_algorithm_t list
  val gnutls_protocol_get_version :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_protocol_t
  val gnutls_protocol_get_name :
    Nettls_gnutls_bindings.gnutls_protocol_t -> string
  val gnutls_cipher_suite_get_name :
    Nettls_gnutls_bindings.gnutls_kx_algorithm_t ->
    Nettls_gnutls_bindings.gnutls_cipher_algorithm_t ->
    Nettls_gnutls_bindings.gnutls_mac_algorithm_t -> string
  val net_have_crypto : unit -> bool
  val gnutls_cipher_init :
    Nettls_gnutls_bindings.gnutls_cipher_algorithm_t ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.gnutls_cipher_hd_t
  val gnutls_cipher_encrypt2 :
    Nettls_gnutls_bindings.gnutls_cipher_hd_t ->
    Netsys_mem.memory -> Netsys_mem.memory -> unit
  val gnutls_cipher_decrypt2 :
    Nettls_gnutls_bindings.gnutls_cipher_hd_t ->
    Netsys_mem.memory -> Netsys_mem.memory -> unit
  val gnutls_cipher_add_auth :
    Nettls_gnutls_bindings.gnutls_cipher_hd_t -> Bytes.t -> unit
  val gnutls_cipher_tag :
    Nettls_gnutls_bindings.gnutls_cipher_hd_t -> Bytes.t -> unit
  val gnutls_handshake_set_private_extensions :
    Nettls_gnutls_bindings.gnutls_session_t -> bool -> unit
  val gnutls_handshake_get_last_out :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_handshake_description_t
  val gnutls_handshake_get_last_in :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_handshake_description_t
  val gnutls_handshake_set_max_packet_length :
    Nettls_gnutls_bindings.gnutls_session_t -> int -> unit
  val gnutls_sign_algorithm_get_requested :
    Nettls_gnutls_bindings.gnutls_session_t ->
    int -> Nettls_gnutls_bindings.gnutls_sign_algorithm_t
  val gnutls_session_enable_compatibility_mode :
    Nettls_gnutls_bindings.gnutls_session_t -> unit
  val gnutls_record_disable_padding :
    Nettls_gnutls_bindings.gnutls_session_t -> unit
  val gnutls_record_get_max_size :
    Nettls_gnutls_bindings.gnutls_session_t -> int
  val gnutls_record_set_max_size :
    Nettls_gnutls_bindings.gnutls_session_t -> int -> unit
  val gnutls_server_name_set :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_server_name_type_t -> Bytes.t -> unit
  val gnutls_server_name_get :
    Nettls_gnutls_bindings.gnutls_session_t ->
    int -> Bytes.t * Nettls_gnutls_bindings.gnutls_server_name_type_t
  val gnutls_safe_renegotiation_status :
    Nettls_gnutls_bindings.gnutls_session_t -> bool
  val gnutls_supplemental_get_name :
    Nettls_gnutls_bindings.gnutls_supplemental_data_format_type_t -> string
  val gnutls_credentials_clear :
    Nettls_gnutls_bindings.gnutls_session_t -> unit
  val gnutls_key_generate : int -> string
  val gnutls_fingerprint :
    Nettls_gnutls_bindings.gnutls_digest_algorithm_t ->
    Nettls_gnutls_bindings.str_datum_p -> Bytes.t
  val gnutls_certificate_allocate_credentials :
    unit -> Nettls_gnutls_bindings.gnutls_certificate_credentials_t
  val gnutls_certificate_set_x509_system_trust :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t -> unit
  val gnutls_certificate_set_x509_trust_file :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    string -> Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_certificate_set_x509_trust_mem :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_certificate_set_x509_crl_file :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    string -> Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_certificate_set_x509_crl_mem :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_certificate_set_x509_key_file :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    string -> string -> Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_certificate_set_x509_key_mem :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_certificate_set_x509_simple_pkcs12_file :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    string -> Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> string -> unit
  val gnutls_certificate_set_x509_simple_pkcs12_mem :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> string -> unit
  val gnutls_certificate_set_x509_key :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.gnutls_x509_crt_t array ->
    Nettls_gnutls_bindings.gnutls_x509_privkey_t -> unit
  val gnutls_certificate_set_x509_trust :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.gnutls_x509_crt_t array -> int
  val gnutls_certificate_set_x509_crl :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.gnutls_x509_crl_t array -> int
  val gnutls_anon_allocate_server_credentials :
    unit -> Nettls_gnutls_bindings.gnutls_anon_server_credentials_t
  val gnutls_anon_allocate_client_credentials :
    unit -> Nettls_gnutls_bindings.gnutls_anon_client_credentials_t
  val gnutls_dh_params_init :
    unit -> Nettls_gnutls_bindings.gnutls_dh_params_t
  val gnutls_dh_params_import_raw :
    Nettls_gnutls_bindings.gnutls_dh_params_t ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.str_datum_p -> unit
  val gnutls_dh_params_import_pkcs3 :
    Nettls_gnutls_bindings.gnutls_dh_params_t ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_dh_params_generate2 :
    Nettls_gnutls_bindings.gnutls_dh_params_t -> int -> unit
  val gnutls_dh_params_cpy :
    Nettls_gnutls_bindings.gnutls_dh_params_t ->
    Nettls_gnutls_bindings.gnutls_dh_params_t -> unit
  val gnutls_certificate_set_dh_params :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.gnutls_dh_params_t -> unit
  val gnutls_anon_set_server_dh_params :
    Nettls_gnutls_bindings.gnutls_anon_server_credentials_t ->
    Nettls_gnutls_bindings.gnutls_dh_params_t -> unit
  val gnutls_psk_set_server_dh_params :
    Nettls_gnutls_bindings.gnutls_psk_server_credentials_t ->
    Nettls_gnutls_bindings.gnutls_dh_params_t -> unit
  val gnutls_dh_set_prime_bits :
    Nettls_gnutls_bindings.gnutls_session_t -> int -> unit
  val gnutls_dh_get_secret_bits :
    Nettls_gnutls_bindings.gnutls_session_t -> int
  val gnutls_dh_get_peers_public_bits :
    Nettls_gnutls_bindings.gnutls_session_t -> int
  val gnutls_dh_get_prime_bits :
    Nettls_gnutls_bindings.gnutls_session_t -> int
  val gnutls_dh_get_group :
    Nettls_gnutls_bindings.gnutls_session_t -> string * string
  val gnutls_dh_get_pubkey :
    Nettls_gnutls_bindings.gnutls_session_t -> string
  val gnutls_auth_get_type :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_credentials_type_t
  val gnutls_auth_server_get_type :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_credentials_type_t
  val gnutls_auth_client_get_type :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_credentials_type_t
  val gnutls_certificate_get_ours :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.const_str_datum_p
  val gnutls_certificate_activation_time_peers :
    Nettls_gnutls_bindings.gnutls_session_t -> float
  val gnutls_certificate_expiration_time_peers :
    Nettls_gnutls_bindings.gnutls_session_t -> float
  val gnutls_certificate_client_get_request_status :
    Nettls_gnutls_bindings.gnutls_session_t -> bool
  val gnutls_certificate_get_issuer :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.empty_flags ->
    Nettls_gnutls_bindings.gnutls_x509_crt_t
  val gnutls_certificate_set_verify_flags :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    Nettls_gnutls_bindings.gnutls_certificate_verify_flags -> unit
  val gnutls_certificate_set_verify_limits :
    Nettls_gnutls_bindings.gnutls_certificate_credentials_t ->
    int -> int -> unit
  val gnutls_openpgp_send_cert :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_openpgp_crt_status_t -> unit
  val gnutls_srp_allocate_client_credentials :
    unit -> Nettls_gnutls_bindings.gnutls_srp_client_credentials_t
  val gnutls_srp_set_client_credentials :
    Nettls_gnutls_bindings.gnutls_srp_client_credentials_t ->
    string -> string -> unit
  val gnutls_srp_allocate_server_credentials :
    unit -> Nettls_gnutls_bindings.gnutls_srp_server_credentials_t
  val gnutls_srp_set_server_credentials_file :
    Nettls_gnutls_bindings.gnutls_srp_server_credentials_t ->
    string -> string -> unit
  val gnutls_srp_server_get_username :
    Nettls_gnutls_bindings.gnutls_session_t -> string
  val gnutls_srp_set_prime_bits :
    Nettls_gnutls_bindings.gnutls_session_t -> int -> unit
  val gnutls_srp_verifier :
    string ->
    string ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.str_datum_p -> string
  val gnutls_psk_allocate_client_credentials :
    unit -> Nettls_gnutls_bindings.gnutls_psk_client_credentials_t
  val gnutls_psk_set_client_credentials :
    Nettls_gnutls_bindings.gnutls_psk_client_credentials_t ->
    string ->
    Nettls_gnutls_bindings.str_datum_p ->
    Nettls_gnutls_bindings.gnutls_psk_key_flags -> unit
  val gnutls_psk_allocate_server_credentials :
    unit -> Nettls_gnutls_bindings.gnutls_psk_server_credentials_t
  val gnutls_psk_set_server_credentials_file :
    Nettls_gnutls_bindings.gnutls_psk_server_credentials_t -> string -> unit
  val gnutls_psk_set_server_credentials_hint :
    Nettls_gnutls_bindings.gnutls_psk_server_credentials_t -> string -> unit
  val gnutls_psk_server_get_username :
    Nettls_gnutls_bindings.gnutls_session_t -> string
  val gnutls_psk_client_get_hint :
    Nettls_gnutls_bindings.gnutls_session_t -> string
  val gnutls_x509_crt_init : unit -> Nettls_gnutls_bindings.gnutls_x509_crt_t
  val gnutls_x509_crt_import :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.const_str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_x509_crt_export :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> Bytes.t
  val gnutls_x509_crt_get_issuer_dn :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> Bytes.t
  val gnutls_x509_crt_get_issuer_dn_oid :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> int -> Bytes.t
  val gnutls_x509_crt_get_dn :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> Bytes.t
  val gnutls_x509_crt_get_dn_oid :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> int -> Bytes.t
  val gnutls_x509_crt_check_hostname :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> string -> bool
  val gnutls_x509_crt_get_signature_algorithm :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.gnutls_sign_algorithm_t
  val gnutls_x509_crt_get_signature :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> Bytes.t
  val gnutls_x509_crt_get_version :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> int
  val gnutls_x509_crt_get_key_id :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.empty_flags -> Bytes.t
  val gnutls_x509_crt_get_authority_key_id :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> Bytes.t * bool
  val gnutls_x509_crt_get_subject_key_id :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> Bytes.t * bool
  val gnutls_x509_crt_get_subject_unique_id :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> Bytes.t
  val gnutls_x509_crt_get_issuer_unique_id :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> Bytes.t
  val gnutls_x509_crt_get_authority_info_access :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    int -> Nettls_gnutls_bindings.gnutls_info_access_what_t -> string * bool
  val gnutls_x509_crt_get_activation_time :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> float
  val gnutls_x509_crt_get_expiration_time :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> float
  val gnutls_x509_crt_get_serial :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> Bytes.t
  val gnutls_x509_crt_get_pk_algorithm :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.gnutls_pk_algorithm_t * int
  val gnutls_x509_crt_get_pk_rsa_raw :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> string * string
  val gnutls_x509_crt_get_pk_dsa_raw :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    string * string * string * string
  val gnutls_x509_crt_get_subject_alt_name :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    int ->
    Nettls_gnutls_bindings.gnutls_x509_subject_alt_name_t * Bytes.t * bool
  val gnutls_x509_crt_get_subject_alt_othername_oid :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    int -> Nettls_gnutls_bindings.gnutls_x509_subject_alt_name_t * Bytes.t
  val gnutls_x509_crt_get_issuer_alt_name :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    int ->
    Nettls_gnutls_bindings.gnutls_x509_subject_alt_name_t * Bytes.t * bool
  val gnutls_x509_crt_get_issuer_alt_othername_oid :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    int -> Nettls_gnutls_bindings.gnutls_x509_subject_alt_name_t * Bytes.t
  val gnutls_x509_crt_get_ca_status :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> bool
  val gnutls_x509_crt_get_basic_constraints :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> bool * bool * int
  val gnutls_x509_crt_get_key_usage :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.key_usage * bool
  val gnutls_x509_crt_get_extension_oid :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> int -> Bytes.t
  val gnutls_x509_crt_get_extension_info :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> int -> Bytes.t * bool
  val gnutls_x509_crt_get_extension_data :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> int -> Bytes.t
  val gnutls_x509_crt_check_issuer :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> bool
  val gnutls_x509_crt_list_verify :
    Nettls_gnutls_bindings.gnutls_x509_crt_t array ->
    Nettls_gnutls_bindings.gnutls_x509_crt_t array ->
    Nettls_gnutls_bindings.gnutls_x509_crl_t array ->
    Nettls_gnutls_bindings.gnutls_certificate_verify_flags ->
    Nettls_gnutls_bindings.gnutls_certificate_status_t
  val gnutls_x509_crt_verify :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.gnutls_x509_crt_t array ->
    Nettls_gnutls_bindings.gnutls_certificate_verify_flags ->
    Nettls_gnutls_bindings.gnutls_certificate_status_t
  val gnutls_x509_crl_verify :
    Nettls_gnutls_bindings.gnutls_x509_crl_t ->
    Nettls_gnutls_bindings.gnutls_x509_crt_t array ->
    Nettls_gnutls_bindings.gnutls_certificate_verify_flags ->
    Nettls_gnutls_bindings.gnutls_certificate_status_t
  val gnutls_x509_crt_check_revocation :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.gnutls_x509_crl_t array -> bool
  val gnutls_x509_crt_get_fingerprint :
    Nettls_gnutls_bindings.gnutls_x509_crt_t ->
    Nettls_gnutls_bindings.gnutls_digest_algorithm_t -> Bytes.t
  val gnutls_x509_crt_get_key_purpose_oid :
    Nettls_gnutls_bindings.gnutls_x509_crt_t -> int -> Bytes.t * bool
  val gnutls_x509_privkey_init :
    unit -> Nettls_gnutls_bindings.gnutls_x509_privkey_t
  val gnutls_x509_privkey_import :
    Nettls_gnutls_bindings.gnutls_x509_privkey_t ->
    Nettls_gnutls_bindings.const_str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_x509_privkey_import_pkcs8 :
    Nettls_gnutls_bindings.gnutls_x509_privkey_t ->
    Nettls_gnutls_bindings.const_str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t ->
    string -> Nettls_gnutls_bindings.gnutls_pkcs_encrypt_flags_t -> unit
  val gnutls_x509_crl_init : unit -> Nettls_gnutls_bindings.gnutls_x509_crl_t
  val gnutls_x509_crl_import :
    Nettls_gnutls_bindings.gnutls_x509_crl_t ->
    Nettls_gnutls_bindings.const_str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val net_have_pubkey : unit -> bool
  val gnutls_pubkey_init : unit -> Nettls_gnutls_bindings.gnutls_pubkey_t
  val gnutls_privkey_init : unit -> Nettls_gnutls_bindings.gnutls_privkey_t
  val gnutls_pubkey_import :
    Nettls_gnutls_bindings.gnutls_pubkey_t ->
    Nettls_gnutls_bindings.const_str_datum_p ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t -> unit
  val gnutls_pubkey_import_url :
    Nettls_gnutls_bindings.gnutls_pubkey_t -> string -> int -> unit
  val gnutls_pubkey_import_privkey :
    Nettls_gnutls_bindings.gnutls_pubkey_t ->
    Nettls_gnutls_bindings.gnutls_privkey_t -> int -> int -> unit
  val gnutls_privkey_import_x509 :
    Nettls_gnutls_bindings.gnutls_privkey_t ->
    Nettls_gnutls_bindings.gnutls_x509_privkey_t -> int -> unit
  val gnutls_pubkey_encrypt_data :
    Nettls_gnutls_bindings.gnutls_pubkey_t ->
    int -> Nettls_gnutls_bindings.const_str_datum_p -> string
  val gnutls_privkey_decrypt_data :
    Nettls_gnutls_bindings.gnutls_privkey_t ->
    int -> Nettls_gnutls_bindings.const_str_datum_p -> string
  val gnutls_privkey_sign_data :
    Nettls_gnutls_bindings.gnutls_privkey_t ->
    Nettls_gnutls_bindings.gnutls_digest_algorithm_t ->
    int -> Nettls_gnutls_bindings.const_str_datum_p -> string
  val gnutls_pubkey_verify_data2 :
    Nettls_gnutls_bindings.gnutls_pubkey_t ->
    Nettls_gnutls_bindings.gnutls_sign_algorithm_t ->
    int ->
    Nettls_gnutls_bindings.const_str_datum_p ->
    Nettls_gnutls_bindings.const_str_datum_p -> unit
  val b_error_of_name : string -> Nettls_gnutls_bindings.error_code
  exception Null_pointer
  exception Error of Nettls_gnutls_bindings.error_code
  exception Short_memory_buffer of int
  type memory =
      (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
  type gnutls_credentials =
      [ `Anon_client of
          Nettls_gnutls_bindings.gnutls_anon_client_credentials_t
      | `Anon_server of
          Nettls_gnutls_bindings.gnutls_anon_server_credentials_t
      | `Certificate of
          Nettls_gnutls_bindings.gnutls_certificate_credentials_t
      | `Psk_client of Nettls_gnutls_bindings.gnutls_psk_client_credentials_t
      | `Psk_server of Nettls_gnutls_bindings.gnutls_psk_server_credentials_t
      | `Srp_client of Nettls_gnutls_bindings.gnutls_srp_client_credentials_t
      | `Srp_server of Nettls_gnutls_bindings.gnutls_srp_server_credentials_t ]
  val gnutls_credentials_set :
    Nettls_gnutls_bindings.gnutls_session_t ->
    Nettls_gnutls_bindings.gnutls_credentials -> unit
  val b_set_pull_callback :
    Nettls_gnutls_bindings.gnutls_session_t ->
    (Nettls_gnutls_bindings.memory -> int) -> unit
  val b_set_push_callback :
    Nettls_gnutls_bindings.gnutls_session_t ->
    (Nettls_gnutls_bindings.memory -> int -> int) -> unit
  val b_set_pull_timeout_callback :
    Nettls_gnutls_bindings.gnutls_session_t -> (int -> bool) -> unit
  val b_set_verify_callback :
    Nettls_gnutls_bindings.gnutls_session_t ->
    (Nettls_gnutls_bindings.gnutls_session_t -> bool) -> unit
  val set_fd :
    Nettls_gnutls_bindings.gnutls_session_t -> Unix.file_descr -> unit
  val b_set_db_callbacks :
    Nettls_gnutls_bindings.gnutls_session_t ->
    (string -> string -> unit) ->
    (string -> unit) -> (string -> string) -> unit
  val string_of_verification_status_flag :
    Nettls_gnutls_bindings.gnutls_certificate_status_t_flag -> string
  val gnutls_x509_crt_list_import :
    string ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t ->
    Nettls_gnutls_bindings.gnutls_certificate_import_flags ->
    Nettls_gnutls_bindings.gnutls_x509_crt_t array
  val gnutls_x509_crl_list_import :
    string ->
    Nettls_gnutls_bindings.gnutls_x509_crt_fmt_t ->
    Nettls_gnutls_bindings.gnutls_certificate_import_flags ->
    Nettls_gnutls_bindings.gnutls_x509_crl_t array
end
ocamlnet-4.1.2/doc/html-main/type_Netmime.html0000644000175000017500000006472312731530352017741 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime sig
  type store = [ `File of string | `Memory ]
  exception Immutable of string
  class type mime_header_ro =
    object
      method field : string -> string
      method fields : (string * string) list
      method multiple_field : string -> string list
    end
  class type mime_header =
    object
      method delete_field : string -> unit
      method field : string -> string
      method fields : (string * string) list
      method multiple_field : string -> string list
      method ro : bool
      method set_fields : (string * string) list -> unit
      method update_field : string -> string -> unit
      method update_multiple_field : string -> string list -> unit
    end
  class type mime_body_ro =
    object
      method finalize : unit -> unit
      method open_value_rd : unit -> Netchannels.in_obj_channel
      method store : Netmime.store
      method value : string
    end
  class type mime_body =
    object
      method finalize : unit -> unit
      method open_value_rd : unit -> Netchannels.in_obj_channel
      method open_value_wr : unit -> Netchannels.out_obj_channel
      method ro : bool
      method set_value : string -> unit
      method store : store
      method value : string
    end
  type complex_mime_message = Netmime.mime_header * Netmime.complex_mime_body
  and complex_mime_body =
      [ `Body of Netmime.mime_body
      | `Parts of Netmime.complex_mime_message list ]
  type complex_mime_message_ro =
      Netmime.mime_header_ro * Netmime.complex_mime_body_ro
  and complex_mime_body_ro =
      [ `Body of Netmime.mime_body_ro
      | `Parts of Netmime.complex_mime_message_ro list ]
  type mime_message = Netmime.mime_header * [ `Body of Netmime.mime_body ]
  type mime_message_ro =
      Netmime.mime_header_ro * [ `Body of Netmime.mime_body_ro ]
  class basic_mime_header : (string * string) list -> mime_header
  val basic_mime_header : (string * string) list -> Netmime.mime_header
  class wrap_mime_header : #Netmime.mime_header -> mime_header
  class wrap_mime_header_ro : #Netmime.mime_header_ro -> mime_header
  val wrap_mime_header_ro : #Netmime.mime_header_ro -> Netmime.mime_header
  class memory_mime_body : string -> mime_body
  val memory_mime_body : string -> Netmime.mime_body
  class file_mime_body : ?fin:bool -> string -> mime_body
  val file_mime_body : ?fin:bool -> string -> Netmime.mime_body
  class wrap_mime_body : #Netmime.mime_body -> mime_body
  class wrap_mime_body_ro : #Netmime.mime_body_ro -> mime_body
  val wrap_mime_body_ro : #Netmime.mime_body_ro -> Netmime.mime_body
  val wrap_complex_mime_message_ro :
    Netmime.complex_mime_message_ro -> Netmime.complex_mime_message
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.direct_socket_acceptor-c.html0000644000175000017500000004260712731530352025660 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.direct_socket_acceptor

Class Uq_engines_compat.direct_socket_acceptor

class direct_socket_acceptor : Unix.file_descr -> Unixqueue.event_system -> server_endpoint_acceptor

ocamlnet-4.1.2/doc/html-main/Tls.html0000644000175000017500000012156312731530352016040 0ustar gerdgerd Ocamlnet 4 Reference Manual : Tls

Tls


TLS support

Since Ocamlnet-4, all implemented network protocols support now TLS. This document here explains how TLS is generally configured, and points to other pages for details.

Before Ocamlnet-4, there was some incomplete TLS support for HTTP clients. At that time, the ocaml-ssl wrappers were used to link with openssl. This was mainly a quick solution to satisfy the demand, but we could never implement all the features we would like to have. Also, the development of ocaml-ssl seems to have stalled, and because of this, the migration to a new TLS library was started.

The TLS provider

Ocamlnet-4 uses first class modules to separate the definition of the TLS provider (the library implementing the TLS protocol) from the TLS user (the protocol interpreters in Ocamlnet). This mainly means that the TLS provider is not hard-coded into Ocamlnet, but that the same code can be linked with different providers. Even better, it is possible to plug in providers at runtime, and - believe it or not - to use several providers at the same time.

The definition of the TLS provider is Netsys_crypto_types.TLS_PROVIDER. Any module implementing this module type can be plugged into the system. There is the notion of a "current" provider (Netsys_crypto.current_tls), so that if any TLS provider is linked into the executable, the code checks whether the current provider is set, and automatically uses it. The protocol interpreters, however, also allow it to set the TLS provider per client, or even per connection.

The provider defines types and functions that implement the TLS security mechanisms. Using the provider directly is a bit tricky, because the types it defines must always be in scope when value of these types are manipulated (a consequence of using first-class modules). Because of this, the protocol interpreters normally use the provider only via a thin layer around it that deals with these issues, Netsys_tls.

GnuTLS as TLS provider

Currently, there is only one provider, GnuTLS. The bindings for GnuTLS are already quite complete, and are available as nettls-gnutls library. So, enabling TLS in a program is quite easy:

  • Add nettls-gnutls to the list of findlib packages
  • Call Nettls_gnutls.init() (which mainly forces that the bindings are really linked in). After init, Netsys_crypto.current_tls returns the GnuTLS provider.
OPAM users: Note that the OPAM package for OCamlnet does not build the TLS provider by default. The trigger for this is the presence of the conf-gnutls OPAM package, i.e. do opam install conf-gnutls to rebuild with TLS.

At the moment, not all of the functionaliy of GnuTLS is available through the provider API. If necessary, you can access the bindings directly:

Configurations, and endpoints

Almost always TLS needs to be configured. For clients, there is a kind of secure default (by using the system-installed list of CA certificates as trusted list), but even then the configuration needs to be frequently adapted to the individual requirements.

Note that we currently only support X.509 configurations (although GnuTLS also supports OpenPGP, SRP, and a few more).

You get the secure default for clients by running:

let provider = Netsys_crypto.current_tls()

let tls_config = 
  Netsys_tls.create_x509_config
     ~system_trust:true
     ~peer_auth:`Required
     provider
 

You can add more certificates to the trust list by passing the trust option, e.g.

let tls_config = 
  Netsys_tls.create_x509_config
     ~system_trust:true
     ~trust:[ `PEM_file:"/path/file/with/certs" ]
     ~peer_auth:`Required
     provider
 

For servers, the configuration looks a bit different. You need a server certificate with a private key:

let tls_config = 
  Netsys_tls.create_x509_config
     ~keys:[ (`PEM_file "/path/to/cert", `PEM_file "/path/to/key", None) ]
     ~peer_auth:`None
     tp
 

(replace None by Some "password" if the key is password-protected). This example does not authenticate the client (peer_auth:`None). If you need that, change peer_auth back to `Required, and also pass trust so that the CA signing the client certificate is trusted.

The value tls_config is actually also a first-class module, and includes the provider as sub-module:

module type TLS_CONFIG =
  sig
    module TLS : TLS_PROVIDER
    val config : TLS.config
  end

Because of this, it is sufficient to pass a TLS_CONFIG module to a protocol implementation to tell it about the combination of a provider and a configuration (e.g. look at the tls_config argument of Netftp_fs.ftp_fs). The reason for this kind of wrapping is that the type of the configuration is defined by the provider, and hence the configuration cannot exist without provider (the OCaml type checker enforces this).

There is also

module type TLS_ENDPOINT =
  sig
    module TLS : TLS_PROVIDER
    val endpoint : TLS.endpoint
  end

and even

module type FILE_TLS_ENDPOINT =
  sig
    module TLS : TLS_PROVIDER
    val endpoint : TLS.endpoint
    val rd_file : Unix.file_descr
    val wr_file : Unix.file_descr
  end

An "endpoint" denotes here the TLS state for a single connection.

Using TLS in clients

HTTP: In Nethttp_client, TLS is now automatically available once a TLS provider is initialized. Just submit "https" URLs, and that's it. There is no Https_client module anymore (as in earlier versions of Ocamlnet).

If you need to change the TLS configuration (or want to enable a different provider), you can set the Nethttp_client.http_options.tls option, e.g.

let http_options = pipeline # get_options
let new_options =
  { http_options with
      Nethttp_client.tls = Some tls_config
  }
pipeline # set_options new_options

Nethttp_fs inherits the automatic configuration from Nethttp_client.

FTP: After starting an FTP session, you need to enable TLS explicitly using Netftp_client.tls_method. For instance:

let client = new Netftp_client.ftp_client() ;;
client # exec (connect_method ~host ());
client # exec (tls_method ~config ~required ());
client # exec (login_method ~user ~get_password ~get_account ());

Here, config is the TLS configuration. Set required if TLS is mandatory, and the file transfer will fail for servers not supporting TLS.

For Netftp_fs, things are a bit simpler: Just pass tls_enabled:true when creating the fs object:

let fs = Netftp_fs.ftp_fs ~tls_enabled:true "ftp://user@host/path"

Again, you can set whether TLS is required: tls_required. There is also the tls_config option to set an alternate TLS configuration.

SMTP and POP: These two clients have now additional methods starttls (SMTP) and stls (POP), respectively. These methods can be called when the right moment has come to switch to TLS. They take the TLS configuration and the domain name of the peer as arguments, e.g.

smtp_client # starttls ~peer_name:(Some "smtp.google.com") config

RPC: You need to run the client in `Socket mode, and pass the special TLS socket configuration, e.g.

let socket_config =
  Rpc_client.tls_socket_config config

let client =
  Rpc_client.create2
    (`Socket(Rpc.Tcp, connect_address, socket_config))
    program
    esys

where config is still the TLS configuration.

Client features

Note that TLS security is bound to domain names, and not IP addresses. Because of this, you cannot create TLS sessions when the host name is only an IP address. (In some cases, Ocamlnet allows it to pass the domain name separately. This is the peer_name argument you can find here and there.)

All clients support SNI, and thus can talk to name-based virtual servers. SNI is a protocol extension that allows it clients to announce early in the feature negotiation to which domain they want to talk. SNI is not available on all servers, though.

So far, only Nethttp_client supports the caching of TLS sessions between TCP connects, but it needs to be explicitly configured (method set_tls_cache). (A "TLS session" is an established security context where both parties know the secret credentials, and can exchange confidential messages. TLS sessions are independent of TCP connections, i.e. the next TCP connection can reuse the same TLS session if both parties allow it.)

Using TLS in servers

HTTP: If you use the Netplex encapsulation of the server processes, TLS is normally available. Just add the required configuration to the configuration file: See Configuring TLS for details.

If you use the more low-level modules Nethttpd_kernel, Nethttpd_reactor and Nethttpd_engine, things are a bit more complicated. The TLS configuration is hidden in the Nethttpd_kernel.http_protocol_config, and you need here to set config_tls.

Note that these low-level modules do not provide TLS session caching automatically. You need to do this on your own by getting an Nethttpd_kernel.http_protocol_hooks object, and calling tls_set_cache there. For the Netplex-encapsulated version, this is already done.

RPC: This is almost identical to the client case:

let socket_config =
  Rpc_server.tls_socket_config config

let server =
  Rpc_server.create2
    (`Socket(Rpc.Tcp, connect_address, socket_config))

If you use Rpc_netplex, the rpc_factory doesn't allow to configure TLS via the configuration file. However, you can do it on your own, by calling Netplex_config.read_tls_config to extract the TLS configuration from the file.

Server features

The HTTP server supports SNI, and thus name-based virtual hosting. For every domain, just configure a separate certificate.

Wildcard certificates are supported.

Both HTTP and RPC servers allow it to pass down the user name of a client that was authenticated with a client certificate. For HTTP, this name is available in the environment as REMOTE_USER variable. For RPC, you can use the Rpc_server.auth_transport pseudo-authentication method (which does nothing on the RPC level, but just looks whether there is a more low-level way of authentication like a client certificate). The user name is then returned by Rpc_server.get_user.

So far, we don't support that servers request a client certificate in a rehandshake.

Programming with TLS

As already mentioned, it is normally not advisable to program with the TLS provider directly. Better ways:

In all cases, it is expected that there is already a bidirectional data connection between the client and the server. Unlike in the old ocaml-ssl binding, there is no such thing like a TLS-enabled socket. Rather, TLS can be started on top of any kind of bidirectional connection, and instead of using special versions of the connect and accept routines you can run the TLS handshake on the already existing connection.

So, the following steps are needed:

  • Establish the bidirectional data connection on a file descriptor (which is often a socket, but is not restricted to this)
  • Create the TLS endpoint for the TLS configuration. With Netsys_tls, this is done by calling Netsys_tls.create_file_endpoint.
  • The handshake is done by calling Netsys_tls.handshake. It is not mandatory for the user to call this function, but if not done, the call is triggered by the next step implicitly.
  • Now use Netsys_tls.recv, Netsys_tls.mem_recv, Netsys_tls.send and Netsys_tls.mem_send to exchange application data with the peer.
  • Finally, invoke Netsys_tls.shutdown to shut down the secure data channel. Note that this function does not shut down the underlying file descriptor, but just signals the end of the data transfer on TLS level.
The Netsys_tls module assumes non-blocking data transfer. All I/O functions (including handshake and shutdown) may raise the two special exceptions Netsys_types.EAGAIN_RD and Netsys_types.EAGAIN_WR when they need to be called again when there is data to read, and buffer space for the next write, respectively. Note that it is possible that a send raises Netsys_types.EAGAIN_RD and that a recv raises Netsys_types.EAGAIN_WR.

Example for using TLS on the descriptor fd (omitting exception handling, which is ok for synchronous descriptors):

(* Get fd e.g. with Unix.socket, and connect it to the peer. *)

let endpoint =
  Netsys_tls.create_file_endpoint
     ~role:`Client
     ~rd:fd
     ~wr:fd
     ~peer_name:(Some "www.domain.com")
     tls_config

let () =
  Netsys_tls.handshake endpoint

let n =
  Netsys_tls.recv endpoint s pos len

let n =
  Netsys_tls.send endpoint s pos len

let () =
  Netsys_tls.shutdown endpoint Unix.SHUTDOWN_ALL

The Netsys_tls module supports renegotiations of the security context. Normally, such renegotiations are just accepted, and automatically carried out. The Netsys_tls.recv function allows it to intercept a renegotiation request, and to refuse it (or otherwise react on it) with the on_rehandshake callback.

Note that passing the domain name to Netsys_tls.create_file_endpoint is mandatory for clients that authenticate servers (i.e. for the "normal" case). Essentially, TLS ensures then that the server reachable under the IP address for the domain is really the server it claims to be.

The Netsys.gread and functions also support TLS-protected descriptors. You need, however, pass the TLS endpoint explicitly to these functions, e.g.

let fd_style = `TLS tls_endpoint

(* Now use: *)
let n = Netsys.gread fd_style fd s pos len
let n = Netsys.gwrite fd_style fd s pos len
let () = Netsys.gshutdown fd_style Unix.SHUTDOWN_ALL

Similar "convenience functions" exist for Netchannels (see Netchannels_crypto.tls_layer) and multiplex controllers (see Uq_multiplex.tls_multiplex_controller).

Some word on the shutdown of a TLS session: TLS implements this by exchanging a special alert message called "close notify". Either party of the connection can start closing the data channel by sending such a "close notify" to the other side, which means that no more data will follow. The other side can send more data, but will finally reply with another "close notify". At this point, the connection is completely shut down on the TLS level. The "close notify" is just a special byte pattern in the encrypted data channel. Because it is encrypted, nobody else can fake such a message.

Note that this part of the protocol was not done right in the first revisions of TLS (in particular in SSL 1.0 and 2.0), and even today many protocol implementations are broken in this respect. In particular, you should know that:

  • Some implementations just tear down the TCP connection instead of going through the "close notify" protocol. It depends very much on the application protocol whether this is ok or not. For example, such a "hard termination" of the connection is ok between HTTP messages when there is Content-length header, but it is not ok to use it for signaling the end of a HTTP message when this header is missing.
  • Often, just one party sends a "close notify", but does not wait on the closure message from the other side. For some protocols (e.g. HTTP) this is explcitly allowed, for others not.
  • Some implementations only react on a "close notify" when a closure on TCP level follows. Because of this, it is common practice to just do a one-sided TCP shutdown (SHUTDOWN_SEND) directly after sending a "close notify", at least when the protocol allows this.
Note you have to program the latter explicitly. Neither Netsys_tls nor one of the other ways of interacting with the TLS provider will trigger a TCP shutdown on its own.

X.509 Certificates

For an introduction see Credentials for TLS.

Ocamlnet includes now a simple parser for X.509 certificates. You can use this parser to add checks to clients and servers whether the certificates submitted by the peer are acceptable or not.

The data structure used here is Netx509.x509_certificate. If you get the certificate as binary blob it is normally DER-encoded, and you can use Netx509.x509_certificate_from_DER to parse it. Many protocol interpreters also export an object Nettls_support.tls_session_props which includes the already decoded certificate.

There are also functions for dealing with distinguished names:

The most frequently used certificate extensions are also supported in Netx509. For writing parsers there is the generic ASN.1 module Netasn1.
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.TLS_EXCEPTIONS.html0000644000175000017500000004225412731530352024651 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_EXCEPTIONS sig
  exception EAGAIN_RD
  exception EAGAIN_WR
  exception TLS_switch_request
  exception TLS_switch_response of bool
  exception TLS_error of string
  exception TLS_warning of string
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_util.html0000644000175000017500000004237012731530352021164 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_util sig
  val std_error_response : Nethttpd_types.error_response_params -> string
  val std_error_log_string : Nethttpd_types.request_info -> string -> string
  val std_access_log_string : Nethttpd_types.full_info -> string
  val std_debug_access_log_string : Nethttpd_types.full_info -> string
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.pseudo_async_out_channel-c.html0000644000175000017500000004262612731530352026232 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.pseudo_async_out_channel

Class Uq_engines_compat.pseudo_async_out_channel

class pseudo_async_out_channel : #Netchannels.raw_out_channel -> async_out_channel

ocamlnet-4.1.2/doc/html-main/type_Rpc_client.Debug.html0000644000175000017500000004201412731530352021437 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.Debug sig
  val enable : bool Pervasives.ref
  val enable_ptrace : bool Pervasives.ref
  val ptrace_verbosity : Rpc_util.verbosity Pervasives.ref
  val disable_for_client : Rpc_client.t -> unit
end
ocamlnet-4.1.2/doc/html-main/Uq_transfer.html0000644000175000017500000006767212731530352017601 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer

Module Uq_transfer

module Uq_transfer: sig .. end

Transfer engines




Transfer engines



Transfer engines



Transfer engines copy data between file descriptors. This kind of engine is likely to be declared as deprecated in the future. If possible, one should use multiplex controllers (see below), and for copying streams the generic copier Uq_io.copy_e is a better choice.

The pure types async_in_channel and async_out_channel have been proven to be useful for bridging with Netchannels.

class type async_out_channel = object .. end
An asynchrounous output channel provides methods to output data to a stream descriptor.
class type async_in_channel = object .. end
An asynchrounous input channel provides methods to input data from a stream descriptor.
class pseudo_async_out_channel : #Netchannels.raw_out_channel -> async_out_channel
Takes a Netchannels.raw_out_channel as an asynchronous channel.
class pseudo_async_in_channel : #Netchannels.raw_in_channel -> async_in_channel
Takes a Netchannels.raw_in_channel as an asynchronous channel.
class receiver : src:Unix.file_descr -> dst:#async_out_channel -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines.engine
This engine copies all data from the src file descriptor to the dst output channel.
class sender : src:#async_in_channel -> dst:Unix.file_descr -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines.engine
This engine copies all data from the src input channel to the dst file descriptor.
class type async_out_channel_engine = object .. end
Combination of engine + async_out_channel
class type async_in_channel_engine = object .. end
Combination of engine + async_in_channel
class output_async_descr : dst:Unix.file_descr -> ?buffer_size:int -> ?close_dst:bool -> Unixqueue.event_system -> async_out_channel_engine
This engine implements an async_out_channel for the output descriptor dst.
class input_async_descr : src:Unix.file_descr -> ?buffer_size:int -> ?close_src:bool -> Unixqueue.event_system -> async_in_channel_engine
The corresponding class for asynchronous input channels.
type copy_task = [ `Bidirectional of Unix.file_descr * Unix.file_descr
| `Tridirectional of Unix.file_descr * Unix.file_descr * Unix.file_descr
| `Uni_socket of Unix.file_descr * Unix.file_descr
| `Unidirectional of Unix.file_descr * Unix.file_descr ]
Specifies the task the copier class has to do:

  • `Unidirectional(src,dst): Data from src are copied to dst. EOF of src causes that both descriptors are closed.
  • `Uni_socket(src,dst): Data from src are copied to dst. EOF of src causes that dst is shut down for sending; all descriptors remain open. It is required that dst is a socket.
  • `Bidirectional(bi1,bi2): Data from bi1 are copied to bi2, and data from bi2 are copied to bi1. EOF of one descriptor causes that the other descriptor is shut down for sending. When both descriptors are at EOF, both are closed. It is required that bi1 and bi2 are sockets.
  • `Tridirectional(bi,dst,src): Data from bi are copied to dst, and data from src are copied to bi (i.e. a bidirectional descriptor is split up into two unidirectional descriptors). EOF of bi causes that dst is closed. EOF of src causes that bi is shut down for sending. EOF in both directions causes that all descriptors are closed. It is required that bi is a socket.

class copier : copy_task -> Unixqueue.event_system -> [unit] Uq_engines.engine
This engine copies data between file descriptors as specified by the copy_task argument.
type onshutdown_out_spec = [ `Action of
async_out_channel_engine ->
Uq_engines.multiplex_controller -> unit Uq_engines.engine_state -> unit
| `Ignore
| `Initiate_shutdown ]
See class output_async_mplex for explanations
type onshutdown_in_spec = [ `Action of
async_in_channel_engine ->
Uq_engines.multiplex_controller -> unit Uq_engines.engine_state -> unit
| `Ignore
| `Initiate_shutdown ]
See class input_async_mplex for explanations
class output_async_mplex : ?onclose:[ `Ignore | `Write_eof ] -> ?onshutdown:onshutdown_out_spec -> ?buffer_size:int -> Uq_engines.multiplex_controller -> async_out_channel_engine
Creates an asynchronous output channel writing to the multiplex controller (see also output_async_descr for the corresponding class writing to a single descriptor).
class input_async_mplex : ?onshutdown:onshutdown_in_spec -> ?buffer_size:int -> Uq_engines.multiplex_controller -> async_in_channel_engine
Creates an asynchronous input channel reading from the multiplex controller.
ocamlnet-4.1.2/doc/html-main/Netmcore_tut.html0000644000175000017500000024345312731530352017751 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_tut

Netmcore_tut


Netmulticore Tutorial

Contents

This manual gives an overview of Netmulticore, which allows it to manage subprocesses for speeding up computations on multicore CPU's. Netmulticore tries to overcome a limitation of OCaml's runtime, namely that only one thread at a time can get the CPU. Because of this, multi-threaded programs cannot make use of the additional power of multicore CPU's.

Readers are encouraged to first have a look at Netmcore_basics, which is more fundamental and doesn't use unsafe language features.

Since OCaml-4.01: This OCaml version changed the semantics of the built-in primitives caml_modify and caml_initialize. Essentially, it is no longer possible to modify OCaml values residing outside the regular OCaml heap. As we do this inside Netmulticore, this change affects this library. Fortunately, there is a workaround on systems supporting weak symbols (all ELF systems and OS X): Here, caml_modify and caml_initialize are overridden by Netmulticore so that they are again compatible. Note that this is a global modification of the runtime system!

Future versions of Ocamlnet may solve this problem differently.

The approach of Netmulticore is to spawn subprocesses acting in the role of worker threads. Processes are separated from each other, and hence there is normally no direct way of getting into interaction. The help of the operating system is required here - a classic example of IPC (interprocess communication) are pipes, which create a data stream from one process to the other. Of course, we want here even closer interaction than this. Another, rarely used IPC mechanism is shared memory. This means that a block of RAM is allocated and mapped into all processes. When one process mutates a RAM cell in a shared block, the other processes immediately see this mutation, so that there is no system call overhead for transporting data. Actually, there is a bit of overhead in modern computers when this technique is used, but it is only occuring on the hardware level, and is very fast.

Netmulticore does not only allocate a shared block of RAM, but also manages it. Ideally, using the shared block would be as simple as using normal, process-local memory. Unfortunately, this is not possible, but the design of Netmulticore allows it to come quite close to this ideal. With Netmulticore a process can write normal Ocaml values like strings, tuples or records to the shared block, and the other processes can directly access this data as if it were in normal RAM. Unfortunately, one cannot use direct assignment to do such writing to the shared block, but has to follow special programming rules which ensure that the shared block remains in a consistent state. Large parts of this tutorial explain how to accomplish this.

The list of features supported by Netmulticore:

  • Creation of worker processes
  • Management of shared resources like file descriptors and shared memory blocks
  • Management of shared RAM pools that are mapped to the same address in all worker processes
  • Management of shared heaps, i.e. containers for Ocaml values
  • Garbage collection for shared heaps
  • Predefined data structures that live in shared heaps
  • Synchronization primitives (locks, condition variables)
  • Message passing between worker processes
  • Integration with Netplex
Before you start looking at Netmulticore, I should also give a warning. Netmulticore requires unsafe programming elements which can, if used the wrong way, lead to corrupt results or even crash the program. This is, to some degree, comparable to interfacing the Ocaml runtime on the C level. Unfortunately, when it comes to parallel programming, such unsafeness is unavoidable if you want to get real speedups of your program. Note that multi-threading suffers from the safe problem, and is in no way different.

Design

The process hierarchy

When processes start other processes, the Unix system design defines a relation between processes: The started workers are children of the process requesting the starts. An immediate effect of this is that only the requesting process can wait for the termination of the children. There are more implications than this, but it should be clear that we have to take the relations between processes into account.

When a Netmulticore program is started, the implicitly created first process has a special role. It is called the master process, and it is normally not used for doing the real work. It is merely acting as a supervisor managing the workers. The tasks of the master process include the management of the resource table, and of course watching the lifetime of the workers. The master normally starts quickly the first worker process, which in turn starts as many workers as needed for accomplishing the computation.

Now, what does it mean to start processes? Unix only defines this via the fork system call. When doing a fork the requesting process is duplicated (i.e. RAM contents and many resources are copied, with only a few exceptions), and the duplicate is registered as the new child process. Netmulticore requires that the relationships between processes remain manageable, and because of this it is always the master process which requests the start of new children. Of course, the programmer can also call Netmcore_process.start from other workers, but the Netmulticore machinery just sends this request to the master, where it is really executed.

All in all this means: When a new worker is created, it is initialized as copy of the master process, independently of from where the user code requests the creation.

Resources

Netmulticore manages not only processes but also other kinds of resources. As of now the supported types are:

  • Temporary files
  • Shared memory blocks
  • Shared memory blocks with the additional requirement that all workers map them at the same address
  • Named semaphores
  • Fork points, i.e. registered functions acting as worker body
  • Join points, i.e. the option of waiting for the completion of worker bodies
All resources have a resource ID (Netmcore.res_id) which is effectively an integer. With only the resource ID every worker can request to get the details of the resource (e.g. which name the temporary file has). The master process also keeps records which worker needs which resource. If a resource is not needed anymore by any worker, it is automatically deleted.

Since Ocamlnet-3.6, the deletion procedure has been substantially improved. Now, a list of the alive resources is not only kept in memory, but also written to a file "netplex.pmanage". This allows it to delete the resources after the program has crashed or terminated somehow abnormally. This is automatically done when the program is restarted, or by the user running the netplex-admin utility with option -unlink. The background for this is that the mentioned resources have kernel persistency, and continue to exist when the program is finished.

Memory pools

For setting up shared heaps as explained below, we especially need shared memory blocks that are mapped at the same address by all worker processes. This kind of block is needed for memory pools as implemented by Netmcore_mempool. There is, unfortunately, only one reliable method of doing so: The master process allocates the block and maps it into its own address space, and the workers get access to the block by inheriting the mapping. This just means that the fork operation leaves the mapping in place, and because all workers are created in the same way, all workers end up seeing the shared block at the same address. The details of this procedure are hidden in Netmulticore, but the user should know the limitations of this method.

A process cannot inherit a posteriori - when the process is already created, and a new shared block is set up, there is no safe way for the process to get access to the block at the right address. Because of this, there are two important programming rules:

  • A newly created shared block (with the "same address" requirement) is only visible in worker processes that are created after the block
  • This even means that the requesting process does not get access to the shared block it just created if the requesting process is a worker
The safest and easiest way to deal with this is to create the shared block in the master before starting any worker.

Another limitation of the inheritance method: A shared block cannot be enlarged later. For the programmer this means that the initially created block must be large enough for the whole lifetime of the program.

The management of the shared blocks is now done by two modules: Netmcore_mempool is responsible in the first place, and can hand out pieces of the shared block to users. Netmcore_heap is such a user, and manages the pieces it gets as a heap of Ocaml values. Heaps can be enlarged if necessary, i.e. more pieces can be obtained from the big shared block that is managed by Netmcore_mempool. Of course, it is also possible to have several heaps getting their memory pieces from a single Netmcore_mempool.

Shared heaps

What is now a heap, or better shared heap? It is just a memory area, and it is possible to put Ocaml values into it. The values are connected by pointers that reach from one value to the next. This is not very much different than what is done by the Ocaml runtime and the normal Ocaml heap, only that the values are now exposed to a multitude of processes. We'll later see how we can create such a heap, and how it can be filled with Ocaml values. At this point, let me only mention that it requires the discipline of the programmer to fill and access a shared heap in the right way. If something gets wrong, the punishment is an illegal memory access, normally leading to a segmentation fault.

If a shared heap fills up, Netmcore_heap starts a special garbage collection run over it to reclaim memory that is no longer referenced. This garbage collector works very much like the "major GC" that is built into the Ocaml runtime.

As it is a bit complicated to manage shared heaps directly, there are a number of pre-defined data structures over shared heaps that can be directly used. Among these structures are buffers, queues, arrays, and hash tables.

Camlboxes

For fast notification between processes, Netmulticore uses Camlboxes. This data structure was invented before and exists independently of Netmulticore, but is specially supported.

Camlboxes are like mail boxes where an open number of senders can send messages to a single receiver. The messages are normal Ocaml values (like strings, records, or variants), so there is no marshalling issue. Camlboxes also use shared memory as transport medium, but it is here not required that the shared block needs to be mapped at the same address. Because of this, it is also possible to connect processes with Camlboxes that are not related to each other.

Camlboxes are optimized for speed and maximum parallelism. The data model is the following: The receiver creates the box which consists of a fixed number of slots, and each slot has a fixed maximum size. Each sender can map the box into its own address space, and fill any free slot. Because there is no strict ordering of the messages, the senders can avoid to run into lock contention issues (the senders simply use different slots and avoid to step on each other's feet). The receiver can look at the messages, copy the messages outside the box, and delete messages. The messages are not strings or marshalled data, but really Ocaml values, relocated to the receiver's address.

Synchronization

Netmulticore provides these synchronization primitives:

  • Mutexes
  • Semaphores
  • Condition variables
These primitives can be used in conjuction with shared heaps, and allow the programmer to define additional synchronization requirements that are not satisfied by the data structure in the heap.

For example, consider a shared hash table (Netmcore_hashtbl). This data structure already includes everything to protect the internal representation from concurrent accesses, but not more. For example, a Netmcore_hashtbl.add adds a value to the table, and it is safe to call this operation from several processes at the same time. This is not enough, however, to protect whole read/modify/update cycles where the whole cycle needs to be run uninterrupted to avoid data corruption. The user can define these additional synchronization requests with the mentioned primitives.

As this is a quite frequent programming case, many shared data structures already contain a special area called the header where the user can put these primitives.

How to start processes

For starting processes, there are actually two API's: the slightly more generic one in Netmcore, and the strictly typed one in Netmcore_process. They are quite similar, and I'm only explaining the latter.

Before a process can be started, it needs to be defined:

let process_fork, process_join =
  Netmcore_process.def_process process_body

The definition via Netmcore_process.def_process takes a function process_body, which is simply a function of type 'a -> 'b, and returns a fork point process_fork and a join point process_join. This definition must happen in the master process. Remember that it is also always the master process that is forked when a new worker process is created. This is consistent with this programming rule - process_body will be called in the context of a fresh copy of the master, so it needs also to be defined in the context of the master.

Practically, the definition is usually done when a top-level module is initialized, and process_body is a normal top-level function.

The fork point process_fork has type 'a fork_point where 'a is the type of the argument of process_body. Imagine a fork point as a way to fork the master process, where a value of type 'a is passed down, and process_body is finally called with this value in the new child. At the other end, the joint point process_join (of type 'b join_point) is a way to wait for the completion of the process_body and for getting the result of type 'b.

Of course, after defining a process, one can start it as many times as needed. Here is how to do:

let pid = Netmcore_process.start process_fork arg

This finally does:

  • The master process is notified that a new process is needed which will run a process as defined by process_fork
  • Once the process is running, the argument arg is marshalled and sent to the new process
  • Execution returns now to the caller of start with a process ID pid
  • The new process runs process_body arg' where arg' is the restored value arg
The process ID's are Netmulticore's own ID's, and are guaranteed to be unique (other than the process ID's the operating system uses which can wrap around).

When process_body finishes, the function result is passed back to the master where it is stored until the join is done. The worker process is terminated. One can get the result value by doing:

let r_opt = Netmcore_process.join process_join pid

This waits until the result value is available, and returns it as Some r (when r is of type 'b). If no result is available because of an exception or other termination of the process, None is returned. Note that the result r is also marshalled.

If there is no interest in getting results at all, one can also do

Netmcore_process.release_join_point process_join

which prevents that results are stored in the master until they are picked up.

Before giving a complete example, let's look at how to initialize Netmulticore. When the master is set up (processes are defined etc.) one can start the first worker. At this point, the whole management machinery needs to be started, too. This is normally done by a function call like

Netmcore.startup
   ~socket_directory:"some_dir" 
   ~first_process:(fun () -> Netmcore_process.start process_fork arg)
   ()

The socket_directory is needed by the machinery to store runtime files like Unix domain sockets (inherited from Netplex). In doubt, set it to something like "/tmp/dir", but note that each running instance of the program needs its own socket directory. (There is a chance that socket_directory becomes optional in future releases.)

Now a complete example: The master starts process X which in turn starts process Y. The processes do not much, but let's see:

let c = ref 0

let body_Y k =
  k + 1 + !c

let fork_Y, join_Y =
  Netmcore_process.def_process body_Y

let body_X k =
  c := 1;
  let pid_Y = Netmcore_process.start fork_Y k in
  let j =
     match Netmcore_process.join join_Y pid_Y with
      | Some j -> j
      | None -> failwith "Error in process Y" in
  Printf.printf "Result: %d\n%!" j

let fork_X, join_X =
  Netmcore_process.def_process body_X

Netmcore.startup
   ~socket_directory:"some_dir" 
   ~first_process:(fun () -> Netmcore_process.start fork_X 1)
   ()

The result is of course 2 (and not 3), because the assignment to c does not have any effect. Remember that process X is forked from the master process where c still has the value 0.

A final word on marshalling before going on. Arguments and results of processes are transmitted as strings that have been created with the functions from the Marshal module of the standard library. There are a number of constraints one should be aware of:

  • Functions, objects, and lazy values are not supported, and will cause exceptions. For a few other types this is also the case (e.g. in_channel).
  • Unfortunately, there are also types of values that do not trigger exceptions, but do nonsense. For example, Unix.file_descr is such a case. This unfortunately also holds for many Netmulticore types such as heaps. For these types the marshalling seems to work, but the restored values are actually unusable because they have lost their connection with the underlying resources of the operating system.

How to use Camlboxes for passing messages

Camlboxes must always be created by the (single) receiver of the messages. The address of the box is then made available to the senders which can then start the transmission of messages.

The number of message slots is fixed, and cannot be changed later. Also, the maximum size of the messages must be specified in advance, in bytes. Of course, this means one cannot use Camlboxes for arbitrarily large messages, but this is not what they are designed for. Camlboxes are good for small notifications that need to be quickly sent without risking any lock contention. (If big payload data needs to be included, a good workaround is to include that data by reference to a shared heap only.)

Let's just give an example: Process X creates a box, starts process Y, and Y sends a message to the box of X.

let body_Y box_res =
  let (box_sender : string Netcamlbox.camlbox_sender) = 
     Netmcore_camlbox.lookup_camlbox_sender box_res in
  Netcamlbox.camlbox_send box_sender "Hello world"

let fork_Y, join_Y =
  Netmcore_process.def_process body_Y

let () =
  Netmcore_process.release_join_point join_Y

let body_X () =
  let ((box : string Netcamlbox.camlbox),box_res) = 
     Netmcore_camlbox.create_camlbox "example" 1 100 in
  let pid_Y = Netmcore_process.start fork_Y box_res in
  ( match Netcamlbox.camlbox_wait box with
     | [ slot ] ->
         let m = Netcamlbox.camlbox_get_copy box slot in
         Netcamlbox.camlbox_delete box slot;
         printf "Message: %s\n%!" m
     | _ ->
         (* in _this_ example not possible *)
         assert false
  )

let fork_X, join_X =
  Netmcore_process.def_process body_X

Netmcore.startup
   ~socket_directory:"some_dir" 
   ~first_process:(fun () -> Netmcore_process.start fork_X ())
   ()

Let's go through it:

  • The box is created at the beginning of body_X, by a call of Netmcore_camlbox.create_camlbox. Generally, Netmcore_camlbox contains Netmulticore-specific extensions of the Camlbox abstraction which is primarily defined in Netcamlbox. The function Netmcore_camlbox.create_camlbox does not only create the box, but also registers it as resource in the master process. The string "example" is used for naming the shared memory block backing the box. This box has a capacity of one message which may get 100 bytes long. There are two return values, box and box_res. The value box is the way to access the box for receiving messages. The value box_res is the resource ID.
  • We pass box_res when we start body_Y. Resource ID's can be marshalled (whereas camlboxes cannot).
  • The helper function Netmcore_camlbox.lookup_camlbox_sender is called at the beginning of body_Y to look up the sender interface for the box identified by box_res. The sender view of the box is box_sender.
  • Now the string "Hello world" is sent by invoking Netcamlbox.camlbox_send.
  • In the meantime, process X continued running in parallel, and by invoking Netcamlbox.camlbox_wait the execution is suspended until at least one message is in the box. The function returns the slots containing messages.
  • We look now into the single slot where we expect a message. With Netcamlbox.camlbox_get_copy we can get a copy of the message in the slot. Note that there is also Netcamlbox.camlbox_get which does not make a copy but returns a reference to the message as it is in the box. This is unsafe because this reference becomes invalid when the message is deleted.
  • Finally we delete the message in the slot with Netcamlbox.camlbox_delete. The slot is now again free, and can hold the next message.
You may wonder why I added the type annotations for box and box_sender. If you look at the signatures of the Camlbox modules, you'll see that there is no enforcement that the types of box and box_sender fit to each other. The type parameter string is lost at the moment the resource ID is used for identifying the box.

When sending a message, it is always copied into the box. For doing this a special "value copier" is used. This copier traverses deeply through the value representation and copies each piece into the box. This is a bit like marshalling, only that this does not result in a string but a copy of the orginal value (and the copy is placed into a reserved region in the shared memory block of the Camlbox). This copier has also restrictions which types of values can be handled, very much like marshalling.

How to create and use memory pools

Now back to the core of Netmulticore. For the remaining data structures the shared memory must be managed as a memory pool. The module Netmcore_mempool accomplishes this.

As explained above, there are certain restrictions on which processes have access to memory pools. For most applications it is best when they simply create the pool in the master process directly after program startup and before launching any worker process. This avoids all restrictions, but the size of the pool needs to be set at this early point of execution (remember that pools also cannot be enlarged).

It is a good question how big a pool should be. Generally, the pool should be a small factor larger than the minimum amount of RAM needed for the pool. I cannot give really good recommendations, but factors between 1.5 and 3.0 seem to be good choices. If the pool size is chosen too tight, the garbage collector will run often and slow down the program.

Another strategy for the pool size is to make it always large, e.g. 25% of the available system memory. The idea here is that when parts of the pool remain unused throughout the lifetime of the program, they actually will also not consume RAM. Operating systems typically distinguish between RAM that is reserved by a memory allocation and RAM that is actually filled with data. Only the latter type consumes real RAM, whereas the first type is only taken into account for bookkeeping. This means the pool memory is reserved for the case it is needed at a certain point, but RAM is not wasted if not.

Now, the pool is simply created with

let pool = Netmcore_mempool.create_mempool size_in_bytes

The value pool is again a resource ID, and it is no problem to marshal this ID. When creating shared heaps, and for a number of other operations the pool ID is required, so it is a good idea to passed it down to all worker processes.

Pools are backed by shared memory blocks, and these blocks have kernel persistence (usually they even appear as files, but this depends on the operating system). This means they exist until explicitly deleted (like files). To do so, just call

Netmcore.release pool

after the Netmcore.startup function returns to the caller, and before the program is finally terminated.

As pool memory is inherited by worker processes (as explained in the section about "Design"), one has to enable the inheritance for each started process, e.g.

let pid = 
  Netmcore_process.start 
    ~inherit_resources:`All
    process_fork arg

Otherwise the pool is not accessible by the started worker process. (I'm thinking about making this the default, but haven't come to a conclusion yet.)

If system memory is very tight, you will sometimes see bus errors when using pools (signal SIGBUS is sent to one of the processes, typically the signal number is 7). This happens when allocated shared memory is actually not available when it is used for the first time. (I'm still looking for ways how to get nicer reactions.)

Shared ref-type variables

Let's now look at a data structure that lives in a shared heap. Note that there is also a direct interface to shared heaps, but for the sake of explaining the concept, it is easier to first look at a concrete instance of a heap.

The module Netmcore_ref provides a mutable reference for a single value residing in the shared heap. The reference is comparable to the ref type provided by the standard library, and it is possible to dereference it, and to assign new values to it. The difference is, however, that the reference and the referenced value reside completely in shared memory, and are accessible by all workers.

The reference is created by something like

let s = Netmcore_ref.sref pool initial_value

where pool is the resource ID of a pool (see above), and initial_value is the value to assign to the reference initially. This is comparable to

let r = ref initial_value

for normal references. There is an important difference, however. The referenced value must completely reside in shared memory, and in order to achieve this, the sref function copies the initial_value to it. (The same copy mechanism is used that also puts messages into Camlboxes.)

After running sref, a new shared heap has been created which is initialized as a reference. You can get a direct handle for the heap structure by calling Netmcore_ref.heap.

Also note that you have to call sref from a worker process. It is not possible to do this from the master process. This also applies to almost any other heap-related function.

It is possible to assign a new value to s:

Netmcore_ref.assign s new_value

This also copies the new_value to the heap, and changes the reference.

You may wonder what happens when you assign new values over and over again. There is no mechanism for deleting the old values immediately. Instead, the values accumulate over time in the heap, and when a certain threshold is reached, a garbage collection run is started. This run checks for values (or value parts) that became unreachable, and reclaims the memory used for them.

This garbage collector (GC) is not the normal garbage collector that cleans the process-local heap managed by the Ocaml runtime. It is a special GC designed for shared heaps. Unfortunately, this special GC is not as automatic as the GC built into the Ocaml runtime, as we'll see.

Back to our shared references. There are three functions for getting the value pointed to by a reference:

let v1 = Netmcore_ref.deref_ro s

let v2 = Netmcore_ref.deref_c s

Netmcore_ref.deref_p s (fun v3 -> ...)

The first function, deref_ro, is the fastest but unsafest. It just returns the current value of the reference as-is, and this value is of course stored in the shared heap. The problem is, however, that further assignments to the variable can invalidate this value when a GC run occurs. If this happens, v1 becomes invalid because the memory holding the representation for v1 is overwritten with something else, and any accesses to v1 or its parts may crash the program! For this reason, the deref_ro function must only be used if it can be excluded by other means that the variable is not being assigned while v1 is being accessed (e.g. by a lock). The suffix "_ro" is meant to remind of the fact that it is safe to use in read-only contexts. (N.B. The GC could theoretically also check for values that are only alive because of references from process-local memory. Unfortunately, this would complicate everything dramatically - the local GC and the shared GC would need some synchronization, and slow or misbehaving local GC's could delay shared GC runs almost indefinitely.)

The second function, deref_c, does not have this problem because it always returns a copy of the referenced value (suffix "_c" = "copy"). It is, of course, a lot slower because of this, and the copy semantics may not always be the right design for an application.

The third function, deref_p, is a clever alternative. As you can see, deref_p does not return the value, but it runs an argument function with the current value. The trick is now that v3 is specially protected while this function is running. This protection does not prevent assignments, but it prevents that the GC deletes the value v3, if a GC run is done. This type of protection is also called pinning, and the suffix "_p" is meant to remind of this.

When using deref_p, one still should be careful and think about whether accesses to v3 (or parts of v3) can occur after the pinning protection has ended. This must be excluded by all means!

Let's look at another thing the programmer must not do. Imagine some inner part of the value is mutable, e.g.

type t = { mutable data : string }

let s = Netmcore_ref.sref pool { data = "initial string" }

The question is now: Is it allowed to assign to the data component, as in

(Netmcore_ref.deref_ro s).data <- "new string"   (* WARNING - PROBLEMATIC CODE *)

The meaning of this assignment is that the data component is overwritten with a pointer to a string residing in process-local memory. Imagine now what happens if a different worker process accesses the data component. The address of this pointer is now meaningless, because the string does not exist in context of the other process at this address. If we access nevertheless, we risk getting random data or even segmentation faults.

I'll explain below how to fix this assignment. It is possible, if done in the right way.

Finally, here is a complete example using shared references:

let body_Y (pool, c_descr, k) =
  let c = Netmcore_sref.sref_of_descr pool c_descr in
  let c_value = Netmcore_sref.deref_ro c in
  k + 1 + c_value

let fork_Y, join_Y =
  Netmcore_process.def_process body_Y

let body_X (pool,k) =
  let c = Netmcore_sref.sref pool 1 in
  let c_descr = Netmcore_sref.descr_of_sref c in
  let pid_Y = 
    Netmcore_process.start ~inherit_resources:`All fork_Y (pool, c_descr, k) in
  let j =
     match Netmcore_process.join join_Y pid_Y with
      | Some j -> j
      | None -> failwith "Error in process Y" in
  Printf.printf "Result: %d\n%!" j

let fork_X, join_X =
  Netmcore_process.def_process body_X

let () = 
  let pool = Netmcore_mempool.create_mempool (1024 * 1024) in

  Netmcore.startup
     ~socket_directory:"some_dir" 
     ~first_process:
        (fun () -> 
           Netmcore_process.start ~inherit_resources:`All fork_X (pool,1))
     ();

  Netmcore.release pool

Compare this with the example I gave when explaining how to start processes. The variable c is now a shared reference, and because of this process Y can access the contents of c. The result is now 3.

In this example already a feature is used that is first explained in the next section: descriptors. For some reason (we'll see why) it is not possible to marshal shared heaps, and thus you cannot call body_Y with c as argument. The workaround is to create a descriptor for c, use the descriptor for marshalling, and restore the orginal heap in the called function.

Descriptors

Shared heaps are very special objects - in particular, the heaps reside in shared memory at a certain address, and this address also appears in the internal data structures the heaps use to manage their memory space.

Imagine what happens when you do not respect this special nature of shared heaps, and create a copy nevertheless (e.g. by marshalling the heap, or by putting the heap into another heap). At the first glance, you will see that you can actually create the copy (it's a valid Ocaml value), but when you try to use it, the program will crash. What has happened?

The problem is that the internal data structure of the copied heap still contains addresses that are only valid for the orignal heap, but are meaningless for the copy. When these addresses are followed, invalid memory access occur, and the program crashes.

So, a very important programming rule: Never copy shared heaps! Unfortunately, this really requires discipline, as there are many mechanisms in Netmulticore where copies are automatically created (just page back and look how often I told you that a copy is created here and there), for example when starting worker processes the arguments are also copied over to the newly created process.

How to work around? First let's think about what we really want to have when we e.g. start a worker process and pass a shared heap to it. Of course, we do not want to create a copy, but rather we want to make the same shared heap accessible to the worker. We want call by reference!

Descriptors are the solution. A descriptor of a shared heap is just a marshallable reference to the heap. For each shared data structure there is a special descriptor type, and it is possible to get the descriptor for a heap, and to look up the heap by descriptor. For example, shared references define this as (in Netmcore_ref):

type 't sref_descr

val descr_of_sref : 't sref -> 't sref_descr
val sref_of_descr : Netmcore.res_id -> 't sref_descr -> 't sref

Note that the sref_of_descr function takes the resource ID of the pool as first argument, and that this function is quite slow (because it has to ask the master process where to find the shared memory object).

For the other shared data structures, the are comparable functions supporting descriptors.

How to mutate shared values

Remember this code?

(Netmcore_ref.deref_ro s).data <- "new string"   (* WARNING - PROBLEMATIC CODE *)

We now look how to fix it. The basic problem is that the new string is not residing in shared memory, and if we could achieve that this is the case, the assignment would be acceptable.

The correct way to do it is this:

Netmcore_heap.modify
  (Netmcore_ref.heap s)
  (fun mut ->
    (Netmcore_ref.deref_ro s).data <- Netmcore_heap.add mut "new string"
  )

The essence is that we now call Netmcore_heap.add before assigning the string. This function again copies the argument value, and puts the copy onto the heap. For managing the copy, this function needs an special object mut, which is actually a mutator. The only way to get a mutator is to call Netmcore_heap.modify, which - among other actions - locks the heap, and prevents that any competing write access occurs. This is required, because otherwise mutations could overlap in bad ways when they are done in parallel, and the internal representation of the heap would be corrupted.

Note that you need to call add for assigning all values that are not yet residing in the same heap. This means: Call it if the new value is in process-local memory, but also call it when the new value is already part of a different heap (because pointers from one heap to the other are not allowed - heaps must be completely self-contained).

You may wonder why we used deref_ro to get the current value of s, and not one of the other access functions. Quite easy answer: the other functions deref_c and deref_p would deadlock the program! The modify function already acquires the heap lock for the duration of the mutation, and using any access function that also plays with this lock will cause deadlocks.

Let's look at this example:

type u = { mutable data1 : string;
           mutable data2 : string;
         }

let s = Netmcore_ref.sref
           pool
           { data1 = "initial string 1"; data2 = "initial string 2" }

We want now to swap the values in the two components data1 and data2. The solution is of course:

Netmcore_heap.modify
  (Netmcore_ref.heap s)
  (fun mut ->
    let u = Netmcore_ref.deref_ro s in
    let p = u.data1 in
    u.data1 <- u.data2;
    u.data2 <- p
  )

Note that we call modify although we do not need the mutator for doing our work. The reason is that modify also write-locks the heap, and this protects the integrity of our data. We do not need to call add because the two strings are already residing in the same shared heap, and we are just swapping them.

A little variation of this let us run into a possible problem, though:

Netmcore_heap.modify
  (Netmcore_ref.heap s)
  (fun mut ->
    let u = Netmcore_ref.deref_ro s in
    let p = u.data1 in
    u.data1 <- Netmcore_heap.add mut ("Previously in data2: " ^ u.data2);
    u.data2 <- Netmcore_heap.add mut ("Previously in data1: " ^ p);
    printf "p=%s\n" p;                    (* THIS LINE IS PROBLEMATIC *)
  )

This piece of code will crash now and then (not often, so maybe difficult to run into). What is going wrong?

There is one phenomenon we haven't paid attention to yet: When we call add it is possible that the available space in the heap is not sufficient anymore to do the required memory allocations, and that a GC run is started. When this happens in the second add, the field data1 is already overwritten, and because of this the string p is now unreachable from the top-level value of the heap. The space occupied by p is reclaimed, and may even be overwritten. For the two assignments this is no problem, because p is no longer needed. When we access p after the second add, however, the value may have become invalid. Accessing it may crash the program!

How to fix? It is possible to pin additional values during mutation so that they cannot be collected by the GC:

Netmcore_heap.modify
  (Netmcore_ref.heap s)
  (fun mut ->
    let u = Netmcore_ref.deref_ro s in
    let p = u.data1 in
    u.data1 <- Netmcore_heap.add mut ("Previously in data2: " ^ u.data2);
    u.data2 <- Netmcore_heap.add mut ("Previously in data1: " ^ p);
    Netmcore_heap.pin mut p;
    printf "p=%s\n" p;
  )

This piece of code is now correct. The effect of pin lasts until the end of the modify function.

Shared data structures

Besides references, there are a number of further shared data structures:

You may wonder why these data structures exist. Isn't it possible to e.g. put a normal Queue into a shared reference in order to get a shared version? The problem is that existing types like Queue do not adhere to the programming rules we've outlined above. Queue is a mutable structure, and when elements are added to or removed from the queue, new value allocations are always done in the normal process-local heap but not in the right shared heap. This is nothing one can fix by wrapping code around these data structures.

If you look at the implementation of e.g. Netmcore_queue (which is really recommended), you'll see that it looks very much like the implementation of Queue, only that Netmcore_heap.modify is used for managing mutation.

The above listed modules also include all the necessary means to protect the data structures against the possibly disastrous effects of parallel mutation. Also, for read accesses there are always several access functions corresponding to what we've seen for references (deref_ro, deref_c, and deref_p).

Let's have a closer look at Netmcore_array to see how this is done. The signature is:

type ('e,'h) sarray
type ('e,'h) sarray_descr
val create : Netmcore.res_id -> 'e array -> 'h -> ('e,'h) sarray
val make : Netmcore.res_id -> int -> 'e -> 'h -> ('e,'h) sarray
val init : Netmcore.res_id -> int -> (int -> 'e) -> 'h -> ('e,'h) sarray
val grow : ('e,_) sarray -> int -> 'e -> unit
val set : ('e,_) sarray -> int -> 'e -> unit
val get_ro : ('e,_) sarray -> int -> 'e
val get_p : ('e,_) sarray -> int -> ('e -> 'a) -> 'a
val get_c : ('e,_) sarray -> int -> 'e
val length : (_,_) sarray -> int
val header : (_,'h) sarray -> 'h
val deref : ('e,_) sarray -> 'e array
val heap : (_,_) sarray -> Obj.t Netmcore_heap.heap
val descr_of_sarray : ('e,'h) sarray -> ('e,'h) sarray_descr
val sarray_of_descr : Netmcore.res_id -> ('e,'h) sarray_descr -> ('e,'h) sarray

As you can see, the type is not only 'e sarray (when 'e is the type of the elements), but there is a second type variable 'h, so that the type becomes ('e,'h) sarray. This is the type of the header, which is simply an extra place for storing data that exists once per shared data structure. The header can have any type, but is often a record with a few fields. If you do not need the header, just set it to () (i.e. 'h = unit).

For managing shared data structures one often needs a few extra fields that can be put into the header. For example, a requirement could be that the length of a shared queue is limited, and one needs synchronization variables to ensure that the users of the queue stick to the limit (i.e. the addition of new elements to the queue is suspended when it is full, and it is restarted when there is again space). As such extra requirements are very common, all shared data structures have such a header (well, for Netmcore_ref it was omitted for obvious reasons).

When you create an instance of the structure, you always have to pass the resource ID of the pool (here for create, make, init). Another argument is the initial value of the header (which is also copied into the shared heap). The header, after being copied to the heap, can be accessed with the header function.

The function set looks very much like the one in Array. Note that for all mutation the shared heap is write-locked, so there can actually only be one running set operation at a time. Because set copies the argument data to the shared heap, this time is not neglectable.

For accessing elements, there are the known three variants: get_ro, get_c, and get_p. The length function works as in Array.

As it would be difficult for the user to implement growable arrays on top of the basic version, it was chosen to add a grow function exactly doing that. This function avoids to copy the values again into the shared heap that are already there.

The type ('e,'h) sarray_descr is used for descriptors to shared arrays, and the functions descr_of_sarray and sarray_of_descr allow it to manage descriptors.

Synchronization

There are three kinds of synchronization devices:

Unlike the above explained data structures, these synchronization means are simply special values, and not shared heaps of their own (which would be quite costly). One consequence of their special nature is that it is not possible to copy these values around - they must exist at a fixed memory address, and cannot be copied or moved. This just means that after copying or moving the values become non-functional.

Of course, these special values must be put into shared heaps in order to be accessible by several processes. Let's just walk through an example, to see how this is done right.

Imagine you have a field x of some type, and a lock m that is going to protect concurrent accesses to x:

type t =
  { mutable x : some_type;
    mutable m : Netmcore_mutex.mutex
  }

This record is put into a shared reference:

let s = Netmcore_ref.sref { x = ...; m = ... }

Remember that sref initializes the reference with a copy of the argument value. This would mean we copy m, which is invalid as we've learned. How to solve?

Mutexes (like the other synchronization devices) are designed for this use pattern, so there is already a built-in solution. There is a special dummy value one can use during initialization:

let s = Netmcore_ref.sref { x = ...; m = Netmcore_mutex.dummy() }

Dummies are placeholders that need to be re-initialized later when the mutex is already copied to the shared heap. This is done by:

Netmcore_heap.modify
  (Netmcore_ref.heap s)
  (fun mut ->
     let r = Netmcore_ref.deref_ro mut in
     r.m <- Netmcore_mutex.create mut `Normal
  )

That's it! Note that we've set the type of the mutex to `Normal which creates a fast mutex without deadlock protection.

The mutex can now be used in statements like

Netmcore_ref.deref_p (fun r -> Netmcore_mutex.lock r)

Be careful not to use deref_c because this would create a copy of the mutex, and render it useless!

Semaphores are much like mutexes, only that the synchronization functions are not lock and unlock but wait and post.

Condition variables are a bit harder to use, unfortunately. When implementing them I ran into the issue that the fast algorithm needs to allocate special storage places, one for each process that can be suspended. (There is a slow algorithm not requiring additional storage, but this would have been a very bad deal.) In system-level implementations of condition variables the additional storage can usually be hidden from the user. This is not possible in a pure user-space implementation like this one. For this reason, the user of condition variables has to allocate these places called wait_entry. One wait_entry is needed for each process that can ever wait for a condition variable. There is also wait_set which is just a collection of wait_entry values. Let's look at an example:

type t =
  { mutable x : some_type;
    mutable m : Netmcore_mutex.mutex;
    mutable c : Netmcore_condition.condition;
    mutable w : Netmcore_condition.wait_set
  }

let s = 
  Netmcore_ref.sref
     { x = ...; 
       m = Netmcore_mutex.dummy();
       c = Netmcore_condition.dummy_condition();
       w = Netmcore_condition.dummy_wait_set()
     }

let () =
  Netmcore_heap.modify
    (Netmcore_ref.heap s)
    (fun mut ->
       let r = Netmcore_ref.deref_ro mut in
       r.m <- Netmcore_mutex.create mut `Normal;
       r.c <- Netmcore_condition.create_condition mut;
       r.w <- Netmcore_condition.create_wait_set mut
    )

The field w is now an empty wait_set. Note that we only need one w for all condition variables that exist in the same shared heap.

The point is now that we need to get a wait_entry for each process using s. Get it with:

let we =
  Netmcore_heap.modify
    (Netmcore_ref.heap s)
    (fun mut -> 
      Netmcore_condition.alloc_wait_entry mut (Netmcore_ref.deref_ro s).w
    )

This just needs to happen once for each process. The value we can be used for all wait calls related to all condition variable in the same shared heap.

A wait call looks then like:

Netmcore_ref.deref_p (fun r -> Netmcore_condition.wait we r.c r.m)

For signal and broadcast the value we is not needed. As you see the only additional complexity has to do with the initialization of the process - we need to create we once for each process.

Where to find examples

It is very much recommended to study complete examples before trying to develop with Netmulticore. There are a few examples in the examples/multicore directory of the distributed tarball.

The latest version can always be found in the svn repository:

Remarks on the implementation

The current implementation of shared heaps only uses a single lock for protecting every heap, even for the initial actions of read accesses. This e.g. means that a deref_c locks the reference for a short time until it has pinned the current value. The (perhaps time consuming) copy operation is then done without lock.

This might not be optimal for all use cases. An improved locking scheme would use reader/writer locks. However, this kind of lock is complicated to implement on top of just semaphores, so it was omitted for now. Also, reader/writer locks are more expensive in general, so it is not clear whether it is better at all.

The memory management of heaps is still in a quite experimental state. Heaps are extended in units of 64 KB which may be way too big or way too small for the application. Also, it is tried to achieve that at least half of the heap memory is free (i.e. the "overhead factor" is 50%).

If parts of a shared heap become completely free they are in deed given back to the memory pool.

Some points where Netmulticore is different from multi-threading

When porting multi-threaded programs to Netmulticore, you may wonder where the differences are.

Netmulticore can only deal with values that are completely stored in shared heaps. This requires that the value is initially copied to the heap, and the described programming rules must be adhered to when modifiying and also reading the values. Of course, there are also programming rules in a multi-threaded environment, so this is not completely different.

The way the shared heaps are managed is less automatic than in the multi-threaded case. Especially, the garbage collector of shared heaps does not recognize values in process-local memory as roots. This is really unfortunate, because the user has to work around this limitation (pinning), and this is error-prone. There is, however, probably nothing we can do about it. Theoretically it is possible to create a protocol between the shared GC and the process-local GC, but it looks very complicated to implement it.

Another problem is that there is nothing that would prevent erroneous pointers from shared heaps to process-local heaps. In multi-threaded environments this distinction does not exist, so there is no such problem. By changing the Ocaml compiler it could be possible (without having checked it in detail) to emit different code when a process-local value is assigned to a shared variable, and to automatically allocate the value in the shared heap.

The Netmulticore approach also has advantages. Especially, it is way more scalable than a multi-threaded environment with a single heap only. There is no global lock that could become the bottleneck of the implementation. Each shared heap has its own lock, so there is always the possibility to increase the "lock capacity" by using more shared heaps together. In some sense, this is not a "multicore" solution, but rather a "manycore" approach that will also work for hundreds of cores.

Operating system issues

Administering POSIX shared memory

Many of the data structures described here are actually backed by shared memory blocks. For managing these blocks, the POSIX API is used (i.e. shm_open). Note that there is also an older API on many systems called System V API (i.e. shmget). This API is not used.

Shared memory has kernel persistence, i.e. the blocks remain allocated even after the process terminates that created them. The blocks need to be explicitly deleted. This can be done by the right API calls (e.g. call Netmcore.release for objects with a Netmulticore resource ID), but from time to time a program does not terminate normally, and this deletion is not performed. The question is how to get administratively rid of the blocks.

The nice aspect of the POSIX API is that shared memory looks very much like files, and in deed, in many implementations I've seen the blocks appear somewhere in the file system. Typical locations for these files are /dev/shm and /tmp. The files have names like mempool_f7e8bdaa, or generally <prefix>_<8hexdigits>. The prefix depends on the data structure the block is used for, and the hex digits make the name unique. By deleting these files, the blocks are removed.

Since Ocamlnet-3.6, one can also delete shared memory administratively with the netplex-admin utility. See Deleting persistent kernel objects for details. This method works for all OS. Also, an unlink of old memory is automatically done when the program is restarted.

Another issue is that OS typically define an upper limit for the amount of shared memory. This is e.g. 50% of the system RAM for Linux. There are usually ways to configure this limit.
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.engine_mixin-c.html0000644000175000017500000004500312731530352023620 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.engine_mixin

Class Uq_engines_compat.engine_mixin

class ['t] engine_mixin : 't engine_state -> Unixqueue.event_system -> object .. end

method state : 't engine_state
method private set_state : 't engine_state -> unit
method request_notification : (unit -> bool) -> unit
method request_proxy_notification : ('t engine -> bool) -> unit
method private notify : unit -> unit
method event_system : Unixqueue.event_system
ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.async_in_channel.html0000644000175000017500000004224612731530352024122 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.async_in_channel object
  method can_input : bool
  method close_in : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method pos_in : int
  method request_notification : (unit -> bool) -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_client.auth_method.html0000644000175000017500000004145112731530352022716 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.auth_method object
  method name : string
  method new_session :
    Rpc_client.t -> string option -> Rpc_client.auth_protocol
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.prioritizer.html0000644000175000017500000004103012731530352023003 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.prioritizer Unixqueue.event_system -> ['a] Uq_engines.prioritizer_tocamlnet-4.1.2/doc/html-main/Uq_server.direct_acceptor-c.html0000644000175000017500000004244312731530352022621 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_server.direct_acceptor

Class Uq_server.direct_acceptor

class direct_acceptor : ?close_on_shutdown:bool -> ?preclose:unit -> unit -> Unix.file_descr -> Unixqueue.event_system -> server_endpoint_acceptor
An implementation of server_endpoint_acceptor for sockets and Win32 named pipes. For sockets, the passed descriptor must be the master socket. For Win32 named pipes, the passed descriptor must be the proxy descriptor of the pipe server..

ocamlnet-4.1.2/doc/html-main/type_Uq_engines.delegate_engine.html0000644000175000017500000004113312731530352023524 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.delegate_engine '#Uq_engines.engine -> ['t] Uq_engines.engineocamlnet-4.1.2/doc/html-main/Netchannels.rec_in_channel-c.html0000644000175000017500000004555112731530352022710 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.rec_in_channel

Class type Netchannels.rec_in_channel

class type rec_in_channel = object .. end
Recommended input class type for library interoperability.

Description

This class type is defined in "Basic I/O class types" as collaborative effort of several library creators.

method input : Bytes.t -> int -> int -> int
Reads octets from the channel and puts them into the string. The first int argument is the position of the substring, and the second int argument is the length of the substring where the data are stored. The method returns the number of octets actually read and stored.

When the end of the channel is reached and there is no further octet to read, the exception End_of_file will be raised. This has been changed in ocamlnet-0.97! In previous releases the number 0 was returned at the end of the channel.

When the channel is non-blocking, and there are currently no bytes to read, the number 0 will be returned. This has been changed in ocamlnet-0.97! In previous releases this behaviour was undefined.

When the channel is closed, the exception Closed_channel will be raised if an ocamlnet implementation is used. For implementations of other libraries there is no standard for this case.

method close_in : unit -> unit
Closes the channel for input.

When the channel is already closed, this is a no-op.

Error policy: Exceptions are only raised in cases of serious corruption, e.g. if the underlying descriptor is invalid.

ocamlnet-4.1.2/doc/html-main/Uq_engines.engine-c.html0000644000175000017500000004736712731530352021070 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.engine

Class type Uq_engines.engine

class type ['t] engine = object .. end
This class type defines the interface an engine must support. The class parameter 't is the type of the result values (when the engine goes to state `Done).

Requirements for engines

method state : 't engine_state
Returns the state of the engine
method abort : unit -> unit
Forces that the engine aborts operation. If the state is already `Done , `Aborted, or `Error, this method must do nothing (you cannot abort an already finished engine).
method request_notification : (unit -> bool) -> unit
Requests notification about state changes.

After the notification has been requested, the passed function must be called whenever state changes its value (or might change its value; it is allowed to call the notification function more frequently than necessary). The function returns true if there is still interest in notification, and false if notification must be disabled; the function must not be called any longer in this case.

There can be any number of parallel active notifications. It is allowed that a notification callback function requests further notifications.

If the callback raises an exception, this exception is propagated to the caller of Unixqueue.run.

method request_proxy_notification : ('t engine -> bool) -> unit
Requests to call back the function when there is another engine that can be used as proxy for this object. Note that this is a pure optimization for qseq_engine, and is normally not implemented for any other engine construction. It is ok to define this method as a no-op.
method event_system : Unixqueue.event_system
Returns the event system the engine is attached to
ocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi_types.simple_message.html0000644000175000017500000004062112731530352026617 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_types.simple_message Netmime.mime_bodyocamlnet-4.1.2/doc/html-main/type_Netsys_types.html0000644000175000017500000005220112731530352021040 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_types sig
  type memory =
      (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
  type tbuffer =
      [ `Bytes of Bytes.t
      | `Memory of Netsys_types.memory
      | `String of Bytes.t ]
  type tstring =
      [ `Bytes of Bytes.t
      | `Memory of Netsys_types.memory
      | `String of string ]
  class type mstring =
    object
      method as_bytes : Bytes.t * int
      method as_memory : Netsys_types.memory * int
      method as_string : string * int
      method blit_to_bytes : int -> Bytes.t -> int -> int -> unit
      method blit_to_memory :
        int -> Netsys_types.memory -> int -> int -> unit
      method blit_to_string : int -> Bytes.t -> int -> int -> unit
      method length : int
      method preferred : [ `Bytes | `Memory ]
    end
  exception EAGAIN_RD
  exception EAGAIN_WR
  exception TLS_switch_request
  exception TLS_switch_response of bool
  exception TLS_error of string
  exception TLS_warning of string
end
ocamlnet-4.1.2/doc/html-main/Netplex_mt.mt-c.html0000644000175000017500000004161312731530352020251 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mt.mt

Class Netplex_mt.mt

class mt : unit -> Netplex_types.parallelizer
Uses Thread.create to create new threads

ocamlnet-4.1.2/doc/html-main/Uq_engines.timeout_engine-c.html0000644000175000017500000004307412731530352022625 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.timeout_engine

Class Uq_engines.timeout_engine

class ['a] timeout_engine : float -> exn -> 'a engine -> ['a] engine
timeout_engine d x e: If the engine e finishes within d seconds, the result remains unchanged. If the engine takes longer, though, it is aborted, and the state transitions to `Error x

ocamlnet-4.1.2/doc/html-main/type_Ipv6.html0000644000175000017500000004060512731530352017160 0ustar gerdgerd Ocamlnet 4 Reference Manual : Ipv6 sig  endocamlnet-4.1.2/doc/html-main/type_Netmime_string.html0000644000175000017500000012377112731530352021326 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime_string sig
  val find_line_end : string -> int -> int -> int
  val find_line_end_poly :
    'Netstring_tstring.tstring_ops -> '-> int -> int -> int
  val find_line_start : string -> int -> int -> int
  val find_line_start_poly :
    'Netstring_tstring.tstring_ops -> '-> int -> int -> int
  val find_double_line_start : string -> int -> int -> int
  val find_double_line_start_poly :
    'Netstring_tstring.tstring_ops -> '-> int -> int -> int
  val skip_line_ends : string -> int -> int -> int
  val skip_line_ends_poly :
    'Netstring_tstring.tstring_ops -> '-> int -> int -> int
  val fold_lines_p :
    ('-> int -> int -> int -> bool -> 'a) ->
    '-> string -> int -> int -> 'a
  val fold_lines_p_poly :
    'Netstring_tstring.tstring_ops ->
    ('-> int -> int -> int -> bool -> 'a) -> '-> '-> int -> int -> 'a
  val fold_lines : ('-> string -> 'a) -> '-> string -> int -> int -> 'a
  val fold_lines_poly :
    'Netstring_tstring.tstring_ops ->
    ('-> '-> 'a) -> '-> '-> int -> int -> 'a
  val iter_lines : (string -> unit) -> string -> int -> int -> unit
  val iter_lines_poly :
    'Netstring_tstring.tstring_ops ->
    ('-> unit) -> '-> int -> int -> unit
  val skip_whitespace_left : string -> int -> int -> int
  val skip_whitespace_right : string -> int -> int -> int
  val fold_header :
    ?downcase:bool ->
    ?unfold:bool ->
    ?strip:bool ->
    ('-> string -> string -> 'a) -> '-> string -> int -> int -> 'a
  val list_header :
    ?downcase:bool ->
    ?unfold:bool ->
    ?strip:bool -> string -> int -> int -> (string * string) list
  val scan_header :
    ?downcase:bool ->
    ?unfold:bool ->
    ?strip:bool ->
    string -> start_pos:int -> end_pos:int -> (string * string) list * int
  val scan_header_tstring :
    ?downcase:bool ->
    ?unfold:bool ->
    ?strip:bool ->
    Netsys_types.tstring ->
    start_pos:int -> end_pos:int -> (string * string) list * int
  val scan_header_poly :
    ?downcase:bool ->
    ?unfold:bool ->
    ?strip:bool ->
    'Netstring_tstring.tstring_ops ->
    '-> start_pos:int -> end_pos:int -> (string * string) list * int
  val read_header :
    ?downcase:bool ->
    ?unfold:bool ->
    ?strip:bool -> Netstream.in_obj_stream -> (string * string) list
  val write_header :
    ?soft_eol:string ->
    ?eol:string ->
    Netchannels.out_obj_channel -> (string * string) list -> unit
  type s_token =
      Atom of string
    | EncodedWord of ((string * string) * string * string)
    | QString of string
    | Control of char
    | Special of char
    | DomainLiteral of string
    | Comment
    | End
  type s_option =
      No_backslash_escaping
    | Return_comments
    | Recognize_encoded_words
  type s_extended_token
  val get_token : Netmime_string.s_extended_token -> Netmime_string.s_token
  val get_decoded_word : Netmime_string.s_extended_token -> string
  val get_charset : Netmime_string.s_extended_token -> string
  val get_language : Netmime_string.s_extended_token -> string
  val get_pos : Netmime_string.s_extended_token -> int
  val get_line : Netmime_string.s_extended_token -> int
  val get_column : Netmime_string.s_extended_token -> int
  val get_length : Netmime_string.s_extended_token -> int
  val separates_adjacent_encoded_words :
    Netmime_string.s_extended_token -> bool
  type mime_scanner
  val create_mime_scanner :
    specials:char list ->
    scan_options:Netmime_string.s_option list ->
    ?pos:int ->
    ?line:int -> ?column:int -> string -> Netmime_string.mime_scanner
  val get_pos_of_scanner : Netmime_string.mime_scanner -> int
  val get_line_of_scanner : Netmime_string.mime_scanner -> int
  val get_column_of_scanner : Netmime_string.mime_scanner -> int
  val scan_token :
    Netmime_string.mime_scanner ->
    Netmime_string.s_extended_token * Netmime_string.s_token
  val scan_token_list :
    Netmime_string.mime_scanner ->
    (Netmime_string.s_extended_token * Netmime_string.s_token) list
  val scan_structured_value :
    string ->
    char list -> Netmime_string.s_option list -> Netmime_string.s_token list
  val specials_rfc822 : char list
  val specials_rfc2045 : char list
  val scan_encoded_text_value :
    string -> Netmime_string.s_extended_token list
  val scan_value_with_parameters :
    string -> Netmime_string.s_option list -> string * (string * string) list
  type s_param
  val param_value : Netmime_string.s_param -> string
  val param_charset : Netmime_string.s_param -> string
  val param_language : Netmime_string.s_param -> string
  val mk_param :
    ?charset:string -> ?language:string -> string -> Netmime_string.s_param
  val print_s_param : Format.formatter -> Netmime_string.s_param -> unit
  val scan_value_with_parameters_ep :
    string ->
    Netmime_string.s_option list ->
    string * (string * Netmime_string.s_param) list
  val scan_mime_type :
    string -> Netmime_string.s_option list -> string * (string * string) list
  val scan_mime_type_ep :
    string ->
    Netmime_string.s_option list ->
    string * (string * Netmime_string.s_param) list
  val split_mime_type : string -> string * string
  exception Line_too_long
  val write_value :
    ?maxlen1:int ->
    ?maxlen:int ->
    ?hardmaxlen1:int ->
    ?hardmaxlen:int ->
    ?fold_qstring:bool ->
    ?fold_literal:bool ->
    ?unused:int Pervasives.ref ->
    ?hardunused:int Pervasives.ref ->
    Netchannels.out_obj_channel -> Netmime_string.s_token list -> unit
  val param_tokens :
    ?maxlen:int ->
    (string * Netmime_string.s_param) list -> Netmime_string.s_token list
  val split_uri : string -> Netmime_string.s_token list
  val scan_multipart_body :
    string ->
    start_pos:int ->
    end_pos:int -> boundary:string -> ((string * string) list * string) list
  val scan_multipart_body_and_decode :
    string ->
    start_pos:int ->
    end_pos:int -> boundary:string -> ((string * string) list * string) list
  val scan_multipart_body_from_netstream :
    Netstream.in_obj_stream ->
    boundary:string ->
    create:((string * string) list -> 'a) ->
    add:('-> Netstream.in_obj_stream -> int -> int -> unit) ->
    stop:('-> unit) -> unit
  val read_multipart_body :
    (Netstream.in_obj_stream -> 'a) ->
    string -> Netstream.in_obj_stream -> 'a list
  val create_boundary : ?random:string list -> ?nr:int -> unit -> string
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_proxy.ReliabilityCache.html0000644000175000017500000005476612731530352023532 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_proxy.ReliabilityCache sig
  type rcache
  type rcache_policy =
      [ `Any_failing_port_disables_host
      | `Failing_port_disables_host of int
      | `Independent
      | `None ]
  type rcache_config = {
    rcache_policy : Rpc_proxy.ReliabilityCache.rcache_policy;
    rcache_disable_timeout_min : float;
    rcache_disable_timeout_max : float;
    rcache_threshold : int;
    rcache_availability :
      Rpc_proxy.ReliabilityCache.rcache -> Unix.sockaddr -> bool;
  }
  val create_rcache_config :
    ?policy:Rpc_proxy.ReliabilityCache.rcache_policy ->
    ?disable_timeout_min:float ->
    ?disable_timeout_max:float ->
    ?threshold:int ->
    ?availability:(Rpc_proxy.ReliabilityCache.rcache -> Unix.sockaddr -> bool) ->
    unit -> Rpc_proxy.ReliabilityCache.rcache_config
  val create_rcache :
    Rpc_proxy.ReliabilityCache.rcache_config ->
    Rpc_proxy.ReliabilityCache.rcache
  val rcache_config :
    Rpc_proxy.ReliabilityCache.rcache ->
    Rpc_proxy.ReliabilityCache.rcache_config
  val global_rcache_config : unit -> Rpc_proxy.ReliabilityCache.rcache_config
  val set_global_rcache_config :
    Rpc_proxy.ReliabilityCache.rcache_config -> unit
  val global_rcache : unit -> Rpc_proxy.ReliabilityCache.rcache
  val derive_rcache :
    Rpc_proxy.ReliabilityCache.rcache ->
    Rpc_proxy.ReliabilityCache.rcache_config ->
    Rpc_proxy.ReliabilityCache.rcache
  val incr_rcache_error_counter :
    Rpc_proxy.ReliabilityCache.rcache -> Unix.sockaddr -> unit
  val reset_rcache_error_counter :
    Rpc_proxy.ReliabilityCache.rcache -> Unix.sockaddr -> unit
  val sockaddr_is_enabled :
    Rpc_proxy.ReliabilityCache.rcache -> Unix.sockaddr -> bool
  val host_is_enabled :
    Rpc_proxy.ReliabilityCache.rcache -> Unix.inet_addr -> bool
end
ocamlnet-4.1.2/doc/html-main/Netftp_client.html0000644000175000017500000020743112731530352020073 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_client

Module Netftp_client

module Netftp_client: sig .. end
FTP client

Currently implements:

  • Core FTP (RFC 959), except compressed transfer modes, and except page files
  • Negotiation of FTP extensions (RFC 2389)
  • Common FTP extensions (RFC 3659)
  • IPv6 (RFC 2428)
  • Internationalization (RFC 2640)
  • Directory walking (NVFS) and direct access (TVFS)
  • TLS (it is required, though, that a TLS provider is initialized, see Tls for more information)
  • GSSAPI (RFC 2228)
The client is written in asynchronous style (using Uq_engines).

The interface of this module was changed in Ocamlnet-3.3. Before this release, the module was marked as "experimental". This is no longer the case, as the interface has been updated, and the missing features have been added (e.g. STOR support).


exception FTP_error of exn
Something went wrong, often on socket level
exception FTP_protocol_violation of string
The server violates the FTP specification
exception FTP_timeout of string
A timeout on the control or data connection (this is a fatal error)
exception GSSAPI_error of string
An error on GSSAPI level
type cmd_state = [ `Auth_data
| `Init
| `Not_connected
| `Pass_acct_seq
| `Perm_failure
| `Preliminary
| `Proto_error
| `Rename_seq
| `Restart_seq
| `Success
| `Temp_failure
| `User_acct_seq
| `User_pass_seq ]
The command state:
  • `Not_connected: Not connected.
  • `Init: Just connected, no greeting message arrived yet
  • `Success: Got the greeting message/last command was successful
  • `Proto_error: currently unused
  • `Temp_failure: Last command was not successful, and the code was between 400 and 499
  • `Perm_failure: Last command was not successful, and the code was between 500 and 599
  • `Rename_seq: Used instead of `Success after the RNFR command
  • `Restart_seq: Used instead of `Success after the REST command
  • `User_pass_seq: Used instead of `Success after the USER command when a password must be typed in
  • `User_acct_seq: Used instead of `Success after the USER command when an account ID must be typed in
  • `Pass_acct_seq: Used instead of `Success after the PASS command when an account iD must be typed in
  • `Preliminary: a reply with code 100 to 199. There will be another final reply for the command
  • `Auth_data: an ADAT reply inidicating that another round of authentication is necessary.

type port = [ `Active of string * int * Unix.file_descr
| `Ext_active of string * int * Unix.file_descr
| `Ext_passive of int
| `Passive of string * int
| `Unspecified ]
The port of the data connection: `Active means that the server initiates the data connection to the listening client, and in the case of `Passive the client initiates the data connection to the listening server. The string argument is the IP address as dotted quad, the int argument is the port number, and the descriptor is the listening master socket.
type form_code = [ `ASA | `Non_print | `Telnet ] 
The form_code has a meaning when FTP is used to print files:
  • `Non_print: This is not the case.
  • `Telnet: Telnet control codes are used for vertical movement
  • `ASA: ASA (Fortran) control codes are used for vertical movement

type representation = [ `ASCII of form_code option
| `EBCDIC of form_code option
| `Image ]
The representation of the transferred file:
  • `ASCII: An ASCII variant is used, i.e. the server sends files in ASCII encoding with CR/LF as end-of-line marker. Supported by all servers.
  • `EBCDIC: An EBCDIC variant is used, i.e. the server sends files in EBCDIC encoding with NEL as end-of-line marker
  • `Image: The file is transferred in its original binary representation. Supported by all servers.
"Local" representations are not supported.

This FTP client does not recode the files such that they match the selected representation. When files are downloaded, they are stored as they are received. When files are uploaded, they are sent as they are. The user of this client must do recodings when necessary (the class Netftp_data_endpoint.data_converter may be useful for this).

If no representation is selected, FTP servers assume `ASCII None as default.

type structure = [ `File_structure | `Record_structure ] 
The client supports two structures:
  • `File_structure: Files are simply contiguous streams of bytes
  • `Record_structure: Files are sequences of records. FTP does not make a difference between variable and fixed length records. It is not forbidden that the records are themselves structured into lines, in fact it can happen that end-of-line markers are contained in binary records. Operating systems that support record-structured files often store text files in this format, i.e. every line is stored in its own record, without end-of-line marker. If record structure is selected by a STRU command, it is recommended to use the classes Netftp_data_endpoint.out_record_channel and Netftp_data_endpoint.in_record_channel for the local representation of the files, otherwise the records may be incorrectly mapped to the local conventions.
Page-structured files (i.e. indexed files) are not supported.

If no structure is selected, FTP servers will assume file structure as default.

type transmission_mode = [ `Block_mode | `Stream_mode ] 
The transmission mode selects how the data are encoded in the data connection.
  • `Stream_mode: This is the simple format that is responsible for all the failed FTP downloads. It is supported by all FTP servers, actually, you cannot assume a better transmission mode from an unknown FTP server. It is unreliable because it cannot distinguish between a transmission failure and the regular end-of-file condition.
  • `Block_mode: This is an improved format using frames to protect the transmitted data. Unfortunately, almost no FTP server supports it.
Both modes are compatible with both structures, i.e. you can transfer a record-structured file in stream mode and a flat file in block mode. However, in practice this is not the case. Servers that only know flat files are likely to only support stream mode, and servers implementing record structure imply that block transfers base on the record format. So the advice is to use stream mode for flat files, and block mode for record files.
type ftp_auth = [ `GSSAPI | `None | `TLS ] 
type ftp_data_prot = [ `C | `E | `P | `S ] 
Meaning:
  • `C: no protection (clear)
  • `S: integrity protection
  • `E: encryption without integrity protection
  • `P: integrity protection and encryption (= privacy)

type support_level = [ `If_possible | `None | `Required ] 
type ftp_state = {
   cmd_state : cmd_state; (*
the command state
*)
   ftp_connected : bool; (*
whether connected with the server
*)
   ftp_data_conn : bool; (*
whether there is a clean data conn
*)
   ftp_user : string option; (*
successfully sent user identifier
*)
   ftp_password : string option; (*
successfully sent password
*)
   ftp_account : string option; (*
successfully sent account identifier
*)
   ftp_logged_in : bool; (*
whether the user is logged in
*)
   ftp_host : string; (*
Host name
*)
   ftp_port : port; (*
the selected port
*)
   ftp_repr : representation; (*
the selected representation
*)
   ftp_structure : structure; (*
the selected structure
*)
   ftp_trans : transmission_mode; (*
the selected trans mode
*)
   ftp_dir : string list; (*
The current directory, expressed as list of CWD changes minus CDUP changes. This is only reasonable if CWD does not include slashes. The list is in reverse order, i.e. deepest directory first.
*)
   ftp_features : (string * string option) list option; (*
The list of features returned by the last FEAT command. None means that no FEAT command was yet tried. Some [] means that there are no features (either FEAT returned an empty list, or the FEAT command is not implemented by the server). Otherwise the list enumerates pairs (label,param) where label is the case-sensitive feature label and param the optional parameter. There is no defined order for the list of features.
*)
   ftp_options : (string * string option) list; (*
Remembers the OPTS commands sent to the server. The list enumerates pairs (command,optionparam), where command is the uppercase command name the option refers to. Only the last negotiated optionparam for the command is remembered.
*)
   ftp_auth : ftp_auth; (*
Authentication/privacy mode (AUTH command)
*)
   ftp_auth_data : string option; (*
The data from the last ADAT reply, already base64-decoded
*)
   ftp_data_prot : ftp_data_prot; (*
Security protocol for data connections (PROT command)
*)
   ftp_data_pbsz : int; (*
protection buffer size (PBSZ command)
*)
   ftp_prot : Netftp_data_endpoint.ftp_protector option; (*
a security layer (RFC 2228)
*)
}
The ftp_state reflects the knowledge of the client about what has been agreed upon with the server.
type cmd = [ `ACCT of string
| `ADAT of string
| `ALLO of int * int option
| `APPE of
string * (ftp_state -> Netftp_data_endpoint.local_sender)
| `AUTH of string
| `CDUP
| `CWD of string
| `Connect of string * int
| `DELE of string
| `Disconnect
| `Dummy
| `EPRT
| `EPSV of [ `AF of Unix.socket_domain | `ALL ] option
| `FEAT
| `HELP of string option
| `LANG of string option
| `LIST of
string option *
(ftp_state -> Netftp_data_endpoint.local_receiver)
| `MDTM of string
| `MKD of string
| `MLSD of
string option *
(ftp_state -> Netftp_data_endpoint.local_receiver)
| `MLST of string option
| `MODE of transmission_mode
| `NLST of
string option *
(ftp_state -> Netftp_data_endpoint.local_receiver)
| `NOOP
| `OPTS of string * string option
| `PASS of string
| `PASV
| `PBSZ of int
| `PORT
| `PROT of ftp_data_prot
| `PWD
| `QUIT
| `REIN
| `REST of string
| `RETR of
string * (ftp_state -> Netftp_data_endpoint.local_receiver)
| `RMD of string
| `RNFR of string
| `RNTO of string
| `SITE of string
| `SIZE of string
| `SMNT of string
| `STAT of string option
| `STOR of
string * (ftp_state -> Netftp_data_endpoint.local_sender)
| `STOU of ftp_state -> Netftp_data_endpoint.local_sender
| `STRU of structure
| `SYST
| `Start_TLS of (module Netsys_crypto_types.TLS_CONFIG)
| `Start_protection of Netftp_data_endpoint.ftp_protector
| `TYPE of representation
| `USER of string ]
An FTP command. Not all commands are implemented by all servers.

`Start_TLS is a pseudo command - at this point the TLS handshake starts.

type reply = int * string 
Reply code plus text
class type ftp_client_pi = object .. end
The client protocol interpreter...
type ftp_method = ftp_client_pi -> unit Uq_engines.engine 
An ftp_method is a small procedure doing some task
exception FTP_method_temp_failure of int * string
exception FTP_method_perm_failure of int * string
exception FTP_method_unexpected_reply of int * string
These exceptions may be raised during execution by the FTP method. The int is the unexpected FTP control code and the string the corresponding text. A temporary failure has a code between 400 and 499, and a permanent failure has a code between 500 and 599.
val connect_method : host:string -> ?port:int -> unit -> ftp_method
This method connects to the host
val login_method : user:string ->
get_password:(unit -> string) ->
get_account:(unit -> string) -> unit -> ftp_method
This FTP method logs the user in. get_password is called when the FTP server asks for the password (may be skipped). get_account is called when the server asks for the account ID (may be skipped).
val quit_method : unit -> ftp_method
Quits and disconnects
val tls_method : config:(module Netsys_crypto_types.TLS_CONFIG) ->
required:bool -> unit -> ftp_method
This FTP method negotiates the use of TLS. If required, it is an error if TLS is not supported. Otherwise, it is ok to omit the TLS protection.
val gssapi_method : config:Netsys_gssapi.client_config ->
required:bool -> (module Netsys_gssapi.GSSAPI) -> ftp_method
This method negotiates the use of GSSAPI authentication and security. You need to pass the GSSAPI provider (e.g. Netgss.System).

The config can often simply be created with Netsys_gssapi.create_client_config(), as normally reasonably defaults are assumed by the GSSAPI provider. See Netsys_gssapi.create_client_config for options.

If required, it is an error if the server doesn't support GSSAPI authentication. Otherwise, this method is a no-op in this case.

Note that you cannot combine gssapi_method with tls_method. Although the gssapi_method authenticates the user, you still need to log in, although without password (basically, GSSAPI just gives you permissions to be somebody, but you still need to select who you want to be).

val walk_method : [ `Dir of string | `File of string | `Stay ] -> ftp_method
This FTP method walks to the target directory:

  • `File name: The name is interpreted as slash-separated path. It is always interpreted relative to the home directory of the user (i.e. the directory after login), even if it begins with a slash. The FTP command walks to the directory containing name.
  • `Dir name: The FTP command walks to the directory name (same syntax as for `File).
  • `Stay: The FTP command does nothing (stays in the current directory).

type filename = [ `NVFS of string | `TVFS of string | `Verbatim of string ] 
There are several methods how to specify filenames:
  • `NVFS name: The "Network Virtual File System" is the normal way of accessing FTP files. The client walks into the directory containing the file using CWD and CDUP commands, and calls the file operation from this directory. For simplicity, this client interprets slashes in name as path component separators. The FTP server will never see these slashes.
  • `TVFS name: The optional "Trivial Network File System" avoids the CWD and CDUP commands. The tagged name is normalized (double slashed removed etc.), and is passed to the server as-is. Before using the faster TVFS one should check whether it is supported (feature "TVFS"). Note that even for TVFS there are no special files "." and ".."!
  • `Verbatim name: The string name is passed to the server without transforming it in any way.

val get_method : file:filename ->
representation:representation ->
store:(ftp_state -> Netftp_data_endpoint.local_receiver) ->
unit -> ftp_method
This FTP method walks to the right directory and gets file from the server. The file is stored in the local_receiver that can be obtained by calling the store function. The selected representation remains unchanged.
val put_method : ?meth:[ `APPE | `STOR ] ->
file:filename ->
representation:representation ->
store:(ftp_state -> Netftp_data_endpoint.local_sender) ->
unit -> ftp_method
This FTP method walks to the right directory and puts file to the server. The file is taken from the local_sender that can be obtained by calling the store function. The selected representation remains unchanged.

meth selects the method to use (default `STOR).

val invoke_method : command:cmd -> unit -> ftp_method
This FTP method simply invokes command.
val set_structure_method : structure -> ftp_method
Requests a certain structure for future file transfers
val set_mode_method : transmission_mode -> ftp_method
Requests a certain mode for future file transfers
val rename_method : file_from:filename ->
file_to:filename -> unit -> ftp_method
Renames the file_from into file_to.

Both file names must be of the same type, either `NVFS or `Verbatim. If `NVFS, both names must be in the same directory.

val mkdir_method : filename -> ftp_method
Creates the named directory
val rmdir_method : filename -> ftp_method
Deletes the named directory
val delete_method : filename -> ftp_method
Deletes the named file
val list_method : dir:filename ->
representation:representation ->
store:(ftp_state -> Netftp_data_endpoint.local_receiver) ->
unit -> ftp_method
Lists the contents of the directory dir using the LIST command. The representation must not be `Image.
val nlst_method : dir:filename ->
representation:representation ->
store:(ftp_state -> Netftp_data_endpoint.local_receiver) ->
unit -> ftp_method
Lists the contents of the directory dir using the NLST command The representation must not be `Image.
val parse_nlst_document : string -> string list
Returns the filenames contained in the output of `NLST
val mdtm_method : file:filename ->
process_result:(float -> unit) -> unit -> ftp_method
Determines the date and time of the last modification of file. On success, process_result is called.
val size_method : file:filename ->
representation:representation ->
process_result:(int64 -> unit) -> unit -> ftp_method
Determines the size of file. On success, process_result is called. The size depends on representation.
val feat_method : ?process_result:((string * string option) list -> unit) ->
unit -> ftp_method
Get the list of feature tokens (see also Netftp_client.ftp_state.ftp_features)
type entry = string * (string * string) list 
A file entry (name, facts). The facts are given as pairs (factname,value) where factname is always lowercase. For parsers for common facts see below.
val mlst_method : file:filename ->
process_result:(entry list -> unit) ->
unit -> ftp_method
Get the file entry for file.
val mlsd_method : dir:filename ->
store:(ftp_state -> Netftp_data_endpoint.local_receiver) ->
unit -> ftp_method
Gets the entries for this directory.
val parse_mlsd_document : string -> entry list
Returns the entries contained in the output of `MLSD
type entry_type = [ `Cdir | `Dir | `File | `Other | `Pdir ] 
Types:
  • `File: entry refers to file
  • `Cdir: entry refers to the directory being listed
  • `Pdir: entry is a parent of the directory being listed
  • `Dir: entry refers to directory
  • `Other: entry is neither file nor directory

type entry_perm = [ `Append
| `Create
| `Delete
| `Delete_member
| `Enter
| `List
| `Mkdir
| `Read
| `Rename
| `Write ]
Permissions:
  • `Append: append to file possible
  • `Create: file can be created in this dir
  • `Delete: file or dir can be deleted
  • `Enter: dir can be entered
  • `Rename: file or dir can be renamed
  • `List: dir can be listed
  • `Mkdir: subdir can be created in this dir
  • `Delete_member: a file or dir can be deleted in this directory
  • `Read: a file can be retrieved
  • `Write: a file can be stored


The following functions extract commonly used facts from entries. They may raise Not_found.
val get_name : entry -> string
val get_size : entry -> int64
val get_modify : entry -> float
val get_create : entry -> float
val get_type : entry -> entry_type
val get_unique : entry -> string
val get_perm : entry -> entry_perm list
val get_lang : entry -> string
val get_media_type : entry -> string
val get_charset : entry -> string
val get_unix_mode : entry -> int
val get_unix_uid : entry -> string
val get_unix_gid : entry -> string
class ftp_client : ?event_system:Unixqueue.event_system -> unit -> object .. end
The ftp client is a user session that may even span several connections.

Examples and Discussion

To download a single flat file from a server:

 
   let buffer = Buffer.create 1000 in
   let ch = new Netchannels.output_buffer buffer in
   let client = new ftp_client() in
   client # exec (connect_method ~host:"127.0.0.1" ());
   client # exec (login_method ~user:"foo"
                                ~get_password:(fun () -> "password")
                                ~get_account:(fun () -> "foo") ());
   client # exec (get_method ~file:(`NVFS "path/to/file")
                             ~representation:`Image
                             ~store:(fun _ -> `File_structure ch) ());
 

The file is stored in buffer. By using a different netchannel, it can be stored whereever wanted.

To download a record-structured text file, use a store like:

 
    let ch = (as above) in
    let rec_ch = new Netftp_data_endpoint.write_out_record_channel
                       ~repr:(`ASCII_unix `Enc_iso88591)
                       ch
    ...
    ... ~store:(fun _ -> `Record_structure rec_ch)
 

Here, the end-of-record is transcoded to newline. Note that the ASCII variant (`Enc_iso88591) is ignored by write_out_record_channel. Open: How to select record structure using an FTP method.

Character conversions: To convert an EBCDIC file to ASCII, use something like

 
    let ch = (as above) in
    let converter = new Netftp_data_endpoint.data_converter
                         ~fromrepr:(`EBCDIC `Enc_cp1047)
                         ~torepr:(`ASCII_unix `Enc_iso88591) in
    let ch_ebcdic = new Netchannels.output_filter converter ch in
    ...
    ... ~representation:(`EBCDIC None)
    ... ~store:(fun _ -> `File_structure ch_ebcdic)
 

The class data_converter also performs the transformation of the end-of-line convention, unlike the similar class Netconversion.conversion_pipe.

Examples and Discussion

To download a single flat file from a server:

 
   let buffer = Buffer.create 1000 in
   let ch = new Netchannels.output_buffer buffer in
   let client = new ftp_client() in
   client # exec (connect_method ~host:"127.0.0.1" ());
   client # exec (login_method ~user:"foo"
                                ~get_password:(fun () -> "password")
                                ~get_account:(fun () -> "foo") ());
   client # exec (get_method ~file:(`NVFS "path/to/file")
                             ~representation:`Image
                             ~store:(fun _ -> `File_structure ch) ());
 

The file is stored in buffer. By using a different netchannel, it can be stored whereever wanted.

To download a record-structured text file, use a store like:

 
    let ch = (as above) in
    let rec_ch = new Netftp_data_endpoint.write_out_record_channel
                       ~repr:(`ASCII_unix `Enc_iso88591)
                       ch
    ...
    ... ~store:(fun _ -> `Record_structure rec_ch)
 

Here, the end-of-record is transcoded to newline. Note that the ASCII variant (`Enc_iso88591) is ignored by write_out_record_channel. Open: How to select record structure using an FTP method.

Character conversions: To convert an EBCDIC file to ASCII, use something like

 
    let ch = (as above) in
    let converter = new Netftp_data_endpoint.data_converter
                         ~fromrepr:(`EBCDIC `Enc_cp1047)
                         ~torepr:(`ASCII_unix `Enc_iso88591) in
    let ch_ebcdic = new Netchannels.output_filter converter ch in
    ...
    ... ~representation:(`EBCDIC None)
    ... ~store:(fun _ -> `File_structure ch_ebcdic)
 

The class data_converter also performs the transformation of the end-of-line convention, unlike the similar class Netconversion.conversion_pipe.

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Uq_engines.html0000644000175000017500000023674612731530352017405 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines

Module Uq_engines

module Uq_engines: sig .. end
An engine performs a certain task in an autonomous way. Engines are attached to a Unixqueue.event_system, and do their task by generating events for resources of the operating system, and by handling such events. Engines are in one of four states: They may be still working, they may be done, they may be aborted, or they may be in an error state. The three latter states a called final states, because they indicate that the engine has stopped operation.

It is possible to ask an engine to notify another object when it changes its state. For simplicity, notification is done by invoking a callback function, and not by issuing notification events.

Effectively, engines provide a calculus for cooperative microthreading. This calculus includes combinators for sequential execution and synchronization. Moreover, it is easy to connect it with callback-style microthreading - one can arrange callbacks when an engine is done, and one can catch callbacks and turn them into engines.



Exceptions


exception Closed_channel
Raised when a method of a closed channel object is called (only channel methods count).

This exception should be regarded as equivalent to Netchannels.Closed_channel, but need not be the same exception.

exception Broken_communication
Some engines indicate this error when they cannot continue because the other endpoint of communication signals an error.

This exception is not raised, but used as argument of the `Error state.

exception Watchdog_timeout
Used by the watchdog engine to indicate a timeout.

This exception is not raised, but used as argument of the `Error state.

exception Timeout
Used by input_engine and output_engine to indicate timeouts
exception Addressing_method_not_supported
Raised by client_endpoint_connector and server_endpoint_acceptor to indicate that the passed address is not supported by the class.
exception Cancelled
The callback function of a multiplex_controller is invoked with this exception if the operation is cancelled.

Engine definition


type 't engine_state = [ `Aborted | `Done of 't | `Error of exn | `Working of int ] 
The type of states with result values of type 't:
  • `Working n: The engine is working. The number n counts the number of events that have been processed.
  • `Done arg: The engine has completed its task without errors. The argument arg is the result value of the engine
  • `Error exn: The engine has aborted because of an error. The argument exn describes the error as an exception.
  • `Aborted: The engine has aborted because the abort method was called

type 't final_state = [ `Aborted | `Done of 't | `Error of exn ] 
Same as engine_state without `Working. These are only the final states.
val string_of_state : 'a engine_state -> string
For debug purposes: Returns a string describing the state
class type ['t] engine = object .. end
This class type defines the interface an engine must support.
class ['t] delegate_engine : 't #engine -> ['t] engine
Turns an engine value into a class

Engines and callbacks


val when_state : ?is_done:('a -> unit) ->
?is_error:(exn -> unit) ->
?is_aborted:(unit -> unit) ->
?is_progressing:(int -> unit) -> 'a #engine -> unit
Watches the state of the argument engine, and arranges that one of the functions is called when the corresponding state change is done. Once a final state is reached, the engine is no longer watched. Note that when_state only observes future state changes.

If one of the functions raises an exception, this exception is propagated to the caller of Unixqueue.run.


is_done : The state transitions to `Done. The argument of is_done is the argument of the `Done state.
is_error : The state transitions to `Error. The argument of is_error is the argument of the `Error state.
is_aborted : The state transitions to `Aborted.
is_progressing : This function is called when the `Working state changes. The int argument is the new `Working arg.
class ['a] signal_engine : Unixqueue.event_system -> object .. end
let se = new signal_engine esys: The engine se remains in `Working 0 until the method se # signal x is called.
val signal_engine : Unixqueue.event_system ->
'a engine * ('a final_state -> unit)
let (se, signal) = signal_engine esys: Same as function

Combinators



Combinators



The following combinators serve as the control structures to connect primitive engines with each other.
class [['a, 'b]] map_engine : map_done:('a -> 'b engine_state) -> ?map_error:exn -> 'b engine_state -> ?map_aborted:unit -> 'b engine_state -> ?propagate_working:bool -> 'a #engine -> ['b] engine
The map_engine observes the argument engine, and when the state changes to `Done, `Error, or `Aborted, the corresponding mapping function is called, and the resulting state becomes the state of the mapped engine.
val map_engine : map_done:('a -> 'b engine_state) ->
?map_error:(exn -> 'b engine_state) ->
?map_aborted:(unit -> 'b engine_state) ->
?propagate_working:bool -> 'a #engine -> 'b engine
Same as function
class [['a, 'b]] fmap_engine : 'a #engine -> ('a final_state -> 'b final_state) -> ['b] engine
Similar to map_engine but different calling conventions: The mapping function is called when the argument engine reaches a final state, and this state can be mapped to another final state.
val fmap_engine : 'a #engine ->
('a final_state -> 'b final_state) ->
'b engine
Same as function

After opening Uq_engines.Operators, this is also available as operator >>, e.g.

 
         e >>
           (function
             | `Done r -> ...
             | `Error error -> ...
             | `Aborted -> ...
           )
       

class ['a] meta_engine : 'a #engine -> ['a final_state] engine
maps the final state s to `Done s
val meta_engine : 'a #engine -> 'a final_state engine
Same as function
class ['t] epsilon_engine : 't engine_state -> Unixqueue.event_system -> ['t] engine
This engine transitions from its initial state `Working 0 in one step ("epsilon time") to the passed constant state.
val epsilon_engine : 't engine_state -> Unixqueue.event_system -> 't engine
Same as function
class [['a, 'b]] seq_engine : 'a #engine -> ('a -> 'b #engine) -> ['b] engine
This engine runs two engines in sequential order.
val seq_engine : 'a #engine ->
('a -> 'b #engine) -> 'b engine
Same as function.

After opening Uq_engines.Operators, this is also available as operator ++, e.g.

 e1 ++ (fun r1 -> e2) 
(when e1 and e2 are engines, and r1 is the result of e1).
class [['a, 'b]] qseq_engine : 'a #engine -> ('a -> 'b #engine) -> ['b] engine
val qseq_engine : 'a #engine ->
('a -> 'b #engine) -> 'b engine
Almost the same as seq_engine, but this version does not propagate working state (i.e. no progress reporting).

qseq_engine should be preferred for recursive chains of engines.

class ['a] stream_seq_engine : 'a -> ('a -> 'a #engine) Stream.t -> Unixqueue.event_system -> ['a] engine
let se = new stream_seq_engine x0 s esys: The constructed engine se fetches functions f : 'a -> 'a #engine from the stream s, and runs the engines obtained by calling these functions e = f x one after the other.
val stream_seq_engine : 'a ->
('a -> 'a #engine) Stream.t ->
Unixqueue.event_system -> 'a engine
Same as function
class [['a, 'b]] sync_engine : 'a #engine -> 'b #engine -> [('a * 'b)] engine
This engine runs two engines in parallel, and waits until both are `Done (synchronization).
val sync_engine : 'a #engine -> 'b #engine -> ('a * 'b) engine
Same as function
class [['a, 'b]] msync_engine : 'a #engine list -> ('a -> 'b -> 'b) -> 'b -> Unixqueue.event_system -> ['b] engine
Multiple synchronization: let me = new msync_engine el f x0 esys - Runs the engines in el in parallel, and waits until all are `Done.
val msync_engine : 'a #engine list ->
('a -> 'b -> 'b) -> 'b -> Unixqueue.event_system -> 'b engine
Same as function
class ['a] delay_engine : float -> (unit -> 'a #engine) -> Unixqueue.event_system -> ['a] engine
let de = delay_engine d f esys: The engine e = f() is created after d seconds, and the result of e becomes the result of de.
val delay_engine : float ->
(unit -> 'a #engine) ->
Unixqueue.event_system -> 'a engine
Same as function
class ['a] timeout_engine : float -> exn -> 'a engine -> ['a] engine
timeout_engine d x e: If the engine e finishes within d seconds, the result remains unchanged.
val timeout_engine : float -> exn -> 'a engine -> 'a engine
Same as function
class watchdog : float -> 'a #engine -> [unit] engine
A watchdog engine checks whether the argument engine makes progress, and if there is no progress for the passed number of seconds, the engine is aborted, and the watchdog state changes to `Error Watchdog_timeout.
val watchdog : float -> 'a #engine -> unit engine
Same as function
class type ['a] serializer_t = object .. end
A serializer queues up engines, and starts the next engine when the previous one finishes.
class ['a] serializer : Unixqueue.event_system -> ['a] serializer_t
Creates a serializer
val serializer : Unixqueue.event_system -> 'a serializer_t
Same as function
class type ['a] prioritizer_t = object .. end
A prioritizer allows to prioritize the execution of engines: At any time, only engines of a certain priority p can be executed.
class ['a] prioritizer : Unixqueue.event_system -> ['a] prioritizer_t
Creates a prioritizer
val prioritizer : Unixqueue.event_system -> 'a prioritizer_t
Same as function
class type ['a] cache_t = object .. end
A cache contains a mutable value that is obtained by running an engine.
class ['a] cache : (Unixqueue.event_system -> 'a engine) -> Unixqueue.event_system -> ['a] cache_t
new cache f esys: A cache that runs f esys to obtain values
val cache : (Unixqueue.event_system -> 'a engine) ->
Unixqueue.event_system -> 'a cache_t
Same as function
class ['t] engine_mixin : 't engine_state -> Unixqueue.event_system -> object .. end
A useful class fragment that implements state and request_notification.
module Operators: sig .. end
Handy operators: ++, >>, and eps_e

Basic I/O engines


class poll_engine : ?extra_match:exn -> bool -> (Unixqueue.operation * float) list -> Unixqueue.event_system -> object .. end
This engine waits until one of the passed operations can be carried out, or until one of the operations times out.
class ['a] input_engine : (Unix.file_descr -> 'a) -> Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
Generic input engine for reading from a file descriptor: let e = new input_engine f fd tmo - Waits until the file descriptor becomes readable, and calls then let x = f fd to read from the descriptor.
class ['a] output_engine : (Unix.file_descr -> 'a) -> Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
Generic output engine for writing to a file descriptor: let e = new output_engine f fd tmo - Waits until the file descriptor becomes writable, and calls then let x = f fd to write to the descriptor.
class poll_process_engine : ?period:float -> pid:int -> Unixqueue.event_system -> [Unix.process_status] engine
This class is deprecated! Use the classes in Shell_uq instead.

More I/O

The module Uq_io provides a bunch of functions to read and write data via various "devices". All these functions return engines, and are easy to use. Devices can be file descriptors, but also other data structures. In particular, there is also support for buffered I/O and for reading line-by-line from an input device.

More I/O

The module Uq_io provides a bunch of functions to read and write data via various "devices". All these functions return engines, and are easy to use. Devices can be file descriptors, but also other data structures. In particular, there is also support for buffered I/O and for reading line-by-line from an input device.

Recursion



More I/O

The module Uq_io provides a bunch of functions to read and write data via various "devices". All these functions return engines, and are easy to use. Devices can be file descriptors, but also other data structures. In particular, there is also support for buffered I/O and for reading line-by-line from an input device.

Recursion



When programming with engines, it is normal to use recursion for any kind of loops. For example, to read the lines from a file:

      open Uq_engines.Operators  (* for ">>" and "++" *)

      let fd = 
        Unix.openfile filename [Unix.O_RDONLY] 0 in
      let d = 
        `Buffer_in(Uq_io.create_in_buffer(`Polldescr(`Read_write,fd,esys))) in

      let rec read_lines acc =
        Uq_io.input_line_e d >>
          (function                       (* catch exception End_of_file *)
            | `Done line -> `Done(Some line)
            | `Error End_of_file -> `Done None
            | `Error error -> `Error error
            | `Aborted -> `Aborted
          ) ++
          (function
            | Some line ->
                read_lines (line :: acc)
            | None ->
                eps_e (`Done (List.rev acc)) esys
          ) in

      let e = read_lines []
    

There is generally the question whether this style leads to stack overflows. This depends on the mechanisms that come into play:

  • The engine mechanism passing control from one engine to the next is not tail-recursive, and thus the stack can overflow when the recursion becomes too deep
  • The event queue mechanism, however, does not have this problem. Control falls automatically back to the event queue whenever I/O needs to be done.
In this example, this means that only the engine mechanism is used as long as the data is read from the buffer. When the buffer needs to be refilled, however, control is passed back to the event queue (so the stack is cleaned), and the continuation of the execution is only managed via closures (which only allocate memory on the heap, not on the stack). Usually, this is a good compromise: The engine mechnism is a lot faster, but I/O is an indicator for using the better but slower technique.

Also note another difference: The event queue mechanism allows that other asynchronous code attached to the same event queue may run (control maybe yielded to unrelated execution contexts). The pure engine mechanism does not allow that. This may be handy when exclusive access to variables is needed. (But be careful here - this is very sensitive to minimal changes of the implementation.)

Certain engines enforce using the event queue mechanisms although they are unrelated to I/O. Especially Uq_engines.delay_engine is useful here: A "delay" of 0 seconds is already sufficient to go back to the event queue. If recursions sometimes lead to stack overflows the solution is to include such a zero delay before doing the self call.

More I/O

The module Uq_io provides a bunch of functions to read and write data via various "devices". All these functions return engines, and are easy to use. Devices can be file descriptors, but also other data structures. In particular, there is also support for buffered I/O and for reading line-by-line from an input device.

Recursion



When programming with engines, it is normal to use recursion for any kind of loops. For example, to read the lines from a file:

      open Uq_engines.Operators  (* for ">>" and "++" *)

      let fd = 
        Unix.openfile filename [Unix.O_RDONLY] 0 in
      let d = 
        `Buffer_in(Uq_io.create_in_buffer(`Polldescr(`Read_write,fd,esys))) in

      let rec read_lines acc =
        Uq_io.input_line_e d >>
          (function                       (* catch exception End_of_file *)
            | `Done line -> `Done(Some line)
            | `Error End_of_file -> `Done None
            | `Error error -> `Error error
            | `Aborted -> `Aborted
          ) ++
          (function
            | Some line ->
                read_lines (line :: acc)
            | None ->
                eps_e (`Done (List.rev acc)) esys
          ) in

      let e = read_lines []
    

There is generally the question whether this style leads to stack overflows. This depends on the mechanisms that come into play:

  • The engine mechanism passing control from one engine to the next is not tail-recursive, and thus the stack can overflow when the recursion becomes too deep
  • The event queue mechanism, however, does not have this problem. Control falls automatically back to the event queue whenever I/O needs to be done.
In this example, this means that only the engine mechanism is used as long as the data is read from the buffer. When the buffer needs to be refilled, however, control is passed back to the event queue (so the stack is cleaned), and the continuation of the execution is only managed via closures (which only allocate memory on the heap, not on the stack). Usually, this is a good compromise: The engine mechnism is a lot faster, but I/O is an indicator for using the better but slower technique.

Also note another difference: The event queue mechanism allows that other asynchronous code attached to the same event queue may run (control maybe yielded to unrelated execution contexts). The pure engine mechanism does not allow that. This may be handy when exclusive access to variables is needed. (But be careful here - this is very sensitive to minimal changes of the implementation.)

Certain engines enforce using the event queue mechanisms although they are unrelated to I/O. Especially Uq_engines.delay_engine is useful here: A "delay" of 0 seconds is already sufficient to go back to the event queue. If recursions sometimes lead to stack overflows the solution is to include such a zero delay before doing the self call.

More Engines



More I/O

The module Uq_io provides a bunch of functions to read and write data via various "devices". All these functions return engines, and are easy to use. Devices can be file descriptors, but also other data structures. In particular, there is also support for buffered I/O and for reading line-by-line from an input device.

Recursion



When programming with engines, it is normal to use recursion for any kind of loops. For example, to read the lines from a file:

      open Uq_engines.Operators  (* for ">>" and "++" *)

      let fd = 
        Unix.openfile filename [Unix.O_RDONLY] 0 in
      let d = 
        `Buffer_in(Uq_io.create_in_buffer(`Polldescr(`Read_write,fd,esys))) in

      let rec read_lines acc =
        Uq_io.input_line_e d >>
          (function                       (* catch exception End_of_file *)
            | `Done line -> `Done(Some line)
            | `Error End_of_file -> `Done None
            | `Error error -> `Error error
            | `Aborted -> `Aborted
          ) ++
          (function
            | Some line ->
                read_lines (line :: acc)
            | None ->
                eps_e (`Done (List.rev acc)) esys
          ) in

      let e = read_lines []
    

There is generally the question whether this style leads to stack overflows. This depends on the mechanisms that come into play:

  • The engine mechanism passing control from one engine to the next is not tail-recursive, and thus the stack can overflow when the recursion becomes too deep
  • The event queue mechanism, however, does not have this problem. Control falls automatically back to the event queue whenever I/O needs to be done.
In this example, this means that only the engine mechanism is used as long as the data is read from the buffer. When the buffer needs to be refilled, however, control is passed back to the event queue (so the stack is cleaned), and the continuation of the execution is only managed via closures (which only allocate memory on the heap, not on the stack). Usually, this is a good compromise: The engine mechnism is a lot faster, but I/O is an indicator for using the better but slower technique.

Also note another difference: The event queue mechanism allows that other asynchronous code attached to the same event queue may run (control maybe yielded to unrelated execution contexts). The pure engine mechanism does not allow that. This may be handy when exclusive access to variables is needed. (But be careful here - this is very sensitive to minimal changes of the implementation.)

Certain engines enforce using the event queue mechanisms although they are unrelated to I/O. Especially Uq_engines.delay_engine is useful here: A "delay" of 0 seconds is already sufficient to go back to the event queue. If recursions sometimes lead to stack overflows the solution is to include such a zero delay before doing the self call.

More Engines



Pointers to other modules related to engines:



More I/O

The module Uq_io provides a bunch of functions to read and write data via various "devices". All these functions return engines, and are easy to use. Devices can be file descriptors, but also other data structures. In particular, there is also support for buffered I/O and for reading line-by-line from an input device.

Recursion



When programming with engines, it is normal to use recursion for any kind of loops. For example, to read the lines from a file:

      open Uq_engines.Operators  (* for ">>" and "++" *)

      let fd = 
        Unix.openfile filename [Unix.O_RDONLY] 0 in
      let d = 
        `Buffer_in(Uq_io.create_in_buffer(`Polldescr(`Read_write,fd,esys))) in

      let rec read_lines acc =
        Uq_io.input_line_e d >>
          (function                       (* catch exception End_of_file *)
            | `Done line -> `Done(Some line)
            | `Error End_of_file -> `Done None
            | `Error error -> `Error error
            | `Aborted -> `Aborted
          ) ++
          (function
            | Some line ->
                read_lines (line :: acc)
            | None ->
                eps_e (`Done (List.rev acc)) esys
          ) in

      let e = read_lines []
    

There is generally the question whether this style leads to stack overflows. This depends on the mechanisms that come into play:

  • The engine mechanism passing control from one engine to the next is not tail-recursive, and thus the stack can overflow when the recursion becomes too deep
  • The event queue mechanism, however, does not have this problem. Control falls automatically back to the event queue whenever I/O needs to be done.
In this example, this means that only the engine mechanism is used as long as the data is read from the buffer. When the buffer needs to be refilled, however, control is passed back to the event queue (so the stack is cleaned), and the continuation of the execution is only managed via closures (which only allocate memory on the heap, not on the stack). Usually, this is a good compromise: The engine mechnism is a lot faster, but I/O is an indicator for using the better but slower technique.

Also note another difference: The event queue mechanism allows that other asynchronous code attached to the same event queue may run (control maybe yielded to unrelated execution contexts). The pure engine mechanism does not allow that. This may be handy when exclusive access to variables is needed. (But be careful here - this is very sensitive to minimal changes of the implementation.)

Certain engines enforce using the event queue mechanisms although they are unrelated to I/O. Especially Uq_engines.delay_engine is useful here: A "delay" of 0 seconds is already sufficient to go back to the event queue. If recursions sometimes lead to stack overflows the solution is to include such a zero delay before doing the self call.

More Engines



Pointers to other modules related to engines:



Moved



More I/O

The module Uq_io provides a bunch of functions to read and write data via various "devices". All these functions return engines, and are easy to use. Devices can be file descriptors, but also other data structures. In particular, there is also support for buffered I/O and for reading line-by-line from an input device.

Recursion



When programming with engines, it is normal to use recursion for any kind of loops. For example, to read the lines from a file:

      open Uq_engines.Operators  (* for ">>" and "++" *)

      let fd = 
        Unix.openfile filename [Unix.O_RDONLY] 0 in
      let d = 
        `Buffer_in(Uq_io.create_in_buffer(`Polldescr(`Read_write,fd,esys))) in

      let rec read_lines acc =
        Uq_io.input_line_e d >>
          (function                       (* catch exception End_of_file *)
            | `Done line -> `Done(Some line)
            | `Error End_of_file -> `Done None
            | `Error error -> `Error error
            | `Aborted -> `Aborted
          ) ++
          (function
            | Some line ->
                read_lines (line :: acc)
            | None ->
                eps_e (`Done (List.rev acc)) esys
          ) in

      let e = read_lines []
    

There is generally the question whether this style leads to stack overflows. This depends on the mechanisms that come into play:

  • The engine mechanism passing control from one engine to the next is not tail-recursive, and thus the stack can overflow when the recursion becomes too deep
  • The event queue mechanism, however, does not have this problem. Control falls automatically back to the event queue whenever I/O needs to be done.
In this example, this means that only the engine mechanism is used as long as the data is read from the buffer. When the buffer needs to be refilled, however, control is passed back to the event queue (so the stack is cleaned), and the continuation of the execution is only managed via closures (which only allocate memory on the heap, not on the stack). Usually, this is a good compromise: The engine mechnism is a lot faster, but I/O is an indicator for using the better but slower technique.

Also note another difference: The event queue mechanism allows that other asynchronous code attached to the same event queue may run (control maybe yielded to unrelated execution contexts). The pure engine mechanism does not allow that. This may be handy when exclusive access to variables is needed. (But be careful here - this is very sensitive to minimal changes of the implementation.)

Certain engines enforce using the event queue mechanisms although they are unrelated to I/O. Especially Uq_engines.delay_engine is useful here: A "delay" of 0 seconds is already sufficient to go back to the event queue. If recursions sometimes lead to stack overflows the solution is to include such a zero delay before doing the self call.

More Engines



Pointers to other modules related to engines:



Moved



OCamlnet-4.0 moves a number of definitions to the modules For convenience, the types are still also exported here, but functions and classes are now defined in these modules. See also the module Uq_engines_compat.
class type async_out_channel = object .. end
class type async_in_channel = object .. end
class type async_out_channel_engine = object .. end
type copy_task = [ `Bidirectional of Unix.file_descr * Unix.file_descr
| `Tridirectional of Unix.file_descr * Unix.file_descr * Unix.file_descr
| `Uni_socket of Unix.file_descr * Unix.file_descr
| `Unidirectional of Unix.file_descr * Unix.file_descr ]
class type async_in_channel_engine = object .. end
class type multiplex_controller = object .. end
This definition has now been moved to Uq_multiplex.multiplex_controller
exception Mem_not_supported
class type datagram_multiplex_controller = object .. end
type onshutdown_out_spec = [ `Action of
async_out_channel_engine ->
multiplex_controller -> unit engine_state -> unit
| `Ignore
| `Initiate_shutdown ]
type onshutdown_in_spec = [ `Action of
async_in_channel_engine ->
multiplex_controller -> unit engine_state -> unit
| `Ignore
| `Initiate_shutdown ]
type inetspec = [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
| `Sock_inet_byname of Unix.socket_type * string * int ]
type sockspec = [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
| `Sock_inet_byname of Unix.socket_type * string * int
| `Sock_unix of Unix.socket_type * string ]
type connect_address = [ `Command of string * (int -> Unixqueue.event_system -> unit)
| `Socket of sockspec * connect_options
| `W32_pipe of Netsys_win32.pipe_mode * string ]
type connect_options = {
   conn_bind : sockspec option; (*
Bind the connecting socket to this address (same family as the connected socket required). None: Use an anonymous port.
*)
}
type connect_status = [ `Command of Unix.file_descr * int
| `Socket of Unix.file_descr * sockspec
| `W32_pipe of Unix.file_descr ]
class type client_endpoint_connector = object .. end
type listen_address = [ `Socket of sockspec * listen_options
| `W32_pipe of Netsys_win32.pipe_mode * string * listen_options ]
type listen_options = {
   lstn_backlog : int;
   lstn_reuseaddr : bool;
}
class type server_endpoint_acceptor = object .. end
class type server_endpoint_listener = object .. end
Moved to Uq_server.server_endpoint_listener
type datagram_type = [ `Inet6_udp | `Inet_udp | `Unix_dgram ] 
class type wrapped_datagram_socket = object .. end
class type datagram_socket_provider = object .. end

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netsys_mem.html0000644000175000017500000015243312731530352017421 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_mem

Module Netsys_mem

module Netsys_mem: sig .. end
Bigarrays as memory buffers

type memory = Netsys_types.memory 
We consider 1-dimensional bigarrays of chars as memory buffers. They have the useful property that the garbage collector cannot relocate them, i.e. the address is fixed. Also, one can mmap a file, and connect the bigarray with shared memory.

General


val blit_memory_to_bytes : memory -> int -> Bytes.t -> int -> int -> unit
blit_memory_to_bytes src srcoff dst dstoff len copies len characters from buffer src, starting at character number srcoff, to string dst, starting at character number dstoff

Raise Invalid_argument if srcoff and len do not designate a valid subbuffer of src, or if dstoff and len do not designate a valid substring of dst.

val blit_memory_to_string : memory -> int -> Bytes.t -> int -> int -> unit
Deprecated."Use blit_memory_to_bytes instead."
val blit_memory_to_bytes_unsafe : memory -> int -> Bytes.t -> int -> int -> unit
Unsafe version
val blit_memory_to_string_unsafe : memory -> int -> Bytes.t -> int -> int -> unit
Deprecated."Use blit_memory_to_bytes_unsafe instead."
val blit_bytes_to_memory : Bytes.t -> int -> memory -> int -> int -> unit
blit_bytes_to_memory src srcoff dst dstoff len copies len characters from string src, starting at character number srcoff, to buffer dst, starting at character number dstoff

Raise Invalid_argument if srcoff and len do not designate a valid substring of src, or if dstoff and len do not designate a valid subbuffer of dst.

val blit_bytes_to_memory_unsafe : Bytes.t -> int -> memory -> int -> int -> unit
Unsafe version
val blit_string_to_memory : string -> int -> memory -> int -> int -> unit
blit_string_to_memory src srcoff dst dstoff len: A version for immutable strings
val blit_string_to_memory_unsafe : string -> int -> memory -> int -> int -> unit
Unsafe version
val memory_of_bytes : Bytes.t -> memory
Return a new bigarray as a copy of the string
val memory_of_string : string -> memory
Return a new bigarray as a copy of the string
val bytes_of_memory : memory -> Bytes.t
Return a new string as a copy of the bigarray
val string_of_memory : memory -> string
Return a new string as a copy of the bigarray
val memory_address : memory -> nativeint
Returns the start address of the buffer
val memory_of_bigarray : ('a, 'b, 'c) Bigarray.Genarray.t -> memory
val memory_of_bigarray_1 : ('a, 'b, 'c) Bigarray.Array1.t -> memory
val memory_of_bigarray_2 : ('a, 'b, 'c) Bigarray.Array2.t -> memory
val memory_of_bigarray_3 : ('a, 'b, 'c) Bigarray.Array3.t -> memory
These functions return an arbitrary bigarray as memory.

Due to a bug in the OCaml runtime, this is for now limited to arrays of up to 2G size (in bytes). (The bug exists at least up to OCaml-3.12.1.)


Allocation and memory-mapping


val getpagesize : unit -> int
Returns the size of a page as reported by sysconf.

On many systems, a page has 4096 bytes, but this cannot be relied upon.

This function is only available if the system has sysconf.

val pagesize : int
The best guess at the page size
val alloc_memory_pages : ?addr:nativeint -> ?exec:bool -> int -> memory
Allocates memory in units of pages. The memory buffer will start on a page boundary.

The passed int is the requested number of bytes. The size of the buffer is rounded up so a whole number of pages is allocated.

Optionally, one can request a certain address addr (which must be a multiple of the page size). There is, however, no guarantee that this wish can be fulfilled. In any way, one should check with memory_address what the start address really is.

If exec, the memory region is marked as executable.

This function is only available if the system has sysconf, mmap, and allows to allocate anonymous memory with mmap (outside POSIX but common).

val alloc_aligned_memory : int -> int -> memory
alloc_aligned_memory alignment size: Allocates a buffer of size whose start address is a multiple of alignment. The alignment must be a power of two, and at least Sys.word_size/8.

Aligned memory can be useful for ensuring that the whole memory block is in the same cache line. A cache line typically has 64 or 128 bytes - but this is very platform-specific. (Linux: look at /proc/cpuinfo.)

This function is only available if the system has posix_memalign.

val memory_map_file : Unix.file_descr ->
?pos:int64 -> ?addr:nativeint -> bool -> int -> memory
memory_map_file fd shared size: Maps size bytes of the file fd into memory, and returns the memory buffer like Bigarray.Array1.map_file. pos and shared have the same meaning as there. In addr one can suggest a start address. There is, however, no guarantee that this wish can be fulfilled.
val memory_unmap_file : memory -> unit
Unmaps the file. The memory block must have been allocated with memory_map_file or with Bigarray.Array1.map_file.

Note that the data pointer of the bigarray is set to NULL, and that any further access of the array will trigger a segmentation violation! The intention of this function is to control when the file mapping is removed. Normally, this is done first when the GC finalizer is run.

It is required that there are no subarrays at the time of calling this function. (If so, the function does nothing.)

val zero_pages : memory -> int -> int -> unit
zero_pages m pos len: If possible, the memory pages in the range pos to pos+len-1 of m are allocated again, so that they replace the previous pages.

It is required that the start address of the range is a multiple of the page size, and the len is a multiple of the page size. Fails with Invalid_argument if the requirements are not met, or the function is otherwise unavailable.

Calling zero_pages is sometimes an optimization when old memory pages can be dropped, and when the alternative of overwriting these pages would imply a copy-on-write operation.

val grab : nativeint -> int -> memory
grab addr len: Interprets the address range from addr to addr+len-1 as memory bigarray.

This function does not allocate! It assumes that the given address range points to valid memory.


Interpreting memory as values


val as_value : memory -> int -> 'a
as_value mem offset: Returns a pointer to mem+offset. There must be a valid boxed value at this address (i.e. at the word preceding mem+offset there must be a valid block header, followed by a valid value of the right type). However, this is not checked:

This is an unsafe function that may crash the program if used in the wrong way!

It is possible that the memory block is deallocated while the returned value still exists. Any attempt to access the value will result into undefined behavior (anything from funny results to crashes may happen).

Some Ocaml primitives might not work on the returned values (polymorphic equality, marshalling, hashing) unless Netsys_mem.value_area is called for the memory block.

val as_obj : memory -> int -> Obj.t
Same as as_value but returns the value as Obj.t
val value_area : memory -> unit
Marks the memory block as value area. This enables that the value primitives (polymorphic equality, marshalling, hashing) return meaningful results. The memory area is automatically unmarked when the finaliser for the memory block is run.

Be careful when marking sub arrays.

This function is first available since O'Caml 3.11.

val obj_address : Obj.t -> nativeint
val hdr_address : Obj.t -> nativeint
These two functions return the address of the Obj.t and the address of the header of the Obj.t, respectively.

Note that this can only be relied upon if the input object cannot be moved around by the garbage collector!

val cmp_bytes : Bytes.t -> Bytes.t -> int
Compares two strings like String.compare. This also works when the strings reside outside the O'Caml heap, e.g. in a memory block.
val cmp_string : string -> string -> int
A version for immutable strings
exception Out_of_space
val init_header : memory -> int -> int -> int -> unit
init_header mem offset tag size: Initializes the word at mem+offset as an Ocaml value header with the given tag and the given size (in words). The GC color is always set to "white".
val init_string : memory -> int -> int -> int * int
let voffset, bytelen = init_string mem offset len: Initializes the memory at offset and following bytes as Ocaml string with length len. Returns in voffset the offset where the value starts (i.e. offset plus one word), and in bytelen the number of bytes used in mem.

offset must be a multiple of the word size in bytes.

The string can be accessed with

 let s = (as_value mem voffset : string) 

The function is useful for initializing shared memory as string so that several processes can directly access the string.

The string has the GC color White.

Raises Out_of_space if the memory block is too small.

val init_string_bytelen : int -> int
Returns bytelen if init_string was called with the passed len.
val init_array : memory -> int -> int -> int * int
let voffset, bytelen = init_array mem offset size: Initializes the memory at offset and following bytes as Ocaml array with size elements. Returns in voffset the offset where the value starts (i.e. offset plus one word), and in bytelen the number of bytes used in mem.

The array cannot be used as float array.

offset must be a multiple of the word size in bytes.

The array can be accessed with

 let a = (as_value mem voffset : _ array) 

The elements of the array have a value but it might not be valid for the element type of the array. Because of this, it is unwise to access the elements before setting them for the first time.

The array has the GC color White.

Raises Out_of_space if the memory block is too small.

val init_float_array : memory -> int -> int -> int * int
Same for arrays of floats
val init_array_bytelen : int -> int
Returns bytelen if init_array was called with the passed size.
val init_float_array_bytelen : int -> int
Same for arrays of floats
type custom_ops = nativeint 
type init_value_flag = 
| Copy_bigarray
| Copy_custom_int
| Copy_atom
| Copy_simulate
| Copy_conditionally
| Keep_atom
val init_value : ?targetaddr:nativeint ->
?target_custom_ops:(string * custom_ops) list ->
?cc:(nativeint * nativeint) list ->
memory ->
int -> 'a -> init_value_flag list -> int * int
let voffset, bytelen = init_value mem offset v flags: Initializes the memory at offset and following bytes as copy of the boxed value v. Returns in voffset the offset where the value starts (i.e. offset plus one word), and in bytelen the number of bytes used in mem.

The copied value can then be accessed with

 let v' = (as_value mem voffset : 'a) 

offset must be a multiple of the word size in bytes.

The input value v must be heap-allocated. Also, a number of restrictions and caveats apply:

  • Objects, closures, and lazy values are not supported
  • Bigarrays are only supported if the Copy_bigarray flag is given. In this case, a copy of the bigarray is also made and appended to the value copy (i.e. it is also placed into the buffer mem).
  • Abstract and custom values need to be enabled. For int32, int64, and nativeint the flag Copy_custom_int enables copying, and for bigarrays the flag Copy_bigarray. Generally, there is a function pointer in such data blocks which might be invalid when the memory buffer is loaded into a different executable. This specific problem can be fixed by passing target_custom_ops with the right pointers.
  • Atoms (i.e. zero-sized blocks such as empty arrays) are only supported if the Copy_atom or Keep_atom flags are present, otherwise the function fails. Keep_atom means here to keep atoms as-is. This is correct, but also keeps references to the atom definitions which live outside mem. Copy_atom means to create a copy of the atom as a zero-sized block outside the atom table. This way the value in mem is self-contained, but this unfortunately breaks some assumptions of the OCaml code generator. In particular, comparisons like if array=[| |] then... may yield wrong results.
  • The input value may reside outside the Ocaml heap. This may break badly written C wrappers that do not use abstract or custom tags to mark foreign data.
The function raises Out_of_space if the memory block is too small. Cyclic input values are supported, and value sharing is kept intact.

If the Copy_simulate flag is given, mem is not modified. In simulation mode, it is pretended that mem is as large as necessary to hold the value, no matter how large mem really is. The returned values voffset and bytelen reflect how much of mem would have been used.

If the targetaddr argument is passed, it is assumed that the memory block is mapped at this address and not at the address it is really mapped. This is useful for preparing memory that is going to be mapped at a different address than it is right now.

The new value has the GC color White.

If bigarrays are copied, the copy also includes the data part. The data part is directly following the bigarray block, and is represented in a special implementation-defined way.

If the Copy_conditionally flag is set, the condition cc is evaluated for every block, and only if cc returns true, the block is copied. cc is a list of addresses (start,end), and a block is not copied if its address lies in any of these address ranges. Otherwise the block is copied. As an exception of the foregoing, the first block (i.e. v) is always copied.

val get_custom_ops : 'a -> string * custom_ops
Returns custom ops for a sample value (or Invalid_argument)
val copy_value : init_value_flag list -> 'a -> 'a
copy_value flags v: Creates a deep copy of v and returns it. The copy is allocated in the normal Ocaml heap.

Restrictions:

  • Objects, closures, and lazy values are not supported (FIXME)
  • Bigarrays are only supported if the Copy_bigarray flag is given. In this case, a copy of bigarrays are also made, and placed into additional buffers obtained via stat_alloc.
  • Abstract and custom values need to be enabled. For int32, int64, and nativeint the flag Copy_custom_int enables copying, and for bigarrays the flag Copy_bigarray.
  • Atoms are automatically fixed. Copy_atoms is ignored.
Cyclic input values are supported. Copy_simulate is ignored.
type color = 
| White
| Gray
| Blue
| Black (*
GC colors
*)
val color : Obj.t -> color
Return the GC color
val set_color : Obj.t -> color -> unit
Set the GC color
val is_bigarray : Obj.t -> bool
Checks whether the objects ia actually a bigarray

I/O using memory as buffers


val mem_read : Unix.file_descr -> memory -> int -> int -> int
A version of Unix.read that uses a memory buffer. Some OS allow faster I/O when memory is page-aligned (see alloc_memory_pages). Also, a copy in the stub function can be avoided. Both effects can result in a considerable speedup.
val mem_write : Unix.file_descr -> memory -> int -> int -> int
A version of Unix.single_write that uses a memory buffer.
val mem_recv : Unix.file_descr ->
memory -> int -> int -> Unix.msg_flag list -> int
val mem_send : Unix.file_descr ->
memory -> int -> int -> Unix.msg_flag list -> int
Versions of Unix.recv, and Unix.send using memory buffers.

Buffer pools


type memory_pool 
A pool of memory blocks that are all the same size and page-aligned (if the OS supports this). The pool tries to bundle memory allocations so that not for every block a system call is required. This reduces the number of system calls, and the number of entries in the process page table. Also, unused blocks are automatically returned to the pool.
val create_pool : int -> memory_pool
Create a new pool. The argument is the size of the memory blocks (must be a multiple of the page size)
val pool_alloc_memory : memory_pool -> memory
let m = pool_alloc_memory p: Gets a memory block m from the pool p. If required, new blocks are automatically allocated and added to the pool. This function is thread-safe.

The memory block is automatically garbage-collected.

val pool_alloc_memory2 : memory_pool -> memory * (unit -> unit)
let m, free = pool_alloc_memory2 p: Gets a memory block m from the pool p like pool_alloc_memory. This function also returns the function free marking the block as free again. The block can then be immediately recycled for another use.

If free is not called, the block m is first recycled when it is not referenced any more (like in pool_alloc_memory).

val pool_reclaim : memory_pool -> unit
Reclaim as much memory as possible
val pool_block_size : memory_pool -> int
Returns the size of the memory blocks in bytes
val default_block_size : int
The default block size, normally 64 K (or better, 16 times the page size)
val default_pool : memory_pool
The default pool with the default block size. This pool is used by Ocamlnet itself as much as possible
val small_block_size : int
The block size of small_pool, normally 4K (or better, the page size)
val small_pool : memory_pool
Another standard pool where the blocks are smaller than in default_pool.
val pool_report : memory_pool -> string
Returns a report describing the memory allocation in the pool
ocamlnet-4.1.2/doc/html-main/Netmech_gs2_sasl.PROFILE.html0000644000175000017500000005473512731530352021563 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_gs2_sasl.PROFILE

Module type Netmech_gs2_sasl.PROFILE

module type PROFILE = sig .. end

val mechanism_name : string
The GS2 version of the mechanism name (w/o "-PLUS" suffix)
val announce_channel_binding : bool
Whether to announce the availability of channel binding by adding "-PLUS" to the mechanism name, and by offering channel bindings in the initial token.
val mechanism_oid : Netsys_gssapi.oid
The OID of the mechanism to use
val client_additional_params : string list
Additional parameters understood by create_client_session
val server_additional_params : string list
Additional parameters understood by create_server_session
val client_map_user_name : params:(string * string) list -> string -> string * Netsys_gssapi.oid
For clients: maps user names to a pair (name_string,name_type) that can be used in the GSSAPI for acquiring a name. If the name_type is the empty array, no target name is passed to the GSSAPI.

The params are from the create_client_session call.

val server_map_user_name : params:(string * string) list -> string * Netsys_gssapi.oid -> string
For servers: maps a pair (name_string,name_type) coming from the GSSAPI to a user name. The params are from the create_server_session call.

The function may raise Not_found in which case the authentication will fail.

val client_get_target_name : params:(string * string) list -> string * Netsys_gssapi.oid
For clients: get the GSSAPI name of the target to contact as (name_string,name_type) pair. If the name_type is the empty array, no target name is passed to the GSSAPI.

The params are from the create_client_session call.

val server_bind_target_name : params:(string * string) list -> (string * Netsys_gssapi.oid) option
For servers: optionally bind the GSSAPI name of the server. The params are from the create_server_session call.
val server_check_target_name : params:(string * string) list -> string * Netsys_gssapi.oid -> bool
For servers: check whether the GSSAPI name the client sent is the right one. This is a more flexible alternative to server_bind_target_name: instead of binding to a single name, the client may send any target name, and we check now whether this name is acceptable. params are from the create_server_session call.
val client_flags : params:(string * string) list -> (Netsys_gssapi.req_flag * bool) list
Flags for init_sec_context. The bool says whether the flag is required (otherwise the feature is only offered). `Mutual_flag is always required.
val server_flags : params:(string * string) list -> Netsys_gssapi.req_flag list
Required flags for accept_sec_context. `Mutual_flag is always required.
val client_credential : exn option
If set, the client will use a certain credential (and not acquire one). This is intended for passing in delegated credentials (well, not really elegant). This needs to be set to the Credential exception of the GSSAPI provider.
ocamlnet-4.1.2/doc/html-main/Netchannels_crypto.tls_layer-c.html0000644000175000017500000004350312731530352023352 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.tls_layer

Class Netchannels_crypto.tls_layer

class tls_layer : ?start_pos_in:int -> ?start_pos_out:int -> ?resume:string -> role:[ `Client | `Server ] -> rd:Netchannels.raw_in_channel -> wr:Netchannels.raw_out_channel -> peer_name:string option -> Netsys_crypto_types.tls_config -> tls_channel
Adds TLS security to an already established connection, here made available as separate channels for input and output.

The TLS handshake is done on the first I/O activity (call flush to enforce it).

resume: see Netsys_tls.create_file_endpoint.


ocamlnet-4.1.2/doc/html-main/Netxdr_mstring.html0000644000175000017500000011664112731530352020306 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netxdr_mstring

Module Netxdr_mstring

module Netxdr_mstring: sig .. end
Managed Strings


Managed strings are used in XDR context for constant strings that are stored either as string or as memory (bigarray of char).

A managed string ms is declared in the XDR file as in

      typedef _managed string ms<>;
    

In the encoded XDR stream there is no difference between strings and managed strings, i.e. the wire representation is identical. Only the Ocaml type differs to which the managed string is mapped. This type is Netxdr_mstring.mstring (below).

In the RPC context there is often the problem that the I/O backend would profit from a different string representation than the user of the RPC layer. To bridge this gap, managed strings have been invented. Generally, the user can determine how to represent strings (usually either as an Ocaml string, or as memory), and the I/O backend can request to transform to a different representation when this leads to an improvement (i.e. copy operations can be saved).

Only large managed strings result in a speedup of the program (at least several K).

How to practically use managed strings

There are two cases: The encoding case, and the decoding case. In the encoding case the mstring object is created by the user and passed to the RPC library. This happens when a client prepares an argument for calling a remote procedure, or when the server sends a response back to the caller. In the decoding case the client analyzes the response from an RPC call, or the server looks at the arguments of an RPC invocation. The difference here is that in the encoding case user code can directly create mstring objects by calling functions of this module, whereas in the decoding case the RPC library creates the mstring objects.

For simplicity, let us only look at this problem from the perspective of an RPC client.

Encoding. Image a client wants to call an RPC, and one of the arguments is a managed string. This means we finally need an mstring object that can be put into the argument list of the call.

This library supports two string representation specially: The normal Ocaml string type, and Netsys_mem.memory which is actually just a bigarray of char's. There are two factories fac,

and both can be used to create the mstring to pass to the RPC layer. It should be noted that this layer can process the memory representation a bit better. So, if the original data value is a string, the factory for string should be used, and if it is a char bigarray, the factory for memory should be used. Now, the mstring object is created by

  • let mstring = fac # create_from_string data pos len copy_flag, or by
  • let mstring = fac # create_from_memory data pos len copy_flag.
Of course, if fac is the factory for strings, the create_from_string method works better, and if fac is for memory, the create_from_memory method works better. pos and len can select a substring of data. If copy_flag is false, the mstring object does not copy the data if possible, but just keeps a reference to data until it is accessed; otherwise if copy_flag is true, a copy is made immediately. Of couse, delaying the copy is better, but this requires that data is not modified until the RPC call is completed.

Decoding. Now, the call is done, and the client looks at the result. There is also an mstring object in the result. As noted above, this mstring object was already created by the RPC library (and currently this library prefers string-based objects if not told otherwise). The user code can now access this mstring object with the access methods of the mstring class (see below). As these methods are quite limited, it makes normally only sense to output the mstring contents to a file descriptor.

The user can request a different factory for managed strings. The function Rpc_client.set_mstring_factories can be used for this purpose. (Similar ways exist for managed clients, and for RPC servers.)

Potential. Before introducing managed strings, a clean analysis was done how many copy operations can be avoided by using this technique. Example: The first N bytes of a file are taken as argument of an RPC call. Instead of reading these bytes into a normal Ocaml string, an optimal implementation uses now a memory buffer for this purpose. This gives:

  • Old implementation with strings and ocamlnet-2: Data is copied six times from reading it from the file until writing it to the socket.
  • New implementation with memory-based mstrings: Data is copied only twice! The first copy reads it from the file into the input buffer (a memory value), and the second copy writes the data into the socket.
Part of the optimization is that Unix.read and Unix.write do a completely avoidable copy of the data which is prevented by switching to Netsys_mem.mem_read and Netsys_mem.mem_write, respectively. The latter two functions exploit an optimization that is only possible when the data is memory-typed.

The possible optimizations for the decoding side of the problem are slightly less impressive, but still worth doing it.

Managed strings are used in XDR context for constant strings that are stored either as string or as memory (bigarray of char).

A managed string ms is declared in the XDR file as in

      typedef _managed string ms<>;
    

In the encoded XDR stream there is no difference between strings and managed strings, i.e. the wire representation is identical. Only the Ocaml type differs to which the managed string is mapped. This type is Netxdr_mstring.mstring (below).

In the RPC context there is often the problem that the I/O backend would profit from a different string representation than the user of the RPC layer. To bridge this gap, managed strings have been invented. Generally, the user can determine how to represent strings (usually either as an Ocaml string, or as memory), and the I/O backend can request to transform to a different representation when this leads to an improvement (i.e. copy operations can be saved).

Only large managed strings result in a speedup of the program (at least several K).

How to practically use managed strings

There are two cases: The encoding case, and the decoding case. In the encoding case the mstring object is created by the user and passed to the RPC library. This happens when a client prepares an argument for calling a remote procedure, or when the server sends a response back to the caller. In the decoding case the client analyzes the response from an RPC call, or the server looks at the arguments of an RPC invocation. The difference here is that in the encoding case user code can directly create mstring objects by calling functions of this module, whereas in the decoding case the RPC library creates the mstring objects.

For simplicity, let us only look at this problem from the perspective of an RPC client.

Encoding. Image a client wants to call an RPC, and one of the arguments is a managed string. This means we finally need an mstring object that can be put into the argument list of the call.

This library supports two string representation specially: The normal Ocaml string type, and Netsys_mem.memory which is actually just a bigarray of char's. There are two factories fac,

and both can be used to create the mstring to pass to the RPC layer. It should be noted that this layer can process the memory representation a bit better. So, if the original data value is a string, the factory for string should be used, and if it is a char bigarray, the factory for memory should be used. Now, the mstring object is created by

  • let mstring = fac # create_from_string data pos len copy_flag, or by
  • let mstring = fac # create_from_memory data pos len copy_flag.
Of course, if fac is the factory for strings, the create_from_string method works better, and if fac is for memory, the create_from_memory method works better. pos and len can select a substring of data. If copy_flag is false, the mstring object does not copy the data if possible, but just keeps a reference to data until it is accessed; otherwise if copy_flag is true, a copy is made immediately. Of couse, delaying the copy is better, but this requires that data is not modified until the RPC call is completed.

Decoding. Now, the call is done, and the client looks at the result. There is also an mstring object in the result. As noted above, this mstring object was already created by the RPC library (and currently this library prefers string-based objects if not told otherwise). The user code can now access this mstring object with the access methods of the mstring class (see below). As these methods are quite limited, it makes normally only sense to output the mstring contents to a file descriptor.

The user can request a different factory for managed strings. The function Rpc_client.set_mstring_factories can be used for this purpose. (Similar ways exist for managed clients, and for RPC servers.)

Potential. Before introducing managed strings, a clean analysis was done how many copy operations can be avoided by using this technique. Example: The first N bytes of a file are taken as argument of an RPC call. Instead of reading these bytes into a normal Ocaml string, an optimal implementation uses now a memory buffer for this purpose. This gives:

  • Old implementation with strings and ocamlnet-2: Data is copied six times from reading it from the file until writing it to the socket.
  • New implementation with memory-based mstrings: Data is copied only twice! The first copy reads it from the file into the input buffer (a memory value), and the second copy writes the data into the socket.
Part of the optimization is that Unix.read and Unix.write do a completely avoidable copy of the data which is prevented by switching to Netsys_mem.mem_read and Netsys_mem.mem_write, respectively. The latter two functions exploit an optimization that is only possible when the data is memory-typed.

The possible optimizations for the decoding side of the problem are slightly less impressive, but still worth doing it.

Interface


class type mstring = object .. end
The object holding the string value
class type mstring_factory = object .. end
The object creating new mstring objects
val bytes_based_mstrings : mstring_factory
Uses bytes to represent mstrings
val string_based_mstrings : mstring_factory
Deprecated."Use bytes_based_mstrings instead."
val string_to_mstring : ?pos:int -> ?len:int -> string -> mstring
Represent a string as mstring (no copy)
val bytes_to_mstring : ?pos:int -> ?len:int -> Bytes.t -> mstring
Represent bytes as mstring (no copy)
val memory_based_mstrings : mstring_factory
Uses memory to represent mstrings. The memory bigarrays are allocated with Bigarray.Array1.create
val memory_to_mstring : ?pos:int -> ?len:int -> Netsys_mem.memory -> mstring
Represent memory as mstring (no copy)
val paligned_memory_based_mstrings : mstring_factory
Uses memory to represent mstrings. The memory bigarrays are allocated with Netsys_mem.alloc_memory_pages if available, and Bigarray.Array1.create if not.
val memory_pool_based_mstrings : Netsys_mem.memory_pool -> mstring_factory
Uses memory to represent mstrings. The memory bigarrays are obtained from the pool. The length of these mstrings is limited by the blocksize of the pool.
val length_mstrings : mstring list -> int
returns the sum of the lengths of the mstrings
val concat_mstrings : mstring list -> string
concatenates the mstrings and return them as single string. The returned string may be shared with one of the mstrings passed in.
val concat_mstrings_bytes : mstring list -> Bytes.t
Same, returning bytes
val prefix_mstrings : mstring list -> int -> string
prefix_mstrings l n: returns the first n chars of the concatenated mstrings l as single string
val prefix_mstrings_bytes : mstring list -> int -> Bytes.t
Same, returning bytes
val blit_mstrings_to_memory : mstring list -> Netsys_mem.memory -> unit
blits the mstrings one after the other to the memory, so that they appear there concatenated
val shared_sub_mstring : mstring -> int -> int -> mstring
shared_sub_mstring ms pos len: returns an mstring that includes a substring of ms, starting at pos, and with len bytes. The returned mstring shares the buffer with the original mstring ms
val shared_sub_mstrings : mstring list -> int -> int -> mstring list
Same for a list of mstrings
val copy_mstring : mstring -> mstring
Create a copy
val copy_mstrings : mstring list -> mstring list
Create a copy
val in_channel_of_mstrings : mstring list -> Netchannels.in_obj_channel
Returns a channel reading from the sequence of mstrings
val mstrings_of_in_channel : Netchannels.in_obj_channel -> mstring list
Returns the data of a channel as a sequence of mstrings

See also Netsys_digests.digest_mstrings for a utiliy function to compute cryptographic digests on mstrings
type named_mstring_factories = (string, mstring_factory) Hashtbl.t 
ocamlnet-4.1.2/doc/html-main/Nethttp.Header.html0000644000175000017500000017567312731530352020126 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.Header

Module Nethttp.Header

module Header: sig .. end


This module is a parser/printer for the header fields used in HTTP/1.1. The get_* functions generally raise Not_found when the queried header is not present. If the syntax of the field is a comma-separated list of multiple values, the get_* functions generally merge all headers of the same type. The order is preserved in this case. The list [] means that the header exists, but only with empty value. For example,

 Accept: text/html
 Accept: text/plain
 

would be returned as ["text/html",[],[]; "text/plain", [],[]] by get_accept. The header

Accept:

would be returned as [].

The set_* functions generally produce only a single header with comma- separated values. Existing header are overwritten/removed.

To remove a header, simply use the delete_field method of http_header.

Error behaviour: The get_* functions raise Bad_header_field when they cannot parse a header field. The set_* functions raise Invalid_argument when an invalid value is passed to them (only very few functions do that). The argument of both exceptions is the function name.

type param_value = [ `Q of string | `V of string ] 
Parameters may occur quoted (`Q) or as already decoded values (`V)
type auth_challenge = string * (string * param_value) list 
The type of a single challenge, used during authentication. It is interpreted as (mechanism_name, params). The headers www-authenticate and proxy-authenticate use this.

See RFC 7235 for general information.

type auth_credentials = string * (string * param_value) list 
The type of a single credentials response, used during authentication. It is interpreted as (mechanism_name, params). The headers authorize and proxy-authorize use this.

See RFC 7235 for general information.

val parse_quoted_parameters : string -> (string * string) list
A generic parser for comma-separated parameters in the form key=value or key="value". Fails if the string cannot be parsed.
val get_accept : #Nethttp.http_header_ro ->
(string * (string * string) list * (string * string) list) list
Returns the Accept header as list of triples (media_range, media_range_params, accept_params). If there are accept_params, the first such parameter is always "q".

All present Accept headers are merged. The function returns [] when there is at least one Accept header, but none of the headers has a non-empty value. The function raises Not_found if there no such headers at all (which should be interpreted as ["*/*",[],[] ] ).

val best_media_type : #Nethttp.http_header_ro -> string list -> string * (string * string) list
Returns the best media type for a header and a list of supported types. If any type is acceptable, "*/*" will be returned. If no type is acceptable, "" will be returned. The supported media types should be sorted such that the best type is mentioned first. Of several media types with equal quality the one mentioned first in the list of supported types is chosen. In case several types in the Accept: header match the same type in the list of supported types, the most specific type is chosen.
val set_accept : #Nethttp.http_header ->
(string * (string * string) list * (string * string) list) list -> unit
Sets the Accept header
val get_accept_charset : #Nethttp.http_header_ro -> (string * (string * string) list) list
Returns the Accept-charset header as list of pairs (charset,params). The only mentioned parameter in RFC 2616 is "q".

All present Accept-charset headers are merged. The function raises Not_found when there is no Accept-charset header (which should be interpreted as ["*",[]] ).

val best_charset : #Nethttp.http_header_ro -> string list -> string
Returns the best charset for a header and a list of supported charsets. If any charset is acceptable, "*" will be returned. The supported charsets should be sorted such that the best charset is mentioned first.

This function already implements the special handling of ISO-8859-1 mentioned in RFC 2616.

val set_accept_charset : #Nethttp.http_header -> (string * (string * string) list) list -> unit
Sets the Accept-charset header
val get_accept_encoding : #Nethttp.http_header_ro -> (string * (string * string) list) list
Returns the Accept-encoding header as list of pairs (coding,params). The only mentioned parameter in RFC 2616 is "q". The RFC describes compatibility problems with the "q" parameter.

All present Accept-encoding headers are merged. The function raises Not_found when there is no Accept-encoding header (which should be interpreted as ["identity",[]] ). The return value [] must be interpreted as ["identity",[]] .

val best_encoding : #Nethttp.http_header_ro -> string list -> string
Returns the best encoding for a header and a list of supported encodings. If anything else fails, "identity" will be returned. The supported encodings should be sorted such that the best encoding is mentioned first.
val set_accept_encoding : #Nethttp.http_header -> (string * (string * string) list) list -> unit
Sets the Accept-encoding header
val get_accept_language : #Nethttp.http_header_ro -> (string * (string * string) list) list
Returns the Accept-language header as list of pairs (lang_range,params). The only mentioned parameter in RFC 2616 is "q".

All present Accept-language headers are merged. The function raises Not_found when there is no Accept-language header (which should be interpreted as ["*",[]] ).

val set_accept_language : #Nethttp.http_header -> (string * (string * string) list) list -> unit
Sets the Accept-language header
val get_accept_ranges : #Nethttp.http_header_ro -> string list
Returns the Accept-ranges header as list of tokens.

All present Accept-ranges headers are merged. The function raises Not_found when there is no Accept-ranges header. The RFC leaves it open how this is to be interpreted in general.

val set_accept_ranges : #Nethttp.http_header -> string list -> unit
Sets the Accept-ranges header
val get_age : #Nethttp.http_header_ro -> float
Returns the Age header as number
val set_age : #Nethttp.http_header -> float -> unit
Sets the Age header
val get_allow : #Nethttp.http_header_ro -> string list
Returns the Allow header as list of tokens.

All present Allow headers are merged. The function raises Not_found when there is no Allow header. The RFC leaves it open how this is to be interpreted in general.

val set_allow : #Nethttp.http_header -> string list -> unit
Sets the Allow header
val get_authorization : #Nethttp.http_header_ro -> auth_credentials
Returns the Authorization header as pair (auth_scheme,auth_params), or raises Not_found if not present.

The "Basic" authentication scheme is represented specially as ("basic", [ "credentials", creds ]) where creds are the Base64-encoded credentials.

At present, parameters are always decoded (`V).

val set_authorization : #Nethttp.http_header -> auth_credentials -> unit
Sets the Authorization header. The "Basic" authentication scheme is represented as explained for get_authorization.
val get_cache_control : #Nethttp.http_header_ro -> Nethttp.cache_control_token list
Returns the Cache-control header as list of tokens.

All present Cache-control headers are merged. The function raises Not_found when there is no Cache-control header.

val set_cache_control : #Nethttp.http_header -> Nethttp.cache_control_token list -> unit
Sets the Cache-control header
val get_connection : #Nethttp.http_header_ro -> string list
Returns the Connection header as list of tokens.

All present Connection headers are merged. The function raises Not_found when there is no Connection header.

The Connection header must be ignored when received from a HTTP/1.0 client.

val set_connection : #Nethttp.http_header -> string list -> unit
Sets the Connection header
val get_content_encoding : #Nethttp.http_header_ro -> string list
Returns the Content-encoding header as list of tokens.

All present Content-encoding headers are merged.
Raises Not_found when there is no Content-encoding header.

val set_content_encoding : #Nethttp.http_header -> string list -> unit
Sets the Content-encoding header
val get_content_language : #Nethttp.http_header_ro -> string list
Returns the Content-language header as list of tokens.

All present Content-language headers are merged.
Raises Not_found when there is no Content-language header.

val set_content_language : #Nethttp.http_header -> string list -> unit
Sets the Content-language header
val get_content_length : #Nethttp.http_header_ro -> int64
Returns the Content-length header as number. If the number is too big for int64, the exception Bad_header_field "Content-length" will be raised.
Raises Not_found when the header is missing.
val set_content_length : #Nethttp.http_header -> int64 -> unit
Sets the Content-length header
val get_content_location : #Nethttp.http_header_ro -> string
Returns the Content-location header as string.
Raises Not_found when the header is missing.
val set_content_location : #Nethttp.http_header -> string -> unit
Sets the Content-location header
val get_content_md5 : #Nethttp.http_header_ro -> string
Returns the Content-MD5 header as string. The Base64 encoding has not been touched.
Raises Not_found when the header is missing.
val set_content_md5 : #Nethttp.http_header -> string -> unit
Sets the Content-MD5 header
val get_content_range : #Nethttp.http_header_ro ->
[ `Bytes of (int64 * int64) option * int64 option ]
Returns the Content-range header as `Bytes(byte_range_resp_spec, instance_length). The option value None corresponds to "*" in the RFC.
Raises Not_found when the header is missing.
val set_content_range : #Nethttp.http_header ->
[ `Bytes of (int64 * int64) option * int64 option ] -> unit
Sets the Content-range header
val get_content_type : #Nethttp.http_header_ro -> string * (string * string) list
Returns the Content-type header as pair (media_type, params).
Raises Not_found when the header is missing.
val set_content_type : #Nethttp.http_header -> string * (string * string) list -> unit
Sets the Content-type header
val get_date : #Nethttp.http_header_ro -> float
Returns the Date header as number (seconds since the Epoch).
Raises Not_found when the header is missing.
val set_date : #Nethttp.http_header -> float -> unit
Sets the Date header
val get_etag : #Nethttp.http_header_ro -> Nethttp.etag
Returns the Etag header.
Raises Not_found when the header is missing.
val set_etag : #Nethttp.http_header -> Nethttp.etag -> unit
Sets the Etag header
val get_expect : #Nethttp.http_header_ro ->
(string * string option * (string * string) list) list
Returns the Expect header as list of triples (token,value,params).

All present Expect headers are merged.
Raises Not_found when there is no Expect header.

val set_expect : #Nethttp.http_header ->
(string * string option * (string * string) list) list -> unit
Sets the Expect header
val get_expires : #Nethttp.http_header_ro -> float
Returns the Expires header as number (seconds since the Epoch).
Raises Not_found when the header is missing.
val set_expires : #Nethttp.http_header -> float -> unit
Sets the Expires header
val get_from : #Nethttp.http_header_ro -> string
Returns the From header as string.
Raises Not_found when the header is missing.
val set_from : #Nethttp.http_header -> string -> unit
Sets the From header
val get_host : #Nethttp.http_header_ro -> string * int option
Returns the Host header as pair (host,port).
Raises Not_found when the header is missing.
val set_host : #Nethttp.http_header -> string * int option -> unit
Sets the Host header
val get_if_match : #Nethttp.http_header_ro -> Nethttp.etag list option
Returns the If-match header. The value None means "*".
Raises Not_found when the header is missing.
val set_if_match : #Nethttp.http_header -> Nethttp.etag list option -> unit
Sets the If-match header
val get_if_modified_since : #Nethttp.http_header_ro -> float
Returns the If-modified-since header as number (seconds since the Epoch).
Raises Not_found when the header is missing.
val set_if_modified_since : #Nethttp.http_header -> float -> unit
Sets the If-modified-since header
val get_if_none_match : #Nethttp.http_header_ro -> Nethttp.etag list option
Returns the If-none-match header. The value None means "*".
Raises Not_found when the header is missing.
val set_if_none_match : #Nethttp.http_header -> Nethttp.etag list option -> unit
Sets the If-none-match header
val get_if_range : #Nethttp.http_header_ro -> [ `Date of float | `Etag of Nethttp.etag ]
Returns the If-range header.
Raises Not_found when the header is missing.
val set_if_range : #Nethttp.http_header -> [ `Date of float | `Etag of Nethttp.etag ] -> unit
Sets the If-range header
val get_if_unmodified_since : #Nethttp.http_header_ro -> float
Returns the If-unmodified-since header as number (seconds since the Epoch).
Raises Not_found when the header is missing.
val set_if_unmodified_since : #Nethttp.http_header -> float -> unit
Sets the If-unmodified-since header
val get_last_modified : #Nethttp.http_header_ro -> float
Returns the Last-modified header as number (seconds since the Epoch).
Raises Not_found when the header is missing.
val set_last_modified : #Nethttp.http_header -> float -> unit
Sets the Last-modified header
val get_location : #Nethttp.http_header_ro -> string
Returns the Location header as string.
Raises Not_found when the header is missing.
val set_location : #Nethttp.http_header -> string -> unit
Sets the Location header
val get_max_forwards : #Nethttp.http_header_ro -> int
Returns the Max-forwards header as number.
Raises Not_found when the header is missing.
val set_max_forwards : #Nethttp.http_header -> int -> unit
Sets the Max-forwards header
val get_pragma : #Nethttp.http_header_ro -> (string * string option) list
Returns the Pragma header as list of pairs (token,value).

All present Pragma headers are merged.
Raises Not_found when there is no Pragma header.

val set_pragma : #Nethttp.http_header -> (string * string option) list -> unit
Sets the Pragma header
val get_proxy_authenticate : #Nethttp.http_header_ro -> auth_challenge list
Returns the Proxy-authenticate header as list of challenges (auth_scheme,auth_params). See also get_www_authenticate.

All present Proxy-authenticate headers are merged.
Raises Not_found when there is no Proxy-authenticate header.

At present, parameters are always decoded (`V).

val set_proxy_authenticate : #Nethttp.http_header -> auth_challenge list -> unit
Sets the Proxy-authenticate header
val get_proxy_authorization : #Nethttp.http_header_ro -> auth_credentials
Returns the Proxy-authorization header as pair (auth_scheme,auth_params).
Raises Not_found when the header is missing.

The "Basic" authentication scheme is represented specially as ("basic", [ "credentials", creds ]) where creds are the Base64-encoded credentials.

At present, parameters are always decoded (`V).

val set_proxy_authorization : #Nethttp.http_header -> auth_credentials -> unit
Sets the Proxy-authorization header The "Basic" authentication scheme is represented as explained for get_proxy_authorization.
val get_range : #Nethttp.http_header_ro -> [ `Bytes of (int64 option * int64 option) list ]
Returns the Range header as `Bytes ranges, where the list ranges has elements of the form (Some first_pos, Some last_pos), (Some first_pos, None) (prefix range), or (None, Some last_pos) (suffix range).
Raises Not_found when the header is missing.
val set_range : #Nethttp.http_header ->
[ `Bytes of (int64 option * int64 option) list ] -> unit
Sets the Range header
val get_referer : #Nethttp.http_header_ro -> string
Returns the Referer header as string.
Raises Not_found when the header is missing.
val get_referrer : #Nethttp.http_header_ro -> string
Same, for addicts of correct orthography
val set_referer : #Nethttp.http_header -> string -> unit
Sets the Referer header
val set_referrer : #Nethttp.http_header -> string -> unit
Same, for addicts of correct orthography
val get_retry_after : #Nethttp.http_header_ro -> [ `Date of float | `Seconds of int ]
Returns the Retry-after header.
Raises Not_found when the header is missing.
val set_retry_after : #Nethttp.http_header -> [ `Date of float | `Seconds of int ] -> unit
Sets the Retry-after header
val get_server : #Nethttp.http_header_ro -> string
Returns the Server header as uninterpreted string (including comments).
Raises Not_found when the header is missing.
val set_server : #Nethttp.http_header -> string -> unit
Sets the Server header
val get_te : #Nethttp.http_header_ro ->
(string * (string * string) list * (string * string) list) list
Returns the TE header as list of triples (te_token, te_params, accept_params). If there are accept_params, the first such parameter is always "q".

All present TE headers are merged. The function returns [] when there is at least one TE header, but none of the headers has a non-empty value.
Raises Not_found if there no such headers at all.

val set_te : #Nethttp.http_header ->
(string * (string * string) list * (string * string) list) list -> unit
Sets the TE header
val get_trailer : #Nethttp.http_header_ro -> string list
Returns the Trailer header as list of field names.

All present Trailer headers are merged. The function returns [] when there is at least one Trailer header, but none of the headers has a non-empty value.
Raises Not_found if there no such headers at all.

val set_trailer : #Nethttp.http_header -> string list -> unit
Sets the Trailer header
val get_transfer_encoding : #Nethttp.http_header_ro -> (string * (string * string) list) list
Returns the Transfer-encoding header as list of pairs (token, params).

All present Transfer-encoding headers are merged. The function returns [] when there is at least one Transfer-encoding header, but none of the headers has a non-empty value.
Raises Not_found if there no such headers at all.

val set_transfer_encoding : #Nethttp.http_header -> (string * (string * string) list) list -> unit
Sets the Transfer-encoding header
val get_upgrade : #Nethttp.http_header_ro -> string list
Returns the Upgrade header as list of products.

All present Upgrade headers are merged. The function returns [] when there is at least one Upgrade header, but none of the headers has a non-empty value.
Raises Not_found if there no such headers at all.

val set_upgrade : #Nethttp.http_header -> string list -> unit
Sets the Upgrade header
val get_user_agent : #Nethttp.http_header_ro -> string
Returns the User-agent header as uninterpreted string (including comments).
Raises Not_found if the header is missing.
val set_user_agent : #Nethttp.http_header -> string -> unit
Sets the User-agent header
val get_vary : #Nethttp.http_header_ro -> [ `Fields of string list | `Star ]
Returns the Vary header.
Raises Not_found if the header is missing.
val set_vary : #Nethttp.http_header -> [ `Fields of string list | `Star ] -> unit
Sets the Vary header
val get_www_authenticate : #Nethttp.http_header_ro -> auth_challenge list
Returns the WWW-Authenticate header as list of challenges (auth_scheme,auth_params).

All present WWW-Authenticate headers are merged.

The scheme "negotiate" uses a deviating header format. This data is returned as e.g. ("negotiate", ["credentials", data]).

At present, parameters are always decoded (`V).
Raises Not_found if the header is missing.

val set_www_authenticate : #Nethttp.http_header -> auth_challenge list -> unit
Sets the WWW-Authenticate header
val get_cookie : #Nethttp.http_header_ro -> (string * string) list
Get the (Netscape) cookies as (name,value) pairs (or Not_found).
val get_cookie_ct : #Nethttp.http_header_ro -> Nethttp.Cookie.t list
Get the cookies in the Nethttp.Cookie.t representation (the suffix "_ct" reminds of Cookie.t). This function also supports version 1 cookies. Returns the empty list if there are no cookies.
val set_cookie : #Nethttp.http_header -> (string * string) list -> unit
Set the Cookie header. Note: This does not set cookies in the client, use set_set_cookie instead!
val get_set_cookie : #Nethttp.http_header_ro -> Nethttp.netscape_cookie list
Get the Set-Cookie header
val set_set_cookie : #Nethttp.http_header -> Nethttp.netscape_cookie list -> unit
Set the Set-Cookie header
val set_set_cookie_ct : #Nethttp.http_header -> Nethttp.Cookie.t list -> unit
Set the Set-Cookie and Set-Cookie2 headers:

set_set_cookie_ct header cookies sets the cookies in header using version 0 or version 1 depending on whether version 1 fields are used. For better browser compatibility, if "Set-cookie2" (RFC 2965) is issued, then a "Set-cookie" precedes (declaring the same cookie with a limited number of options).

ocamlnet-4.1.2/doc/html-main/type_Netcgi_dbi.DbiPool.html0000644000175000017500000004255712731530352021722 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_dbi.DbiPool functor (Dbi_driver : DBI_DRIVER->
  sig
    type connection = Dbi_driver.connection
    val get :
      Netcgi.cgi ->
      ?host:string ->
      ?port:string ->
      ?user:string -> ?password:string -> string -> connection
  end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.trans_out_obj_channel.html0000644000175000017500000004545012731530352025140 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.trans_out_obj_channel object
  method close_out : unit -> unit
  method commit_work : unit -> unit
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method output_buffer : Buffer.t -> unit
  method output_byte : int -> unit
  method output_bytes : Bytes.t -> unit
  method output_channel : ?len:int -> in_obj_channel -> unit
  method output_char : char -> unit
  method output_string : string -> unit
  method pos_out : int
  method really_output : Bytes.t -> int -> int -> unit
  method really_output_string : string -> int -> int -> unit
  method rollback_work : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/Unixqueue.Debug.html0000644000175000017500000004302112731530352020303 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.Debug

Module Unixqueue.Debug

module Debug: sig .. end


This module controls debugging of all Unixqueue_* modules
val enable : bool Pervasives.ref
Enable Netlog debugging
val set_debug_mode : bool -> unit
Sets enable.
val set_debug_target : Equeue.Debug.debug_target -> unit
Restricts debugging to this target.
ocamlnet-4.1.2/doc/html-main/Uq_libevent.POLLSET.html0000644000175000017500000004246412731530352020676 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_libevent.POLLSET

Module type Uq_libevent.POLLSET

module type POLLSET = sig .. end

val create_pollset : unit -> Netsys_pollset.pollset
val create_event_system : unit -> Unixqueue.event_system
ocamlnet-4.1.2/doc/html-main/Netcgi_apache.Apache.Server.html0000644000175000017500000004436612731530352022442 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache.Server

Module Netcgi_apache.Apache.Server

module Server: sig .. end

type t 
Apache server_rec structure.
val hostname : t -> string
server_hostname field (as declared in Apache configuration file).
Raises Not_found if NULL.
val admin : t -> string
server_admin field.
Raises Not_found if NULL.
val is_virtual : t -> bool
is_virtual field.
Raises Not_found if NULL.
ocamlnet-4.1.2/doc/html-main/type_Netplex_kit.empty_processor_hooks.html0000644000175000017500000004071212731530352025260 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.empty_processor_hooks unit -> Netplex_types.processor_hooksocamlnet-4.1.2/doc/html-main/Netcgi_common.html0000644000175000017500000012250712731530352020056 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common

Module Netcgi_common

module Netcgi_common: sig .. end
Functions to develop new connectors.

The following module is provided as a set of helper functions to define new connectors. As a normal user of Netcgi, you should not use this module.



The goal of this module is to factor out common routines to easily set up new connectors. Here is the normal flow of operations:

  • You start by reading the request environment properties as well as the input header. Often both are undistinguished and provided through some sort of meta-variables. The function Netcgi_common.update_props_inheader helps you to sort them and to normalize the input header fields. You also need to set up a Netchannels.out_obj_channel to the output stream of your connector. Then, Netcgi_common.cgi_environment can create an environment object for you. If stderr output is not appropriate (e.g. ot is not redirected to the server log), you need to override #log_error.
  • From the environment object and arguments, Netcgi_common.cgi creates a CGI object. Often, arguments are read from the environment #cgi_query_string (in case of GET) or from an input channel (in case of POST). Netcgi_common.cgi_with_args handles this for you: it requires a Netchannels.in_obj_channel from which the arguments are read (only used in the case of POST).
  • Netcgi_common.exn_handler_default provides a default error page for uncaught exceptions. It also allows the user to pass his own exception handler that has precedence on the default one.
To see this schema in use, we recommend you have a look to the implementation of the CGI connector because it is very simple.

The goal of this module is to factor out common routines to easily set up new connectors. Here is the normal flow of operations:

  • You start by reading the request environment properties as well as the input header. Often both are undistinguished and provided through some sort of meta-variables. The function Netcgi_common.update_props_inheader helps you to sort them and to normalize the input header fields. You also need to set up a Netchannels.out_obj_channel to the output stream of your connector. Then, Netcgi_common.cgi_environment can create an environment object for you. If stderr output is not appropriate (e.g. ot is not redirected to the server log), you need to override #log_error.
  • From the environment object and arguments, Netcgi_common.cgi creates a CGI object. Often, arguments are read from the environment #cgi_query_string (in case of GET) or from an input channel (in case of POST). Netcgi_common.cgi_with_args handles this for you: it requires a Netchannels.in_obj_channel from which the arguments are read (only used in the case of POST).
  • Netcgi_common.exn_handler_default provides a default error page for uncaught exceptions. It also allows the user to pass his own exception handler that has precedence on the default one.
To see this schema in use, we recommend you have a look to the implementation of the CGI connector because it is very simple.

Arguments


type representation = [ `MIME of Netmime.mime_message | `Simple of Netmime.mime_body ] 
type store = [ `File of string | `Memory ] 
exception Oversized
exception Too_many_arguments
Hit the limit max_arguments
class type cgi_argument = object .. end
class type rw_cgi_argument = object .. end
class simple_arg : ?ro:bool -> string -> string -> rw_cgi_argument
class mime_arg : ?work_around_backslash_bug:bool -> ?name:string -> Netmime.mime_message -> rw_cgi_argument

Cookies



Cookies



The cookie implementation has been moved to Nethttp.Cookie. New code should directly call the functions defined there.
module Cookie: sig .. end

Environment


type config = {
   tmp_directory : string;
   tmp_prefix : string;
   permitted_http_methods : [ `DELETE | `GET | `HEAD | `POST | `PUT ] list;
   permitted_input_content_types : string list;
   input_content_length_limit : int;
   max_arguments : int;
   workarounds : [ `Backslash_bug
| `MSIE_Content_type_bug
| `Work_around_MSIE_Content_type_bug
| `Work_around_backslash_bug ] list
;
   default_exn_handler : bool;
}
type output_type = [ `Direct of string
| `Transactional of
config ->
Netchannels.out_obj_channel -> Netchannels.trans_out_obj_channel ]
val fix_MSIE_Content_type_bug : string -> string
fix_MSIE_Content_type_bug ct transforms the content-type string ct to fix the MSIE Content-Type bug.
val is_MSIE : string -> bool
is_MSIE user_agent tells whether the user_agent is Microsoft Internet Explorer. Useful to know when to apply Netcgi_common.fix_MSIE_Content_type_bug.
class cgi_environment : config:config -> properties:(string * string) list -> input_header:(string * string) list -> Netchannels.out_obj_channel -> object .. end
new cgi_environment ~config ~properties ~input_header out_obj generates a Netcgi.cgi_environment object, from the arguments.

CGI


type other_url_spec = [ `Env | `None | `This of string ] 
type query_string_spec = [ `Args of rw_cgi_argument list
| `Env
| `None
| `This of cgi_argument list ]
type cache_control = [ `Max_age of int | `No_cache | `Unspecified ] 
type request_method = [ `DELETE | `GET | `HEAD | `POST | `PUT of cgi_argument ] 
val string_of_request_method : request_method -> string
type arg_store_type = [ `Automatic
| `Automatic_max of float
| `Discard
| `File
| `File_max of float
| `Memory
| `Memory_max of float ]
type arg_store = cgi_environment ->
string -> Netmime.mime_header_ro -> arg_store_type
class cgi : cgi_environment -> output_type -> request_method -> cgi_argument list -> object .. end
cgi env op meth args constructs Netcgi.cgi objects.
val cgi_with_args : (cgi_environment ->
output_type ->
request_method -> cgi_argument list -> 'a) ->
cgi_environment ->
output_type ->
Netchannels.in_obj_channel -> arg_store -> 'a
cgi_with_args (new cgi) env out op ?put_arg in_chan constructs a Netcgi.cgi object. However, new cgi can be replaced by any function, so it is easy to use this to construct extensions of the cgi class (as needed by some connectors). The arguments of the cgi object are taken from the environment env (for HEAD, GET, DELETE) or from the in_chan (for POST, PUT) and processed according to arg_store.
Raises HTTP if the data does not conform the standards or it not allowed.

Exceptions


exception HTTP of Nethttp.http_status * string
Exception raised by various functions of this library to return to the user agent an appropriate error page with the specified http-status (this exception must be caught by the connector and a default answer sent).

The string is a description of the cause of the error.

This exception is for use by connectors only, users should deal with the exceptions in their code by generating a response with the usual #set_header and #out_channel of Netcgi.cgi.

val exn_handler_default : cgi_environment ->
exn_handler:(cgi_environment -> (unit -> unit) -> unit) ->
finally:(unit -> unit) -> (unit -> exn option) -> unit
exn_handler_default env ~exn_handler ~finally run_cgi will basically execute exn_handler env run_cgi. Provided that the environment config default_exn_handler is set to true (the default), any exception e not caught by the user provided exn_handler (or that is raised by it) will be passed to the default handler of OCamlNet which will rollback the current output, produce a page describing the exception e, and close the output channel of env. Note that the default handler treats HTTP exceptions specially -- for example, the response to HTTP(`Method_not_allowed,...) includes an "Allow" header (as mandated by HTTP/1.1);...

Note that, regardless of the value of default_exn_handler, the Exit exception is always caught and treated like an acceptable early termination (thus produces no error page).

Whether run_cgi terminates normally or by an exception, finally() is executed last.

Sometimes, you want that some "special" exceptions (for example exceptions internal to the connector) CANNOT to be caught by exn_handler. In this case, run_cgi() catches the exception, say e, and returns it as Some e. The exception e will "go through" exn_handler_default, it will not even be passed to the default handler. Therefore, you must take care that it is handled by the surrounding code or your connector may die without an error message. Of course, run_cgi must return None if no "special" exception is raised.

REMARK: Stricly speaking, exn_handler env run_cgi is obviously not possible because the return type of run_cgi is not unit but you can ignore that to understand what this function does.

val error_page : cgi_environment ->
Nethttp.http_status ->
(string * string list) list -> string -> string -> unit
error_page env status fields msg detail: Logs an error message and outputs an error page via env.

status is the status of the error page, e.g. `Internal_server_error. fields are put into the response header of the error page.

msg occurs in the log message and in the error page, and should be a concise description without linefeeds. detail is only printed to the error page, and may be longer than this, and may also include HTML markup.


Useful functions

The following functions are used in several connectors and are gouped here for convenience.

val update_props_inheader : string * string ->
(string * string) list * (string * string) list ->
(string * string) list * (string * string) list
update_props_inheader (name, value) (props, inheader) returns (props, inheader) to which the new parameter name-value has been added -- to props or inheader, depending on name. Unless you know what you are going, you must use this function to classify parameters as it also performs some standardisation.
val rm_htspace : (char -> bool) -> string -> int -> int -> string
rm_htspace is_space s low up returns the substring s.[low .. up - 1] stripped of possible heading and trailing spaces identified by the function is_space.
Raises Invalid_argument if low < 0 or up > String.length s
val rev_split : (char -> bool) -> string -> string list
split_rev is_delim s split s at each character is_delim and returns the list of substrings in reverse order. Several consecutive delimiters are treated as a single one. The substrings do not share s memory.
val is_prefix : string -> string -> bool
is_prefix pre s checks whether pre is a prefix of s.
type http_method = [ `DELETE | `GET | `HEAD | `POST | `PUT ] 
val string_of_http_method : http_method -> string
Returns the string value of the method
ocamlnet-4.1.2/doc/html-main/Netaddress.mailbox-c.html0000644000175000017500000004417312731530352021245 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaddress.mailbox

Class Netaddress.mailbox

class mailbox : ?name:string -> string list -> addr_spec -> object .. end
A mailbox has a name, optionally a route (not used nowadays), and a formal address specification.

Create a mailbox with

new mailbox ~name route addr_spec

Pass route = [] if not used (formerly, routes were used to specify the way the mail should take from the sender to the receiver, and contained a list of hostnames/IP addresses).


method name : string
The name of the mailbox. Raises Not_found if not set
method route : string list
The route to the mailbox
method spec : addr_spec
The formal address specification
ocamlnet-4.1.2/doc/html-main/Uq_transfer.receiver-c.html0000644000175000017500000004520712731530352021612 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.receiver

Class Uq_transfer.receiver

class receiver : src:Unix.file_descr -> dst:#async_out_channel -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines.engine
This engine copies all data from the src file descriptor to the dst output channel. The engine attaches immediately to the event system, and detaches automatically.

By default, both the file descriptor and the output channel are closed when the engine stops operation, either successfully or because of an error.

The semantics of the engine is undefined if src is not a stream-oriented descriptor.

The engine goes to `Error state when either reading from src or writing to dst raises an unexpected exception.

For every file descriptor event, the state is advanced from `Working n to `Working (n+1).

TODO: This class cannot yet cope with Win32 named pipes.


close_src : Whether to close src when the engine stops (default: true)
close_dst : Whether to close dst when the engine stops (default: true)

ocamlnet-4.1.2/doc/html-main/Netmcore_heap.html0000644000175000017500000010211512731530352020037 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_heap

Module Netmcore_heap

module Netmcore_heap: sig .. end
Shared heaps of structured values

These heaps live in Netmcore_mempool-type shared memory pools, and can contain an arbitrary number of Ocaml values. These values can be mutable, but special care has to be taken when modifying them. The first value pushed onto the heap is called the root element. All other values must be (directly or indirectly) reachable from the root element.

Heaps are created with a certain initial size. The heaps remain connected with the memory pool, and they are enlarged if necessary by allocating more blocks in the pool.

As the heaps are shared between processes, it must be taken care that no reference is made from shared heaps to normal process-local memory. These references would only be valid in the process creating them, and following such references from other processes would probably crash the program (or at least return wrong values). In order to ensure this, it is strictly forbidden to directly manipulate mutable data structures. The Netmcore_heap.modify function has to be used, as this function makes it possible to copy more values to the heap. Unfortunately, there is nothing in the type system that would prevent direct mutation. so this can only be ensured by the discipline of the programmer.

The values of the heap are also garbage-collected: If all allocated space is used and more values need to be added, it is first tried to get rid of old unreachable values. The garbarge collection is done by the process that happens to initiate the addition of the value that does no more fit onto the heap. During garbage collection, no other additions can be done, but read accesses are not prevented. The garbage collector does not move values (addresses remain unchanged).

The garabage collector only considers values as reachable that are reachable via the root element. It is not sufficient when a value is only reachable via a process-specific reference.


type 'a heap 
A heap where the type of the root element is 'a
type 'a descr 
A descriptor ("address") pointing to the heap. Descriptors can be marshalled.
val create_heap : Netmcore.res_id -> int -> 'a -> 'a heap
create_heap pool_id size root: Creates a new heap with size bytes in the pool identified by pool_id. This ID must refer to a Netmcore_mempool-managed pool.

The value root is copied to the new heap. This is done by deeply duplicating root and all values pointed to by root, and storing these duplicates in the heap.

The possible types of value root are restricted, see the add function for more.

val minimum_size : 'a -> int
Returns the size value one must pass to create_heap at minimum to put this root element onto the heap.
val root : 'a heap -> 'a
Returns the root element
val descr_of_heap : 'a heap -> 'a descr
Get the descriptor of a heap
val heap_of_descr : Netmcore.res_id -> 'a descr -> 'a heap
heap_of_descr pool d: Get the heap for a descriptor. This assumes that the heap still exists.
type mutator 
Mutators allow it to push new values onto the heap.

Caveat: pushed values are not considered as roots, and thus they need immediately be attached to the existing data structure. Otherwise, the next push might trigger a garbage collection, and the new value is deleted. If this is not possible, one can call pin instead (see below).

val modify : 'a heap -> (mutator -> 'r) -> 'r
modify h mutate: This function locks the heap so that this process has exclusive write access to it for the duration of the mutate function. The mutate function is immediately called back, and the argument of mutate is the mutator m that allows one to push values onto the heap.

By calling add m x from the body of mutate one can create a copy of x that is stored in the heap.

val add : mutator -> 'a -> 'a
Pushes a new value onto the heap. This creates a deep copy of the value.

Not all values can be pushed here. In particular, forbidden are:

  • Functions
  • Objects
  • Unsupported custom blocks, e.g. in_channel and out_channel. Supported custom blocks are only int32, int64, nativeint, and bigarrays.
  • Heaps (a heap cannot contain a heap)
  • Values containing semaphores and other synchronization primitives. Explicitly allowed are dummy primitives like Netmcore_mutex.dummy.

val add_immutable : mutator -> 'a -> 'a
Pushes a new value onto the heap. This function must only be used if the added value is immutable. An important optimization is applied here: if parts of the value are already living on the heap, these parts are not copied, but shared with the output value.

The same value restrictions apply as for add. Note that add_immutable cannot be used if the value to copy lives in a different heap of the same pool (as a whole or partially). In this case use add.

val add_uniform_array : mutator -> int -> 'a -> 'a array
add_uniform_array m n x: Pushes a new value with n elements onto the heap. Each index position of the array is initialized with the same copy of x.

You should not call this function with n=0, because this results in a copied atom, which is an illegal representation in OCaml.

val add_init_array : mutator -> int -> (int -> 'a) -> 'a array
add_init_array m n f: Pushes a new value with n elements onto the heap. The index position k is inititialized by running f k and pushing the copy of this onto the heap.

You should not call this function with n=0, because this results in a copied atom, which is an illegal representation in OCaml.

val add_some : mutator -> 'a -> 'a option
add_some mut x: Returns Some x where the O'Caml value representing Some is allocated in the heap using mut. It is assumed that x is already a resident of the heap. This means x is not copied!
val add_string : mutator -> int -> string
let s = add_string mut len: Adds an uninitialized string of length len to the heap using mut, and returns the string
val pin : mutator -> 'a -> unit
pin m x: Pins a shared value x so it cannot be deleted by the garbage collector. The value remains pinned for the lifetime of the mutator m (i.e. the runtime of the modify function).

Pinning is relatively expensive if done in masses, and should be avoided if possible.

val copy : 'a -> 'a
Creates a deep copy of the input value, and stores the duplicate in normal process memory.
val with_value : 'a heap -> (unit -> 'b) -> ('b -> 'c) -> 'c
with_value h find process: Logically, this runs process (find ()) and returns the result. While find is being executed, the heap is write-locked. This returns a value x. While process is being executed, the value x is temporarily added to the set of reachable values, so that a parallely running garbage collection will not delete it.

Note that x must reside in the heap!

Calling modify from find will cause a deadlock. Calling it from process is allowed.

val with_value_2 : 'a heap -> (unit -> 'b * 'c) -> ('b * 'c -> 'z) -> 'z
val with_value_3 : 'a heap -> (unit -> 'b * 'c * 'd) -> ('b * 'c * 'd -> 'z) -> 'z
val with_value_4 : 'a heap ->
(unit -> 'b * 'c * 'd * 'e) -> ('b * 'c * 'd * 'e -> 'z) -> 'z
val with_value_5 : 'a heap ->
(unit -> 'b * 'c * 'd * 'e * 'f) -> ('b * 'c * 'd * 'e * 'f -> 'z) -> 'z
Same as with_value, but a tuple of values can be passed down
val with_value_n : 'a heap -> (unit -> 'b list) -> ('b list -> 'c) -> 'c
Same as with_value, but a list of values can be passed down
val destroy : 'a heap -> unit
Destroys the heap and gives the memory back to the pool
val gc : 'a heap -> unit
Lock the heap and do a GC pass
val pool : 'a heap -> Netmcore.res_id
Return the pool ID
val mut_pool : mutator -> Netmcore.res_id
Return the pool ID
val sem_container : 'a heap -> Netsys_sem.container
Return the semaphore container
val mut_sem_container : mutator -> Netsys_sem.container
Return the semaphore container
val debug_info : 'a heap -> string
Returns a multi-line debug string

Example: Mutable Variable

This example creates a heap that stores a single value. (This is available as Netmcore_ref.)

    let shared_ref x =
      (* The shm version of [ref x] *)
      let r = ref x in
      let init_size = minimum_size r in
      let hp = create_heap pool_id init_size r in
      hp

    let deref sref =
      (* The shm version of [!] *)
      !(root sref)

    let assign sref x =
      (* The shm version of [:=] - however, a copy of x is done *)
      modify sref
        (fun add ->
          (root sref) := add x
        )
    

module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.delegate_engine-c.html0000644000175000017500000004222612731530352024252 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.delegate_engine

Class Uq_engines_compat.delegate_engine

class ['t] delegate_engine : 't #engine -> ['t] engine

ocamlnet-4.1.2/doc/html-main/type_Netmcore_process.html0000644000175000017500000004556412731530352021657 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_process sig
  type 'a fork_point
  type 'b join_point
  val def_process :
    ('-> 'b) ->
    'Netmcore_process.fork_point * 'Netmcore_process.join_point
  val start :
    ?inherit_resources:Netmcore.inherit_request ->
    'Netmcore_process.fork_point -> '-> Netmcore.process_id
  val join :
    'Netmcore_process.join_point -> Netmcore.process_id -> 'b option
  val join_nowait :
    'Netmcore_process.join_point -> Netmcore.process_id -> 'b option
  val release_fork_point : 'Netmcore_process.fork_point -> unit
  val release_join_point : 'Netmcore_process.join_point -> unit
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.head-c.html0000644000175000017500000004221512731530352021376 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.head

Class Nethttp_client.head

class head : string -> http_call
Argument: URI

ocamlnet-4.1.2/doc/html-main/Uq_gtk.gtk_event_system-c.html0000644000175000017500000004406212731530352022337 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_gtk.gtk_event_system

Class Uq_gtk.gtk_event_system

class gtk_event_system : ?run:runner -> unit -> Unixqueue.event_system
This class is an alternate implementation of the Unixqueue event systems for the Glib event loop. Use this class instead of unix_event_system.

Both Unixqueue and Glib provide event queues for system events, and it is possible to merge both queues such that events may happen and be processed on one queue while the other queue blocks.

To achieve this, just use this class instead of unix_event_system. It automatically creates handlers for the Glib loop when necessary. However, you must not invoke the method run, as this class does not provide its own event loop. Instead, ensure that GMain.main is called.

Of course, this is all intended to help writing applications which have a graphical user interface (GUI) built with lablgtk, and some network functionality which is designed to work in the background. Simply create your GUI with lablgtk, and after the button is pressed which starts the network I/O, you add resources to this event queue, and the I/O will be processed concurrently with any user input coming from the GUI.


ocamlnet-4.1.2/doc/html-main/index_methods.html0000644000175000017500000126306112731530352020131 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of class methods

Index of class methods


A
abort [Nethttpd_kernel.http_protocol]
Stops the transmission of data.
abort [Netftp_client.ftp_client_pi]
Shuts any active connection immediately down, and changes the state of the engine to `Aborted.
abort [Uq_engines_compat.cache_t]
abort [Uq_engines_compat.engine]
abort [Uq_engines.cache_t]
Any engine running to get the cache value is aborted, and the contents of the cache are invalidated.
abort [Uq_engines.engine]
Forces that the engine aborts operation.
abort [Uq_resolver.engine]
abort_rw [Rpc_transport.rpc_multiplex_controller]
Aborts the current reader and/or writer forever.
accept [Uq_engines_compat.server_endpoint_acceptor]
accept [Uq_server.server_endpoint_acceptor]
Instantiates an engine that accepts connections on the listening endpoint.
accept [Uq_engines.server_endpoint_acceptor]
accept_body [Nethttpd_reactor.http_reactive_request]
Call this method to unlock the body channels.
accept_sec_context [Netsys_gssapi.poly_gss_api]
On the first call, pass ~context:None.
acceptor_name [Netsys_gssapi.server_config]
acquire_cred [Netsys_gssapi.poly_gss_api]
activate_lever [Netplex_types.container]
Runs a lever function registered in the controller.
activate_lever [Netplex_types.controller]
Runs the registered lever directly
add [Netsys_pollset.pollset]
Add a descriptor or modify an existing descriptor
add [Nethttp_client.pipeline]
Adds the call to the end of the pipeline.
add_abort_action [Unixqueue_select.sb_event_system]
add_abort_action [Unixqueue.event_system]
add_admin [Netplex_types.controller]
add_admin setup: Allows to bind another RPC program to the admin socket.
add_auth_handler [Nethttp_client.pipeline]
adds a new-style authentication handler
add_close_action [Unixqueue_select.sb_event_system]
add_close_action [Unixqueue.event_system]
add_cred [Netsys_gssapi.poly_gss_api]
add_e [Nethttp_client.pipeline]
The same as engine: The call c is added to the pipeline, and when it is processed, the returned engine transitions to the state `Done c.
add_event [Unixqueue_select.sb_event_system]
add_event [Unixqueue.event_system]
add_handler [Unixqueue_select.sb_event_system]
add_handler [Unixqueue.event_system]
add_key [Nethttp_client.key_ring]
Adds a key to the ring
add_memory [Netsys_digests.digest_ctx]
Add data
add_message_receiver [Netplex_types.controller]
Adds a message receiver.
add_plugin [Netplex_types.controller]
Adds a plugin.
add_resource [Unixqueue_select.sb_event_system]
add_resource [Unixqueue.event_system]
add_service [Netplex_types.controller]
Adds a new service.
add_subbytes [Netsys_digests.digest_ctx]
Add data
add_substring [Netsys_digests.digest_ctx]
Add data
add_tstring [Netsys_digests.digest_ctx]
Add data
add_weak_resource [Unixqueue_select.sb_event_system]
add_weak_resource [Unixqueue.event_system]
add_with_callback [Nethttp_client.pipeline]
Adds the call to the end of the pipeline.
addressed_server [Nettls_support.tls_session_props]
The name of the server (for name-based virtual servers).
addresses [Netplex_types.protocol]
The addresses of the master sockets.
adjust [Netplex_types.workload_manager]
This function is called by the controller at certain events to adjust the number of available containers.
advance [Nethttpd_kernel.http_response]
Tell this object that n bytes of the front token could be really sent using Unix.write.
alive [Rpc_transport.rpc_multiplex_controller]
If the controller is alive, the socket is not yet completely down.
alive [Uq_engines_compat.multiplex_controller]
alive [Uq_multiplex.multiplex_controller]
If the controller is alive, the socket is not yet completely down.
alive [Uq_engines.multiplex_controller]
apop [Netpop.client]
Specifies the user and password using APOP authentication.
argument [Netcgi1_compat.Netcgi_types.cgi_activation]
argument [Netcgi.cgi]
#argument name returns the value of the argument named name.
argument [Netcgi_common.cgi]
argument_exists [Netcgi.cgi]
#argument_exists returns false if the named parameter is missing and true otherwise.
argument_exists [Netcgi_common.cgi]
argument_value [Netcgi1_compat.Netcgi_types.cgi_activation]
argument_value [Netcgi.cgi]
#argument_value returns the value of the argument as a string.
argument_value [Netcgi_common.cgi]
arguments [Netcgi1_compat.Netcgi_types.cgi_activation]
Mutability of arguments has been dropped.
arguments [Netcgi.cgi]
The complete list of arguments.
arguments [Netcgi_common.cgi]
as_bytes [Netsys_types.mstring]
as_bytes [Netxdr_mstring.mstring]
Returns the contents as bytes.
as_memory [Netsys_types.mstring]
as_memory [Netxdr_mstring.mstring]
Returns the contents as memory.
as_string [Netsys_types.mstring]
as_string [Netxdr_mstring.mstring]
Returns the contents as string (this is always a copy)
assoc_multi_req_header [Nethttp_client.http_call]
Return all header values for a given field name (header entries which allow several values separated by commas can also be transmitted by several header lines with the same name).
assoc_multi_resp_header [Nethttp_client.http_call]
Return all response header values for a given field name (header entries which allow several values separated by commas can also be transmitted by several header lines with the same name).
assoc_req_header [Nethttp_client.http_call]
Query a specific header entry, or raise Not_found
assoc_resp_header [Nethttp_client.http_call]
Query a specific header entry of the response.
at_exit [Netcgi.cgi]
#at_exit f registers the function f to be executed when #finalize is called (which is done automatically when the request finishes).
at_exit [Netcgi_common.cgi]
attach [Nettelnet_client.telnet_session]
Attach to the event system.
auth [Netpop.client]
auth mech user authz creds params: Performs a SASL authentication using the AUTH command (RFC 5034).
auth [Netsmtp.client]
auth mech user authz creds params: Performs a SASL authentication using the AUTH command.
auth_domain [Nethttp_client.auth_session]
The list of domain URIs defines the protection space.
auth_method [Rpc_client.auth_protocol]
auth_protocol [Rpc_client.auth_session]
Return the corresponding protocol
auth_realm [Nethttp_client.auth_session]
The realm
auth_scheme [Nethttp_client.auth_session]
The authentication scheme, e.g.
auth_session_id [Nethttp_client.auth_session]
An optional ID which is only needed for multi-step authentication protocols (i.e.
auth_status [Nethttp_client.http_call]
Authenticaton status.
auth_user [Nethttp_client.auth_session]
The user identifier (UTF-8)
authenticate [Rpc_server.auth_method]
authenticate srv conn_id details f: This method is called when a remote call has arrived.
authenticate [Nethttp_client.auth_session]
Returns a list of additional headers that will authenticate the passed call for this session.
authenticated [Netsmtp.client]
Whether the auth command ran successfully
avoid_proxy_for [Nethttp_client.pipeline]
sets a list of host names or domain suffixes for which no proxy should be used.

B
bidirectional_phase [Nethttpd_kernel.http_response]
The bidrectional phase starts after "100 Continue" has been sent to the client, and stops when the response body begins.
blit_to_bytes [Netsys_types.mstring]
blit_to_bytes [Netxdr_mstring.mstring]
blit_to_bytes mpos s spos len: Copies the substring of the managed string from mpos to mpos+len-1 to the substring of s from spos to spos+len-1
blit_to_memory [Netsys_types.mstring]
blit_to_memory [Netxdr_mstring.mstring]
blit_to_string mpos mem mempos len: Copies the substring of the managed string from mpos to mpos+len-1 to the substring of mem from mempos to mempos+len-1
blit_to_string [Netsys_types.mstring]
blit_to_string [Netxdr_mstring.mstring]
block_constraint [Netsys_ciphers.cipher]
The buffers used with encrypt/decrypt must have a length that is a multiple of this number.
block_constraint [Netsys_ciphers.cipher_ctx]
The buffers used with encrypt/decrypt must have a length that is a multiple of this number.
block_length [Netsys_digests.digest]
The block length of the hash function (for HMAC) in bytes
block_size [Netstream.in_obj_stream]
The block size of the stream
body_size [Nethttpd_kernel.http_response]
Accumulated size of the response body
bool_param [Netplex_types.config_file]
broadcast [Netsys_oothr.condition]
In a multi-threaded program: Signal all waiting processes that the condition holds.

C
call_plugin [Netplex_types.container]
call_plugin p procname procarg: This method can be called from the container context to invoke the plugin p procedure procname.
callback [Netcgi_modtpl.template]
Set a callback in the template.
can_input [Uq_engines_compat.async_in_channel]
can_input [Uq_transfer.async_in_channel]
Whether input is possible, i.e.
can_input [Uq_engines.async_in_channel]
can_output [Uq_engines_compat.async_out_channel]
can_output [Uq_transfer.async_out_channel]
Whether output is possible, i.e.
can_output [Uq_engines.async_out_channel]
cancel [Netfs.stream_fs]
Cancels any ongoing write.
cancel [Nethttp_fs.http_stream_fs]
cancel_rd_polling [Rpc_transport.rpc_multiplex_controller]
Cancels polling for the next input message.
cancel_reading [Uq_engines_compat.multiplex_controller]
cancel_reading [Uq_multiplex.multiplex_controller]
Cancels the read job.
cancel_reading [Uq_engines.multiplex_controller]
cancel_shutting_down [Rpc_transport.rpc_multiplex_controller]
Cancels the shutdown procedure.
cancel_shutting_down [Uq_engines_compat.multiplex_controller]
cancel_shutting_down [Uq_multiplex.multiplex_controller]
Cancels the shutdown procedure.
cancel_shutting_down [Uq_engines.multiplex_controller]
cancel_wait [Netsys_pollset.pollset]
There is a cancel bit in the pollset, and this method sets it to the argument value.
cancel_writing [Uq_engines_compat.multiplex_controller]
cancel_writing [Uq_multiplex.multiplex_controller]
Cancels the write job.
cancel_writing [Uq_engines.multiplex_controller]
canonicalize_name [Netsys_gssapi.poly_gss_api]
capa [Netpop.client]
Requests a list of capabilities (RFC 2449).
capabilities [Netpop.client]
The result of the last capa command
capacity [Netplex_types.workload_manager]
Computes the capacity, i.e.
cgi_auth_type [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_auth_type [Netcgi.cgi_environment]
cgi_auth_type [Netcgi_common.cgi_environment]
cgi_gateway_interface [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_gateway_interface [Netcgi.cgi_environment]
cgi_gateway_interface [Netcgi_common.cgi_environment]
cgi_https [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_https [Netcgi.cgi_environment]
A well-known extension is the HTTPS property.
cgi_https [Netcgi_common.cgi_environment]
cgi_path_info [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_path_info [Netcgi.cgi_environment]
cgi_path_info [Netcgi_common.cgi_environment]
cgi_path_translated [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_path_translated [Netcgi.cgi_environment]
cgi_path_translated [Netcgi_common.cgi_environment]
cgi_properties [Nethttpd_types.request_info]
The distilled CGI properties
cgi_properties [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_properties [Netcgi.cgi_environment]
Return all properties as an associative list.
cgi_properties [Netcgi_common.cgi_environment]
Return the parameter properties.
cgi_property [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_property [Netcgi.cgi_environment]
Returns a (possibly non-standard) CGI environment property.
cgi_property [Netcgi_common.cgi_environment]
cgi_query_string [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_query_string [Netcgi.cgi_environment]
This is the row query string.
cgi_query_string [Netcgi_common.cgi_environment]
cgi_remote_addr [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_remote_addr [Netcgi.cgi_environment]
cgi_remote_addr [Netcgi_common.cgi_environment]
cgi_remote_host [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_remote_host [Netcgi.cgi_environment]
cgi_remote_host [Netcgi_common.cgi_environment]
cgi_remote_ident [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_remote_ident [Netcgi.cgi_environment]
cgi_remote_ident [Netcgi_common.cgi_environment]
cgi_remote_user [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_remote_user [Netcgi.cgi_environment]
cgi_remote_user [Netcgi_common.cgi_environment]
cgi_request_method [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_request_method [Netcgi.cgi_environment]
We recommend you to use the method Netcgi.cgi.request_method which is more type-safe and informative.
cgi_request_method [Netcgi_common.cgi_environment]
cgi_request_uri [Nethttpd_types.v_extended_environment]
The full request URI.
cgi_request_uri [Netcgi1_compat.Netcgi_env.cgi_environment]
I rest to be convinced we need this.
cgi_script_name [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_script_name [Netcgi.cgi_environment]
cgi_script_name [Netcgi_common.cgi_environment]
cgi_server_name [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_server_name [Netcgi.cgi_environment]
cgi_server_name [Netcgi_common.cgi_environment]
cgi_server_port [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_server_port [Netcgi.cgi_environment]
cgi_server_port [Netcgi_common.cgi_environment]
cgi_server_protocol [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_server_protocol [Netcgi.cgi_environment]
cgi_server_protocol [Netcgi_common.cgi_environment]
cgi_server_software [Netcgi1_compat.Netcgi_env.cgi_environment]
cgi_server_software [Netcgi.cgi_environment]
cgi_server_software [Netcgi_common.cgi_environment]
change_user_to [Netplex_types.socket_service_config]
Instructs the container to change the user of the process after starting the service.
charset [Netcgi1_compat.Netcgi_types.cgi_argument]
charset [Netcgi.cgi_argument]
The charset parameter of the content type of the header, or "" when there is no such parameter, or no header.
charset [Netcgi_common.cgi_argument]
cipher_algo [Nettls_support.tls_session_props]
The name of the algorithm for encrypting the data stream, e.g.
cipher_suite_type [Nettls_support.tls_session_props]
A string describing the authentication and privacy mechanism that is in effect: "X509": X509 certificates are used, "OPENPGP": OpenPGP certificates are used, "ANON": anonymous credentials, "SRP": SRP credentials, "PSK": PSK credentials
cleanup [Uq_lwt.lwt_backend]
clear [Nethttp_client.tls_cache]
Clear the cache
clear [Nethttp_client.key_ring]
Deletes all keys from this key ring
clear [Unixqueue_select.sb_event_system]
clear [Unixqueue.event_system]
client_addr [Rpc_server.auth_details]
close [Netfs.local_file]
Indicate that we are done with the file
close [Nethttpd_reactor.http_reactor]
Closes the file descriptor with a reliable method.
close [Netpop.client]
Closes the file descriptors
close [Netsmtp.client]
Closes the file descriptors
close [Netftp_fs.ftp_stream_fs]
Forces that the FTP client is closed.
close_all [Nethttp_client_conncache.connection_cache]
Closes all descriptors known to the cache
close_connection [Nethttpd_kernel.http_response]
Returns whether the connection should be closed after this response.
close_connection [Nethttp_client_conncache.connection_cache]
Deletes the connection from the cache, and closes it
close_in [Netchannels.augment_raw_in_channel]
As in raw_in_channel
close_in [Netchannels.rec_in_channel]
Closes the channel for input.
close_in [Uq_engines_compat.async_in_channel]
close_in [Uq_transfer.async_in_channel]
Closes the channel
close_in [Uq_engines.async_in_channel]
close_out [Netchannels.augment_raw_out_channel]
As in raw_out_channel
close_out [Netchannels.rec_out_channel]
Flushes the buffer, if any, and closes the channel for output.
close_out [Uq_engines_compat.async_out_channel]
close_out [Uq_transfer.async_out_channel]
Closes the channel
close_out [Uq_engines.async_out_channel]
cnt_crashed_connections [Nethttp_client.pipeline]
Counts connections with network or protocol errors
cnt_failed_connections [Nethttp_client.pipeline]
Counts totally failed connections (no more reconnects allowed)
cnt_new_connections [Nethttp_client.pipeline]
Counts new connections (or better: attempts to establish connections)
cnt_server_eof_connections [Nethttp_client.pipeline]
Counts connections the server terminated with EOF
cnt_successful_connections [Nethttp_client.pipeline]
Counts connections closed because pipelines become empty
cnt_timed_out_connections [Nethttp_client.pipeline]
Counts connections given up because of timeouts
code [Netldap.ldap_result]
The code, `Success on success
command [Netsmtp.client]
Sends this command, and returns the status code and the status texts.
commit_work [Netchannels.trans_out_obj_channel]
Flushes the transaction buffer, and writes its contents to the underlying resource.
compare_name [Netsys_gssapi.poly_gss_api]
compression_algo [Nettls_support.tls_session_props]
The name of the compression algorithm (or "NULL"), on the TLS layer.
conditional [Netcgi_modtpl.template]
Set a conditional in the template.
config [Nethttpd_kernel.http_protocol]
Just returns the configuration
config [Netcgi1_compat.Netcgi_env.cgi_environment]
config [Netcgi.cgi_environment]
The configuration of the request.
config [Netcgi_common.cgi_environment]
config_announce_server [Nethttpd_kernel.http_protocol_config]
Whether to set the Server header: `Ignore: The kernel does not touch the Server header., `Ocamlnet: Announce this web server as "Ocamlnet/<version>", `Ocamlnet_and s: Announce this web server as s and append the Ocamlnet string., `As s: Announce this web server as s
config_cgi [Nethttpd_reactor.http_processor_config]
The CGI configuration to use in the Netcgi environment
config_error_response [Nethttpd_reactor.http_processor_config]
Get HTML error text for the HTTP status code.
config_error_response [Nethttpd_types.min_config]
config_input_flow_control [Nethttpd_engine.http_engine_config]
If true, the engine stops reading input tokens from the HTTP kernel when there is data in the input channel of the engine not yet read.
config_internal [Netplex_types.processor_hooks]
For internal services, this list configures which message kind is used for which protocol.
config_limit_pipeline_length [Nethttpd_kernel.http_protocol_config]
Limits the length of the pipeline (= unreplied requests).
config_limit_pipeline_size [Nethttpd_kernel.http_protocol_config]
Limits the size of the pipeline in bytes.
config_log_access [Nethttpd_reactor.http_processor_config]
Logs the access after the request/response cycle is complete.
config_log_error [Nethttpd_reactor.http_processor_config]
config_log_error info msg: Log the message msg.
config_log_error [Nethttpd_types.min_config]
config_max_header_length [Nethttpd_kernel.http_protocol_config]
Maximum size of the header, including the request line.
config_max_reqline_length [Nethttpd_kernel.http_protocol_config]
Maximum size of the request line.
config_max_trailer_length [Nethttpd_kernel.http_protocol_config]
Maximum size of the trailer
config_output_flow_control [Nethttpd_engine.http_engine_config]
If true, the engine signals the user when there is already enough data to output, and no more output should be generated.
config_reactor_synch [Nethttpd_reactor.http_reactor_config]
Specifies when to synchronize output, i.e.
config_suppress_broken_pipe [Nethttpd_kernel.http_protocol_config]
Whether to suppress `Broken_pipe errors.
config_synch_input [Nethttpd_engine.http_engine_processing_config]
The "input synchronizer": It is called as obj # config_synch_input f ch to create a synchronous input channel from an asynchronous one, ch.
config_synch_output [Nethttpd_engine.http_engine_processing_config]
The "output synchronizer": It is called as obj # config_synch_output f ch to create a synchronous output channel from an asynchronous one, ch.
config_timeout [Nethttpd_reactor.http_processor_config]
General timeout for network I/O (per I/O primitive).
config_timeout_next_request [Nethttpd_reactor.http_processor_config]
Timeout in seconds to wait for the next request after the previous one has been completely received.
config_tls [Nethttpd_kernel.http_protocol_config]
If set, the server enables TLS with the arugment config
config_tls_cert_props [Nethttpd_reactor.http_processor_config]
Whether to include certificate properties in the cgi environment.
config_tls_remote_user [Nethttpd_reactor.http_processor_config]
configure_slave_socket [Netplex_types.protocol]
A user-supplied function to configure slave sockets (after accept).
configure_timeout [Netftp_client.ftp_client]
Configures a timeout for both the control and the data connection.
configure_transport [Nethttp_client.pipeline]
configure_transport id transport: Configures that messages with transport layer ID id are exchanged on transport.
conn_limit [Netplex_types.socket_service_config]
An optional limit of the number of connections this container can accept.
connect [Uq_engines_compat.client_endpoint_connector]
connect [Uq_client.client_endpoint_connector]
Instantiates an engine that connects to the endpoint given by the connect_address argument.
connect [Uq_engines.client_endpoint_connector]
connection_cache [Nethttp_client.pipeline]
The current connection cache.
connections [Nethttp_client.pipeline]
Reports which connections exist: (host, port, queue_length)
container_count [Netplex_types.controller]
The number of containers for a certain socket service name
container_event_system [Netplex_types.processor_hooks]
This method is called to get the event systems for containers.
container_id [Netplex_types.container]
Return the container ID
container_run [Netplex_types.processor_hooks]
container_run esys: By default, it just runs esys#run().
container_state [Netplex_types.socket_controller]
containers [Netplex_types.controller]
Lists the containers
containers_for [Netplex_types.controller]
Lists the containers for a certain socket service name
content_type [Netcgi1_compat.Netcgi_types.cgi_argument]
content_type [Netcgi.cgi_argument]
Returns the content type of the header and its parameters as a couple (hdr, params).
content_type [Netcgi_common.cgi_argument]
content_type_params [Netcgi1_compat.Netcgi_types.cgi_argument]
Method content_type : unit -> string * (string * Netmime_string.s_param) list defined instead of content_type and content_type_params to be coherent with Netmime.mime_header_ro -- yet as easy to use.
context_time [Netsys_gssapi.poly_gss_api]
continue [Nethttp_client.transport_channel_type]
continue is called when an already established circuit needs to be continued.
controller_config [Netplex_types.netplex_config]
controller_config [Netplex_types.socket_service_config]
Make this config accessible here too, for convenience
controller_config [Netplex_types.controller]
cookie [Netcgi.cgi_environment]
#cookie cn returns the cookie with name cn.
cookie [Netcgi_common.cgi_environment]
cookies [Netcgi1_compat.Netcgi_env.cgi_environment]
Cookies are returned in decoded form.
cookies [Netcgi.cgi_environment]
Returns the list of valid cookies found in the request header.
cookies [Netcgi_common.cgi_environment]
copy [Netfs.stream_fs]
Copies a file to a new name.
copy [Nethttp_fs.http_stream_fs]
create [Netsys_digests.digest]
Start digestion
create [Netsys_ciphers.cipher]
create c p key: create a new cipher context for key.
create_condition [Netsys_oothr.mtprovider]
In a multi-threaded program: Creates a condition variable and returns the object.
create_container [Netplex_types.socket_service]
Internal method.
create_datagram_socket [Uq_engines_compat.datagram_socket_provider]
create_datagram_socket [Uq_datagram.datagram_socket_provider]
Creates an engine that creates a wrapped_datagram_socket object and that sets up any further resources the objects needs.
create_datagram_socket [Uq_engines.datagram_socket_provider]
create_from_bytes [Netxdr_mstring.mstring_factory]
create_from_string s pos len must_copy: Creates the mstring from the sub string of s starting at pos with length len
create_from_memory [Netxdr_mstring.mstring_factory]
create_from_memory m pos len must_copy: Creates the mstring from the sub string of m starting at pos with length len
create_from_string [Netxdr_mstring.mstring_factory]
create_from_string s pos len must_copy: Creates the mstring from the sub string of s starting at pos with length len
create_logger [Netplex_types.logger_factory]
create_logger [Netplex_types.controller_config]
Create a logger to be used for the whole Netplex system.
create_mem_mutex [Netplex_types.parallelizer]
let lock, unlock = par#create_mem_locker(): Creates a mutex that is sufficient to protect process memory from uncoordinated access.
create_mutex [Netsys_oothr.mtprovider]
In a multi-threaded program: Creates a mutex and returns the object.
create_processor [Netplex_types.processor_factory]
create_proxy_session [Nethttp_client.auth_handler]
Same for proxy authentication (status 407)
create_session [Nethttp_client.auth_handler]
Create a new authentication session.
create_thread [Netsys_oothr.mtprovider]
In a multi-threaded program: Starts a new thread, and calls the passed function with the passed argument in the new thread (like Thread.create).
create_workload_manager [Netplex_types.workload_manager_factory]
credential [Rpc_server.auth_details]
credentials [Nethttp_client.key]
The key in the common "credentials" format that is used by generic mechanisms.
ctrl_added [Netplex_types.plugin]
This method is invoked when the plugin has been added to this controller.
ctrl_container_finished [Netplex_types.plugin]
This method is called when a container finishes (after post_finish_hook).
ctrl_receive_call [Netplex_types.plugin]
ctrl_receive_call ctrl cid procname procarg emit: This method is called in the controller context ctrl when a procedure named procname is called.
ctrl_unplugged [Netplex_types.plugin]
The plugin has been unplugged from this controller
current_sys_id [Netplex_types.parallelizer]
Returns the system-dependent thread identifier of the caller
cycle [Nethttpd_kernel.lingering_close]
Reads data from the file descriptor until EOF or until a fixed timeout is over.
cycle [Nethttpd_kernel.http_protocol]
Looks at the file descriptor.

D
data [Netsmtp.client]
This method really send the mail.
data [Netcgi_fcgi.cgi]
This the the channel on which the filter data is available.
data_length [Netcgi_fcgi.cgi]
How many bytes of the data are available.
data_mtime [Netcgi_fcgi.cgi]
The data last modification time, expressed as an integer number of seconds since the epoch (January 1, 1970 UTC).
datagram_type [Uq_engines_compat.wrapped_datagram_socket]
datagram_type [Uq_datagram.wrapped_datagram_socket]
datagram_type [Uq_engines.wrapped_datagram_socket]
decrypt [Netsys_ciphers.cipher_ctx]
let n_in, n_out = decrypt ~last inbuf outbuf: Decrypts the text in inbuf and writes the result to outbuf.
decrypt_bytes [Netsys_ciphers.cipher_ctx]
Decrypts this string as a whole
decrypt_string [Netsys_ciphers.cipher_ctx]
Decrypts this string as a whole
def_empty_path_replacement [Nethttp_client.generic_call]
def_has_req_body [Nethttp_client.generic_call]
def_has_resp_body [Nethttp_client.generic_call]
def_is_idempotent [Nethttp_client.generic_call]
def_request_method [Nethttp_client.generic_call]
The following methods define the values for the corresponding methods without the def_ prefix:
def_term [Nethttpd_types.http_service]
The definition term
default_port [Nethttp_client.transport_channel_type]
If set, the Host header omits this port number
default_user_name [Netmech_scram_gssapi.client_key_ring]
This method may return a default user name
dele [Netpop.client]
Marks the message number of the current mailbox for deletion.
deleg_credential [Netsys_gssapi.server_props]
If a credential was delegated it is returned here as (e,t).
delete_argument [Netcgi1_compat.Netcgi_types.cgi_activation]
delete_field [Netmime.mime_header]
These methods modify the fields of the header.
delete_sec_context [Netsys_gssapi.poly_gss_api]
Output tokens are not supported (this is a deprecated feature of GSSAPI)
descr [Netftp_data_endpoint.ftp_data_engine]
The socket to use for data transfers.
descr_state [Netftp_data_endpoint.ftp_data_engine]
The socket state
descriptor [Uq_engines_compat.wrapped_datagram_socket]
descriptor [Uq_datagram.wrapped_datagram_socket]
The underlying file descriptor.
descriptor [Uq_engines.wrapped_datagram_socket]
dest_status [Nethttp_client.http_call]
Returns the status line of the last response (but status lines with code 100 are ignored).
destroy [Rpc_client.auth_protocol]
Destroys the session (e.g.
diag_msg [Netldap.ldap_result]
diagnostic message
disable [Netplex_types.socket_controller]
Disable a socket service temporarily
disable_local_option [Nettelnet_client.telnet_session]
disable_remote_option [Nettelnet_client.telnet_session]
display_minor_status [Netsys_gssapi.poly_gss_api]
Note that display_minor_status decodes all status value parts in one step and returns the result as string list.
display_name [Netsys_gssapi.poly_gss_api]
dispose [Netsys_pollset.pollset]
Release any OS resources associated with the pollset.
do_input [Nethttpd_kernel.http_protocol]
Returns true iff the protocol engine is interested in new data from the socket.
do_output [Nethttpd_kernel.http_protocol]
Returns true iff the protocol engine has data to output to the socket
domain [Nethttp_client.key]
The domain URIs defining the protection space.
duplicate_name [Netsys_gssapi.poly_gss_api]

E
effective_request_uri [Nethttp_client.http_call]
The URI actually sent to the server in the request line of the protocol.
emit [Rpc_client.auth_protocol]
Emits a token for this xid, prog_nr and vers_nr.
empty_path_replacement [Nethttp_client.http_call]
The string to substitute in the request line for the empty path.
enable [Netplex_types.socket_controller]
Enables a disabled socket service again
enable_local_option [Nettelnet_client.telnet_session]
enable_remote_option [Nettelnet_client.telnet_session]
encrypt [Netsys_ciphers.cipher_ctx]
let n_in, n_out = encrypt ~last inbuf outbuf: Encrypts the text in inbuf and writes the result to outbuf.
encrypt_bytes [Netsys_ciphers.cipher_ctx]
Encrypts this string as a whole
encrypt_string [Netsys_ciphers.cipher_ctx]
Encrypts this string as a whole
endpoint_credentials [Nettls_support.tls_session_props]
Returns the decoded credentials of this endpoint
endpoint_credentials_raw [Nettls_support.tls_session_props]
Returns the credentials in the raw form.
endpoint_credentials_type [Nettls_support.tls_session_props]
The type of credentials
engine [Nethttpd_engine.http_engine_processing_context]
The engine doing HTTP
enhanced_input [Netchannels.enhanced_raw_in_channel]
Works similar to input, but distinguishes between normal data and end-of-line separators.
enhanced_input_line [Netchannels.enhanced_raw_in_channel]
An improved implementation of input_line that uses the buffer
environment [Nethttpd_engine.http_request_notification]
The request environment.
environment [Nethttpd_engine.http_request_header_notification]
The request environment.
environment [Nethttpd_reactor.http_reactive_request]
The Netcgi environment representing the request header, the response header, and the channels to receive the request body and to send the response body.
environment [Netcgi1_compat.Netcgi_types.cgi_activation]
environment [Netcgi.cgi]
The environment object.
environment [Netcgi_common.cgi]
eq_name [Netx509.directory_name]
The name normalized for equality comparisons.
eq_string [Netx509.directory_name]
The eq_name converted to string
error_message [Nethttpd_types.error_response_params]
The error message explaining the detail that went wrong
event_system [Rpc_transport.rpc_multiplex_controller]
Returns the event system
event_system [Netplex_types.container]
The event system the container uses
event_system [Netplex_types.controller]
The event system used by the controller.
event_system [Netftp_client.ftp_client_pi]
The used event system
event_system [Netftp_client.ftp_client]
event_system [Nethttp_client.pipeline]
Returns the event system
event_system [Uq_engines_compat.multiplex_controller]
event_system [Uq_engines_compat.engine_mixin]
event_system [Uq_engines_compat.engine]
event_system [Uq_multiplex.multiplex_controller]
Returns the event system
event_system [Uq_engines.multiplex_controller]
event_system [Uq_engines.engine_mixin]
event_system [Uq_engines.engine]
Returns the event system the engine is attached to
event_system [Uq_resolver.engine]
exec [Netftp_client.ftp_client]
Runs the method synchronously.
exec_e [Netftp_client.ftp_client_pi]
Run another command as engine.
exec_e [Netftp_client.ftp_client]
Runs the method asynchronously as engine.
exists_resource [Unixqueue_select.sb_event_system]
exists_resource [Unixqueue.event_system]
expect_input [Nettelnet_client.telnet_session]
Set whether the timeout value is to be applied to the input side of the connection.
expn [Netsmtp.client]
Expand command : expn list will try to expand the Mailing list list.
export_name [Netsys_gssapi.poly_gss_api]
export_sec_context [Netsys_gssapi.poly_gss_api]
extensions [Netx509.x509_certificate]
Extensions (version 3 certificates) as triples (oid, data, critical).

F
fd [Nethttpd_kernel.lingering_close]
The file descriptor
fd [Nethttpd_kernel.http_protocol]
Just returns the socket
fetch_subnegotiation [Nettelnet_client.telnet_session]
This method should be called as follows: If you find a Telnet_sb at the beginning of the input queue, remove this command Queue.take, and invoke fetch_subnegotiation.
field [Netmime.mime_header_ro]
fields [Netmime.mime_header_ro]
file_descr [Rpc_transport.rpc_multiplex_controller]
If the transport mechanism is on top of a file descriptor, this is returned here.
file_exists [Netglob.glob_fsys]
Whether the file name is valid and refers to an existing file, or to a symlink pointing to an existing file.
file_is_dir [Netglob.glob_fsys]
Whether the file name is valid and a directory, or a symlink to a directory.
filename [Netfs.local_file]
The filename
filename [Netplex_types.config_file]
filename [Netcgi1_compat.Netcgi_types.cgi_argument]
filename [Netcgi.cgi_argument]
The filename parameter found in the header of file uploads.
filename [Netcgi_common.cgi_argument]
finalize [Netmime.mime_body_ro]
After the body has been finalized, it cannot be accessed any longer.
finalize [Netcgi1_compat.Netcgi_types.cgi_activation]
finalize [Netcgi1_compat.Netcgi_types.cgi_argument]
finalize [Netcgi.cgi]
This method calls #finalize for every CGI argument (including the possible one of PUT) to ensure that all files are deleted.
finalize [Netcgi.cgi_argument]
Arguments stored in temp files must be deleted when the argument is no longer used.
finalize [Netcgi_common.cgi_argument]
finalize [Netcgi_common.cgi]
find [Netsys_pollset.pollset]
Checks whether a descriptor is member of the set, and returns its event mask.
find_inactive_connection [Nethttp_client_conncache.connection_cache]
Returns an inactive connection to the passed peer, or raise Not_found.
find_my_connections [Nethttp_client_conncache.connection_cache]
Returns all active connections owned by the object
finish [Netsys_digests.digest_ctx]
Finish digestion, and return the digest
finish [Nethttpd_reactor.http_reactive_request]
This method should be called after the request has been fully processed.
finish_request [Nethttpd_reactor.http_reactive_request]
Reads the rest of the body (if any), and discards that data
fixup_request [Nethttp_client.generic_call]
This method is called just before sending the request.
flags [Netsys_gssapi.server_props]
Actual flags
flags [Netsys_gssapi.server_config]
flags [Netsys_gssapi.client_props]
Actual flags
flags [Netsys_gssapi.client_config]
flavors [Rpc_server.auth_method]
Which credential flavors are handled by this method
float_param [Netplex_types.config_file]
flush [Netchannels.augment_raw_out_channel]
As in raw_out_channel
flush [Netchannels.rec_out_channel]
If there is a write buffer, it will be flushed.
flush [Uq_engines_compat.async_out_channel]
flush [Uq_transfer.async_out_channel]
Flushes the channel.
flush [Uq_engines.async_out_channel]
frame_len [Rpc_server.auth_details]
free_resources [Netplex_types.controller]
Should be called when the controller is finished, in order to free resources again.
front_token [Nethttpd_kernel.http_response]
The first token of the queue, represented as data_chunk.
ftp_client [Netftp_fs.ftp_stream_fs]
The FTP client backing this filesystem
ftp_state [Netftp_client.ftp_client_pi]
Returns the current ftp_state

G
gc_when_idle [Netplex_types.socket_service_config]
If set, idle containers run a Gc.full_major cycle.
generate_response [Nethttpd_types.http_service_generator]
Third stage of HTTP processing: This method is called when the HTTP request has been completely received, and the response is going to be generated.
get [Nethttp_client.tls_cache]
Get a cached session (data string)
get_connection_state [Nethttp_client_conncache.connection_cache]
Returns the state of the file descriptor, or raises Not_found
get_engine [Uq_engines_compat.cache_t]
get_engine [Uq_engines.cache_t]
Requests the value.
get_host [Nethttp_client.http_call]
The host name of the content server, extracted from the URI.
get_local_option [Nettelnet_client.telnet_session]
get_mic [Netsys_gssapi.poly_gss_api]
get_opt [Uq_engines_compat.cache_t]
get_opt [Uq_engines.cache_t]
Returns the cached value if available
get_options [Nettelnet_client.telnet_session]
Get the configuration options.
get_options [Nethttp_client.pipeline]
get_path [Nethttp_client.http_call]
The path (incl.
get_port [Nethttp_client.http_call]
The port number of the content server, extracted from the URI.
get_reconnect_mode [Nethttp_client.http_call]
Get what to do if the server needs to be reconnected, i.e.
get_redirect_mode [Nethttp_client.http_call]
By default, the redirect mode is Redirect_if_idem.
get_remote_option [Nettelnet_client.telnet_session]
get_req_body [Nethttp_client.http_call]
What has been sent as body in the (last) request.
get_req_header [Nethttp_client.http_call]
Deprecated.
get_req_method [Nethttp_client.http_call]
Get the name of the request method.
get_resp_body [Nethttp_client.http_call]
Deprecated.
get_resp_header [Nethttp_client.http_call]
Deprecated.
get_uri [Nethttp_client.http_call]
the full URI of this message: http://server:port/path.
getpeername [Rpc_transport.rpc_multiplex_controller]
The address of the peer's socket.
getsockname [Rpc_transport.rpc_multiplex_controller]
The address of this socket
global_exception_handler [Netplex_types.processor_hooks]
This method is called when an uncaught exception would otherwise terminate the container.
greedy_accepts [Netplex_workload.dynamic_workload_config]
Whether greedy accepts are permitted
group [Uq_engines_compat.poll_engine]
group [Uq_engines.poll_engine]
Returns the group the engine is member of
gssapi_props [Rpc_client.auth_protocol]
Properties of the GSSAPI session (if existing)
gssapi_props [Netpop.client]
Returns GSSAPI properties, if available
gssapi_props [Netsmtp.client]
Returns GSSAPI properties, if available
gssapi_props [Netftp_client.ftp_client_pi]
GSSAPI props if GSSAPI security is negotiated
gssapi_props [Nethttp_client.http_call]
If GSSAPI is active, return the properties

H
has_req_body [Nethttp_client.http_call]
Whether the method allows to send a request body
has_resp_body [Nethttp_client.http_call]
Whether the method allows to reply with a body.
hello [Netplex_types.workload_manager]
Called by the controller when the service is added
helo [Netsmtp.client]
Sends an EHLO command to the server.
helo_response [Netsmtp.client]
The response from the last HELO or EHLO
help [Netsmtp.client]
Performs the Help command.
home_directory [Netglob.user_info]
Returns the home directory of the passed user, or the home directory of the current user for the empty string.
hooks [Nethttpd_kernel.http_protocol]
Set hooks
host_by_name [Uq_resolver.resolver]
Look up the passed host name up.

I
iana_hash_fn [Netsys_digests.digest]
Whether registered at IANA, and if so, which ID we use here
iana_name [Netsys_digests.digest]
The name as registered by IANA (if registered)
id [Netsys_oothr.thread]
In a multi-threaded program: Returns the thread ID.
id [Nettls_support.tls_session_props]
The ID of the session (non-printable string)
id [Netmcore.compute_resource]
an ID of the resource that is valid in the whole Netplex system
identify_conn_by_name [Nethttp_client.transport_channel_type]
Whether connections must be identified by name, and not by IP address.
identify_proxy_session [Nethttp_client.auth_handler]
Same for proxies.
identify_session [Nethttp_client.auth_handler]
Extracts (mech_name,realm,sess_id,trans_id) if possible.
import_name [Netsys_gssapi.poly_gss_api]
import_sec_context [Netsys_gssapi.poly_gss_api]
inactivate [Rpc_transport.rpc_multiplex_controller]
Inactivates the connection immediately, and releases any resources the controller is responsible for (e.g.
inactivate [Uq_engines_compat.multiplex_controller]
inactivate [Uq_multiplex.multiplex_controller]
Inactivates the connection immediately, and releases any resources the controller is responsible for (e.g.
inactivate [Uq_engines.multiplex_controller]
inactivity_timeout [Netplex_workload.dynamic_workload_config]
After this number of seconds a free thread can be terminated
indicate_mechs [Netsys_gssapi.poly_gss_api]
info_string [Netplex_types.par_thread]
Outputs the process or thread ID
init [Netplex_types.parallelizer]
Initializes the main process for usage with this parallelizer.
init_sec_context [Netsys_gssapi.poly_gss_api]
On the first call, pass ~context:None.
initial_argument [Netcgi1_compat.Netcgi_types.cgi_activation]
initial_argument_value [Netcgi1_compat.Netcgi_types.cgi_activation]
initial_arguments [Netcgi1_compat.Netcgi_types.cgi_activation]
initial_multiple_argument [Netcgi1_compat.Netcgi_types.cgi_activation]
initiator_cred [Netsys_gssapi.client_config]
initiator_name [Netsys_gssapi.server_props]
The name of the initiator.
initiator_name [Netsys_gssapi.client_config]
initiator_name_exported [Netsys_gssapi.server_props]
The name of the initiator in exported format
input [Netchannels.augment_raw_in_channel]
As in raw_in_channel
input [Netchannels.rec_in_channel]
Reads octets from the channel and puts them into the string.
input [Uq_engines_compat.async_in_channel]
input [Uq_transfer.async_in_channel]
input s k n: Reads channel data into the substring of s beginning at index k with length n.
input [Uq_engines.async_in_channel]
input_body_size [Nethttpd_types.request_info]
The size of the input body.
input_body_size [Nethttpd_types.v_extended_environment]
so far known, or 0L
input_byte [Netchannels.compl_in_channel]
Reads exactly one octet from the channel and returns its code, or raises End_of_file
input_ch [Netcgi1_compat.Netcgi_env.cgi_environment]
Not the user business.
input_ch_async [Nethttpd_engine.extended_async_environment]
This is the input_ch channel taken as asynchonous channel.
input_channel [Nethttpd_types.v_extended_environment]
The input channel for reading the body of the request
input_char [Netchannels.compl_in_channel]
Reads exactly one character from the channel, or raises End_of_file
input_content_length [Netcgi1_compat.Netcgi_env.cgi_environment]
input_content_length [Netcgi.cgi_environment]
Returns the "Content-length" request header field.
input_content_length [Netcgi_common.cgi_environment]
input_content_type [Netcgi1_compat.Netcgi_env.cgi_environment]
Type now is unit -> string * (string * Netmime_string.s_param) list to be coherent with Netmime.mime_header_ro.
input_content_type [Netcgi.cgi_environment]
Returns the parsed "Content-type" request header field.
input_content_type [Netcgi_common.cgi_environment]
input_content_type_string [Netcgi1_compat.Netcgi_env.cgi_environment]
input_content_type_string [Netcgi.cgi_environment]
Returns the "Content-type" request header field as a plain string or "" if it is not set.
input_content_type_string [Netcgi_common.cgi_environment]
input_eor [Netftp_data_endpoint.in_record_channel]
Skips over the remaining data of the current record and the record boundary to the next record.
input_header [Nethttpd_types.request_info]
The request header.
input_header [Netcgi1_compat.Netcgi_env.cgi_environment]
input_header [Netcgi.cgi_environment]
The whole HTTP header.
input_header [Netcgi_common.cgi_environment]
For special header structures, just override this method.
input_header_field [Netcgi1_compat.Netcgi_env.cgi_environment]
input_header_field [Netcgi.cgi_environment]
#input_header_field ?default f returns the value of a field f of the HTTP request header.
input_header_field [Netcgi_common.cgi_environment]
input_header_fields [Netcgi1_compat.Netcgi_env.cgi_environment]
input_header_fields [Netcgi.cgi_environment]
Returns the input header as (name,value) pairs.
input_header_fields [Netcgi_common.cgi_environment]
input_line [Netchannels.compl_in_channel]
Reads the next line from the channel.
input_queue [Nettelnet_client.telnet_session]
The queue of commands received from the remote side.
input_state [Netcgi1_compat.Netcgi_env.cgi_environment]
Not the user business.
input_timeout_class [Nethttpd_kernel.http_protocol]
Suggests the calculation of a timeout value for input: `Normal: The normal timeout value applies, `Next_message: The timeout value applies while waiting for the next message, `None: The connection is output-driven, no input timeout value
inquire_context [Netsys_gssapi.poly_gss_api]
inquire_cred [Netsys_gssapi.poly_gss_api]
inquire_cred_by_mech [Netsys_gssapi.poly_gss_api]
inquire_key [Nethttp_client.key_handler]
The method is called when a new session must be authenticated.
inquire_mechs_for_name [Netsys_gssapi.poly_gss_api]
inquire_names_for_mech [Netsys_gssapi.poly_gss_api]
int_param [Netplex_types.config_file]
integrity [Netsys_gssapi.server_config]
integrity [Netsys_gssapi.client_config]
internal_sockets [Netplex_types.socket_service]
The internal sockets for internal services: pairs of (protocol,server)
invalidate [Rpc_server.auth_method]
Remove all auth sessions
invalidate [Nethttp_client.auth_session]
The session is notified that authentication failed.
invalidate [Uq_engines_compat.cache_t]
invalidate [Uq_engines.cache_t]
Invalidates the cache - if a value exists in the cache, it is removed.
invalidate_connection [Rpc_server.auth_method]
Removes all auth sessions for this connection
invalidate_key [Nethttp_client.key_handler]
The handler is notified that authentication failed for this key
ipv6 [Uq_resolver.resolver]
Whether host_by_name may return IPv6 addresses
is_empty [Netftp_client.ftp_client_pi]
Whether the queue is empty
is_idempotent [Nethttp_client.http_call]
Whether the method is to be considered as idempotent ( = repeated invocations have the same result and no side effect).
is_no_credential [Netsys_gssapi.poly_gss_api]
A test for GSS_C_NO_CREDENTIAL
is_no_name [Netsys_gssapi.poly_gss_api]
A test for GSS_C_NO_NAME
is_proxy_allowed [Nethttp_client.http_call]
Deprecated.
is_running [Unixqueue_select.sb_event_system]
is_running [Unixqueue.event_system]
is_served [Nethttp_client.http_call]
true if request/response cycle(s) have been finished, i.e.
issuer [Netx509.x509_certificate]
The DN of the issuer
issuer_unique_id [Netx509.x509_certificate]
The unique ID of the issuer
iter [Uq_lwt.lwt_backend]
iv_lengths [Netsys_ciphers.cipher]
Supported iv lengths as pairs min,max.

J
job [Shell_uq.job_handler_engine_type]
Returns the called job
job [Shell_sys.job_handler_engine_type]
Returns the called job
job_instance [Shell_uq.job_handler_engine_type]
Returns the job instance
job_instance [Shell_sys.job_handler_engine_type]
Returns the job instance
join [Netsys_oothr.thread]
In a multi-threaded program: Suspends the calling thread until this thread terminates.

K
key_lengths [Netsys_ciphers.cipher]
Supported key lengths as pairs min,max.
keys [Nethttp_client.key_ring]
List of all known keys
kx_algo [Nettls_support.tls_session_props]
The name of the key exchange algorithm, e.g.

L
last_ftp_state [Netftp_fs.ftp_stream_fs]
The last state of the last operation, or Not_found
last_response_header [Nethttp_fs.http_stream_fs]
Returns the header of the HTTP response of the last operation.
last_response_status [Nethttp_fs.http_stream_fs]
Return the response status of the last operation, as triple (symbolic_code,numeric_code,text).
last_stderr [Shell_fs.shell_stream_fs]
The stderr output of the last operation
ldap_endpoint [Netldap.ldap_server]
ldap_peer_name [Netldap.ldap_server]
ldap_timeout [Netldap.ldap_server]
ldap_tls_config [Netldap.ldap_server]
ldap_tls_mode [Netldap.ldap_server]
length [Netsys_types.mstring]
length [Netxdr_mstring.mstring]
The length of the managed string
lingering [Nethttpd_kernel.lingering_close]
Whether the socket is still lingering
list [Netpop.client]
Returns the scan listing for an optional message number or for all messages in the current mailbox.
listen [Uq_engines_compat.server_endpoint_listener]
listen [Uq_engines.server_endpoint_listener]
listen_options [Rpc_server.socket_config]
local_chmod [Netplex_types.protocol]
Whether to chmod Unix Domain sockets
local_chown [Netplex_types.protocol]
Whether to chown (user,group) Unix Domain sockets
local_receiver [Netftp_data_endpoint.ftp_data_receiver]
The local receiver.
local_sender [Netftp_data_endpoint.ftp_data_sender]
The local sender.
lock [Netsys_oothr.mutex]
In a multi-threaded program: Suspends the calling thread until the mutex is locked.
log [Netplex_types.container]
Sends a log message to the controller.
log [Netplex_types.logger]
Same as log_subch when subchannel is set to the empty string.
log_access [Nethttpd_reactor.internal_environment]
log_component [Netplex_log.generic_config]
log_directory [Netplex_log.multi_file_config]
log_error [Netcgi1_compat.Netcgi_env.cgi_environment]
log_error [Netcgi.cgi_environment]
#log_error msg appends msg to the webserver log.
log_error [Netcgi_common.cgi_environment]
You may want to override this with your custom logging method.
log_facility [Netplex_log.syslog_config]
log_files [Netplex_log.multi_file_config]
Triples (component, subchannel, max_level, file, format) .
log_format [Netplex_log.generic_config]
log_identifier [Netplex_log.syslog_config]
log_max_level [Netplex_log.generic_config]
log_props [Nethttpd_types.v_extended_environment]
Remember this version of cgi_properties as the one sent to the config_log_access function
log_subch [Netplex_types.container]
Sends a log message to the controller.
log_subch [Netplex_types.logger]
Receive a log message of level from component.
log_subchannel [Netplex_log.generic_config]
logger [Netplex_types.controller]
The logger
lookup [Netplex_types.container]
lookup service_name protocol_name tries to find a Unix domain socket for the service and returns it.
lookup_container_sockets [Netplex_types.container]
lookup_container_sockets service_name protocol_name: returns the Unix Domain paths of all container sockets for this service and protocol.
lstn_backlog [Netplex_types.protocol]
The backlog (argument of Unix.listen)
lstn_reuseaddr [Netplex_types.protocol]
Whether to reuse ports immediately

M
mac [Netsys_ciphers.cipher_ctx]
Returns the MAC for AEAD ciphers.
mac [Netchannels_crypto.crypto_in_filter]
Get the MAC of the processed data
mac [Netchannels_crypto.crypto_out_filter]
Get the MAC of the processed data
mac_algo [Nettls_support.tls_session_props]
The name of the data integrity algorithm (actually only the digest algorithm for HMAC), e.g.
mail [Netsmtp.client]
Performs a MAIL FROM command.
mailboxes [Netaddress.group]
The member mailboxes
matched_dn [Netldap.ldap_result]
The matchedDN field sent with some codes
max_free_job_capacity [Netplex_workload.dynamic_workload_config]
If more job capacity is available than this number, threads are terminated.
max_jobs_per_thread [Netplex_workload.dynamic_workload_config]
How many jobs every thread can execute concurrently until it is considered as fully loaded.
max_level [Netplex_types.controller_config]
Return the maximum global log level
max_response_body_length [Nethttp_client.http_call]
Returns the current maximum length (initially Int64.max_int)
max_threads [Netplex_workload.dynamic_workload_config]
The manager does not start more threads than this number
mech_type [Netsys_gssapi.server_props]
Actual mechanism
mech_type [Netsys_gssapi.client_props]
Actual mechanism
mech_type [Netsys_gssapi.client_config]
mech_types [Netsys_gssapi.server_config]
mem_supported [Uq_engines_compat.multiplex_controller]
mem_supported [Uq_multiplex.multiplex_controller]
Whether start_mem_reading and start_mem_writing are possible
mem_supported [Uq_engines.multiplex_controller]
message [Rpc_server.auth_details]
min_free_job_capacity [Netplex_workload.dynamic_workload_config]
The manager starts as many threads as required to ensure that this number of jobs can be executed.
mkdir [Netfs.stream_fs]
Creates a new directory.
mkdir [Nethttp_fs.http_stream_fs]
mlst_enabled_facts [Netftp_client.ftp_client_pi]
The enabled facts for `MLST and `MLSD
mlst_facts [Netftp_client.ftp_client_pi]
All available facts for `MLST and `MLSD
mode [Netsys_ciphers.cipher]
The mode of the cipher
multiple_argument [Netcgi1_compat.Netcgi_types.cgi_activation]
multiple_argument [Netcgi.cgi]
#multiple_argument name returns all the values of the argument named name.
multiple_argument [Netcgi_common.cgi]
multiple_connections [Uq_engines_compat.server_endpoint_acceptor]
multiple_connections [Uq_server.server_endpoint_acceptor]
Whether it is possible to accept multiple connections
multiple_connections [Uq_engines.server_endpoint_acceptor]
multiple_field [Netmime.mime_header_ro]
The current fields of the header.
multiple_input_header_field [Netcgi1_compat.Netcgi_env.cgi_environment]
multiple_input_header_field [Netcgi.cgi_environment]
Returns the values of all fields with the passed name of the request header.
multiple_input_header_field [Netcgi_common.cgi_environment]
multiple_output_header_field [Netcgi1_compat.Netcgi_env.cgi_environment]
multiple_output_header_field [Netcgi.cgi_environment]
Returns the values of all fields with the passed name of the repsonse header.
multiple_output_header_field [Netcgi_common.cgi_environment]
multiplexing [Rpc_server.socket_config]
multiplexing [Rpc_client.socket_config]

N
n_connections [Netplex_types.container]
The current number of connections
n_total [Netplex_types.container]
The sum of all connections so far
name [Rpc_server.auth_method]
The name of the authentication method
name [Rpc_client.auth_method]
The name of this method, used for errors etc.
name [Netsys_digests.digest]
The name conventionally follows the <uppercasestring>-<size> format, e.g.
name [Netsys_ciphers.cipher]
The name of the cipher
name [Netsys_posix.post_fork_handler]
name [Netx509.directory_name]
This is the raw version of the DN: a sequence of relative DNs, and a relative DN is a set of (type,value) pairs.
name [Netaddress.group]
The name of the group
name [Netaddress.mailbox]
The name of the mailbox.
name [Netplex_types.logger_factory]
name [Netplex_types.workload_manager_factory]
name [Netplex_types.processor_factory]
name [Netplex_types.ctrl_message_receiver]
The name of this receiver
name [Netplex_types.protocol]
The protocol name is an arbitrary string identifying groups of sockets serving the same protocol for a socket_service.
name [Netplex_types.socket_service_config]
The proposed name for the socket_service
name [Netplex_types.socket_service]
The name of the socket_service is used to identify the service in the whole netplex process cluster.
name [Nethttpd_types.http_service]
The name of the type of the service provider
name [Netcgi1_compat.Netcgi_types.cgi_argument]
name [Netcgi.cgi_argument]
The name of the argument.
name [Netcgi_common.cgi_argument]
need_ip6 [Netftp_client.ftp_client_pi]
Whether `EPSV or `EPRT are required instead of `PASV and `PORT, respectively.
need_linger [Nethttpd_kernel.http_protocol]
Returns true when a lingering close operation is needed to reliably shut down the socket.
new_group [Unixqueue_select.sb_event_system]
new_group [Unixqueue.event_system]
new_session [Rpc_client.auth_method]
Request a new session.
new_wait_id [Unixqueue_select.sb_event_system]
new_wait_id [Unixqueue.event_system]
next_credentials [Rpc_client.auth_session]
Called with client prog proc xid.
next_request [Nethttpd_reactor.http_reactor]
Tries to read the next request.
no_credential [Netsys_gssapi.poly_gss_api]
A substitute credential for GSS_C_NO_CREDENTIAL
no_name [Netsys_gssapi.poly_gss_api]
A substitute name for GSS_C_NO_NAME
no_proxy [Nethttp_client.http_call]
Same as set_proxy_enabled false
nominal_dot_dot [Netfs.stream_fs]
Whether the effect of .. can be obtained by stripping off the last path component, i.e.
nominal_dot_dot [Nethttp_fs.http_stream_fs]
non_blocking_connect [Rpc_client.socket_config]
non_blocking_connect: Whether the remote service is connected in the background.
noop [Netpop.client]
Pings the server to keep the session alive.
noop [Netsmtp.client]
NOOP : does nothing, keeps the connection alive.
notify [Uq_engines_compat.engine_mixin]
notify [Uq_engines.engine_mixin]
number_of_open_connections [Nethttp_client.pipeline]
Returns the number of connections which are open at the same time and currently being used by this object (i.e.
number_of_open_messages [Nethttp_client.pipeline]
Returns the number of messages which are still in the pipeline.

O
offer_local_option [Nettelnet_client.telnet_session]
oid [Netsys_digests.digest]
The OID (if registered)
on_add [Netplex_types.socket_service]
Get some runtime configuration aspects from this controller.
open_value_rd [Netmime.mime_body_ro]
Opens the value for reading.
open_value_rd [Netcgi1_compat.Netcgi_types.cgi_argument]
open_value_rd [Netcgi.cgi_argument]
Open the contents of the value as an input channel.
open_value_rd [Netcgi_common.cgi_argument]
open_value_wr [Netcgi1_compat.Netcgi_types.cgi_argument]
See #set_value.
open_value_wr [Netmime.mime_body]
Opens the value for writing.
open_value_wr [Netcgi.rw_cgi_argument]
open_value_wr [Netcgi_common.rw_cgi_argument]
option_negotiation_is_over [Nettelnet_client.telnet_session]
out_channel [Netcgi.cgi]
The output channel to which the generated content is intended to be written.
out_channel [Netcgi.cgi_environment]
The "raw" output channel.
out_channel [Netcgi_common.cgi]
out_channel [Netcgi_common.cgi_environment]
output [Netchannels.augment_raw_out_channel]
As in raw_out_channel
output [Netchannels.rec_out_channel]
Takes octets from the string and writes them into the channel.
output [Netcgi1_compat.Netcgi_types.cgi_activation]
output [Netcgi.cgi]
output [Netcgi_common.cgi]
output [Netcgi_modtpl.template]
output cgi outputs the template to the CGI session cgi.
output [Uq_engines_compat.async_out_channel]
output [Uq_transfer.async_out_channel]
output s k n: Writes the substring of s beginning at index k with length n into the channel.
output [Uq_engines.async_out_channel]
output_body_size [Nethttpd_types.full_info]
The size of the output body.
output_buffer [Netchannels.compl_out_channel]
Writes exactly the contents of the buffer
output_byte [Netchannels.compl_out_channel]
Writes exactly one byte passed as integer code
output_bytes [Netchannels.compl_out_channel]
Writes exactly the passed string
output_ch [Netcgi1_compat.Netcgi_env.cgi_environment]
output_ch [Netcgi.cgi_environment]
output_ch [Netcgi_common.cgi_environment]
output_ch_async [Nethttpd_engine.extended_async_environment]
This is the output_ch channel taken as asynchronous channel.
output_channel [Netchannels.compl_out_channel]
Writes the contents of an in_obj_channel until the end of the input channel is reached.
output_char [Netchannels.compl_out_channel]
Writes exactly one character
output_eor [Netftp_data_endpoint.out_record_channel]
Finishes the current record.
output_header [Nethttpd_types.full_info]
The response header
output_header [Netcgi1_compat.Netcgi_env.cgi_environment]
output_header [Netcgi.cgi_environment]
The whole HTTP response header
output_header [Netcgi_common.cgi_environment]
For special header structures, override this method and maybe #send_output_header.
output_header_field [Netcgi1_compat.Netcgi_env.cgi_environment]
output_header_field [Netcgi.cgi_environment]
Returns the value of a field of the response header.
output_header_field [Netcgi_common.cgi_environment]
output_header_fields [Netcgi1_compat.Netcgi_env.cgi_environment]
output_header_fields [Netcgi.cgi_environment]
Returns the output header as (name,value) pairs.
output_header_fields [Netcgi_common.cgi_environment]
output_queue [Nettelnet_client.telnet_session]
The queue of commands to send to the remote side.
output_state [Nethttpd_types.v_extended_environment]
Reflects the state of the output generation: `Start: Nothing is generated yet, `Sending: Output is already being sent, `End: The response (for a single request) has been fully sent
output_state [Nethttpd_types.extended_environment]
output_state [Netcgi1_compat.Netcgi_env.cgi_environment]
Not the user business.
output_string [Netchannels.compl_out_channel]
Writes exactly the passed string
owned_container_sockets [Netplex_types.container]
List of pairs (protocol_name, path) of all container sockets of this container

P
padding [Netsys_ciphers.cipher_ctx]
The padding scheme of the cipher
parallelizer [Netplex_types.par_thread]
Returns the parallelizer that created this thread.
partial_value [Netldap.ldap_result]
the value so far available, independently of the code
pass [Netpop.client]
Authenticates a user with the plain-text password pass.
password [Nethttp_client.key]
The password in cleartext (UTF-8)
password_of_user_name [Netmech_scram_gssapi.client_key_ring]
Returns the cleartext password for a user name, or raises Not_found if the user is unknown
path_encoding [Netglob.glob_fsys]
Paths of filesystems may be encoded
path_encoding [Netglob.user_info]
Paths of filesystems may be encoded
path_encoding [Netfs.stream_fs]
The encoding must be ASCII-compatible (Netconversion.is_ascii_compatible).
path_encoding [Nethttp_fs.http_stream_fs]
path_exclusions [Netfs.stream_fs]
Code points that must not occur in path components between slashes.
path_exclusions [Nethttp_fs.http_stream_fs]
peek [Rpc_server.auth_method]
If available, this function is called for every accepted connection.
peek_recv [Nethttpd_kernel.http_protocol]
Peeks the first token, but leaves it in the queue.
peer_credentials [Nettls_support.tls_session_props]
Returns the decoded peer credentials
peer_credentials_raw [Nettls_support.tls_session_props]
Returns the peer credentials in the raw form.
peer_credentials_type [Nettls_support.tls_session_props]
The type of credentials
peer_user_name [Rpc_transport.rpc_multiplex_controller]
If the transport mechanism provides a way to authenticate the peer, it can return the name here.
pi [Netftp_client.ftp_client]
The curerent protocol interpreter.
pipeline [Nethttp_fs.http_stream_fs]
The HTTP pipeline backing this file system
pipeline_len [Nethttpd_kernel.http_protocol]
Returns the number of unanswered requests = Number of received `Req_end tokens minus number of responses in state `Processed.
pos_in [Netchannels.augment_raw_in_channel]
As in raw_in_channel
pos_in [Netchannels.raw_in_channel]
Returns the current channel position.
pos_in [Uq_engines_compat.async_in_channel]
pos_in [Uq_transfer.async_in_channel]
Returns the number of characters read from the channel
pos_in [Uq_engines.async_in_channel]
pos_out [Netchannels.augment_raw_out_channel]
As in raw_out_channel
pos_out [Netchannels.raw_out_channel]
Returns the current channel position.
pos_out [Uq_engines_compat.async_out_channel]
pos_out [Uq_transfer.async_out_channel]
Returns the number of characters output into the channel
pos_out [Uq_engines.async_out_channel]
post_add_hook [Netplex_types.processor_hooks]
A user-supplied function that is called after the service has been added to the controller
post_finish_hook [Netplex_types.processor_hooks]
A user-supplied function that is called after the container is terminated.
post_rm_hook [Netplex_types.processor_hooks]
A user-supplied function that is called after the service has been removed from the controller
post_start_hook [Netplex_types.processor_hooks]
A user-supplied function that is called after the container is created and started, but before the first service request arrives.
pre_finish_hook [Netplex_types.processor_hooks]
A user-supplied function that is called just before the container is terminated.
pre_start_hook [Netplex_types.processor_hooks]
A user-supplied function that is called before the container is created and started.
preferred [Netsys_types.mstring]
preferred [Netxdr_mstring.mstring]
Whether as_memory or as_bytes is cheaper
print [Netplex_types.config_file]
print [Nethttpd_types.http_service]
Outputs the definition term to a formatter
prioritized [Uq_engines_compat.prioritizer_t]
prioritized [Uq_engines.prioritizer_t]
let pe = prioritized f p: Queues up f on priority level p.
privacy [Netsys_gssapi.server_config]
privacy [Netsys_gssapi.client_config]
private_api [Nethttp_client.http_call]
procedure [Rpc_server.auth_details]
process [Netplex_kit.v_processor]
process [Netplex_types.processor]
A user-supplied function that is called when a new socket connection is established.
process_body [Nethttpd_types.http_service_receiver]
Second stage of HTTP processing: This method is called when the body is expected to be arriving.
process_context_token [Netsys_gssapi.poly_gss_api]
process_header [Nethttpd_types.http_service]
First stage of HTTP processing: This method is called when the HTTP header has been received.
process_internal [Netplex_types.processor_hooks]
process_internal ~when_done cont client protocol: This function is called instead of process when a connection to an internal service is made.
process_option_command [Nettelnet_client.telnet_session]
processor [Netplex_types.socket_service]
A user-supplied object to process incoming connections
program [Rpc_server.auth_details]
program [Netplex_types.plugin]
The RPC program structure on which the messaging bases.
propagate [Netsys_global.propagator]
propagate name value version: push the new value of the variable called name to other processes.
protocol [Rpc_transport.rpc_multiplex_controller]
The protocol encapsulation
protocol [Nettls_support.tls_session_props]
The name of the TLS protocol version, e.g.
protocol [Nethttpd_kernel.http_response]
The HTTP version of the response.
protocol [Netcgi1_compat.Netcgi_env.cgi_environment]
protocol [Netcgi.cgi_environment]
The server protocol in a decoded form.
protocol [Netcgi_common.cgi_environment]
protocols [Netplex_types.socket_service_config]
This list describes the sockets to create in detail
provider [Netsys_gssapi.poly_gss_api]
A string name identifying the provider
proxy_enabled [Nethttp_client.http_call]
Returns the proxy mode
proxy_type [Nethttp_client.pipeline]
proxy_type url returns Some pt if a proxy would be used for this url, and None if a direct connection would be made.
proxy_type_of_call [Nethttp_client.pipeline]
Same for an already created call object
proxy_use_connect [Nethttp_client.http_call]
Whether to use the CONNECT method if the connection is made via a web proxy.
ptype [Netplex_types.netplex_config]
ptype [Netplex_types.parallelizer]
ptype [Netplex_types.par_thread]
ptype [Netplex_types.container]
The parallelization type actually used for this container
ptype [Netplex_types.controller]
The actually effective parallelization type
public_key [Netx509.x509_certificate]
The subject's public key
public_key_algorithm [Netx509.x509_certificate]
The algorithm of the public key (OID, and algorithm-specific parameters)
put [Uq_engines_compat.cache_t]
put [Uq_engines.cache_t]
Puts a value immediately into the cache.

Q
queue_events [Unixqueue_select.sb_event_system]
quit [Netpop.client]
Requests the server to end this session.
quit [Netsmtp.client]
Requests the server to end this session.

R
rcpt [Netsmtp.client]
Performs a RCPT TO command.
read [Netfs.stream_fs]
read flags filename: Opens the file filename for reading, and returns the input stream.
read [Nethttp_fs.http_stream_fs]
Additional flag: `Header h: Set these headers in the submitted GET request
read_dir [Netglob.glob_fsys]
Returns the file names contained in the directory, without path.
read_eof [Rpc_transport.rpc_multiplex_controller]
Whether the EOF marker has been read
read_eof [Uq_engines_compat.multiplex_controller]
read_eof [Uq_multiplex.multiplex_controller]
Whether the EOF marker has been read
read_eof [Uq_engines.multiplex_controller]
read_file [Netfs.stream_fs]
read_file flags filename: Opens the file filename for reading, and returns the contents as a local_file.
read_file [Nethttp_fs.http_stream_fs]
Additional flag: `Header h: Set these headers in the submitted GET request
readdir [Netfs.stream_fs]
Reads the contents of a directory.
readdir [Nethttp_fs.http_stream_fs]
reading [Rpc_transport.rpc_multiplex_controller]
True iff there is a reader
reading [Uq_engines_compat.multiplex_controller]
reading [Uq_multiplex.multiplex_controller]
True iff there is a reader
reading [Uq_engines.multiplex_controller]
readlink [Netfs.stream_fs]
Reads the target of a symlink
readlink [Nethttp_fs.http_stream_fs]
really_input [Netchannels.compl_in_channel]
Reads exactly as many octets from the channel as the second int argument specifies.
really_input_string [Netchannels.compl_in_channel]
really_input_string ic len reads len characters from channel ic and returns them in a new string.
really_output [Netchannels.compl_out_channel]
Writes exactly as many octets to the channel as the second int argument specifies.
really_output_string [Netchannels.compl_out_channel]
Same for strings
realm [Nethttp_client.key]
The realm
receive [Rpc_client.auth_protocol]
Receive a token for the xid announced in state.
receive [Nethttpd_kernel.http_protocol]
Returns the first req_token from the receive queue.
receive_admin_message [Netplex_types.processor_hooks]
This function is called when a broadcast admin message is received.
receive_admin_message [Netplex_types.ctrl_message_receiver]
This function is called when a broadcast admin message is received.
receive_message [Netplex_types.processor_hooks]
This function is called when a broadcast message is received.
receive_message [Netplex_types.ctrl_message_receiver]
This function is called when a broadcast message is received.
received_from [Uq_engines_compat.datagram_multiplex_controller]
received_from [Uq_multiplex.datagram_multiplex_controller]
Returns the socket address of the last received datagram.
received_from [Uq_engines.datagram_multiplex_controller]
recommended_jobs_per_thread [Netplex_workload.dynamic_workload_config]
The number of jobs every thread can execute with normal service quality.
recv_queue_byte_size [Nethttpd_kernel.http_protocol]
Returns the (estimated) size of the input queue in bytes
recv_queue_len [Nethttpd_kernel.http_protocol]
Returns the length of the receive queue (number of tokens)
recvfrom [Uq_engines_compat.wrapped_datagram_socket]
recvfrom [Uq_datagram.wrapped_datagram_socket]
Receive data from the (unconnected) socket.
recvfrom [Uq_engines.wrapped_datagram_socket]
referral [Netldap.ldap_result]
if non-empty, a list of URIs where to find more results
register [Netsys_pmanage.pmanage]
Mass-register a list of objects
register_file [Netsys_pmanage.pmanage]
Register a temporary file
register_lever [Netplex_types.controller]
let id = register_lever f: It is possible to register a function f in the controller, and run it over the internal RPC interface from any container.
register_posix_sem [Netsys_pmanage.pmanage]
Register a POSIX named semaphore identified by this path
register_posix_shm [Netsys_pmanage.pmanage]
Register a POSIX shared memory object identified by this path
register_readable [Uq_lwt.lwt_backend]
register_sem_cont [Netsys_pmanage.pmanage]
Register a semaphore container (see Netsys_sem)
register_timer [Uq_lwt.lwt_backend]
register_writable [Uq_lwt.lwt_backend]
registered [Netsys_pmanage.pmanage]
Return the registered objects
reject_body [Nethttpd_reactor.http_reactive_request]
Call this method to unlock the body channels.
release [Netmcore.compute_resource]
Notify the manager that the resource is not used any longer by this process.
remote_socket_addr [Nethttpd_types.request_info]
The socket address of the client.
remote_socket_addr [Nethttpd_types.v_extended_environment]
These are always the physical IP addresses and ports of the two endpoints of the current connection.
remote_socket_addr [Nethttpd_types.extended_environment]
remove [Netsys_pollset.pollset]
Remove a descriptor from the set (if it is member)
remove [Netfs.stream_fs]
Removes the file or symlink.
remove [Nethttp_fs.http_stream_fs]
remove_resource [Unixqueue_select.sb_event_system]
remove_resource [Unixqueue.event_system]
rename [Netfs.stream_fs]
Renames the file.
rename [Nethttp_fs.http_stream_fs]
reopen [Netplex_types.logger]
Reopen the log files
repr [Netsys_oothr.condition]
May be used internally be the implementation
repr [Netsys_oothr.mutex]
May be used internally be the implementation
repr [Netsys_oothr.thread]
May be used internally be the implementation
repr [Netmcore.compute_resource]
the resource detail
representation [Netcgi1_compat.Netcgi_types.cgi_argument]
representation [Netcgi.cgi_argument]
The representation of the argument.
representation [Netcgi_common.cgi_argument]
req_method [Nethttpd_reactor.internal_environment]
req_state [Nethttpd_engine.http_request_notification]
Returns the request processing state which is `Received_request at the moment when this notification is delivered.
req_state [Nethttpd_engine.http_request_header_notification]
Returns the request processing state which is `Received_header at the moment when this notification is delivered.
request [Netcgi_apache.cgi]
The underlying apache request structure.
request_body [Nethttp_client.http_call]
The whole body of the request.
request_body_rejected [Nethttpd_types.v_extended_environment]
so far known, or false
request_body_rejected [Nethttpd_types.full_info]
Whether the request body was rejected
request_header [Nethttp_client.http_call]
The whole header of the request.
request_method [Nethttpd_types.request_info]
The method like GET.
request_method [Nethttp_client.http_call]
The HTTP method as string
request_method [Netcgi1_compat.Netcgi_types.cgi_activation]
request_method [Netcgi.cgi]
The HTTP method used to make the request.
request_method [Netcgi_common.cgi]
request_notification [Netftp_client.ftp_client_pi]
request_notification [Uq_engines_compat.async_in_channel]
request_notification [Uq_engines_compat.async_out_channel]
request_notification [Uq_engines_compat.engine_mixin]
request_notification [Uq_engines_compat.engine]
request_notification [Uq_transfer.async_in_channel]
After the notification has been requested, the passed function is be called whenever can_input changes its value (or might change its value).
request_notification [Uq_transfer.async_out_channel]
After the notification has been requested, the passed function is be called whenever can_output changes its value (or might change its value).
request_notification [Uq_engines.async_in_channel]
request_notification [Uq_engines.async_out_channel]
request_notification [Uq_engines.engine_mixin]
request_notification [Uq_engines.engine]
Requests notification about state changes.
request_notification [Uq_resolver.engine]
request_proxy_notification [Netftp_client.ftp_client_pi]
request_proxy_notification [Uq_engines_compat.engine_mixin]
request_proxy_notification [Uq_engines_compat.engine]
request_proxy_notification [Uq_engines.engine_mixin]
request_proxy_notification [Uq_engines.engine]
Requests to call back the function when there is another engine that can be used as proxy for this object.
request_proxy_notification [Uq_resolver.engine]
request_remote_option [Nettelnet_client.telnet_session]
request_uri [Nethttpd_types.request_info]
The URI of the client request.
request_uri [Nethttp_client.http_call]
The request URI as string.
required [Netplex_types.plugin]
Required plugins
reset [Netftp_client.ftp_client]
Aborts all current activities if any, and re-initializes the client
reset [Nettelnet_client.telnet_session]
Closes the connection immediately and empties all queues.
reset [Nethttp_client.pipeline]
Empties the pipeline and inactivates any open connection.
reset_counters [Nethttp_client.pipeline]
reset_local_option [Nettelnet_client.telnet_session]
reset_remote_option [Nettelnet_client.telnet_session]
resolve_parameter [Netplex_types.config_file]
resolve_section [Netplex_types.config_file]
resp_queue_filled [Nethttpd_kernel.http_protocol]
Whether there is data to send in the internal output queue.
resp_queue_len [Nethttpd_kernel.http_protocol]
Returns the length of the internal response queue (number of http_response objects that have not yet fully processed)
response [Nethttpd_reactor.internal_environment]
response_body [Nethttp_client.http_call]
The whole body of the response.
response_body_storage [Nethttp_client.http_call]
How to create the response body.
response_header [Nethttp_client.http_call]
The whole header of the response.
response_protocol [Nethttp_client.http_call]
The HTTP version indicated in the response
response_status [Nethttp_client.http_call]
The decoded code.
response_status_code [Nethttpd_types.error_response_params]
The HTTP status code to response
response_status_code [Nethttpd_types.full_info]
The HTTP status code to response
response_status_code [Nethttp_client.http_call]
The three-digit status code
response_status_text [Nethttp_client.http_call]
The text transmitted along with the code
restart [Netplex_types.socket_controller]
Restarts the containers for this socket service only
restart [Netplex_types.controller]
Initiates a restart of all containers: All threads/processes are terminated and replaced by newly initialized ones.
restart [Uq_engines_compat.poll_engine]
restart [Uq_engines.poll_engine]
Activate the engine again when it is already in a final state.
restrict_parameters [Netplex_types.config_file]
restrict_subsections [Netplex_types.config_file]
retr [Netpop.client]
Retrieves a message from the server.
rmdir [Netfs.stream_fs]
Removes an empty directory
rmdir [Nethttp_fs.http_stream_fs]
ro [Netmime.mime_header]
whether the header is read-only or not
ro [Netcgi1_compat.Netcgi_types.cgi_argument]
Irrelevant: there are no methods to mutate an argument.
ro [Netmime.mime_body]
whether this body is read-only or not
ro [Netcgi.rw_cgi_argument]
ro [Netcgi_common.rw_cgi_argument]
role [Netcgi_fcgi.cgi]
A FastCGI application can fulfill each of the following three roles:
rollback_work [Netchannels.trans_out_obj_channel]
Empties the transaction buffer
root_addr [Netplex_types.config_file]
root_name [Netplex_types.config_file]
route [Netaddress.mailbox]
The route to the mailbox
rset [Netpop.client]
Unmarks any messages that have previously been marked as deleted.
rset [Netsmtp.client]
Reset the current transaction
run [Netsys_posix.post_fork_handler]
run [Netftp_client.ftp_client_pi]
Starts the event system; same as Unixqueue.run
run [Netftp_client.ftp_client]
Starts the event system; same as Unixqueue.run
run [Nettelnet_client.telnet_session]
Run the event system
run [Nethttp_client.pipeline]
Runs through the requests in the pipeline.
run [Unixqueue_select.sb_event_system]
run [Unixqueue.event_system]

S
same_call [Nethttp_client.http_call]
This method returns a new object that will perform the same call as this object (this function is called "reload" in browsers).
schedule_accept_body [Nethttpd_engine.http_request_header_notification]
Schedules that the request body is accepted.
schedule_finish [Nethttpd_engine.http_request_notification]
Schedules that the request is finished.
schedule_finish [Nethttpd_engine.http_request_header_notification]
Schedules that the request is finished.
schedule_reject_body [Nethttpd_engine.http_request_header_notification]
Schedules that the request body is rejected.
scram_credentials [Netmech_scram_gssapi.server_key_verifier]
Returns the credentials for a user, or raises Not_found.
self [Netsys_oothr.mtprovider]
In a multi-threaded program: Returns the currently running thread.
send [Nethttpd_kernel.http_response]
Add token to the end of the send queue
send_abort [Netftp_client.ftp_client_pi]
Sends immediately an ABOR command, even when a data transfer is in progress.
send_admin_message [Netplex_types.controller]
send_message destination msgname msgargs: Sends an admin message to destination.
send_file [Nethttpd_types.v_extended_environment]
Sends the output header with a file as body.
send_message [Netplex_types.container]
send_message service_pattern msg_name msg_arguments: Sends a message to all services and message receivers matching service_pattern.
send_message [Netplex_types.controller]
send_message destination msgname msgargs: Sends a message to destination.
send_output_header [Netcgi1_compat.Netcgi_env.cgi_environment]
send_output_header [Netcgi.cgi_environment]
This method will encode and send the output header to the output channel.
send_output_header [Netcgi_common.cgi_environment]
send_queue_empty [Nethttpd_kernel.http_response]
Return whether the send queue is empty.
send_synch [Nettelnet_client.telnet_session]
At the next output oppurtunity, a Synch sequence is sent to the remote peer.
send_to [Uq_engines_compat.datagram_multiplex_controller]
send_to [Uq_multiplex.datagram_multiplex_controller]
Sets the socket address of the next datagram to send.
send_to [Uq_engines.datagram_multiplex_controller]
sendto [Uq_engines_compat.wrapped_datagram_socket]
sendto [Uq_datagram.wrapped_datagram_socket]
Send data over the (unconnected) socket
sendto [Uq_engines.wrapped_datagram_socket]
serial_number [Netx509.x509_certificate]
The "serialNumber" field
serialized [Uq_engines_compat.serializer_t]
serialized [Uq_engines.serializer_t]
let se = serialized f: Waits until all the previous engines reach a final state, and then runs e = f esys.
server_accepts [Rpc_client.auth_session]
Called if the server accepts the credentials.
server_addr [Rpc_server.auth_details]
server_address [Uq_engines_compat.server_endpoint_acceptor]
server_address [Uq_server.server_endpoint_acceptor]
The contact address under which the clients can establish new connections with this server.
server_address [Uq_engines.server_endpoint_acceptor]
server_rejects [Rpc_client.auth_session]
Called if the server rejects the credentials or the verifier (Auth_xxx).
server_socket_addr [Nethttpd_types.request_info]
The socket address of this server.
server_socket_addr [Nethttpd_types.v_extended_environment]
server_socket_addr [Nethttpd_types.extended_environment]
services [Netplex_types.netplex_config]
services [Netplex_types.controller]
The list of controlled services
set [Nethttp_client.tls_cache]
This is called by the client to store a new session in the cache.
set [Netcgi_modtpl.template]
Set a variable in the template.
set_accept_encoding [Nethttp_client.http_call]
Sets the Accept-Encoding field in the request header, and includes all decompression algorithms registered in Netcompression.
set_arguments [Netcgi1_compat.Netcgi_types.cgi_activation]
set_callback [Nethttpd_kernel.http_response]
The function will be called when either set_state changes the state, or when the send queue becomes empty.
set_callback [Nettelnet_client.telnet_session]
Sets the callback function.
set_chunked_request [Nethttp_client.http_call]
Configures that the request is transmitted using chunked encoding.
set_connection [Nettelnet_client.telnet_session]
Sets the host name and the port of the remote server to contact.
set_connection_cache [Nethttp_client.pipeline]
Set the connection cache.
set_connection_state [Nethttp_client_conncache.connection_cache]
Sets the state of the file descriptor.
set_event_system [Nettelnet_client.telnet_session]
Sets the event system to use.
set_event_system [Nethttp_client.pipeline]
Sets the event system.
set_exception_handler [Nettelnet_client.telnet_session]
Sets the exception handler.
set_expect_handshake [Nethttp_client.http_call]
Configures that a handshake is done before sending the request body.
set_fields [Netmime.mime_header]
set_header [Netsys_ciphers.cipher_ctx]
Sets the header to authenticate for AEAD (this must be done before starting the encryption or decryption).
set_header [Netcgi1_compat.Netcgi_types.cgi_activation]
Added ?content_length for user convenience and deprecated ?set_cookie in favor of ?set_cookies for coherence e.g.
set_header [Netcgi.cgi]
Sets the header (removing any previous one).
set_header [Netcgi_common.cgi]
set_input_state [Netcgi1_compat.Netcgi_env.cgi_environment]
Not the user business.
set_iv [Netsys_ciphers.cipher_ctx]
Sets the initialization vector (this must be done before starting the encryption or decryption).
set_max_level [Netplex_types.controller_config]
Set the maximum global log level
set_max_response_body_length [Nethttp_client.http_call]
Sets a new maximum length.
set_multiple_output_header_field [Netcgi1_compat.Netcgi_env.cgi_environment]
set_multiple_output_header_field [Netcgi.cgi_environment]
Sets multiple values of a field of the response header.
set_multiple_output_header_field [Netcgi_common.cgi_environment]
set_options [Nettelnet_client.telnet_session]
Set the configuration options.
set_options [Nethttp_client.pipeline]
Get/Set the available options for the HTTP engine.
set_output_header_field [Netcgi1_compat.Netcgi_env.cgi_environment]
set_output_header_field [Netcgi.cgi_environment]
Sets the value of a field of the response header.
set_output_header_field [Netcgi_common.cgi_environment]
set_output_header_fields [Netcgi1_compat.Netcgi_env.cgi_environment]
set_output_header_fields [Netcgi.cgi_environment]
Sets the complete response header at once.
set_output_header_fields [Netcgi_common.cgi_environment]
set_output_state [Netcgi1_compat.Netcgi_env.cgi_environment]
Not the user business.
set_proxy [Nethttp_client.pipeline]
set_proxy name port: sets that an HTTP proxy name listening on port is to be used
set_proxy_auth [Nethttp_client.pipeline]
sets user and password for the proxy.
set_proxy_enabled [Nethttp_client.http_call]
Sets the proxy mode
set_proxy_from_environment [Nethttp_client.pipeline]
Inspect the environment variables http_proxy and no_proxy and set the proxy options from them.
set_reconnect_mode [Nethttp_client.http_call]
Sets the reconnect mode
set_redirect_mode [Nethttp_client.http_call]
Sets the redirect mode
set_redirection_header [Netcgi1_compat.Netcgi_types.cgi_activation]
set_redirection_header [Netcgi.cgi]
Sets the header such that a redirection to the specified URL is performed.
set_redirection_header [Netcgi_common.cgi]
set_req_header [Nethttp_client.http_call]
set_request_body [Nethttp_client.http_call]
Replaces the whole body object
set_request_device [Nethttp_client.http_call]
Sets that the request data is read from the passed device instead of taking it from a body object.
set_request_header [Nethttp_client.http_call]
Replaces the whole `Base header object
set_request_uri [Nethttp_client.http_call]
Sets the request URI.
set_response_body_storage [Nethttp_client.http_call]
Sets how to create the response body
set_socks5_proxy [Netftp_client.ftp_client]
Sets that a SOCKS version 5 proxy is used at this host and port.
set_socks5_proxy [Nethttp_client.pipeline]
Sets that a SOCKS version 5 proxy is used at this host and port.
set_state [Nethttpd_kernel.http_response]
Sets the state
set_state [Uq_engines_compat.engine_mixin]
set_state [Uq_engines.engine_mixin]
set_status [Netcgi1_compat.Netcgi_env.cgi_environment]
set_status [Netcgi.cgi_environment]
Sets the response status.
set_status [Netcgi_common.cgi_environment]
set_timeout [Rpc_transport.rpc_multiplex_controller]
If there is no read or write activity for the passed number of seconds, the notify callback is invoked.
set_tls_cache [Nethttp_client.pipeline]
Sets the TLS cache (NB.
set_transport_layer [Nethttp_client.http_call]
Sets the transport layer.
set_transport_proxy [Nethttp_client.pipeline]
set_transport_proxy id host port auth ptype: Sets a special proxy for the transport identified by id.
set_transport_proxy_from_environment [Nethttp_client.pipeline]
Like set_proxy_from_environment, this method inspects environment variables and configures the proxy settings.
set_value [Netcgi1_compat.Netcgi_types.cgi_argument]
Dealing with the arguments is the task of an higher order library.
set_value [Netmime.mime_body]
Sets the value.
set_value [Netcgi.rw_cgi_argument]
set_value [Netcgi_common.rw_cgi_argument]
set_var [Netplex_types.container]
Sets the value of a container variable
setup [Unixqueue_select.sb_event_system]
setup_e [Nethttp_client.transport_channel_type]
setup fd trans tmo tmo_x host port esys tls_cache: Create or configure a communication circuit over the file descriptor fd that can be driven by the returned multiplex controller object.
shut_down [Uq_engines_compat.wrapped_datagram_socket]
shut_down [Uq_engines_compat.server_endpoint_acceptor]
shut_down [Uq_datagram.wrapped_datagram_socket]
Close the descriptor, shuts down any further needed resources
shut_down [Uq_server.server_endpoint_acceptor]
The server endpoint is shut down such that no further connections are possible.
shut_down [Uq_engines.wrapped_datagram_socket]
shut_down [Uq_engines.server_endpoint_acceptor]
shutdown [Netplex_types.workload_manager]
Called by the controller to notify the manager about a shutdown
shutdown [Netplex_types.container]
Initiates a shutdown of the container.
shutdown [Netplex_types.processor_hooks]
A user-supplied function that is called when a shutdown notification arrives.
shutdown [Netplex_types.socket_controller]
Closes the socket service forever, and initiates a shutdown of all containers serving this type of service.
shutdown [Netplex_types.socket_service]
Shuts down the master sockets
shutdown [Netplex_types.controller]
Initiates a shutdown of all containers.
shutdown [Nethttpd_kernel.http_protocol]
Shuts the socket down.
shutting_down [Uq_engines_compat.multiplex_controller]
shutting_down [Uq_multiplex.multiplex_controller]
True iff the shutdown is in progress
shutting_down [Uq_engines.multiplex_controller]
signal [Netsys_oothr.condition]
In a multi-threaded program: Signal one process that the condition holds.
signal [Uq_engines_compat.signal_engine]
signal [Uq_engines.signal_engine]
signature [Netx509.x509_certificate]
The signature
signature_algorithm [Netx509.x509_certificate]
The algorithm of the signature (OID, and algorithm-specific parameters)
single_threaded [Netsys_oothr.mtprovider]
Whether this is a single-threaded program.
size [Netsys_digests.digest]
The size of the digest string in bytes
size [Netfs.stream_fs]
Returns the size of a file.
size [Nethttp_fs.http_stream_fs]
skip [Netstream.in_obj_stream]
Skip the n bytes of the stream.
skip_challenge [Nethttp_client.auth_handler]
If true, this method allows to skip the challenge entirely for authentication.
skip_challenge_session [Nethttp_client.auth_handler]
Create a session for the case that the challenge was skipped
so_keepalive [Netplex_types.protocol]
Whether to set the keep-alive socket option
socket_directory [Netplex_types.controller_config]
The directory where Unix domain sockets are created.
socket_domain [Uq_engines_compat.wrapped_datagram_socket]
socket_domain [Uq_datagram.wrapped_datagram_socket]
socket_domain [Uq_engines.wrapped_datagram_socket]
socket_protocol [Uq_engines_compat.wrapped_datagram_socket]
socket_protocol [Uq_datagram.wrapped_datagram_socket]
socket_protocol [Uq_engines.wrapped_datagram_socket]
socket_service [Netplex_types.container]
socket_service_config [Netplex_types.socket_service]
The configuration
socket_service_name [Netplex_types.container]
socket_type [Uq_engines_compat.wrapped_datagram_socket]
socket_type [Uq_datagram.wrapped_datagram_socket]
socket_type [Uq_engines.wrapped_datagram_socket]
sockets [Netplex_types.socket_service]
A socket_service consists of a list of supported protocols which are identified by a name.
source [Netcgi_modtpl.template]
Return the original source code for the template.
source [Unixqueue_select.sb_event_system]
spec [Netaddress.mailbox]
The formal address specification
start [Netplex_types.container]
Internal Method.
start_containers [Netplex_types.socket_controller]
start_mem_reading [Uq_engines_compat.multiplex_controller]
start_mem_reading [Uq_multiplex.multiplex_controller]
Same as start_reading, but puts the data into a memory buffer.
start_mem_reading [Uq_engines.multiplex_controller]
start_mem_writing [Uq_engines_compat.multiplex_controller]
start_mem_writing [Uq_multiplex.multiplex_controller]
Same as start_writing, but takes the data from a memory buffer.
start_mem_writing [Uq_engines.multiplex_controller]
start_reading [Rpc_transport.rpc_multiplex_controller]
Start reading from the connection.
start_reading [Uq_engines_compat.multiplex_controller]
start_reading [Uq_multiplex.multiplex_controller]
Start reading from the connection.
start_reading [Uq_engines.multiplex_controller]
start_shutting_down [Rpc_transport.rpc_multiplex_controller]
Start shutting down the connection.
start_shutting_down [Uq_engines_compat.multiplex_controller]
start_shutting_down [Uq_multiplex.multiplex_controller]
Start shutting down the connection.
start_shutting_down [Uq_engines.multiplex_controller]
start_thread [Netplex_types.parallelizer]
start_thread f l_close l_share name logger: Starts a new thread or process and calls f thread in that context.
start_tls [Nettelnet_client.telnet_session]
Switch to TLS.
start_writing [Rpc_transport.rpc_multiplex_controller]
Starts writing the message.
start_writing [Uq_engines_compat.multiplex_controller]
start_writing [Uq_multiplex.multiplex_controller]
Start writing to the connection.
start_writing [Uq_engines.multiplex_controller]
start_writing_eof [Uq_engines_compat.multiplex_controller]
start_writing_eof [Uq_multiplex.multiplex_controller]
Start writing the EOF marker to the connection.
start_writing_eof [Uq_engines.multiplex_controller]
starttls [Netsmtp.client]
Sends STARTTLS, and negotiates a secure connection.
startup_directory [Netplex_types.container]
The current directory at Netplex startup time (same view as controller)
startup_directory [Netplex_types.socket_service]
The current directory at Netplex startup time (same view as controller)
startup_directory [Netplex_types.controller]
The current directory at startup time
startup_timeout [Netplex_types.socket_service_config]
After this many seconds the container must have finished the post_start_hook.
stat [Netpop.client]
Returns information about the current mailbox as tuple (count,size,ext) where count is the number of messages in the mailbox, size is the size of the mailbox in octets, and ext is any server extension data.
state [Rpc_client.auth_protocol]
The state of the authentication protocol: `Emit: The client needs to emit another token, `Receive xid: The client waits for another token (with session identifier xid), `Done session: The protocol is finished and session can be used for authenticating, `Error: Something went wrong.
state [Netplex_types.socket_controller]
The current state
state [Nethttpd_kernel.http_response]
Reports the state.
state [Netpop.client]
Current state of this session.
state [Netftp_client.ftp_client_pi]
The state in the sense of Uq_engines.
state [Uq_engines_compat.engine_mixin]
state [Uq_engines_compat.engine]
state [Uq_engines.engine_mixin]
state [Uq_engines.engine]
Returns the state of the engine
state [Uq_resolver.engine]
status [Nethttp_client.http_call]
The condensed status
stls [Netpop.client]
Sends STLS (STARTTLS), and negotiates a secure connection.
stop_containers [Netplex_types.socket_controller]
store [Netmime.mime_body_ro]
Where the body is actually stored.
store [Netcgi1_compat.Netcgi_types.cgi_argument]
store [Netcgi.cgi_argument]
Tells whether the argument is stored in memory (as a string) or as a file (the argument of `File being the filename).
store [Netcgi_common.cgi_argument]
string [Netx509.directory_name]
The DN as string (RFC 4514)
string_param [Netplex_types.config_file]
subject [Netx509.x509_certificate]
The DN of the subject
subject_unique_id [Netx509.x509_certificate]
The unique ID of the subject
supported_ptypes [Netplex_kit.v_processor]
supported_ptypes [Netplex_types.processor]
The supported parallelization types
supports_aead [Netsys_ciphers.cipher]
Whether this cipher integrates authentication
supports_aead [Netsys_ciphers.cipher_ctx]
Whether this cipher integrates authentication
supports_aead [Netchannels_crypto.crypto_in_filter]
Whether the cipher supports authentication, and will provide a MAC
supports_aead [Netchannels_crypto.crypto_out_filter]
Whether the cipher supports authentication, and will provide a MAC
supports_half_open_connection [Uq_engines_compat.multiplex_controller]
supports_half_open_connection [Uq_multiplex.multiplex_controller]
Whether the underlying transport mechanism can close the write side of the connection only (half-open connection).
supports_half_open_connection [Uq_engines.multiplex_controller]
supports_mdtm [Netftp_client.ftp_client_pi]
Whether the `MDTM command is supported.
supports_mlst [Netftp_client.ftp_client_pi]
Whether the `MLST and `MLSD commands are supported
supports_size [Netftp_client.ftp_client_pi]
Whether the `SIZE command is supported.
supports_tls [Netftp_client.ftp_client_pi]
Whether TLS is supported
supports_tvfs [Netftp_client.ftp_client_pi]
Whether TVFS filenames are supported
supports_utf8 [Netftp_client.ftp_client_pi]
Whether the UTF-8 extension is understood by the server (RFC 2640)
symlink [Netfs.stream_fs]
symlink flags oldpath newpath: Creates a symlink.
symlink [Nethttp_fs.http_stream_fs]
sys_id [Netplex_types.par_thread]
Returns a system-dependent identifier for the thread: `Thread id: The id as returned by Thread.id, `Process id: The id is the process ID
sys_id [Netplex_types.controller]
The thread running the controller
system [Netplex_types.container]
An RPC client that can be used to send messages to the controller.
system_monitor [Netplex_types.container]
The thread monitor protecting the system RPC client
system_shutdown [Netplex_types.processor_hooks]
A user-supplied function that is called when a system shutdown notification arrives.

T
table [Netcgi_modtpl.template]
Set a table in the template.
target_name [Netsys_gssapi.client_config]
tcp_nodelay [Netplex_types.protocol]
Whether to set the TCP_NODELAY option
test [Netfs.stream_fs]
Returns whether the test is true.
test [Nethttp_fs.http_stream_fs]
test_coverage [Nethttpd_kernel.http_protocol]
For testing: returns a list of tokens indicating into which cases the program ran.
test_list [Netfs.stream_fs]
Similar to test but this function performs all tests in the list at once, and returns a bool for each test.
test_list [Nethttp_fs.http_stream_fs]
time [Netsys_gssapi.server_props]
Actual context lifetime
time [Netsys_gssapi.client_props]
Actual context lifetime
timeout [Nethttpd_kernel.http_protocol]
Process a timeout condition as cycle does
tls_endpoint [Netchannels_crypto.tls_channel]
tls_endpoint [Netpop.client]
Returns the TLS endpoint (after STARTTLS)
tls_endpoint [Netsmtp.client]
Returns the TLS endpoint (after STARTTLS)
tls_session [Uq_engines_compat.multiplex_controller]
tls_session [Uq_multiplex.multiplex_controller]
If TLS is enabled, this returns (session_id, session_data).
tls_session [Uq_engines.multiplex_controller]
tls_session_data [Nettelnet_client.telnet_session]
TLS session data (if on)
tls_session_props [Rpc_transport.rpc_multiplex_controller]
The TLS session properties (if TLS is enabled)
tls_session_props [Nethttpd_kernel.http_protocol]
If TLS is enabled, this returns the session properties.
tls_session_props [Nethttpd_types.request_info]
The TLS properties
tls_session_props [Nethttpd_types.v_extended_environment]
The TLS session properties if TLS is active
tls_session_props [Netpop.client]
Returns the TLS session properties (after STARTTLS)
tls_session_props [Netsmtp.client]
Returns the TLS session properties (after STARTTLS)
tls_session_props [Nettelnet_client.telnet_session]
TLS session properties (if on)
tls_session_props [Nethttp_client.http_call]
If TLS is enabled, this returns the session properties
tls_session_props [Uq_engines_compat.multiplex_controller]
tls_session_props [Uq_multiplex.multiplex_controller]
If TLS is enabled, this returns the session properties.
tls_session_props [Uq_engines.multiplex_controller]
tls_set_cache [Nethttpd_kernel.http_protocol_hooks]
Sets the functions for accessing the session cache
tls_stashed_endpoint [Uq_engines_compat.multiplex_controller]
tls_stashed_endpoint [Uq_multiplex.multiplex_controller]
Returns the TLS endpoint in stashed form.
tls_stashed_endpoint [Uq_engines.multiplex_controller]
to_channel [Netcgi_modtpl.template]
Write the template to a channel.
to_string [Netcgi_modtpl.template]
Return the template as a string.
top [Netpop.client]
Returns the message header plus a limited number of lines of the message body.
transfer_encoding [Nethttpd_kernel.http_response]
Returns the selected transfer encoding.
translate [Netftp_fs.ftp_stream_fs]
Translates a path into a URL
translate [Nethttp_fs.http_stream_fs]
Translates a path into a URL
transport_layer [Nethttp_client.pipeline]
Reports the current transport of this call
transport_user [Rpc_server.auth_details]
tree [Netplex_types.config_file]
try_lock [Netsys_oothr.mutex]
In a multi-threaded program: Tries to immediately lock the mutex, and returns whether the lock could be obtained.
typ [Netmcore.compute_resource]
which type of resource

U
uidl [Netpop.client]
Returns the unique identifier(s) for an optional message number or for all messages in the current mailbox.
unlink [Netsys_pmanage.pmanage]
Delete all registered objects
unlock [Netsys_oothr.mutex]
In a multi-threaded program: Unlocks a mutex.
unlock [Nethttpd_reactor.internal_environment]
unregister_file [Netsys_pmanage.pmanage]
Unregister a temporary file
unregister_posix_sem [Netsys_pmanage.pmanage]
Unregister a POSIX named semaphore identified by this path
unregister_posix_shm [Netsys_pmanage.pmanage]
Unregister a POSIX shared memory object identified by this path
unregister_sem_cont [Netsys_pmanage.pmanage]
Unregister a semaphore container (see Netsys_sem)
unwrap [Netsys_gssapi.poly_gss_api]
Note that the output_message can be a buffer of different type (string vs.
update [Netsys_global.propagator]
update name version: checks whether there is a new value of the variable name with a version higher than the passed version.
update [Nettelnet_client.telnet_session]
If there are commands in the output queue, the event system is signaled that this client wants to do network I/O.
update_argument [Netcgi1_compat.Netcgi_types.cgi_activation]
update_detail [Netplex_types.container]
Update the detail string output for the netplex.connections admin message
update_field [Netmime.mime_header]
update_multiple_argument [Netcgi1_compat.Netcgi_types.cgi_activation]
update_multiple_field [Netmime.mime_header]
url [Netcgi1_compat.Netcgi_types.cgi_activation]
url [Netcgi.cgi]
Returns the URL of the current CGI-like script.
url [Netcgi_common.cgi]
The following environment properties must be available for this method to work properly (please make sure your connector provides them; the CGI spec make them compulsory anyway): cgi_server_name, cgi_server_port, cgi_script_name, cgi_path_info
user [Netpop.client]
Specifies the name of the mailbox the client would like to open using plain-text authentication.
user [Nethttp_client.key]
The user name (UTF-8)
user_agent [Netcgi1_compat.Netcgi_env.cgi_environment]
user_agent [Netcgi.cgi_environment]
This is a convenience method that returns the "User-agent" field of the HTTP request header.
user_agent [Netcgi_common.cgi_environment]

V
valid_not_after [Netx509.x509_certificate]
Expiration time as seconds since the epoch ("notAfter" field)
valid_not_before [Netx509.x509_certificate]
Activation time as seconds since the epoch ("notBefore" field)
value [Netmime.mime_body_ro]
The value method returns the _decoded_ body, i.e.
value [Netldap.ldap_result]
the value when code=`Success.
value [Netcgi1_compat.Netcgi_types.cgi_argument]
value [Netcgi.cgi_argument]
The value of the argument, after all transfer encodings have been removed.
value [Netcgi_common.cgi_argument]
var [Netplex_types.container]
Returns the value of a container variable or Not_found.
verifier [Rpc_server.auth_details]
verify_mic [Netsys_gssapi.poly_gss_api]
version [Rpc_server.auth_details]
version [Netx509.x509_certificate]
The "version" field, 1 to 3

W
wait [Netsys_oothr.condition]
In a multi-threaded program: Wait for the condition to be true and use the mutex to protect this situation.
wait [Netsys_pollset.pollset]
Wait for events, and return the output events matching the event mask.
waiting_for_next_message [Nethttpd_kernel.http_protocol]
Whether the kernel is currently waiting for the beginning of a new arriving HTTP request.
want [Netstream.in_obj_stream]
Increases the length of the window such that the length is at least the passed number of bytes or that the window reaches EOF (whatever happens first).
want_another_block [Netstream.in_obj_stream]
The same as: want block_size
watch_shutdown [Netplex_types.par_thread]
Called by the controller if it thinks the container is down.
when_blocking [Unixqueue_select.sb_event_system]
when_blocking [Unixqueue.event_system]
window [Netstream.in_obj_stream]
The look-ahead window.
window_at_eof [Netstream.in_obj_stream]
Whether the window is at eof
window_length [Netstream.in_obj_stream]
Returns the length of the window
workload_hook [Netplex_types.processor_hooks]
A user-supplied function that is called when the workload changes, i.e.
wrap [Netsys_gssapi.poly_gss_api]
output_message_preferred_type: see unwrap
wrap_size_limit [Netsys_gssapi.poly_gss_api]
write [Netfs.stream_fs]
write flags filename: Opens (and optionally creates) the filename for writing, and returns the output stream.
write [Nethttp_fs.http_stream_fs]
Additional flag: `Header h: Set these headers in the submitted PUT request
write_file [Netfs.stream_fs]
write_file flags filename localfile: Opens the file filename for writing, and copies the contents of the localfile to it.
write_file [Nethttp_fs.http_stream_fs]
Additional flag: `Header h: Set these headers in the submitted PUT request
writing [Rpc_transport.rpc_multiplex_controller]
True iff there is a writer
writing [Uq_engines_compat.multiplex_controller]
writing [Uq_multiplex.multiplex_controller]
True iff there is a writer
writing [Uq_engines.multiplex_controller]
wrote_eof [Uq_engines_compat.multiplex_controller]
wrote_eof [Uq_multiplex.multiplex_controller]
Whether the EOF marker has been written
wrote_eof [Uq_engines.multiplex_controller]

X
xid [Rpc_server.auth_details]

Y
yield [Netsys_oothr.mtprovider]
In a multi-threaded program: gives a hint that another thread should better run now.
ocamlnet-4.1.2/doc/html-main/Nettelnet_client.html0000644000175000017500000012656312731530352020603 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettelnet_client

Module Nettelnet_client

module Nettelnet_client: sig .. end
Telnet client

This is a Telnet client providing the basic Telnet services. It supports sending and receiving data (asynchronously), and the negotiation of Telnet options, but it does not implement any option.


exception Telnet_protocol of exn
Wrapper for exceptions that already passed the exception handler.
type telnet_command = 
| Telnet_data of string (*
User data
*)
| Telnet_nop (*
No operation
*)
| Telnet_dm (*
data mark
*)
| Telnet_brk (*
break
*)
| Telnet_ip (*
interrupt process
*)
| Telnet_ao (*
abort output
*)
| Telnet_ayt (*
are you there?
*)
| Telnet_ec (*
erase character
*)
| Telnet_el (*
erase line
*)
| Telnet_ga (*
Go ahead
*)
| Telnet_sb of char (*
Begin of subnegotiation
*)
| Telnet_se (*
End of subnegotation
*)
| Telnet_will of char (*
Acknowledges that option is in effect
*)
| Telnet_wont of char (*
Acknowledges that option is rejected
*)
| Telnet_do of char (*
Requests to turn on an option
*)
| Telnet_dont of char (*
Requests to turn off an option
*)
| Telnet_unknown of char (*
Unknown command
*)
| Telnet_eof (*
End of file
*)
| Telnet_timeout (*
Timeout event
*)
A telnet_command is the interpretation of the octets in a Telnet session, i.e. it is one level above the octet stream. See RFC 854 for an explanation what the commands mean. Telnet_data represents the data chunks between the commands. Note that you do not need to double octets having value 255; this is done automatically. Telnet_unknown represents any command not covered by RFC 854, for example the End-of-record-mark (introduced in RFC 885) would be Telnet_unknown '\239'. Telnet_eof represents the end of the octet stream, useable in both directions. Telnet_timeout is added to the input queue if I/O has not been happened for the configured period of time.
type telnet_options = {
   connection_timeout : float;
   verbose_input : bool;
   verbose_output : bool;
}
telnet_options: modifies the behaviour of the client. Do not mix these options up with the options negotiated with the remote side.

  • connection_timeout: After this period of time (in seconds) a Telnet_timeout pseudo-command is added to the input queue, and the connection is aborted.
  • verbose_input: Enables printing of input events to Netlog.Debug.
  • verbose_output: Enables printing of output events to Netlog.Debug

type telnet_negotiated_option = 
| Telnet_binary (*
see RFC 856
*)
| Telnet_echo (*
see RFC 857
*)
| Telnet_suppress_GA (*
see RFC 858
*)
| Telnet_status (*
see RFC 859
*)
| Telnet_timing_mark (*
see RFC 860
*)
| Telnet_ext_opt_list (*
see RFC 861
*)
| Telnet_end_of_rec (*
see RFC 885
*)
| Telnet_window_size (*
see RFC 1073
*)
| Telnet_term_speed (*
see RFC 1079
*)
| Telnet_term_type (*
see RFC 1091
*)
| Telnet_X_display (*
see RFC 1096
*)
| Telnet_linemode (*
see RFC 1184
*)
| Telnet_flow_ctrl (*
see RFC 1372
*)
| Telnet_auth (*
see RFC 1416
*)
| Telnet_new_environ (*
see RFC 1572 and 1571
*)
| Telnet_option of int (*
all other options
*)
telnet_negotiated_option: names for the most common options, and the generic name Telnet_option for other options.
type telnet_option_state = 
| Not_negotiated
| Accepted
| Rejected (*
*)
An option has one of three states:
  • Not_negotiated: There was no negotiation about the option. This means that the option is turned off (but this client is allowed to reject it explicitly)
  • Accepted: Both sides have accepted the option.
  • Rejected: One side has rejected the option. This also means that the option is off, but the client refuses to send further acknoledgements that the option is off (to avoid endless negotiation loops).

val char_of_option : telnet_negotiated_option -> char
Converts the option name to the character representing it on the octet-stream level.
val option_of_char : char -> telnet_negotiated_option
Converts a character representing an option to the internal option name.
type telnet_connector = 
| Telnet_connect of (string * int)
| Telnet_socket of Unix.file_descr (*
*)
Connectors:
  • Telnet_connect(host,port): The client connects to this port.
  • Telnet_socket s: The client uses an already connected socket.
Why Telnet_socket? Telnet is a symmetrical protocol; client and servers implement the same protocol features (the only difference is the environment: a client is typically connected with a real terminal; a server is connected with a pseudo terminal). This simply means that this implementation of a client can also be used as a server implementation. You need only to add code which accepts new connections and which passes these connections over to a telnet_session object via Telnet_socket.
class telnet_session : object .. end
A telnet session

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netplex_mp.mp.html0000644000175000017500000004107212731530352021061 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mp.mp ?keep_fd_open:bool ->
?terminate_tmo:int -> unit -> Netplex_types.parallelizer
ocamlnet-4.1.2/doc/html-main/type_Netchannels.raw_in_channel.html0000644000175000017500000004160312731530352023543 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_in_channel object
  method close_in : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method pos_in : int
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.delete_call.html0000644000175000017500000004061012731530352023550 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.delete_call Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Netdn.DN_string_generic.html0000644000175000017500000004521412731530352021726 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdn.DN_string_generic

Functor Netdn.DN_string_generic

module DN_string_generic: 
functor (L : AT_LOOKUP) -> DN_string
For a given attribute lookup module L this module provides parser and printer for distinguished names in string format (RFC 4514).
Parameters:
L : AT_LOOKUP


For a given attribute lookup module L this module provides parser and printer for distinguished names in string format (RFC 4514).

This implementation is restricted to attributes using the ASN.1 types PrintableString, TeletexString, IA5String, UniversalString, BMPString, and UTF8String. It is not possible to parse hexencoded strings ('#' notation).

(NB. We'd need a generic BER printer for supporting this.)

val parse : string -> Netdn.dn
Parses the string (or fails). The string must use UTF-8 encoding.
val print : Netdn.dn -> string
Prints the DN (cannot fail), using UTF-8 encoding
ocamlnet-4.1.2/doc/html-main/Nettls_nettle_bindings.html0000644000175000017500000006050612731530352021776 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_nettle_bindings

Module Nettls_nettle_bindings

module Nettls_nettle_bindings: sig .. end
Bindings of a C library

type net_nettle_cipher_t 
type net_nettle_cipher_ctx_t 
type net_nettle_gcm_aes_ctx_t 
type net_nettle_hash_t 
type net_nettle_hash_ctx_t 
val net_nettle_ciphers : unit -> net_nettle_cipher_t array
val net_ext_ciphers : unit -> net_nettle_cipher_t array
val net_nettle_cipher_name : net_nettle_cipher_t -> string
val net_nettle_create_cipher_ctx : net_nettle_cipher_t ->
net_nettle_cipher_ctx_t
val net_nettle_set_encrypt_key : net_nettle_cipher_t ->
net_nettle_cipher_ctx_t -> Bytes.t -> unit
val net_nettle_set_decrypt_key : net_nettle_cipher_t ->
net_nettle_cipher_ctx_t -> Bytes.t -> unit
val net_nettle_encrypt : net_nettle_cipher_t ->
net_nettle_cipher_ctx_t ->
int -> Netsys_mem.memory -> Netsys_mem.memory -> unit
val net_nettle_decrypt : net_nettle_cipher_t ->
net_nettle_cipher_ctx_t ->
int -> Netsys_mem.memory -> Netsys_mem.memory -> unit
val net_nettle_gcm_aes_init : unit -> net_nettle_gcm_aes_ctx_t
val nettle_gcm_aes_set_key : net_nettle_gcm_aes_ctx_t -> Bytes.t -> unit
val nettle_gcm_aes_set_iv : net_nettle_gcm_aes_ctx_t -> Bytes.t -> unit
val nettle_gcm_aes_update : net_nettle_gcm_aes_ctx_t -> Bytes.t -> unit
val nettle_gcm_aes_encrypt : net_nettle_gcm_aes_ctx_t ->
int -> Netsys_mem.memory -> Netsys_mem.memory -> unit
val nettle_gcm_aes_decrypt : net_nettle_gcm_aes_ctx_t ->
int -> Netsys_mem.memory -> Netsys_mem.memory -> unit
val nettle_gcm_aes_digest : net_nettle_gcm_aes_ctx_t -> Bytes.t -> unit
val net_have_gcm_aes : unit -> bool
val net_nettle_hashes : unit -> net_nettle_hash_t array
val net_nettle_hash_name : net_nettle_hash_t -> string
val net_nettle_create_hash_ctx : net_nettle_hash_t ->
net_nettle_hash_ctx_t
val net_nettle_hash_init : net_nettle_hash_t ->
net_nettle_hash_ctx_t -> unit
val net_nettle_hash_update : net_nettle_hash_t ->
net_nettle_hash_ctx_t -> Netsys_mem.memory -> unit
val net_nettle_hash_digest : net_nettle_hash_t ->
net_nettle_hash_ctx_t -> Bytes.t -> unit
ocamlnet-4.1.2/doc/html-main/Netchannels.output_filter-c.html0000644000175000017500000004335412731530352022665 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_filter

Class Netchannels.output_filter

class output_filter : io_obj_channel -> out_obj_channel -> out_obj_channel
An output_filter filters the data written to it through the io_obj_channel (usually a pipe), and writes the filtered data to the passed out_obj_channel.

If the filter is closed, the io_obj_channel will be closed, too, but not the destination out_obj_channel (so you can still append further data).


ocamlnet-4.1.2/doc/html-main/type_Netmcore_queue.html0000644000175000017500000005465112731530352021322 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_queue sig
  type ('e, 'h) squeue
  type ('e, 'h) squeue_descr
  exception Empty
  val create : Netmcore.res_id -> '-> ('e, 'h) Netmcore_queue.squeue
  val push : '-> ('e, 'h) Netmcore_queue.squeue -> unit
  val pop_p : ('e, 'h) Netmcore_queue.squeue -> ('-> 'a) -> 'a
  val pop_c : ('e, 'h) Netmcore_queue.squeue -> 'e
  val top_p : ('e, 'h) Netmcore_queue.squeue -> ('-> 'a) -> 'a
  val top_c : ('e, 'h) Netmcore_queue.squeue -> 'e
  val clear : ('e, 'h) Netmcore_queue.squeue -> unit
  val is_empty : ('e, 'h) Netmcore_queue.squeue -> bool
  val length : ('e, 'h) Netmcore_queue.squeue -> int
  val iter : ('-> unit) -> ('e, 'h) Netmcore_queue.squeue -> unit
  val fold : ('-> '-> 'a) -> '-> ('e, 'h) Netmcore_queue.squeue -> 'a
  val header : ('e, 'h) Netmcore_queue.squeue -> 'h
  val heap : ('a, 'b) Netmcore_queue.squeue -> Obj.t Netmcore_heap.heap
  val descr_of_squeue :
    ('e, 'h) Netmcore_queue.squeue -> ('e, 'h) Netmcore_queue.squeue_descr
  val squeue_of_descr :
    Netmcore.res_id ->
    ('e, 'h) Netmcore_queue.squeue_descr -> ('e, 'h) Netmcore_queue.squeue
end
ocamlnet-4.1.2/doc/html-main/Netchannels_tut.html0000644000175000017500000014025212731530352020430 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_tut

Netchannels_tut


Netchannels Tutorial

Netchannels is one of the basic modules of this library, because it provides some very basic abstractions needed for many other functions of the library. The key abstractions Netchannels defines are the types in_obj_channel and out_obj_channel. Both are class types providing sequential access to byte streams, one for input, one for output. They are comparable to the types in_channel and out_channel of the standard library that allow access to files. However, there is one fundamental difference: in_channel and out_channel are restricted to resources that are available through file descriptors, whereas in_obj_channel and out_obj_channel are just class types, and by providing implementations for them any kind of resources can be accessed.

Motivation

In some respect, Netchannels fixes a deficiency of the standard library. Look at the module Printf which defines six variants of the printf function:

val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a
val printf : ('a, out_channel, unit) format -> 'a
val eprintf : ('a, out_channel, unit) format -> 'a
val sprintf : ('a, unit, string) format -> 'a
val bprintf : Buffer.t -> ('a, Buffer.t, unit) format -> 'a
val kprintf : (string -> string) -> ('a, unit, string) format -> 'a
It is possible to write into six different kinds of print targets. The basic problem of this style is that the provider of a service function like printf must define it for every commonly used print target. The other solution is that the provider defines only one version of the service function, but that the caller of the function arranges the polymorphism. A Netchannels-aware Printf would have only one variant of printf:
val printf : out_obj_channel -> ('a, out_obj_channel, unit) format -> 'a
The caller would create the right out_obj_channel object for the real print target:
let file_ch = new output_file (file : out_channel) in
printf file_ch ...
(printing into files), or:
let buffer_ch = new output_buffer (buf : Buffer.t) in
printf buffer_ch ...
(printing into buffers). Of course, this is only a hypothetical example. The point is that this library defines many parsers and printers, and that it is really a simplification for both the library and the user of the library to have this object encapsulation of I/O resources.

Programming with in_obj_channel

For example, let us program a function reading a data source line by line, and returning the sum of all lines which must be integer numbers. The argument ch is an open Netchannels.in_obj_channel, and the return value is the sum:

let sum_up (ch : in_obj_channel) =
  let sum = ref 0 in
  try
    while true do
      let line = ch # input_line() in
      sum := !sum + int_of_string line
    done;
    assert false
  with
    End_of_file ->
      !sum
The interesting point is that the data source can be anything: a channel, a string, or any other class that implements the class type in_obj_channel.

This expression opens the file "data" and returns the sum of this file:

let ch = new input_channel (open_in "data") in
sum_up ch
The class Netchannels.input_channel is an implementation of the type in_obj_channel where every method of the class simply calls the corresponding function of the module Pervasives. (By the way, it would be a good idea to close the channel afterwards: ch#close_in(). We will discuss that below.)

This expression sums up the contents of a constant string:

let s = "1\n2\n3\n4" in
let ch = new input_string s in
sum_up ch
The class Netchannels.input_string is an implementation of the type in_obj_channel that reads from a string that is treated like a channel.

The effect of using the Netchannels module is that the same implementation sum_up can be used to read from multiple data sources, as it is sufficient to call the function with different implementations of in_obj_channel.

The details of in_obj_channel

The properties of any class that implements in_obj_channel can be summarized as follows:

  • After the object has been created (new), the netchannel is open. The netchannel remains open until it is explicitly closed (method close_in : unit -> unit). When you call a method of a closed netchannel, the exception Closed_channel is raised (even if you try to close the channel again).
  • The methods
     
      really_input : string -> int -> int -> unit
      input_char : unit -> char
      input_byte : unit -> int
      input_line : unit -> string
      
    work like their counterparts of the standard library. In particular, the end of file condition is signaled by rasising End_of_file.
  • The method
      input : string -> int -> int -> int
      
    works like its counterpart of the standard library, except that the end of the file is also signaled by End_of_file, and not by the return value 0.
  • The method pos_in : int returns the current byte position of the channel in a way that is logically consistent with the input methods: After reading n bytes, the method must return a position that is increased by n. Usually the position is zero after the object has been created, but this is not specified. Positions are available even for file descriptors that are not seekable.
  • There is intentionally no seek_in method. Seekable channels are currently out of scope, as netstring focuses on non-seekable channels.

Programming with out_obj_channel

The following function outputs the numbers of an int list sequentially on the passed netchannel:

 
let print_int_list (ch : out_obj_channel) l =
  List.iter
    (fun n ->
       ch # output_string (string_of_int n);
       ch # output_char '\n';
    )
    l;
  ch # flush()
The following statements write the output into a file:
let ch = new output_channel (open_out "data") in
print_int_list ch [1;2;3]
And these statements write the output into a buffer:
let b = Buffer.create 16 in
let ch = new output_buffer b in
print_int_list ch [1;2;3]

Again, the caller of the function print_int_list determines the type of the output destination, and you do not need several functions for several types of destination.

The details of out_obj_channel

The properties of any class that implements out_obj_channel can be summarized as follows:

  • After the object has been created (new), the netchannel is open. The netchannel remains open until it is explicitly closed (method close_out : unit -> unit). When you call a method of a closed netchannel, the exception Closed_channel is raised (even if you try to close the channel again).
  • The methods
      output : string -> int -> int -> int
      really_output : string -> int -> int -> unit
      output_char : char -> unit
      output_byte : int -> unit
      output_string : string -> unit
      
    work like their counterparts of the standard library. There is usually an output buffer, but this is not specified. By calling flush : unit -> unit, the contents of the output buffer are forced to be written to the destination.
  • The method
      output_buffer : Buffer.t -> unit
      
    works like Buffer.output_channel, i.e. the contents of the buffer are printed to the channel.
  • The method
      output_channel : ?len:int -> in_obj_channel -> unit
      
    reads data from the argument in_obj_channel and prints them to the output channel. By default, the input channel is read until the EOF position. If the len argument is passed, at most this number of bytes are copied from the input channel to the output channel. The input channel remains open in all cases.
  • The method pos_out : int returns byte positions that are logically consistent: After writing n bytes, the method must return a position that is increased by n. Usually the position is zero after the object has been created, but this is not specified. Positions are available even for file descriptors that are not seekable.
  • There is intentionally no seek_out method. Seekable channels are currently out of scope, as netstring focuses on non-seekable channels.

How to close channels

As channels may use file descriptors for their implementation, it is very important that all open channels are closed after they have been used; otherwise the operating system will certainly get out of file descriptors. The simple way,

let ch = new <channel_class> args ... in
... do something ...
ch # close_in() or close_out()
is dangerous because an exception may be raised between channel creation and the close_* invocation. An elegant solution is to use with_in_obj_channel and with_out_obj_channel, as in:
with_in_obj_channel             (* or with_out_obj_channel *)
  (new <channel_class> ...)
  (fun ch ->
     ... do something ...
  )
This programming idiom ensures that the channel is always closed after usage, even in the case of exceptions.

Complete examples:

let sum = with_in_obj_channel
            (new input_channel (open_in "data"))
            sum_up ;;

with_out_obj_channel
  (new output_channel (open_out "data"))
  (fun ch -> print_int_list ch ["1";"2";"3"]) ;;

Examples: HTML Parsing and Printing

In the Netstring library there are lots of parsers and printers that accept netchannels as data sources and destinations, respectively. One of them is the Nethtml module providing an HTML parser and printer. A few code snippets how to call them, just to get used to netchannels:

let html_document =
  with_in_obj_channel
    (new input_channel (open_in "myfile.html"))
    Nethtml.parse ;;
with_out_obj_channel
  (new output_channel (open_out "otherfile.html"))
  (fun ch -> Nethtml.write ch html_document) ;;

Transactional Output Channels

Sometimes you do not want that generated output is directly sent to the underlying file descriptor, but rather buffered until you know that everything worked fine. Imagine you program a network service, and you want to return the result only when the computations are successful, and an error message otherwise. One way to achieve this effect is to manually program a buffer:

let network_service ch =
  try
    let b = Buffer.create 16 in
    let ch' = new output_buffer b in
    ... computations, write results into ch' ...
    ch' # close_out;
    ch # output_buffer b
  with
    error ->
      ... write error message to ch ...
There is a better way to do this, as there are transactional output channels. This type of netchannels provide a buffer for all written data like the above example, and only if data is explicitly committed it is copied to the real destination. Alternatively, you can also rollback the channel, i.e. delete the internal buffer. The signature of the type trans_out_obj_channel is:
class type trans_out_obj_channel = object
  inherit out_obj_channel
  method commit_work : unit -> unit
  method rollback_work : unit -> unit
end
They have the same methods as out_obj_channel plus commit_work and rollback_work. There are two implementations, one of them keeping the buffer in memory, and the other using a temporary file:
let ch' = new buffered_trans_channel ch
And:
let ch' = new tempfile_trans_channel ch
In the latter case, there are optional arguments specifiying where the temporary file is created.

Now the network service would look like:

let network_service transaction_provider ch =
  try
    let ch' = transaction_provider ch in
    ... computations, write results into ch' ...
    ch' # commit_work();
    ch' # close_out()     (* implies ch # close_out() *)
  with
    error ->
      ch' # rollback_work();
      ... write error message to ch' ...
      ch' # commit_work();
      ch' # close_out()   (* implies ch # close_out() *)
You can program this function without specifying which of the two implementations is used. Just call this function as
network_service (new buffered_trans_channel) ch
or
network_service (new tempfile_trans_channel) ch
to determine the type of transaction buffer.

Some details:

  • The method commit_work copies all uncommitted data to the underlying channel, and flushes all buffers.
  • When rollback_work is called the uncommitted data are deleted.
  • The method flush does not have any effect.
  • The reported position adds the committed and the uncommitted amounts of data. This means that rollback_work resets the position to the value of the last commit_work call.
  • When the transactional channel is closed, the underlying channel is closed, too. By default, the uncommitted data is deleted, but the current implementations can optionally commit data in this case.

Pipes and Filters

The class pipe is an in_obj_channel and an out_obj_channel at the same time (i.e. the class has the type io_obj_channel). A pipe has two endpoints, one for reading and one for writing (similar in concept to the pipes provided by the operating system, but note that our pipes have nothing to do with the OS pipes). Of course, you cannot read and write at the same time, so there must be an internal buffer storing the data that have been written but not yet read. How can such a construction be useful? Imagine you have two routines that run alternately, and one is capable of writing into netchannels, and the other can read from a netchannel. Pipes are the missing communication link in this situation, because the writer routine can output into the pipe, and the reader routine can read from the buffer of the pipe. In the following example, the writer outputs numbers from 1 to 100, and the reader sums them up:

let pipe = new pipe() ;;
let k = ref 1 ;;
let writer() =
  if !k <= 100 then (
    pipe # output_string (string_of_int !k);
    incr k;
    if !k > 100 then pipe # close_out() else pipe # output_char '\n';
  ) ;;
let sum = ref 0 ;;
let reader() =
  let line = pipe # input_line() in
  sum := !sum + int_of_string line ;;
try
  while true do
    writer();
    reader()
  done
with
  End_of_file ->
    () ;;
The writer function prints the numbers into the pipe, and the reader function reads them in. By closing only the output end Of the pipe the writer signals the end of the stream, and the input_line method raises the exception End_of_file.

Of course, this example is very simple. What does happen when more is printed into the pipe than read? The internal buffer grows. What does happen when more is tried to read from the pipe than available? The input methods signal this by raising the special exception Buffer_underrun. Unfortunately, handling this exception can be very complicated, as the reader must be able to deal with partial reads.

This could be solved by using the Netstream module. A netstream is another extension of in_obj_channel that allows one to look ahead, i.e. you can look at the bytes that will be read next, and use this information to decide whether enough data are available or not. Netstreams are explained in another chapter of this manual.

Pipes have another feature that makes them useful even for "normal" programming. You can specify a conversion function that is called when data is to be transferred from the writing end to the reading end of the pipe. The module Netencoding.Base64 defines such a pipe that converts data: The class encoding_pipe automatically encodes all bytes written into it by the Base64 scheme:

let pipe = new Netencoding.Base64.encoding_pipe() ;;
pipe # output_string "Hello World";
pipe # close_out() ;;
let s = pipe # input_line() ;;
s has now the value "SGVsbG8gV29ybGQ=", the encoded form of the input. This kind of pipe has the same interface as the basic pipe class, and the same problems to use it. Fortunately, the Netstring library has another facility simplifying the usage of pipes, namely filters.

There are two kinds of filters: The class Netchannels.output_filter redirects data written to an out_obj_channel through a pipe, and the class Netchannels.input_filter arranges that data read from an in_obj_channel flows through a pipe. An example makes that clearer. Imagine you have a function write_results that writes the results of a computation into an out_obj_channel. Normally, this channel is simply a file:

with_out_obj_channel
  (new output_channel (open_out "results"))
  write_results
Now you want that the file is Base64-encoded. This can be arranged by calling write_results differently:
let pipe = new Netencoding.Base64.encoding_pipe() in
with_out_obj_channel
  (new output_channel (open_out "results"))
  (fun ch ->
    let ch' = new output_filter pipe ch in
    write_results ch';
    ch' # close_out()
  )
Now any invocation of an output method for ch' actually prints into the filter, which redirects the data through the pipe, thus encoding them, and finally passing the encoded data to the underlying channel ch. Note that you must close ch' to ensure that all data are filtered, it is not sufficient to flush output.

It is important to understand why filters must be closed to work properly. The problem is that the Base64 encoding converts triples of three bytes into quadruples of four bytes. Because not every string to convert is a multiple of three, there are special rules how to handle the exceeding one or two bytes at the end. The pipe must know the end of the input data in order to apply these rules correctly. If you only flush the filter, the exceeding bytes would simply remain in the internal buffer, because it is possible that more bytes follow. By closing the filter, you indicate that the definite end is reached, and the special rules for trailing data must be performed. \- Many conversions have similar problems, and because of this it is a good advice to always close output filters after usage.

There is not only the class output_filter but also input_filter. This class can be used to perform conversions while reading from a file. Note that you often do not need to close input filters, because input channels can signal the end by raising End_of_file, so the mentioned problems usually do not occur.

There are a number of predefined conversion pipes:

Defining Classes for Object Channels

As subtyping and inheritance are orthogonal in O'Caml, you can simply create your own netchannels by defining classes that match the in_obj_channel or out_obj_channel types. E.g.

class my_in_channel : in_obj_channel =
object (self)
  method input s pos len = ...
  method close_in() = ...
  method pos_in = ...
  method really_input s pos len = ...
  method input_char() = ...
  method input_line() = ...
  method input_byte() = ...
end

Of course, this is non-trivial, especially for the in_obj_channel case. Fortunately, the Netchannels module includes a "construction kit" that allows one to define a channel class from only a few methods. A closer look at in_obj_channel and out_obj_channel shows that some methods can be derived from more fundamental methods. The following class types include only the fundamental methods:

class type raw_in_channel = object
  method input : string -> int -> int -> int
  method close_in : unit -> unit
  method pos_in : int
end
class type raw_out_channel = object
  method output : string -> int -> int -> int
  method close_out : unit -> unit
  method pos_out : int
  method flush : unit -> unit
end

In order to define a new class, it is sufficient to define this raw version of the class, and to lift it to the full functionality. For example, to define my_in_channel:

class my_raw_in_channel : raw_in_channel =
object (self)
  method input s pos len = ...
  method close_in() = ...
  method pos_in = ...
end
class my_in_channel =
  in_obj_channel_delegation (lift_in (`Raw(new my_raw_in_channel)))

The function Netchannels.lift_in can lift several forms of incomplete channel objects to the full class type in_obj_channel. There is also the corresponding function Netchannels.lift_out. Note that lifting adds by default another internal buffer to the channel that must be explicitly turned off when it is not wanted. The rationale for this buffer is that it avoids some cases with extremely poor performance which might be surprising for many users.

The class in_obj_channel_delegation is just an auxiliary construction to turn the in_obj_channel object returned by lift_in again into a class.

Some FAQ

  • Netchannels add further layers on top of the built-in channels or file descriptors. Does this make them slow?

    Of course, Netchannels are slower than the underlying built-in I/O facilities. There is at least one, but often even more than one method call until the data is transferred to or from the final I/O target. This costs time, and it is a good idea to reduce the number of method calls for maximum speed. Especially the character- or byte-based method calls should be avoided, it is better to collect data and pass them in larger chunks. This reduces the number of method calls that are needed to transfer a block of data.

    However, some classes implement buffers themselves, and data are only transferred when the buffers are full (or empty). The overhead for the extra method calls is small for these classes. The classes that implement their own buffers are the transactional channels, the pipes, and all the classes with "buffer" in their name.

    Netchannels are often stacked, i.e. one netchannel object transfers data to an underlying object, and this object passes the data to further objects. Often buffers are involved, and data are copied between buffers several times. Of course, these copies can reduce the speed, too.

  • Why do Netchannels not support seeking?

    Netchannels were invented to support the implementation of network protocols. Network endpoints are not seekable.

  • What about printf and scanf?

    In principle, methods for printf and scanf could be added to out_obj_channel and in_obj_channel, respectively, as recent versions of O'Caml added the necessary language means (polymorphic methods, kprintf, kscanf). However, polymorphic methods work only well when the type of the channel object is always annotated (e.g. as (ch : out_obj_channel) # printf ...), so this is not that much better than ch # output_string (sprintf ...).

  • Can I pass an in_obj_channel to an ocamllex-generated lexer?

    Yes, just call Netchannels.lexbuf_of_in_obj_channel to turn the in_obj_channel into a lexbuf.

  • Do Netchannels support non-blocking I/O?

    Yes and no. Yes, because you can open a descriptor in non-blocking mode, and create a netchannel from it. When the program would block, the input and output methods return 0 to indicate this. However, the non-raw methods cannot cope with these situations.

  • Do Netchannels support multiplexed I/O?

    No, there is no equivalent to Unix.select on the level of netchannels.

  • Can I use Netchannels in multi-threaded programs?

    Yes. However, shared netchannels are not locked, and strange things can happen when netchannels are used by several threads at the same time.

  • Can I use pipes to communicate between threads?

    This could be made work, but it is currently not the case. A multithreading-aware wrapper around pipes could do the job.

  • Pipes call external programs to do their job, don't they?

    No, they do not call external programs, nor do they need any parallel execution threads. Pipes are just a tricky way of organizing buffers.

  • How do I define my own conversion pipe?

    Look at the sources netencoding.ml, it includes several examples of conversion pipes.


ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.options_call.html0000644000175000017500000004061112731530352024002 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.options_call Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Netdn.DN_string.html0000644000175000017500000004373512731530352020240 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdn.DN_string

Module type Netdn.DN_string

module type DN_string = sig .. end


For a given attribute lookup module L this module provides parser and printer for distinguished names in string format (RFC 4514).

This implementation is restricted to attributes using the ASN.1 types PrintableString, TeletexString, IA5String, UniversalString, BMPString, and UTF8String. It is not possible to parse hexencoded strings ('#' notation).

(NB. We'd need a generic BER printer for supporting this.)

val parse : string -> Netdn.dn
Parses the string (or fails). The string must use UTF-8 encoding.
val print : Netdn.dn -> string
Prints the DN (cannot fail), using UTF-8 encoding
ocamlnet-4.1.2/doc/html-main/Netchannels.input_command-c.html0000644000175000017500000004317312731530352022614 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_command

Class Netchannels.input_command

class input_command : string -> in_obj_channel
Runs the command with /bin/sh, and reads the data the command prints to stdout.

The method pos_in returns the number of read octets.

When close_in is invoked, the subprocess is waited for. If the process exits with code 0, the method returns normally. Otherwise, the exception Command_failure is raised.


ocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.SCRAM_SHA256_PLUS.html0000644000175000017500000010710412731530352023522 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM_SHA256_PLUS

Module Netmech_scram_sasl.SCRAM_SHA256_PLUS

module SCRAM_SHA256_PLUS: Netsys_sasl_types.SASL_MECHANISM 
SCRAM with SHA256_PLUS profile

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/Netsys_gssapi.client_props-c.html0000644000175000017500000004356612731530352023057 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.client_props

Class type Netsys_gssapi.client_props

class type client_props = object .. end
Return properties of the client context

method mech_type : oid
Actual mechanism
method flags : ret_flag list
Actual flags
method time : time
Actual context lifetime
ocamlnet-4.1.2/doc/html-main/Uq_tcl.tcl_event_system-c.html0000644000175000017500000004416312731530352022333 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_tcl.tcl_event_system

Class Uq_tcl.tcl_event_system

class tcl_event_system : ?run:runner -> unit -> Unixqueue.event_system
This class is an alternate implementation of the Unixqueue event systems for the TCL event loop. Use this class instead of unix_event_system.

Both Unixqueue and TCL provide event queues for system events, and it is possible to merge both queues such that events may happen and be processed on one queue while the other queue blocks.

To achieve this, just use this class instead of unix_event_system. It automatically creates handlers for the TCL loop when necessary. However, you must not invoke the method run, as this class does not provide its own event loop. Instead, ensure that Tk.mainLoop is called.

Of course, this is all intended to help writing applications which have a graphical user interface (GUI) built with labltk, and some network functionality which is designed to work in the background. Simply create your GUI with labltk, and after the button is pressed which starts the network I/O, you add resources to this event queue, and the I/O will be processed concurrently with any user input coming from the GUI.

Note: The implementation is not thread-safe (and neither TCL).


ocamlnet-4.1.2/doc/html-main/type_Netmech_digest_sasl.DIGEST_MD5.html0000644000175000017500000004066512731530352023731 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_sasl.DIGEST_MD5 Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/type_Netcgi_apache.cgi.html0000644000175000017500000005307212731530352021611 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.cgi object
  method argument : string -> Netcgi.cgi_argument
  method argument_exists : string -> bool
  method argument_value : ?default:string -> string -> string
  method arguments : Netcgi.cgi_argument list
  method at_exit : (unit -> unit) -> unit
  method environment : Netcgi.cgi_environment
  method finalize : unit -> unit
  method multiple_argument : string -> Netcgi.cgi_argument list
  method out_channel : Netchannels.trans_out_obj_channel
  method output : Netchannels.trans_out_obj_channel
  method request : Netcgi_apache.Apache.Request.t
  method request_method :
    [ `DELETE | `GET | `HEAD | `POST | `PUT of Netcgi.cgi_argument ]
  method set_header :
    ?status:Nethttp.http_status ->
    ?content_type:string ->
    ?content_length:int ->
    ?set_cookie:Nethttp.cookie list ->
    ?set_cookies:Netcgi.Cookie.t list ->
    ?cache:Netcgi.cache_control ->
    ?filename:string ->
    ?language:string ->
    ?script_type:string ->
    ?style_type:string -> ?fields:(string * string list) list -> unit -> unit
  method set_redirection_header :
    ?set_cookies:Netcgi.Cookie.t list ->
    ?fields:(string * string list) list -> string -> unit
  method url :
    ?protocol:Nethttp.protocol ->
    ?with_authority:Netcgi.other_url_spec ->
    ?with_script_name:Netcgi.other_url_spec ->
    ?with_path_info:Netcgi.other_url_spec ->
    ?with_query_string:Netcgi.query_string_spec -> unit -> string
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.async_in_channel_engine.html0000644000175000017500000004337512731530352025257 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.async_in_channel_engine object
  method abort : unit -> unit
  method can_input : bool
  method close_in : unit -> unit
  method event_system : Unixqueue.event_system
  method input : Bytes.t -> int -> int -> int
  method pos_in : int
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : (unit engine -> bool) -> unit
  method state : unit engine_state
end
ocamlnet-4.1.2/doc/html-main/Netmech_crammd5_sasl.html0000644000175000017500000004573712731530352021323 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_crammd5_sasl

Module Netmech_crammd5_sasl

module Netmech_crammd5_sasl: sig .. end
The CRAM-MD5 SASL mechanism (RFC 2195), which is obsolete and only provided for completeness.

Key facts:

  • The password is checked with a challenge-response mechanism, and does not appear in the clear.
  • The mechanism is vulnerable to man-in-the-middle attacks.
  • The client does not authenticate the server in any way.
  • The hash function MD5 counts as broken.
  • There is no support for channel binding within the mechanism.
  • There is no support for authorization names.
  • The mechanism provides at best medium security, and should only be used over channels that are otherwise secured.
This implementation checks whether the server receives user names and passwords in UTF-8 encoding. Note that the mechanism predates the widespread use of Unicode, so this may cause interoperability issues with old implementations.

Parameters:

  • Both create_client_session and create_server_session accept the boolean parameter "mutual". If true, however, authentication fails immediately, as mutual authentication cannot be supported.
  • The boolean parameter "secure" is ignored (i.e. we regard this mechanism as secure)
As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of CRAM-MD5 should pass user names and passwords through Netsaslprep.saslprep.

module CRAM_MD5: Netsys_sasl_types.SASL_MECHANISM 
The CRAM-MD5 SASL mechanism (RFC 2195), which is obsolete and only provided for completeness.
ocamlnet-4.1.2/doc/html-main/Netglob.local_fsys-c.html0000644000175000017500000004223212731530352021240 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.local_fsys

Class Netglob.local_fsys

class local_fsys : ?encoding:Netconversion.encoding -> unit -> glob_fsys

ocamlnet-4.1.2/doc/html-main/type_Netftp_data_endpoint.ftp_data_engine.html0000644000175000017500000004307512731530352025577 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.ftp_data_engine object
  method abort : unit -> unit
  method descr : Unix.file_descr
  method descr_state : Netftp_data_endpoint.descr_state
  method event_system : Unixqueue.event_system
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    (unit Uq_engines.engine -> bool) -> unit
  method state : unit Uq_engines.engine_state
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.sync_engine-c.html0000644000175000017500000004261212731530352023453 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.sync_engine

Class Uq_engines_compat.sync_engine

class [['a, 'b]] sync_engine : 'a #engine -> 'b #engine -> [('a * 'b)] engine

ocamlnet-4.1.2/doc/html-main/type_Netplex_cenv.Debug.html0000644000175000017500000004100512731530352022006 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netmech_krb5_sasl.Krb5_gs2.html0000644000175000017500000004122612731530352023241 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_krb5_sasl.Krb5_gs2 functor (GSS : Netsys_gssapi.GSSAPI-> Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/Netplex_cenv.Debug.html0000644000175000017500000004220712731530352020752 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.Debug

Module Netplex_cenv.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging
ocamlnet-4.1.2/doc/html-main/type_Netnumber.BE.html0000644000175000017500000004055012731530352020557 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber.BE ENCDECocamlnet-4.1.2/doc/html-main/Netplex_types.plugin-c.html0000644000175000017500000005014712731530352021655 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.plugin

Class type Netplex_types.plugin

class type plugin = object .. end
Plugins are extensions of the Netplex system that run in the controller and can be invoked from containers

method required : plugin list
Required plugins
method program : Rpc_program.t
The RPC program structure on which the messaging bases. The program, version and procedure numbers are ignored
method ctrl_added : controller -> unit
This method is invoked when the plugin has been added to this controller. Note that plugins can be added to several controllers.
method ctrl_unplugged : controller -> unit
The plugin has been unplugged from this controller
method ctrl_receive_call : controller ->
container_id ->
string -> Netxdr.xdr_value -> (Netxdr.xdr_value option -> unit) -> unit
ctrl_receive_call ctrl cid procname procarg emit: This method is called in the controller context ctrl when a procedure named procname is called. In procarg the argument of the procedure is passed. cid is the container ID from where the call originates. To pass the result r of the call back to the caller, is is required to call emit (Some r) (either immediately, or at some time in the future). By calling emit None, an error condition is propagated back to the caller.
method ctrl_container_finished : controller -> container_id -> bool -> unit
This method is called when a container finishes (after post_finish_hook). The boolean is true if the container is the last of the terminated socket service.
ocamlnet-4.1.2/doc/html-main/Netplex_types.processor_hooks-c.html0000644000175000017500000006200612731530352023576 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.processor_hooks

Class type Netplex_types.processor_hooks

class type processor_hooks = object .. end
Processor hooks can be used to modify the behavior of a processor. See Services And Processors for some documentation about the hooks.

method post_add_hook : socket_service -> controller -> unit
A user-supplied function that is called after the service has been added to the controller
method post_rm_hook : socket_service -> controller -> unit
A user-supplied function that is called after the service has been removed from the controller
method pre_start_hook : socket_service ->
controller -> container_id -> unit
A user-supplied function that is called before the container is created and started. It is called from the process/thread of the controller.
method post_start_hook : container -> unit
A user-supplied function that is called after the container is created and started, but before the first service request arrives. It is called from the process/thread of the container.
method pre_finish_hook : container -> unit
A user-supplied function that is called just before the container is terminated. It is called from the process/thread of the container.
method post_finish_hook : socket_service ->
controller -> container_id -> unit
A user-supplied function that is called after the container is terminated. It is called from the process/thread of the controller.
method workload_hook : container -> bool -> int -> unit
A user-supplied function that is called when the workload changes, i.e. a new connection has been accepted, or an existing connection could be completely processed. The bool argument is true if the reason is a new connection. The int argument is the number of connections. This function is called from the process/thread of the container.
method receive_message : container -> string -> string array -> unit
This function is called when a broadcast message is received. The first string is the name of the message, and the array are the arguments.
method receive_admin_message : container -> string -> string array -> unit
This function is called when a broadcast admin message is received. The first string is the name of the message, and the array are the arguments.
method config_internal : (string * polysocket_kind_box) list
For internal services, this list configures which message kind is used for which protocol.
method process_internal : when_done:(unit -> unit) ->
container -> polyserver_box -> string -> unit
process_internal ~when_done cont client protocol: This function is called instead of process when a connection to an internal service is made. This method has to accept or reject the connection with Netsys_polysocket.accept or Netsys_polysocket.refuse, respectively. The default is to refuse.

Like process, the function must call when_done when the connection is fully processed.

method system_shutdown : unit -> unit
A user-supplied function that is called when a system shutdown notification arrives. This notification is just for information that every container of the system will soon be shut down. The system is still completely up at the time this notification arrives, so if the services of other components are required to go down this is the right point in time to do that (e.g. send important data to a storage component).
method shutdown : unit -> unit
A user-supplied function that is called when a shutdown notification arrives. That means that the container should terminate ASAP. There is, however, no time limitation. The termination is started by calling the when_done function passed to the process method.
method global_exception_handler : exn -> bool
This method is called when an uncaught exception would otherwise terminate the container. It can return true to indicate that the container continues running.
method container_event_system : unit -> Unixqueue.event_system
This method is called to get the event systems for containers. This is normally a Unixqueue.standard_event_system, but users can override it.
method container_run : Unixqueue.event_system -> unit
container_run esys: By default, it just runs esys#run(). This method is called to run the event system of the containers. Users can override it.
ocamlnet-4.1.2/doc/html-main/Netsys.Debug.html0000644000175000017500000004170312731530352017605 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys.Debug

Module Netsys.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging
ocamlnet-4.1.2/doc/html-main/type_Netmime.file_mime_body.html0000644000175000017500000004076012731530352022676 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.file_mime_body ?fin:bool -> string -> Netmime.mime_bodyocamlnet-4.1.2/doc/html-main/type_Nethttp_client.Convenience.html0000644000175000017500000004753112731530352023560 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.Convenience sig
  val http_trials : int Pervasives.ref
  val http_user : string Pervasives.ref
  val http_password : string Pervasives.ref
  val configure : ?insecure:bool -> unit -> unit
  val configure_pipeline : (Nethttp_client.pipeline -> unit) -> unit
  val http_get_message : string -> Nethttp_client.http_call
  val http_head_message : string -> Nethttp_client.http_call
  val http_post_message :
    string -> (string * string) list -> Nethttp_client.http_call
  val http_put_message : string -> string -> Nethttp_client.http_call
  val http_delete_message : string -> Nethttp_client.http_call
  val http_get : string -> string
  val http_post : string -> (string * string) list -> string
  val http_put : string -> string -> string
  val http_delete : string -> string
  val http_verbose :
    ?verbose_status:bool ->
    ?verbose_request_header:bool ->
    ?verbose_response_header:bool ->
    ?verbose_request_contents:bool ->
    ?verbose_response_contents:bool ->
    ?verbose_connection:bool -> ?verbose_events:bool -> unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netaccel.html0000644000175000017500000004077212731530352020057 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaccel sig val init : unit -> unit endocamlnet-4.1.2/doc/html-main/type_Netplex_admin.html0000644000175000017500000004061612731530352021125 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_admin sig  endocamlnet-4.1.2/doc/html-main/Netcgi_scgi.html0000644000175000017500000005331012731530352017506 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_scgi

Module Netcgi_scgi

module Netcgi_scgi: sig .. end
SCGI connector.

The SCGI connects your web applications through a TCP/IP socket (thus the application can run on a machine different from the web server).

See the Setup section at the end of this file to know how to configure your web server.


val run : ?config:Netcgi.config ->
?allow:(Unix.sockaddr -> bool) ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?exn_handler:Netcgi.exn_handler ->
?socket:Unix.file_descr ->
?sockaddr:Unix.sockaddr -> ?port:int -> (Netcgi.cgi -> unit) -> unit
run f executes f cgi for each SCGI request.
config : Default: Netcgi.default_config
allow : Tells whether a connection from the socket is allowed. Default: allow from all.
output_type : Default: `Direct ""
arg_store : Default: `Automatic for all arguments.
exn_handler : See Netcgi.exn_handler. Default: delegate all exceptions to the default handler.
socket : is a listening socket to use. Overrides sockaddr and port
sockaddr : The sockaddr for listening. Overrides port
port : The port for listening. Needs to be specified if no sockaddr is passed.
val handle_request : Netcgi.config ->
Netcgi.output_type ->
Netcgi.arg_store ->
Netcgi.exn_handler ->
(Netcgi.cgi -> unit) ->
log:(string -> unit) option -> Unix.file_descr -> Netcgi.connection_directive
handle_request config output_type arg_store eh f ~log fd: This is a lower-level interface that processes exactly one request arriving on the existing connection fd.

log is the error logger function or None, in which case errors are passed through to the FCGI client.

The other arguments are just like for run.

The return value indicates whether the connection can be kept open or must be closed.

val handle_connection : Netcgi.config ->
Netcgi.output_type ->
Netcgi.arg_store ->
Netcgi.exn_handler -> (Netcgi.cgi -> unit) -> Unix.file_descr -> unit
handle_connection config output_type arg_store eh f ?script_name fd: This is a lower-level interface that processes exactly one connection fd. The descriptor is closed (even on error).

The other arguments are just like for run.


Setup

Add to httpd.conf or to, say, scgi.conf in /etc/apache/conf.d

    LoadModule scgi_module /usr/lib/apache/1.3/mod_scgi.so
    # Serve the URL /scgi by contacting 127.0.0.1 on port 8888
    SCGIMount /scgi 127.0.0.1:8888
    

ocamlnet-4.1.2/doc/html-main/Netplex_cenv.FUN_TYPE.html0000644000175000017500000004267112731530352021222 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.FUN_TYPE

Module type Netplex_cenv.FUN_TYPE

module type FUN_TYPE = sig .. end
Abstraction for function types s->t

type s 
argument type
type r 
result type
ocamlnet-4.1.2/doc/html-main/Netldap.html0000644000175000017500000013172112731530352016662 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netldap

Module Netldap

module Netldap: sig .. end
LDAP client


This is a simple asynchronous LDAP client.

Regarding LDAP URLs, please note that there are some special functions in Neturl_ldap.

This is a simple asynchronous LDAP client.

Regarding LDAP URLs, please note that there are some special functions in Neturl_ldap.

Error handling


type result_code = [ `AdminLimitExceeded
| `AffectsMultipleDSAs
| `AliasDereferencingProblem
| `AliasProblem
| `AttributeOrValueExists
| `AuthMethodNotSupported
| `Busy
| `CompareFalse
| `CompareTrue
| `ConfidentialityRequired
| `ConstraintViolation
| `EntryAlreadyExists
| `InappropriateAuthentication
| `InappropriateMatching
| `InsufficientAccessRights
| `InvalidAttributeSyntax
| `InvalidCredentials
| `InvalidDNSyntax
| `LoopDetect
| `NamingViolation
| `NoSuchAttribute
| `NoSuchObject
| `NotAllowedOnNonLeaf
| `NotAllowedOnRDN
| `ObjectClassModsProhibited
| `ObjectClassViolation
| `OperationsError
| `Other
| `ProtocolError
| `Referral
| `SaslBindInProgress
| `SizeLimitExceeded
| `StrongAuthRequired
| `Success
| `TimeLimitExceeded
| `Unavailable
| `UnavailableCriticalExtension
| `UndefinedAttributeType
| `Unknown_code of int
| `UnwillingToPerform ]
exception Timeout
Raised when the TCP connection times out. Timeouts should be considered as non-recoverable by the user, and the connection should be aborted.
exception LDAP_error of result_code * string
The server indicates a (logical) error. Such errors are normal messages, and the connection remains intact.
exception Auth_error of string
Authentication error

Specifying the LDAP server


type tls_mode = [ `Disabled | `Immediate | `StartTLS | `StartTLS_if_possible ] 
Options:
  • `Disabled: do not negotiate TLS
  • `Immediate: assume that the connection directly requires TLS
  • `StartTLS: upgrade an initially unprotected connection to TLS
  • `StartTLS_if_possible: upgrade an unprotected connection to TLS if possible (i.e. if supported by both ends of the connection)

class type ldap_server = object .. end
val ldap_server : ?timeout:float ->
?peer_name:string ->
?tls_config:(module Netsys_crypto_types.TLS_CONFIG) ->
?tls_mode:tls_mode -> Netsockaddr.socksymbol -> ldap_server
Specifies how to reach the server: e.g.

let server = ldap_server (`Inet_byname("hostname", 389))
      

Options:

  • timeout: The timeout for connecting and for subsequent request/response cycles. Defaults to 15 seconds.
  • peer_name: The expected domain name in the certificate for TLS-secured connections. If not passed, the name is derived from the socksymbol argument.
  • tls_config: The TLS configuration (i.e. the TLS provider and how to use it). Defaults to the provider set in Netsys_crypto, and to requiring valid server certificates.
  • tls_mode: Whether and how to negotiate TLS. Defaults to `StartTLS_if_possible.

val ldap_server_of_url : ?timeout:float ->
?tls_config:(module Netsys_crypto_types.TLS_CONFIG) ->
?tls_mode:tls_mode -> Neturl.url -> ldap_server
Gets the host and port from an LDAP URL. Otherwise the same as ldap_server.

The URL can have schemes "ldap" or "ldaps". In the latter case, the tls_mode is automatically adjusted to `Immediate.


Specifying LDAP credentials


type bind_creds 
val anon_bind_creds : bind_creds
val simple_bind_creds : dn:string -> pw:string -> bind_creds
val sasl_bind_creds : dn:string ->
user:string ->
authz:string ->
creds:(string * string * (string * string) list) list ->
params:(string * string * bool) list ->
(module Netsys_sasl_types.SASL_MECHANISM) -> bind_creds

LDAP connections


type ldap_connection 
val connect_e : ?proxy:#Uq_engines.client_endpoint_connector ->
ldap_server ->
Unixqueue.event_system -> ldap_connection Uq_engines.engine
val connect : ?proxy:#Uq_engines.client_endpoint_connector ->
ldap_server -> ldap_connection
val close_e : ldap_connection -> unit Uq_engines.engine
Close the connection using the close protocol
val close : ldap_connection -> unit
Same as synchronous function
val abort : ldap_connection -> unit
Close the connection immediately
val conn_bind_e : ldap_connection -> bind_creds -> unit Uq_engines.engine
Bind the connection to credentials
val conn_bind : ldap_connection -> bind_creds -> unit
Same as synchronous function
val tls_session_props : ldap_connection -> Nettls_support.tls_session_props option
Returns the TLS session properties

LDAP results


class type ['a] ldap_result = object .. end
A class type for encapsulating results
exception Notification of string ldap_result
An unsolicited notification. The string is the OID. Best reaction is to terminate the connection. This is e.g. sent when the server cannot decode the client message, but also for other special conditions. Notification exception are directly raised by the LDAP client functions.

LDAP searches


type scope = [ `Base | `One | `Sub ] 
The scope of the search:
  • `Base: only the base object
  • `One: only the direct children of the base object
  • `Sub: the base object and all direct and indirect children

type deref_aliases = [ `Always | `Finding_base_obj | `In_searching | `Never ] 
What to do when aliases (server-dereferenced symbolic links) are found in the tree:
  • `Never: do not dereference aliases but return them as part of the search result
  • `In_searching: when aliases are found in the children of the base object dereference the aliases, and continue the search there, and repeat this recursively if needed
  • `Finding_base_obj: dereference alises in base objects but not in children
  • `Always: always dereference aliases

type filter = [ `And of filter list
| `Approx_match of string * string
| `Equality_match of string * string
| `Extensible_match of string option * string option * string * bool
| `Greater_or_equal of string * string
| `Less_or_equal of string * string
| `Not of filter
| `Or of filter list
| `Present of string
| `Substrings of string * string option * string list * string option ]
Filter:
  • `Equality_match(attr_descr, value)
  • `Substrings(attr_descr, prefix_match, substring_matches, suffix_match)
  • `Greater_or_equal(attr_descr,value)
  • `Less_or_equal(attr_descr,value)
  • `Present(attr_descr)
  • `Approx_match(attr_descr,value)
  • `Extensible_match(matching_rule_id, attr_descr, value, dn_attrs)
Here, attr_descr is the name of the attribute, either given by an OID (in dotted representation) or a by a descriptive name. There can be options, separated from the name by a semicolon.

The value is the value to filter with (an UTF-8 string).

type search_result = [ `Entry of string * (string * string list) list | `Reference of string list ] 
Search results are either entries or references:
  • `Entry(object_dn, [(attr_descr, values); ...])
  • `Reference urls: The entry is not present on this server but can be looked up by following one of the urls

val search_e : ldap_connection ->
base:string ->
scope:scope ->
deref_aliases:deref_aliases ->
size_limit:int ->
time_limit:int ->
types_only:bool ->
filter:filter ->
attributes:string list ->
unit -> search_result list ldap_result Uq_engines.engine
Run the specified search: Search at base according to scope for entries matching the filter and return their attributes.

If the base object is not present on the server but somewhere else (redirection) the result will be empty and the referral is set in the response. If children of the base object are redirected to another server, the result will contain `Reference elements.

Note that time_limit is a server-enforced limit (in seconds; 0 for no limit). Independently of that this client employs the timeout set in the ldap_connection. This timeout limits the time between two consecutive server messages.

The size_limit limits the number of returned entries (0 for no limit).

If types_only there will not be values in the result (instead, empty lists are returned).

A filter is mandatory. If you want to get all results, specify a useless filter like `Present("objectclass").

If you pass an empty attributes list, no attributes will be returned. In order to get all attributes, pass the list ["*"]. The asterisk can also be appended to a non-empty list to get all remaining attributes in any order.

val search : ldap_connection ->
base:string ->
scope:scope ->
deref_aliases:deref_aliases ->
size_limit:int ->
time_limit:int ->
types_only:bool ->
filter:filter ->
attributes:string list ->
unit -> search_result list ldap_result
Same as synchronous function
val compare_e : ldap_connection ->
dn:string ->
attr:string ->
value:string -> unit -> bool ldap_result Uq_engines.engine
compare_e conn ~dn ~attr ~value (): returns true if the attribute attr of entry dn has value (according to equality matching)
val compare : ldap_connection ->
dn:string -> attr:string -> value:string -> unit -> bool ldap_result
Same as synchronous function

LDAP updates



LDAP updates



Although updates do not return a regular result, there might be an error message. An exception is not automatically raised. It is done, though, when the value method of the result is invoked (returning normally just ()). Example:

let () = (add conn ~dn ~attributes) # value

val add_e : ldap_connection ->
dn:string ->
attributes:(string * string list) list ->
unit -> unit ldap_result Uq_engines.engine
add_e conn ~dn ~attributes: Adds a new entry under dn with the attributes, given as list (attr_descr, values).
val add : ldap_connection ->
dn:string ->
attributes:(string * string list) list -> unit -> unit ldap_result
Same as synchronous function
val delete_e : ldap_connection ->
dn:string -> unit -> unit ldap_result Uq_engines.engine
delete_e conn ~dn: Deletes the entry dn
val delete : ldap_connection -> dn:string -> unit -> unit ldap_result
Same as synchronous function
type operation = [ `Add | `Delete | `Replace ] 
val modify_e : ldap_connection ->
dn:string ->
changes:(operation * (string * string list)) list ->
unit -> unit ldap_result Uq_engines.engine
modify_e conn ~dn ~changes (): Modifies attributes of the entry for dn. The changes are given as a list (op, (attr_descr, values)). Here, op is the operation to do. attr_descr identifies the attribute to add/delete/replace. The values are the additional values, or the values to delete, or the values to substitute. In case of "delete", an empty values list means to delete the whole attribute.
val modify : ldap_connection ->
dn:string ->
changes:(operation * (string * string list)) list ->
unit -> unit ldap_result
Same as synchronous function
val modify_dn_e : ldap_connection ->
dn:string ->
new_rdn:string ->
delete_old_rdn:bool ->
new_superior:string option ->
unit -> unit ldap_result Uq_engines.engine
modify_dn_e conn ~dn ~new_rdn ~delete_old_rdn ~new_superior: renames and/or moves the entry in the tree. The entry under dn is the modified entry. The new_rdn is the new name of the leaf (renaming). If delete_old_rdn, the attributes describing the old name of the leaf are deleted, and otherwise retained. If new_superior is set, the entry is additionally moved to this new parent entry.
val modify_dn : ldap_connection ->
dn:string ->
new_rdn:string ->
delete_old_rdn:bool ->
new_superior:string option -> unit -> unit ldap_result
Same as synchronous function
val modify_password_e : ldap_connection ->
uid:string option ->
old_pw:string option ->
new_pw:string option ->
unit -> string option ldap_result Uq_engines.engine
This is the LDAP extension for modifying passwords (potentially outside the tree; RFC 3062). uid is the user ID to modify (which can be a DN but needs not to). The old password can be specified in old_pw. The new password is in new_pw.

In cases where the server generates a password, this one is contained in the returned result.

val modify_password : ldap_connection ->
uid:string option ->
old_pw:string option ->
new_pw:string option -> unit -> string option ldap_result
Same as synchronous function

LDAP routines


val test_bind_e : ?proxy:#Uq_engines.client_endpoint_connector ->
ldap_server ->
bind_creds -> Unixqueue.event_system -> bool Uq_engines.engine
Tries to bind to the server with the given credentials. Returns whether successful.
val test_bind : ?proxy:#Uq_engines.client_endpoint_connector ->
ldap_server -> bind_creds -> bool
Same as synchronous function
val retr_password_e : dn:string ->
ldap_server ->
bind_creds ->
Unixqueue.event_system ->
(string * string * (string * string) list) list Uq_engines.engine
Connects and binds to the server, and retrieves the userPassword and authPassword attributes of the entry referenced by dn. The passwords are returned in the format outlined in Credentials. This function can process these password formats:
  • userPassword in RFC-2307 format using any schemes
  • authPassword in RFC-3112 format using any schemes
Raises an LDAP_error exception when problems occur.
val retr_password : dn:string ->
ldap_server ->
bind_creds -> (string * string * (string * string) list) list
Same as synchronous function

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netshm_intro.html0000644000175000017500000010173412731530352017745 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm_intro

Netshm_intro


Shared Memory for IPC

The netshm library implements a number of practical schemes to manage shared memory. Here we give a tutorial how to use that functions.

What kind of shared memory we talk about

In general, shared memory is a memory region that is mapped into several address spaces. The O'Caml language already supports one kind of shared memory out of the box, the so-called multi-threading. Here, several execution threads access the same memory, and thus can access the same data. There are a lot of accompanying techniques allowing one to manage shared memory (mutexes, condition variables, event channels, etc.).

Of course, the netshm library does not use this kind of shared memory (it is effectively even incompatible with multi-threading to some degree). Here, memory is shared by independent processes. This means that any process on the computer can access a shared memory object provided

  • the process knows the global name of the object, and
  • the process has the access rights.
It is not necessary that the processes have something else in common (e.g. that one process is created by the other, etc.).

Types of shared memory provided by the OS

In the Unix world, there are (at least) two common APIs to access global shared memory objects:

  • System V shared memory
  • POSIX shared memory
The netshm library has an extensible interface that can support several system APIs. Currently, however, there is only an implementation for POSIX shared memory.

In addition to that, it is also possible to access file-backed memory.

Note that not all OS support POSIX shared memory. To check, look at the value of Netsys.have_posix_shm().

Global names

The module Netshm defines the possible global names:

 
type shm_name =
  [ `POSIX of string * string
  | `File of string
  ]

For POSIX shared memory you must take a `POSIX global name, for file-backed memory a `File name. A `POSIX global name has two strings as arguments: (file_name,mem_name). The file_name points to a normal file, usually located in the /tmp hierarchy. This file is only used for management and locking purposes. The mem_name is the actual POSIX memory object. This name looks like a file name, but actually lives in a different name space. It must begin with a slash, followed by the name that must not contain further slashes. An exampe: `POSIX("/tmp/sample", "/sample").

Opening shared memory objects

There is the function Netshm.open_shm that works much like Unix.openfile. For example,

let sd = 
  Netshm.open_shm
    (`POSIX("/tmp/sample","/sample")) [Unix.O_CREAT; Unix.O_RDWR] 0o666

opens /sample for read-write access, and if the object does not exist yet, it is created with mode 0o666. The returned result is a so-called shared memory descriptor.

In order to create unique new objects, you can also use Netshm.create_unique_shm. This function takes a pattern for the global name, and creates a new object with a unique name based on the pattern. This is done by replacing all 'X' letters in the string argument by random characters until a new name has been found. For example:

let sd =
  Netshm.create_unique_shm
     (`POSIX("/tmp/myprogram.XXXXX","/myprogram.XXXXX")) 0o666

The actual name is returned by Netshm.name_of_shm.

Like files, shared memory objects must be closed after usage:

Netshm.close_shm sd

Of course, the object continues to exist after the descriptor has been closed. There is a special function Netshm.unlink_shm to delete objects.

It is discouraged to open shared memory objects several times in parallel from the same process, as locking methods (see below) are confused by this.

If you create several processes by calling Unix.fork it is required that every process opens the shared memory object anew. It is not sufficient to open the object in the master process, and to use it in the child processes after forking. This will cause subtle malfunctions.

Data structures

The Netshm module contains only the algorithms for the primitve data structure, a hash table from int32 to bigarrays of int32 elements. Netshm_hashtbl and Netshm_array have user-friendlier data structures:

  • Netshm_hashtbl is a hash table from type s to t, where both s and t can be any so-called manageable type (see below).
  • Netshm_array is an array of elements, again of one of the mentioned manageable types. Arrays can be sparse.
The element types are restricted to those types that can be managed with Netshm_data. In principle, this can be any type for which you can write a data manager. Netshm_data contains only data managers for these types:

  • int
  • int32
  • int64
  • nativeint
  • string
  • pairs of two manageable types (pairs of pairs are allowed)
For example, to get a data manager for the pair of an int and a string, one can do

 let dm =
      Netshm_data.pair_manager
         Netshm_data.int_manager
         Netshm_data.string_manager

dm has then type (int * string) data_manager.

In order to view a shared memory object as hash table or array, it is necessary to manage it:

 
  let sd = 
    Netshm.open_shm (`POSIX("/tmp/sample", "/sample")) [Unix.O_RDWR] 0 in
  let tab =
    Netshm_hashtbl.manage
      Netshm_data.string_manager
      dm
      `No_locking
      sd

The manage function for hash tables takes the data managers for keys and values of the table, a thing called `No_locking, and the shared memory descriptor sd as input. It returns the abstract value that represents the hash table. What `No_locking means will become clearer below.

After being managed, you can access tab like a hash table:

  Netshm_hashtbl.add tab "First Key" (1, "First value")

  let (n, s) = Netshm_hashtbl.find tab "First Key"

Note that neither input nor output values of managed objects are placed in shared memory. They are normal O'Caml values for which no restrictions apply. The shared memory is totally hidden from user code (actually, there are two functions in Netshm that exhibit values that reside in this memory, but they should only be used by experts).

The manage function for arrays is slightly different. In particular, only one data manager must be given.

Concurrent Access

If `No_locking is effective, nothing is done by netshm to make concurrent accesses by several processes to the same object safe. The implications depend on what you do. If you only read, everything is ok. If there is a writer, it is possible that netshm cannot access the object properly in certain situations, and it is even possible that the internal structures of the object are destroyed.

In order to avoid such problems, you can specify a locking method other than `No_locking. Currently there is only `Record_locking.

It is sufficient to pass `Record_locking to the manage functions - the rest works automatically:

  let tab =
    Netshm_hashtbl.manage
      Netshm_data.string_manager
      dm
      `Record_locking
      sd

Record locking bases on the Unix.lockf function. It has been chosen as primary locking method because it is available everywhere - although it is not the fastest method.

The effect of locking is that every read access places read locks on the relevant parts of the object, and that every write access acquires the needed write locks. The locking scheme is rather fine-grained and allows true parallel accesses when a reader and a writer manipulate the same key of the hash table. Two writers, however, lock each other out.

Grouping

Consider this piece of code:

  let v = Netshm_hashtbl.find tab k in
  let v' = compute_something v in
  Netshm_hashtbl.replace tab k v'

This is a so-called read-modify-write cycle. If several processes do this in parallel, the execution of the cycles can overlap. For example, it is possible that process P writes the modified value v' while process Q checks for the value of this key. The outcome of such overlapping cycles is quite random: In the best case, computations are repeated, in the worst case, results of computations are lost.

Netshm has the function Netshm.group to avoid such effects:

  Netshm.group
    (Netshm_hashtbl.shm_table tab)
    (fun () ->
       let v = Netshm_hashtbl.find tab k in
       let v' = compute_something v in
       Netshm_hashtbl.replace tab k v'
    )
    ()

Note that you need Netshm_hashtbl.shm_table to get the underlying primitive table in order to use group.

The effect of group is that conflicting accesses to the same parts of the memory object are deferred, so that they do not overlap anymore (technically, the release of the locks is deferred). However, another phenomenon is now possible: Deadlocks.

Deadlock situations usually occur between the locking requirements of a reader and a function that removes a value (remove or replace). Imagine what happens when processes P and Q execute the same grouped read-modify-write cycle almost at the same time:

  • First, both P and Q read-lock the read value
  • Second, one process is a little bit faster (say P), and wants to replace the value, thus needing a write lock. It cannot get the write lock now because Q still has a read lock
  • Third, Q wants to replace the value, needing a write lock. It cannot get the write lock now because P still has a read lock
If nothing else happened, both processes would wait forever.

Fortunately, record locking includes deadlock detection. One process is notified that there is a deadlock. The netshm user gets the Netshm.Deadlock exception.

In a simple read-modifiy-write cycle, this exception is quite harmless: The replace call is interrupted before it got the chance to modify the table. The suggested strategy to cope with that is to sleep for a moment to let the other process do its job and to restart the cycle from the beginning.

In a more complicated cycle, it can happen that a value is already written, and the second trial to write a value triggers the exception. Well, written is written, and there is no mechanism to "undo" the chaos. Best strategy: avoid such cycles, or use another way to store values in a shared storage (e.g. database system).

Persistency of shared memory

Note that POSIX shared memory is not automatically released when the process terminates. Instead, such memory objects persist until explicitly deleted (just like files). If you forget to delete such objects, RAM will be consumed until the system is rebooted!

There is a helper data structure in Netsys_pmanage helping to find and delete memory: If you have an object `POSIX(tmp_name, mem_name), the file tmp_name contains a line pointing to mem_name, e.g.

 R POSIX_SHM "/my_object" 

You can use Netsys_pmanage to read this line and to unlink the object:

let m = Netsys_pmanage.pmanage tmp_name in
m # unlink()

Applications

I hope it has become clear that netshm is only useful for simple applications as there is no support for transactions. Another fundamental limitation is that the file format is non-portable (netshm files written on platform A may not be readable on platform B).

Ideas:

  • Servers using multi-processing where the processes must share some state (e.g. sessions)
  • Scientific computations implemented on a multi-CPU system with multi-processing, where the processes put their results into shared memory
  • Using netshm as fast persistent lookup table

Limits

The maximum size of a memory object depends on the pagesize and init parameters of the manage call. Roughly, the maximum size is

pagesize * init * 32768

which is about 8 G for the defaults pagesize = 256 and init = 1000. Usually, other limits are hit first.

The hash table and array elements use 32 bit numbers for their bookkeeping, e.g. strings can have at most a length of 2 ^ 31 - 1 bytes.
ocamlnet-4.1.2/doc/html-main/Nethttp_client.key_ring-c.html0000644000175000017500000004467112731530352022314 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.key_ring

Class Nethttp_client.key_ring

class key_ring : ?uplink:#key_handler -> ?no_invalidation:bool -> unit -> object .. end
The key_ring is a cache for keys. The optional uplink handler is invoked when no matching key is found in the cache. The uplink is intended for interactively asking the user for a password. If no_invalidation is set, keys are never invalidated (removed after they did not work)
Inherits
method clear : unit -> unit
Deletes all keys from this key ring
method add_key : key -> unit
Adds a key to the ring
method keys : key list
List of all known keys
ocamlnet-4.1.2/doc/html-main/Netsys_sasl_types.SASL_MECHANISM.html0000644000175000017500000010645412731530352023160 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl_types.SASL_MECHANISM

Module type Netsys_sasl_types.SASL_MECHANISM

module type SASL_MECHANISM = sig .. end

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/Uq_transfer.sender-c.html0000644000175000017500000004516112731530352021265 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.sender

Class Uq_transfer.sender

class sender : src:#async_in_channel -> dst:Unix.file_descr -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines.engine
This engine copies all data from the src input channel to the dst file descriptor. The engine attaches immediately to the event system, and detaches automatically.

By default, both the file descriptor and the output channel are closed when the engine stops operation, either successfully or because of an error.

The semantics of the engine is undefined if dst is not a stream-oriented descriptor.

The engine goes to `Error state when either reading from src or writing to dst raises an unexpected exception.

For every file descriptor event, the state is advanced from `Working n to `Working (n+1).

TODO: This class cannot yet cope with Win32 named pipes.


close_src : Whether to close src when the engine stops (default: true)
close_dst : Whether to close dst when the engine stops (default: true)

ocamlnet-4.1.2/doc/html-main/Nethttp_client_conncache.connection_cache-c.html0000644000175000017500000004634412731530352025767 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client_conncache.connection_cache

Class type Nethttp_client_conncache.connection_cache

class type connection_cache = object .. end

method get_connection_state : Unix.file_descr -> conn_state
Returns the state of the file descriptor, or raises Not_found
method set_connection_state : Unix.file_descr ->
peer -> conn_state -> unit
Sets the state of the file descriptor. It is allowed that inactive descriptors are simply closed and forgotten. It is also possible that this method raises Not_found, leaving it to the caller to close the connection.
method find_inactive_connection : peer ->
transport_layer_id ->
Unix.file_descr * inactive_data
Returns an inactive connection to the passed peer, or raise Not_found. Since Ocamlnet-3.3, the required transport ID is also an argument of this method. Since Ocamlnet-4, the inactive_data record is also returned.
method find_my_connections : <  > -> Unix.file_descr list
Returns all active connections owned by the object
method close_connection : Unix.file_descr -> unit
Deletes the connection from the cache, and closes it
method close_all : unit -> unit
Closes all descriptors known to the cache
ocamlnet-4.1.2/doc/html-main/Netplex_mp.mp-c.html0000644000175000017500000004327112731530352020243 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mp.mp

Class Netplex_mp.mp

class mp : ?keep_fd_open:bool -> ?terminate_tmo:int -> unit -> Netplex_types.parallelizer
Uses Unix.fork to create new threads.

After forking the child process is initialized by calling Netsys_posix.run_post_fork_handlers.

By default, all file descriptors are closed that are not explicitly shared with the parent process. This can be wrong for some kind of applications. By setting keep_fd_open another behavior can be demanded: The descriptors are kept open except those that need to be closed.

When the controller wants to shut down the process, it notifies the process, and waits terminate_tmo seconds until the process terminates. If this timeout expires, the process is killed. Defaults to 60. A negative value disables this function.


ocamlnet-4.1.2/doc/html-main/Nethttpd_engine.Debug.html0000644000175000017500000004202112731530352021431 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.Debug

Module Nethttpd_engine.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module
ocamlnet-4.1.2/doc/html-main/Netplex_cenv.html0000644000175000017500000011061712731530352017726 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv

Module Netplex_cenv

module Netplex_cenv: sig .. end
Container environment

Some helper functions to explore the environment from a container. Most of the following functions must be called from a container context, i.e. from a process or thread that acts as container, otherwise the exception Not_in_container_thread is raised. There are also some functions that can be called from controller context for convenience.

Thread safety: Full. The functions in this module can be called from any thread.


exception Not_in_container_thread
Raised when the caller's thread is not a container thread

Logging



Logging



Logging functions can be invoked from both container and controller contexts.
val log : Netplex_types.level -> string -> unit
Writes a log message
val logf : Netplex_types.level -> ('a, unit, string, unit) Pervasives.format4 -> 'a
Writes a log message like printf
val report_connection_string : Unix.file_descr -> string -> string
Output a log line for the netplex.connections admin message. The string is the detail to report.

Timer



Timer



Timer functions can only be invoked from container contexts. More documentation is available in Running timers in containers.
type timer 
A timer
val create_timer : (timer -> bool) -> float -> timer
create_timer f tmo: Creates a timer with timeout value tmo: In tmo seconds f is called, and if this function returns true, the timer remains active, and another round of timing is arranged. If the functions returns false or raises an exception, the timer is stopped.

Timers are also stopped on container shutdown.

Timers are attached to the container event system, and run only if this event system runs. Also note that f is always called from the main thread of the container.

val cancel_timer : timer -> unit
Cancels the timer: The callback function is not called any longer
val cancel_all_timers : unit -> unit
Cancels all active timers
val timer_id : timer -> int
Returns an ID, e.g. useful for debugging

Container variables



Container variables



Container variables exist once per container. Primary access is done via the var and set_var methods of the container class. The following functions are often more convenient, however.

These functions can only be invoked from container contexts.

More documentation: Container variables

exception Container_variable_not_found of string
The variable does not exist
exception Container_variable_type_mismatch of string
The (dynamically typed) variable has the wrong type
val int_var : string -> int
val string_var : string -> string
val float_var : string -> float
val bool_var : string -> bool
Access a variable with simple type. May raise Container_variable_not_found or Container_variable_type_mismatch
val set_int_var : string -> int -> unit
val set_string_var : string -> string -> unit
val set_float_var : string -> float -> unit
val set_bool_var : string -> bool -> unit
Set a variable with simple type
val make_var_type : ('a -> Netplex_types.encap) ->
(Netplex_types.encap -> 'a) -> (string -> 'a) * (string -> 'a -> unit)
Create get and set functions for any (monomorphic) type. For example, to create such function for a type foo, do

 
          module E = Netplex_encap.Make_encap(struct type t = foo end)
          let (get, set) = 
            make_var_type E.wrap E.unwrap
      

Read on for using functors to create get and set.

module type TYPE = sig .. end
Just a (monomorphic) type t
module type VAR_TYPE = sig .. end
A (monomorphic) type t with two functions get and set accessing the container variables
module Make_var_type: 
functor (T : TYPE) -> VAR_TYPE with type t = T.t
Creates get and set like make_var_type.

System control



System control



System control functions can be invoked from both container and controller contexts.
val system_shutdown : unit -> unit
Initiates a system shutdown (like the shutdown method of the controller)
val system_restart : unit -> unit
Initiates a system restart (like the restart method of the controller)

Inter-Container Communication



Inter-Container Communication



These functions can only be invoked from container contexts, except send_message.
val send_message : string -> string -> string array -> unit
send_message service_pattern msg_name msg_arguments: Sends a message to all services and message receivers matching service_pattern. The pattern may include the wildcard *.

See the Netplex_types.controller.send_message method for the notification guarantees.

This function can be invoked from both container and controller contexts.

val lookup : string -> string -> string option
lookup service_name protocol_name tries to find a Unix domain socket for the service and returns it.

On Win32, the returned path refers to a file describing the IPC mechanism. Use Netplex_sockserv.any_file_client_connector to convert the path into an RPC connector.

val lookup_container_sockets : string -> string -> string array
lookup_container_sockets service_name protocol_name: returns the Unix Domain paths of all container sockets for this service and protocol. These are the sockets declared with address type "container" in the config file.

On Win32, the returned paths refer to files describing the IPC mechanism. Use Netplex_sockserv.any_file_client_connector to convert the paths into RPC connectors.

Container sockets are explained here: Sending messages to individual containers


Direct container and admin interface access


val self_cont : unit -> Netplex_types.container
Returns the container running the code of the caller, or raise Not_in_container_thread if called from outside a container context.
val self_obj : unit ->
[ `Container of Netplex_types.container
| `Controller of Netplex_types.controller ]
Returns the container or the controller running the code of the caller, or raise Not_found if called from neither a container not a controller thread.
val current_sys_id : unit -> [ `Process of int | `Thread of int ]
Returns the system-dependent thread identifier of the caller (which must be in container or controller context)
val admin_connector : unit -> Rpc_client.mode2
Determines the admin socket of the controller, and returns an RPC client connector suitable for connecting with the admin interface of the controller. For instance to initiate a system shutdown from the context of a container:

         let conn = Netplex_cenv.admin_connector() in
         let client = Netplex_ctrl_clnt.Admin.V2.create_client2 conn in
         Netplex_ctrl_clnt.Admin.V2.system_shutdown client ();
         Rpc_client.shut_down client
       

Note that the admin interface is going to evolve, and it is advisable to avoid admin calls whenever possible.

This function must be called from container context.

val run_in_controller_context : Netplex_types.controller -> (unit -> unit) -> unit
run_in_controller_context ctrl f: Arranges that f() is executed in the context of the controller. This is only possible for multi-threading but not for multi-processing style! For programs using multi-processing, see Netplex_cenv.Make_lever for a workaround.

This function can be called from any thread. The function f is executed by pushing it onto the event queue, and calling it when the pushed event is reached. This is usually a safe point for many kinds of operations, but if controller methods are invoked the details are left unspecified.

For example, this allows it to start helper threads via Netplex_kit.add_helper_service at any time.

An example can be found here: Levers - calling controller functions from containers

val run_in_container_context : Netplex_types.container -> (unit -> unit) -> unit
run_in_container_context cont f: Arranges that f() is executed in the context of the container cont. This is only possible for multi-threading but not for multi-processing style!

This function can be called from any thread. The function f is executed by pushing it onto the event queue, and calling it when the pushed event is reached. This is usually a safe point for many kinds of operations, but if container method are invoked the details are left unspecified.

There is no guarantee that f is called anytime soon - if the container is busy with something else than with the event queue the execution will be blocked until these other activities are over.


Levers are a way to send messages to the controller, and to effectively run functions there that were previously registered.

More documentation: Levers - calling controller functions from containers

module type FUN_TYPE = sig .. end
Abstraction for function types s->t
module type LEVER = sig .. end
module Make_lever: 
functor (T : FUN_TYPE) -> LEVER with type s=T.s and type r=T.r
Creates a LEVER module from a function type as specified in FUN_TYPE

Persistent kernel objects


val pmanage : unit -> Netsys_pmanage.pmanage
Access the manager for persistent kernel objects with limited lifetime. Among these objects there are shared memory objects, and named semaphores. These objects can usually be deleted when the program finishes (or crashes), but this is not done automatically because of kernel persistency.

See Deleting persistent kernel objects for more information.


Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netencoding.Base64.decoding_pipe.html0000644000175000017500000004117212731530352024404 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Base64.decoding_pipe ?accept_spaces:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipeocamlnet-4.1.2/doc/html-main/type_Nethttp_client_conncache.html0000644000175000017500000005220612731530352023321 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client_conncache sig
  type transport_layer_id = int
  type inactive_data = {
    conn_trans : Nethttp_client_conncache.transport_layer_id;
    tls_stashed_endpoint : exn option;
  }
  type conn_state =
      [ `Active of <  > | `Inactive of Nethttp_client_conncache.inactive_data ]
  type peer =
      [ `Direct of string * int
      | `Direct_name of string * int
      | `Http_proxy of string * int
      | `Http_proxy_connect of (string * int) * (string * int)
      | `Socks5 of (string * int) * (string * int) ]
  class type connection_cache =
    object
      method close_all : unit -> unit
      method close_connection : Unix.file_descr -> unit
      method find_inactive_connection :
        Nethttp_client_conncache.peer ->
        Nethttp_client_conncache.transport_layer_id ->
        Unix.file_descr * Nethttp_client_conncache.inactive_data
      method find_my_connections : <  > -> Unix.file_descr list
      method get_connection_state :
        Unix.file_descr -> Nethttp_client_conncache.conn_state
      method set_connection_state :
        Unix.file_descr ->
        Nethttp_client_conncache.peer ->
        Nethttp_client_conncache.conn_state -> unit
    end
  class restrictive_cache : unit -> connection_cache
  class aggressive_cache : unit -> connection_cache
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_client.tls_socket_config.html0000644000175000017500000004110712731530352024112 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.tls_socket_config (module Netsys_crypto_types.TLS_CONFIG-> Rpc_client.socket_configocamlnet-4.1.2/doc/html-main/Unixqueue_select.sb_event_system-c.html0000644000175000017500000004776412731530352024267 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_select.sb_event_system

Class type Unixqueue_select.sb_event_system

class type sb_event_system = object .. end

method new_group : unit -> Unixqueue_util.group
method new_wait_id : unit -> Unixqueue_util.wait_id
method exists_resource : Unixqueue_util.operation -> bool
method add_resource : Unixqueue_util.group -> Unixqueue_util.operation * float -> unit
method add_weak_resource : Unixqueue_util.group -> Unixqueue_util.operation * float -> unit
method add_close_action : Unixqueue_util.group -> Unix.file_descr * (Unix.file_descr -> unit) -> unit
method add_abort_action : Unixqueue_util.group -> (Unixqueue_util.group -> exn -> unit) -> unit
method remove_resource : Unixqueue_util.group -> Unixqueue_util.operation -> unit
method add_handler : Unixqueue_util.group ->
(Unixqueue.event_system ->
Unixqueue_util.event Equeue.t -> Unixqueue_util.event -> unit) ->
unit
method add_event : Unixqueue_util.event -> unit
method clear : Unixqueue_util.group -> unit
method run : unit -> unit
method is_running : bool
method when_blocking : (unit -> unit) -> unit
method private setup : unit ->
Unix.file_descr list * Unix.file_descr list * Unix.file_descr list * float
method private queue_events : Unix.file_descr list * Unix.file_descr list * Unix.file_descr list -> bool
method private source : Unixqueue_util.event Equeue.t -> unit
ocamlnet-4.1.2/doc/html-main/Netplex_types.processor-c.html0000644000175000017500000004536412731530352022403 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.processor

Class type Netplex_types.processor

class type processor = object .. end
The processor is the object that is notified when a new TCP connection is accepted. The processor has to include the protocol interpreter that reads and write data on this connection. See Defining Custom Processors for an example how to define a processor.
Inherits
method process : when_done:(unit -> unit) ->
container -> Unix.file_descr -> string -> unit
A user-supplied function that is called when a new socket connection is established. The function can now process the requests arriving over the connection. It is allowed to use the event system of the container, and to return immediately (multiplexing processor). It is also allowed to process the requests synchronously and to first return to the caller when the connection is terminated.

The function must call when_done to indicate that it processed this connection completely.

The string argument is the protocol name.

method supported_ptypes : parallelization_type list
The supported parallelization types
ocamlnet-4.1.2/doc/html-main/type_Netplex_mbox.html0000644000175000017500000004615212731530352021003 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mbox sig
  val plugin : Netplex_types.plugin
  module type MBOX =
    sig
      type t
      type mbox
      val create : string -> Netplex_mbox.MBOX.mbox
      val send : Netplex_mbox.MBOX.mbox -> Netplex_mbox.MBOX.t -> unit
      val receive : Netplex_mbox.MBOX.mbox -> Netplex_mbox.MBOX.t
    end
  module Make_mbox_type :
    functor (T : Netplex_cenv.TYPE->
      sig
        type t = T.t
        type mbox
        val create : string -> mbox
        val send : mbox -> t -> unit
        val receive : mbox -> t
      end
end
ocamlnet-4.1.2/doc/html-main/type_Netgzip.input_inflate.html0000644000175000017500000004076212731530352022620 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.input_inflate Netchannels.in_obj_channel -> Netchannels.in_obj_channelocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.modify_http_reactor_config.html0000644000175000017500000004365112731530352027242 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.modify_http_reactor_config ?modify_http_protocol_config:(Nethttpd_kernel.http_protocol_config ->
                              Nethttpd_kernel.http_protocol_config) ->
?modify_http_processor_config:(Nethttpd_reactor.http_processor_config ->
                               Nethttpd_reactor.http_processor_config) ->
?config_reactor_synch:[ `Close | `Connection | `Flush | `Write ] ->
Nethttpd_reactor.http_reactor_config -> Nethttpd_reactor.http_reactor_config
ocamlnet-4.1.2/doc/html-main/type_Uq_lwt.html0000644000175000017500000004453712731530352017617 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_lwt sig
  class lwt_backend :
    Unixqueue.event_system ->
    object
      method private cleanup : unit
      method iter : bool -> unit
      method private register_readable :
        Unix.file_descr -> (unit -> unit) -> unit Lazy.t
      method private register_timer :
        float -> bool -> (unit -> unit) -> unit Lazy.t
      method private register_writable :
        Unix.file_descr -> (unit -> unit) -> unit Lazy.t
    end
end
ocamlnet-4.1.2/doc/html-main/Netftp_data_endpoint.read_in_record_channel-c.html0000644000175000017500000004371312731530352026275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.read_in_record_channel

Class Netftp_data_endpoint.read_in_record_channel

class read_in_record_channel : repr:text_data_repr -> Netchannels.in_obj_channel -> in_record_channel
Provides an in_record_channel that takes newline characters as EOR representation.

In this implementation, input_line can be used to read the full contents of a record (=line). However, input_line does not switch to the next record.


repr : Determines the newline character to use

ocamlnet-4.1.2/doc/html-main/Netmcore_process.html0000644000175000017500000005562712731530352020617 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_process

Module Netmcore_process

module Netmcore_process: sig .. end
Statically typed processes


This module provides a slightly higher-level view on processes, but is also a bit more restricted than the primitives in Netmcore.

Please read Netmcore_basics for an introduction into using this module. There is also Netmcore_tut with more advanced techniques.

type 'a fork_point 
A fork point can start a new process with argument 'a
type 'b join_point 
A join point can wait until a process finishes with a result 'b
val def_process : ('a -> 'b) -> 'a fork_point * 'b join_point
let (fp,jp) = def_process proc: Defines a process (which must happen in the master process), so that:

  • let pid = start fp arg: Starts the new process and passes the argument arg to it. The process runs proc arg which will finally result in a value r
  • let r_opt = join jp pid: Waits until the process identified by pid finishes, and returns the result as r_opt = Some r. On error, it returns None.
def_process should be called at module initialization time before any process is started. This interface is not designed for calling def_process later.
val start : ?inherit_resources:Netmcore.inherit_request ->
'a fork_point -> 'a -> Netmcore.process_id
let pid = start fp arg: Starts a new process at the fork point fp with argument arg. This means that the process is forked from the master process, and that the value of arg is sent to it using Marshal. The returned process ID is Netmulticore's own ID and not to be confused with the ID assigned by the operating system.

Option inherit_resources: Certain resources are only accessible by the process when they are inherited to it. This is the case for `Posix_shm_preallocated. This can be set to `All to inherit all inheritable resources, or to `Resources l to only inherit the resources of l. By default, no resources are inherited.

val join : 'b join_point -> Netmcore.process_id -> 'b option
let r_opt = join jp pid: Waits until the process pid finishes, and uses the join point jp to extract the result. The result is returned as Some r on success, and None on error. Result values are transmitted from the joining process to this function using Marshal. Errors include uncaught exceptions as well as unexpected process termination (exit, signal).

If the process referenced by pid is not an instance that belongs to jp, the function will fail.

This function must not be called from the master process (which is not allowed to block until a result is available).

val join_nowait : 'b join_point -> Netmcore.process_id -> 'b option
Like join, but it is not waited for the termination of the process. If the process is not yet done, this function returns None. It also returns None if the process terminated with an error or did not set a result value for other reasons.

Unlike join, this function can be called in the master process.

val release_fork_point : 'a fork_point -> unit
Releases a fork point so it is deleted from the internal resource table.
val release_join_point : 'b join_point -> unit
Releases a join point so it is deleted from the internal resource table.
ocamlnet-4.1.2/doc/html-main/type_Rpc_portmapper_clnt.Make'PMAP.html0000644000175000017500000016414712731530352023762 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt.Make'PMAP functor (U'C : Rpc_client_pre.USE_CLIENT->
  sig
    module V2 :
      sig
        type t = U'C.t
        val _program : Rpc_program.t
        val pmapproc_null :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res
        val pmapproc_null'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res) -> unit) ->
          unit
        val pmapproc_set :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res
        val pmapproc_set'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res) -> unit) ->
          unit
        val pmapproc_unset :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res
        val pmapproc_unset'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res) -> unit) ->
          unit
        val pmapproc_getport :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res
        val pmapproc_getport'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res) ->
           unit) ->
          unit
        val pmapproc_dump :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res
        val pmapproc_dump'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res) -> unit) ->
          unit
        val pmapproc_callit :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res
        val pmapproc_callit'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res) -> unit) ->
          unit
      end
    module V3 :
      sig
        type t = U'C.t
        val _program : Rpc_program.t
        val rpcbproc_null :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res
        val rpcbproc_null'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res) -> unit) ->
          unit
        val rpcbproc_set :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res
        val rpcbproc_set'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res) -> unit) ->
          unit
        val rpcbproc_unset :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res
        val rpcbproc_unset'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res) -> unit) ->
          unit
        val rpcbproc_getaddr :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res
        val rpcbproc_getaddr'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res) ->
           unit) ->
          unit
        val rpcbproc_dump :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res
        val rpcbproc_dump'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res) -> unit) ->
          unit
        val rpcbproc_callit :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res
        val rpcbproc_callit'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res) -> unit) ->
          unit
        val rpcbproc_gettime :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res
        val rpcbproc_gettime'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res) ->
           unit) ->
          unit
        val rpcbproc_uaddr2taddr :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res
        val rpcbproc_uaddr2taddr'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res) ->
           unit) ->
          unit
        val rpcbproc_taddr2uaddr :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res
        val rpcbproc_taddr2uaddr'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res) ->
           unit) ->
          unit
      end
    module V4 :
      sig
        type t = U'C.t
        val _program : Rpc_program.t
        val rpcbproc_null :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res
        val rpcbproc_null'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res) -> unit) ->
          unit
        val rpcbproc_set :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res
        val rpcbproc_set'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res) -> unit) ->
          unit
        val rpcbproc_unset :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res
        val rpcbproc_unset'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res) -> unit) ->
          unit
        val rpcbproc_getaddr :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res
        val rpcbproc_getaddr'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res) ->
           unit) ->
          unit
        val rpcbproc_dump :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res
        val rpcbproc_dump'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res) -> unit) ->
          unit
        val rpcbproc_bcast :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res
        val rpcbproc_bcast'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res) -> unit) ->
          unit
        val rpcbproc_gettime :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res
        val rpcbproc_gettime'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res) ->
           unit) ->
          unit
        val rpcbproc_uaddr2taddr :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res
        val rpcbproc_uaddr2taddr'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res) ->
           unit) ->
          unit
        val rpcbproc_taddr2uaddr :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res
        val rpcbproc_taddr2uaddr'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res) ->
           unit) ->
          unit
        val rpcbproc_getversaddr :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res
        val rpcbproc_getversaddr'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res) ->
           unit) ->
          unit
        val rpcbproc_indirect :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res
        val rpcbproc_indirect'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res) ->
           unit) ->
          unit
        val rpcbproc_getaddrlist :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res
        val rpcbproc_getaddrlist'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res) ->
           unit) ->
          unit
        val rpcbproc_getstat :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res
        val rpcbproc_getstat'async :
          U'C.t ->
          Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg ->
          ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res) ->
           unit) ->
          unit
      end
  end
ocamlnet-4.1.2/doc/html-main/Rpc_transport.html0000644000175000017500000005407012731530352020134 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_transport

Module Rpc_transport

module Rpc_transport: sig .. end
Low-level RPC transporters

type 't result = [ `Error of exn | `Ok of 't ] 
type 't result_eof = [ `End_of_file | `Error of exn | `Ok of 't ] 
type sockaddr = [ `Implied | `Sockaddr of Unix.sockaddr ] 
val string_of_sockaddr : sockaddr -> string
Convert to string, for debugging purposes
exception Error of string
Passed back as `Error. Such errors are fatal.

Note errors on stream connections: These are normally not recoverable. One should close the connection and open a new one.
type in_rule = [ `Accept | `Deny | `Drop | `Reject | `Reject_with of Rpc.server_error ] 
type in_record = [ `Accept of Rpc_packer.packed_value
| `Deny
| `Drop
| `Reject of Rpc_packer.packed_value
| `Reject_with of Rpc_packer.packed_value * Rpc.server_error ]
class type rpc_multiplex_controller = object .. end
val stream_rpc_multiplex_controller : ?dbg_name:string Pervasives.ref ->
?close_inactive_descr:bool ->
?preclose:(unit -> unit) ->
?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option ->
role:[ `Client | `Server ] ->
Unix.file_descr ->
Unixqueue.event_system -> rpc_multiplex_controller
The multiplex controller for stream encapsulation

  • close_inactive_descr: If true, the descriptor is closed when inactivated
  • preclose: This function is called just before the descriptor is closed.
  • tls: Enables TLS support for the passed config and the passed DNS peer name

val datagram_rpc_multiplex_controller : ?dbg_name:string Pervasives.ref ->
?close_inactive_descr:bool ->
?preclose:(unit -> unit) ->
role:[ `Client | `Server ] ->
Unix.file_descr ->
Unixqueue.event_system -> rpc_multiplex_controller
The multiplex controller for datagrams ((D)TLS not yet supported)
type internal_pipe = Netxdr.xdr_value Netsys_polypipe.polypipe 
val internal_rpc_multiplex_controller : ?dbg_name:string Pervasives.ref ->
?close_inactive_descr:bool ->
?preclose:(unit -> unit) ->
internal_pipe ->
internal_pipe ->
Unixqueue.event_system -> rpc_multiplex_controller
The multiplex controller for internal connections

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Rpc_auth_local.html0000644000175000017500000004515112731530352020213 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_auth_local

Module Rpc_auth_local

module Rpc_auth_local: sig .. end
Return the authentication method AUTH_LOCAL.

Note that you need another authentication method that operates at message level (like AUTH_NONE, AUTH_SYS, AUTH_DH), otherwise you will get an error Auth_too_weak. AUTH_LOCAL overrides the result of the other authentication method.


val server_auth_method : unit -> Rpc_server.auth_method
Return the authentication method AUTH_LOCAL.

Note that you need another authentication method that operates at message level (like AUTH_NONE, AUTH_SYS, AUTH_DH), otherwise you will get an error Auth_too_weak. AUTH_LOCAL overrides the result of the other authentication method.

val get_peer_credentials : Unix.file_descr -> int * int
Return the pair (euid,egid) for a Unix domain socket. The function raises Invalid_argument if it is not available for this operating system. (Generally, this should work on Linux, BSD, and Solaris, and OS with compatible system functions - supported methods are SO_PEERCRED, getpeerucred, and getpeereid).

Some OS support this only for named Unix domain sockets but not for socketpairs.

ocamlnet-4.1.2/doc/html-main/type_Netx509_pubkey.Key.html0000644000175000017500000005070412731530352021617 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey.Key sig
  val rsa_key : Netx509_pubkey.oid
  val rsassa_pss_key : Netx509_pubkey.oid
  val rsaes_oaep_key : Netx509_pubkey.oid
  val dsa_key : Netx509_pubkey.oid
  val dh_key : Netx509_pubkey.oid
  val ec_key : Netx509_pubkey.oid
  val ecdh_key : Netx509_pubkey.oid
  val ecmqv_key : Netx509_pubkey.oid
  val kea_key : Netx509_pubkey.oid
  val eddsa_key : Netx509_pubkey.oid
  val catalog : (string * string list * string * Netx509_pubkey.oid) list
  val private_key_format_of_key : Netx509_pubkey.oid -> string
  val create_rsassa_pss_alg_id :
    hash_function:Netx509_pubkey.hash_function ->
    maskgen_function:Netx509_pubkey.maskgen_function ->
    salt_length:int -> unit -> Netx509_pubkey.alg_id
  val create_rsassa_pss_key :
    hash_function:Netx509_pubkey.hash_function ->
    maskgen_function:Netx509_pubkey.maskgen_function ->
    salt_length:int -> Netx509_pubkey.pubkey -> Netx509_pubkey.pubkey
  val create_rsaes_oaep_alg_id :
    hash_function:Netx509_pubkey.hash_function ->
    maskgen_function:Netx509_pubkey.maskgen_function ->
    psource_function:string -> unit -> Netx509_pubkey.alg_id
  val create_rsaes_oaep_key :
    hash_function:Netx509_pubkey.hash_function ->
    maskgen_function:Netx509_pubkey.maskgen_function ->
    psource_function:string -> Netx509_pubkey.pubkey -> Netx509_pubkey.pubkey
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.parallelizer.html0000644000175000017500000004407712731530352023673 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.parallelizer object
  method create_mem_mutex : unit -> (unit -> unit) * (unit -> unit)
  method current_sys_id : [ `Process of int | `Thread of int ]
  method init : unit -> unit
  method ptype : Netplex_types.parallelization_type
  method start_thread :
    (Netplex_types.par_thread -> unit) ->
    Unix.file_descr list ->
    Unix.file_descr list ->
    string -> Netplex_types.logger -> Netplex_types.par_thread
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.client_endpoint_connector-c.html0000644000175000017500000004336712731530352026412 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.client_endpoint_connector

Class type Uq_engines_compat.client_endpoint_connector

class type client_endpoint_connector = object .. end

method connect : connect_address ->
Unixqueue.event_system ->
connect_status engine
ocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.SHA256.html0000644000175000017500000004430512731530352021735 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SHA256

Module Netmech_scram_sasl.SHA256

module SHA256: PROFILE 
Uses SHA-256 as hash function. The iteration count is limited to 100000. The mechanism name is "SCRAM-SHA-256".

val hash_function : Netsys_digests.iana_hash_fn
The hash function. We only allow functions where IANA registered an official name. Note that SCRAM is currently only specified for SHA1, although the hash function is easily exchangable.
val iteration_count_limit : int
The maximum iteration count supported
val announce_channel_binding : bool
Whether servers announce the availability of channel binding by adding "-PLUS" to the mechanism name.
ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.pseudo_async_in_channel.html0000644000175000017500000004104412731530352025474 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.pseudo_async_in_channel #Netchannels.raw_in_channel -> Uq_transfer.async_in_channelocamlnet-4.1.2/doc/html-main/Uq_transfer.pseudo_async_in_channel-c.html0000644000175000017500000004301212731530352024650 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.pseudo_async_in_channel

Class Uq_transfer.pseudo_async_in_channel

class pseudo_async_in_channel : #Netchannels.raw_in_channel -> async_in_channel
Takes a Netchannels.raw_in_channel as an asynchronous channel. It is always possible to input from this channel.

ocamlnet-4.1.2/doc/html-main/Uq_transfer.async_out_channel-c.html0000644000175000017500000004726712731530352023512 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.async_out_channel

Class type Uq_transfer.async_out_channel

class type async_out_channel = object .. end
An asynchrounous output channel provides methods to output data to a stream descriptor. It is based on raw_out_channel, which is defined by the Ocamlnet module Netchannels (see there for an introduction into the idea of using objects as I/O channels). An asynchronous channel can indicate that there is no space in the output buffer. Furthermore, one can request notification in the case that there is no space or again space in the output buffer.

method output : Bytes.t -> int -> int -> int
output s k n: Writes the substring of s beginning at index k with length n into the channel. The channel is free to accept only a portion of the string (or even nothing), and returns the number of bytes it accepts.
method close_out : unit -> unit
Closes the channel
method pos_out : int
Returns the number of characters output into the channel
method flush : unit -> unit
Flushes the channel. Asynchronous channels usually ignore flush requests. A potential meaning of flushing could be that no more data are accepted until the current buffer is completely processed. Implementing this is optional.
method can_output : bool
Whether output is possible, i.e. the output method accepts at least one byte
method request_notification : (unit -> bool) -> unit
After the notification has been requested, the passed function is be called whenever can_output changes its value (or might change its value). The function returns true if there is still interest in notification, and false if notification must be disabled.

There can be any number of parallel active notifications. It is allowed that a notification callback requests further notifications.

ocamlnet-4.1.2/doc/html-main/type_Netglob.html0000644000175000017500000006622212731530352017731 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob sig
  type glob_expr = Netglob.glob_expr_atom list
  and glob_expr_atom =
      [ `Brace of Netglob.glob_expr list
      | `Bracket of bool * Netglob.glob_set
      | `Literal of string
      | `Qmark
      | `Star
      | `Tilde of string ]
  and glob_set = < set : (int * int) list >
  type valid_glob_expr
  class type user_info =
    object
      method home_directory : string -> string
      method path_encoding : Netconversion.encoding option
    end
  class type glob_fsys =
    object
      method file_exists : string -> bool
      method file_is_dir : string -> bool
      method path_encoding : Netconversion.encoding option
      method read_dir : string -> string list
    end
  type glob_mode = [ `All_paths | `All_words | `Existing_paths ]
  type pattern = [ `Expr of Netglob.valid_glob_expr | `String of string ]
  exception Bad_glob_expr of string
  exception Unsupported_expr of string
  val parse_glob_expr :
    ?encoding:Netconversion.encoding ->
    ?enable_star:bool ->
    ?enable_qmark:bool ->
    ?enable_brackets:bool ->
    ?enable_braces:bool ->
    ?enable_tilde:bool ->
    ?enable_escape:bool -> string -> Netglob.valid_glob_expr
  val validate_glob_expr :
    Netconversion.encoding -> Netglob.glob_expr -> Netglob.valid_glob_expr
  val recover_glob_expr : Netglob.valid_glob_expr -> Netglob.glob_expr
  val encoding_of_glob_expr :
    Netglob.valid_glob_expr -> Netconversion.encoding
  val literal_glob_expr :
    Netconversion.encoding -> string -> Netglob.valid_glob_expr
  val print_glob_expr :
    ?escape_in_literals:bool -> Netglob.valid_glob_expr -> string
  val expand_glob_expr :
    ?user_info:Netglob.user_info ->
    ?expand_brace:bool ->
    ?expand_tilde:bool ->
    Netglob.valid_glob_expr -> Netglob.valid_glob_expr list
  val match_glob_expr :
    ?protect_period:bool ->
    ?protect_slash:bool ->
    ?encoding:Netconversion.encoding ->
    Netglob.valid_glob_expr -> string -> bool
  val split_glob_expr :
    Netglob.valid_glob_expr -> Netglob.valid_glob_expr list
  val check_rooted_glob_expr :
    Netglob.valid_glob_expr -> Netglob.valid_glob_expr option
  val check_directory_glob_expr :
    Netglob.valid_glob_expr -> Netglob.valid_glob_expr option
  val glob :
    ?encoding:Netconversion.encoding ->
    ?base_dir:string ->
    ?protect_period:bool ->
    ?fsys:Netglob.glob_fsys ->
    ?user_info:Netglob.user_info ->
    ?mode:Netglob.glob_mode -> Netglob.pattern -> string list
  class local_user_info : unit -> user_info
  val local_user_info : unit -> Netglob.user_info
  class local_fsys : ?encoding:Netconversion.encoding -> unit -> glob_fsys
  val local_fsys :
    ?encoding:Netconversion.encoding -> unit -> Netglob.glob_fsys
  class of_stream_fs : #Netfs.stream_fs -> glob_fsys
  val of_stream_fs : #Netfs.stream_fs -> Netglob.glob_fsys
end
ocamlnet-4.1.2/doc/html-main/Uq_datagram.html0000644000175000017500000004616412731530352017526 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_datagram

Module Uq_datagram

module Uq_datagram: sig .. end

Datagrams



type datagram_type = [ `Inet6_udp | `Inet_udp | `Unix_dgram ] 
- `Unix_dgram: Datagrams over Unix domain sockets
  • `Inet_udp: Internet v4 UDP protocol
  • `Inet6_udp: Internet v6 UDP protocol

class type wrapped_datagram_socket = object .. end
A wrapped_datagram_socket allows datagrams to be sent via proxies.
class type datagram_socket_provider = object .. end
This is a factory for wrapped_datagram_socket objects.
val datagram_provider : ?proxy:#datagram_socket_provider ->
datagram_type ->
Unixqueue.event_system ->
wrapped_datagram_socket Uq_engines.engine
This engine creates a datagram socket as demanded by the datagram_type, optionally using proxy for sending and receiving datagrams.

The socket is unconnected.

The socket is in non-blocking mode, and the close-on-exec flag is set.

ocamlnet-4.1.2/doc/html-main/Netplex_container.Debug.html0000644000175000017500000004174112731530352022003 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_container.Debug

Module Netplex_container.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables debug logging of containers
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.wrapped_datagram_socket.html0000644000175000017500000004426712731530352026655 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.wrapped_datagram_socket object
  method datagram_type : Uq_engines_compat.datagram_type
  method descriptor : Unix.file_descr
  method recvfrom :
    Bytes.t ->
    int -> int -> Unix.msg_flag list -> int * Uq_engines_compat.sockspec
  method sendto :
    Bytes.t ->
    int -> int -> Unix.msg_flag list -> Uq_engines_compat.sockspec -> int
  method shut_down : unit -> unit
  method socket_domain : Unix.socket_domain
  method socket_protocol : int
  method socket_type : Unix.socket_type
end
ocamlnet-4.1.2/doc/html-main/Netmech_digest_sasl.DIGEST_MD5.html0000644000175000017500000011262312731530352022662 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_sasl.DIGEST_MD5

Module Netmech_digest_sasl.DIGEST_MD5

module DIGEST_MD5: Netsys_sasl_types.SASL_MECHANISM 
The DIGEST-MD5 SASL mechanism (RFC 2831).

This mechanism is only provided to connect to old services; it shouldn't be used otherwise.

Key facts:

  • The password is not sent in the clear
  • Not only authenticates the client to the server, but the client can also find out whether the server knew the password, i.e. the server is also authenticated.
  • DIGEST-MD5 is vulnerable to man-in-the-middle attacks.
  • The MD5 hash is broken (too weak)
Only "auth" mode is supported (no integrity or privacy protection).

This implementation rejects servers that offer multiple realms.

This implementation supports both server_session_id (which is the nonce) and the client_session_id (the cnonce).

Parameters:

  • create_server_session understands: "realm" (optional), "nonce" (optional)
  • server_prop will return: "realm" (the realm selected by the client), "nonce", "digest-uri" (once known), "cnonce" (once known), "nc" (once known).
  • create_client_session understands: "realm" (optional), "cnonce" (optional), "digest-uri" (optional). If the digest-uri is not set, it defaults to "generic/generic".
  • client_prop will return: "cnonce", "realm" (once known; this is always the server realm), "nonce" (once known), "nc" (after sending the response).
  • The parameters mutual and secure are understood but ignored (there is mutual authentication anyway, and DIGEST is considered as secure method)
As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of DIGEST-MD5 should pass user names and passwords through Netsaslprep.saslprep.

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/type_Netplex_config.html0000644000175000017500000004610612731530352021302 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_config sig
  exception Config_error of string
  val read_config_file : string -> Netplex_types.config_file
  val repr_config_file :
    string -> Netplex_types.config_tree -> Netplex_types.config_file
  val read_netplex_config :
    Netplex_types.parallelization_type ->
    Netplex_types.logger_factory list ->
    Netplex_types.workload_manager_factory list ->
    Netplex_types.processor_factory list ->
    Netplex_types.config_file -> Netplex_types.netplex_config
  val read_tls_config :
    ?verify:((module Netsys_crypto_types.TLS_ENDPOINT->
             bool -> bool -> bool) ->
    Netplex_types.config_file ->
    Netplex_types.address ->
    (module Netsys_crypto_types.TLS_PROVIDER) option ->
    (module Netsys_crypto_types.TLS_CONFIG) option
end
ocamlnet-4.1.2/doc/html-main/type_Unixqueue_pollset.html0000644000175000017500000004166712731530352022077 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_pollset sig
  class pollset_event_system :
    Netsys_pollset.pollset -> Unixqueue_util.event_system
  val pollset_event_system :
    Netsys_pollset.pollset -> Unixqueue_util.event_system_t
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_common.html0000644000175000017500000015507412731530352021124 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common sig
  type representation =
      [ `MIME of Netmime.mime_message | `Simple of Netmime.mime_body ]
  type store = [ `File of string | `Memory ]
  exception Oversized
  exception Too_many_arguments
  class type cgi_argument =
    object
      method charset : string
      method content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method filename : string option
      method finalize : unit -> unit
      method name : string
      method open_value_rd : unit -> Netchannels.in_obj_channel
      method representation : Netcgi_common.representation
      method store : Netcgi_common.store
      method value : string
    end
  class type rw_cgi_argument =
    object
      method charset : string
      method content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method filename : string option
      method finalize : unit -> unit
      method name : string
      method open_value_rd : unit -> Netchannels.in_obj_channel
      method open_value_wr : unit -> Netchannels.out_obj_channel
      method representation : representation
      method ro : bool
      method set_value : string -> unit
      method store : store
      method value : string
    end
  class simple_arg : ?ro:bool -> string -> string -> rw_cgi_argument
  class mime_arg :
    ?work_around_backslash_bug:bool ->
    ?name:string -> Netmime.mime_message -> rw_cgi_argument
  module Cookie :
    sig
      type t = Nethttp.Cookie.t
      val make :
        ?max_age:int ->
        ?domain:string ->
        ?path:string ->
        ?secure:bool ->
        ?comment:string ->
        ?comment_url:string ->
        ?ports:int list -> string -> string -> Netcgi_common.Cookie.t
      val name : Netcgi_common.Cookie.t -> string
      val value : Netcgi_common.Cookie.t -> string
      val max_age : Netcgi_common.Cookie.t -> int option
      val domain : Netcgi_common.Cookie.t -> string option
      val path : Netcgi_common.Cookie.t -> string option
      val secure : Netcgi_common.Cookie.t -> bool
      val comment : Netcgi_common.Cookie.t -> string
      val comment_url : Netcgi_common.Cookie.t -> string
      val ports : Netcgi_common.Cookie.t -> int list option
      val set_value : Netcgi_common.Cookie.t -> string -> unit
      val set_max_age : Netcgi_common.Cookie.t -> int option -> unit
      val set_domain : Netcgi_common.Cookie.t -> string option -> unit
      val set_path : Netcgi_common.Cookie.t -> string option -> unit
      val set_secure : Netcgi_common.Cookie.t -> bool -> unit
      val set_comment : Netcgi_common.Cookie.t -> string -> unit
      val set_comment_url : Netcgi_common.Cookie.t -> string -> unit
      val set_ports : Netcgi_common.Cookie.t -> int list option -> unit
      val set : #Netmime.mime_header -> Netcgi_common.Cookie.t list -> unit
      val get : #Netmime.mime_header -> Netcgi_common.Cookie.t list
      val of_record : Nethttp.cookie -> Netcgi_common.Cookie.t
      val to_record : Netcgi_common.Cookie.t -> Nethttp.cookie
    end
  type config = {
    tmp_directory : string;
    tmp_prefix : string;
    permitted_http_methods : [ `DELETE | `GET | `HEAD | `POST | `PUT ] list;
    permitted_input_content_types : string list;
    input_content_length_limit : int;
    max_arguments : int;
    workarounds :
      [ `Backslash_bug
      | `MSIE_Content_type_bug
      | `Work_around_MSIE_Content_type_bug
      | `Work_around_backslash_bug ] list;
    default_exn_handler : bool;
  }
  type output_type =
      [ `Direct of string
      | `Transactional of
          Netcgi_common.config ->
          Netchannels.out_obj_channel -> Netchannels.trans_out_obj_channel ]
  val fix_MSIE_Content_type_bug : string -> string
  val is_MSIE : string -> bool
  class cgi_environment :
    config:Netcgi_common.config ->
    properties:(string * string) list ->
    input_header:(string * string) list ->
    Netchannels.out_obj_channel ->
    object
      val mutable header_not_sent : bool
      method cgi_auth_type : string
      method cgi_gateway_interface : string
      method cgi_https : bool
      method cgi_path_info : string
      method cgi_path_translated : string
      method cgi_properties : (string * string) list
      method cgi_property : ?default:string -> string -> string
      method cgi_query_string : string
      method cgi_remote_addr : string
      method cgi_remote_host : string
      method cgi_remote_ident : string
      method cgi_remote_user : string
      method cgi_request_method : string
      method cgi_script_name : string
      method cgi_server_name : string
      method cgi_server_port : int option
      method cgi_server_protocol : string
      method cgi_server_software : string
      method config : Netcgi_common.config
      method cookie : string -> Netcgi_common.Cookie.t
      method cookies : Netcgi_common.Cookie.t list
      method input_content_length : int
      method input_content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method input_content_type_string : string
      method input_header : Netmime.mime_header
      method input_header_field : ?default:string -> string -> string
      method input_header_fields : (string * string) list
      method log_error : string -> unit
      method multiple_input_header_field : string -> string list
      method multiple_output_header_field : string -> string list
      method out_channel : Netchannels.out_obj_channel
      method output_ch : Netchannels.out_obj_channel
      method output_header : Netmime.mime_header
      method output_header_field : ?default:string -> string -> string
      method output_header_fields : (string * string) list
      method protocol : Nethttp.protocol
      method send_output_header : unit -> unit
      method set_multiple_output_header_field : string -> string list -> unit
      method set_output_header_field : string -> string -> unit
      method set_output_header_fields : (string * string) list -> unit
      method set_status : Nethttp.http_status -> unit
      method user_agent : string
    end
  type other_url_spec = [ `Env | `None | `This of string ]
  type query_string_spec =
      [ `Args of Netcgi_common.rw_cgi_argument list
      | `Env
      | `None
      | `This of Netcgi_common.cgi_argument list ]
  type cache_control = [ `Max_age of int | `No_cache | `Unspecified ]
  type request_method =
      [ `DELETE | `GET | `HEAD | `POST | `PUT of Netcgi_common.cgi_argument ]
  val string_of_request_method : Netcgi_common.request_method -> string
  type arg_store_type =
      [ `Automatic
      | `Automatic_max of float
      | `Discard
      | `File
      | `File_max of float
      | `Memory
      | `Memory_max of float ]
  type arg_store =
      Netcgi_common.cgi_environment ->
      string -> Netmime.mime_header_ro -> Netcgi_common.arg_store_type
  class cgi :
    Netcgi_common.cgi_environment ->
    Netcgi_common.output_type ->
    Netcgi_common.request_method ->
    Netcgi_common.cgi_argument list ->
    object
      method argument : string -> Netcgi_common.cgi_argument
      method argument_exists : string -> bool
      method argument_value : ?default:string -> string -> string
      method arguments : Netcgi_common.cgi_argument list
      method at_exit : (unit -> unit) -> unit
      method environment : Netcgi_common.cgi_environment
      method finalize : unit -> unit
      method multiple_argument : string -> Netcgi_common.cgi_argument list
      method out_channel : Netchannels.trans_out_obj_channel
      method output : Netchannels.trans_out_obj_channel
      method request_method : Netcgi_common.request_method
      method set_header :
        ?status:Nethttp.http_status ->
        ?content_type:string ->
        ?content_length:int ->
        ?set_cookie:Nethttp.cookie list ->
        ?set_cookies:Netcgi_common.Cookie.t list ->
        ?cache:Netcgi_common.cache_control ->
        ?filename:string ->
        ?language:string ->
        ?script_type:string ->
        ?style_type:string ->
        ?fields:(string * string list) list -> unit -> unit
      method set_redirection_header :
        ?set_cookies:Netcgi_common.Cookie.t list ->
        ?fields:(string * string list) list -> string -> unit
      method url :
        ?protocol:Nethttp.protocol ->
        ?with_authority:Netcgi_common.other_url_spec ->
        ?with_script_name:Netcgi_common.other_url_spec ->
        ?with_path_info:Netcgi_common.other_url_spec ->
        ?with_query_string:Netcgi_common.query_string_spec -> unit -> string
    end
  val cgi_with_args :
    (Netcgi_common.cgi_environment ->
     Netcgi_common.output_type ->
     Netcgi_common.request_method -> Netcgi_common.cgi_argument list -> 'a) ->
    Netcgi_common.cgi_environment ->
    Netcgi_common.output_type ->
    Netchannels.in_obj_channel -> Netcgi_common.arg_store -> 'a
  exception HTTP of Nethttp.http_status * string
  val exn_handler_default :
    Netcgi_common.cgi_environment ->
    exn_handler:(Netcgi_common.cgi_environment -> (unit -> unit) -> unit) ->
    finally:(unit -> unit) -> (unit -> exn option) -> unit
  val error_page :
    Netcgi_common.cgi_environment ->
    Nethttp.http_status ->
    (string * string list) list -> string -> string -> unit
  val update_props_inheader :
    string * string ->
    (string * string) list * (string * string) list ->
    (string * string) list * (string * string) list
  val rm_htspace : (char -> bool) -> string -> int -> int -> string
  val rev_split : (char -> bool) -> string -> string list
  val is_prefix : string -> string -> bool
  type http_method = [ `DELETE | `GET | `HEAD | `POST | `PUT ]
  val string_of_http_method : Netcgi_common.http_method -> string
end
ocamlnet-4.1.2/doc/html-main/Unixqueue.standard_event_system-c.html0000644000175000017500000004260012731530352024104 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.standard_event_system

Class Unixqueue.standard_event_system

class standard_event_system : unit -> event_system
The standard implementation of an event system. It uses Unixqueue_pollset.pollset_event_system on top of Netsys_pollset_generic.standard_pollset.

ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_modes.Bundle.html0000644000175000017500000004115212731530352023616 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes.Bundle functor (C : CIPHERS-> Netsys_crypto_types.SYMMETRIC_CRYPTOocamlnet-4.1.2/doc/html-main/type_Nethttpd_services.Debug.html0000644000175000017500000004101212731530352023047 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_services.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Uq_engines.server_endpoint_acceptor-c.html0000644000175000017500000004420312731530352024673 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.server_endpoint_acceptor

Class type Uq_engines.server_endpoint_acceptor

class type server_endpoint_acceptor = object .. end

method server_address : connect_address
method multiple_connections : bool
method accept : unit -> (Unix.file_descr * inetspec option) engine
method shut_down : unit -> unit
ocamlnet-4.1.2/doc/html-main/Netcamlbox.html0000644000175000017500000011167312731530352017373 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcamlbox

Module Netcamlbox

module Netcamlbox: sig .. end
Camlboxes are a fast IPC mechanism to send Ocaml values from one process to another. Source and destination processes must run on the same machine (no network). The Ocaml value is copied to a shared memory object where it can be directly accessed by the receiver without unmarshalling step. This means the sender writes the value into the shared memory in a format that can immediately interpreted by the receiver.

A camlbox is owned by the single receiving process. Only this process (or a fork) can look for new messages and can read them. There can be any number of sending processes, i.e. we have a n:1 message passing scenario.

The receiver process creates the camlbox, and is seen as the owner. The receiver is accountible for deleting the camlbox when it is no longer needed.

The sender(s) can send messages to any existing camlbox. There is no notification whether the messages are actually read. The sender, however, blocks when the destination camlbox is full, and will only proceed when the receiver makes room for new messages. If there is space in the camlbox the sender does not need to synchronize with the receiver, i.e. it is possible to put a message into the box when the receiver is busy with something else (asynchronous send operation).

Camlboxes have a fixed capacity of messages, and the message slots have a fixed maximum length. The messages can have any type with only a few restrictions (e.g. no functions and no custom blocks). There is no check whether the sender and the receiver assume the same type of the messages. This is left to the user. Breaking this assumption will lead to unpredictable effects, including program crashes. It is strongly advised to only communicate between processes that run the same executable.

The user is also responsible for keeping only references to existing messages. It is possible to get a value pointer for a certain message via camlbox_get and then to delete the message. The user must no longer access the value - once the value is deleted it may be overwritten, and the program may crash. Another danger is that message values are modified so that pointers to heap values are put into the message. This may lead to delayed crashes when the heap value is moved to a different location or is even deleted by the garbage collector. There is nothing the camlbox implementation can do about that. If this is a problem, it is advised to use camlbox_get_copy instead which is not dangerous in this respect.

On the system level, camlboxes are stored in POSIX shared memory objects. These objects have kernel persistence and continue to live after the process creating the camlbox has terminated without unlinking the box.

This module requires Ocaml 3.11 or newer. The system must support POSIX shared memory and POSIX semaphores. Camlboxes may be used in multi-threaded programs as long as the values camlbox and camlbox_sender are not used by several threads at the same time.

Examples. There a few examples in the distribution tarball (examples/camlbox).

Multi-core: Camlboxes can be used to gain speed-ups on multi-cores. See examples/camlbox/README in the distribution tarball for an example how to accomplish this.

Integration into event-based programs: See the section below, Integration into event-based programs.



Since OCaml-4.01: This OCaml version changed the semantics of the built-in primitives caml_modify and caml_initialize. Essentially, it is no longer possible to modify OCaml values residing outside the regular OCaml heap. As we do this inside Netcamlbox, this change affects this library. Fortunately, there is a workaround on systems supporting weak symbols (all ELF systems and OS X): Here, caml_modify and caml_initialize are overridden by Netcamlbox so that they are again compatible. Note that this is a global modification of the runtime system!

Future versions of Ocamlnet may solve this problem differently.

type camlbox_address = string 
The address of a camlbox is a string that does not contain slashes. Addresses are system-global.
type 'a camlbox 
A camlbox may receive messages of type 'a
type 'a camlbox_sender 
An endpoint that may send messages of type 'a to a camlbox
exception Empty
exception Message_too_big
val create_camlbox : camlbox_address -> int -> int -> 'a camlbox
create_camlbox addr n size: Creates a new camlbox for up to n messages of size bytes. The messages are numbered from 0 to n-1. The camlbox is only meaningful for the creating process, and must not be directly accessed by other processes. Other processes can only send using a camlbox_sender.

It is an error if the camlbox already exists.

It is suggested that the result of create_camlbox is immediately coerced to the right type t, e.g.

        let box = (create_camlbox addr n size : t camlbox)
      
as this ensures type safety for all following operations.

Note that camlboxes have kernel persistence! They are not automatically deleted when the process finishes. Call unlink_camlbox to delete camlboxes.

val unlink_camlbox : camlbox_address -> unit
Removes the global name of the camlbox. All functions requiring a camlbox_address as input will not find the box anymore. The box, however, continues to exist until the receiver and the senders are done with it.
val format_camlbox : camlbox_address ->
Unix.file_descr -> int -> int -> 'a camlbox
format_camlbox addr fd n size: The file fd is mapped into memory, and formatted as camlbox.

In Ocamlnet-3.6, the function got the extra camlbox_address argument.

val camlbox_addr : 'a camlbox -> camlbox_address
returns the address
val camlbox_saddr : 'a camlbox_sender -> camlbox_address
returns the address
val camlbox_fd : camlbox_address -> Unix.file_descr
Opens a new file descriptor to this address
val camlbox_capacity : camlbox_address -> int
Returns the maximum number of messages n
val camlbox_bcapacity : 'a camlbox -> int
same for an already opened box
val camlbox_scapacity : 'a camlbox_sender -> int
same for a box already opened for sending
val camlbox_msg_size : camlbox_address -> int
Returns the max size of a message in bytes
val camlbox_bmsg_size : 'a camlbox -> int
same for an already opened box
val camlbox_smsg_size : 'a camlbox_sender -> int
same for a box already opened for sending
val camlbox_messages : camlbox_address -> int
Returns the number of messages at the moment
val camlbox_bmessages : 'a camlbox -> int
same for an already opened box
val camlbox_smessages : 'a camlbox_sender -> int
same for a box already opened for sending
val camlbox_get : 'a camlbox -> int -> 'a
camlbox_get box k: Returns message number k from box. The returned value lives in the camlbox, and using it is only safe as long as the camlbox exists and the message is not deleted.

If there is no message at k the exception Empty will be raised.

The result value must have the same type as the sent value. This is not checked, however. Violating this rule is likely to crash the program.

val camlbox_get_copy : 'a camlbox -> int -> 'a
camlbox_get box k: Returns a deep copy of message number k from box. This is safer than camlbox_get, because the returned value remains valid when the message is deleted from the box.

If there is no message at k the exception Empty will be raised.

The result value must have the same type as the sent value. This is not checked, however. Violating this rule is likely to crash the program.

val camlbox_delete : 'a camlbox -> int -> unit
camlbox_delete box k: Deletes the message number k from box. Any value obtained via camlbox_get for a message or a part of a message becomes invalid and must not be used anymore. There is no way to check this - violating this rule is likely to crash the program. (In doubt use camlbox_get_copy instead which cannot interfer with camlbox_delete.)

If there is no message at k the exception Empty will be raised.

val camlbox_wait : 'a camlbox -> int list
Waits until new messages arrive, and return the message numbers. A new message is only reported once by camlbox_wait. The order of the messages is not specified.

Only one thread at a time must wait for new messages.

It is allowed that this function returns the empty list.

val camlbox_cancel_wait : 'a camlbox -> unit
Cancels a camlbox_wait operation called by a different thread
val camlbox_sender : camlbox_address -> 'a camlbox_sender
Prepares for sending.

It is suggested that the result of camlbox_sender is immediately coerced to the right type t, e.g.

        let box = (camlbox_sender addr : t camlbox_sender)
      
as this ensures type safety for all following operations.
val camlbox_sender_of_fd : camlbox_address -> Unix.file_descr -> 'a camlbox_sender
Gets a sender for a file descriptor from camlbox_fd.

Ocamlnet-3.6: new arg camlbox_address

val camlbox_send : ?prefer:int ->
?slot:int Pervasives.ref -> 'a camlbox_sender -> 'a -> unit
Sends a message to a camlbox. The value must be boxed (neither char, bool, int, nor a variant type), and a number of restrictions apply:
  • The size of the representation must not exceed the maximum message size of the camlbox, or the exception Message_too_big is raised.
  • Objects, closures, and lazy values are not supported
  • Abstract and custom block values are not supported except bigarrays, int32, int64, and nativeint.
  • Atoms (like empty arrays) may cause problems when the message is extracted by camlbox_get because atoms are duplicated, and no longer unique. For example, a test if array=[||] then... is likely not to work. Use if Array.length array = 0 then..., or use camlbox_get_copy for extraction.
The value is copied to the receiving camlbox.

This function blocks until the receiving camlbox has free space.

Several threads may try to send messages at the same time.

prefer: suggests a slot for sending slot: the actual slot number is stored here

val camlbox_wake : 'a camlbox_sender -> unit
Sends an "empty message" - this only means that if the receiving thread is waiting for new messages it is interrupted and camlbox_wait will return the empty list.

This function is non-blocking.


Integration into event-based programs

The functions camlbox_wait and camlbox_send may both block the execution of the program when no message has arrived, and no space is available, respectively. This is a challenge for event-based programs where all waiting is bound to events on file descriptors.

Generally, Camlboxes use semaphores for speed. The results are good, often only 4 microseconds for sending and receiving a short message. This is only possible because semaphores implement a fast path where the help of the kernel is not needed, i.e. no context switch happens. This is basically incompatible with the style of waiting implemented for file descriptors, because this kind of waiting for an event must always go through the kernel, and is thus slower by design.

But anyway, what to do if Camlboxes need to be integrated into a program that bases already on file descriptor polling? Of course, speed will decrease, but maybe not dramatically. We assume here that the program uses Unixqueues as the basic data structure for organizing polling.

If the program can use the Netmulticore library, there is a very simple solution. The condition variables provided by this library allow the integration into Unixqueues, see Netmcore_condition. The condition variable is signalled whenever a new message is put into the Camlbox, and the receiver waits until this signal arrives. The function Netmcore_condition.wait_e permits it to integrate waiting into a Unixqueue.

Otherwise, if Netmulticore is no option (e.g. because the processes are unrelated that communicate via Camlboxes), the other workaround is to use threads. A special thread is set up which waits for new Camlbox messages. Whenever a message arrives, an engine is notified via a Uq_engines.signal_engine (which is thread-safe). This engine can run in a different thread.

module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netsys_types.html0000644000175000017500000005343412731530352020010 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_types

Module Netsys_types

module Netsys_types: sig .. end
Types for all Netsys modules


Bytes and characters



Bytes and characters



Remember that up to OCaml-4.01 there was only the string type, and strings were mutable (although frequently used as if there were immutable). Since OCaml-4.02 there is the immutable string and the mutable bytes type.

The general strategy for switching to the string/bytes scheme is to replace string everywhere with bytes, and to provide additional functions taking strings as input or output where it makes sense. There are exceptions, though, e.g. when the string acts as a key in a data structure.

The type name "string" also occurs in function names (e.g. "get_string") and in variant names (e.g. String_case). As we want to be backward compatible, we keep the old names for functions on bytes, and mark them as deprecated.

type memory = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t 
We consider 1-dimensional bigarrays of chars as memory buffers. They have the useful property that the garbage collector cannot relocate them, i.e. the address is fixed. Also, one can mmap a file, and connect the bigarray with shared memory.
type tbuffer = [ `Bytes of Bytes.t | `Memory of memory | `String of Bytes.t ] 
A tagged buffer. Note that the `String case is deprecated, and only provided for backward compatibility.
type tstring = [ `Bytes of Bytes.t | `Memory of memory | `String of string ] 
A tagged string which is considered as immutable. See also the support module Netstring_tstring.
class type mstring = object .. end
See Netxdr_mstring.mstring for documentation
exception EAGAIN_RD
exception EAGAIN_WR
A read or write cannot be done because the descriptor is in non-blocking mode and would block. This corresponds to the Unix.EAGAIN error but includes whether it was a read or write.

When the read or write is possible, the interrupted function should simply be again called.

These two exceptions are preferred by TLS providers.

exception TLS_switch_request
The server requested a rehandshake (this exception is thrown in the client)
exception TLS_switch_response of bool
The client accepted or denied a rehandshake (this exception is thrown in the server). true means acceptance.
exception TLS_error of string
A fatal error occurred (i.e. the session needs to be terminated). The string is a symbol identifying the error.
exception TLS_warning of string
A non-fatal error occurred. The interrupted function should be called again. The string is a symbol identifying the warning.
ocamlnet-4.1.2/doc/html-main/Netsys_digests.digest_ctx-c.html0000644000175000017500000004402312731530352022654 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_digests.digest_ctx

Class type Netsys_digests.digest_ctx

class type digest_ctx = object .. end

method add_memory : Netsys_types.memory -> unit
Add data
method add_subbytes : Bytes.t -> int -> int -> unit
Add data
method add_substring : string -> int -> int -> unit
Add data
method add_tstring : Netsys_types.tstring -> int -> int -> unit
Add data
method finish : unit -> string
Finish digestion, and return the digest
ocamlnet-4.1.2/doc/html-main/Netchannels.compl_out_channel-c.html0000644000175000017500000004726312731530352023454 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.compl_out_channel

Class type Netchannels.compl_out_channel

class type compl_out_channel = object .. end
Further methods usually supported by ocamlnet channel implementations. These methods are only reasonable when the channel is of blocking type, i.e. waits for output readiness when the underlying resource currently cannot process enough data. Implementations may choose to fail when they detect the channel is non-blocking.

method really_output : Bytes.t -> int -> int -> unit
Writes exactly as many octets to the channel as the second int argument specifies. The octets are taken from the string position denoted by the first int argument.
method really_output_string : string -> int -> int -> unit
Same for strings
method output_char : char -> unit
Writes exactly one character
method output_bytes : Bytes.t -> unit
Writes exactly the passed string
method output_string : string -> unit
Writes exactly the passed string
method output_byte : int -> unit
Writes exactly one byte passed as integer code
method output_buffer : Buffer.t -> unit
Writes exactly the contents of the buffer
method output_channel : ?len:int -> in_obj_channel -> unit
Writes the contents of an in_obj_channel until the end of the input channel is reached.


len : If passed, at most this number of octets are read from the input channel and written to this channel.
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.http_reactor.html0000644000175000017500000004226012731530352024341 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_reactor ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) ->
#Nethttpd_reactor.http_reactor_config ->
Unix.file_descr ->
object
  method close : unit -> unit
  method next_request : unit -> Nethttpd_reactor.http_reactive_request option
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.html0000644000175000017500000015544112731530352021176 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat sig
  exception Not_implemented of string
  module Netcgi_env :
    sig
      type input_mode = [ `Standard ]
      type input_state =
          [ `Received_body
          | `Received_header
          | `Receiving_body
          | `Receiving_header
          | `Start ]
      type output_mode = [ `Standard ]
      type output_state =
          [ `End
          | `Sending_body
          | `Sending_header
          | `Sending_part_body
          | `Sending_part_header
          | `Sent_body
          | `Sent_header
          | `Sent_part_body
          | `Sent_part_header
          | `Start ]
      type protocol_version = Nethttp.protocol_version
      type protocol_attribute = Nethttp.protocol_attribute
      type protocol = Nethttp.protocol
      type workaround =
          [ `Work_around_MSIE_Content_type_bug | `Work_around_backslash_bug ]
      type cgi_config = {
        tmp_directory : string;
        tmp_prefix : string;
        permitted_http_methods : string list;
        permitted_input_content_types : string list;
        input_content_length_limit : int;
        workarounds : Netcgi1_compat.Netcgi_env.workaround list;
      }
      val default_config : Netcgi1_compat.Netcgi_env.cgi_config
      val of_compat_config :
        Netcgi1_compat.Netcgi_env.cgi_config -> Netcgi.config
      val to_compat_config :
        Netcgi.config -> Netcgi1_compat.Netcgi_env.cgi_config
      class type cgi_environment =
        object
          method cgi_auth_type : string
          method cgi_gateway_interface : string
          method cgi_https : bool
          method cgi_path_info : string
          method cgi_path_translated : string
          method cgi_properties : (string * string) list
          method cgi_property : ?default:string -> string -> string
          method cgi_query_string : string
          method cgi_remote_addr : string
          method cgi_remote_host : string
          method cgi_remote_ident : string
          method cgi_remote_user : string
          method cgi_request_method : string
          method cgi_request_uri : string
          method cgi_script_name : string
          method cgi_server_name : string
          method cgi_server_port : int option
          method cgi_server_protocol : string
          method cgi_server_software : string
          method config : Netcgi1_compat.Netcgi_env.cgi_config
          method cookies : (string * string) list
          method input_ch : Netchannels.in_obj_channel
          method input_content_length : int
          method input_content_type :
            string * (string * Netmime_string.s_param) list
          method input_content_type_string : string
          method input_header : Netmime.mime_header
          method input_header_field : ?default:string -> string -> string
          method input_header_fields : (string * string) list
          method input_state : Netcgi1_compat.Netcgi_env.input_state
          method log_error : string -> unit
          method multiple_input_header_field : string -> string list
          method multiple_output_header_field : string -> string list
          method output_ch : Netchannels.out_obj_channel
          method output_header : Netmime.mime_header
          method output_header_field : ?default:string -> string -> string
          method output_header_fields : (string * string) list
          method output_state : Netcgi1_compat.Netcgi_env.output_state
          method protocol : Netcgi1_compat.Netcgi_env.protocol
          method send_output_header : unit -> unit
          method set_input_state :
            Netcgi1_compat.Netcgi_env.input_state -> unit
          method set_multiple_output_header_field :
            string -> string list -> unit
          method set_output_header_field : string -> string -> unit
          method set_output_header_fields : (string * string) list -> unit
          method set_output_state :
            Netcgi1_compat.Netcgi_env.output_state -> unit
          method set_status : Nethttp.http_status -> unit
          method user_agent : string
        end
      val to_compat_environment :
        Netcgi.cgi_environment -> Netcgi1_compat.Netcgi_env.cgi_environment
      val of_compat_environment :
        Netcgi1_compat.Netcgi_env.cgi_environment -> Netcgi.cgi_environment
    end
  module Netcgi_types :
    sig
      class type simple_message = Netmime.mime_body
      type store = [ `File of string | `Memory ]
      type representation =
          [ `MIME of Netmime.mime_message
          | `Simple of Netcgi1_compat.Netcgi_types.simple_message ]
      class type cgi_argument =
        object
          method charset : string
          method content_type : string
          method content_type_params : (string * Netmime_string.s_param) list
          method filename : string option
          method finalize : unit -> unit
          method name : string
          method open_value_rd : unit -> Netchannels.in_obj_channel
          method open_value_wr : unit -> Netchannels.out_obj_channel
          method representation : Netcgi1_compat.Netcgi_types.representation
          method ro : bool
          method set_value : string -> unit
          method store : Netcgi1_compat.Netcgi_types.store
          method value : string
        end
      val to_compat_argument :
        Netcgi.cgi_argument -> Netcgi1_compat.Netcgi_types.cgi_argument
      val of_compat_argument :
        Netcgi1_compat.Netcgi_types.cgi_argument -> Netcgi.cgi_argument
      type cgi_cookie =
        Nethttp.netscape_cookie = {
        cookie_name : string;
        cookie_value : string;
        cookie_expires : float option;
        cookie_domain : string option;
        cookie_path : string option;
        cookie_secure : bool;
      }
      type status = Nethttp.http_status
      type request_method =
          [ `DELETE
          | `GET
          | `HEAD
          | `POST
          | `PUT of Netcgi1_compat.Netcgi_types.cgi_argument ]
      type cache_control = [ `Max_age of int | `No_cache | `Unspecified ]
      type query_string_spec =
          [ `Args of Netcgi1_compat.Netcgi_types.cgi_argument list
          | `Current
          | `Initial
          | `None ]
      type other_url_spec = [ `Env | `None | `This of string ]
      class type cgi_activation =
        object
          method argument :
            string -> Netcgi1_compat.Netcgi_types.cgi_argument
          method argument_value : ?default:string -> string -> string
          method arguments :
            (string * Netcgi1_compat.Netcgi_types.cgi_argument) list
          method delete_argument : ?fin:bool -> string -> unit
          method environment : Netcgi1_compat.Netcgi_env.cgi_environment
          method finalize : unit -> unit
          method initial_argument :
            string -> Netcgi1_compat.Netcgi_types.cgi_argument
          method initial_argument_value : ?default:string -> string -> string
          method initial_arguments :
            (string * Netcgi1_compat.Netcgi_types.cgi_argument) list
          method initial_multiple_argument :
            string -> Netcgi1_compat.Netcgi_types.cgi_argument list
          method multiple_argument :
            string -> Netcgi1_compat.Netcgi_types.cgi_argument list
          method output : Netchannels.trans_out_obj_channel
          method request_method : Netcgi1_compat.Netcgi_types.request_method
          method set_arguments :
            ?fin:bool ->
            Netcgi1_compat.Netcgi_types.cgi_argument list -> unit
          method set_header :
            ?status:Netcgi1_compat.Netcgi_types.status ->
            ?content_type:string ->
            ?cache:Netcgi1_compat.Netcgi_types.cache_control ->
            ?filename:string ->
            ?language:string ->
            ?script_type:string ->
            ?style_type:string ->
            ?set_cookie:Netcgi1_compat.Netcgi_types.cgi_cookie list ->
            ?fields:(string * string list) list -> unit -> unit
          method set_redirection_header : string -> unit
          method update_argument :
            ?fin:bool -> Netcgi1_compat.Netcgi_types.cgi_argument -> unit
          method update_multiple_argument :
            ?fin:bool ->
            Netcgi1_compat.Netcgi_types.cgi_argument list -> unit
          method url :
            ?protocol:Netcgi1_compat.Netcgi_env.protocol ->
            ?with_authority:Netcgi1_compat.Netcgi_types.other_url_spec ->
            ?with_script_name:Netcgi1_compat.Netcgi_types.other_url_spec ->
            ?with_path_info:Netcgi1_compat.Netcgi_types.other_url_spec ->
            ?with_query_string:Netcgi1_compat.Netcgi_types.query_string_spec ->
            unit -> string
        end
      val to_compat_activation :
        Netcgi.cgi -> Netcgi1_compat.Netcgi_types.cgi_activation
      val of_compat_activation :
        Netcgi1_compat.Netcgi_types.cgi_activation -> Netcgi.cgi
    end
  module Netcgi :
    sig
      type argument_processing = [ `Automatic | `File | `Memory ]
      type operating_type =
          [ `Direct of string
          | `Transactional of
              Netcgi1_compat.Netcgi_env.cgi_config ->
              Netchannels.out_obj_channel ->
              Netchannels.trans_out_obj_channel ]
      class simple_argument :
        ?ro:bool -> string -> string -> Netcgi_types.cgi_argument
      class mime_argument :
        ?work_around_backslash_bug:bool ->
        string -> Netmime.mime_message -> Netcgi_types.cgi_argument
      class std_activation :
        ?env:Netcgi1_compat.Netcgi_env.cgi_environment ->
        ?processing:(string ->
                     Netmime.mime_header ->
                     Netcgi1_compat.Netcgi.argument_processing) ->
        ?operating_type:Netcgi1_compat.Netcgi.operating_type ->
        unit -> Netcgi_types.cgi_activation
      val buffered_transactional_optype :
        Netcgi1_compat.Netcgi.operating_type
      val tempfile_transactional_optype :
        Netcgi1_compat.Netcgi.operating_type
    end
end
ocamlnet-4.1.2/doc/html-main/Netplex_mbox.MBOX.html0000644000175000017500000004450112731530352020502 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mbox.MBOX

Module type Netplex_mbox.MBOX

module type MBOX = sig .. end
The type of mailboxes mbox with messages of type t

type t 
The type of messages
type mbox 
The type of the mailboxes
val create : string -> mbox
Creates a new mailbox with the passed name, or opens an existing mailbox. Names are global to the whole Netplex process system.
val send : mbox -> t -> unit
Send a message to this box. If the box is full, it is waited until the box is free again. If several senders wait for the box, one sender is selected.
val receive : mbox -> t
Receive a message: It is waited until a sender puts a message into the box. If several receivers wait for the box, one receiver is selected.
ocamlnet-4.1.2/doc/html-main/Nethttp_client.pipeline-c.html0000644000175000017500000010160612731530352022302 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.pipeline

Class Nethttp_client.pipeline

class pipeline : object .. end
A pipeline is a queue of HTTP calls to perform

A

pipeline object is a FIFO queue of HTTP calls. It is called "pipeline" because it is processed asynchronously: Requests may be sent to the HTTP server independently of whether responses of the previous requests already arrived or not.

Furthermore, a pipeline object may keep connections to several servers at once. (More exactly, it has a FIFO queue for every server it is connected with.)

The pipeline object keeps track what is happening, so you need not to care about the details of communications. The API is simple: Create a pipeline object, do some setup (add authentication methods; configure the proxy to use), add the requests, and run the pipeline. The rest is done automatically. To get the results, you can either memorize the requests you wanted to know yourself and ask every request object about the reply of the server; or you can specify that a callback function should be called once the request is processed (with positive or negative result). It is possible to add further requests to the pipeline from within these callback functions.

If you want to have several pipelines, or some cooperation with other network services, you may specify a Unixqueue.event_system. For example, to have two pipelines working concurrently:

 let ues = Unixqueue.create_unix_event_system() in
 let p1 = new pipeline in
 let p2 = new pipeline in
 p1 # set_event_system ues;
 p2 # set_event_system ues;
 Unixqueue.run ues             (* run p1 and p2 in parallel *)
 

This works not only with pipelines, but with every network client or server which is compatible with the Unixqueue design.

method event_system : Unixqueue.event_system
Returns the event system
method set_event_system : Unixqueue.event_system -> unit
Sets the event system. Must be called before the first call is added
method connection_cache : connection_cache
The current connection cache. By default, a private restrictive cache is used.
method set_connection_cache : connection_cache -> unit
Set the connection cache. This must happen before the first call is added.
method add_auth_handler : auth_handler -> unit
adds a new-style authentication handler
method set_proxy : string -> int -> unit
set_proxy name port: sets that an HTTP proxy name listening on port is to be used
method set_proxy_auth : insecure:bool -> string -> string -> unit
sets user and password for the proxy. Works for both "digest" and "basic" mechanisms (the latter only if the insecure flag is set). Any realm is acceptable.
method avoid_proxy_for : string list -> unit
sets a list of host names or domain suffixes for which no proxy should be used. e.g. "localhost"; ".our.net"
method set_proxy_from_environment : insecure:bool -> unit -> unit
Inspect the environment variables http_proxy and no_proxy and set the proxy options from them. If insecure is set, basic authentication is enabled (otherwise only secure auth methods like Digest).
method set_socks5_proxy : string -> int -> unit
Sets that a SOCKS version 5 proxy is used at this host and port. There is no authentication. The avoid_proxy_for setting is honoured.
method configure_transport : transport_layer_id ->
transport_channel_type -> unit
configure_transport id transport: Configures that messages with transport layer ID id are exchanged on transport.

By default, there is only a configuration for Nethttp_client.http_trans_id, i.e. for normal unencrypted channels.

method set_tls_cache : tls_cache -> unit
Sets the TLS cache (NB. The default cache is null_tls_cache)
method set_transport_proxy : transport_layer_id ->
string ->
int -> (string * string * bool) option -> proxy_type -> unit
set_transport_proxy id host port auth ptype: Sets a special proxy for the transport identified by id. This overrides set_proxy, set_proxy_auth, and set_socks5_proxy for the given transport.

The auth triple contains (user,password,insecure).

method set_transport_proxy_from_environment : insecure:bool -> (string * transport_layer_id) list -> unit
Like set_proxy_from_environment, this method inspects environment variables and configures the proxy settings. This function, however, is more flexible, and can use different environment variables for different transports.

The argument list has pairs (var_name, id) meaning that the environment variable var_name configures the proxy for id. For instance,

 [("http_proxy", http_trans_id); ("https_proxy", https_trans_id)] 
means that these two variables are used for the respective transports.

The variable "no_proxy" is interpreted anyway.

insecure: whether basic authentication is enabled.

method reset : unit -> unit
Empties the pipeline and inactivates any open connection. The currently active operation is interrupted, and every request with response is set to No_reply (i.e. you get the exception No_reply if you try to access the response). If there are callbacks for these requests, the callback functions are invoked. The queues of open requests and replies are cleared. All connections to all servers are inactivated.

Inactivation means that open connections are given back to the connection cache for further reuse if the state of the connection allows this; otherwise the connections are closed.

method add : http_call -> unit
Adds the call to the end of the pipeline. One must not add calls that have already been served.
method add_with_callback : http_call -> (http_call -> unit) -> unit
Adds the call to the end of the pipeline.

After the call has been processed, the callback function is called. This function is called for every call that leaves the pipeline, it does not matter whether processing was successful or not. Invoke status on the message to get what happened; either some status information from the server is available (perhaps OK status), or an exception is indicated.

method add_e : http_call -> http_call Uq_engines.engine
The same as engine: The call c is added to the pipeline, and when it is processed, the returned engine transitions to the state `Done c.
method proxy_type : string -> proxy_type option
proxy_type url returns Some pt if a proxy would be used for this url, and None if a direct connection would be made.
method proxy_type_of_call : http_call -> proxy_type option
Same for an already created call object
method transport_layer : http_call -> transport_layer_id
Reports the current transport of this call
method run : unit -> unit
Runs through the requests in the pipeline. If a request can be fulfilled, i.e. the server sends a response, the state of the request is set and the request is removed from the pipeline. If a request cannot be fulfilled (no response, bad response, network error), the exception is stored in the http_call object and will be raised once the state of the object is queried.

Under certain conditions (serious network errors) run does not catch the exception; it simply cleans its own state up (aborting the errorneous network connection). In this case, simply invoke run again to continue. run terminates normally if the pipeline becomes empty.

The engine handles the following HTTP return codes itself:

  • 100: This is an intermediate return code
  • 301: The redirection is followed if configured
  • 302: The redirection is followed if configured
  • 401: Content server authentication
  • 407: Proxy server authentication
All other return codes remain uninterpreted, it is up to the caller of this function to react on them.
method get_options : http_options
method set_options : http_options -> unit
Get/Set the available options for the HTTP engine. The new options will take into effect immediately.
method number_of_open_messages : int
Returns the number of messages which are still in the pipeline.
method number_of_open_connections : int
Returns the number of connections which are open at the same time and currently being used by this object (i.e. connections returned to the cache do not count)
method connections : (string * int * int) list
Reports which connections exist: (host, port, queue_length)
method cnt_new_connections : int
Counts new connections (or better: attempts to establish connections)
method cnt_timed_out_connections : int
Counts connections given up because of timeouts
method cnt_crashed_connections : int
Counts connections with network or protocol errors
method cnt_server_eof_connections : int
Counts connections the server terminated with EOF
method cnt_successful_connections : int
Counts connections closed because pipelines become empty
method cnt_failed_connections : int
Counts totally failed connections (no more reconnects allowed)
method reset_counters : unit -> unit
ocamlnet-4.1.2/doc/html-main/type_Netchannels.lift_rec_out_channel.html0000644000175000017500000004110212731530352024734 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.lift_rec_out_channel ?start_pos_out:int ->
Netchannels.rec_out_channel -> Netchannels.out_obj_channel
ocamlnet-4.1.2/doc/html-main/type_Uq_server.direct_acceptor.html0000644000175000017500000004143212731530352023437 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_server.direct_acceptor ?close_on_shutdown:bool ->
?preclose:(unit -> unit) ->
Unix.file_descr ->
Unixqueue.event_system -> Uq_server.server_endpoint_acceptor
ocamlnet-4.1.2/doc/html-main/Uq_socks5.html0000644000175000017500000004513012731530352017145 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_socks5

Module Uq_socks5

module Uq_socks5: sig .. end
This module implements a SOCKS version 5 client (see RFC 1928) for use with the Uq_engines.connector, Uq_engines.listener, and Uq_engines.datagram_provider engine factories.

This implementation supports IPv4 and IPv6.



This module implements a SOCKS version 5 client (see RFC 1928) for use with the Uq_engines.connector, Uq_engines.listener, and Uq_engines.datagram_provider engine factories.

This implementation supports IPv4 and IPv6.

exception Socks_error of string
Raised when error messages of the SOCKS proxy are received, or because of other SOCKS-related problems.
class proxy_client : Uq_engines.connect_address -> object .. end
The object created by new proxy_client addr can be passed as proxy to the Uq_engines.connector, Uq_engines.listener, and Uq_engines.datagram_provider functions to use the SOCKS proxy for connections, servers, and datagram socket, respectively.
ocamlnet-4.1.2/doc/html-main/Netplex_sharedvar.Make_vv.html0000644000175000017500000004533012731530352022340 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sharedvar.Make_vv

Functor Netplex_sharedvar.Make_vv

module Make_vv: 
functor (T : Netplex_cenv.TYPE) -> VV_TYPE with type t = T.t
Parameters:
T : Netplex_cenv.TYPE

type t 
type var 
val access : string -> var
val get : var -> t
val set : var -> t -> unit
val version : var -> int64
val update : var -> bool
ocamlnet-4.1.2/doc/html-main/Netsys_pmanage.pmanage-c.html0000644000175000017500000004661112731530352022102 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pmanage.pmanage

Class type Netsys_pmanage.pmanage

class type pmanage = object .. end

method register_file : string -> unit
Register a temporary file
method unregister_file : string -> unit
Unregister a temporary file
method register_posix_shm : string -> unit
Register a POSIX shared memory object identified by this path
method unregister_posix_shm : string -> unit
Unregister a POSIX shared memory object identified by this path
method register_posix_sem : string -> unit
Register a POSIX named semaphore identified by this path
method unregister_posix_sem : string -> unit
Unregister a POSIX named semaphore identified by this path
method register_sem_cont : string -> unit
Register a semaphore container (see Netsys_sem)
method unregister_sem_cont : string -> unit
Unregister a semaphore container (see Netsys_sem)
method registered : pm_obj list
Return the registered objects
method register : pm_obj list -> unit
Mass-register a list of objects
method unlink : unit -> unit
Delete all registered objects
ocamlnet-4.1.2/doc/html-main/type_Netgzip.inflating_pipe.html0000644000175000017500000004067412731530352022751 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.inflating_pipe unit -> Netchannels.io_obj_channelocamlnet-4.1.2/doc/html-main/Netplex_kit.v_processor-c.html0000644000175000017500000004333512731530352022347 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.v_processor

Class type virtual Netplex_kit.v_processor

class type virtual v_processor = object .. end
Same as processor, but the methods process and supported_ptypes are flagged as virtual
Inherits
  • processor_hooks

method virtual process : when_done:(unit -> unit) ->
Netplex_types.container -> Unix.file_descr -> string -> unit
method virtual supported_ptypes : Netplex_types.parallelization_type list
ocamlnet-4.1.2/doc/html-main/type_Netpop.client.html0000644000175000017500000005122412731530352021055 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpop.client Netchannels.in_obj_channel ->
Netchannels.out_obj_channel ->
object
  method apop : user:string -> pass:string -> unit
  method auth :
    Netsys_sasl.sasl_mechanism ->
    string ->
    string ->
    Netsys_sasl.credentials -> (string * string * bool) list -> unit
  method capa : unit -> (string * string list) list
  method capabilities : (string * string list) list
  method close : unit -> unit
  method dele : msgno:int -> unit
  method gssapi_props : Netsys_gssapi.client_props option
  method list : ?msgno:int -> unit -> (int, int * string) Hashtbl.t
  method noop : unit -> unit
  method pass : pass:string -> unit
  method quit : unit -> unit
  method retr : msgno:int -> Netchannels.in_obj_channel
  method rset : unit -> unit
  method stat : unit -> int * int * string
  method state : Netpop.state
  method stls :
    peer_name:string option -> Netsys_crypto_types.tls_config -> unit
  method tls_endpoint : Netsys_crypto_types.tls_endpoint option
  method tls_session_props : Nettls_support.tls_session_props option
  method top : ?lines:int -> msgno:int -> unit -> Netchannels.in_obj_channel
  method uidl : ?msgno:int -> unit -> (int, string) Hashtbl.t
  method user : user:string -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_posix.Debug.html0000644000175000017500000004100512731530352022063 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_posix.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Nethttp.Cookie.html0000644000175000017500000005364212731530352021177 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.Cookie sig
  type t
  val make :
    ?max_age:int ->
    ?domain:string ->
    ?path:string ->
    ?secure:bool ->
    ?comment:string ->
    ?comment_url:string ->
    ?ports:int list -> string -> string -> Nethttp.Cookie.t
  val name : Nethttp.Cookie.t -> string
  val value : Nethttp.Cookie.t -> string
  val domain : Nethttp.Cookie.t -> string option
  val path : Nethttp.Cookie.t -> string option
  val ports : Nethttp.Cookie.t -> int list option
  val max_age : Nethttp.Cookie.t -> int option
  val secure : Nethttp.Cookie.t -> bool
  val comment : Nethttp.Cookie.t -> string
  val comment_url : Nethttp.Cookie.t -> string
  val set_value : Nethttp.Cookie.t -> string -> unit
  val set_max_age : Nethttp.Cookie.t -> int option -> unit
  val set_domain : Nethttp.Cookie.t -> string option -> unit
  val set_path : Nethttp.Cookie.t -> string option -> unit
  val set_secure : Nethttp.Cookie.t -> bool -> unit
  val set_comment : Nethttp.Cookie.t -> string -> unit
  val set_comment_url : Nethttp.Cookie.t -> string -> unit
  val set_ports : Nethttp.Cookie.t -> int list option -> unit
  val of_netscape_cookie : Nethttp.netscape_cookie -> Nethttp.Cookie.t
  val to_netscape_cookie : Nethttp.Cookie.t -> Nethttp.netscape_cookie
end
ocamlnet-4.1.2/doc/html-main/Netmech_spnego_http.html0000644000175000017500000005705312731530352021275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_spnego_http

Module Netmech_spnego_http

module Netmech_spnego_http: sig .. end
SPNEGO (GSSAPI) authentication for HTTP


This module enables the Negotiate authentication method for HTTP, which is an encapsulation of the SPNEGO protocol. SPNEGO in turn is a layer on top of GSSAPI, and adds mechanism negotiation.

This is the usual way of kerberizing HTTP.

This implementation of the Negotiate method requires a HTTPS connection by default. Running it over unencrypted HTTP would be possible, but we don't do it because the additional security can be easily lost. In particular, a man-in-the-middle could steal credentials, or he could run a downgrade attack on the authentication method (and replace it by e.g. "basic").

The Negotiate authentication method is somewhat special because it implicitly authenticates the whole connection, and not only a single message. At least this is what MS Windows implements, the reference implementation of this authentication method. Other implementations nevertheless require per-message authentication, e.g. Apache's mod_auth_kerb. Both behaviors are basically compatible to each other if implemented with some care.

In order to keep authenticated messages somewhat separate, this client only submits requests bearing Negotiate headers on TCP connections that have been specially created for this purpose. Basically, the authenticated communication with the server is seen as a separate transport subsystem. The flow of requests/responses is as follows:

  • A fresh HTTP request does not carry any authentication data. Because of this, it is sent over the normal transports to the server.
  • The server replies with a 401 response and an SPNEGO token.
  • The client authenticates the request (usually this is a one step action)
  • The authenticated request cannot be sent over the existing TCP connection. A second connection is created which will be used for authenticated requests only.
  • The request is sent over this connection.
  • The server responds with content data
This way we can be sure that requests are handled normally that either need not to be authenticated at all, or that are authenticated with different methods.

Technically, the route of the HTTP request depends on the transport_layer ID. As long as the HTTP request has an ID of Nethttp_client.https_trans_id, it will go over the normal transports. If the ID changes to Nethttp_client.spnego_trans_id, the separate transports for SPNEGO are used.

If it is already known that the HTTP request needs to be authenticated with SPNEGO, the authentication protocol can be abbreviated by directly switching to Nethttp_client.spnego_trans_id:

c # set_transport_layer Nethttp_client.spnego_trans_id
    

The effect is that only one request/response cycle is needed to process the request c (except it is the very first request).

Although GSSAPI mechanisms, and in particular Kerberos often do not require a password, you need to set up a "key" object. User and password of this key are ignored. The realm, however, must be set to the fixed string "SPNEGO" (and not to the Kerberos realm). A full example how to use this method:

module A =
  Netmech_spnego_http.SPNEGO(Netmech_spnego_http.Default)(Netgss.System)

let keys = new Nethttp_client.key_ring ()
let () =
  keys # add_key (key ~user:"" ~password:"" ~realm:"SPNEGO" ~domain:[])
let a = 
  new Nethttp_client.generic_auth_handler
        keys [ (module A : Nethttp.HTTP_MECHANISM) ]
let p = new Nethttp_client.pipeline
let () =
  p # add_auth_handler a
let c = new Nethttp_client.get "https://gps.dynxs.de/krb/"
let () =
  p # add c;
  p # run()
    

At the moment, this authentication protocol cannot be configured, so you always get the default behaviour of GSSAPI.

Statefulness:

The GSSAPI is stateful. Our HTTP authentication interface is stateless. We cannot hide the statefulness of the GSSAPI, and because of this old versions of sessions are invalidated. E.g. this does not work

let s1 = A.client_emit_resonse s0 m1 uri1 hdr1
let s2 = A.client_emit_resonse s0 m2 uri2 hdr2
      

and the second attempt to continue with the old session s0 will fail.

module type PROFILE = sig .. end
module Default: PROFILE 
The default profile for Netmech_spnego_http: Use spnego_trans_id for the https transport, and reject any unencrypted transport (empty list).
module SPNEGO: 
The SPNEGO mechanism for HTTP, see Netmech_spnego_http
ocamlnet-4.1.2/doc/html-main/Netldap.Debug.html0000644000175000017500000004173112731530352017710 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netldap.Debug

Module Netldap.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module
ocamlnet-4.1.2/doc/html-main/Shell_fs.shell_fs-c.html0000644000175000017500000004201612731530352021046 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_fs.shell_fs

Class Shell_fs.shell_fs

class shell_fs : ?encoding:Netconversion.encoding -> ?root:string -> ?dd_has_excl:bool -> ?tmp_directory:string -> ?tmp_prefix:string -> command_interpreter -> shell_stream_fs

ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.serializer-c.html0000644000175000017500000004246412731530352023330 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.serializer

Class Uq_engines_compat.serializer

class ['a] serializer : Unixqueue.event_system -> ['a] serializer_t

ocamlnet-4.1.2/doc/html-main/type_Netplex_kit.processor_base.html0000644000175000017500000004076712731530352023643 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.processor_base Netplex_types.processor_hooks -> Netplex_kit.v_processorocamlnet-4.1.2/doc/html-main/Rpc_server.default_socket_config-c.html0000644000175000017500000004201612731530352024143 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.default_socket_config

Class Rpc_server.default_socket_config

class default_socket_config : socket_config

ocamlnet-4.1.2/doc/html-main/Netgzip.html0000644000175000017500000005267412731530352016724 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip

Module Netgzip

module Netgzip: sig .. end
Gzip object channels


OPAM users: Note that the OPAM package for OCamlnet does not build with GZIP support by default. The trigger for this is the presence of the camlzip OPAM package, i.e. do opam install camlzip to include the netzip library in a rebuild.
class input_gzip : Gzip.in_channel -> Netchannels.in_obj_channel
A Gzip.in_channel turned into a Netchannels.in_obj_channel
class output_gzip : Gzip.out_channel -> Netchannels.out_obj_channel
A Gzip.out_channel turned into a Netchannels.out_obj_channel
class inflating_pipe : unit -> Netchannels.io_obj_channel
An inflating (uncompressing) pipe for gzip data, to be used in filters
class deflating_pipe : ?level:int -> unit -> Netchannels.io_obj_channel
A deflating (compressing) pipe for gzip data, to be used in filters
class input_inflate : Netchannels.in_obj_channel -> Netchannels.in_obj_channel
let ch' = new input_inflate ch: Reading data from ch' inflates data read from ch.
class input_deflate : ?level:int -> Netchannels.in_obj_channel -> Netchannels.in_obj_channel
let ch' = new input_deflate ch: Reading data from ch' deflates data read from ch.
class output_inflate : Netchannels.out_obj_channel -> Netchannels.out_obj_channel
let ch' = new output_inflate ch: Data written to ch' is inflated and written to ch.
class output_deflate : ?level:int -> Netchannels.out_obj_channel -> Netchannels.out_obj_channel
let ch' = new output_deflate ch: Data written to ch' is deflated and written to ch.
val init : unit -> unit
By calling this function it is enforced that the (de)-compression algorithms are registered at Netcompression.
ocamlnet-4.1.2/doc/html-main/Netldap.ldap_result-c.html0000644000175000017500000004453212731530352021422 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netldap.ldap_result

Class type Netldap.ldap_result

class type ['a] ldap_result = object .. end
A class type for encapsulating results

method code : result_code
The code, `Success on success
method matched_dn : string
The matchedDN field sent with some codes
method diag_msg : string
diagnostic message
method referral : string list
if non-empty, a list of URIs where to find more results
method value : 'a
the value when code=`Success. Raises LDAP_error for other codes
method partial_value : 'a
the value so far available, independently of the code
ocamlnet-4.1.2/doc/html-main/type_Uq_lwt.lwt_backend.html0000644000175000017500000004371612731530352022071 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_lwt.lwt_backend Unixqueue.event_system ->
object
  method private cleanup : unit
  method iter : bool -> unit
  method private register_readable :
    Unix.file_descr -> (unit -> unit) -> unit Lazy.t
  method private register_timer :
    float -> bool -> (unit -> unit) -> unit Lazy.t
  method private register_writable :
    Unix.file_descr -> (unit -> unit) -> unit Lazy.t
end
ocamlnet-4.1.2/doc/html-main/Netmech_scram_http.PROFILE.html0000644000175000017500000004236412731530352022205 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_http.PROFILE

Module type Netmech_scram_http.PROFILE

module type PROFILE = sig .. end

val mutual : bool
val hash_function : Netsys_digests.iana_hash_fn
val test_nonce : string option
ocamlnet-4.1.2/doc/html-main/Netplex_types.html0000644000175000017500000011123412731530352020133 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types

Module Netplex_types

module Netplex_types: sig .. end
Types for Netplex

type encap = Netplex_encap.encap 
type param_value = [ `Bool of bool | `Float of float | `Int of int | `String of string ] 
type param_value_or_any = [ `Any of exn
| `Bool of bool
| `Encap of encap
| `Float of float
| `Int of int
| `String of string ]
type level = [ `Alert | `Crit | `Debug | `Emerg | `Err | `Info | `Notice | `Warning ] 
Log levels, modeled after syslog
class type logger = object .. end
A logger receives log messages
type parallelization_type = [ `Controller_attached | `Multi_processing | `Multi_threading ] 
Type of parallelization:
  • `Multi_processing on a single host
  • `Multi_threading on a single host
  • `Controller_attached means that the service runs within the controller. This is (for now) only allowed for controller-internal services.

type thread_sys_id = [ `Process of int | `Thread of int ] 
A system-specific identifier of the thread/process
type socket_state = [ `Disabled | `Down | `Enabled | `Restarting of bool ] 
The state of a socket:
  • `Enabled: The controller allows containers to accept connections. Note that this does not necessarily means that there such containers.
  • `Disabled: It is not allowed to accept new connections. The socket is kept open, however.
  • `Restarting b: The containers are being restarted. The boolean argument says whether the socket will be enabled after that.
  • `Down: The socket is down/closed

type container_id = <
   socket_service_name : string;
>
Such objects identify containers. As additional info, the method socket_service_name returns the name of the socket service the container implements
type container_state = [ `Accepting of int * float | `Busy | `Shutting_down | `Starting of float ] 
The container state for workload management:
  • `Accepting(n,t): The container is accepting further connections. It currently processes n connections. The last connection was accepted at time t (seconds since the epoch).
  • `Busy: The container does not accept connections
  • `Starting t: The container was started at time t and is not yet ready.
  • `Shutting_down: The container is being shutted down.

type capacity = [ `Low_quality of int * bool | `Normal_quality of int * bool | `Unavailable ] 
How many connections a container can accept in addition to the existing connections:
  • `Normal_quality(n,greedy): It can accept n connections with normal service quality, n > 0
  • `Low_quality(n,greedy): It can accept n connections with low service quality (e.g. because it is already quite loaded), n > 0
  • `Unavailable: No capacity free
The greedy flag sets whether greedy accepts are allowed.
type extended_address = [ `Container of
string * string * string * [ `Any | `Process of int | `Thread of int ]
| `Internal of string
| `Socket of Unix.sockaddr
| `Socket_file of string
| `W32_pipe of string
| `W32_pipe_file of string ]
Possible addresses:
  • `Socket s: The socket at this socket address
  • `Socket_file f: The file f contains the (anonymous) port number of a socket bound to 127.0.0.1 (This is meant as substitute for Unix Domain sockets on Win32.)
  • `W32_pipe name: The Win32 pipe with this name which must be of the form "\\.\pipe\<pname>"
  • `W32_pipe_file f: The file f contains the (random) name of a Win32 pipe
  • `Container(socket_dir,service_name,proto_name,thread_id): The special endpoint of the container for service_name that is running as thread_id. It is system-dependent what this endpoint "is" in reality, usually a socket or named pipe. If any container of a service is meant, the value `Any is substituted as a placeholder for a not yet known thread_id.
  • `Internal name: an internal service called name. Internal sockets are only available for multithreaded programs, and are registered at Netplex_internal.

type ('_, '_) eq = 
| Equal : ('a, 'a) eq
| Not_equal
Equality witness
type '_ polysocket_kind = ..
List possible argument types for polysockets (Netsys_polysocket), which are the basis for internal services. Since OCaml-4.02 this type is extensible by the user.
type '_ polysocket_kind += 
| Tstring : string polysocket_kind
| Txdr : Netxdr.xdr_value polysocket_kind
type 'a kind_check = {
   kind_check : 'b. 'b polysocket_kind -> ('a, 'b) eq;
}
Helper type for a polymorphic check whether a kind this the expected kind
type polysocket_kind_box = 
| Polysocket_kind_box : 'a polysocket_kind -> polysocket_kind_box
Boxed version of polysocket_kind where the type parameter is hidden
type polyserver_box = 
| Polyserver_box : 'a polysocket_kind * 'a Netsys_polysocket.polyserver -> polyserver_box
This type pairs a polysocket_kind with a polyserver as GADT. The type parameter is hidden.
type polyclient_box = 
| Polyclient_box : 'a polysocket_kind * 'a Netsys_polysocket.polyclient -> polyclient_box
This type pairs a polysocket_kind with a polyclient as GADT. The type parameter is hidden.
type extfd = 
| OS_descr of Unix.file_descr
| Poly_endpoint of Netxdr.xdr_value Netsys_polysocket.polyendpoint
Internally used
class type controller = object .. end
The controller is the object in the Netplex master process/thread that manages the containers, logging, and service definitions
class type controller_config = object .. end
class type socket_service = object .. end
class type socket_service_config = object .. end
class type protocol = object .. end
class type socket_controller = object .. end
class type ctrl_message_receiver = object .. end
class type processor_hooks = object .. end
Processor hooks can be used to modify the behavior of a processor.
class type processor = object .. end
The processor is the object that is notified when a new TCP connection is accepted.
class type container = object .. end
Containers encapsulate the control flow of the service components.
class type workload_manager = object .. end
See Netplex_workload for definitions of workload managers
class type plugin = object .. end
Plugins are extensions of the Netplex system that run in the controller and can be invoked from containers
class type par_thread = object .. end
class type parallelizer = object .. end
type config_tree = [ `Parameter of string * param_value
| `Section of string * config_tree list ]
type address = <
>
class type config_file = object .. end
class type processor_factory = object .. end
class type workload_manager_factory = object .. end
class type logger_factory = object .. end
class type netplex_config = object .. end
ocamlnet-4.1.2/doc/html-main/type_Nethttp.Header.html0000644000175000017500000014213112731530352021146 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.Header sig
  type param_value = [ `Q of string | `V of string ]
  type auth_challenge = string * (string * Nethttp.Header.param_value) list
  type auth_credentials = string * (string * Nethttp.Header.param_value) list
  val parse_quoted_parameters : string -> (string * string) list
  val get_accept :
    #Nethttp.http_header_ro ->
    (string * (string * string) list * (string * string) list) list
  val best_media_type :
    #Nethttp.http_header_ro -> string list -> string * (string * string) list
  val set_accept :
    #Nethttp.http_header ->
    (string * (string * string) list * (string * string) list) list -> unit
  val get_accept_charset :
    #Nethttp.http_header_ro -> (string * (string * string) list) list
  val best_charset : #Nethttp.http_header_ro -> string list -> string
  val set_accept_charset :
    #Nethttp.http_header -> (string * (string * string) list) list -> unit
  val get_accept_encoding :
    #Nethttp.http_header_ro -> (string * (string * string) list) list
  val best_encoding : #Nethttp.http_header_ro -> string list -> string
  val set_accept_encoding :
    #Nethttp.http_header -> (string * (string * string) list) list -> unit
  val get_accept_language :
    #Nethttp.http_header_ro -> (string * (string * string) list) list
  val set_accept_language :
    #Nethttp.http_header -> (string * (string * string) list) list -> unit
  val get_accept_ranges : #Nethttp.http_header_ro -> string list
  val set_accept_ranges : #Nethttp.http_header -> string list -> unit
  val get_age : #Nethttp.http_header_ro -> float
  val set_age : #Nethttp.http_header -> float -> unit
  val get_allow : #Nethttp.http_header_ro -> string list
  val set_allow : #Nethttp.http_header -> string list -> unit
  val get_authorization :
    #Nethttp.http_header_ro -> Nethttp.Header.auth_credentials
  val set_authorization :
    #Nethttp.http_header -> Nethttp.Header.auth_credentials -> unit
  val get_cache_control :
    #Nethttp.http_header_ro -> Nethttp.cache_control_token list
  val set_cache_control :
    #Nethttp.http_header -> Nethttp.cache_control_token list -> unit
  val get_connection : #Nethttp.http_header_ro -> string list
  val set_connection : #Nethttp.http_header -> string list -> unit
  val get_content_encoding : #Nethttp.http_header_ro -> string list
  val set_content_encoding : #Nethttp.http_header -> string list -> unit
  val get_content_language : #Nethttp.http_header_ro -> string list
  val set_content_language : #Nethttp.http_header -> string list -> unit
  val get_content_length : #Nethttp.http_header_ro -> int64
  val set_content_length : #Nethttp.http_header -> int64 -> unit
  val get_content_location : #Nethttp.http_header_ro -> string
  val set_content_location : #Nethttp.http_header -> string -> unit
  val get_content_md5 : #Nethttp.http_header_ro -> string
  val set_content_md5 : #Nethttp.http_header -> string -> unit
  val get_content_range :
    #Nethttp.http_header_ro ->
    [ `Bytes of (int64 * int64) option * int64 option ]
  val set_content_range :
    #Nethttp.http_header ->
    [ `Bytes of (int64 * int64) option * int64 option ] -> unit
  val get_content_type :
    #Nethttp.http_header_ro -> string * (string * string) list
  val set_content_type :
    #Nethttp.http_header -> string * (string * string) list -> unit
  val get_date : #Nethttp.http_header_ro -> float
  val set_date : #Nethttp.http_header -> float -> unit
  val get_etag : #Nethttp.http_header_ro -> Nethttp.etag
  val set_etag : #Nethttp.http_header -> Nethttp.etag -> unit
  val get_expect :
    #Nethttp.http_header_ro ->
    (string * string option * (string * string) list) list
  val set_expect :
    #Nethttp.http_header ->
    (string * string option * (string * string) list) list -> unit
  val get_expires : #Nethttp.http_header_ro -> float
  val set_expires : #Nethttp.http_header -> float -> unit
  val get_from : #Nethttp.http_header_ro -> string
  val set_from : #Nethttp.http_header -> string -> unit
  val get_host : #Nethttp.http_header_ro -> string * int option
  val set_host : #Nethttp.http_header -> string * int option -> unit
  val get_if_match : #Nethttp.http_header_ro -> Nethttp.etag list option
  val set_if_match : #Nethttp.http_header -> Nethttp.etag list option -> unit
  val get_if_modified_since : #Nethttp.http_header_ro -> float
  val set_if_modified_since : #Nethttp.http_header -> float -> unit
  val get_if_none_match : #Nethttp.http_header_ro -> Nethttp.etag list option
  val set_if_none_match :
    #Nethttp.http_header -> Nethttp.etag list option -> unit
  val get_if_range :
    #Nethttp.http_header_ro -> [ `Date of float | `Etag of Nethttp.etag ]
  val set_if_range :
    #Nethttp.http_header ->
    [ `Date of float | `Etag of Nethttp.etag ] -> unit
  val get_if_unmodified_since : #Nethttp.http_header_ro -> float
  val set_if_unmodified_since : #Nethttp.http_header -> float -> unit
  val get_last_modified : #Nethttp.http_header_ro -> float
  val set_last_modified : #Nethttp.http_header -> float -> unit
  val get_location : #Nethttp.http_header_ro -> string
  val set_location : #Nethttp.http_header -> string -> unit
  val get_max_forwards : #Nethttp.http_header_ro -> int
  val set_max_forwards : #Nethttp.http_header -> int -> unit
  val get_pragma : #Nethttp.http_header_ro -> (string * string option) list
  val set_pragma :
    #Nethttp.http_header -> (string * string option) list -> unit
  val get_proxy_authenticate :
    #Nethttp.http_header_ro -> Nethttp.Header.auth_challenge list
  val set_proxy_authenticate :
    #Nethttp.http_header -> Nethttp.Header.auth_challenge list -> unit
  val get_proxy_authorization :
    #Nethttp.http_header_ro -> Nethttp.Header.auth_credentials
  val set_proxy_authorization :
    #Nethttp.http_header -> Nethttp.Header.auth_credentials -> unit
  val get_range :
    #Nethttp.http_header_ro ->
    [ `Bytes of (int64 option * int64 option) list ]
  val set_range :
    #Nethttp.http_header ->
    [ `Bytes of (int64 option * int64 option) list ] -> unit
  val get_referer : #Nethttp.http_header_ro -> string
  val get_referrer : #Nethttp.http_header_ro -> string
  val set_referer : #Nethttp.http_header -> string -> unit
  val set_referrer : #Nethttp.http_header -> string -> unit
  val get_retry_after :
    #Nethttp.http_header_ro -> [ `Date of float | `Seconds of int ]
  val set_retry_after :
    #Nethttp.http_header -> [ `Date of float | `Seconds of int ] -> unit
  val get_server : #Nethttp.http_header_ro -> string
  val set_server : #Nethttp.http_header -> string -> unit
  val get_te :
    #Nethttp.http_header_ro ->
    (string * (string * string) list * (string * string) list) list
  val set_te :
    #Nethttp.http_header ->
    (string * (string * string) list * (string * string) list) list -> unit
  val get_trailer : #Nethttp.http_header_ro -> string list
  val set_trailer : #Nethttp.http_header -> string list -> unit
  val get_transfer_encoding :
    #Nethttp.http_header_ro -> (string * (string * string) list) list
  val set_transfer_encoding :
    #Nethttp.http_header -> (string * (string * string) list) list -> unit
  val get_upgrade : #Nethttp.http_header_ro -> string list
  val set_upgrade : #Nethttp.http_header -> string list -> unit
  val get_user_agent : #Nethttp.http_header_ro -> string
  val set_user_agent : #Nethttp.http_header -> string -> unit
  val get_vary :
    #Nethttp.http_header_ro -> [ `Fields of string list | `Star ]
  val set_vary :
    #Nethttp.http_header -> [ `Fields of string list | `Star ] -> unit
  val get_www_authenticate :
    #Nethttp.http_header_ro -> Nethttp.Header.auth_challenge list
  val set_www_authenticate :
    #Nethttp.http_header -> Nethttp.Header.auth_challenge list -> unit
  val get_cookie : #Nethttp.http_header_ro -> (string * string) list
  val get_cookie_ct : #Nethttp.http_header_ro -> Nethttp.Cookie.t list
  val set_cookie : #Nethttp.http_header -> (string * string) list -> unit
  val get_set_cookie :
    #Nethttp.http_header_ro -> Nethttp.netscape_cookie list
  val set_set_cookie :
    #Nethttp.http_header -> Nethttp.netscape_cookie list -> unit
  val set_set_cookie_ct :
    #Nethttp.http_header -> Nethttp.Cookie.t list -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.poll_engine.html0000644000175000017500000004361012731530352022722 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.poll_engine ?extra_match:(exn -> bool) ->
(Unixqueue.operation * float) list ->
Unixqueue.event_system ->
object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method group : Unixqueue.group
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    (Unixqueue.event engine -> bool) -> unit
  method restart : unit -> unit
  method state : Unixqueue.event engine_state
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.prioritizer-c.html0000644000175000017500000004245712731530352023543 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.prioritizer

Class Uq_engines_compat.prioritizer

class ['a] prioritizer : Unixqueue.event_system -> ['a] prioritizer_t

ocamlnet-4.1.2/doc/html-main/type_Uq_engines.epsilon_engine.html0000644000175000017500000004124612731530352023430 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.epsilon_engine 'Uq_engines.engine_state ->
Unixqueue.event_system -> ['t] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/Netsys_polysocket.html0000644000175000017500000006334712731530352021044 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_polysocket

Module Netsys_polysocket

module Netsys_polysocket: sig .. end
Polymorphic message sockets


These pipes are restricted to a single process, and can be used to send messages of any types between threads.

These pipes are restricted to a single process, and can be used to send messages of any types between threads.

Types


type 'a polyendpoint = 'a Netsys_polypipe.polypipe * 'a Netsys_polypipe.polypipe 
An endpoint is simply a pair (rd,wr) where rd is a polypipe open for reading, and wr is a polypipe open for writing.
type 'a polyclient 
A client, connected or unconnected
type 'a polyserver 
A server

Clients


val create_client : int -> 'a polyclient
Create a new socket client. The int is the number of messages in the pipe buffer.
val connect : 'a polyclient -> 'a polyserver -> unit
Requests the connection with this server. This function returns always immediately.

Possible Unix.unix_error codes:

  • EALREADY
  • EISCONN

val endpoint : synchronous:bool ->
nonblock:bool ->
'a polyclient -> 'a polyendpoint
Returns the endpoint once connected. In asynchronous mode, the connect is immediately successful. In synchronous mode, it is awaited that the server accepts the connection. If also nonblock is true, the Unix_error EAGAIN is returned if such waiting is needed.

Possible Unix.unix_error codes:

  • EAGAIN: the client is non-blocking, and the connection is not yet established
  • EINTR: a signal arrived
  • ECONNREFUSED: the server went down in the meantime
  • ENOTCONN: no previous connect
If called several times, this function always returns the same endpoint.
val close_client : 'a polyclient -> unit
Closes the client and the endpoint. Further interactions with the client raise the exception Netsys_polypipe.Closed.
val set_connect_notify : 'a polyclient -> (unit -> unit) -> unit
set_connect_notify cl f: Sets that the function f is called when the connection is accepted. There can only be one such function; any previous function is overwritten. Only future connect events are reported. The function is called from a different thread.
val connect_descr : 'a polyclient -> Unix.file_descr
Returns a descriptor that can be used for polling. This is only meaningful for synchronous connects. When the descriptor is readable the connection is accepted, and calling endpoint again is promising.

If connect_descr is called several times, always the same descriptor is returned.

The caller has to close the descriptor after use.

You can call this function only after connect.


Servers


val create_server : unit -> 'a polyserver
Create a new socket server.

Note that a server needs 2-6 file descriptors in the current implementation.

val accept : nonblock:bool ->
'a polyserver -> 'a polyendpoint
Accepts the next connection (or returns the next connection from the backlog queue). If the server is blocking, this function waits until the connection is established.

Possible Unix.unix_error codes:

  • EAGAIN: the server is non-blocking, and no connection attempt is pending
  • EINTR: a signal arrived

val refuse : nonblock:bool -> 'a polyserver -> unit
All pending connection attempts will be refused. The clients will get ECONNREFUSED. It is possible to return to accepting connections.

For a non-blocking refuse you need to call refuse again after catching EAGAIN.

val pending_connection : 'a polyserver -> bool
Whether there is a client waiting for being accepted
val close_server : 'a polyserver -> unit
Closes the server. The accepted endpoints need to be closed separately.

Further interactions with the server cause that the exception Netsys_polypipe.Closed will be raised.

val set_accept_notify : 'a polyserver -> (unit -> unit) -> unit
set_accept_notify srv f: Sets that the function f is called when a new connection arrives. There can only be one such function; any previous function is overwritten. The event is edge-triggered: when several connections arrive the function is only called once. The function is called from a different thread.
val accept_descr : 'a polyserver -> Unix.file_descr
Returns a descriptor that can be used for polling. When the descriptor is readable a pending connection exists. If called several times, always the same descriptor is returned.

The caller has to close the descriptor after use.

You can call this function before or after accept.

ocamlnet-4.1.2/doc/html-main/type_Netchannels.buffered_raw_out_channel.html0000644000175000017500000004120612731530352025605 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.buffered_raw_out_channel ?buffer_size:int ->
?pass_through:int ->
Netchannels.raw_out_channel -> Netchannels.raw_out_channel
ocamlnet-4.1.2/doc/html-main/type_Netplex_cenv.VAR_TYPE.html0000644000175000017500000004165612731530352022265 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.VAR_TYPE sig
  type t
  val get : string -> Netplex_cenv.VAR_TYPE.t
  val set : string -> Netplex_cenv.VAR_TYPE.t -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Equeue.Debug.html0000644000175000017500000004312012731530352020605 0ustar gerdgerd Ocamlnet 4 Reference Manual : Equeue.Debug sig
  type debug_target = [ `Any | `Process of int | `Thread of int ]
  val enable : bool Pervasives.ref
  val set_debug_mode : bool -> unit
  val set_debug_target : Equeue.Debug.debug_target -> unit
  val test_debug_target : Equeue.Debug.debug_target -> bool
end
ocamlnet-4.1.2/doc/html-main/index_modules.html0000644000175000017500000021210712731530352020130 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of modules

Index of modules


A
AD [Netx509]
AES_CTS [Netmech_scram]
This module implements AES in Ciphertext Stealing mode (see RFC 3962)
Add_modes [Netsys_crypto_modes]
Returns a new crypto module where missing modes are added for all ECB ciphers.
Apache [Netcgi_apache]
Interface to Apache API.
Argument [Netcgi]
Operations on arguments and lists of thereof.
ArrayAux [Netaux]
Auth [Netgssapi_auth]
Authentication

B
BE [Netnumber]
Encoders/decoders for big endian - network byte order
Base64 [Netencoding]
Bundle [Netsys_crypto_modes]
Bundle a list of ciphers as crypto module

C
CE [Netx509]
CRAM_MD5 [Netmech_crammd5_sasl]
The CRAM-MD5 SASL mechanism (RFC 2195), which is obsolete and only provided for completeness.
Client [Netsys_sasl]
Connection [Netcgi_apache.Apache]
Convenience [Nethttp_client]
Cookie [Nethttp]
Cookie [Netcgi]
Functions to manipulate cookies.
Cookie [Netcgi_common]
Credentials
Crypto
Cryptosystem [Netmech_scram]
This is the cryptosystem as defined in RFC 3961, so far needed here.

D
DIGEST_MD5 [Netmech_digest_sasl]
The DIGEST-MD5 SASL mechanism (RFC 2831).
DN_attributes [Netx509]
DN_string_generic [Netdn]
For a given attribute lookup module L this module provides parser and printer for distinguished names in string format (RFC 4514).
DbiPool [Netcgi_dbi]
module MyPool = DbiPool (Dbi_postgres)
Debug [Shell_sys]
Debug [Rpc_auth_gssapi]
Debug [Rpc_server]
Debug [Rpc_client]
Debug [Rpc_transport]
Debug [Netsys_polypipe]
Debug [Netsys_tls]
Debug [Netsys_sem]
Debug [Netsys_signal]
Debug [Netsys_pollset_win32]
Debug [Netsys_win32]
Debug [Netlog]
Debug [Netsys_posix]
Debug [Netsys]
Debug [Netmech_scram]
Debug [Netstring_str]
Debug [Netplex_cenv]
Debug [Netplex_container]
Debug [Netplex_controller]
Debug [Netmcore_condition]
Debug [Netmcore_heap]
Debug [Netmcore_mempool]
Debug [Netmcore]
Debug [Nethttpd_services]
Debug [Nethttpd_engine]
Debug [Nethttpd_reactor]
Debug [Nethttpd_kernel]
Debug [Netldap]
Debug [Netpop]
Debug [Netsmtp]
Debug [Netftp_client]
Debug [Nettelnet_client]
Debug [Nethttp_client]
Debug [Netcamlbox]
Debug [Uq_engines_compat]
Debug [Uq_engines]
Debug [Unixqueue]
Debug [Equeue]
Default [Netmech_spnego_http]
The default profile for Netmech_spnego_http: Use spnego_trans_id for the https transport, and reject any unencrypted transport (empty list).
Digest [Netmech_digest_http]
This is the standard HTTP digest authentication mechanism (see RFCs 2069, 2617, 7616).
Digest_mutual [Netmech_digest_http]
This is the standard HTTP digest authentication mechanism (see RFCs 2069, 2617, 7616).
Digests [Nettls_gnutls]
Cryptographic digests

E
Encryption [Netx509_pubkey]
Equeue
Equeue implements generic event queues.
Equeue_howto
Equeue_intro
Exc [Netsys_crypto_types.TLS_PROVIDER]
Access to exceptions

F
Foreword

G
GNUTLS [Nettls_gnutls]
The implementation of TLS backed by GnuTLS, here using Netsys_types as TLS_EXCEPTIONS module
GS2 [Netmech_gs2_sasl]
This is an adapter turning any GSSAPI mechanism into a SASL mechanism.
Get
Gssapi

H
HO [Netnumber]
Encoders/decoders for host byte order - which is either little endian or big endian, depending on the CPU (or CPU mode)
Handler [Netcgi_apache]
Registering Apache handlers.
Header [Nethttp]
Html [Netencoding]

I
Info [Netsys_sasl]
Intro
Ipv6

K
KMP [Netaux]
KP [Netx509]
Key purpose IDs as returned by parse_ext_key_usage
Key [Netx509_pubkey]
Keyagreement [Netx509_pubkey]
Krb5_gs1 [Netmech_krb5_sasl]
This is an adapter turning the Kerberos 5 GSSAPI mechanism into a SASL mechanism.
Krb5_gs2 [Netmech_krb5_sasl]
This is the other adapter turning the Kerberos 5 GSSAPI mechanism into a SASL mechanism.
Krb5_gs2_profile [Netmech_krb5_sasl]
This is the profile used for Netmech_krb5_sasl.Krb5_gs2

L
LE [Netnumber]
Encoders/decoders for little endian

M
Make [Uq_libevent]
Instantiate this module.
Make'PMAP [Rpc_portmapper_clnt]
Make_SCRAM [Netmech_scram_http]
Make_digest [Netmech_digest_http]
Create a custom version of the digest mechanism
Make_encap [Netplex_encap]
Create an encapsulation module
Make_lever [Netplex_cenv]
Creates a LEVER module from a function type as specified in FUN_TYPE
Make_mbox_type [Netplex_mbox]
Create a new mailbox access module for message type T.t
Make_var_type [Netplex_sharedvar]
Creates a module with get and set functions to access variables of type T.t.
Make_var_type [Netplex_cenv]
Creates get and set like make_var_type.
Make_vv [Netplex_sharedvar]
Manage [Netgssapi_auth]
ManagedClient [Rpc_proxy]
ManagedSet [Rpc_proxy]

N
Netaccel
Accelerators for bytecode
Netaccel_link
Enables accelerator module Netaccel
Netaddress
Parsing of mail addresses
Netascii_armor
Messages with ASCII armor
Netasn1
ASN.1 support functions
Netasn1_encode
ASN.1 encoder
Netauth
Some primitives for authentication
Netaux
Internal auxiliary functions
Netbuffer
A Netbuffer.t is a buffer that can grow and shrink dynamically.
Netcamlbox
Camlboxes are a fast IPC mechanism to send Ocaml values from one process to another.
Netcgi [Netcgi1_compat]
Netcgi
Common data-structures for CGI-like connectors.
Netcgi1_compat
Compatibility module with the previous version of Netcgi.
Netcgi_ajp
Apache JServ Protocol (AJP) 1.3 connector.
Netcgi_apache
Netcgi Apache "mod" connector.
Netcgi_cgi
Classical CGI connector.
Netcgi_common
Functions to develop new connectors.
Netcgi_dbi
Pools of connections for the ocamldbi generic database interface.
Netcgi_env [Netcgi1_compat]
Netcgi_fcgi
FastCGI connector.
Netcgi_modtpl
Netcgi_plex
Netplex support for FastCGI, SCGI and AJP connectors
Netcgi_porting
Netcgi_scgi
SCGI connector.
Netcgi_test
Connector for testing your code.
Netcgi_types [Netcgi1_compat]
Netchannels
Object-oriented I/O: Basic types and classes
Netchannels_crypto
Crypto extensions for Netchannels
Netchannels_tut
Netclient_tut
Netcompression
Registry for compression algorithms
Netconversion
Conversion between character encodings
Netdate
Support for common date/time parsing and formatting.
Netdn
X.500 distinguished names
Netencoding
Base64, Quoted Printable, URL encoding, HTML escaping
Netexn
Exception registry
Netfs
Class type stream_fs for filesystems with stream access to files
Netftp_client
FTP client
Netftp_data_endpoint
Senders and receivers for the FTP data connection
Netftp_fs
FTP filesystem
Netglob
Globbing
Netgss
This is the system-wide version of GSSAPI
Netgss_bindings
Bindings of a C library
Netgssapi_auth
Authentication helpers for GSSAPI
Netgssapi_support
Support functions for GSS-API
Netgzip
Gzip object channels
Nethtml
Parsing of HTML
Nethttp
Basic definitions for the HTTP protocol
Nethttp_client
HTTP 1.1 client
Nethttp_client_conncache
Connection cache
Nethttp_fs
HTTP filesystem
Nethttpd_engine
The event-based encapsulation of the HTTP daemon
Nethttpd_intro
Nethttpd_kernel
The protocol kernel of the HTTP daemon
Nethttpd_plex
Netplex support
Nethttpd_reactor
The reactive encapsulation of the HTTP daemon
Nethttpd_services
Service Providers for HTTP daemon
Nethttpd_types
Type definitions for the HTTP daemon
Nethttpd_util
Utility functions
Netldap
LDAP client
Netlog
Basic logging facility
Netmappings
Internal access to the character conversion database
Netmcore
Multi-processing for compute jobs
Netmcore_array
Shared arrays
Netmcore_basics
Netmcore_buffer
Shared buffer
Netmcore_camlbox
Camlboxes for use in netmulticore programs
Netmcore_condition
Condition variables
Netmcore_hashtbl
Shared hashtables
Netmcore_heap
Shared heaps of structured values
Netmcore_matrix
Shared 2-dimensional arrays (matrices)
Netmcore_mempool
Memory pools
Netmcore_mutex
Mutexes
Netmcore_process
Statically typed processes
Netmcore_queue
Shared queues
Netmcore_ref
Shared mutable variables
Netmcore_sem
Semaphores
Netmcore_tut
Netmech_crammd5_sasl
The CRAM-MD5 SASL mechanism (RFC 2195), which is obsolete and only provided for completeness.
Netmech_digest_http
Digest authentication for HTTP
Netmech_digest_sasl
The DIGEST-MD5 SASL mechanism (RFC 2831).
Netmech_gs2_sasl
The GS2 bridge for using GSSAPI mechanisms as SASL mechanisms
Netmech_krb5_sasl
Kerberos 5 as SASL mechanism
Netmech_plain_sasl
The PLAIN SASL mechanism (RFC 4616).
Netmech_scram
SCRAM mechanism for authentication (RFC 5802)
Netmech_scram_gssapi
The SCRAM security mechanism for GSS-API
Netmech_scram_http
SCRAM for HTTP (prerelease)
Netmech_scram_sasl
SCRAM as SASL mechanism
Netmech_spnego_http
SPNEGO (GSSAPI) authentication for HTTP
Netmime
Netmime contains high-level classes and functions to process mail and MIME messages.
Netmime_channels
MIME: parsing and printing for channels
Netmime_header
MIME: Access methods for frequent standard fields.
Netmime_string
Low-level functions to parse and print mail and MIME messages
Netmime_tut
Netnumber
Binary encodings of numbers
Netoid
X.500 Object Identifiers
Netpagebuffer
Buffer for page-aligned I/O
Netplex_admin
Netplex_advanced
Netplex_cenv
Container environment
Netplex_config
Read the configuration file
Netplex_container
Containers
Netplex_controller
Controller
Netplex_encap
Type-safe marshalling between processes of the same executable
Netplex_internal
Internal services
Netplex_intro
Netplex_kit
Netplex toolkit
Netplex_log
Loggers
Netplex_main
Main program for Netplex servers
Netplex_mbox
Netplex message boxes
Netplex_mp
Multi-processing provider
Netplex_mt
Multi-threading provider
Netplex_mutex
Netplex-wide mutexes
Netplex_semaphore
Netplex-wide semaphores
Netplex_sharedvar
Netplex-wide variables
Netplex_sockserv
Socket service creation
Netplex_types
Types for Netplex
Netplex_workload
Workload management
Netpop
This is an interface for the Post Office Protocol - Version 3 (POP3) as specifed by RFC 1939.
Netsaslprep
The SASLprep algorithm (RFC 4013)
Netsendmail
Functions to compose and send electronic mails
Netsendmail_tut
Netshm
Shared memory for O'Caml programs using multi-processing
Netshm_array
Arrays in shared memory
Netshm_data
Data representation for shared memory
Netshm_hashtbl
Hash tables in shared memory
Netshm_intro
Netsmtp
This is an interface for the Simple Mail Tranfer Protocol (SMTP) as specified by RFC 2821.
Netsockaddr
Parsing of socket addresses
Netstream
A netstream is an input channel that is read block by block.
Netstring_pcre
Wrapper for regexps with PCRE syntax
Netstring_str
Wrapper for regexps with Str syntax
Netstring_tstring
Support module for tagged strings
Netsys
System calls missing in the Unix module
Netsys_ciphers
Symmetric cryptographic ciphers
Netsys_crypto
Cryptographic providers
Netsys_crypto_modes
Helpers for crypto modes
Netsys_crypto_types
Types for crypto providers
Netsys_digests
Cryptographic digests (hashes)
Netsys_global
Global variables
Netsys_gssapi
GSS-API Definition
Netsys_mem
Bigarrays as memory buffers
Netsys_oothr
Object-oriented thread API
Netsys_pmanage
Manage persistent objects
Netsys_pollset
Sets of file descriptors for polling
Netsys_pollset_generic
Returns a good standard implementation of pollset for this platform.
Netsys_pollset_posix
Pollsets for POSIX operating systems
Netsys_pollset_win32
Pollsets for Win32
Netsys_polypipe
Polymorphic message pipes
Netsys_polysocket
Polymorphic message sockets
Netsys_posix
POSIX-specific system calls missing in the Unix module, and further API's from POSIX-style operating systems.
Netsys_rng
Random-number generator
Netsys_sasl
User interface for SASL mechanisms
Netsys_sasl_types
Possible channel bindings: `None: this is the default, `SASL_none_but_advertise: the client supports channel binding and advertises this. For this time, the SCRAM protocol is run without channel binding, though. (Only available in the SASL profile.), `SASL_require(type,data): Require channel binding. E.g. type="tls-unique", and data is set to the channel identifier (RFC 5929). (Only available in the SASL profile.), `GSSAPI data: use this channel binding for GSS-API This type is shared by SASL and GSSAPI providers.
Netsys_sem
Generic anonymous semaphores
Netsys_signal
Signal handler framework
Netsys_tls
User-level TLS API
Netsys_tmp
Temporary files
Netsys_types
Types for all Netsys modules
Netsys_win32
Primitives for Win32
Netsys_xdr
Some helpers for en/decoding XDR faster
Nettelnet_client
Telnet client
Nettls_gnutls
GnuTLS
Nettls_gnutls_bindings
Bindings of a C library
Nettls_nettle_bindings
Bindings of a C library
Nettls_support
Support types and functions for TLS
Netulex
Support module for Alain Frisch's ulex lexer generator
Netulex_tut
Netunichar
Unicode character information
Netunidata
Configure how to load Unicode tables
Neturl
Uniform Resource Locators (URLs)
Neturl_ldap
LDAP-specific URLs
Neturl_tut
Netx509
X.509 certificates
Netx509_pubkey
X.509 public key cryptography - keys and naming
Netx509_pubkey_crypto
X.509 public key cryptography - wrappers
Netxdr
External Data Representation
Netxdr_mstring
Managed Strings

O
Ocamlnet4
Operators [Uq_engines_compat]
Operators [Uq_engines]
Handy operators: ++, >>, and eps_e

P
PLAIN [Netmech_plain_sasl]
The PLAIN SASL mechanism (RFC 4616).
Platform

Q
Q [Netencoding]
QuotedPrintable [Netencoding]

R
Regexp
ReliabilityCache [Rpc_proxy]
Request [Netcgi_apache.Apache]
Rpc
Common types and exceptions
Rpc_auth_gssapi
GSS-API for RPC authentication
Rpc_auth_local
Return the authentication method AUTH_LOCAL.
Rpc_auth_sys
Authentication module AUTH_SYS
Rpc_client
RPC clients
Rpc_intro
Rpc_intro_gss
Rpc_mapping_ref
Rpc_netplex
Netplex support for RPC servers (TCP only)
Rpc_packer
Packing and Unpacking of messages; can be used by both client and server programs.
Rpc_portmapper
Portmapper/RPCBIND interface
Rpc_portmapper_aux
Rpc_portmapper_clnt
Rpc_program
RPC programs
Rpc_proxy
RPC proxies
Rpc_server
RPC servers
Rpc_simple_client
Synchronous API for RPC clients
Rpc_transport
Low-level RPC transporters
Rpc_util
Utility functions
Rpc_xti_client
Minimal support for TI-RPC over the XTI API

S
SCRAM [Netmech_scram_sasl]
Create a new SCRAM SASL mechanism for this profile.
SCRAM_SHA1 [Netmech_scram_sasl]
SCRAM with SHA1 profile
SCRAM_SHA1_PLUS [Netmech_scram_sasl]
SCRAM with SHA1_PLUS profile
SCRAM_SHA256 [Netmech_scram_sasl]
SCRAM with SHA256 profile
SCRAM_SHA256_PLUS [Netmech_scram_sasl]
SCRAM with SHA256_PLUS profile
SHA1 [Netmech_scram_sasl]
Uses SHA-1 as hash function.
SHA1_PLUS [Netmech_scram_sasl]
Same as Netmech_scram_sasl.SHA1, only that the mechanism name is "SCRAM-SHA-1-PLUS"
SHA256 [Netmech_scram_sasl]
Uses SHA-256 as hash function.
SHA256_PLUS [Netmech_scram_sasl]
Same as Netmech_scram_sasl.SHA256, only that the mechanism name is "SCRAM-SHA-256-PLUS"
SPNEGO [Netmech_spnego_http]
The SPNEGO mechanism for HTTP, see Netmech_spnego_http
Server [Netsys_sasl]
Server [Netcgi_apache.Apache]
Shell
Calls external programs, creates pipelines, etc.
Shell_fs
Shell filesystem
Shell_intro
Shell_sys
Calls external programs, creates pipelines, etc.
Shell_uq
Run shell commands within Unixqueues
Signing [Netx509_pubkey]
Symmetric_cipher [Netsys_crypto_modes]
Symmetric_crypto [Nettls_gnutls]
Symmetric cryptography as provided by GnuTLS and its helper library Nettle
System [Netgss]
This is the system-wide version of GSSAPI

T
TLS [Nettls_gnutls.GNUTLS_ENDPOINT]
TLS [Nettls_gnutls]
Same as GNUTLS, but without the extra gnutls_* functions
TLS [Netsys_crypto_types.FILE_TLS_ENDPOINT]
TLS [Netsys_crypto_types.TLS_ENDPOINT]
TLS [Netsys_crypto_types.TLS_CONFIG]
Table [Netcgi_apache.Apache]
Tls
Type_name [Netasn1]

U
ULB [Netulex]
Ulexing [Netulex]
Unixqueue
Unixqueues are one of the two forms of system event loops provided by Ocamlnet.
Unixqueue_pollset
Unixqueue implementation on top of Netsys_pollset
Unixqueue_select
This the old Unix.select-based imeplementation of event systems which was the default one until Ocamlnet-2.2.
Uq_client
Support for socket clients
Uq_datagram
Datagrams
Uq_engines
An engine performs a certain task in an autonomous way.
Uq_engines_compat
Compatibility with OCamlnet-3
Uq_gtk
Integration with lablgtk/lablgtk2 event systems
Uq_io
Unified engines for stream I/O
Uq_libevent
Use Libevent as event loop
Uq_lwt
Compatibility with Lwt
Uq_mt
Using engines in multi-threaded programs
Uq_multiplex
Multiplex Controllers
Uq_resolver
Support for pluggable resolvers
Uq_server
Server sockets
Uq_socks5
This module implements a SOCKS version 5 client (see RFC 1928) for use with the Uq_engines.connector, Uq_engines.listener, and Uq_engines.datagram_provider engine factories.
Uq_tcl
Integration with the labltk event system
Uq_transfer
Transfer engines
Url [Netencoding]

V
V2 [Rpc_portmapper_clnt.Make'PMAP]
V3 [Rpc_portmapper_clnt.Make'PMAP]
V4 [Rpc_portmapper_clnt.Make'PMAP]
Value [Netasn1]

X
X509_DN_string [Netx509]
Parser/printer for distnguished names as they may occur in X.509 certificates
ocamlnet-4.1.2/doc/html-main/Uq_gtk.html0000644000175000017500000004514712731530352016533 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_gtk

Module Uq_gtk

module Uq_gtk: sig .. end
Integration with lablgtk/lablgtk2 event systems


Integration with lablgtk/lablgtk2 event systems

Integration with lablgtk/lablgtk2 event systems

This module provides integration of Unixqueue event systems with the Glib event queue (and, as a consequence, with the lablgtk event queue).

There are two flavours of this module, both named Uq_gtk, and with identical interfaces, but one is used with lablgtk, and one with lablgtk2. Compile with

 ocamlfind ... -package equeue-gtk1 ... 
to get the variant for lablgtk, and compile with
 ocamlfind ... -package equeue-gtk2 ... 
to get the variant for lablgtk2.

OPAM users: Note that the OPAM package for OCamlnet does not build with lablgtk support by default. The trigger for this is the presence of the lablgtk OPAM package, i.e. do opam install lablgtk to include equeue-gtk2 in a rebuild. (There is no lablgtk-1 anymore in OPAM.)

type runner = Unixqueue.event_system -> (unit -> unit) -> unit 
class gtk_event_system : ?run:runner -> unit -> Unixqueue.event_system
This class is an alternate implementation of the Unixqueue event systems for the Glib event loop.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.delay_engine.html0000644000175000017500000004145612731530352023060 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.delay_engine float ->
(unit -> '#Uq_engines.engine) ->
Unixqueue.event_system -> ['a] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/Netencoding.Base64.decoding_pipe-c.html0000644000175000017500000004247212731530352023567 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Base64.decoding_pipe

Class Netencoding.Base64.decoding_pipe

class decoding_pipe : ?accept_spaces:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipe
This pipe decodes the data written into the pipe. url_variant and accept_spaces work as in decode.

ocamlnet-4.1.2/doc/html-main/type_Nettls_gnutls.GNUTLS_PROVIDER.html0000644000175000017500000007564612731530352023543 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.GNUTLS_PROVIDER sig
  type config
  type credentials
  type endpoint
  module Exc : Netsys_crypto_types.TLS_EXCEPTIONS
  val error_message : string -> string
  type dh_params =
      [ `Generate of int | `PKCS3_DER of string | `PKCS3_PEM_file of string ]
  val create_config :
    ?algorithms:string ->
    ?dh_params:dh_params ->
    ?verify:(endpoint -> bool -> bool -> bool) ->
    peer_auth:[ `None | `Optional | `Required ] ->
    credentials:credentials -> unit -> config
  type crt_list = [ `DER of string list | `PEM_file of string ]
  type crl_list = [ `DER of string list | `PEM_file of string ]
  type private_key =
      [ `DSA of string
      | `EC of string
      | `PEM_file of string
      | `PKCS8 of string
      | `PKCS8_encrypted of string
      | `RSA of string ]
  val create_x509_credentials :
    ?system_trust:bool ->
    ?trust:crt_list list ->
    ?revoke:crl_list list ->
    ?keys:(crt_list * private_key * string option) list ->
    unit -> credentials
  val create_endpoint :
    role:[ `Client | `Server ] ->
    recv:(Netsys_types.memory -> int) ->
    send:(Netsys_types.memory -> int -> int) ->
    peer_name:string option -> config -> endpoint
  val stash_endpoint : endpoint -> exn
  val restore_endpoint :
    recv:(Netsys_types.memory -> int) ->
    send:(Netsys_types.memory -> int -> int) -> exn -> endpoint
  val resume_client :
    recv:(Netsys_types.memory -> int) ->
    send:(Netsys_types.memory -> int -> int) ->
    peer_name:string option -> config -> string -> endpoint
  type state =
      [ `Accepting
      | `Data_r
      | `Data_rs
      | `Data_rw
      | `Data_w
      | `End
      | `Handshake
      | `Refusing
      | `Start
      | `Switching ]
  val get_state : endpoint -> state
  type raw_credentials = [ `Anonymous | `X509 of string ]
  val at_transport_eof : endpoint -> bool
  val hello : endpoint -> unit
  val bye : endpoint -> Unix.shutdown_command -> unit
  val verify : endpoint -> unit
  val get_config : endpoint -> config
  val get_endpoint_creds : endpoint -> raw_credentials
  val get_peer_creds : endpoint -> raw_credentials
  val get_peer_creds_list : endpoint -> raw_credentials list
  val switch : endpoint -> config -> unit
  val accept_switch : endpoint -> config -> unit
  val refuse_switch : endpoint -> unit
  val send : endpoint -> Netsys_types.memory -> int -> int
  val recv : endpoint -> Netsys_types.memory -> int
  val recv_will_not_block : endpoint -> bool
  val get_session_id : endpoint -> string
  val get_session_data : endpoint -> string
  val get_cipher_suite_type : endpoint -> string
  val get_cipher_algo : endpoint -> string
  val get_kx_algo : endpoint -> string
  val get_mac_algo : endpoint -> string
  val get_compression_algo : endpoint -> string
  val get_cert_type : endpoint -> string
  val get_protocol : endpoint -> string
  type server_name = [ `Domain of string ]
  val get_addressed_servers : endpoint -> server_name list
  val set_session_cache :
    store:(string -> string -> unit) ->
    remove:(string -> unit) ->
    retrieve:(string -> string) -> endpoint -> unit
  val implementation_name : string
  val implementation : unit -> exn
  val gnutls_session : endpoint -> Nettls_gnutls_bindings.gnutls_session_t
  val gnutls_credentials :
    credentials -> Nettls_gnutls_bindings.gnutls_credentials
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.async_out_channel-c.html0000644000175000017500000004402412731530352024645 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.async_out_channel

Class type Uq_engines_compat.async_out_channel

class type async_out_channel = object .. end

method output : Bytes.t -> int -> int -> int
method close_out : unit -> unit
method pos_out : int
method flush : unit -> unit
method can_output : bool
method request_notification : (unit -> bool) -> unit
ocamlnet-4.1.2/doc/html-main/type_Netgzip.html0000644000175000017500000004515412731530352017760 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip sig
  class input_gzip : Gzip.in_channel -> Netchannels.in_obj_channel
  class output_gzip : Gzip.out_channel -> Netchannels.out_obj_channel
  class inflating_pipe : unit -> Netchannels.io_obj_channel
  class deflating_pipe : ?level:int -> unit -> Netchannels.io_obj_channel
  class input_inflate :
    Netchannels.in_obj_channel -> Netchannels.in_obj_channel
  class input_deflate :
    ?level:int -> Netchannels.in_obj_channel -> Netchannels.in_obj_channel
  class output_inflate :
    Netchannels.out_obj_channel -> Netchannels.out_obj_channel
  class output_deflate :
    ?level:int -> Netchannels.out_obj_channel -> Netchannels.out_obj_channel
  val init : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram.html0000644000175000017500000011757312731530352021115 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram sig
  type ptype = [ `GSSAPI | `SASL ]
  type profile = {
    ptype : Netmech_scram.ptype;
    hash_function : Netsys_digests.iana_hash_fn;
    return_unknown_user : bool;
    iteration_count_limit : int;
  }
  type cb = Netsys_sasl_types.cb
  type server_error =
      [ `Channel_binding_not_supported
      | `Channel_bindings_dont_match
      | `Extension of string
      | `Extensions_not_supported
      | `Invalid_encoding
      | `Invalid_proof
      | `Invalid_username_encoding
      | `No_resources
      | `Other_error
      | `Server_does_support_channel_binding
      | `Unknown_user
      | `Unsupported_channel_binding_type ]
  type client_session
  type server_session
  exception Invalid_encoding of string * string
  exception Invalid_username_encoding of string * string
  exception Extensions_not_supported of string * string
  exception Protocol_error of string
  exception Invalid_server_signature
  exception Server_error of Netmech_scram.server_error
  val error_of_exn : exn -> string
  val profile :
    ?return_unknown_user:bool ->
    ?iteration_count_limit:int ->
    Netmech_scram.ptype ->
    Netsys_digests.iana_hash_fn -> Netmech_scram.profile
  val string_of_server_error : Netmech_scram.server_error -> string
  val server_error_of_string : string -> Netmech_scram.server_error
  val mechanism_name : Netmech_scram.profile -> string
  val create_client_session :
    ?nonce:string ->
    Netmech_scram.profile -> string -> string -> Netmech_scram.client_session
  val create_client_session2 :
    ?nonce:string ->
    Netmech_scram.profile ->
    string -> string -> string -> Netmech_scram.client_session
  val client_configure_channel_binding :
    Netmech_scram.client_session ->
    Netmech_scram.cb -> Netmech_scram.client_session
  val client_restart :
    Netmech_scram.client_session -> string -> Netmech_scram.client_session
  val client_restart_stale :
    Netmech_scram.client_session -> string -> Netmech_scram.client_session
  val client_emit_flag : Netmech_scram.client_session -> bool
  val client_recv_flag : Netmech_scram.client_session -> bool
  val client_finish_flag : Netmech_scram.client_session -> bool
  val client_semifinish_flag : Netmech_scram.client_session -> bool
  val client_error_flag : Netmech_scram.client_session -> exn option
  val client_channel_binding :
    Netmech_scram.client_session -> Netmech_scram.cb
  val client_emit_message :
    Netmech_scram.client_session -> Netmech_scram.client_session * string
  val client_emit_message_kv :
    Netmech_scram.client_session ->
    Netmech_scram.client_session * string option * (string * string) list
  val client_recv_message :
    Netmech_scram.client_session -> string -> Netmech_scram.client_session
  val client_protocol_key : Netmech_scram.client_session -> string option
  val client_user_name : Netmech_scram.client_session -> string
  val client_authz_name : Netmech_scram.client_session -> string
  val client_password : Netmech_scram.client_session -> string
  val client_export : Netmech_scram.client_session -> string
  val client_import : string -> Netmech_scram.client_session
  val client_prop : Netmech_scram.client_session -> string -> string
  type credentials =
      [ `Salted_password of string * string * int
      | `Stored_creds of string * string * string * int ]
  val create_server_session :
    ?nonce:string ->
    Netmech_scram.profile ->
    (string -> Netmech_scram.credentials) -> Netmech_scram.server_session
  val create_server_session2 :
    ?nonce:string ->
    Netmech_scram.profile ->
    (string -> string -> Netmech_scram.credentials) ->
    Netmech_scram.server_session
  val create_salt : unit -> string
  val salt_password :
    Netsys_digests.iana_hash_fn -> string -> string -> int -> string
  val stored_key :
    Netsys_digests.iana_hash_fn -> string -> string -> int -> string * string
  val server_emit_flag : Netmech_scram.server_session -> bool
  val server_recv_flag : Netmech_scram.server_session -> bool
  val server_finish_flag : Netmech_scram.server_session -> bool
  val server_error_flag : Netmech_scram.server_session -> bool
  val server_emit_message :
    Netmech_scram.server_session -> Netmech_scram.server_session * string
  val server_emit_message_kv :
    Netmech_scram.server_session ->
    Netmech_scram.server_session * (string * string) list
  val server_recv_message :
    Netmech_scram.server_session -> string -> Netmech_scram.server_session
  val server_protocol_key : Netmech_scram.server_session -> string option
  val server_channel_binding :
    Netmech_scram.server_session -> Netmech_scram.cb
  val server_user_name : Netmech_scram.server_session -> string option
  val server_authz_name : Netmech_scram.server_session -> string option
  val server_export : Netmech_scram.server_session -> string
  val server_import : string -> Netmech_scram.server_session
  val server_import_any :
    string ->
    (string -> Netmech_scram.credentials) -> Netmech_scram.server_session
  val server_import_any2 :
    string ->
    (string -> string -> Netmech_scram.credentials) ->
    Netmech_scram.server_session
  val server_prop : Netmech_scram.server_session -> string -> string
  type specific_keys = { kc : string; ke : string; ki : string; }
  module AES_CTS :
    sig
      val c : int
      val m : int
      val encrypt : string -> string -> string
      val encrypt_mstrings :
        string -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
      val decrypt : string -> string -> string
      val decrypt_mstrings :
        string -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
      val tests : (string * string * string) list
      val run_tests : unit -> bool
      val run_mtests : unit -> bool
    end
  module Cryptosystem :
    sig
      exception Integrity_error
      val derive_keys : string -> int -> Netmech_scram.specific_keys
      val encrypt_and_sign : Netmech_scram.specific_keys -> string -> string
      val encrypt_and_sign_mstrings :
        Netmech_scram.specific_keys ->
        Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
      val decrypt_and_verify :
        Netmech_scram.specific_keys -> string -> string
      val decrypt_and_verify_mstrings :
        Netmech_scram.specific_keys ->
        Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
      val get_ec : Netmech_scram.specific_keys -> int -> int
      val get_mic : Netmech_scram.specific_keys -> string -> string
      val get_mic_mstrings :
        Netmech_scram.specific_keys -> Netxdr_mstring.mstring list -> string
    end
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Netsockaddr.html0000644000175000017500000004372312731530352020601 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsockaddr sig
  type socksymbol =
      [ `Inet of Unix.inet_addr * int
      | `Inet_byname of string * int
      | `Unix of string ]
  val socksymbol_of_string : string -> Netsockaddr.socksymbol
  val string_of_socksymbol : Netsockaddr.socksymbol -> string
  val norm_socksymbol : Netsockaddr.socksymbol -> Netsockaddr.socksymbol
  val ipv6_socksymbol : Netsockaddr.socksymbol -> Netsockaddr.socksymbol
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_tmp.html0000644000175000017500000004145612731530352020506 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_tmp sig
  val tmp_directory : unit -> string
  val tmp_prefix : string -> string
  val set_tmp_directory : string -> unit
end
ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi_types.cgi_argument-c.html0000644000175000017500000005151712731530352025453 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_types.cgi_argument

Class type Netcgi1_compat.Netcgi_types.cgi_argument

class type cgi_argument = object .. end
Portage: In addition to defining a type, the following cgi_argument also defines a conversion function that allows to connect old scripts to the new infrastructure. Finalizing cgi_argument a will also finalize a.

method name : string
method value : string
method open_value_rd : unit -> Netchannels.in_obj_channel
method ro : bool
Irrelevant: there are no methods to mutate an argument.
method store : store
method content_type : string
method content_type_params : (string * Netmime_string.s_param) list
Method content_type : unit -> string * (string * Netmime_string.s_param) list defined instead of content_type and content_type_params to be coherent with Netmime.mime_header_ro -- yet as easy to use.
method charset : string
method filename : string option
method representation : representation
method finalize : unit -> unit
method set_value : string -> unit
Dealing with the arguments is the task of an higher order library. In fact, it is generally misleading to think arguments as mutable because one must accomodate the back button -- so cache, history,... will use the "initial args". Moreover, the only place where mutability is interesting is the #url method which -- as already remarked -- can be dealt with in a purely functional way.

The new interface contains commodity functions to update lists of arguments (see Netcgi.Argument).

method open_value_wr : unit -> Netchannels.out_obj_channel
See #set_value.
ocamlnet-4.1.2/doc/html-main/type_Netsys_posix.post_fork_handler.html0000644000175000017500000004113312731530352024542 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_posix.post_fork_handler object method name : string method run : unit -> unit endocamlnet-4.1.2/doc/html-main/type_Uq_engines.input_engine.html0000644000175000017500000004154312731530352023116 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.input_engine (Unix.file_descr -> 'a) ->
Unix.file_descr -> float -> Unixqueue.event_system -> ['a] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.serializer.html0000644000175000017500000004102612731530352022577 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.serializer Unixqueue.event_system -> ['a] Uq_engines.serializer_tocamlnet-4.1.2/doc/html-main/type_Netcompression.html0000644000175000017500000004344712731530352021353 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcompression sig
  val register :
    iana_name:string ->
    ?encoder:(unit -> Netchannels.io_obj_channel) ->
    ?decoder:(unit -> Netchannels.io_obj_channel) -> unit -> unit
  val lookup_encoder : iana_name:string -> unit -> Netchannels.io_obj_channel
  val lookup_decoder : iana_name:string -> unit -> Netchannels.io_obj_channel
  val all_encoders : unit -> string list
  val all_decoders : unit -> string list
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.poll_process_engine-c.html0000644000175000017500000004535612731530352023650 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.poll_process_engine

Class Uq_engines.poll_process_engine

class poll_process_engine : ?period:float -> pid:int -> Unixqueue.event_system -> [Unix.process_status] engine
This class is deprecated! Use the classes in Shell_uq instead.

This engine waits until the process with the ID pid terminates. When this happens, the state of the engine changes to `Done, and the argument of `Done is the process status.

The engine does not catch stopped processes.

The engine checks the process status every period seconds, and whenever there is a Signal event on the queue. The idea of the latter is that the user of this engine can increase the responsiveness by defining a signal handler for SIGCHLD signals (the handler need not to perform any special action, it must just be defined). When the sub process terminates, a SIGCHLD signal is sent to the current process. If the event loop happens to wait for new conditions (which is usually very likely), a Signal event will be generated, and the engine will check the process status very soon. Note that it is not guaranteed that a terminating process triggers a Signal event, although it is very likely.

You can define an empty SIGCHLD handler with:

 Sys.set_signal Sys.sigchld (Sys.Signal_handle (fun _ -> ())) 


period : Every period seconds the process status is checked. Defaults to 0.1 seconds.

ocamlnet-4.1.2/doc/html-main/type_Netftp_client.ftp_client_pi.html0000644000175000017500000004661612731530352023760 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_client.ftp_client_pi object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method exec_e :
    ?prelim:(Netftp_client.ftp_state -> Netftp_client.reply -> unit) ->
    Netftp_client.cmd ->
    (Netftp_client.ftp_state * Netftp_client.reply) Uq_engines.engine
  method ftp_state : Netftp_client.ftp_state
  method gssapi_props : Netsys_gssapi.client_props option
  method is_empty : bool
  method mlst_enabled_facts : string list
  method mlst_facts : string list
  method need_ip6 : bool
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    (unit Uq_engines.engine -> bool) -> unit
  method run : unit -> unit
  method send_abort : unit -> unit
  method state : unit Uq_engines.engine_state
  method supports_mdtm : bool
  method supports_mlst : bool
  method supports_size : bool
  method supports_tls : bool
  method supports_tvfs : bool
  method supports_utf8 : bool
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.output_async_descr-c.html0000644000175000017500000004260012731530352025064 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.output_async_descr

Class Uq_engines_compat.output_async_descr

class output_async_descr : dst:Unix.file_descr -> ?buffer_size:int -> ?close_dst:bool -> Unixqueue.event_system -> async_out_channel_engine

ocamlnet-4.1.2/doc/html-main/Uq_client.client_endpoint_connector-c.html0000644000175000017500000004414412731530352024667 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_client.client_endpoint_connector

Class type Uq_client.client_endpoint_connector

class type client_endpoint_connector = object .. end
This class type provides engines to connect to a service. In order to get and activate such an engine, call connect.

method connect : connect_address ->
Unixqueue.event_system -> connect_status Uq_engines.engine
Instantiates an engine that connects to the endpoint given by the connect_address argument. If successful, the state of the engine changes to `Done(status) where status contains the socket details. The connection is established in the background.

The type of status will correspond to the type of connect address (e.g. a `Socket address will return a `Socket status).

The close-on-exec flag of the created socket descriptor is always set. The socket descriptor is always in non-blocking mode.

ocamlnet-4.1.2/doc/html-main/type_Netsmtp.Debug.html0000644000175000017500000004100012731530352021001 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsmtp.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netx509_pubkey.Key.html0000644000175000017500000005464612731530352020567 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey.Key

Module Netx509_pubkey.Key

module Key: sig .. end


These OIDs are used when storing public keys
val rsa_key : Netx509_pubkey.oid
alias PKCS-1. RFC-3279, RFC-3447
val rsassa_pss_key : Netx509_pubkey.oid
RSASSA-PSS. RFC-4055, RFC-3447
val rsaes_oaep_key : Netx509_pubkey.oid
RSAES-OAEP. RFC-4055, RFC-3447
val dsa_key : Netx509_pubkey.oid
DSA. RFC-3279
val dh_key : Netx509_pubkey.oid
DH. RFC-3279
val ec_key : Netx509_pubkey.oid
All EC variants (ECDSA, ECDH, ECMQV). RFC-3279
val ecdh_key : Netx509_pubkey.oid
EC restricted to ECDH (RFC-5480)
val ecmqv_key : Netx509_pubkey.oid
EC restricted to ECMQV (RFC-5480)
val kea_key : Netx509_pubkey.oid
KEA. RFC-3279
val eddsa_key : Netx509_pubkey.oid
EDDSA. draft-josefsson-pkix-eddsa
val catalog : (string * string list * string * Netx509_pubkey.oid) list
(name, aliases, privkey_name, oid)
val private_key_format_of_key : Netx509_pubkey.oid -> string
Get the type of private key for a public key OID

It is possible to derive public keys from rsa_key format so that they can be used with the RSASSA-PSS and RSAES-OAEP algorithms:
val create_rsassa_pss_alg_id : hash_function:Netx509_pubkey.hash_function ->
maskgen_function:Netx509_pubkey.maskgen_function ->
salt_length:int -> unit -> Netx509_pubkey.alg_id
create_rsassa_pss_alg_id ... : Creates an algorithm identifier for RSASSA-PSS.
val create_rsassa_pss_key : hash_function:Netx509_pubkey.hash_function ->
maskgen_function:Netx509_pubkey.maskgen_function ->
salt_length:int -> Netx509_pubkey.pubkey -> Netx509_pubkey.pubkey
Derives a public key that is specific for RSASSA-PSS from an RSA public key.
val create_rsaes_oaep_alg_id : hash_function:Netx509_pubkey.hash_function ->
maskgen_function:Netx509_pubkey.maskgen_function ->
psource_function:string -> unit -> Netx509_pubkey.alg_id
create_rsaep_oaep_alg_id ... : Creates an algorithm identifier for RSAES-OAEP.
val create_rsaes_oaep_key : hash_function:Netx509_pubkey.hash_function ->
maskgen_function:Netx509_pubkey.maskgen_function ->
psource_function:string -> Netx509_pubkey.pubkey -> Netx509_pubkey.pubkey
Derives a public key that is specific for RSAES-OAEP from an RSA public key.
ocamlnet-4.1.2/doc/html-main/type_Uq_datagram.wrapped_datagram_socket.html0000644000175000017500000004415712731530352025440 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_datagram.wrapped_datagram_socket object
  method datagram_type : Uq_datagram.datagram_type
  method descriptor : Unix.file_descr
  method recvfrom :
    Bytes.t -> int -> int -> Unix.msg_flag list -> int * Uq_engines.sockspec
  method sendto :
    Bytes.t -> int -> int -> Unix.msg_flag list -> Uq_engines.sockspec -> int
  method shut_down : unit -> unit
  method socket_domain : Unix.socket_domain
  method socket_protocol : int
  method socket_type : Unix.socket_type
end
ocamlnet-4.1.2/doc/html-main/Unixqueue_pollset.html0000644000175000017500000004335612731530352021033 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_pollset

Module Unixqueue_pollset

module Unixqueue_pollset: sig .. end
Unixqueue implementation on top of Netsys_pollset

class pollset_event_system : Netsys_pollset.pollset -> Unixqueue_util.event_system
val pollset_event_system : Netsys_pollset.pollset -> Unixqueue_util.event_system_t
Implements a unixqueue on top of a pollset.
ocamlnet-4.1.2/doc/html-main/type_Netsys_gssapi.client_config.html0000644000175000017500000004267112731530352023776 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.client_config object
  method flags : (Netsys_gssapi.req_flag * Netsys_gssapi.support_level) list
  method initiator_cred : exn option
  method initiator_name : (string * Netsys_gssapi.oid) option
  method integrity : Netsys_gssapi.support_level
  method mech_type : Netsys_gssapi.oid
  method privacy : Netsys_gssapi.support_level
  method target_name : (string * Netsys_gssapi.oid) option
end
ocamlnet-4.1.2/doc/html-main/Netmech_spnego_http.SPNEGO.html0000644000175000017500000007403612731530352022267 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_spnego_http.SPNEGO

Functor Netmech_spnego_http.SPNEGO

module SPNEGO: 
The SPNEGO mechanism for HTTP, see Netmech_spnego_http
Parameters:
P : PROFILE
G : Netsys_gssapi.GSSAPI

val mechanism_name : string
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
val restart_supported : bool
Whether the mechanism supports quick restarts (re-authentication)
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

The password is encoded in UTF-8. However, note that not all protocols are able to transmit all of UTF-8. If a non-transmittable character is found, the authentication will fail.

The password can have parameters:

  • "realm": the password is only applicable to this realm. The realm parameter should only occur once.
  • "domain-uri": the password is only applicable to this URI space. The URI must include the protocol scheme, the host name, and "/" as path. The port number is optional. Example: "http://localhost/". The domain-uri parameter can occur several times.

val client_match : params:(string * string * bool) list ->
Nethttp.Header.auth_challenge -> Nethttp.match_result
Checks whether this mechanism can accept the initial authentication challenge (i.e. the first challenge sent from the server to the client. The params are as for create_client_session. On success, returns `Accept(realm,id_opt). On failure, returns `Reject. This function usually does not raise exceptions.

If the mechanism does not support the notion of realms, a dummy realm should be returned.

The id_opt is the session ID (if supported). Session IDs can be used to bind reauthentications to the original session.

The challenge is from a www-authenticate or a proxy-authenticate header.

There is also the result `Reroute(realm, trans_id), meaning that the request would be acceptable if it came over the transport identified by trans_id. `Accept_reroute is the combination of accepting and rerouting, i.e. the auth protocol can start, but the second request should go over the other transport. Both `Reroute and `Accept_reroute are only allowed for initial challenges.

type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user. The credentials are creds.

user must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

Available parameters:

  • "realm"
  • "id" (if client_match returns a session ID)
  • "trans_id": the Nethttp_client.transport_layer_id of the current HTTP request
  • "conn_id": an identifier for the TCP connection
  • "https": is set to "true" if the current connection is TLS-secured
  • "target-host": the hostname from the HTTP request
  • "target-uri": the URL from the HTTP request

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : params:(string * string * bool) list ->
client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK. After the restart the session will be in state `Emit.

The params are the same as for create_client_session, but updated where needed.

val client_process_challenge : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
Nethttp.Header.auth_challenge -> client_session
client_process_challenge cs method uri header challenge:

Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.

method is the request method. uri is the request URI

val client_emit_response : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
client_session *
Nethttp.Header.auth_credentials * (string * string) list
let (creds,new_headers) = client_emit_response cs method uri header:

Emit a new response as a pair (creds,new_headers). The state must be `Emit. The creds either go into the authorization or proxy-authorization header. The new_headers are additional headers to modify.

val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_domain : client_session -> string list
After successful authentication, this function may return the URIs defining the authentication space.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. Commonly supported keys:
  • "realm"
  • "domain-uri"

val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Returns the GSSAPI props if available, or raise Not_found
ocamlnet-4.1.2/doc/html-main/Equeue.html0000644000175000017500000005540012731530352016523 0ustar gerdgerd Ocamlnet 4 Reference Manual : Equeue

Module Equeue

module Equeue: sig .. end
Equeue implements generic event queues. An event system consists of an event queue, a list of event handlers, and an event source. The queue has FIFO semantics, i.e. the first event is processed next, and new events are appended to its end. When an event is delivered to an event handler, all handlers are tried until a handler accepts the event (or the event is dropped if no such handler can be found). See below how a handler can indicate whether to accept or reject an event.

When the queue is empty, the event source is called once. The source can add events to the queue, in order to continue event processing. If the queue remains empty, the execution of the event system stops.



THREAD SAFETY

The module can be used in multi-threaded program provided no event system is shared by several threads, or if so, access to functions is serialized.

type 'a t 
This is the type of an event system with events of type 'a
exception Reject
May be raised by event handlers to reject events
exception Terminate
May be raised by event handlers to accept events while terminating themselves
exception Out_of_handlers
Raised by run when the event source adds new events to the queue but there are no event handlers to process them
val create : ?string_of_event:('a -> string) -> ('a t -> unit) -> 'a t
Creates a new event system that has an event source, but is otherwise empty. The argument of type 'a t -> unit is the event source. The source can call add_event to put new events into the queue.


string_of_event : Optionally, one can pass a printer for events. This has only an effect for debugging output.
val add_event : 'a t -> 'a -> unit
Puts an event into the event queue of the system.
val add_handler : 'a t -> ('a t -> 'a -> unit) -> unit
Adds a handler to the list of handlers of the system.

An event handler is called with the event system and the event as arguments. The handler can return in various ways:

  • Return normally: This means that the event is accepted by the handler. No other handler will be asked to process the event.
  • Raise Reject: The event is rejected by the handler. The other handlers are asked to process the event.
  • Raise Terminate: The event is accepted, but the handler is terminated, i.e. will never be called again.
  • Raise another exception: The event is deferred, and will be processed again in the future, but after the already queued events. Furthermore, the exception falls through to the caller of run.
The handler can add new events and new event handlers. The latter will be activated when the next event is processed.
val run : 'a t -> unit
Running a system means that, unless the queue is empty, the events at the time of the run invocation and all later added events are gone through. Each event is presented to the handlers until one handler accepts the event. Events rejected by all handlers are dropped silently. If there is no pending event the default event source is called once. If there are still no events the system stops and returns. If there are events to process but no handlers which can do them all events are silently dropped, and the default event source is called once.

The exception Out_of_handlers is raised if there are events but no handlers after the event source has been called. This is considered as a programming error, and would cause infinite looping if not detected.

Note that there is an implicit order among the handlers which is simply the order the handlers have been added to the system. This means that you can set a fallback handler which catches any unprocessed event by adding it last.

Note that the events are processed in the order they happen. There is no mechanism to assign priorities to events.

Handlers are allowed to raise arbitrary exceptions. Exceptions other than Reject and Terminate are not caught, so the caller has to do this if appropriate. It is possible to restart an event system by just calling run again.

val is_running : 'a t -> bool
Returns whether the event loop is active
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.html0000644000175000017500000016766512731530352020616 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels sig
  exception Closed_channel
  exception Buffer_underrun
  exception Command_failure of Unix.process_status
  class type rec_in_channel =
    object
      method close_in : unit -> unit
      method input : Bytes.t -> int -> int -> int
    end
  class type raw_in_channel =
    object
      method close_in : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method pos_in : int
    end
  class type rec_out_channel =
    object
      method close_out : unit -> unit
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
    end
  class type raw_out_channel =
    object
      method close_out : unit -> unit
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method pos_out : int
    end
  class type raw_io_channel =
    object
      method close_in : unit -> unit
      method close_out : unit -> unit
      method flush : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method output : Bytes.t -> int -> int -> int
      method pos_in : int
      method pos_out : int
    end
  class type compl_in_channel =
    object
      method input_byte : unit -> int
      method input_char : unit -> char
      method input_line : unit -> string
      method really_input : Bytes.t -> int -> int -> unit
      method really_input_string : int -> string
    end
  class type in_obj_channel =
    object
      method close_in : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method input_byte : unit -> int
      method input_char : unit -> char
      method input_line : unit -> string
      method pos_in : int
      method really_input : Bytes.t -> int -> int -> unit
      method really_input_string : int -> string
    end
  class type compl_out_channel =
    object
      method output_buffer : Buffer.t -> unit
      method output_byte : int -> unit
      method output_bytes : Bytes.t -> unit
      method output_channel : ?len:int -> Netchannels.in_obj_channel -> unit
      method output_char : char -> unit
      method output_string : string -> unit
      method really_output : Bytes.t -> int -> int -> unit
      method really_output_string : string -> int -> int -> unit
    end
  class type out_obj_channel =
    object
      method close_out : unit -> unit
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method output_buffer : Buffer.t -> unit
      method output_byte : int -> unit
      method output_bytes : Bytes.t -> unit
      method output_channel : ?len:int -> in_obj_channel -> unit
      method output_char : char -> unit
      method output_string : string -> unit
      method pos_out : int
      method really_output : Bytes.t -> int -> int -> unit
      method really_output_string : string -> int -> int -> unit
    end
  class type io_obj_channel =
    object
      method close_in : unit -> unit
      method close_out : unit -> unit
      method flush : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method input_byte : unit -> int
      method input_char : unit -> char
      method input_line : unit -> string
      method output : Bytes.t -> int -> int -> int
      method output_buffer : Buffer.t -> unit
      method output_byte : int -> unit
      method output_bytes : Bytes.t -> unit
      method output_channel : ?len:int -> in_obj_channel -> unit
      method output_char : char -> unit
      method output_string : string -> unit
      method pos_in : int
      method pos_out : int
      method really_input : Bytes.t -> int -> int -> unit
      method really_input_string : int -> string
      method really_output : Bytes.t -> int -> int -> unit
      method really_output_string : string -> int -> int -> unit
    end
  class type trans_out_obj_channel =
    object
      method close_out : unit -> unit
      method commit_work : unit -> unit
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method output_buffer : Buffer.t -> unit
      method output_byte : int -> unit
      method output_bytes : Bytes.t -> unit
      method output_channel : ?len:int -> in_obj_channel -> unit
      method output_char : char -> unit
      method output_string : string -> unit
      method pos_out : int
      method really_output : Bytes.t -> int -> int -> unit
      method really_output_string : string -> int -> int -> unit
      method rollback_work : unit -> unit
    end
  class input_channel :
    ?onclose:(unit -> unit) -> Pervasives.in_channel -> in_obj_channel
  val input_channel :
    ?onclose:(unit -> unit) ->
    Pervasives.in_channel -> Netchannels.in_obj_channel
  class input_command : string -> in_obj_channel
  val input_command : string -> Netchannels.in_obj_channel
  class input_string : ?pos:int -> ?len:int -> string -> in_obj_channel
  val input_string :
    ?pos:int -> ?len:int -> string -> Netchannels.in_obj_channel
  class input_bytes : ?pos:int -> ?len:int -> Bytes.t -> in_obj_channel
  val input_bytes :
    ?pos:int -> ?len:int -> Bytes.t -> Netchannels.in_obj_channel
  class input_memory :
    ?pos:int -> ?len:int -> Netsys_types.memory -> in_obj_channel
  val input_memory :
    ?pos:int -> ?len:int -> Netsys_types.memory -> Netchannels.in_obj_channel
  val input_tstring :
    ?pos:int ->
    ?len:int -> Netsys_types.tstring -> Netchannels.in_obj_channel
  val create_input_netbuffer :
    ?keep_data:bool ->
    Netbuffer.t -> Netchannels.in_obj_channel * (unit -> unit)
  val lexbuf_of_in_obj_channel : Netchannels.in_obj_channel -> Lexing.lexbuf
  val string_of_in_obj_channel : Netchannels.in_obj_channel -> string
  val bytes_of_in_obj_channel : Netchannels.in_obj_channel -> Bytes.t
  val lines_of_in_obj_channel : Netchannels.in_obj_channel -> string list
  val with_in_obj_channel :
    (#Netchannels.in_obj_channel as 'a) -> ('-> 'b) -> 'b
  class output_channel :
    ?onclose:(unit -> unit) -> Pervasives.out_channel -> out_obj_channel
  class output_command : ?onclose:(unit -> unit) -> string -> out_obj_channel
  class output_buffer :
    ?onclose:(unit -> unit) -> Buffer.t -> out_obj_channel
  class output_netbuffer :
    ?onclose:(unit -> unit) -> Netbuffer.t -> out_obj_channel
  class output_null : ?onclose:(unit -> unit) -> unit -> out_obj_channel
  val with_out_obj_channel :
    (#Netchannels.out_obj_channel as 'a) -> ('-> 'b) -> 'b
  class rec_in_channel_delegation :
    ?close:bool -> Netchannels.rec_in_channel -> rec_in_channel
  class raw_in_channel_delegation :
    ?close:bool -> Netchannels.raw_in_channel -> raw_in_channel
  class in_obj_channel_delegation :
    ?close:bool -> Netchannels.in_obj_channel -> in_obj_channel
  class rec_out_channel_delegation :
    ?close:bool -> Netchannels.rec_out_channel -> rec_out_channel
  class raw_out_channel_delegation :
    ?close:bool -> Netchannels.raw_out_channel -> raw_out_channel
  class out_obj_channel_delegation :
    ?close:bool -> Netchannels.out_obj_channel -> out_obj_channel
  val lift_in :
    ?eol:string list ->
    ?buffered:bool ->
    ?buffer_size:int ->
    ?pass_through:int ->
    [ `Raw of Netchannels.raw_in_channel | `Rec of Netchannels.rec_in_channel ] ->
    Netchannels.in_obj_channel
  val lift_out :
    ?buffered:bool ->
    ?buffer_size:int ->
    ?pass_through:int ->
    [ `Raw of Netchannels.raw_out_channel
    | `Rec of Netchannels.rec_out_channel ] -> Netchannels.out_obj_channel
  class virtual augment_raw_in_channel :
    object
      method virtual close_in : unit -> unit
      method virtual input : Bytes.t -> int -> int -> int
      method input_byte : unit -> int
      method input_char : unit -> char
      method input_line : unit -> string
      method virtual pos_in : int
      method really_input : Bytes.t -> int -> int -> unit
      method really_input_string : int -> string
    end
  class lift_rec_in_channel :
    ?start_pos_in:int -> Netchannels.rec_in_channel -> in_obj_channel
  class virtual augment_raw_out_channel :
    object
      method virtual close_out : unit -> unit
      method virtual flush : unit -> unit
      method virtual output : Bytes.t -> int -> int -> int
      method output_buffer : Buffer.t -> unit
      method output_byte : int -> unit
      method output_bytes : Bytes.t -> unit
      method output_channel : ?len:int -> in_obj_channel -> unit
      method output_char : char -> unit
      method output_string : string -> unit
      method virtual pos_out : int
      method really_output : Bytes.t -> int -> int -> unit
      method really_output_string : string -> int -> int -> unit
    end
  class lift_raw_out_channel : Netchannels.raw_out_channel -> out_obj_channel
  class lift_rec_out_channel :
    ?start_pos_out:int -> Netchannels.rec_out_channel -> out_obj_channel
  type input_result = [ `Data of int | `Separator of string ]
  class type enhanced_raw_in_channel =
    object
      method close_in : unit -> unit
      method private enhanced_input :
        Bytes.t -> int -> int -> Netchannels.input_result
      method private enhanced_input_line : unit -> string
      method input : Bytes.t -> int -> int -> int
      method pos_in : int
    end
  class buffered_raw_in_channel :
    ?eol:string list ->
    ?buffer_size:int ->
    ?pass_through:int ->
    Netchannels.raw_in_channel -> enhanced_raw_in_channel
  class buffered_raw_out_channel :
    ?buffer_size:int ->
    ?pass_through:int -> Netchannels.raw_out_channel -> raw_out_channel
  class input_descr :
    ?blocking:bool ->
    ?start_pos_in:int ->
    ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_in_channel
  class output_descr :
    ?blocking:bool ->
    ?start_pos_out:int ->
    ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_out_channel
  class socket_descr :
    ?blocking:bool ->
    ?start_pos_in:int ->
    ?start_pos_out:int ->
    ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_io_channel
  type close_mode = [ `Commit | `Rollback ]
  class buffered_trans_channel :
    ?close_mode:Netchannels.close_mode ->
    Netchannels.out_obj_channel -> trans_out_obj_channel
  val make_temporary_file :
    ?mode:int ->
    ?limit:int ->
    ?tmp_directory:string ->
    ?tmp_prefix:string ->
    unit -> string * Pervasives.in_channel * Pervasives.out_channel
  class tempfile_trans_channel :
    ?close_mode:Netchannels.close_mode ->
    ?tmp_directory:string ->
    ?tmp_prefix:string ->
    Netchannels.out_obj_channel -> trans_out_obj_channel
  class pipe :
    ?conv:(Netbuffer.t -> bool -> Netbuffer.t -> unit) ->
    ?buffer_size:int -> unit -> io_obj_channel
  class output_filter :
    Netchannels.io_obj_channel ->
    Netchannels.out_obj_channel -> out_obj_channel
  class input_filter :
    Netchannels.in_obj_channel ->
    Netchannels.io_obj_channel -> in_obj_channel
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels_crypto.tls_endpoint.html0000644000175000017500000004217212731530352024700 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.tls_endpoint ?start_pos_in:int ->
?start_pos_out:int ->
?resume:string ->
role:[ `Client | `Server ] ->
peer_name:string option ->
Unix.file_descr ->
Netsys_crypto_types.tls_config -> Netchannels_crypto.tls_channel
ocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi_types.html0000644000175000017500000007745512731530352023642 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_types sig
  class type simple_message = Netmime.mime_body
  type store = [ `File of string | `Memory ]
  type representation =
      [ `MIME of Netmime.mime_message
      | `Simple of Netcgi1_compat.Netcgi_types.simple_message ]
  class type cgi_argument =
    object
      method charset : string
      method content_type : string
      method content_type_params : (string * Netmime_string.s_param) list
      method filename : string option
      method finalize : unit -> unit
      method name : string
      method open_value_rd : unit -> Netchannels.in_obj_channel
      method open_value_wr : unit -> Netchannels.out_obj_channel
      method representation : Netcgi1_compat.Netcgi_types.representation
      method ro : bool
      method set_value : string -> unit
      method store : Netcgi1_compat.Netcgi_types.store
      method value : string
    end
  val to_compat_argument :
    Netcgi.cgi_argument -> Netcgi1_compat.Netcgi_types.cgi_argument
  val of_compat_argument :
    Netcgi1_compat.Netcgi_types.cgi_argument -> Netcgi.cgi_argument
  type cgi_cookie =
    Nethttp.netscape_cookie = {
    cookie_name : string;
    cookie_value : string;
    cookie_expires : float option;
    cookie_domain : string option;
    cookie_path : string option;
    cookie_secure : bool;
  }
  type status = Nethttp.http_status
  type request_method =
      [ `DELETE
      | `GET
      | `HEAD
      | `POST
      | `PUT of Netcgi1_compat.Netcgi_types.cgi_argument ]
  type cache_control = [ `Max_age of int | `No_cache | `Unspecified ]
  type query_string_spec =
      [ `Args of Netcgi1_compat.Netcgi_types.cgi_argument list
      | `Current
      | `Initial
      | `None ]
  type other_url_spec = [ `Env | `None | `This of string ]
  class type cgi_activation =
    object
      method argument : string -> Netcgi1_compat.Netcgi_types.cgi_argument
      method argument_value : ?default:string -> string -> string
      method arguments :
        (string * Netcgi1_compat.Netcgi_types.cgi_argument) list
      method delete_argument : ?fin:bool -> string -> unit
      method environment : Netcgi1_compat.Netcgi_env.cgi_environment
      method finalize : unit -> unit
      method initial_argument :
        string -> Netcgi1_compat.Netcgi_types.cgi_argument
      method initial_argument_value : ?default:string -> string -> string
      method initial_arguments :
        (string * Netcgi1_compat.Netcgi_types.cgi_argument) list
      method initial_multiple_argument :
        string -> Netcgi1_compat.Netcgi_types.cgi_argument list
      method multiple_argument :
        string -> Netcgi1_compat.Netcgi_types.cgi_argument list
      method output : Netchannels.trans_out_obj_channel
      method request_method : Netcgi1_compat.Netcgi_types.request_method
      method set_arguments :
        ?fin:bool -> Netcgi1_compat.Netcgi_types.cgi_argument list -> unit
      method set_header :
        ?status:Netcgi1_compat.Netcgi_types.status ->
        ?content_type:string ->
        ?cache:Netcgi1_compat.Netcgi_types.cache_control ->
        ?filename:string ->
        ?language:string ->
        ?script_type:string ->
        ?style_type:string ->
        ?set_cookie:Netcgi1_compat.Netcgi_types.cgi_cookie list ->
        ?fields:(string * string list) list -> unit -> unit
      method set_redirection_header : string -> unit
      method update_argument :
        ?fin:bool -> Netcgi1_compat.Netcgi_types.cgi_argument -> unit
      method update_multiple_argument :
        ?fin:bool -> Netcgi1_compat.Netcgi_types.cgi_argument list -> unit
      method url :
        ?protocol:Netcgi1_compat.Netcgi_env.protocol ->
        ?with_authority:Netcgi1_compat.Netcgi_types.other_url_spec ->
        ?with_script_name:Netcgi1_compat.Netcgi_types.other_url_spec ->
        ?with_path_info:Netcgi1_compat.Netcgi_types.other_url_spec ->
        ?with_query_string:Netcgi1_compat.Netcgi_types.query_string_spec ->
        unit -> string
    end
  val to_compat_activation :
    Netcgi.cgi -> Netcgi1_compat.Netcgi_types.cgi_activation
  val of_compat_activation :
    Netcgi1_compat.Netcgi_types.cgi_activation -> Netcgi.cgi
end
ocamlnet-4.1.2/doc/html-main/type_Netaddress.mailbox.html0000644000175000017500000004164012731530352022062 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaddress.mailbox ?name:string ->
string list ->
Netaddress.addr_spec ->
object
  method name : string
  method route : string list
  method spec : Netaddress.addr_spec
end
ocamlnet-4.1.2/doc/html-main/Netencoding.Html.html0000644000175000017500000006232412731530352020435 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Html

Module Netencoding.Html

module Html: sig .. end


Encodes characters that need protection by converting them to entity references. E.g. "<" is converted to "&lt;". As the entities may be named, there is a dependency on the character set.

Encodes characters that need protection by converting them to entity references. E.g. "<" is converted to "&lt;". As the entities may be named, there is a dependency on the character set.

Legacy functions:
val encode_from_latin1 : string -> string
val decode_to_latin1 : string -> string

These functions have a more general interface and should be preferred in new programs.
val unsafe_chars_html4 : string
The string contains '<', '>', '"', '&' and the control characters 0-8, 11-12, 14-31, 127.
val encode : in_enc:Netconversion.encoding ->
?out_enc:Netconversion.encoding ->
?prefer_name:bool -> ?unsafe_chars:string -> unit -> string -> string
The input string that is encoded as in_enc is recoded to out_enc, and the following characters are encoded as HTML entity (&name; or &#num;):
  • The ASCII characters contained in unsafe_chars
  • The characters that cannot be represented in out_enc. By default (out_enc=`Enc_usascii), only ASCII characters can be represented, and thus all code points >= 128 are encoded as HTML entities. If you pass out_enc=`Enc_utf8, all characters can be represented.
For example, the string "(a<b) & (c>d)" is encoded as "(a&lt;b) &amp; (c&gt;d)".

It is required that out_enc is an ASCII-compatible encoding.

The option prefer_name selects whether named entities (e.g. &lt;) or numeric entities (e.g. &#60;) are prefered.

The efficiency of the function can be improved when the same encoding is applied to several strings. Create a specialized encoding function by passing all arguments up to the unit argument, and apply this function several times. For example:

     let my_enc = encode ~in_enc:`Enc_utf8 () in
     let s1' = my_enc s1 in
     let s2' = my_enc s2 in ...
 

val encode_tstring : in_enc:Netconversion.encoding ->
out_kind:'s Netstring_tstring.tstring_kind ->
?out_enc:Netconversion.encoding ->
?prefer_name:bool ->
?unsafe_chars:string -> unit -> Netsys_types.tstring -> 's
This version takes a tstring argument, and returns the string type chosen by the out_kind arg.
val encode_poly : in_enc:Netconversion.encoding ->
in_ops:'s Netstring_tstring.tstring_ops ->
out_kind:'t Netstring_tstring.tstring_kind ->
?out_enc:Netconversion.encoding ->
?prefer_name:bool -> ?unsafe_chars:string -> unit -> 's -> 't
Fully polymorphic version
type entity_set = [ `Empty | `Html | `Xml ] 
val decode : in_enc:Netconversion.encoding ->
out_enc:Netconversion.encoding ->
?lookup:(string -> string) ->
?subst:(int -> string) ->
?entity_base:entity_set -> unit -> string -> string
The input string is recoded from in_enc to out_enc, and HTML entities (&name; or &#num;) are resolved. The input encoding in_enc must be ASCII-compatible.

By default, the function knows all entities defined for HTML 4 (this can be changed using entity_base, see below). If other entities occur, the function lookup is called and the name of the entity is passed as input string to the function. It is expected that lookup returns the value of the entity, and that this value is already encoded as out_enc. By default, lookup raises a Failure exception.

If a character cannot be represented in the output encoding, the function subst is called. subst must return a substitute string for the character. By default, subst raises a Failure exception.

The option entity_base determines which set of entities are considered as the known entities that can be decoded without help by the lookup function: `Html selects all entities defined for HTML 4, `Xml selects only &lt;, &gt;, &amp;, &quot;, and &apos;, and `Empty selects the empty set (i.e. lookup is always called).

val decode_tstring : in_enc:Netconversion.encoding ->
out_kind:'s Netstring_tstring.tstring_kind ->
out_enc:Netconversion.encoding ->
?lookup:(string -> string) ->
?subst:(int -> string) ->
?entity_base:entity_set ->
unit -> Netsys_types.tstring -> 's
This version takes a tstring argument, and returns the string type chosen by the out_kind arg.
val decode_poly : in_enc:Netconversion.encoding ->
in_ops:'s Netstring_tstring.tstring_ops ->
out_kind:'t Netstring_tstring.tstring_kind ->
out_enc:Netconversion.encoding ->
?lookup:(string -> string) ->
?subst:(int -> string) ->
?entity_base:entity_set -> unit -> 's -> 't
Fully polymorphic version
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.put.html0000644000175000017500000004076012731530352022131 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.put string -> string -> Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Netplex_sharedvar.Make_var_type.html0000644000175000017500000004557212731530352023546 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sharedvar.Make_var_type

Functor Netplex_sharedvar.Make_var_type

module Make_var_type: 
functor (T : Netplex_cenv.TYPE) -> Netplex_cenv.VAR_TYPE with type t = T.t
Creates a module with get and set functions to access variables of type T.t. Call it like

         module Foo_var = 
           Make_var_type(struct type t = foo end)
      

and use Foo_var.get and Foo_var.set to access the shared variables of type foo. These functions can also raise the exception Sharedvar_not_found (unlike the primitive accessors above).

The variable must have been created with enc:true, e.g.

          let ok = create_var ~enc:true "name"
      

Parameters:
T : Netplex_cenv.TYPE

type t 
val get : string -> t
val set : string -> t -> unit
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.prioritizer_t.html0000644000175000017500000004166212731530352024704 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.prioritizer_t object
  method prioritized :
    (Unixqueue.event_system -> 'Uq_engines_compat.engine) ->
    int -> 'Uq_engines_compat.engine
end
ocamlnet-4.1.2/doc/html-main/Netplex_mt.html0000644000175000017500000004313512731530352017413 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mt

Module Netplex_mt

module Netplex_mt: sig .. end
Multi-threading provider

class mt : unit -> Netplex_types.parallelizer
Uses Thread.create to create new threads
val mt : unit -> Netplex_types.parallelizer
Uses Thread.create to create new threads
ocamlnet-4.1.2/doc/html-main/type_Unixqueue.Debug.html0000644000175000017500000004157512731530352021360 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.Debug sig
  val enable : bool Pervasives.ref
  val set_debug_mode : bool -> unit
  val set_debug_target : Equeue.Debug.debug_target -> unit
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.post_call-c.html0000644000175000017500000004217012731530352022455 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.post_call

Class Nethttp_client.post_call

class post_call : http_call

ocamlnet-4.1.2/doc/html-main/type_Netxdr_mstring.mstring_factory.html0000644000175000017500000004314512731530352024556 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netxdr_mstring.mstring_factory object
  method create_from_bytes :
    Bytes.t -> int -> int -> bool -> Netxdr_mstring.mstring
  method create_from_memory :
    Netsys_mem.memory -> int -> int -> bool -> Netxdr_mstring.mstring
  method create_from_string :
    string -> int -> int -> bool -> Netxdr_mstring.mstring
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_cgi.html0000644000175000017500000004237612731530352020376 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_cgi sig
  val run :
    ?config:Netcgi.config ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?exn_handler:Netcgi.exn_handler -> (Netcgi.cgi -> unit) -> unit
  val is_cgi : unit -> bool
end
ocamlnet-4.1.2/doc/html-main/Netmech_gs2_sasl.html0000644000175000017500000004413312731530352020453 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_gs2_sasl

Module Netmech_gs2_sasl

module Netmech_gs2_sasl: sig .. end
The GS2 bridge for using GSSAPI mechanisms as SASL mechanisms

module type PROFILE = sig .. end
module GS2: 
This is an adapter turning any GSSAPI mechanism into a SASL mechanism.
ocamlnet-4.1.2/doc/html-main/type_Netglob.of_stream_fs.html0000644000175000017500000004077712731530352022406 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.of_stream_fs #Netfs.stream_fs -> Netglob.glob_fsysocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.SCRAM_SHA1.html0000644000175000017500000010730012731530352022501 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM_SHA1

Module Netmech_scram_sasl.SCRAM_SHA1

module SCRAM_SHA1: Netsys_sasl_types.SASL_MECHANISM 
SCRAM with SHA1 profile

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/Uq_engines.serializer-c.html0000644000175000017500000004242612731530352021763 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.serializer

Class Uq_engines.serializer

class ['a] serializer : Unixqueue.event_system -> ['a] serializer_t
Creates a serializer

ocamlnet-4.1.2/doc/html-main/type_Netplex_types.netplex_config.html0000644000175000017500000004236212731530352024204 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.netplex_config object
  method controller_config : Netplex_types.controller_config
  method ptype : Netplex_types.parallelization_type
  method services :
    (Netplex_types.socket_service_config *
     (Netplex_types.address * Netplex_types.processor_factory) *
     (Netplex_types.address * Netplex_types.workload_manager_factory))
    list
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_common.rw_cgi_argument.html0000644000175000017500000004363412731530352024275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.rw_cgi_argument object
  method charset : string
  method content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method filename : string option
  method finalize : unit -> unit
  method name : string
  method open_value_rd : unit -> Netchannels.in_obj_channel
  method open_value_wr : unit -> Netchannels.out_obj_channel
  method representation : representation
  method ro : bool
  method set_value : string -> unit
  method store : store
  method value : string
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_encap.html0000644000175000017500000004467212731530352021131 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_encap sig
  exception Type_mismatch
  type encap
  module type TYPE = sig type t end
  module type ENCAP =
    sig
      type t
      val wrap : Netplex_encap.ENCAP.t -> Netplex_encap.encap
      val unwrap : Netplex_encap.encap -> Netplex_encap.ENCAP.t
    end
  module Make_encap :
    functor (T : TYPE->
      sig type t = T.t val wrap : t -> encap val unwrap : encap -> t end
end
ocamlnet-4.1.2/doc/html-main/type_Netftp_data_endpoint.ftp_data_receiver.html0000644000175000017500000004525012731530352026133 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.ftp_data_receiver ?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option * string option ->
?protector:Netftp_data_endpoint.ftp_protector ->
esys:Unixqueue.event_system ->
mode:Netftp_data_endpoint.transmission_mode ->
local_receiver:Netftp_data_endpoint.local_receiver ->
descr:Unix.file_descr ->
timeout:float ->
timeout_exn:exn ->
unit ->
object
  method abort : unit -> unit
  method descr : Unix.file_descr
  method descr_state : descr_state
  method event_system : Unixqueue.event_system
  method local_receiver : Netftp_data_endpoint.local_receiver
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    (unit Uq_engines.engine -> bool) -> unit
  method state : unit Uq_engines.engine_state
end
ocamlnet-4.1.2/doc/html-main/Netmech_digest_http.Digest_mutual.html0000644000175000017500000007400312731530352024060 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http.Digest_mutual

Module Netmech_digest_http.Digest_mutual

module Digest_mutual: Nethttp.HTTP_CLIENT_MECHANISM 
This is the standard HTTP digest authentication mechanism (see RFCs 2069, 2617, 7616). This version also authenticates the server by checking the Authentication-Info header which must include the correct rspauth parameter. This parameter proves that the server actually knew the password.

Note that mutual authentication does generally not prevent that request data is sent to the server before the authentication succeeds. This includes the header and also the request body (for POST and PUT methods). Because of this it is recommended to ensure that requests not carrying any sensitive data precede those requests that need protection.

You need to explicitly plug in this module into the HTTP client in order to enable it. See Netmech_digest_http.Digest for details.


val mechanism_name : string
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
val restart_supported : bool
Whether the mechanism supports quick restarts (re-authentication)
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

The password is encoded in UTF-8. However, note that not all protocols are able to transmit all of UTF-8. If a non-transmittable character is found, the authentication will fail.

The password can have parameters:

  • "realm": the password is only applicable to this realm. The realm parameter should only occur once.
  • "domain-uri": the password is only applicable to this URI space. The URI must include the protocol scheme, the host name, and "/" as path. The port number is optional. Example: "http://localhost/". The domain-uri parameter can occur several times.

val client_match : params:(string * string * bool) list ->
Nethttp.Header.auth_challenge -> Nethttp.match_result
Checks whether this mechanism can accept the initial authentication challenge (i.e. the first challenge sent from the server to the client. The params are as for create_client_session. On success, returns `Accept(realm,id_opt). On failure, returns `Reject. This function usually does not raise exceptions.

If the mechanism does not support the notion of realms, a dummy realm should be returned.

The id_opt is the session ID (if supported). Session IDs can be used to bind reauthentications to the original session.

The challenge is from a www-authenticate or a proxy-authenticate header.

There is also the result `Reroute(realm, trans_id), meaning that the request would be acceptable if it came over the transport identified by trans_id. `Accept_reroute is the combination of accepting and rerouting, i.e. the auth protocol can start, but the second request should go over the other transport. Both `Reroute and `Accept_reroute are only allowed for initial challenges.

type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user. The credentials are creds.

user must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

Available parameters:

  • "realm"
  • "id" (if client_match returns a session ID)
  • "trans_id": the Nethttp_client.transport_layer_id of the current HTTP request
  • "conn_id": an identifier for the TCP connection
  • "https": is set to "true" if the current connection is TLS-secured
  • "target-host": the hostname from the HTTP request
  • "target-uri": the URL from the HTTP request

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : params:(string * string * bool) list ->
client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK. After the restart the session will be in state `Emit.

The params are the same as for create_client_session, but updated where needed.

val client_process_challenge : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
Nethttp.Header.auth_challenge -> client_session
client_process_challenge cs method uri header challenge:

Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.

method is the request method. uri is the request URI

val client_emit_response : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
client_session *
Nethttp.Header.auth_credentials * (string * string) list
let (creds,new_headers) = client_emit_response cs method uri header:

Emit a new response as a pair (creds,new_headers). The state must be `Emit. The creds either go into the authorization or proxy-authorization header. The new_headers are additional headers to modify.

val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_domain : client_session -> string list
After successful authentication, this function may return the URIs defining the authentication space.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. Commonly supported keys:
  • "realm"
  • "domain-uri"

val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Returns the GSSAPI props if available, or raise Not_found
ocamlnet-4.1.2/doc/html-main/type_Netcgi_porting.html0000644000175000017500000004061712731530352021312 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_porting sig  endocamlnet-4.1.2/doc/html-main/Netasn1.Type_name.html0000644000175000017500000005653512731530352020535 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netasn1.Type_name

Module Netasn1.Type_name

module Type_name: sig .. end

type type_name = 
| Bool
| Integer
| Enum
| Real
| Bitstring
| Octetstring
| Null
| Seq
| Set
| OID
| ROID
| ObjectDescriptor
| External
| Embedded_PDV
| NumericString
| PrintableString
| TeletexString
| VideotexString
| VisibleString
| IA5String
| GraphicString
| GeneralString
| UniversalString
| BMPString
| UTF8String
| CharString
| UTCTime
| GeneralizedTime
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.error_response_params-c.html0000644000175000017500000004341212731530352025141 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.error_response_params

Class type Nethttpd_types.error_response_params

class type error_response_params = object .. end
Inherits
method response_status_code : int
The HTTP status code to response
method error_message : string
The error message explaining the detail that went wrong
ocamlnet-4.1.2/doc/html-main/type_Netplex_cenv.FUN_TYPE.html0000644000175000017500000004075412731530352022263 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.FUN_TYPE sig type s type r endocamlnet-4.1.2/doc/html-main/type_Uq_transfer.async_out_channel_engine.html0000644000175000017500000004377012731530352025653 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.async_out_channel_engine object
  method abort : unit -> unit
  method can_output : bool
  method close_out : unit -> unit
  method event_system : Unixqueue.event_system
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method pos_out : int
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    (unit Uq_engines.engine -> bool) -> unit
  method state : unit Uq_engines.engine_state
end
ocamlnet-4.1.2/doc/html-main/Netgss_bindings.html0000644000175000017500000010365112731530352020414 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgss_bindings

Module Netgss_bindings

module Netgss_bindings: sig .. end
Bindings of a C library

type gss_buffer_t 
type gss_OID 
type gss_OID_set 
type gss_cred_id_t 
type gss_ctx_id_t 
type gss_name_t 
type gss_channel_bindings_t 
type gss_cred_usage_t = [ `Accept | `Both | `Initiate ] 
type flags_flag = [ `Anon_flag
| `Conf_flag
| `Deleg_flag
| `Integ_flag
| `Mutual_flag
| `Prot_ready_flag
| `Replay_flag
| `Sequence_flag
| `Trans_flag ]
type flags = flags_flag list 
type gss_qop_t = [ `Qop_default ] 
type status_type_t = [ `Gss_code | `Mech_code ] 
val gss_accept_sec_context : gss_ctx_id_t ->
gss_cred_id_t ->
gss_buffer_t ->
gss_channel_bindings_t ->
int32 * int32 * gss_ctx_id_t * gss_name_t *
gss_OID * gss_buffer_t *
flags * int32 * gss_cred_id_t
val gss_acquire_cred : gss_name_t ->
int32 ->
gss_OID_set ->
gss_cred_usage_t ->
int32 * int32 * gss_cred_id_t * gss_OID_set *
int32
val gss_init_sec_context : gss_cred_id_t ->
gss_ctx_id_t ->
gss_name_t ->
gss_OID ->
flags ->
int32 ->
gss_channel_bindings_t ->
gss_buffer_t ->
int32 * int32 * gss_ctx_id_t * gss_OID *
gss_buffer_t * flags * int32
val gss_process_context_token : gss_ctx_id_t -> gss_buffer_t -> int32 * int32
val gss_context_time : gss_ctx_id_t -> int32 * int32 * int32
val gss_get_mic : gss_ctx_id_t ->
int32 ->
gss_buffer_t -> int32 * int32 * gss_buffer_t
val gss_verify_mic : gss_ctx_id_t ->
gss_buffer_t ->
gss_buffer_t -> int32 * int32 * int32
val gss_wrap : gss_ctx_id_t ->
bool ->
int32 ->
gss_buffer_t ->
int32 * int32 * bool * gss_buffer_t
val gss_unwrap : gss_ctx_id_t ->
gss_buffer_t ->
int32 * int32 * gss_buffer_t * bool * int32
val gss_display_status : int32 ->
status_type_t ->
gss_OID ->
int32 -> int32 * int32 * int32 * gss_buffer_t
val gss_indicate_mechs : unit -> int32 * int32 * gss_OID_set
val gss_compare_name : gss_name_t ->
gss_name_t -> int32 * int32 * bool
val gss_display_name : gss_name_t ->
int32 * int32 * gss_buffer_t * gss_OID
val gss_import_name : gss_buffer_t ->
gss_OID -> int32 * int32 * gss_name_t
val gss_inquire_cred : gss_cred_id_t ->
int32 * int32 * gss_name_t * int32 *
gss_cred_usage_t * gss_OID_set
val gss_inquire_context : gss_ctx_id_t ->
int32 * int32 * gss_name_t * gss_name_t *
int32 * gss_OID * flags * bool * bool
val gss_wrap_size_limit : gss_ctx_id_t ->
bool -> int32 -> int32 -> int32 * int32 * int32
val gss_add_cred : gss_cred_id_t ->
gss_name_t ->
gss_OID ->
gss_cred_usage_t ->
int32 ->
int32 ->
int32 * int32 * gss_cred_id_t * gss_OID_set *
int32 * int32
val gss_inquire_cred_by_mech : gss_cred_id_t ->
gss_OID ->
int32 * int32 * gss_name_t * int32 * int32 *
gss_cred_usage_t
val gss_export_sec_context : gss_ctx_id_t -> int32 * int32 * gss_buffer_t
val gss_import_sec_context : gss_buffer_t -> int32 * int32 * gss_ctx_id_t
val gss_inquire_names_for_mech : gss_OID -> int32 * int32 * gss_OID_set
val gss_inquire_mechs_for_name : gss_name_t -> int32 * int32 * gss_OID_set
val gss_export_name : gss_name_t -> int32 * int32 * gss_buffer_t
val gss_duplicate_name : gss_name_t -> int32 * int32 * gss_name_t
val gss_canonicalize_name : gss_name_t ->
gss_OID -> int32 * int32 * gss_name_t
val gss_delete_sec_context : gss_ctx_id_t -> int32 * int32
exception Null_pointer
type memory = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t 
val buffer_of_string : string -> int -> int -> gss_buffer_t
val buffer_of_bytes : Bytes.t -> int -> int -> gss_buffer_t
val buffer_of_memory : memory -> gss_buffer_t
val string_of_buffer : gss_buffer_t -> string
val bytes_of_buffer : gss_buffer_t -> Bytes.t
val memory_of_buffer : gss_buffer_t -> memory
val release_buffer : gss_buffer_t -> unit
val oid_of_der : string -> gss_OID
val der_of_oid : gss_OID -> string
val array_of_oid_set : gss_OID_set -> gss_OID array
val oid_set_of_array : gss_OID array -> gss_OID_set
val map_cb : int ->
string -> int -> string -> string -> gss_channel_bindings_t
val no_channel_bindings : unit -> gss_channel_bindings_t
val no_context : unit -> gss_ctx_id_t
val is_no_context : gss_ctx_id_t -> bool
val no_credential : unit -> gss_cred_id_t
val is_no_credential : gss_cred_id_t -> bool
val no_name : unit -> gss_name_t
val is_no_name : gss_name_t -> bool
val no_oid : unit -> gss_OID
val no_oid_set : unit -> gss_OID_set
val gss_indefinite : unit -> int32
ocamlnet-4.1.2/doc/html-main/Uq_transfer.input_async_descr-c.html0000644000175000017500000004271612731530352023524 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.input_async_descr

Class Uq_transfer.input_async_descr

class input_async_descr : src:Unix.file_descr -> ?buffer_size:int -> ?close_src:bool -> Unixqueue.event_system -> async_in_channel_engine
The corresponding class for asynchronous input channels.

TODO: This class cannot yet cope with Win32 named piped.


ocamlnet-4.1.2/doc/html-main/type_Netldap.html0000644000175000017500000014007312731530352017723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netldap sig
  type result_code =
      [ `AdminLimitExceeded
      | `AffectsMultipleDSAs
      | `AliasDereferencingProblem
      | `AliasProblem
      | `AttributeOrValueExists
      | `AuthMethodNotSupported
      | `Busy
      | `CompareFalse
      | `CompareTrue
      | `ConfidentialityRequired
      | `ConstraintViolation
      | `EntryAlreadyExists
      | `InappropriateAuthentication
      | `InappropriateMatching
      | `InsufficientAccessRights
      | `InvalidAttributeSyntax
      | `InvalidCredentials
      | `InvalidDNSyntax
      | `LoopDetect
      | `NamingViolation
      | `NoSuchAttribute
      | `NoSuchObject
      | `NotAllowedOnNonLeaf
      | `NotAllowedOnRDN
      | `ObjectClassModsProhibited
      | `ObjectClassViolation
      | `OperationsError
      | `Other
      | `ProtocolError
      | `Referral
      | `SaslBindInProgress
      | `SizeLimitExceeded
      | `StrongAuthRequired
      | `Success
      | `TimeLimitExceeded
      | `Unavailable
      | `UnavailableCriticalExtension
      | `UndefinedAttributeType
      | `Unknown_code of int
      | `UnwillingToPerform ]
  exception Timeout
  exception LDAP_error of Netldap.result_code * string
  exception Auth_error of string
  type tls_mode =
      [ `Disabled | `Immediate | `StartTLS | `StartTLS_if_possible ]
  class type ldap_server =
    object
      method ldap_endpoint : Netsockaddr.socksymbol
      method ldap_peer_name : string option
      method ldap_timeout : float
      method ldap_tls_config : (module Netsys_crypto_types.TLS_CONFIG) option
      method ldap_tls_mode : Netldap.tls_mode
    end
  val ldap_server :
    ?timeout:float ->
    ?peer_name:string ->
    ?tls_config:(module Netsys_crypto_types.TLS_CONFIG->
    ?tls_mode:Netldap.tls_mode ->
    Netsockaddr.socksymbol -> Netldap.ldap_server
  val ldap_server_of_url :
    ?timeout:float ->
    ?tls_config:(module Netsys_crypto_types.TLS_CONFIG->
    ?tls_mode:Netldap.tls_mode -> Neturl.url -> Netldap.ldap_server
  type bind_creds
  val anon_bind_creds : Netldap.bind_creds
  val simple_bind_creds : dn:string -> pw:string -> Netldap.bind_creds
  val sasl_bind_creds :
    dn:string ->
    user:string ->
    authz:string ->
    creds:(string * string * (string * string) list) list ->
    params:(string * string * bool) list ->
    (module Netsys_sasl_types.SASL_MECHANISM-> Netldap.bind_creds
  type ldap_connection
  val connect_e :
    ?proxy:#Uq_engines.client_endpoint_connector ->
    Netldap.ldap_server ->
    Unixqueue.event_system -> Netldap.ldap_connection Uq_engines.engine
  val connect :
    ?proxy:#Uq_engines.client_endpoint_connector ->
    Netldap.ldap_server -> Netldap.ldap_connection
  val close_e : Netldap.ldap_connection -> unit Uq_engines.engine
  val close : Netldap.ldap_connection -> unit
  val abort : Netldap.ldap_connection -> unit
  val conn_bind_e :
    Netldap.ldap_connection -> Netldap.bind_creds -> unit Uq_engines.engine
  val conn_bind : Netldap.ldap_connection -> Netldap.bind_creds -> unit
  val tls_session_props :
    Netldap.ldap_connection -> Nettls_support.tls_session_props option
  class type ['a] ldap_result =
    object
      method code : Netldap.result_code
      method diag_msg : string
      method matched_dn : string
      method partial_value : 'a
      method referral : string list
      method value : 'a
    end
  exception Notification of string Netldap.ldap_result
  type scope = [ `Base | `One | `Sub ]
  type deref_aliases =
      [ `Always | `Finding_base_obj | `In_searching | `Never ]
  type filter =
      [ `And of Netldap.filter list
      | `Approx_match of string * string
      | `Equality_match of string * string
      | `Extensible_match of string option * string option * string * bool
      | `Greater_or_equal of string * string
      | `Less_or_equal of string * string
      | `Not of Netldap.filter
      | `Or of Netldap.filter list
      | `Present of string
      | `Substrings of string * string option * string list * string option ]
  type search_result =
      [ `Entry of string * (string * string list) list
      | `Reference of string list ]
  val search_e :
    Netldap.ldap_connection ->
    base:string ->
    scope:Netldap.scope ->
    deref_aliases:Netldap.deref_aliases ->
    size_limit:int ->
    time_limit:int ->
    types_only:bool ->
    filter:Netldap.filter ->
    attributes:string list ->
    unit -> Netldap.search_result list Netldap.ldap_result Uq_engines.engine
  val search :
    Netldap.ldap_connection ->
    base:string ->
    scope:Netldap.scope ->
    deref_aliases:Netldap.deref_aliases ->
    size_limit:int ->
    time_limit:int ->
    types_only:bool ->
    filter:Netldap.filter ->
    attributes:string list ->
    unit -> Netldap.search_result list Netldap.ldap_result
  val compare_e :
    Netldap.ldap_connection ->
    dn:string ->
    attr:string ->
    value:string -> unit -> bool Netldap.ldap_result Uq_engines.engine
  val compare :
    Netldap.ldap_connection ->
    dn:string ->
    attr:string -> value:string -> unit -> bool Netldap.ldap_result
  val add_e :
    Netldap.ldap_connection ->
    dn:string ->
    attributes:(string * string list) list ->
    unit -> unit Netldap.ldap_result Uq_engines.engine
  val add :
    Netldap.ldap_connection ->
    dn:string ->
    attributes:(string * string list) list ->
    unit -> unit Netldap.ldap_result
  val delete_e :
    Netldap.ldap_connection ->
    dn:string -> unit -> unit Netldap.ldap_result Uq_engines.engine
  val delete :
    Netldap.ldap_connection -> dn:string -> unit -> unit Netldap.ldap_result
  type operation = [ `Add | `Delete | `Replace ]
  val modify_e :
    Netldap.ldap_connection ->
    dn:string ->
    changes:(Netldap.operation * (string * string list)) list ->
    unit -> unit Netldap.ldap_result Uq_engines.engine
  val modify :
    Netldap.ldap_connection ->
    dn:string ->
    changes:(Netldap.operation * (string * string list)) list ->
    unit -> unit Netldap.ldap_result
  val modify_dn_e :
    Netldap.ldap_connection ->
    dn:string ->
    new_rdn:string ->
    delete_old_rdn:bool ->
    new_superior:string option ->
    unit -> unit Netldap.ldap_result Uq_engines.engine
  val modify_dn :
    Netldap.ldap_connection ->
    dn:string ->
    new_rdn:string ->
    delete_old_rdn:bool ->
    new_superior:string option -> unit -> unit Netldap.ldap_result
  val modify_password_e :
    Netldap.ldap_connection ->
    uid:string option ->
    old_pw:string option ->
    new_pw:string option ->
    unit -> string option Netldap.ldap_result Uq_engines.engine
  val modify_password :
    Netldap.ldap_connection ->
    uid:string option ->
    old_pw:string option ->
    new_pw:string option -> unit -> string option Netldap.ldap_result
  val test_bind_e :
    ?proxy:#Uq_engines.client_endpoint_connector ->
    Netldap.ldap_server ->
    Netldap.bind_creds -> Unixqueue.event_system -> bool Uq_engines.engine
  val test_bind :
    ?proxy:#Uq_engines.client_endpoint_connector ->
    Netldap.ldap_server -> Netldap.bind_creds -> bool
  val retr_password_e :
    dn:string ->
    Netldap.ldap_server ->
    Netldap.bind_creds ->
    Unixqueue.event_system ->
    (string * string * (string * string) list) list Uq_engines.engine
  val retr_password :
    dn:string ->
    Netldap.ldap_server ->
    Netldap.bind_creds -> (string * string * (string * string) list) list
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.http_service_generator.html0000644000175000017500000004116412731530352026117 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.http_service_generator object
  method generate_response : Nethttpd_types.extended_environment -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Uq_server.server_endpoint_acceptor.html0000644000175000017500000004215112731530352025372 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_server.server_endpoint_acceptor object
  method accept :
    unit -> (Unix.file_descr * Uq_engines.inetspec option) Uq_engines.engine
  method multiple_connections : bool
  method server_address : Uq_engines.connect_address
  method shut_down : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netbuffer.html0000644000175000017500000010310112731530352020243 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netbuffer sig
  type t
  val create : int -> Netbuffer.t
  val contents : Netbuffer.t -> string
  val to_bytes : Netbuffer.t -> Bytes.t
  val to_tstring_poly :
    Netbuffer.t -> 'Netstring_tstring.tstring_kind -> 's
  val to_tstring :
    Netbuffer.t -> 'Netstring_tstring.tstring_kind -> Netsys_types.tstring
  val length : Netbuffer.t -> int
  val get : Netbuffer.t -> int -> char
  val nth : Netbuffer.t -> int -> char
  val sub : Netbuffer.t -> int -> int -> string
  val sub_bytes : Netbuffer.t -> int -> int -> Bytes.t
  val blit_to_bytes : Netbuffer.t -> int -> Bytes.t -> int -> int -> unit
  val blit_to_string : Netbuffer.t -> int -> Bytes.t -> int -> int -> unit
  val blit : Netbuffer.t -> int -> Bytes.t -> int -> int -> unit
  val blit_to_memory :
    Netbuffer.t -> int -> Netsys_mem.memory -> int -> int -> unit
  val blit_to_tbuffer :
    Netbuffer.t -> int -> Netsys_types.tbuffer -> int -> int -> unit
  val add_string : Netbuffer.t -> string -> unit
  val add_bytes : Netbuffer.t -> Bytes.t -> unit
  val add_tstring : Netbuffer.t -> Netsys_types.tstring -> unit
  val add_tstring_poly :
    Netbuffer.t -> 'Netstring_tstring.tstring_ops -> '-> unit
  val add_substring : Netbuffer.t -> string -> int -> int -> unit
  val add_subbytes : Netbuffer.t -> Bytes.t -> int -> int -> unit
  val add_subtstring :
    Netbuffer.t -> Netsys_types.tstring -> int -> int -> unit
  val add_sub_string : Netbuffer.t -> string -> int -> int -> unit
  val add_submemory : Netbuffer.t -> Netsys_mem.memory -> int -> int -> unit
  val add_sub_memory : Netbuffer.t -> Netsys_mem.memory -> int -> int -> unit
  val add_subtstring_poly :
    Netbuffer.t ->
    'Netstring_tstring.tstring_ops -> '-> int -> int -> unit
  val add_char : Netbuffer.t -> char -> unit
  val add_char_2 : Netbuffer.t -> char -> char -> unit
  val add_char_4 : Netbuffer.t -> char -> char -> char -> char -> unit
  val add_inplace :
    ?len:int -> Netbuffer.t -> (Bytes.t -> int -> int -> int) -> int
  val add_buffer : Netbuffer.t -> Netbuffer.t -> unit
  val area_for_additions : ?len:int -> Netbuffer.t -> Bytes.t * int * int
  val advance : Netbuffer.t -> int -> unit
  val insert_string : Netbuffer.t -> int -> string -> unit
  val insert_substring : Netbuffer.t -> int -> string -> int -> int -> unit
  val insert_sub_string : Netbuffer.t -> int -> string -> int -> int -> unit
  val insert_subbytes : Netbuffer.t -> int -> Bytes.t -> int -> int -> unit
  val insert_subtstring :
    Netbuffer.t -> int -> Netsys_types.tstring -> int -> int -> unit
  val insert_submemory :
    Netbuffer.t -> int -> Netsys_types.memory -> int -> int -> unit
  val insert_char : Netbuffer.t -> int -> char -> unit
  val set : Netbuffer.t -> int -> char -> unit
  val put_string : Netbuffer.t -> int -> string -> unit
  val blit_from_string : string -> int -> Netbuffer.t -> int -> int -> unit
  val blit_from_bytes : Bytes.t -> int -> Netbuffer.t -> int -> int -> unit
  val blit_from_memory :
    Netsys_types.memory -> int -> Netbuffer.t -> int -> int -> unit
  val blit_from_tstring :
    Netsys_types.tstring -> int -> Netbuffer.t -> int -> int -> unit
  val delete : Netbuffer.t -> int -> int -> unit
  val clear : Netbuffer.t -> unit
  val reset : Netbuffer.t -> unit
  val try_shrinking : Netbuffer.t -> unit
  val index_from : Netbuffer.t -> int -> char -> int
  val unsafe_buffer : Netbuffer.t -> Bytes.t
  val print_buffer : Netbuffer.t -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.qseq_engine.html0000644000175000017500000004153412731530352022730 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.qseq_engine '#Uq_engines.engine ->
('-> '#Uq_engines.engine) -> ['b] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.http_processor_config-c.html0000644000175000017500000005024212731530352025424 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_processor_config

Class type Nethttpd_reactor.http_processor_config

class type http_processor_config = object .. end
Inherits
method config_timeout_next_request : float
Timeout in seconds to wait for the next request after the previous one has been completely received. (-1) means no timeout.
method config_timeout : float
General timeout for network I/O (per I/O primitive). (-1) means no timeout.
method config_cgi : Netcgi.config
The CGI configuration to use in the Netcgi environment
method config_error_response : Nethttpd_types.error_response_params -> string
Get HTML error text for the HTTP status code. Must return a generic text for unknown codes.
method config_log_error : Nethttpd_types.request_info -> string -> unit
config_log_error info msg: Log the message msg. Information about the request can be taken from info. The request may only be partially available - be prepared that info methods raise Not_found.
method config_log_access : Nethttpd_types.full_info -> unit
Logs the access after the request/response cycle is complete.

The cgi_properties are from the environment. As there is no automatic way of recording the last, finally used version of this list, it is required that users call log_props of the extended environment whenever the properties are updated. This is done by all Nethttpd modules.

method config_tls_cert_props : bool
Whether to include certificate properties in the cgi environment. (If set to false, the certificates needs not to be parsed again.)
method config_tls_remote_user : bool
ocamlnet-4.1.2/doc/html-main/Nethttp.http_trailer-c.html0000644000175000017500000004211212731530352021634 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.http_trailer

Class type Nethttp.http_trailer

class type http_trailer = Netmime.mime_header

ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.serializer_t-c.html0000644000175000017500000004304012731530352023642 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.serializer_t

Class type Uq_engines_compat.serializer_t

class type ['a] serializer_t = object .. end

method serialized : (Unixqueue.event_system -> 'a engine) ->
'a engine
ocamlnet-4.1.2/doc/html-main/type_Nettls_gnutls.html0000644000175000017500000011152112731530352021175 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls sig
  module type GNUTLS_PROVIDER =
    sig
      type config
      type credentials
      type endpoint
      module Exc : Netsys_crypto_types.TLS_EXCEPTIONS
      val error_message : string -> string
      type dh_params =
          [ `Generate of int
          | `PKCS3_DER of string
          | `PKCS3_PEM_file of string ]
      val create_config :
        ?algorithms:string ->
        ?dh_params:dh_params ->
        ?verify:(endpoint -> bool -> bool -> bool) ->
        peer_auth:[ `None | `Optional | `Required ] ->
        credentials:credentials -> unit -> config
      type crt_list = [ `DER of string list | `PEM_file of string ]
      type crl_list = [ `DER of string list | `PEM_file of string ]
      type private_key =
          [ `DSA of string
          | `EC of string
          | `PEM_file of string
          | `PKCS8 of string
          | `PKCS8_encrypted of string
          | `RSA of string ]
      val create_x509_credentials :
        ?system_trust:bool ->
        ?trust:crt_list list ->
        ?revoke:crl_list list ->
        ?keys:(crt_list * private_key * string option) list ->
        unit -> credentials
      val create_endpoint :
        role:[ `Client | `Server ] ->
        recv:(Netsys_types.memory -> int) ->
        send:(Netsys_types.memory -> int -> int) ->
        peer_name:string option -> config -> endpoint
      val stash_endpoint : endpoint -> exn
      val restore_endpoint :
        recv:(Netsys_types.memory -> int) ->
        send:(Netsys_types.memory -> int -> int) -> exn -> endpoint
      val resume_client :
        recv:(Netsys_types.memory -> int) ->
        send:(Netsys_types.memory -> int -> int) ->
        peer_name:string option -> config -> string -> endpoint
      type state =
          [ `Accepting
          | `Data_r
          | `Data_rs
          | `Data_rw
          | `Data_w
          | `End
          | `Handshake
          | `Refusing
          | `Start
          | `Switching ]
      val get_state : endpoint -> state
      type raw_credentials = [ `Anonymous | `X509 of string ]
      val at_transport_eof : endpoint -> bool
      val hello : endpoint -> unit
      val bye : endpoint -> Unix.shutdown_command -> unit
      val verify : endpoint -> unit
      val get_config : endpoint -> config
      val get_endpoint_creds : endpoint -> raw_credentials
      val get_peer_creds : endpoint -> raw_credentials
      val get_peer_creds_list : endpoint -> raw_credentials list
      val switch : endpoint -> config -> unit
      val accept_switch : endpoint -> config -> unit
      val refuse_switch : endpoint -> unit
      val send : endpoint -> Netsys_types.memory -> int -> int
      val recv : endpoint -> Netsys_types.memory -> int
      val recv_will_not_block : endpoint -> bool
      val get_session_id : endpoint -> string
      val get_session_data : endpoint -> string
      val get_cipher_suite_type : endpoint -> string
      val get_cipher_algo : endpoint -> string
      val get_kx_algo : endpoint -> string
      val get_mac_algo : endpoint -> string
      val get_compression_algo : endpoint -> string
      val get_cert_type : endpoint -> string
      val get_protocol : endpoint -> string
      type server_name = [ `Domain of string ]
      val get_addressed_servers : endpoint -> server_name list
      val set_session_cache :
        store:(string -> string -> unit) ->
        remove:(string -> unit) ->
        retrieve:(string -> string) -> endpoint -> unit
      val implementation_name : string
      val implementation : unit -> exn
      val gnutls_session :
        endpoint -> Nettls_gnutls_bindings.gnutls_session_t
      val gnutls_credentials :
        credentials -> Nettls_gnutls_bindings.gnutls_credentials
    end
  module type GNUTLS_ENDPOINT =
    sig module TLS : GNUTLS_PROVIDER val endpoint : TLS.endpoint end
  val make_tls :
    (module Netsys_crypto_types.TLS_EXCEPTIONS->
    (module Nettls_gnutls.GNUTLS_PROVIDER)
  module GNUTLS : GNUTLS_PROVIDER
  module TLS : Netsys_crypto_types.TLS_PROVIDER
  val gnutls : (module Nettls_gnutls.GNUTLS_PROVIDER)
  val tls : (module Netsys_crypto_types.TLS_PROVIDER)
  val endpoint : GNUTLS.endpoint -> (module Nettls_gnutls.GNUTLS_ENDPOINT)
  val downcast :
    (module Netsys_crypto_types.TLS_PROVIDER->
    (module Nettls_gnutls.GNUTLS_PROVIDER)
  val downcast_endpoint :
    (module Netsys_crypto_types.TLS_ENDPOINT->
    (module Nettls_gnutls.GNUTLS_ENDPOINT)
  module Symmetric_crypto : Netsys_crypto_types.SYMMETRIC_CRYPTO
  module Digests : Netsys_crypto_types.DIGESTS
  val init : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/Netcgi.cgi_environment-c.html0000644000175000017500000007606312731530352022120 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.cgi_environment

Class type Netcgi.cgi_environment

class type cgi_environment = object .. end
The environment of a request consists of the information available besides the data sent by the user (as key-value pairs).

CGI properties

The following properties are standardised by CGI. The methods return "" (or None in the case of the port number) when the property is not available.

method cgi_gateway_interface : string
method cgi_server_name : string
method cgi_server_port : int option
method cgi_server_protocol : string
method cgi_server_software : string
method cgi_request_method : string
We recommend you to use the method Netcgi.cgi.request_method which is more type-safe and informative.
method cgi_script_name : string
method cgi_path_info : string
method cgi_path_translated : string
method cgi_auth_type : string
method cgi_remote_addr : string
method cgi_remote_host : string
method cgi_remote_user : string
method cgi_remote_ident : string
method cgi_query_string : string
This is the row query string. The Netcgi.cgi class gives you an easy access to the arguments through the #arg... methods.
method protocol : Nethttp.protocol
The server protocol in a decoded form. It can be either
  • `Http((major,minor),attributes) or
  • `Other.

method cgi_property : ?default:string -> string -> string
Returns a (possibly non-standard) CGI environment property. If the property is not set, Not_found is be raised unless the default argument is passed. The default argument determines the result of the function in this case.

The method takes the case-sensitive name and returns the value of the property. Usually, these properties have uppercase names.

For example, cgi_gateway_interface returns the same as

        cgi_property ~default:"" "GATEWAY_INTERFACE" 

You cannot access the fields coming from the HTTP header. Use the method input_header_field instead.

method cgi_properties : (string * string) list
Return all properties as an associative list.
method cgi_https : bool
A well-known extension is the HTTPS property. It indicates whether a secure connection is used (SSL/TLS). This method interprets this property and returns true if the connection is secure. This method fails if there is a HTTPS property with an unknown value.
method input_header : Netmime.mime_header
The whole HTTP header.
method input_header_field : ?default:string -> string -> string
#input_header_field ?default f returns the value of a field f of the HTTP request header. The field name f is case-insensitive; if the name is a compound name, the parts are separated by "-", e.g. "content-length". If there are several fields with the same name only the first field will be returned.
Raises Not_found if the field does not exist, unless the default argument is passed. The default argument is the result of the function in this case.
method multiple_input_header_field : string -> string list
Returns the values of all fields with the passed name of the request header.
method input_header_fields : (string * string) list
Returns the input header as (name,value) pairs. The names may consist of lowercase or uppercase letters.
method cookie : string -> Cookie.t
#cookie cn returns the cookie with name cn.
Raises Not_found if such a cookie does not exists.
method cookies : Cookie.t list
Returns the list of valid cookies found in the request header. Here "valid" means that the decode function does not raise an exception.
method user_agent : string
This is a convenience method that returns the "User-agent" field of the HTTP request header.
method input_content_length : int
Returns the "Content-length" request header field.
Raises Not_found if it is not set.
method input_content_type_string : string
Returns the "Content-type" request header field as a plain string or "" if it is not set.
method input_content_type : unit -> string * (string * Netmime_string.s_param) list
Returns the parsed "Content-type" request header field.
Raises Not_found if it is not set. See also Netmime_string.scan_mime_type_ep.
method output_header : Netmime.mime_header
The whole HTTP response header
method output_header_field : ?default:string -> string -> string
Returns the value of a field of the response header. If the field does not exist, Not_found will be raised unless the default argument is passed. The default argument determines the result of the function in this case.

If there are several fields with the same name only the first field will be returned.

The anonymous string is the name of the field. The name is case-insensitive, and it does not matter whether it consists of lowercase or uppercase letters. If the name is a compound name, the parts are separated by "-", e.g. "content-length".

method multiple_output_header_field : string -> string list
Returns the values of all fields with the passed name of the repsonse header.
method output_header_fields : (string * string) list
Returns the output header as (name,value) pairs. The names may consist of lowercase or uppercase letters.
method set_output_header_field : string -> string -> unit
Sets the value of a field of the response header. The previous value, if any, is overwritten. If there have been multiple values, all values will be removed and replaced by the single new value.
method set_multiple_output_header_field : string -> string list -> unit
Sets multiple values of a field of the response header. Any previous values are removed and replaced by the new values.
method set_output_header_fields : (string * string) list -> unit
Sets the complete response header at once.
method set_status : Nethttp.http_status -> unit
Sets the response status. This is by definition the same as setting the Status output header field.
method send_output_header : unit -> unit
This method will encode and send the output header to the output channel. Note that of the output_channel is `Transactionnal (as opposed to `Direct), no output will actually take place before you issue #commit_work() -- thus a #rollback_work() will also rollback the headers as expected.
method output_ch : Netchannels.out_obj_channel
Deprecated.Use #out_channel instead.
method out_channel : Netchannels.out_obj_channel
The "raw" output channel. In general you should use instead Netcgi.cgi#out_channnel which supports transactions (if you choose to). Access to the "raw" channel is useful however, for example for sending images or download of files (for which transactions are not interesting but merely more work).
method log_error : string -> unit
#log_error msg appends msg to the webserver log.
method config : config
The configuration of the request.
ocamlnet-4.1.2/doc/html-main/Netgssapi_auth.CONFIG.html0000644000175000017500000004163412731530352021220 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_auth.CONFIG

Module type Netgssapi_auth.CONFIG

module type CONFIG = sig .. end

val raise_error : string -> 'a
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.engine_mixin.html0000644000175000017500000004367012731530352024451 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.engine_mixin 'Uq_engines_compat.engine_state ->
Unixqueue.event_system ->
object
  method event_system : Unixqueue.event_system
  method private notify : unit -> unit
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    ('Uq_engines_compat.engine -> bool) -> unit
  method private set_state : 'Uq_engines_compat.engine_state -> unit
  method state : 'Uq_engines_compat.engine_state
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.datagram_socket_provider-c.html0000644000175000017500000004342212731530352026214 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.datagram_socket_provider

Class type Uq_engines_compat.datagram_socket_provider

class type datagram_socket_provider = object .. end

method create_datagram_socket : datagram_type ->
Unixqueue.event_system ->
wrapped_datagram_socket engine
ocamlnet-4.1.2/doc/html-main/type_Netsys_rng.html0000644000175000017500000004142212731530352020465 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_rng sig
  val set_rng : (Bytes.t -> unit) -> unit
  val fill_random : Bytes.t -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.delegate_engine.html0000644000175000017500000004116012731530352025067 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.delegate_engine '#Uq_engines_compat.engine -> ['t] Uq_engines_compat.engineocamlnet-4.1.2/doc/html-main/Rpc_auth_gssapi.Debug.html0000644000175000017500000004162012731530352021431 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_auth_gssapi.Debug

Module Rpc_auth_gssapi.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/type_Netcgi_modtpl.html0000644000175000017500000005010212731530352021115 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_modtpl sig
  type var =
      VarString of string
    | VarTable of Netcgi_modtpl.table_row list
    | VarConditional of bool
    | VarCallback of (string list -> string)
  and table_row = (string * Netcgi_modtpl.var) list
  class template :
    ?filename:string ->
    string ->
    object
      method callback : string -> (string list -> string) -> unit
      method conditional : string -> bool -> unit
      method output : Netcgi.cgi -> unit
      method set : string -> string -> unit
      method source : string
      method table : string -> Netcgi_modtpl.table_row list -> unit
      method to_channel : Pervasives.out_channel -> unit
      method to_string : string
    end
  val template : string -> Netcgi_modtpl.template
  val template_from_string :
    ?filename:string -> string -> Netcgi_modtpl.template
  val template_from_channel :
    ?filename:string -> Pervasives.in_channel -> Netcgi_modtpl.template
end
ocamlnet-4.1.2/doc/html-main/Unixqueue.unix_event_system-c.html0000644000175000017500000004253312731530352023274 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.unix_event_system

Class Unixqueue.unix_event_system

class unix_event_system : unit -> event_system
An alternate name for standard_event_system, provided for backward compatibility.

ocamlnet-4.1.2/doc/html-main/Netx509_pubkey.Signing.html0000644000175000017500000005245012731530352021424 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey.Signing

Module Netx509_pubkey.Signing

module Signing: sig .. end

val rsa_with_sha1 : Netx509_pubkey.sign_alg
These algorithms are used for signing

RSASSA-PKCS1-v1_5

val rsa_with_sha224 : Netx509_pubkey.sign_alg
val rsa_with_sha256 : Netx509_pubkey.sign_alg
val rsa_with_sha384 : Netx509_pubkey.sign_alg
val rsa_with_sha512 : Netx509_pubkey.sign_alg
val rsassa_pss : hash_function:Netx509_pubkey.hash_function ->
maskgen_function:Netx509_pubkey.maskgen_function ->
salt_length:int -> Netx509_pubkey.sign_alg
RSASSA-PSS
val dsa_with_sha1 : Netx509_pubkey.sign_alg
DSA
val dsa_with_sha224 : Netx509_pubkey.sign_alg
val dsa_with_sha256 : Netx509_pubkey.sign_alg
val ecdsa_with_sha1 : Netx509_pubkey.sign_alg
ECDSA
val ecdsa_with_sha224 : Netx509_pubkey.sign_alg
val ecdsa_with_sha256 : Netx509_pubkey.sign_alg
val ecdsa_with_sha384 : Netx509_pubkey.sign_alg
val ecdsa_with_sha512 : Netx509_pubkey.sign_alg
val eddsa : Netx509_pubkey.sign_alg
EDDSA. draft-josefsson-pkix-eddsa
val catalog : (string * string list * Netx509_pubkey.sign_alg * Netx509_pubkey.oid) list
(name, aliases, oid, container_oid)
val alg_id_of_sign_alg : Netx509_pubkey.sign_alg -> Netx509_pubkey.alg_id
Get the alg_id of a sign alg
val key_oid_of_sign_alg : Netx509_pubkey.sign_alg -> Netx509_pubkey.oid
The OID public keys need to have
ocamlnet-4.1.2/doc/html-main/Netplex_types.protocol-c.html0000644000175000017500000004652412731530352022224 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.protocol

Class type Netplex_types.protocol

class type protocol = object .. end

method name : string
The protocol name is an arbitrary string identifying groups of sockets serving the same protocol for a socket_service.
method addresses : extended_address array
The addresses of the master sockets. (The socket type is always SOCK_STREAM.) The list must be non-empty.
method lstn_backlog : int
The backlog (argument of Unix.listen)
method lstn_reuseaddr : bool
Whether to reuse ports immediately
method so_keepalive : bool
Whether to set the keep-alive socket option
method tcp_nodelay : bool
Whether to set the TCP_NODELAY option
method local_chmod : int option
Whether to chmod Unix Domain sockets
method local_chown : (int * int) option
Whether to chown (user,group) Unix Domain sockets
method configure_slave_socket : Unix.file_descr -> unit
A user-supplied function to configure slave sockets (after accept). The function is called from the process/thread of the container.
ocamlnet-4.1.2/doc/html-main/type_Netx509.directory_name.html0000644000175000017500000004203512731530352022512 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.directory_name object
  method eq_name : (Netx509.oid * Netasn1.Value.value) list list
  method eq_string : string
  method name : (Netx509.oid * Netasn1.Value.value) list list
  method string : string
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_container.Debug.html0000644000175000017500000004101212731530352023033 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_container.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netftp_client.ftp_client_pi-c.html0000644000175000017500000005764312731530352023141 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_client.ftp_client_pi

Class type Netftp_client.ftp_client_pi

class type ftp_client_pi = object .. end
The client protocol interpreter...

method exec_e : ?prelim:(ftp_state -> reply -> unit) ->
cmd ->
(ftp_state * reply) Uq_engines.engine
Run another command as engine. The command is first started when the previous command has terminated. The protocol interpreter does not check whether this command is allowed in the current ftp_state or not.

When the command is done, the engine transitions to `Done(st,r) where st is the state after the command, and r is the final reply of the server.

Due to the FTP specification there may be several replies for a command: First, zero or more replies with cmd_state = `Preliminary, and then exactly one reply with a final state. The preliminary replies can be intercepted with the prelim callback.

method send_abort : unit -> unit
Sends immediately an ABOR command, even when a data transfer is in progress.

TODO - not yet implemented

method run : unit -> unit
Starts the event system; same as Unixqueue.run
method ftp_state : ftp_state
Returns the current ftp_state
method state : unit Uq_engines.engine_state
The state in the sense of Uq_engines. Possible values are:
  • `Working _: The control connection is still active. The int argument is currently meaningless.
  • `Done(): The control connection has been terminated.
  • `Error e: A violation of the FTP protocol happened, or another exception e occurred
  • `Aborted: The abort method was called

method abort : unit -> unit
Shuts any active connection immediately down, and changes the state of the engine to `Aborted.
method event_system : Unixqueue.event_system
The used event system
method request_notification : (unit -> bool) -> unit
method request_proxy_notification : (unit Uq_engines.engine -> bool) -> unit
method is_empty : bool
Whether the queue is empty
method need_ip6 : bool
Whether `EPSV or `EPRT are required instead of `PASV and `PORT, respectively. This is first set after connecting to a server (i.e. when the IP address family is known). Before, it is always false.
method gssapi_props : Netsys_gssapi.client_props option
GSSAPI props if GSSAPI security is negotiated
method supports_tvfs : bool
Whether TVFS filenames are supported
method supports_mdtm : bool
Whether the `MDTM command is supported. Note that `MDTM is sometimes even supported even if the server does not provide the `FEAT command to test for this feature.
method supports_size : bool
Whether the `SIZE command is supported. Note that `SIZE is sometimes even supported even if the server does not provide the `FEAT command to test for this feature.
method supports_mlst : bool
Whether the `MLST and `MLSD commands are supported
method mlst_facts : string list
All available facts for `MLST and `MLSD
method mlst_enabled_facts : string list
The enabled facts for `MLST and `MLSD
method supports_utf8 : bool
Whether the UTF-8 extension is understood by the server (RFC 2640)
method supports_tls : bool
Whether TLS is supported
ocamlnet-4.1.2/doc/html-main/Nethttp_client_conncache.html0000644000175000017500000005145212731530352022262 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client_conncache

Module Nethttp_client_conncache

module Nethttp_client_conncache: sig .. end
Connection cache


This module allows one to create special connection caches, e.g. by deriving from the official ones
type transport_layer_id = int 
type inactive_data = {
   conn_trans : transport_layer_id;
   tls_stashed_endpoint : exn option;
}
type conn_state = [ `Active of <  > | `Inactive of inactive_data ] 
A TCP connection may be either `Inactive, i.e. it is not used by any pipeline, or `Active obj, i.e. it is in use by the pipeline obj (this is the Nethttp_client.pipeline coerced to < >).

Since Ocamlnet-4, `Inactive connections carry an inactive_data record (was a transport_layer_id before). Since Ocamlnet-3.3, `Inactive connections carry the transport ID as argument. Since 3.8, there is the option of storing an exception value private_data. This may be used by implementations to store private data together with the file descriptor.

type peer = [ `Direct of string * int
| `Direct_name of string * int
| `Http_proxy of string * int
| `Http_proxy_connect of (string * int) * (string * int)
| `Socks5 of (string * int) * (string * int) ]
class type connection_cache = object .. end
class restrictive_cache : unit -> connection_cache
A restrictive cache closes connections as soon as there are no pending requests.
class aggressive_cache : unit -> connection_cache
This type of cache tries to keep connections as long open as possible.
ocamlnet-4.1.2/doc/html-main/Rpc_client.html0000644000175000017500000017677212731530352017374 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client

Module Rpc_client

module Rpc_client: sig .. end
RPC clients


This module implements an RPC client, i.e. provides means to connect to an RPC service and call remote procedures. In general, this module works in an asynchronous way and is implemented event-driven. All events are handled by an event queue of type Unixqueue.t that must already exist and to which this module adds its own event handlers and event resources. This means that this module can co-exist with other services and share the same event queue with them.

You can push several procedure calls on the event queue at once. The queue serves then as a pipeline; the calls are sent to the server as long as the server accepts new calls. Replies are received in any order, and the return values of the remote procedures are delivered using a callback function.

You can set timeouts and force automatic retransmission if you want this; these features are enabled by default if the underlying transport mechanism is UDP. Timeouts and other exceptions are delivered to the callback functions, too.

The whole mechanism is designed to allow maximum parallelism without needing to use the multi-threading features of O'Caml. Especially, the following parallelisms can be done:

  • Call several procedures of the same server in parallel. Note that this does not necessarily mean that the procedures are run in parallel since the server is free to decide whether to work in a synchronous or asynchronous way.
  • Call several procedures of different servers in parallel. To do so, simply add several RPC clients to the same event queue.
  • Call a procedure and do something completely different in the background; this works well as long as the other task can be programmed using file descriptor events, too.
However, there are still some restrictions concerning asynchronous calls. Some of them will be removed in the future, but others are difficult to tackle:
  • Authentication methods requiring RPC calls or other network services are performed in an synchronous way, too.
  • Name service lookups are synchronous, too.
Multi-threading: Only a single thread may use an RPC client at a time. There is a way so that several threads can share the same client without giving up concurrency, see Example: Threads sharing an RPC client for details.
exception Message_lost
got EOF when some pending procedure calls were not replied or even sent
exception Message_timeout
After all retransmissions, there was still no reply
exception Response_dropped
Drop reason: The response exceeded the configured maximum message size
exception Communication_error of exn
an I/O error happened
exception Client_is_down
The RPC call cannot be performed because the client has been shut down in the meantime. You can get this exception if you begin a new call, but the connection is closed now.
exception Keep_call
This exception can be raised by the callback function that is invoked when the server response arrives. It causes that the RPC call record is kept in the housekeeping structure of the client. If the server sends another response, the callback function will be invoked again. I.e. one call can be replied several times (server-driven batching).
exception Unbound_exception of exn
This exception can be raised by the callback function that is invoked when the server response arrives. It simply causes that the inner exception bypasses the exception handler, and falls through to the caller of Unixqueue.run. This is useful to jump out of the running RPC routines.
type t 
The type of RPC clients
type connector = 
| Inet of (string * int) (*
Hostname or IP address, port
*)
| Internet of (Unix.inet_addr * int) (*
The address plus port
*)
| Unix of string (*
Path to unix dom sock. Not supported on Win32.
*)
| W32_pipe of string (*
Path to named pipe (only Win32)
*)
| Descriptor of Unix.file_descr (*
Pass an already open socket descriptor. The descriptor will not be closed when the client is done! On Win32, the proxy descriptors as returned by Netsys_win32.pipe_descr are also accepted.
*)
| Dynamic_descriptor of (unit -> Unix.file_descr) (*
The function is called to get the socket descriptor. Unlike Descriptor, the descriptor will be closed when the client is done (unless it is a proxy descriptor)
*)
| Portmapped of string (*
The portmapper on this host is queried to get address information
*)
val connector_of_sockaddr : Unix.sockaddr -> connector
Converts the socket address into a connector
val connector_of_socksymbol : Netsockaddr.socksymbol -> connector
Converts the Netsockaddr.socksymbol into a connector
val shutdown_connector : t ->
Rpc_transport.rpc_multiplex_controller -> (unit -> unit) -> unit
The default implementation to shut down the connector. Actions are triggered that will take the connector down at some time in the future. At this time, the callback function is invoked.

For Descriptor connector the socket is shut down but not closed. For the other connector types the socket is also closed. Win32 named pipes are shut down.

class type socket_config = object .. end
Configuration for `Socket (see below).
val default_socket_config : socket_config
Default configuration with non_blocking_connect = true
class default_socket_config : socket_config
Default configuration as class
val blocking_socket_config : socket_config
Configuration with non_blocking_connect = false
class blocking_socket_config : socket_config
blocking connect configuration as class
val tls_socket_config : (module Netsys_crypto_types.TLS_CONFIG) -> socket_config
This configuration establishes TLS when connecting with the server. It is (so far) only compatible with Rpc.Tcp.
class tls_socket_config : (module Netsys_crypto_types.TLS_CONFIG) -> socket_config
TLS configuration as class
type internal_pipe = Netxdr.xdr_value Netsys_polypipe.polypipe 
type internal_socket = Netxdr.xdr_value Netsys_polysocket.polyclient 
type mode2 = [ `Internal_endpoint of internal_pipe * internal_pipe
| `Internal_socket of internal_socket
| `Multiplexer_endpoint of Rpc_transport.rpc_multiplex_controller
| `Socket of Rpc.protocol * connector * socket_config
| `Socket_endpoint of Rpc.protocol * Unix.file_descr ]
Determines the type of the client for create2:

  • `Socket_endpoint(proto,fd): Socket fd is a connected socket descriptor used for communication. proto determines the encapsulation; should be Tcp for stream sockets and Udp for datagram sockets. The descriptor will be closed when the client terminates.
  • `Multiplexer_endpoint m: m is an RPC multiplex controller.
  • `Socket(proto, conn, config): Creates and connect a client socket according to conn. proto determines the encapsulation; should be Tcp for stream sockets and Udp for datagram sockets. config specifies configuration details. In particular, use this option to enable TLS for the socket: Get a tls_socket_config and pass this as config here.
  • `Internal_endpoint(rd,wr): Creates a client that exchanges data over the pair of polypipes (rd,wr) (see Netsys_polypipe). The polypipes will be closed when the client terminates.
  • `Internal_socket psock: Creates a client that exchanges data over the polysocket client psock (see Netsys_polysocket). The client must already be connected to the server (i.e. Netsys_polysocket.connect has already been called). The polysocket will be closed when the client terminates.

val create2 : ?program_number:Netnumber.uint4 ->
?version_number:Netnumber.uint4 ->
?initial_xid:int ->
?shutdown:(t ->
Rpc_transport.rpc_multiplex_controller -> (unit -> unit) -> unit) ->
mode2 -> Rpc_program.t -> Unixqueue.event_system -> t
New style clients: Opens a connection to the server specified by mode2. The server is assumed to implement an RPC program as specified by the Rpc_program.t argument. (You can override the program and version numbers stored in this argument by the optional parameters program_number and version_number. If you need to call several programs/versions with the same client, use unbound_create instead.)

All communication to the server is handled using the given queue Unixqueue.event_system. There is a limit of 2GB per message or Sys.max_string_length, whatever is lower.

If the protocol (passed along with mode2) is Tcp, the communication will be handled stream-oriented. In this case, no timeout is detected and no retransmissions are done.

If the protocol is Udp, a datagram-oriented communication style is used. This works only for Internet UDP sockets because these are bidirectional (Unix domain sockets are unidirectional and do not work). For Udp, there is a timeout of 15 seconds and a maximum of 3 retransmissions (i.e. a total of 4 transmission trials). For connected UDP sockets there is a limit of 64K per message (max. size of an Internet packet). For unconnected UDP sockets there is a limit of 16K per message due to restrictions in the OCaml runtime.


program_number : Overrides the program number in Rpc_program.t
version_number : Overrides the version number in Rpc_program.t
initial_xid : The initial value for the session identifier.
shutdown : This function is called when the client is shut down to close the client socket. By default, shutdown_connector is called.
val unbound_create : ?initial_xid:int ->
?shutdown:(t ->
Rpc_transport.rpc_multiplex_controller -> (unit -> unit) -> unit) ->
mode2 -> Unixqueue.event_system -> t
Creates an unbound client. This is like create2, but the client is not restricted to a particular RPC program.

One can convert an unbound client into a bound client by calling bind, see below. It is possible to bind several times, so several programs can be called with the same client (provided the server is also capable of dealing with several programs).

This function does not support Portmapped connectors.

val bind : t -> Rpc_program.t -> unit
Binds this program additionally
val use : t -> Rpc_program.t -> unit
If there are no bound programs, this is a no-op. Otherwise it is checked whether the passed program is bound. If not, an exception is raised.

Programs are compared by comparing Rpc_program.id. The program must be the same value, but it is also allowed to Rpc_program.update it in the meantime, i.e. to change program and version numbers.

val configure : t -> int -> float -> unit
configure client retransmissions timeout: sets the number of retransmissions and the timeout for the next calls. (These values are defaults; the actual values are stored with each call.)

Values of retransmissions > 0 are semantically only valid if the called procedures are idempotent, i.e. invoking them several times with the same values has the same effect as only one invocation. Positive values for retransmissions should only be used for Udp-style communication.

The timeout value determines how long the client waits until the next retransmission is done, or, if no more retransmissions are permitted, a Message_timeout exception is delivered to the receiving callback function. A timeout value of 0.0 means immediate timeout (see next paragraph). A negative timeout value means 'no timeout'. Positive timeout values are possible for both Udp and Tcp connections. Timeout values are measured in seconds.

There is a special application for the timeout value 0.0: If you don't expect an answer from the server at all ("batch mode"), this timeout value will cause that the message handler will get a Message_timeout exception immediately. You should ignore this exception for batch mode. The positive effect from the timeout is that the internal management routines will remove the remote call from the list of pending calls such that this list will not become too long. (You can get a similar effect by calling set_batch_call, however.)

Note that the meaning of timeouts for TCP connections is unclear. The TCP stream may be in an undefined state. Because of this, the client does not make any attempt to clean the state up for TCP. The user is advised to shut down the client, and reconnect.

There is another subtle difference between UDP and TCP. For UDP, the timer is started when the packet is sent. For TCP, however, the timer is already started when the RPC call is added to the queue, i.e. much earlier. This means that the time for connecting to the remote service is also bound by the timeout. The rationale is that TCP timeouts are usually set to catch total service failures rather than packet losses, and this behaviour is best for this purpose.

val configure_next_call : t -> int -> float -> unit
Same as configure, but it only affects the next call
val set_dgram_destination : t -> Unix.sockaddr option -> unit
set_dgram_destination client addr_opt: This function is required for using the client in conjunction with unconnected UDP sockets. For connected sockets, the destination of datagrams is implicitly given. For unconnected sockets, one has to set the destination explicitly. Do so by calling set_dgram_destination with Some addr as addr_opt argument before calling. Passing None as addr_opt removes the explicit destination again. Note that unconnected sockets differ from connected sockets also in the relaxation that they can receive messages from any IP address, and not only the one they are connected to.

The current destination is used for all following calls. It is not automatically reset to None after the next call.

val set_batch_call : t -> unit
The next call will be a batch call. The client does not wait for the response of a batch call. Instead, the client immediately fakes the response of a "void" return value.

It is required that the batch call has a "void" return type. Otherwise, the client raises an exception, and ignores the call.

This setting only affects the next call.

val set_user_name : t -> string option -> unit
Sets the user name, or None (the default user name). This is only meaningful for authentication.
val set_max_response_length : t -> int -> unit
Sets the maximum length of responses. By default, there is only the implicit maximum of Sys.max_string_length.

If the maximum is exceeded, the exception Response_dropped is raised.

val set_exception_handler : t -> (exn -> unit) -> unit
sets an exception handler (the default prints the exception with `Crit level to the logger set in Netlog). Only exceptions resulting from invocations of a callback function are forwarded to this handler (unless wrapped by Unbound_exception).

Exceptions occuring in the handler itself are not caught, and will fall through.

val set_mstring_factories : t -> Netxdr_mstring.named_mstring_factories -> unit
Sets the mstring factory configuration that is used for decoding responses containing managed strings.
val event_system : t -> Unixqueue.event_system
Returns the unixqueue to which the client is attached
val programs : t -> Rpc_program.t list
Returns the list of all bound programs
val get_socket_name : t -> Unix.sockaddr
val get_peer_name : t -> Unix.sockaddr
Return the addresses of the client socket and the server socket, resp. Note that these are only available when the client is already connected. The function calls fail otherwise. It is also possible that the underlying transport mechanism does not know these data.
val get_sender_of_last_response : t -> Unix.sockaddr
Return the address of the sender of the last received response.
val get_xid_of_last_call : t -> Netnumber.uint4
Returns the session identifier used in the just made call
val get_protocol : t -> Rpc.protocol
Get the protocol flavour
val get_tls_session_props : t -> Nettls_support.tls_session_props option
Get the TLS properties so far TLS is enabled
val get_gssapi_props : t -> Netsys_gssapi.client_props option
Get the GSSAPI properties of the last call (so far available)
val abandon_call : t -> Netnumber.uint4 -> unit
To be used in conjunction with Rpc_client.Keep_call: The call with this session identifier is no longer expected, and removed from the internal data structures.

Restriction: for now, this does not work when there is authentication.

val is_up : t -> bool
Return whether the client is up
val get_stats : t -> int * int * int
Get stats (n_delayed, n_waiting, n_pending):
  • n_delayed: Calls that wait for authentication
  • n_waiting: Calls that wait for being sent
  • n_pending: Calls that wait for the response

val unbound_sync_call : t ->
Rpc_program.t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
unbound_sync_call client pgm proc arg: Invoke the remote procedure proc of the program pgm via client. The input arguments are arg. The result arguments are returned (or an error is raised)
val unbound_async_call : t ->
Rpc_program.t ->
string -> Netxdr.xdr_value -> ((unit -> Netxdr.xdr_value) -> unit) -> unit
unbound_ssync_call client pgm proc arg emit: Invoke the remote procedure proc of the program pgm via client. The input arguments are arg. When the result r is available, the client will call emit (fun () -> r) back. When an exception e is available, the client will call emit (fun () -> raise e) back.
class unbound_async_call : t -> Rpc_program.t -> string -> Netxdr.xdr_value -> [Netxdr.xdr_value] Uq_engines.engine
Same as unbound_async_call, but with an engine API.
val synchronize : Unixqueue.event_system -> ('a -> ((unit -> 'b) -> unit) -> unit) -> 'a -> 'b
Turns an async call into a synchronous call
val shut_down : t -> unit
Shuts down the connection. Any unprocessed calls get the exception Message_lost. It is no error to shut down a client that is already down - nothing happens in this case.

Shutdowns can be complex operations. For this reason, this function implements some magic that is usually the right thing, but may also be wrong:

  • If called outside the event loop, it is assumed that a synchronous shutdown is desired, and the event loop is started to complete the shutdown immediately. This is right when the only task connected with the event loop is the shutdown, which is then done, and this function returns finally to the caller. If there are other tasks on the event loop, these tasks are also run, however, which may lead to side effects and infinite delay. This can be wrong.
  • If called from within the event loop, the shutdown is only triggered but not immediately done. When the caller returns to the event loop the shutdown will be performed. This case is problematic when you pass the file descriptor explicitly with Descriptor to the client. You don't know when the client is finally down, and the descriptor can be closed.
The following functions allow more fine grained control of the shutdown.
val sync_shutdown : t -> unit
Enforces a synchronous shutdown of the connection. This is only possible if called from outside the event loop. This function fails if called from within the event loop.

You can be sure that the shutdown is completely done when this function returns normally.

val trigger_shutdown : t -> (unit -> unit) -> unit
Triggers the shutdown, and calls the passed function back when it is done.

The function is not only called when the client has to be taken down, but also if the client is already down.

val set_debug_name : t -> string -> unit
Set a name printed with debug messages
val get_debug_name : t -> string
Get the debug name
type reject_code = [ `Fail | `Next | `Renew | `Retry ] 
Reaction on authentication problems:
  • `Fail: Stop here, and report to user
  • `Retry: Just try again with current session
  • `Renew: Drop the current session, and get a new session from the current auth_method
  • `Next: Try the next authentication method

class type auth_session = object .. end
An auth_session object is normally created for every client instance.
class type auth_protocol = object .. end
An authentication protocol is used for creating an authentication session.
class type auth_method = object .. end
An auth_method object represents a method of authentication.
val auth_none : auth_method
The authentication method that does not perform authentication.
val set_auth_methods : t -> auth_method list -> unit
Set the authentication methods for this client. The passed methods are tried in turn until a method is accepted by the server. The default is auth_none

When the methods are set for an active client, the ongoing calls are continued with the old method. First new calls are ensured to use the new list.

module type USE_CLIENT = sig .. end
This module type is what the generated "clnt" module assumes about the client interface
val xdr_ctx : t -> Netxdr.ctx
Returns the recommended XDR context

Deprecated Interfaces


val create : ?program_number:Netnumber.uint4 ->
?version_number:Netnumber.uint4 ->
?initial_xid:int ->
?shutdown:(t ->
Rpc_transport.rpc_multiplex_controller -> (unit -> unit) -> unit) ->
Unixqueue.event_system ->
connector -> Rpc.protocol -> Rpc_program.t -> t
Deprecated.This function should not be used any more in new programs. Use create2 or unbound_create.
Opens a connection to the server specified by the connector. The server is assumed to implement an RPC program as specified by the Rpc_program.t argument. (You can override the program and version numbers stored in this argument by the optional parameters program_number and version_number.)

All communication to the server is handled using the given queue Unixqueue.event_system.

If the protocol is Tcp, the communication will be handled stream- oriented. In this case, no timeout is detected and no retransmissions are done.

If the protocol is Udp, a datagram-oriented communication style is used. This works only for Internet UDP sockets because these are bidirectional (Unix domain sockets are unidirectional and do not work). For Udp, there is a timeout of 15 seconds and a maximum of 3 retransmissions (i.e. a total of 4 transmission trials).

Unlike create2, servers made with create always use blocking connect for backwards compatibility.


program_number : Overrides the program number in Rpc_program.t
version_number : Overrides the version number in Rpc_program.t
initial_xid : The initial value for the session identifier.
shutdown : This function is called when the client is shut down to close the client socket. By default, shutdown_connector is called.
val program : t -> Rpc_program.t
Deprecated.This is the same as List.hd (Rpc_client.programs client)
Returns the program the client represents.
val add_call : t ->
string -> Netxdr.xdr_value -> ((unit -> Netxdr.xdr_value) -> unit) -> unit
Deprecated.add_call is restricted to the case that there is only one bound program. It will fail in other cases. Use unbound_async_call instead. Note also that there is no longer the optional when_sent argument. Use set_batch_call instead
add_call client proc_name arg f: add the call to the procedure name with argument arg to the queue of unprocessed calls.

When the reply has arrived or an error situation is detected, the function f is called back. The argument of f is another function that will return the result or raise an exception:

 let my_f get_result =
      try
        let result = get_result() in
        ...
      with
         exn -> ...
    in
    add_call client name arg my_f
 

If f does not catch the exception, the pluggable exception handler of the client is called (see set_exception_handler). Exceptions are either Message_lost, Message_timeout, or Communication_error.

The function f can raise the exception Keep_call to indicate the special handling that a further reply of the call is expected (batching).


val sync_call : t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value

Calls the procedure synchronously. Note that this implies that the underlying unixqueue is started and that all events are processed regardless of whether they have something to do with this call or not.


val verbose : bool -> unit
set whether you want debug messages or not (same as setting Rpc_client.Debug.enable)

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.post-c.html0000644000175000017500000004237012731530352021464 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.post

Class Nethttp_client.post

class post : string -> (string * string) list -> http_call
Arguments: URI, parameter list to be transferred as application/x-www-form-urlencoded body

ocamlnet-4.1.2/doc/html-main/Nethttp_client.generic_call-c.html0000644000175000017500000004575712731530352023122 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.generic_call

Class virtual Nethttp_client.generic_call

class virtual generic_call : object .. end
This class is an implementation of http_call. A subclass must define the virtual methods that mostly define the general properties of the HTTP method.
Inherits
method private virtual fixup_request : unit -> unit
This method is called just before sending the request. It can fix up things in the `Effective request header.
method private virtual def_request_method : string
The following methods define the values for the corresponding methods without the def_ prefix:
method private virtual def_empty_path_replacement : string
method private virtual def_is_idempotent : bool
method private virtual def_has_req_body : bool
method private virtual def_has_resp_body : bool
ocamlnet-4.1.2/doc/html-main/Rpc_server.Debug.html0000644000175000017500000004456112731530352020437 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.Debug

Module Rpc_server.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Whether debug messages of general kind are enabled. See Netlog.Debug for more information.
val enable_ctrace : bool Pervasives.ref
Whether debug messages are enabled that trace connection events. See Netlog.Debug for more information.

The "module name" for these messages is "Rpc_server.Ctrace".

val enable_ptrace : bool Pervasives.ref
Whether the procedure trace is enabled. The procedure trace outputs for every RPC call and response a debug message. ptrace_verbosity says how verbose.
val ptrace_verbosity : Rpc_util.verbosity Pervasives.ref
How verbose the ptrace is. Defaults to `Name_abbrev_args
val disable_for_server : Rpc_server.t -> unit
Disables logging for this server
ocamlnet-4.1.2/doc/html-main/type_Rpc.html0000644000175000017500000005063512731530352017064 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc sig
  type protocol = Tcp | Udp
  type mode = Socket | BiPipe
  type server_error =
      Unavailable_program
    | Unavailable_version of (Netnumber.uint4 * Netnumber.uint4)
    | Unavailable_procedure
    | Garbage
    | System_err
    | Rpc_mismatch of (Netnumber.uint4 * Netnumber.uint4)
    | Auth_bad_cred
    | Auth_rejected_cred
    | Auth_bad_verf
    | Auth_rejected_verf
    | Auth_too_weak
    | Auth_invalid_resp
    | Auth_failed
    | RPCSEC_GSS_credproblem
    | RPCSEC_GSS_ctxproblem
  val string_of_server_error : Rpc.server_error -> string
  exception Rpc_server of Rpc.server_error
  exception Rpc_cannot_unpack of string
  val create_inet_uaddr : Unix.inet_addr -> int -> string
  val parse_inet_uaddr : string -> Unix.inet_addr * int
  val netid_of_inet_addr : Unix.inet_addr -> Rpc.protocol -> string
  val sockaddr_of_uaddr :
    string -> string -> (Unix.sockaddr * Rpc.protocol) option
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_kernel.http_protocol-c.html0000644000175000017500000007070212731530352023545 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_protocol

Class Nethttpd_kernel.http_protocol

class http_protocol : #http_protocol_config -> Unix.file_descr -> object .. end
The core event loop of the HTTP daemon

Exchange of HTTP messages

In fd one must pass the already connected socket. It must be in non- blocking mode.

How to use this class: Basically, one invokes cycle until the whole message exchange on fd is processed. cycle receives data from the socket and sends data to the socket. There are two internal queues:

The receive queue stores parts of received requests as req_token. One can take values from the front of this queue by calling receive.

The response queue stores http_response objects. Each of the objects corresponds to a request that was received before. This queue is handled fully automatically, but one can watch its length to see whether all responses are actually transmitted over the wire.

The basic algorithm to process messages is:

 let rec next_token () =
   if proto # recv_queue_len = 0 then (
     proto # cycle ();
     next_token()
   )
   else
     proto # receive()

 let cur_token = ref (next_token()) in
 while !cur_token <> `Eof do
   (* Process first token of next request: *)
   match !cur_token with
    | `Req_header(req_line, header, resp) ->
         (* Depending on [req_line], read further tokens until [`Req_end] *)
         ...
         (* Switch to the first token of the next message: *)
         cur_token := next_token()
    | `Timeout -> ...
    | `Bad_request_error(e,resp) -> 
          (* Generate 400 error, send it to [resp] *)
          ...
          (* Switch to the first token of the next message: *)
          cur_token := next_token()
    | `Fatal_error e -> failwith "Crash"
    | _ -> assert false
 done;
 while proto # resp_queue_len > 0 do
   proto # cycle ();
 done;
 proto # shutdown()
 

See the file tests/easy_daemon.ml for a complete implementation of this.

As one can see, it is essential to watch the lengths of the queues in order to figure out what has happened during cycle.

When the body of the request is empty, `Req_body tokens are omitted. Note that for requests like GET that always have an empty body, it is still possible that an errorneous client sends a body, and that `Req_body tokens arrive. One must accept and ignore these tokens.

Error handling: For serious errors, the connection is immediately aborted. In this case, receive returns a `Fatal_error token. Note that the queued responses cannot be sent! An example of this is `Broken_pipe.

There is a large class of non-serious errors, esp. format errors in the header and body. It is typical of these errors that one cannot determine the end of the request properly. For this reason, the daemon stops reading further data from the request, but the response queue is still delivered. For these errors, receive returns a `Bad_request_error token. This token contains a http_response object that must be filled with a 400 error response.

method hooks : http_protocol_hooks
Set hooks
method cycle : ?block:float -> unit -> unit
Looks at the file descriptor. If there is data to read from the descriptor, and there is free space in the input buffer, additional data is read into the buffer. It is also tried to interpret the new data as req_tokens, and if possible, new req_tokens are appended to the receive queue.

If the response queue has objects, and there is really data one can send, and if the socket allows one to send data, it is tried to send as much data as possible.

The option block (default: 0) can be set to wait until data can be exchanged with the socket. This avoids busy waiting. The number is the duration in seconds to wait until the connection times out (0 means not to wait at all, -1 means to wait infinitely). When a timeout happens, and there is nothing to send, and the last request was fully processed, receive will simply return `Timeout (i.e. when waiting_for_next_message is true). Otherwise, the fatal error `Timeout is generated.

method receive : unit -> req_token
Returns the first req_token from the receive queue. Raises Recv_queue_empty when the queue is empty (= has no new data)
method peek_recv : unit -> req_token
Peeks the first token, but leaves it in the queue. Raises Recv_queue_empty when the queue is empty.
method recv_queue_len : int
Returns the length of the receive queue (number of tokens)
method resp_queue_len : int
Returns the length of the internal response queue (number of http_response objects that have not yet fully processed)
method pipeline_len : int
Returns the number of unanswered requests = Number of received `Req_end tokens minus number of responses in state `Processed. Note that pipeline_len can become -1 when bad requests are responded.
method recv_queue_byte_size : int
Returns the (estimated) size of the input queue in bytes
method waiting_for_next_message : bool
Whether the kernel is currently waiting for the beginning of a new arriving HTTP request. This is false while the request is being received.
method input_timeout_class : [ `Next_message | `None | `Normal ]
Suggests the calculation of a timeout value for input:
  • `Normal: The normal timeout value applies
  • `Next_message: The timeout value applies while waiting for the next message
  • `None: The connection is output-driven, no input timeout value

method shutdown : unit -> unit
Shuts the socket down. Note: the descriptor is not closed.

TLS: You need to further cycle until XXX.

method timeout : unit -> unit
Process a timeout condition as cycle does
method abort : fatal_error -> unit
Stops the transmission of data. The receive queue is cleared and filled with the two tokens `Fatal_error and `Eof. The response queue is cleared. The cycle method will return immediately without doing anything.
method fd : Unix.file_descr
Just returns the socket
method do_input : bool
Returns true iff the protocol engine is interested in new data from the socket. Returns false after EOF and after errors.
method do_output : bool
Returns true iff the protocol engine has data to output to the socket
method resp_queue_filled : bool
Whether there is data to send in the internal output queue. If TLS is enabled, this is not always the same as do_output.
method need_linger : bool
Returns true when a lingering close operation is needed to reliably shut down the socket. In many cases, this expensive operation is not necessary. See the class lingering_close below.
method tls_session_props : Nettls_support.tls_session_props option
If TLS is enabled, this returns the session properties. These are first available after the TLS handshake.
method config : http_protocol_config
Just returns the configuration
method test_coverage : string list
For testing: returns a list of tokens indicating into which cases the program ran.
ocamlnet-4.1.2/doc/html-main/Nethttp_client.get_call-c.html0000644000175000017500000004220212731530352022243 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.get_call

Class Nethttp_client.get_call

class get_call : http_call

ocamlnet-4.1.2/doc/html-main/type_Uq_datagram.datagram_socket_provider.html0000644000175000017500000004162412731530352025624 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_datagram.datagram_socket_provider object
  method create_datagram_socket :
    Uq_datagram.datagram_type ->
    Unixqueue.event_system ->
    Uq_datagram.wrapped_datagram_socket Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/type_Netftp_client.ftp_client.html0000644000175000017500000004354212731530352023263 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_client.ftp_client ?event_system:Unixqueue.event_system ->
unit ->
object
  method configure_timeout : float -> unit
  method event_system : Unixqueue.event_system
  method exec : Netftp_client.ftp_method -> unit
  method exec_e : Netftp_client.ftp_method -> unit Uq_engines.engine
  method pi : Netftp_client.ftp_client_pi
  method reset : unit -> unit
  method run : unit -> unit
  method set_socks5_proxy : string -> int -> unit
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.signal_engine-c.html0000644000175000017500000004440712731530352022415 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.signal_engine

Class Uq_engines.signal_engine

class ['a] signal_engine : Unixqueue.event_system -> object .. end
let se = new signal_engine esys: The engine se remains in `Working 0 until the method se # signal x is called. At this point e transitions to x. Any further call of signal does not have any effect.

Also, if se is aborted, signal does not have any effect.

The function signal may be called from a different thread. The signalling event is forwarded to the thread running the event system.

Inherits
method signal : 'a final_state -> unit
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.buffering_engine_processing_config.html0000644000175000017500000004066512731530352030535 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.buffering_engine_processing_config Nethttpd_engine.http_engine_processing_configocamlnet-4.1.2/doc/html-main/type_Netsys_ciphers.cipher.html0000644000175000017500000004240612731530352022610 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_ciphers.cipher object
  method block_constraint : int
  method create :
    string -> Netsys_ciphers.padding -> Netsys_ciphers.cipher_ctx
  method iv_lengths : (int * int) list
  method key_lengths : (int * int) list
  method mode : string
  method name : string
  method supports_aead : bool
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.async_out_channel_engine-c.html0000644000175000017500000004320212731530352024624 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.async_out_channel_engine

Class type Uq_engines.async_out_channel_engine

class type async_out_channel_engine = object .. end
Inherits
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.TLS_PROVIDER.Exc.html0000644000175000017500000004061012731530352025132 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_PROVIDER.Exc TLS_EXCEPTIONSocamlnet-4.1.2/doc/html-main/type_Nethttp_client_conncache.aggressive_cache.html0000644000175000017500000004073612731530352026607 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client_conncache.aggressive_cache unit -> Nethttp_client_conncache.connection_cacheocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.poll_engine.html0000644000175000017500000004361712731530352024274 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.poll_engine ?extra_match:(exn -> bool) ->
(Unixqueue.operation * float) list ->
Unixqueue.event_system ->
object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method group : Unixqueue.group
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    (Unixqueue.event engine -> bool) -> unit
  method restart : unit -> unit
  method state : Unixqueue.event engine_state
end
ocamlnet-4.1.2/doc/html-main/Netplex_internal.html0000644000175000017500000006023712731530352020611 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_internal

Module Netplex_internal

module Netplex_internal: sig .. end
Internal services


Internal services are available to multi-threaded programs only, and implemented via Netsys_polysocket.

See below for an introduction.

val register_server : string -> Netplex_types.polyserver_box -> unit
register_server name server: registers a server under the given name. It is an error if a server is already registered for the same name.

The registration is thread-safe.

val connect_client : 'a Netplex_types.kind_check ->
int -> string -> 'a Netsys_polysocket.polyclient
connect_client is_kind n name: Creates a new polyclient that is connected to the registered service name. The arg is_kind determines the type of the messages that can be exchanged. The number n is the size of the pipe buffer, in number of messages.

The function fails if the service is not registered, or assumes the wrong message kind.

The client lookup is thread-safe.

Example how to invoke a service exchanging strings (kind Tstring):

let same : type s t . s polysocket_kind * t polysocket_kind -> (s,t) eq =
  function
  | Tstring, Tstring -> Equal
  | _ -> Not_equal

let client =
  Netplex_internal.connect_client
    { Netplex_types.kind_check = fun k -> same(Tstring,k) }
    n
    "name"
      

(You should strictly stick to this pattern. Any abbreviation will probably not type-check.)


How to configure and use internal services

Internal services are a fast mechanism to invoke containers from other containers. So far, internal services are only available for multi-threaded programs. The messages can have any type.

You add an internal service by configuring an address "internal" in the protocol section of the configuration file, e.g.

protocol {
  name = "my-protocol";
  address {
    type = "internal";
    name = "my-identifier";
  }
  address {                    (* other addresses ok *)
    ...
  }
}

The internal service is only activated when multi-threading is selected. In programs using multi-processing the internal service is simply ignored.

You need to choose the types of your messages. There is the GADT Netplex_types.polysocket_kind listing possible types. It comes with the variants Txdr (for RPC messaging) and Tstring (for any custom strings):

type _ polysocket_kind = ..
type _ polysocket_kind +=
   | Txdr : Netxdr.xdr_value polysocket_kind
   | Tstring : string polysocket_kind

This is an extensible GADT, i.e. you can add more variants with the "+=" notation. (Note that extensible variants are first available since OCaml-4.02. With older OCaml versions, you cannot extend more variants.)

Let's add integers:

type _ polysocket_kind +=
  | Tint : int polysocket_kind

The connections to the internal services do not arrive via the normal process mechanism. There is a second path using the new processor hooks config_internal and process_internal. The hook config_internal defines which message type you are really using. The hook process_internal is invoked when a new connection to the internal service is established. It works very much like process, only that it doesn't use file descriptors but so-called polysockets (see Netsys_polysocket).

class hello_world_processor hooks : processor =
object(self)
  inherit Netplex_kit.processor_base hooks

  method config_internal =
     [ "my-protocol", Polysocket_kind_box Tint ]

  method process_internal ~when_done container srvbox proto_name =
    let Polyserver_box(kind, srv) = srvbox in
    match kind with
      | Tint ->
         let endpoint = Netsys_polysocket.accept ~nonblock:false srv in
         (* Now send and receive messages over endpoint *)
         ...;
         when_done()
      | _ ->
         failwith "wrong kind"

  method process ~when_done container fd proto_name =
    (* this is still invoked when non-internal connections arrive *)
    ...
  method supported_ptypes = 
    ...
end

The endpoint is actually a pair of polypipes (Netsys_polypipe):

let (rd, wr) = endpoint

Over rd you receive messages of type int from the client, and via wr you can send messages to it.

Use Netplex_internal.connect_client to get a client (usually in a different container, or in an arbitrary other thread):

let same : type s t . s polysocket_kind * t polysocket_kind -> (s,t) eq =
  function
  | Tint, Tint -> Equal
  | _ -> Not_equal

let client =
  Netplex_internal.connect_client
    { Netplex_types.kind_check = fun k -> same(Tint,k) }
    5
    "my-identifier" in
let client_endpoint =
   Netsys_polysocket.endpoint ~synchronous:true ~nonblock:false client

Again, the endpoint is a pair of polypipes in reality:

let (client_rd, client_wr) = client_endpoint

Complete example

You find a complete example in the distribution tarball at code/examples/netplex/internal_service.ml.

Using internal services via RPC

RPC clients and servers have now support for polysockets. Note that you need to select Txdr as message kind. The messages are not serialized into strings, but instead the structured XDR format is used as transport encoding.

XXX TODO
ocamlnet-4.1.2/doc/html-main/type_Uq_resolver.resolver.html0000644000175000017500000004152412731530352022503 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_resolver.resolver object
  method host_by_name :
    string -> Unixqueue.event_system -> Unix.host_entry Uq_resolver.engine
  method ipv6 : bool
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_tls.html0000644000175000017500000006641312731530352020510 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_tls sig
  type dh_params =
      [ `Generate of int | `PKCS3_DER of string | `PKCS3_PEM_file of string ]
  type crt_list = [ `DER of string list | `PEM_file of string ]
  type crl_list = [ `DER of string list | `PEM_file of string ]
  type private_key =
      [ `DSA of string
      | `EC of string
      | `PEM_file of string
      | `PKCS8 of string
      | `PKCS8_encrypted of string
      | `RSA of string ]
  val error_message :
    (module Netsys_crypto_types.TLS_PROVIDER-> string -> string
  val create_x509_config :
    ?algorithms:string ->
    ?dh_params:Netsys_tls.dh_params ->
    ?verify:((module Netsys_crypto_types.TLS_ENDPOINT->
             bool -> bool -> bool) ->
    ?system_trust:bool ->
    ?trust:Netsys_tls.crt_list list ->
    ?revoke:Netsys_tls.crl_list list ->
    ?keys:(Netsys_tls.crt_list * Netsys_tls.private_key * string option) list ->
    peer_auth:[ `None | `Optional | `Required ] ->
    (module Netsys_crypto_types.TLS_PROVIDER->
    (module Netsys_crypto_types.TLS_CONFIG)
  val create_file_endpoint :
    ?resume:string ->
    role:[ `Client | `Server ] ->
    rd:Unix.file_descr ->
    wr:Unix.file_descr ->
    peer_name:string option ->
    (module Netsys_crypto_types.TLS_CONFIG->
    (module Netsys_crypto_types.FILE_TLS_ENDPOINT)
  val endpoint :
    (module Netsys_crypto_types.FILE_TLS_ENDPOINT->
    (module Netsys_crypto_types.TLS_ENDPOINT)
  val handshake : (module Netsys_crypto_types.TLS_ENDPOINT-> unit
  val recv :
    ?on_rehandshake:((module Netsys_crypto_types.TLS_ENDPOINT-> bool) ->
    (module Netsys_crypto_types.TLS_ENDPOINT-> Bytes.t -> int -> int -> int
  val mem_recv :
    ?on_rehandshake:((module Netsys_crypto_types.TLS_ENDPOINT-> bool) ->
    (module Netsys_crypto_types.TLS_ENDPOINT->
    Netsys_types.memory -> int -> int -> int
  val send :
    (module Netsys_crypto_types.TLS_ENDPOINT-> Bytes.t -> int -> int -> int
  val mem_send :
    (module Netsys_crypto_types.TLS_ENDPOINT->
    Netsys_types.memory -> int -> int -> int
  val str_send :
    (module Netsys_crypto_types.TLS_ENDPOINT-> string -> int -> int -> int
  val shutdown :
    (module Netsys_crypto_types.TLS_ENDPOINT->
    Unix.shutdown_command -> unit
  val at_transport_eof : (module Netsys_crypto_types.TLS_ENDPOINT-> bool
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Netftp_data_endpoint.ftp_data_sender.html0000644000175000017500000004523612731530352025613 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.ftp_data_sender ?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option * string option ->
?protector:Netftp_data_endpoint.ftp_protector ->
esys:Unixqueue.event_system ->
mode:Netftp_data_endpoint.transmission_mode ->
local_sender:Netftp_data_endpoint.local_sender ->
descr:Unix.file_descr ->
timeout:float ->
timeout_exn:exn ->
unit ->
object
  method abort : unit -> unit
  method descr : Unix.file_descr
  method descr_state : descr_state
  method event_system : Unixqueue.event_system
  method local_sender : Netftp_data_endpoint.local_sender
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    (unit Uq_engines.engine -> bool) -> unit
  method state : unit Uq_engines.engine_state
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi.simple_argument.html0000644000175000017500000004115612731530352025575 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi.simple_argument ?ro:bool -> string -> string -> Netcgi1_compat.Netcgi_types.cgi_argumentocamlnet-4.1.2/doc/html-main/type_Nethttp_client.transport_channel_type.html0000644000175000017500000004500512731530352026103 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.transport_channel_type object
  method continue :
    Unix.file_descr ->
    Nethttp_client.transport_layer_id ->
    float ->
    exn ->
    string ->
    int ->
    Unixqueue.event_system -> exn option -> Uq_engines.multiplex_controller
  method default_port : int option
  method identify_conn_by_name : bool
  method setup_e :
    Unix.file_descr ->
    Nethttp_client.transport_layer_id ->
    float ->
    exn ->
    string ->
    int ->
    Unixqueue.event_system ->
    Nethttp_client.tls_cache ->
    Uq_engines.multiplex_controller Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/Netcgi_plex.html0000644000175000017500000006256312731530352017543 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_plex

Module Netcgi_plex

module Netcgi_plex: sig .. end

Netplex support for FastCGI, SCGI and AJP connectors




Factory


val factory : ?config:Netcgi.config ->
?enable:[ `AJP | `FCGI | `SCGI ] list ->
?name:string ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?exn_handler:Netcgi.exn_handler ->
?configure:(Netplex_types.config_file ->
Netplex_types.address -> Netplex_types.processor_hooks) ->
(Netplex_types.container -> Netcgi.cgi -> unit) ->
Netplex_types.processor_factory
Reads a Netplex configuration section like
    processor {
      type = "netcgi";          (* or the overridden [name] *)
      timeout = 15;             (* optional *)
      mount_dir = "/url/path";  (* optional *)
      mount_at = "/url/path";   (* optional alternative to mount_dir *)
    }
 

and creates a processor for the protocols "fcgi", "scgi", and "ajp" (or a subset of these protocols if the enable parameter restricts them). A complete service definition looks thus like:

      service {
          name = "name_of_service";
          protocol {
              name = "fcgi";        (* or "scgi" or "ajp" *)
              address {
                  type = "internet";
                  bind = "localhost:<port>";
              };
          };
          (* ... several protocol sections allowed! *)
          processor {
              type = "netcgi";
          };
          workload_manager {
              type = "dynamic";
              max_jobs_per_thread = 1;  (* only reasonable value *)
              min_free_job_capacity = <n>;
              max_free_job_capacity = <n>;
              max_threads = <n>;
          };
      }
 

The processor calls the argument function of type container -> cgi -> unit for every incoming request.

The timeout parameter specifies when inactive connections are timed out (in seconds). The mount_dir and mount_at parameters define which part of the URL is considered as SCRIPT_NAME:

  • By default (if neither mount_dir nor mount_at) are given SCRIPT_NAME is determined in a protocol-dependent way. Usually, the server transmits SCRIPT_NAME, but see the note below.
  • If mount_dir is present, the processor accepts only URLs that have this path as true prefix directory, i.e. the URL path is <mount_dir>/<name><rest>. The part <mount_dir>/<name> is taken as SCRIPT_NAME.
  • If mount_at is present, the processor accepts only URLs that have this path as prefix, i.e. the URL path is <mount_at><rest>. <mount_at> is taken as SCRIPT_NAME.
The background is that SCRIPT_NAME is commonly used to distinghuish between different web actions of the netcgi application. The actions are simply names in a directory like /bin/<name> or /servlet/<name>. Not all web servers/protocols transmit good values for SCRIPT_NAME, however. By specifying mount_dir or mount_at one can force to interpret a certain prefix of the request URL as SCRIPT_NAME.


config : The Netcgi configuration to use, default is Netcgi.default_config
enable : Which protocols to support. Default is to support all protocols
name : Defines the name of the processor. Default is "netcgi".
output_type : Default: `Direct ""
arg_store : Default: `Automatic for all arguments.
exn_handler : See Netcgi.exn_handler. Default: delegate all exceptions to the default handler.
configure : Parameters are the netplex configuration file and the address of the processor section. The configure function can look for additional parameters. It returns service hooks that are added to the resulting processor.

Processors



Processors



The following functions create the processors directly
type mountpoint = [ `Mount_at of string | `Mount_dir of string ] 
val fcgi_processor : ?config:Netcgi.config ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?exn_handler:Netcgi.exn_handler ->
?timeout:float ->
?mount:mountpoint ->
(Netplex_types.container -> Netcgi_fcgi.cgi -> unit) ->
Netplex_types.processor
val scgi_processor : ?config:Netcgi.config ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?exn_handler:Netcgi.exn_handler ->
?timeout:float ->
?mount:mountpoint ->
(Netplex_types.container -> Netcgi.cgi -> unit) -> Netplex_types.processor
val ajp_processor : ?config:Netcgi.config ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?exn_handler:Netcgi.exn_handler ->
?timeout:float ->
?mount:mountpoint ->
(Netplex_types.container -> Netcgi.cgi -> unit) -> Netplex_types.processor
ocamlnet-4.1.2/doc/html-main/type_Netsys_gssapi.GSSAPI.html0000644000175000017500000004367312731530352022164 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.GSSAPI sig
  type credential
  type context
  type name
  exception Credential of Netsys_gssapi.GSSAPI.credential
  exception Context of Netsys_gssapi.GSSAPI.context
  exception Name of Netsys_gssapi.GSSAPI.name
  class type gss_api =
    [Netsys_gssapi.GSSAPI.credential, Netsys_gssapi.GSSAPI.name,
     Netsys_gssapi.GSSAPI.context]
    poly_gss_api
  val interface : Netsys_gssapi.GSSAPI.gss_api
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.create_full_info-c.html0000644000175000017500000004265012731530352024032 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.create_full_info

Class Nethttpd_types.create_full_info

class create_full_info : response_status_code:int -> request_body_rejected:bool -> output_header:Nethttp.http_header -> output_body_size:int64 -> request_info -> full_info
Creates a full_info object by adding to a request_info object

ocamlnet-4.1.2/doc/html-main/Rpc_portmapper_clnt.Make'PMAP.V2.html0000644000175000017500000005421212731530352023176 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt.Make'PMAP.V2

Module Rpc_portmapper_clnt.Make'PMAP.V2

module V2: sig .. end

type t = U'C.t 
val _program : Rpc_program.t
val pmapproc_null : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res
val pmapproc_null'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res) -> unit) -> unit
val pmapproc_set : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res
val pmapproc_set'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res) -> unit) -> unit
val pmapproc_unset : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res
val pmapproc_unset'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res) -> unit) -> unit
val pmapproc_getport : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res
val pmapproc_getport'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res) -> unit) -> unit
val pmapproc_dump : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res
val pmapproc_dump'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res) -> unit) -> unit
val pmapproc_callit : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res
val pmapproc_callit'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res) -> unit) -> unit
ocamlnet-4.1.2/doc/html-main/type_Netsys_sem.html0000644000175000017500000005167512731530352020476 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sem sig
  val have_anon_semaphores : unit -> bool
  val sem_value_max : int
  val sem_size : int
  type container
  type prefix = string
  type anon_semaphore
  type sem_open_flag = Netsys_posix.sem_open_flag = SEM_O_CREAT | SEM_O_EXCL
  val container : Netsys_sem.prefix -> Netsys_sem.container
  val create_container : Netsys_sem.prefix -> Netsys_sem.container
  val prefix : Netsys_sem.container -> Netsys_sem.prefix
  val drop : Netsys_sem.container -> unit
  val unlink : Netsys_sem.prefix -> unit
  val sem_init :
    Netsys_sem.container ->
    Netsys_types.memory -> int -> bool -> int -> Netsys_sem.anon_semaphore
  val sem_destroy : Netsys_sem.container -> Netsys_sem.anon_semaphore -> unit
  val as_sem :
    Netsys_sem.container ->
    Netsys_types.memory -> int -> Netsys_sem.anon_semaphore
  val sem_getvalue : Netsys_sem.anon_semaphore -> int
  val sem_post : Netsys_sem.anon_semaphore -> unit
  type sem_wait_behavior =
    Netsys_posix.sem_wait_behavior =
      SEM_WAIT_BLOCK
    | SEM_WAIT_NONBLOCK
  val sem_wait :
    Netsys_sem.anon_semaphore -> Netsys_sem.sem_wait_behavior -> unit
  module Debug : sig val enable : bool Pervasives.ref end
  val force_emulation : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.digest_auth_handler.html0000644000175000017500000004104212731530352025310 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.digest_auth_handler #Nethttp_client.key_handler -> Nethttp_client.auth_handlerocamlnet-4.1.2/doc/html-main/Uq_engines_compat.signal_engine-c.html0000644000175000017500000004322312731530352023753 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.signal_engine

Class Uq_engines_compat.signal_engine

class ['a] signal_engine : Unixqueue.event_system -> object .. end
Inherits
method signal : 'a final_state -> unit
ocamlnet-4.1.2/doc/html-main/Netstring_str.Debug.html0000644000175000017500000004160212731530352021163 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstring_str.Debug

Module Netstring_str.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi.mime_argument.html0000644000175000017500000004126112731530352025230 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi.mime_argument ?work_around_backslash_bug:bool ->
string -> Netmime.mime_message -> Netcgi1_compat.Netcgi_types.cgi_argument
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.processor_factory.html0000644000175000017500000004200712731530352024742 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.processor_factory object
  method create_processor :
    Netplex_types.controller_config ->
    Netplex_types.config_file ->
    Netplex_types.address -> Netplex_types.processor
  method name : string
end
ocamlnet-4.1.2/doc/html-main/Netchannels.enhanced_raw_in_channel-c.html0000644000175000017500000004434212731530352024552 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.enhanced_raw_in_channel

Class type Netchannels.enhanced_raw_in_channel

class type enhanced_raw_in_channel = object .. end
Defines private methods reading text line by line
Inherits
method private enhanced_input_line : unit -> string
An improved implementation of input_line that uses the buffer
method private enhanced_input : Bytes.t -> int -> int -> input_result
Works similar to input, but distinguishes between normal data and end-of-line separators. The latter are returned as `Separator s. When normal data is found, it is copied to the string, and `Data n is returned to indicate that n bytes were copied.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.msync_engine.html0000644000175000017500000004204012731530352023101 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.msync_engine '#Uq_engines.engine list ->
('-> '-> 'b) -> '-> Unixqueue.event_system -> ['b] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Uq_gtk.gtk_event_system.html0000644000175000017500000004103612731530352023156 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_gtk.gtk_event_system ?run:Uq_gtk.runner -> unit -> Unixqueue.event_systemocamlnet-4.1.2/doc/html-main/type_Nethttp_client_conncache.connection_cache.html0000644000175000017500000004434112731530352026603 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client_conncache.connection_cache object
  method close_all : unit -> unit
  method close_connection : Unix.file_descr -> unit
  method find_inactive_connection :
    Nethttp_client_conncache.peer ->
    Nethttp_client_conncache.transport_layer_id ->
    Unix.file_descr * Nethttp_client_conncache.inactive_data
  method find_my_connections : <  > -> Unix.file_descr list
  method get_connection_state :
    Unix.file_descr -> Nethttp_client_conncache.conn_state
  method set_connection_state :
    Unix.file_descr ->
    Nethttp_client_conncache.peer ->
    Nethttp_client_conncache.conn_state -> unit
end
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_modes.html0000644000175000017500000004523612731530352021354 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes

Module Netsys_crypto_modes

module Netsys_crypto_modes: sig .. end
Helpers for crypto modes

module Symmetric_cipher: sig .. end
module type CIPHERS = sig .. end
module Bundle: 
Bundle a list of ciphers as crypto module
module Add_modes: 
Returns a new crypto module where missing modes are added for all ECB ciphers.
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_gssapi.html0000644000175000017500000004415312731530352022454 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_gssapi sig
  val scram_mech : Netsys_gssapi.oid
  class type client_key_ring =
    object
      method default_user_name : string option
      method password_of_user_name : string -> string
    end
  class type server_key_verifier =
    object method scram_credentials : string -> Netmech_scram.credentials end
  val scram_gss_api :
    ?client_key_ring:Netmech_scram_gssapi.client_key_ring ->
    ?server_key_verifier:Netmech_scram_gssapi.server_key_verifier ->
    Netmech_scram.profile -> (module Netsys_gssapi.GSSAPI)
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_server.socket_config.html0000644000175000017500000004255312731530352023266 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.socket_config object
  method listen_options : Uq_engines.listen_options
  method multiplexing :
    dbg_name:string Pervasives.ref ->
    close_inactive_descr:bool ->
    Rpc.protocol ->
    Unix.file_descr ->
    Unixqueue.event_system ->
    Rpc_transport.rpc_multiplex_controller Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/Netplex_cenv.LEVER.html0000644000175000017500000004531612731530352020605 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.LEVER

Module type Netplex_cenv.LEVER

module type LEVER = sig .. end

type s 
argument type
type r 
result type
type t = s -> r 
val register : Netplex_types.controller ->
(Netplex_types.controller -> t) -> t
let reg_lever = register ctrl raw_lever: Registers raw_lever in the controller ctrl, so one can call reg_lever to activate it. For example:

 
           module LT = struct type s = unit type r = int end
           module L = Make_lever(LT)
         
           let get_num_services =
             L.register ctrl (fun ctrl () -> List.length ctrl#services)
        

The registration must be done in controller context, e.g. in the pre_start_hook of a container.

From the running container, one can now call:

 get_num_services() 

to get the current length of the ctrl#services list.

ocamlnet-4.1.2/doc/html-main/type_Netsys_polypipe.Debug.html0000644000175000017500000004101012731530352022556 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_polypipe.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Nethttpd_intro.html0000644000175000017500000006424512731530352020306 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_intro

Nethttpd_intro


Overview over the HTTP daemon

This library implements an HTTP 1.1 server. Because it is a library and not a stand-alone server like Apache, it can be used in very flexible ways. The disadvantage is that the user of the library must do more to get a running program than just configuring the daemon.

The daemon has five modules:

  • Nethttpd_types is just a module with common type definitions used by the other modules
  • Nethttpd_kernel is the implementation of the HTTP protocol. If we talk about the "kernel" we mean this module. The kernel has two interface sides: There is the "socket side" and the "message side" that are connected by bidirectional data flow. The task of the kernel is to decode input received by the socket side and to deliver it to a consumer on the message side, and conversely to encode input coming in through the message side and to send it to the socket. The kernel is a quite low-level module; the socket is accessed in a multiplexing-compatible style, and the messages are sequences of tokens like "status line", "header", "body chunk" and so on. Normally a user of the daemon does not program the kernel directly. It is, however, possible to pass certain configuration options to the kernel even if an encapsulation is used.
  • Nethttpd_reactor is an encapsulation of the kernel with a nicer interface. An instance of the reactor processes, like the kernel, only a single HTTP connection. It is used as follows: The user of the reactor pulls the arriving HTTP requests from the reactor, processes them, and writes the responses back to the reactor. This means that the requests are processed in a strictly sequential way. The reactor hides the details of the HTTP protocol. The reactor is able to perform socket input and output at the same time, i.e. when the response is sent to the client the next request(s) can already be read (pipelining). The reactor can be configured such that buffering of requests and responses is avoided, even if large messages are transferred. As mentioned, the reactor can only deal with one connection at the same time. In order to serve several connections, one must use multi-threading.
  • Nethttpd_engine is another encapsulation of the kernel. It is event-based, and this makes it possible that several instances can work at the same time without using multi-threading. The user of the engine is called back when the beginning of the next HTTP request arrives and at certain other events. The user processes the event, and generates the response. The engine is a highly efficient implementation of an HTTP server, but there are also drawbacks, so user may feel more comfortable with the reactor. Especially, the engine needs large buffers for input and output (there is an idea to use helper threads to avoid these buffers, but this has not been implemented yet). Of course, the engine also supports pipelining.
  • Nethttpd_services has functions to compose complex service functions from simpler ones. In particular, one can configure name- or IP-based virtual hosting, one can bind services to URLs, and one can define static file serving, directory listings, and dynamic services. It is quite easy to turn a Netcgi program into a dynamic service for Nethttpd.
  • Nethttpd_plex provides nice integration into netplex. Most features provided by Nethttpd_services can be activated by simply referencing them in the netplex configuration file.
It is also important to mention what Nethttpd does not include:

  • There is no function to create the socket, and to accept connections.
  • There is no function to manage threads or subprocesses
Ocamlnet provides this in the netplex library.

Suggested strategy

First, look at Nethttpd_services. This module allows the user to define the services of the web server. For example, the following code defines a single host with an URL space:

let fs_spec =
  { file_docroot = "/data/docroot";
    file_uri = "/";
    file_suffix_types = [ "txt", "text/plain";
                          "html", "text/html" ];
    file_default_type = "application/octet-stream";
    file_options = [ `Enable_gzip;
                     `Enable_listings simple_listing
                   ]
  }

let srv =
  host_distributor
    [ default_host ~pref_name:"localhost" ~pref_port:8765 (),
      uri_distributor
        [ "*", (options_service());
          "/files", (file_service fs_spec);
          "/service", (dynamic_service
                           { dyn_handler = process_request;
                             dyn_activation = std_activation `Std_activation_buffered;
                             dyn_uri = Some "/service";
                             dyn_translator = file_translator fs_spec;
                             dyn_accept_all_conditionals = false
                           })
        ]
    ]

The /files path is bound to a static service, i.e. the files found in the directory /data/docroot can be accessed over the web. The record fs_spec configures the static service.

The /service path is bound to a dynamic service, i.e. the requests are processed by the user-defined function process_request. This function is very similar to the request processors used in Netcgi.

The symbolic * path is only bound for the OPTIONS method. This is recommended, because clients can use this method to find out the capabilities of the server.

Second, select an encapsulation. As mentioned, the reactor is much simpler to use, but you must take a multi-threaded approach to serve multiple connections simultaneously. The engine is more efficient, but may use more memory (unless it is only used for static pages).

Third, write the code to create the socket and to accept connections. For the reactor, you should do this in a multi-threaded way (but multi-processing is also possible). For the engine, you should do this in an event-based way.

Now, just call Nethttpd_reactor.process_connection or Nethttpd_engine.process_connection, and pass the socket descriptor as argument. These functions do all the rest.

The Ocamlnet source tarball includes examples for several approaches. Especially look at file_reactor.ml, file_mt_reactor.ml, and file_engine.ml.

Configuration

One of the remaining questions is: How to set all these configuration options.

The user configures the daemon by passing a configuration object. This object has a number of methods that usually return constants, but there are also a few functions, e.g.

  let config : http_reactor_config =
    object
      method config_timeout_next_request = 15.0
      method config_timeout = 300.0
      method config_reactor_synch = `Write
      method config_cgi = Netcgi_env.default_config
      method config_error_response n = "<html>Error " ^ string_of_int n ^ "</html>"
      method config_log_error _ _ _ _ msg =
        printf "Error log: %s\n" msg
      method config_max_reqline_length = 256
      method config_max_header_length = 32768
      method config_max_trailer_length = 32768
      method config_limit_pipeline_length = 5
      method config_limit_pipeline_size = 250000
    end 

Some of the options are interpreted by the encapsulation, and some by the kernel. The object approach has been taken, because it can be arranged that the layers of the daemon correspond to a hierarchy of class types.

The options are documented in the modules where the class types are defined. Some of them are difficult to understand. In doubt, it is recommended to just copy the values found in the examples, because these are quite reasonable for typical usage scenarios.

Linking

In Ocamlnet 3 the nethttpd library can be both referenced as -package nethttpd or -package nethttpd-for-netcgi2 (the latter being an alias). As the netcgi1 library was dropped, there is no reason for nethttpd-for-netcgi1 anymore - this name is now unavailable.
ocamlnet-4.1.2/doc/html-main/type_Netchannels.buffered_trans_channel.html0000644000175000017500000004117312731530352025257 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.buffered_trans_channel ?close_mode:Netchannels.close_mode ->
Netchannels.out_obj_channel -> Netchannels.trans_out_obj_channel
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.logger.html0000644000175000017500000004243612731530352022461 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.logger object
  method log :
    component:string -> level:Netplex_types.level -> message:string -> unit
  method log_subch :
    component:string ->
    subchannel:string -> level:Netplex_types.level -> message:string -> unit
  method reopen : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_transport.html0000644000175000017500000007125412731530352021200 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_transport sig
  type 't result = [ `Error of exn | `Ok of 't ]
  type 't result_eof = [ `End_of_file | `Error of exn | `Ok of 't ]
  type sockaddr = [ `Implied | `Sockaddr of Unix.sockaddr ]
  val string_of_sockaddr : Rpc_transport.sockaddr -> string
  exception Error of string
  type in_rule =
      [ `Accept | `Deny | `Drop | `Reject | `Reject_with of Rpc.server_error ]
  type in_record =
      [ `Accept of Rpc_packer.packed_value
      | `Deny
      | `Drop
      | `Reject of Rpc_packer.packed_value
      | `Reject_with of Rpc_packer.packed_value * Rpc.server_error ]
  class type rpc_multiplex_controller =
    object
      method abort_rw : unit -> unit
      method alive : bool
      method cancel_rd_polling : unit -> unit
      method cancel_shutting_down : unit -> unit
      method event_system : Unixqueue.event_system
      method file_descr : Unix.file_descr option
      method getpeername : Rpc_transport.sockaddr
      method getsockname : Rpc_transport.sockaddr
      method inactivate : unit -> unit
      method peer_user_name : string option
      method protocol : Rpc.protocol
      method read_eof : bool
      method reading : bool
      method set_timeout : notify:(unit -> unit) -> float -> unit
      method start_reading :
        ?peek:(unit -> unit) ->
        ?before_record:(int ->
                        Rpc_transport.sockaddr -> Rpc_transport.in_rule) ->
        when_done:((Rpc_transport.in_record * Rpc_transport.sockaddr)
                   Rpc_transport.result_eof -> unit) ->
        unit -> unit
      method start_shutting_down :
        when_done:(unit Rpc_transport.result -> unit) -> unit -> unit
      method start_writing :
        when_done:(unit Rpc_transport.result -> unit) ->
        Rpc_packer.packed_value -> Rpc_transport.sockaddr -> unit
      method tls_session_props : Nettls_support.tls_session_props option
      method writing : bool
    end
  val stream_rpc_multiplex_controller :
    ?dbg_name:string Pervasives.ref ->
    ?close_inactive_descr:bool ->
    ?preclose:(unit -> unit) ->
    ?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option ->
    role:[ `Client | `Server ] ->
    Unix.file_descr ->
    Unixqueue.event_system -> Rpc_transport.rpc_multiplex_controller
  val datagram_rpc_multiplex_controller :
    ?dbg_name:string Pervasives.ref ->
    ?close_inactive_descr:bool ->
    ?preclose:(unit -> unit) ->
    role:[ `Client | `Server ] ->
    Unix.file_descr ->
    Unixqueue.event_system -> Rpc_transport.rpc_multiplex_controller
  type internal_pipe = Netxdr.xdr_value Netsys_polypipe.polypipe
  val internal_rpc_multiplex_controller :
    ?dbg_name:string Pervasives.ref ->
    ?close_inactive_descr:bool ->
    ?preclose:(unit -> unit) ->
    Rpc_transport.internal_pipe ->
    Rpc_transport.internal_pipe ->
    Unixqueue.event_system -> Rpc_transport.rpc_multiplex_controller
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_ajp.html0000644000175000017500000005110012731530352020367 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_ajp sig
  val arg_parse :
    (Arg.key * Arg.spec * Arg.doc) list ->
    Arg.anon_fun -> Arg.usage_msg -> (string * string) list
  val props_of_file : string -> (string * string) list
  val run :
    ?props:(string * string) list ->
    ?config:Netcgi.config ->
    ?script_name:string ->
    ?allow:(Unix.sockaddr -> bool) ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?exn_handler:Netcgi.exn_handler ->
    ?socket:Unix.file_descr ->
    ?sockaddr:Unix.sockaddr -> ?port:int -> (Netcgi.cgi -> unit) -> unit
  val handle_request :
    ?script_name:string ->
    Netcgi.config ->
    Netcgi.output_type ->
    Netcgi.arg_store ->
    Netcgi.exn_handler ->
    (Netcgi.cgi -> unit) ->
    log:(string -> unit) option ->
    Unix.file_descr -> Netcgi.connection_directive
  val handle_connection :
    Netcgi.config ->
    Netcgi.output_type ->
    Netcgi.arg_store ->
    Netcgi.exn_handler ->
    (Netcgi.cgi -> unit) -> ?script_name:string -> Unix.file_descr -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netoid.html0000644000175000017500000004323712731530352017562 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netoid sig
  type t = int array
  val equal : Netoid.t -> Netoid.t -> bool
  val compare : Netoid.t -> Netoid.t -> int
  val of_string : string -> Netoid.t
  val to_string : Netoid.t -> string
  val of_string_curly : string -> Netoid.t
  val to_string_curly : Netoid.t -> string
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.msync_engine-c.html0000644000175000017500000004263712731530352023637 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.msync_engine

Class Uq_engines_compat.msync_engine

class [['a, 'b]] msync_engine : 'a #engine list -> ('a -> 'b -> 'b) -> 'b -> Unixqueue.event_system -> ['b] engine

ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.DIGESTS.html0000644000175000017500000004766012731530352022515 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.DIGESTS

Module type Netsys_crypto_types.DIGESTS

module type DIGESTS = sig .. end


Cryptographic digests.

Users should not call functions of the provider directly, but use Netsys_digests, or another higher-level layer.

type digest 
Describes a digest
val digests : digest list
returns digests
val find : string -> digest
Returns the digest of this name, or raises Not_found
val name : digest -> string
returns the name of the digest. The name follows the format <uppercasename>-<size>, e.g. "MD5-128", "SHA1-160", "SHA2-256".
val size : digest -> int
returns the size of the hash output (in bytes)
val block_length : digest -> int
the block length (in bytes)
type digest_ctx 
A digest context stores state while digesting data
val create : digest -> digest_ctx
Creates a fresh context
val add : digest_ctx -> Netsys_types.memory -> unit
Adds data
val finish : digest_ctx -> string
Returns the digest
ocamlnet-4.1.2/doc/html-main/Netchannels_crypto.crypto_in_filter-c.html0000644000175000017500000004334112731530352024727 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.crypto_in_filter

Class type Netchannels_crypto.crypto_in_filter

class type crypto_in_filter = object .. end
Encrypt or decrypt data while reading from a channel
Inherits
method supports_aead : bool
Whether the cipher supports authentication, and will provide a MAC
method mac : unit -> string
Get the MAC of the processed data
ocamlnet-4.1.2/doc/html-main/Netmime.basic_mime_header-c.html0000644000175000017500000004442312731530352022512 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.basic_mime_header

Class Netmime.basic_mime_header

class basic_mime_header : (string * string) list -> mime_header
An implementation of mime_header.

The argument is the list of (name,value) pairs of the header.

Example: Create a MIME header with only the field "Content-type":

 let h = new basic_mime_header ["content-type", "text/plain"] 

Example: Set the field "Subject":

 h # update_field "subject" "The value of this field" 

This mime_header implementation bases on a mixture of a Map data structure and a doubly linked list. The efficiency of the operations (n=number of fields; m=average number of values per field; n*m=total number of values):

  • new, set_fields: O(m * n * log n), but the construction of the dictionary is deferred until the first real access
  • field: O(log n)
  • multiple_field: O(log n + m)
  • fields: O(n * m)
  • update_field, update_multiple_field: O(log n + m)
  • delete_field: O(n + m)


ocamlnet-4.1.2/doc/html-main/type_Netchannels.input_channel.html0000644000175000017500000004114712731530352023426 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_channel ?onclose:(unit -> unit) ->
Pervasives.in_channel -> Netchannels.in_obj_channel
ocamlnet-4.1.2/doc/html-main/Nethttp_client.transport_channel_type-c.html0000644000175000017500000004755212731530352025273 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.transport_channel_type

Class type Nethttp_client.transport_channel_type

class type transport_channel_type = object .. end

method identify_conn_by_name : bool
Whether connections must be identified by name, and not by IP address. (Set for TLS connections.)
method setup_e : Unix.file_descr ->
transport_layer_id ->
float ->
exn ->
string ->
int ->
Unixqueue.event_system ->
tls_cache -> Uq_engines.multiplex_controller Uq_engines.engine
setup fd trans tmo tmo_x host port esys tls_cache: Create or configure a communication circuit over the file descriptor fd that can be driven by the returned multiplex controller object. Since OCamlnet-3.8, the method can also return private data for the connection cache.

tmo is the timeout. After inactivity the exception tmo_x must be raised.

host is the name of the machine to connect to. port is the port number. The descriptor fd is already connected to this port, directly or via a proxy.

method continue : Unix.file_descr ->
transport_layer_id ->
float ->
exn ->
string ->
int ->
Unixqueue.event_system -> exn option -> Uq_engines.multiplex_controller
continue is called when an already established circuit needs to be continued. The additional argument contains the stashed TLS session.

Note that the event system can be different now.

If it is not possible to continue, the method may raise Not_found.

method default_port : int option
If set, the Host header omits this port number
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.engine.html0000644000175000017500000004250212731530352021673 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.engine object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : ('Uq_engines.engine -> bool) -> unit
  method state : 'Uq_engines.engine_state
end
ocamlnet-4.1.2/doc/html-main/type_Netglob.local_fsys.html0000644000175000017500000004104212731530352022057 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.local_fsys ?encoding:Netconversion.encoding -> unit -> Netglob.glob_fsysocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.SCRAM_SHA1_PLUS.html0000644000175000017500000010733712731530352023356 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM_SHA1_PLUS

Module Netmech_scram_sasl.SCRAM_SHA1_PLUS

module SCRAM_SHA1_PLUS: Netsys_sasl_types.SASL_MECHANISM 
SCRAM with SHA1_PLUS profile

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.internal_environment-c.html0000644000175000017500000004407212731530352025265 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.internal_environment

Class type Nethttpd_reactor.internal_environment

class type internal_environment = object .. end
For private use only
Inherits
  • extended_environment

method unlock : unit -> unit
method req_method : Nethttp.http_method
method response : Nethttpd_kernel.http_response
method log_access : unit -> unit
ocamlnet-4.1.2/doc/html-main/type_Netsys_posix.html0000644000175000017500000021544512731530352021051 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_posix sig
  val int_of_file_descr : Unix.file_descr -> int
  val file_descr_of_int : int -> Unix.file_descr
  external sysconf_open_max : unit -> int = "netsys_sysconf_open_max"
  external get_nonblock : Unix.file_descr -> bool = "netsys_get_nonblock"
  external fchdir : Unix.file_descr -> unit = "netsys_fchdir"
  external fdopendir : Unix.file_descr -> Unix.dir_handle
    = "netsys_fdopendir"
  external realpath : string -> string = "netsys_realpath"
  external getpgid : int -> int = "netsys_getpgid"
  val getpgrp : unit -> int
  external setpgid : int -> int -> unit = "netsys_setpgid"
  val setpgrp : unit -> unit
  external tcgetpgrp : Unix.file_descr -> int = "netsys_tcgetpgrp"
  external tcsetpgrp : Unix.file_descr -> int -> unit = "netsys_tcsetpgrp"
  external ctermid : unit -> string = "netsys_ctermid"
  external ttyname : Unix.file_descr -> string = "netsys_ttyname"
  external getsid : int -> int = "netsys_getsid"
  val with_tty : (Unix.file_descr -> unit) -> unit
  val tty_read_password : ?tty:Unix.file_descr -> string -> string
  external posix_openpt : bool -> Unix.file_descr = "netsys_posix_openpt"
  external grantpt : Unix.file_descr -> unit = "netsys_grantpt"
  external unlockpt : Unix.file_descr -> unit = "netsys_unlockpt"
  external ptsname : Unix.file_descr -> string = "netsys_ptsname"
  type node_type =
      S_IFREG
    | S_IFCHR of int
    | S_IFBLK of int
    | S_IFIFO
    | S_IFSOCK
  external mknod : string -> int -> Netsys_posix.node_type -> unit
    = "netsys_mknod"
  external setreuid : int -> int -> unit = "netsys_setreuid"
  external setregid : int -> int -> unit = "netsys_setregid"
  external initgroups : string -> int -> unit = "netsys_initgroups"
  val have_at : unit -> bool
  val at_fdcwd : Unix.file_descr
  type at_flag =
      AT_EACCESS
    | AT_SYMLINK_NOFOLLOW
    | AT_SYMLINK_FOLLOW
    | AT_REMOVEDIR
  val openat :
    Unix.file_descr ->
    string -> Unix.open_flag list -> Unix.file_perm -> Unix.file_descr
  val faccessat :
    Unix.file_descr ->
    string ->
    Unix.access_permission list -> Netsys_posix.at_flag list -> unit
  val mkdirat : Unix.file_descr -> string -> int -> unit
  val renameat :
    Unix.file_descr -> string -> Unix.file_descr -> string -> unit
  val linkat :
    Unix.file_descr ->
    string -> Unix.file_descr -> string -> Netsys_posix.at_flag list -> unit
  val unlinkat :
    Unix.file_descr -> string -> Netsys_posix.at_flag list -> unit
  val symlinkat : string -> Unix.file_descr -> string -> unit
  val mkfifoat : Unix.file_descr -> string -> int -> unit
  val readlinkat : Unix.file_descr -> string -> string
  type poll_array
  type poll_req_events
  type poll_act_events
  type poll_cell = {
    mutable poll_fd : Unix.file_descr;
    mutable poll_req_events : Netsys_posix.poll_req_events;
    mutable poll_act_events : Netsys_posix.poll_act_events;
  }
  val have_poll : unit -> bool
  val poll_req_events : bool -> bool -> bool -> Netsys_posix.poll_req_events
  val poll_req_triple : Netsys_posix.poll_req_events -> bool * bool * bool
  val poll_null_events : unit -> Netsys_posix.poll_act_events
  val poll_result : Netsys_posix.poll_act_events -> bool
  val poll_rd_result : Netsys_posix.poll_act_events -> bool
  val poll_wr_result : Netsys_posix.poll_act_events -> bool
  val poll_pri_result : Netsys_posix.poll_act_events -> bool
  val poll_err_result : Netsys_posix.poll_act_events -> bool
  val poll_hup_result : Netsys_posix.poll_act_events -> bool
  val poll_nval_result : Netsys_posix.poll_act_events -> bool
  val create_poll_array : int -> Netsys_posix.poll_array
  val set_poll_cell :
    Netsys_posix.poll_array -> int -> Netsys_posix.poll_cell -> unit
  val get_poll_cell :
    Netsys_posix.poll_array -> int -> Netsys_posix.poll_cell
  val blit_poll_array :
    Netsys_posix.poll_array ->
    int -> Netsys_posix.poll_array -> int -> int -> unit
  val poll_array_length : Netsys_posix.poll_array -> int
  val poll : Netsys_posix.poll_array -> int -> float -> int
  val restarting_poll : Netsys_posix.poll_array -> int -> float -> int
  val poll_single : Unix.file_descr -> bool -> bool -> bool -> float -> bool
  val int_of_req_events : Netsys_posix.poll_req_events -> int
  val int_of_act_events : Netsys_posix.poll_act_events -> int
  val req_events_of_int : int -> Netsys_posix.poll_req_events
  val act_events_of_int : int -> Netsys_posix.poll_act_events
  val const_rd_event : int
  val const_wr_event : int
  val const_pri_event : int
  val const_err_event : int
  val const_hup_event : int
  val const_nval_event : int
  type event_aggregator
  type event_source
  val have_event_aggregation : unit -> bool
  val create_event_aggregator : bool -> Netsys_posix.event_aggregator
  val destroy_event_aggregator : Netsys_posix.event_aggregator -> unit
  val fd_event_source :
    Unix.file_descr ->
    Netsys_posix.poll_req_events -> Netsys_posix.event_source
  val modify_fd_event_source :
    Netsys_posix.event_source -> Netsys_posix.poll_req_events -> unit
  val get_fd_of_event_source : Netsys_posix.event_source -> Unix.file_descr
  val act_events_of_event_source :
    Netsys_posix.event_source -> Netsys_posix.poll_act_events
  val add_event_source :
    Netsys_posix.event_aggregator -> Netsys_posix.event_source -> unit
  val del_event_source :
    Netsys_posix.event_aggregator -> Netsys_posix.event_source -> unit
  val interrupt_event_aggregator : Netsys_posix.event_aggregator -> unit
  val push_event_updates : Netsys_posix.event_aggregator -> unit
  val poll_event_sources :
    Netsys_posix.event_aggregator -> float -> Netsys_posix.event_source list
  val event_aggregator_fd : Netsys_posix.event_aggregator -> Unix.file_descr
  class type post_fork_handler =
    object method name : string method run : unit -> unit end
  val register_post_fork_handler : Netsys_posix.post_fork_handler -> unit
  val remove_post_fork_handler : Netsys_posix.post_fork_handler -> unit
  val run_post_fork_handlers : unit -> unit
  type wd_spec = Wd_keep | Wd_chdir of string | Wd_fchdir of Unix.file_descr
  type pg_spec =
      Pg_keep
    | Pg_new_bg_group
    | Pg_new_fg_group
    | Pg_join_group of int
  type fd_action =
      Fda_close of Unix.file_descr
    | Fda_close_ignore of Unix.file_descr
    | Fda_close_except of bool array
    | Fda_dup2 of Unix.file_descr * Unix.file_descr
  type sig_action =
      Sig_default of int
    | Sig_ignore of int
    | Sig_mask of int list
  val spawn :
    ?chdir:Netsys_posix.wd_spec ->
    ?pg:Netsys_posix.pg_spec ->
    ?fd_actions:Netsys_posix.fd_action list ->
    ?sig_actions:Netsys_posix.sig_action list ->
    ?env:string array ->
    ?no_posix_spawn:bool -> string -> string array -> int
  type not_event
  val create_event : unit -> Netsys_posix.not_event
  external set_nonblock_event : Netsys_posix.not_event -> unit
    = "netsys_set_nonblock_not_event"
  val get_event_fd : Netsys_posix.not_event -> Unix.file_descr
  external set_event : Netsys_posix.not_event -> unit
    = "netsys_set_not_event"
  external wait_event : Netsys_posix.not_event -> unit
    = "netsys_wait_not_event"
  external consume_event : Netsys_posix.not_event -> unit
    = "netsys_consume_not_event"
  val destroy_event : Netsys_posix.not_event -> unit
  val report_signal_as_event : Netsys_posix.not_event -> int -> unit
  type watched_subprocess
  val watch_subprocess :
    int -> int -> bool -> Unix.file_descr * Netsys_posix.watched_subprocess
  val ignore_subprocess : Netsys_posix.watched_subprocess -> unit
  val forget_subprocess : Netsys_posix.watched_subprocess -> unit
  val get_subprocess_status :
    Netsys_posix.watched_subprocess -> Unix.process_status option
  val kill_subprocess : int -> Netsys_posix.watched_subprocess -> unit
  val killpg_subprocess : int -> Netsys_posix.watched_subprocess -> unit
  val kill_all_subprocesses : int -> bool -> bool -> unit
  val killpg_all_subprocesses : int -> bool -> unit
  val install_subprocess_handler : unit -> unit
  val register_subprocess_handler : unit -> unit
  type level = Netlog.level
  type syslog_facility =
      [ `Authpriv
      | `Cron
      | `Daemon
      | `Default
      | `Ftp
      | `Kern
      | `Local0
      | `Local1
      | `Local2
      | `Local3
      | `Local4
      | `Local5
      | `Local6
      | `Local7
      | `Lpr
      | `Mail
      | `News
      | `Syslog
      | `User
      | `Uucp ]
  type syslog_option = [ `Cons | `Ndelay | `Nowait | `Odelay | `Pid ]
  val openlog :
    string option ->
    Netsys_posix.syslog_option list -> Netsys_posix.syslog_facility -> unit
  val syslog :
    Netsys_posix.syslog_facility -> Netsys_posix.level -> string -> unit
  val closelog : unit -> unit
  external fsync : Unix.file_descr -> unit = "netsys_fsync"
  external fdatasync : Unix.file_descr -> unit = "netsys_fdatasync"
  external have_fadvise : unit -> bool = "netsys_have_posix_fadvise"
  type advice =
      POSIX_FADV_NORMAL
    | POSIX_FADV_SEQUENTIAL
    | POSIX_FADV_RANDOM
    | POSIX_FADV_NOREUSE
    | POSIX_FADV_WILLNEED
    | POSIX_FADV_DONTNEED
    | FADV_NORMAL
    | FADV_SEQUENTIAL
    | FADV_RANDOM
    | FADV_NOREUSE
    | FADV_WILLNEED
    | FADV_DONTNEED
  external fadvise :
    Unix.file_descr -> int64 -> int64 -> Netsys_posix.advice -> unit
    = "netsys_fadvise"
  external have_fallocate : unit -> bool = "netsys_have_posix_fallocate"
  external fallocate : Unix.file_descr -> int64 -> int64 -> unit
    = "netsys_fallocate"
  external have_posix_shm : unit -> bool = "netsys_have_posix_shm"
  type shm_open_flag =
      SHM_O_RDONLY
    | SHM_O_RDWR
    | SHM_O_CREAT
    | SHM_O_EXCL
    | SHM_O_TRUNC
  external shm_open :
    string -> Netsys_posix.shm_open_flag list -> int -> Unix.file_descr
    = "netsys_shm_open"
  external shm_unlink : string -> unit = "netsys_shm_unlink"
  val shm_create : string -> int -> Unix.file_descr * string
  val have_named_posix_semaphores : unit -> bool
  val have_anon_posix_semaphores : unit -> bool
  val have_posix_semaphores : unit -> bool
  val sem_value_max : int
  val sem_size : int
  type sem_kind = [ `Anonymous | `Named ]
  type 'sem_kind semaphore
  type named_semaphore = [ `Named ] Netsys_posix.semaphore
  type anon_semaphore = [ `Anonymous ] Netsys_posix.semaphore
  type sem_open_flag = SEM_O_CREAT | SEM_O_EXCL
  val sem_open :
    string ->
    Netsys_posix.sem_open_flag list ->
    int -> int -> Netsys_posix.named_semaphore
  val sem_close : Netsys_posix.named_semaphore -> unit
  val sem_unlink : string -> unit
  val sem_create : string -> int -> Netsys_posix.named_semaphore * string
  val sem_init :
    Netsys_types.memory -> int -> bool -> int -> Netsys_posix.anon_semaphore
  val sem_destroy : Netsys_posix.anon_semaphore -> unit
  val as_sem : Netsys_types.memory -> int -> Netsys_posix.anon_semaphore
  val sem_getvalue : 'kind Netsys_posix.semaphore -> int
  val sem_post : 'kind Netsys_posix.semaphore -> unit
  type sem_wait_behavior = SEM_WAIT_BLOCK | SEM_WAIT_NONBLOCK
  val sem_wait :
    'kind Netsys_posix.semaphore -> Netsys_posix.sem_wait_behavior -> unit
  type langinfo = {
    nl_CODESET : string;
    nl_D_T_FMT : string;
    nl_D_FMT : string;
    nl_T_FMT : string;
    nl_T_FMT_AMPM : string;
    nl_AM_STR : string;
    nl_PM_STR : string;
    nl_DAY_1 : string;
    nl_DAY_2 : string;
    nl_DAY_3 : string;
    nl_DAY_4 : string;
    nl_DAY_5 : string;
    nl_DAY_6 : string;
    nl_DAY_7 : string;
    nl_ABDAY_1 : string;
    nl_ABDAY_2 : string;
    nl_ABDAY_3 : string;
    nl_ABDAY_4 : string;
    nl_ABDAY_5 : string;
    nl_ABDAY_6 : string;
    nl_ABDAY_7 : string;
    nl_MON_1 : string;
    nl_MON_2 : string;
    nl_MON_3 : string;
    nl_MON_4 : string;
    nl_MON_5 : string;
    nl_MON_6 : string;
    nl_MON_7 : string;
    nl_MON_8 : string;
    nl_MON_9 : string;
    nl_MON_10 : string;
    nl_MON_11 : string;
    nl_MON_12 : string;
    nl_ABMON_1 : string;
    nl_ABMON_2 : string;
    nl_ABMON_3 : string;
    nl_ABMON_4 : string;
    nl_ABMON_5 : string;
    nl_ABMON_6 : string;
    nl_ABMON_7 : string;
    nl_ABMON_8 : string;
    nl_ABMON_9 : string;
    nl_ABMON_10 : string;
    nl_ABMON_11 : string;
    nl_ABMON_12 : string;
    nl_ERA : string;
    nl_ERA_D_FMT : string;
    nl_ERA_D_T_FMT : string;
    nl_ERA_T_FMT : string;
    nl_ALT_DIGITS : string;
    nl_RADIXCHAR : string;
    nl_THOUSEP : string;
    nl_YESEXPR : string;
    nl_NOEXPR : string;
    nl_CRNCYSTR : string;
  }
  val query_langinfo : string -> Netsys_posix.langinfo
  type timespec = float * int
  external nanosleep :
    Netsys_posix.timespec -> Netsys_posix.timespec Pervasives.ref -> unit
    = "netsys_nanosleep"
  type clock_id
  type clock =
      CLOCK_REALTIME
    | CLOCK_MONOTONIC
    | CLOCK_ID of Netsys_posix.clock_id
  external clock_gettime : Netsys_posix.clock -> Netsys_posix.timespec
    = "netsys_clock_gettime"
  external clock_settime :
    Netsys_posix.clock -> Netsys_posix.timespec -> unit
    = "netsys_clock_settime"
  external clock_getres : Netsys_posix.clock -> Netsys_posix.timespec
    = "netsys_clock_getres"
  external clock_getcpuclockid : int -> Netsys_posix.clock_id
    = "netsys_clock_getcpuclockid"
  type posix_timer
  type timer_expiration =
      TEXP_NONE
    | TEXP_EVENT of Netsys_posix.not_event
    | TEXP_EVENT_CREATE
    | TEXP_SIGNAL of int
  val have_posix_timer : unit -> bool
  val timer_create :
    Netsys_posix.clock ->
    Netsys_posix.timer_expiration -> Netsys_posix.posix_timer
  val timer_settime :
    Netsys_posix.posix_timer ->
    bool -> Netsys_posix.timespec -> Netsys_posix.timespec -> unit
  val timer_gettime : Netsys_posix.posix_timer -> Netsys_posix.timespec
  val timer_delete : Netsys_posix.posix_timer -> unit
  val timer_event : Netsys_posix.posix_timer -> Netsys_posix.not_event
  val have_ioprio : unit -> bool
  type ioprio_target =
      Ioprio_process of int
    | Ioprio_pgrp of int
    | Ioprio_user of int
  type ioprio = Noprio | Real_time of int | Best_effort of int | Idle
  external ioprio_get : Netsys_posix.ioprio_target -> Netsys_posix.ioprio
    = "netsys_ioprio_get"
  external ioprio_set :
    Netsys_posix.ioprio_target -> Netsys_posix.ioprio -> unit
    = "netsys_ioprio_set"
  module Debug : sig val enable : bool Pervasives.ref end
  external get_event_fd_nodup : Netsys_posix.not_event -> Unix.file_descr
    = "netsys_get_not_event_fd_nodup"
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_digests.digest_ctx.html0000644000175000017500000004302612731530352023477 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_digests.digest_ctx object
  method add_memory : Netsys_types.memory -> unit
  method add_subbytes : Bytes.t -> int -> int -> unit
  method add_substring : string -> int -> int -> unit
  method add_tstring : Netsys_types.tstring -> int -> int -> unit
  method finish : unit -> string
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.http_call.html0000644000175000017500000006203312731530352023270 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.http_call object
  method assoc_multi_req_header : string -> string list
  method assoc_multi_resp_header : string -> string list
  method assoc_req_header : string -> string
  method assoc_resp_header : string -> string
  method auth_status : unit Nethttp_client.auth_status
  method dest_status : unit -> string * int * string
  method effective_request_uri : string
  method empty_path_replacement : string
  method get_host : unit -> string
  method get_path : unit -> string
  method get_port : unit -> int
  method get_reconnect_mode :
    Nethttp_client.http_call Nethttp_client.how_to_reconnect
  method get_redirect_mode :
    Nethttp_client.http_call Nethttp_client.how_to_redirect
  method get_req_body : unit -> string
  method get_req_header : unit -> (string * string) list
  method get_req_method : unit -> string
  method get_resp_body : unit -> string
  method get_resp_header : unit -> (string * string) list
  method get_uri : unit -> string
  method gssapi_props : Netsys_gssapi.client_props option
  method has_req_body : bool
  method has_resp_body : bool
  method is_idempotent : bool
  method is_proxy_allowed : unit -> bool
  method is_served : bool
  method max_response_body_length : int64
  method no_proxy : unit -> unit
  method private_api : Nethttp_client.private_api
  method proxy_enabled : bool
  method proxy_use_connect : bool
  method request_body : Netmime.mime_body
  method request_header : Nethttp_client.header_kind -> Netmime.mime_header
  method request_method : string
  method request_uri : string
  method response_body : Netmime.mime_body
  method response_body_storage : Nethttp_client.response_body_storage
  method response_header : Netmime.mime_header
  method response_protocol : string
  method response_status : Nethttp.http_status
  method response_status_code : int
  method response_status_text : string
  method same_call : unit -> Nethttp_client.http_call
  method set_accept_encoding : unit -> unit
  method set_chunked_request : unit -> unit
  method set_expect_handshake : unit -> unit
  method set_max_response_body_length : int64 -> unit
  method set_proxy_enabled : bool -> unit
  method set_reconnect_mode :
    Nethttp_client.http_call Nethttp_client.how_to_reconnect -> unit
  method set_redirect_mode :
    Nethttp_client.http_call Nethttp_client.how_to_redirect -> unit
  method set_req_header : string -> string -> unit
  method set_request_body : Netmime.mime_body -> unit
  method set_request_device : (unit -> Uq_io.in_device) -> unit
  method set_request_header : Netmime.mime_header -> unit
  method set_request_uri : string -> unit
  method set_response_body_storage :
    Nethttp_client.response_body_storage -> unit
  method set_transport_layer : Nethttp_client.transport_layer_id -> unit
  method status : Nethttp_client.status
  method tls_session_props : Nettls_support.tls_session_props option
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_semaphore.html0000644000175000017500000004313712731530352022021 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_semaphore sig
  val plugin : Netplex_types.plugin
  val increment : string -> int64
  val decrement : ?wait:bool -> string -> int64
  val get : string -> int64
  val create : ?protected:bool -> string -> int64 -> bool
  val destroy : string -> unit
  val ctrl_increment : string -> Netplex_types.container_id -> int64
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_krb5_sasl.html0000644000175000017500000004277112731530352021672 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_krb5_sasl sig
  module Krb5_gs1 :
    functor (GSS : Netsys_gssapi.GSSAPI-> Netsys_sasl_types.SASL_MECHANISM
  module Krb5_gs2 :
    functor (GSS : Netsys_gssapi.GSSAPI-> Netsys_sasl_types.SASL_MECHANISM
  module Krb5_gs2_profile : Netmech_gs2_sasl.PROFILE
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_auth_local.html0000644000175000017500000004143012731530352021250 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_auth_local sig
  val server_auth_method : unit -> Rpc_server.auth_method
  val get_peer_credentials : Unix.file_descr -> int * int
end
ocamlnet-4.1.2/doc/html-main/Rpc_portmapper_clnt.html0000644000175000017500000004264312731530352021314 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt

Module Rpc_portmapper_clnt

module Rpc_portmapper_clnt: sig .. end

module Make'PMAP: 
functor (U'C : Rpc_client_pre.USE_CLIENT) -> sig .. end
ocamlnet-4.1.2/doc/html-main/Nethttpd_kernel.http_response-c.html0000644000175000017500000005634512731530352023551 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_response

Class type Nethttpd_kernel.http_response

class type http_response = object .. end
Encapsultation of the HTTP response for a single request

Represents the action of sending the response

This class has an internal queue of response tokens that are not yet processed. One can easily add new tokens to the end of the queue (send).

The class is responsible for determining the transfer encoding:

  • When the HTTP version is 1.0, the encoding is always "identity", and the connection will be closed after the response.
  • When the HTTP version is 1.1, and there is a Content-length header, the encoding will be selected as "identity". It is checked whether the body has really this length. If too short, it is suggested to close the connection. If too long, the extra part of the message is silently dropped.
  • When the HTTP version is 1.1, and there is no Content-length header, the encoding will be selected as "chunked".
Currently, the TE request header is not taken into account. The trailer is always empty.

The following headers are set (or removed) by this class:

  • Transfer-Encoding
  • Trailer
  • Date
  • Connection
  • Upgrade
  • Server (it is appended to this field)
Responses for HEAD requests have the special behaviour that the body is silently dropped. The calculation of header fields is not affected by this. This means that HEAD can be easily implemented by doing the same as for GET.

Responses for other requests that must not include a body must set Content-Length to 0.

method state : resp_state
Reports the state. The initial state is `Inhibited
method bidirectional_phase : bool
The bidrectional phase starts after "100 Continue" has been sent to the client, and stops when the response body begins. The bidirectional phase is special for the calculation of timeout values (input determines the timeout although the response has started).
method send : resp_token -> unit
Add token to the end of the send queue
method send_queue_empty : bool
Return whether the send queue is empty. When the state is `Inhibited, this method fakes an empty queue.
method protocol : Nethttp.protocol
The HTTP version of the response. This is currently always HTTP/1.1, but maybe we need to fake lower versions for buggy clients. Let's see what comes.
method close_connection : bool
Returns whether the connection should be closed after this response. This flag should be evaluated when the `Resp_end front token has been reached.
method transfer_encoding : transfer_coding
Returns the selected transfer encoding. This is valid after the header has been passed to this object with send.
method front_token : front_token
The first token of the queue, represented as data_chunk. Raises Send_queue_empty when there is currently no front token, or the state is `Inhibited. If there is a front token, it will never have length 0.

Note that Unix_error exceptions can be raised when `Resp_action tokens are processed.

method set_callback : (unit -> unit) -> unit
The function will be called when either set_state changes the state, or when the send queue becomes empty. Note that the callback must never fail, it is called in situations that make it hard to recover from errors.
method body_size : int64
Accumulated size of the response body
method set_state : resp_state -> unit
Sets the state
method advance : int -> unit
Tell this object that n bytes of the front token could be really sent using Unix.write. If this means that the whole front token has been sent, the next token is pulled from the queue and is made the new front token. Otherwise, the data chunk representing the front token is modified such that the position is advanced by n, and the length is reduced by n.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.pseudo_async_out_channel.html0000644000175000017500000004106312731530352027045 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.pseudo_async_out_channel #Netchannels.raw_out_channel -> Uq_engines_compat.async_out_channelocamlnet-4.1.2/doc/html-main/type_Netsys_sem.Debug.html0000644000175000017500000004100312731530352021503 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sem.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netftp_data_endpoint.read_in_record_channel.html0000644000175000017500000004121612731530352027112 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.read_in_record_channel repr:Netftp_data_endpoint.text_data_repr ->
Netchannels.in_obj_channel -> Netftp_data_endpoint.in_record_channel
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_modes.Bundle.html0000644000175000017500000006230512731530352022560 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes.Bundle

Functor Netsys_crypto_modes.Bundle

module Bundle: 
Bundle a list of ciphers as crypto module
Parameters:
C : CIPHERS


Symmetric cryptographic ciphers.

Users should not call functions of the provider directly, but use Netsys_ciphers, or another higher-level layer.

type scipher 
Describes a cipher
val ciphers : scipher list
List of supported ciphers. OCamlnet implements a number of modes anyway, and it is normally only required to implement "ECB" here. If there is special hardware acceleration, though, it is an option to provide accelerated modes too (e.g. some CPUs support AES-GCM specially).
val find : string * string -> scipher
find (name,mode): Looks up a cipher by name and mode, or raises Not_found
val name : scipher -> string
Returns the name. This should follow the convention <uppercasestring>-<size>, e.g. "AES-128" or "TWOFISH-128". The size is normally the key size.
val mode : scipher -> string
Returns the mode. Modes are "ECB", "CBC", "OFB", "CTR", "STREAM", "GCM".

Note that the mode needs not to deal with padding (this is done on a higher level).

val key_lengths : scipher -> (int * int) list
Supported key lengths as pairs min,max. If there is a recommended key length, this should be the first.
val iv_lengths : scipher -> (int * int) list
Supported iv lengths as pairs min,max. If there is a recommended iv length, this should be the first.
val block_constraint : scipher -> int
The buffers used with encrypt/decrypt must have a length that is a multiple of this number. (In ECB mode, this is the block size.)
val supports_aead : scipher -> bool
Whether this cipher integrates authentication
type scipher_ctx 
A cipher context stores processing data while encrypting or decrypting data
val create : scipher ->
string -> scipher_ctx
create c key: create a new cipher context for key. If not set, the initialization vector is zero, and the header the empty string.
val set_iv : scipher_ctx -> string -> unit
set_iv cctx iv: Sets the initialization vector. This is only allowed before encrypting or decrypting data
val set_header : scipher_ctx -> string -> unit
set_header cctx data: Sets the additional header that is authenticated for AEAD schemes. The header must have been set before starting the encryption or decryption (otherwise it is assumed to be the empty string).

For non-AEAD schemes, the header is ignored for encryption, and must be empty for decryption.

val encrypt : scipher_ctx ->
Netsys_types.memory -> Netsys_types.memory -> unit
encrypt cctx inbuf outbuf: Encrypts the data in inbuf and writes the result into outbuf. Both buffers must have the same size. It is not allowed to pass the same buffer as inbuf and outbuf.

In order to encrypt long texts, it is allowed to call encrypt several times in sequence.

val decrypt : scipher_ctx ->
Netsys_types.memory -> Netsys_types.memory -> bool
decrypt cctx inbuf outbuf: Decrypts the data in inbuf and writes the result into outbuf. Both buffers must have the same size. It is not allowed to pass the same buffer as inbuf and outbuf.

The function returns true on success, and false if a problem is detected.

In order to decrypt long texts, it is allowed to call decrypt several times in sequence.

val mac : scipher_ctx -> string
Returns the MAC for AEAD ciphers. This is updated after encrypt/decrypt. This function fails for non-AEAD ciphers.
ocamlnet-4.1.2/doc/html-main/type_Rpc_client.socket_config.html0000644000175000017500000004264012731530352023233 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.socket_config object
  method multiplexing :
    dbg_name:string Pervasives.ref ->
    close_inactive_descr:bool ->
    peer_name:string option ->
    Rpc.protocol ->
    Unix.file_descr ->
    Unixqueue.event_system ->
    Rpc_transport.rpc_multiplex_controller Uq_engines.engine
  method non_blocking_connect : bool
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.prioritizer-c.html0000644000175000017500000004242212731530352022170 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.prioritizer

Class Uq_engines.prioritizer

class ['a] prioritizer : Unixqueue.event_system -> ['a] prioritizer_t
Creates a prioritizer

ocamlnet-4.1.2/doc/html-main/Netsendmail_tut.html0000644000175000017500000006514312731530352020436 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsendmail_tut

Netsendmail_tut


Netsendmail Tutorial

Generating mail messages is a very complicated procedure. Netsendmail provides a comparatively simple interface to accomplish this task without knowing too much about the details of the mail format. Here is a kind of cookbook:

Generate an ASCII Mail

In the simplest case, the mail is an ASCII text. Generate the mail with

 
compose ~from_addr ~to_addrs ~subject main_text

Here, from_addr is the sender's address as pair (name,formal_address), and to_addrs is the list of recipients in the same format. The variable subject contains the subject of the message as string. Finally, main_text is the ASCII text.

Generate an Internationalised Mail

When addresses or the main text contain non-ASCII characters, you should care about the in_charset and out_charset parameters. In general, the strings you pass to compose are encoded as in_charset, and the strings in the generated mail are encoded as out_charset. Usually, it is a good idea to have in_charset = out_charset, or out_charset as a superset of in_charset (otherwise you might get conversion errors).

The default for both parameters is `Enc_iso88591.

Not everything can be internationalised. In particular, the subject, the informal names of mail addresses, the content_description, and the main text can be encoded in a non-ASCII character set. Especially, the formal mail addresses cannot be internationalised. Example:

compose 
  ~in_charset:`Enc_iso885915
  ~out_charset:`Enc_iso885915
  ~from_addr:("Heinz Dräger", "heinz\@draeger.de") 
  ~to_addr:("Marion Schröder", "marion\@irgendwo.de")
  ~subject:"Geschäftlich"
  "Verkaufe Teddy-Bären für 100¤"

Note that when you also pass content_type, the main text is no longer converted according to in_charset and out_charset. It is expected that the main text has already the right encoding, and that the encoding is indicated by the content_type. Example:

compose 
  ~in_charset:`Enc_iso885915
  ~out_charset:`Enc_iso885915
  ~from_addr:("Heinz Dräger", "heinz\@draeger.de") 
  ~to_addr:("Marion Schröder", "marion\@irgendwo.de")
  ~content_type:("text/html", ["charset", Netmime_string.mk_param "ISO-8859-1"])
  ~subject:"Geschäftlich"
  "<html><body>Verkaufe Teddy-Bären für 100&euro;</body></html>"
Here, the header fields are encoded in ISO-8859-15, but the main text uses ISO-8859-1.

The function Netmime_string.mk_param encapsulates parameter values for several kinds of structured values that may occur in mail headers, here for Content-type. This function takes care of the appropriate representation of the parameter value (e.g. for parameters like "title" that can be internationalised).

Generate a Mail with Attachments

An attachment can simply be passed to compose. For example, to add a file "foo.gif":

compose
  ...
  attachments:[ wrap_attachment
                  ~content_type:("image/gif", [])
                  (new Netmime.file_mime_body "foo.gif") ]
  ...

This creates a multipart/mixed mail. The class Netmime.file_mime_body encapsulates a file as a MIME body that can be attached to the mail (note: The file is not read as a whole into memory, but only chunk by chunk, so you can even attach large files without exhausting memory).

The type multipart/mixed has the special feature that the attached parts can either by displayed "inline" with the other contents, or suggested for saving in a file. This hint is indicated by the Content-disposition header. For example, to have the first attachment "inline", and the second as a file with name "foo.gif", use:

compose
  ...
  attachments:[ wrap_attachment
                  ~content_type:("image/gif", [])
                  ~content_disposition:("inline", [])
                  (new Netmime.file_mime_body "foo.gif");
                wrap_attachment
                  ~content_type:("image/gif", [])
                  ~content_disposition:("attachment", ["filename",
                                                       Netmime_string.mk_param "foo.gif"])
                  (new Netmime.file_mime_body "foo.gif") ]
  ...

Generate a Multi-Format Mail

It is possible to generate messages where the main part is available in several formats, e.g. in text/plain and text/html. The mail reader program can select which format can be presented best to the user.

The compose function is not the right means to produce such a mail. It is better to use the more capable functions wrap_parts and wrap_mail for this purpose.

For example, to get a message with the text/plain version s_plain and the text/html version s_html, use:

wrap_mail
   ~from_addr ~to_addrs ~subject
   (wrap_parts
      ~content_type:("multipart/alternative", [])
      [ wrap_attachment
          ~content_type:("text/plain", [])
          (new Netmime.memory_mime_body s_plain);
        wrap_attachment
          ~content_type:("text/html", [])
          (new Netmime.memory_mime_body s_html)
      ])

Here, wrap_attachment is used to encapsulate the two versions of the main text. This works because there is no difference between the format of an attachment and the format of a text part. (Actually, wrap_attachment should be better called wrap_body.) The class Netmime.memory_mime_body encapsulates a string as MIME body.

The function wrap_parts bundles the two versions to the main message, and wrap_mail adds the mail headers necessary to deliver the mail.

Note that the simplest version of the message should be added first, and the fanciest version of the message should be added last.

As a variant, one can also add file attachments. To do so, insert a multipart/mixed container around the multipart/alternative message:

wrap_mail
   ~from_addr ~to_addrs ~subject
   (wrap_parts
      ~content_type:("multipart/mixed", [])
      [ wrap_parts
          ~content_type:("multipart/alternative", [])
          [ wrap_attachment
              ~content_type:("text/plain", [])
              (new Netmime.memory_mime_body s_plain);
            wrap_attachment
              ~content_type:("text/html", [])
              (new Netmime.memory_mime_body s_html)
          ];
        wrap_attachment
          ~content_type:("audio/wav", [])
          (new Netmime.file_mime_body "music.wav")
      ])

Generate an MHTML Message

MHTML is an HTML document with attached resource files like images or style sheets. For example, to have the HTML text s_html bundled with an image and a style sheet, use:

wrap_mail
   ~from_addr ~to_addrs ~subject
   (wrap_parts
      ~content_type:("multipart/related",
                     [ "type", Netmime_string.mk_param "text/html" ])
      [ wrap_attachment
          ~content_type:("text/html", [])
          (new Netmime.memory_mime_body s_html);
        wrap_attachment
          ~content_type:("image/gif", [])
          ~content_id:"img1"
          (new Netmime.file_mime_body "my.gif")
        wrap_attachment
          ~content_type:("text/css", [])
          ~content_id:"style1"
          (new Netmime.file_mime_body "style.css")
      ])

Note the content_id arguments that assign names to the individual parts. One can now refer to the parts from the HTML document by cid URLs, e.g. cid:img1 points to the image in the second part.

There is another mechanism using the Content-Location header to resolve hyperlinks to message parts. See RFC 2557 for details.


ocamlnet-4.1.2/doc/html-main/Netsys_global.propagator-c.html0000644000175000017500000004353212731530352022477 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_global.propagator

Class type Netsys_global.propagator

class type propagator = object .. end

method propagate : string -> string -> int64
propagate name value version: push the new value of the variable called name to other processes. The version of the new value is returned.
method update : string -> int64 -> (string * int64) option
update name version: checks whether there is a new value of the variable name with a version higher than the passed version. If not, None is returned. If so, Some(val,vers) is returned where val is the value with version vers.
ocamlnet-4.1.2/doc/html-main/Netsockaddr.html0000644000175000017500000005064012731530352017534 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsockaddr

Module Netsockaddr

module Netsockaddr: sig .. end
Parsing of socket addresses

type socksymbol = [ `Inet of Unix.inet_addr * int
| `Inet_byname of string * int
| `Unix of string ]
Symbolic socket names:

  • `Inet(ip,port): An internet socket with IP ip and the given port
  • `Inet_byname(n,port): An internet socket with the IP resulting from the resolution of the name n, and with the given port
  • `Unix p: A Unix Domain socket with the path p
Use Uq_resolver.sockaddr_of_socksymbol to convert to a Unix.sockaddr (and resolve names).
val socksymbol_of_string : string -> socksymbol
Parses designations of the forms:
  • <IPv4>:port
  • [<IPv4_or_IPv6]:port
  • <name>:port
  • /path
  • ./path
Raises Failure on parse error.
val string_of_socksymbol : socksymbol -> string
The reverse function
val norm_socksymbol : socksymbol -> socksymbol
Normalizes numeric IP addresses: if the address is an IPv4 address mapped to the IPv6 address space, the real IPv4 address is returned. This also works for numeric addresses in string form, whose writing is also normalized.

E.g.

  • norm_socksymbol (`Inet_by_name("::ffff:127.0.0.1", 80)) returns `Inet_by_name("127.0.0.1",80)
  • norm_socksymbol (`Inet_by_name("0::1",80)) returns `Inet_by_name("::1", 80)

val ipv6_socksymbol : socksymbol -> socksymbol
IPv6-ification of numeric IP addresses: IPv4 addresses are mapped to the IPv6 address space. This also works for numeric addresses in string form, whose writing is also normalized.

E.g.

  • norm_socksymbol (`Inet_by_name("127.0.0.1", 80)) returns `Inet_by_name("::ffff:127.0.0.1",80)
  • norm_socksymbol (`Inet_by_name("0::1",80)) returns `Inet_by_name("::1", 80)

ocamlnet-4.1.2/doc/html-main/Netmech_digest_http.Digest.html0000644000175000017500000007476412731530352022507 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http.Digest

Module Netmech_digest_http.Digest

module Digest: Nethttp.HTTP_CLIENT_MECHANISM 
This is the standard HTTP digest authentication mechanism (see RFCs 2069, 2617, 7616). The hash functions MD5 and SHA-256 are supported, in server preference.

This version does not include mutual authentication, i.e. it does not matter what the server responds in the Authentication-Info header.

There is no support for the "auth-int" level of protection.

How to use with Nethttp_client: The handlers Nethttp_client.unified_auth_handler and Nethttp_client.digest_auth_handler wrap this mechanism already. Additionally, there is also the option of plugging in this module directly. For this, you need the adapter Nethttp_client.generic_auth_handler, e.g.

  let m = ( module Netmech_digest_http.Digest )
  let h = new Nethttp_client.generic_auth_handler key_ring [ m ]
  http_pipeline # add_auth_handler h
      

Get key_ring by instantiating Nethttp_client.key_ring.

Note that the key ring must use UTF-8 encoding (although the Digest protocol might need to recode to ISO-8859-1 - note that authentication will fail if this is not possible).


val mechanism_name : string
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
val restart_supported : bool
Whether the mechanism supports quick restarts (re-authentication)
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

The password is encoded in UTF-8. However, note that not all protocols are able to transmit all of UTF-8. If a non-transmittable character is found, the authentication will fail.

The password can have parameters:

  • "realm": the password is only applicable to this realm. The realm parameter should only occur once.
  • "domain-uri": the password is only applicable to this URI space. The URI must include the protocol scheme, the host name, and "/" as path. The port number is optional. Example: "http://localhost/". The domain-uri parameter can occur several times.

val client_match : params:(string * string * bool) list ->
Nethttp.Header.auth_challenge -> Nethttp.match_result
Checks whether this mechanism can accept the initial authentication challenge (i.e. the first challenge sent from the server to the client. The params are as for create_client_session. On success, returns `Accept(realm,id_opt). On failure, returns `Reject. This function usually does not raise exceptions.

If the mechanism does not support the notion of realms, a dummy realm should be returned.

The id_opt is the session ID (if supported). Session IDs can be used to bind reauthentications to the original session.

The challenge is from a www-authenticate or a proxy-authenticate header.

There is also the result `Reroute(realm, trans_id), meaning that the request would be acceptable if it came over the transport identified by trans_id. `Accept_reroute is the combination of accepting and rerouting, i.e. the auth protocol can start, but the second request should go over the other transport. Both `Reroute and `Accept_reroute are only allowed for initial challenges.

type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user. The credentials are creds.

user must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

Available parameters:

  • "realm"
  • "id" (if client_match returns a session ID)
  • "trans_id": the Nethttp_client.transport_layer_id of the current HTTP request
  • "conn_id": an identifier for the TCP connection
  • "https": is set to "true" if the current connection is TLS-secured
  • "target-host": the hostname from the HTTP request
  • "target-uri": the URL from the HTTP request

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : params:(string * string * bool) list ->
client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK. After the restart the session will be in state `Emit.

The params are the same as for create_client_session, but updated where needed.

val client_process_challenge : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
Nethttp.Header.auth_challenge -> client_session
client_process_challenge cs method uri header challenge:

Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.

method is the request method. uri is the request URI

val client_emit_response : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
client_session *
Nethttp.Header.auth_credentials * (string * string) list
let (creds,new_headers) = client_emit_response cs method uri header:

Emit a new response as a pair (creds,new_headers). The state must be `Emit. The creds either go into the authorization or proxy-authorization header. The new_headers are additional headers to modify.

val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_domain : client_session -> string list
After successful authentication, this function may return the URIs defining the authentication space.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. Commonly supported keys:
  • "realm"
  • "domain-uri"

val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Returns the GSSAPI props if available, or raise Not_found
ocamlnet-4.1.2/doc/html-main/type_Netmech_spnego_http.PROFILE.html0000644000175000017500000004163012731530352023427 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_spnego_http.PROFILE sig
  val acceptable_transports_http : Nethttp.transport_layer_id list
  val acceptable_transports_https : Nethttp.transport_layer_id list
  val enable_delegation : bool
  val deleg_credential : exn option
end
ocamlnet-4.1.2/doc/html-main/Netmech_scram_gssapi.html0000644000175000017500000005040712731530352021412 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_gssapi

Module Netmech_scram_gssapi

module Netmech_scram_gssapi: sig .. end
The SCRAM security mechanism for GSS-API

This module needs the SHA-1 hash function. In order to use it, initialize crypto support, e.g. by including the nettls-gnutls packages and calling Nettls_gnutls.init.



See RFC 5802
val scram_mech : Netsys_gssapi.oid
The OID of SCRAM
class type client_key_ring = object .. end
A client_key_ring identifies the user on the client side
class type server_key_verifier = object .. end
A server_key_verifier verifies on the server side that the users exist and have the right authentication credentials
val scram_gss_api : ?client_key_ring:client_key_ring ->
?server_key_verifier:server_key_verifier ->
Netmech_scram.profile -> (module Netsys_gssapi.GSSAPI)
Returns a standard-compliant GSS-API object for the passed SCRAM profile. The object can be used on the client side for all users whose passwords are available via client_key_ring. By default, the key ring is empty. On the server side, the object authenticates all users whose credentials are available via server_key_verifier. By default, no user can be verified.

SCRAM only allows usernames of type NT_USER_NAME for identifying users.

For principals (servers), this SCRAM implementation allows identifiers of type NT_HOSTBASED_SERVICE and NT_USER_NAME. Any such name can be used, because the SCRAM protocol does not use principal names. The contexts will always return the hostbased service "@" as name of the principals.

This implementation checks whether the messages are verified and unwrapped in the same order than generated, and reports this via the `Unseq_token and `Gap_token flags. Support for true replay detection (`Duplicate_token) is not implemented, though. Replayed tokens will also be marked as `Unseq_token.

ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_modes.html0000644000175000017500000005446612731530352022422 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes sig
  module Symmetric_cipher :
    sig
      type sc_ctx = {
        set_iv : string -> unit;
        set_header : string -> unit;
        encrypt : Netsys_types.memory -> Netsys_types.memory -> unit;
        decrypt : Netsys_types.memory -> Netsys_types.memory -> bool;
        mac : unit -> string;
      }
      type sc = {
        name : string;
        mode : string;
        key_lengths : (int * int) list;
        iv_lengths : (int * int) list;
        block_constraint : int;
        supports_aead : bool;
        create : string -> Netsys_crypto_modes.Symmetric_cipher.sc_ctx;
      }
      val extract :
        (module Netsys_crypto_types.SYMMETRIC_CRYPTO->
        string * string -> Netsys_crypto_modes.Symmetric_cipher.sc
      val extract_all :
        (module Netsys_crypto_types.SYMMETRIC_CRYPTO->
        Netsys_crypto_modes.Symmetric_cipher.sc list
      val cbc_of_ecb :
        Netsys_crypto_modes.Symmetric_cipher.sc ->
        Netsys_crypto_modes.Symmetric_cipher.sc
      val ofb_of_ecb :
        Netsys_crypto_modes.Symmetric_cipher.sc ->
        Netsys_crypto_modes.Symmetric_cipher.sc
      val ctr_of_ecb :
        Netsys_crypto_modes.Symmetric_cipher.sc ->
        Netsys_crypto_modes.Symmetric_cipher.sc
    end
  module type CIPHERS =
    sig val ciphers : Netsys_crypto_modes.Symmetric_cipher.sc list end
  module Bundle :
    functor (C : CIPHERS-> Netsys_crypto_types.SYMMETRIC_CRYPTO
  module Add_modes :
    functor (SC : Netsys_crypto_types.SYMMETRIC_CRYPTO->
      Netsys_crypto_types.SYMMETRIC_CRYPTO
end
ocamlnet-4.1.2/doc/html-main/Netftp_client.ftp_client-c.html0000644000175000017500000004700512731530352022440 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_client.ftp_client

Class Netftp_client.ftp_client

class ftp_client : ?event_system:Unixqueue.event_system -> unit -> object .. end
The ftp client is a user session that may even span several connections. However, only one server is connected at once.

method exec_e : ftp_method -> unit Uq_engines.engine
Runs the method asynchronously as engine.
method exec : ftp_method -> unit
Runs the method synchronously. Note that this implies a call of Unixqueue.run.
method pi : ftp_client_pi
The curerent protocol interpreter. It is allowed that a different pi is created when a new connection is opened.

The pi is first available after running the first method. The method fails if pi is unavailable.

method run : unit -> unit
Starts the event system; same as Unixqueue.run
method configure_timeout : float -> unit
Configures a timeout for both the control and the data connection. This must be done before connecting to a server.
method set_socks5_proxy : string -> int -> unit
Sets that a SOCKS version 5 proxy is used at this host and port. There is no support for authentication at the proxy. Only passive mode is supported.
method event_system : Unixqueue.event_system
method reset : unit -> unit
Aborts all current activities if any, and re-initializes the client
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_http.html0000644000175000017500000004263712731530352022152 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_http sig
  module type PROFILE =
    sig
      val mutual : bool
      val hash_function : Netsys_digests.iana_hash_fn
      val test_nonce : string option
    end
  module Make_SCRAM : functor (P : PROFILE-> Nethttp.HTTP_CLIENT_MECHANISM
end
ocamlnet-4.1.2/doc/html-main/Netaccel_link.html0000644000175000017500000004210212731530352020020 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaccel_link

Module Netaccel_link

module Netaccel_link: sig .. end
Enables accelerator module Netaccel

This module exists for technical reasons.


ocamlnet-4.1.2/doc/html-main/type_Get.html0000644000175000017500000004060412731530352017052 0ustar gerdgerd Ocamlnet 4 Reference Manual : Get sig  endocamlnet-4.1.2/doc/html-main/type_Netgzip.output_deflate.html0000644000175000017500000004106112731530352022774 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.output_deflate ?level:int -> Netchannels.out_obj_channel -> Netchannels.out_obj_channelocamlnet-4.1.2/doc/html-main/Nethttp_fs.http_fs-c.html0000644000175000017500000005243412731530352021302 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_fs.http_fs

Class Nethttp_fs.http_fs

class http_fs : ?config_pipeline:Nethttp_client.pipeline -> unit -> ?streaming:bool -> ?tmp_directory:string -> ?tmp_prefix:string -> ?path_encoding:Netconversion.encoding -> ?enable_read_for_directories:bool -> ?enable_ftp:bool -> string -> http_stream_fs
http_fs base_url: Accesses the HTTP file system rooted at base_url.

The following access methods are supported (compare with Netfs.stream_fs):

  • path_encoding: Returns the passed path_encoding. Paths are always encoded.
  • path_exclusions: is just 0,0; 47,47
  • nominal_dot_dot is true
  • read: is supported. All files are considered as binary. The `Skip flag works, and is translated to a Range header.
  • write: is supported and translated to PUT. It is assumed that PUT truncates existing files, and creates new files. Note that errors are often first reported when the returned channel is closed!
  • size: this works only if the server includes the Content-length header in responses to HEAD requests.
  • test and test_list: The tests `N, `E, `D, `F, and `S should work. Files are never symlinks. `R is handled like `E, and `X is handled like `X (i.e. it is assumed that all files are readable, and all directories can be entered). The `W test is never successful.
  • remove: is translated to a DELETE request.
  • readdir: works if index pages are generated (see above)
There is no support for rename, symlink, mkdir, rmdir, and copy.

Options:

  • config_pipeline: one can enable further features on the pipeline object (e.g. authentication, proxies)
  • streaming: if true, the read method only reads as much data from the HTTP connection as requested by the user. This assumes that the user does not pause stream accesses for longer periods as this would risk a server timeout. Also, there is no way for the client to automatically reconnect to the HTTP server after crashes. If false (the default), files are first downloaded to a temporary file before they are made accessible as in_obj_channel. Streaming can also be enabled for each read or write by including `Streaming in the list of flags.
  • tmp_directory: directory for temporary files
  • tmp_prefix: file prefix for temporary files (w/o directory)
  • path_encoding: The encoding that is used for the file names. This must match the encoding the server assumes for translating file names to hyperlinks. Unfortunately, there is no way to query the server for this. The default, `Enc_utf8, seems to be the de-facto standard on the web (e.g. browsers use UTF-8 when non-ASCII characters are entered in the address line).
  • enable_ftp: This enables anonymous FTP via web proxies. In this case the base_url is of the form ftp://host:port/path. This works only if the pipeline is configured to contact a web proxy understanding FTP URLs.


ocamlnet-4.1.2/doc/html-main/Netplex_kit.processor_hooks_delegation-c.html0000644000175000017500000004272512731530352025422 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.processor_hooks_delegation

Class Netplex_kit.processor_hooks_delegation

class processor_hooks_delegation : Netplex_types.processor_hooks -> Netplex_types.processor_hooks
Takes a hooks object, and makes a class of it. Useful for overriding methods in an object.

ocamlnet-4.1.2/doc/html-main/type_Netchannels.out_obj_channel_delegation.html0000644000175000017500000004110212731530352026112 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.out_obj_channel_delegation ?close:bool -> Netchannels.out_obj_channel -> Netchannels.out_obj_channelocamlnet-4.1.2/doc/html-main/type_Netpagebuffer.html0000644000175000017500000006323312731530352021113 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpagebuffer sig
  type t
  val create : int -> Netpagebuffer.t
  val contents : Netpagebuffer.t -> string
  val to_bytes : Netpagebuffer.t -> Bytes.t
  val to_tstring_poly :
    Netpagebuffer.t -> 'Netstring_tstring.tstring_kind -> 's
  val to_tstring :
    Netpagebuffer.t ->
    'Netstring_tstring.tstring_kind -> Netsys_types.tstring
  val length : Netpagebuffer.t -> int
  val sub : Netpagebuffer.t -> int -> int -> string
  val sub_bytes : Netpagebuffer.t -> int -> int -> Bytes.t
  val blit_to_bytes : Netpagebuffer.t -> int -> Bytes.t -> int -> int -> unit
  val blit_to_string :
    Netpagebuffer.t -> int -> Bytes.t -> int -> int -> unit
  val blit_to_memory :
    Netpagebuffer.t -> int -> Netsys_mem.memory -> int -> int -> unit
  val blit_to_tbuffer :
    Netpagebuffer.t -> int -> Netsys_types.tbuffer -> int -> int -> unit
  val blit : Netpagebuffer.t -> int -> Bytes.t -> int -> int -> unit
  val add_string : Netpagebuffer.t -> string -> unit
  val add_bytes : Netpagebuffer.t -> Bytes.t -> unit
  val add_tstring : Netpagebuffer.t -> Netsys_types.tstring -> unit
  val add_substring : Netpagebuffer.t -> string -> int -> int -> unit
  val add_sub_string : Netpagebuffer.t -> string -> int -> int -> unit
  val add_subbytes : Netpagebuffer.t -> Bytes.t -> int -> int -> unit
  val add_submemory :
    Netpagebuffer.t -> Netsys_mem.memory -> int -> int -> unit
  val add_sub_memory :
    Netpagebuffer.t -> Netsys_mem.memory -> int -> int -> unit
  val add_subtstring :
    Netpagebuffer.t -> Netsys_types.tstring -> int -> int -> unit
  val add_inplace :
    Netpagebuffer.t -> (Netsys_mem.memory -> int -> int -> int) -> int
  val page_for_additions : Netpagebuffer.t -> Netsys_mem.memory * int * int
  val advance : Netpagebuffer.t -> int -> unit
  val page_for_consumption : Netpagebuffer.t -> Netsys_mem.memory * int * int
  val delete_hd : Netpagebuffer.t -> int -> unit
  val clear : Netpagebuffer.t -> unit
  val index_from : Netpagebuffer.t -> int -> char -> int
end
ocamlnet-4.1.2/doc/html-main/type_Netdn.html0000644000175000017500000004553712731530352017415 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdn sig
  type oid = Netoid.t
  type dn = (Netdn.oid * Netasn1.Value.value) list list
  module type AT_LOOKUP =
    sig
      val attribute_types : (Netdn.oid * string * string list) list
      val lookup_attribute_type_by_oid : Netdn.oid -> string * string list
      val lookup_attribute_type_by_name :
        string -> Netdn.oid * string * string list
    end
  module type DN_string =
    sig val parse : string -> Netdn.dn val print : Netdn.dn -> string end
  module DN_string_generic : functor (L : AT_LOOKUP-> DN_string
  val directory_string_from_ASN1 : Netasn1.Value.value -> string
end
ocamlnet-4.1.2/doc/html-main/Rpc_packer.html0000644000175000017500000007464012731530352017352 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_packer

Module Rpc_packer

module Rpc_packer: sig .. end
Packing and Unpacking of messages; can be used by both client and server programs. RPC messages consists of a frame and of application data. The packing (and unpacking) of the latter into the frame is done by this module. The frame is an XDR value with some slots that can be filled with application data, normally again an XDR value. The slots are represented using the X_param mechanism provided by the XDR module. As nested X_param usage is not permitted, this feature is not available for application data.

type packed_value 
val pack_call : ?encoder:Netxdr.encoder ->
Rpc_program.t ->
Netnumber.uint4 ->
string ->
string ->
string -> string -> string -> Netxdr.xdr_value -> packed_value

Packs the call and returns a packed_value that wraps the message string
val pack_call_pseudo : Rpc_program.t ->
Netnumber.uint4 ->
string ->
string ->
string -> string -> string -> Netxdr.xdr_value -> packed_value

Packs the call and returns a packed_value that contains the arguments as they are (i.e. not encoded as string).
val pack_call_gssapi_header : Rpc_program.t ->
Netnumber.uint4 -> string -> string -> string -> packed_value
for GSS-API - packs the call header up to the credentials
val unpack_call : ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
?decoder:Netxdr.decoder ->
Rpc_program.t ->
string ->
packed_value ->
Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 *
string * string * string * string * Netxdr.xdr_value

Unpacks the call completely
val unpack_call_frame : packed_value ->
Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 *
string * string * string * string

Unpacks only the frame of the call.
val unpack_call_frame_l : packed_value ->
Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 *
string * string * string * string * int

Unpacks only the frame of the call, returns also the length of the frame
val extract_call_gssapi_header : packed_value -> int
returns the length of the prefix of the message so that the prefix includes the header until (and including) the credentials.

This function is unavailable for values packed with any of the pack_*_pseudo functions.

val unpack_call_body : ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
?decoder:Netxdr.decoder ->
Rpc_program.t -> string -> packed_value -> int -> Netxdr.xdr_value

Unpacks only the body (the parameters of the procedure call) of the packed_value. You can pass the length of the call frame as the position of the body.

This works also for values packed with pack_*_pseudo, and the position is ignored in this case.

val unpack_call_body_raw : packed_value -> int -> string
val unpack_call_body_raw_bytes : packed_value -> int -> Bytes.t

A successful reply means that the procedure call returned a value. An accepting reply means that authentication was successful but the procedure could not be evaluated. The third catagory of replies are rejecting replies.
val pack_successful_reply : ?encoder:Netxdr.encoder ->
Rpc_program.t ->
string ->
Netnumber.uint4 ->
string -> string -> Netxdr.xdr_value -> packed_value

Packs a successful reply
val pack_successful_reply_pseudo : Rpc_program.t ->
string ->
Netnumber.uint4 ->
string -> string -> Netxdr.xdr_value -> packed_value

Packs a successful reply as pseudo message
val pack_successful_reply_raw : Netnumber.uint4 ->
string -> string -> Netxdr_mstring.mstring list -> packed_value
val pack_accepting_reply : Netnumber.uint4 ->
string -> string -> Rpc.server_error -> packed_value

Packs a server error that counts as accepting call
val pack_accepting_reply_pseudo : Netnumber.uint4 ->
string -> string -> Rpc.server_error -> packed_value

Same, but returns a pseudo message
val pack_rejecting_reply : Netnumber.uint4 -> Rpc.server_error -> packed_value

Packs a server error that counts as rejecting call
val pack_rejecting_reply_pseudo : Netnumber.uint4 -> Rpc.server_error -> packed_value

Same, but returns a pseudo message
val unpack_reply : ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
?decoder:Netxdr.decoder ->
Rpc_program.t ->
string ->
packed_value ->
Netnumber.uint4 * string * string * Netxdr.xdr_value

unpack_reply may raise:
  • Rpc_server: If one of the server error conditions is true. Note that the call may be "accepted" even if this exception occurs. In this case use unpack_reply_verfifier to get the verifier.

val unpack_reply_verifier : Rpc_program.t -> string -> packed_value -> string * string
val peek_xid : packed_value -> Netnumber.uint4
Extracts the session ID without analyzing the rest of the message.
val peek_auth_error : packed_value -> Rpc.server_error option
If an authentication error occurs, this function extracts it from the packed message.
val length_of_packed_value : packed_value -> int
val string_of_packed_value : packed_value -> string
val bytes_of_packed_value : packed_value -> Bytes.t
val mstrings_of_packed_value : packed_value -> Netxdr_mstring.mstring list
Get the packed string. These functions cannot be used for values returned from any of the pack_*_pseudo functions.
val packed_value_of_string : string -> packed_value
val packed_value_of_bytes : Bytes.t -> packed_value
val packed_value_of_mstrings : Netxdr_mstring.mstring list -> packed_value
val prefix_of_packed_value : packed_value -> int -> string
The first n bytes of the packed value
val xdr_of_pseudo_value : packed_value -> Netxdr.xdr_value
val pseudo_value_of_xdr : Netxdr.xdr_value -> packed_value
ocamlnet-4.1.2/doc/html-main/Rpc_server.html0000644000175000017500000016545712731530352017422 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server

Module Rpc_server

module Rpc_server: sig .. end
RPC servers


Like the client, the RPC server module is programmed on top of the Unixqueue event system. It pushes itself on an existing Unixqueue as a new service that accepts RPC calls, forwards them to configurable functions, and sends the replies back.

The server module can manage two kinds of RPC functions: synchronous and asynchronous. Synchronous functions compute their result immediately and thus the result can be sent back just after the evaluation of the function has finished. In contrast to this, asynchronous functions only get noticed about the call and need not to know immediately what should be answered. Typically, an asynchronous function initiates a second communication channel and its result depends on what happens on the second channel. The communication on this channel is done in an asynchronous way, too, and can be managed by the same event system that carries out the RPC service. After several input or output events, the result has somehow been computed, and the answer can be sent back to the original caller. To do so, the asynchronous RPC function invokes 'reply' together with the necessary session IDs that identify the answer among all answers.

exception Connection_lost
raised by the 'reply' function if the connection to the original caller has been lost in the meantime.
type t 
represents a server for an RPC program
type session 
identifies a pair of a call and a reply
type connection_id 
identifies the connection of a session. For connectionless servers, every session gets a new connection_id. You can compare connection_ids to find out whether two sessions belong to the same connection. Use "=" for equality.
type connector = 
| Localhost of int (*
The service is installed on 'localhost' and listens on the given port number. A number of 0 means that the port is chosen by the operating system. Note: The service is only locally reachable.

IPv6: not supported for compatibility reasons

*)
| Portmapped (*
The service is installed on every network interface; the port is chosen by the operating system; the program is registered with the portmapper (or rpcbind).

IPv6: if the socket can be bound to ::, this is preferred. Also, if Netsys.is_ipv6_system returns true, the IPv6 capability is registered with rpcbind.

*)
| Internet of (Unix.inet_addr * int) (*
The service is installed on the passed interface/port combination. Use Unix.inet_addr_any to listen on all network interfaces (IPv4), or Unix.inet6_addr_any for IPv6 and IPv4. Use port 0 to automatically choose the port number.
*)
| Unix of string (*
The service is installed on a Unix domain socket. Note: the socket path must not exist when the server is started, and the socket must be unlinked when the server terminates. Note Win32: Unix domain sockets are emulated by writing the inet4 port number into a one-line file.
*)
| W32_pipe of string (*
The service is installed for a named pipe. (Only for Win32.)
*)
| Descriptor of Unix.file_descr (*
The service listens on the given file descriptor.
*)
| Dynamic_descriptor of (unit -> Unix.file_descr) (*
The service listens on the returned file descriptor.
*)
type binding_sync = {
   sync_name : string; (*
procedure name
*)
   sync_proc : t -> Netxdr.xdr_value -> Netxdr.xdr_value; (*
the function that implements the procedure
*)
}
type binding_async = {
   async_name : string; (*
procedure name
*)
   async_invoke : t -> session -> Netxdr.xdr_value -> unit; (*
A function that is called when the procedure is called
*)
}
type binding = 
| Sync of binding_sync (*
bind a synchonous procedure
*)
| Async of binding_async (*
bind an asynchonous procedure
*)
val connector_of_sockaddr : Unix.sockaddr -> connector
Converts the socket address into a connector
val connector_of_socksymbol : Netsockaddr.socksymbol -> connector
Converts the Netsockaddr.socksymbol into a connector
val create : ?program_number:Netnumber.uint4 ->
?version_number:Netnumber.uint4 ->
Unixqueue.event_system ->
connector ->
Rpc.protocol ->
Rpc.mode -> Rpc_program.t -> binding list -> int -> t
Deprecated creation of an RPC server. For new programs, use create2 or one of its variants.

Creates a new server that is pushed onto the event queue. The connector, protocol and mode values control the network type of the server. Note that not all combinations are valid; the following can be used:

  • any connector, protocol=Tcp, mode=Socket: creates a classic TCP server socket that allows multiple stream connections at the same time
  • connector=Descriptor s, protocol=Tcp, mode=BiPipe: (where s is one half of a socketpair) creates a stream socket that is the endpoint of a point-to-point stream connection (bidirectional pipe)
  • any Internet namespace connector, protocol=Udp, mode=Socket: creates a UDP server socket that allows serving multiple datagrams
Note: If connector = Descriptor _ the file descriptor is not opened by this module and not closed. The other connectors work automatically regarding this point, i.e. descriptors are opened and closed as necessary.

connector = Dynamic_descriptor: The open descriptor is closed after use.

The Rpc_program.t specifies the procedures that are available and their signatures. The binding list should contain for every procedure name the function that handles calls of the procedures.

The remaining integer is the maximum number of waiting connections if a classic Tcp server socket is used; other connection types ignore this number.

The optional arguments ?program_number and ?version_number override the numbers specified in the passed program.

Notes on servers:

  • servers that allow multiple connections never terminate by themselves
  • servers for only one connection (endpoint of a bidirectional pipe) terminate if they see an EOF on the stream; in this case the stream is closed by the server
  • the create function may block if the connector is Portmapped
Note for UDP servers: Due to limitations of the ocaml runtime there is a limit of 16K per message.
class type socket_config = object .. end
val default_socket_config : socket_config
class default_socket_config : socket_config
val tls_socket_config : (module Netsys_crypto_types.TLS_CONFIG) -> socket_config
This configuration establishes TLS when accepting new connections. It is (so far) only compatible with Rpc.Tcp.
class tls_socket_config : (module Netsys_crypto_types.TLS_CONFIG) -> socket_config
TLS configuration as class
type internal_pipe = Netxdr.xdr_value Netsys_polypipe.polypipe 
type internal_socket = Netxdr.xdr_value Netsys_polysocket.polyserver 
type mode2 = [ `Dummy of Rpc.protocol
| `Internal_endpoint of internal_pipe * internal_pipe
| `Internal_socket of internal_socket
| `Multiplexer_endpoint of Rpc_transport.rpc_multiplex_controller
| `Socket of Rpc.protocol * connector * socket_config
| `Socket_endpoint of Rpc.protocol * Unix.file_descr ]
Determines the type of the server for create2:

  • `Socket_endpoint(proto,fd): Socket fd is a connected socket descriptor used for communication. proto determines the encapsulation; should be Tcp for stream sockets and Udp for datagram sockets.
  • `Multiplexer_endpoint m: m is an RPC multiplex controller.
  • `Socket(proto, conn, config): Opens or uses a server socket according to conn. proto determines the encapsulation; should be Tcp for stream sockets and Udp for datagram sockets. config specifies configuration details.
  • `Internal_endpoint(rd,wr): Creates a server that exchanges data over the pair of polypipes (rd,wr) (see Netsys_polypipe). The polypipes will be closed when the connection is terminated.
  • `Internal_socket psock: Creates a server that accepts connections from the polysocket server psock (see Netsys_polysocket). The polysocket will be closed when the server is stopped.
Despite their names, `Socket_endpoint and `Socket also support Win32 named pipes.
val create2 : mode2 -> Unixqueue.event_system -> t
Creates a server according to the mode2 argument. This kind of server does initially not have any bindings.
val bind : ?program_number:Netnumber.uint4 ->
?version_number:Netnumber.uint4 ->
?pm_continue:bool ->
Rpc_program.t -> binding list -> t -> unit
Binds the program as specified by the binding list. If the portmapper must be informed, this action is started (and continued in the background). One can bind several programs in several versions to the same server.

pm_continue: you need to set this to true for all follow-up binds after the first one. If pm_continue is false, the portmapper entry is completely removed before a new registration is done. If it is true, the new registration is appended to the existing one.

val unbind : ?program_number:Netnumber.uint4 ->
?version_number:Netnumber.uint4 -> Rpc_program.t -> t -> unit
Unbinds the program if it is bound by the server
val bound_programs : t -> Rpc_program.t list
Returns the bound programs
val get_event_system : session -> Unixqueue.event_system
Find out the event system that contains the 'session'
val get_connection_id : session -> connection_id
Get the connection_id
val get_xid : session -> Netnumber.uint4
Returns the session ID. Important note: This number identifies the session from the caller's view, not from the server's view!
val get_socket_name : session -> Unix.sockaddr
val get_peer_name : session -> Unix.sockaddr
Return the address of the socket serving the session, and the client socket, resp. These functions fail if the server is not running on a socket.
val get_conn_socket_name : connection_id -> Unix.sockaddr
val get_conn_peer_name : connection_id -> Unix.sockaddr
Return the address of the socket serving the connection, and the client socket, resp. These functions fail if the server is not running on a socket.
val get_server : session -> t
Returns the server instance of the session
val get_main_socket_name : t -> Unix.sockaddr
Returns the address of the server socket, or the address of the bidirectional pipe. This function fails if the main file descriptor is not a socket.
val get_protocol : t -> Rpc.protocol
Return whether Tcp or Udp
val get_srv_event_system : t -> Unixqueue.unix_event_system
Returns the event system
val get_last_proc_info : t -> string
Get a debug string describing the last invoked procedure
val is_dummy : t -> bool
Whether this is a server in `Dummy mode. These servers cannot be used for communication
val get_tls_session_props : session -> Nettls_support.tls_session_props option
Get the TLS properties so far TLS is enabled
val get_gssapi_props : session -> Netsys_gssapi.server_props option
Get the GSSAPI properties if available
type rule = [ `Accept
| `Accept_limit_length of int * rule
| `Deny
| `Drop
| `Reject
| `Reject_with of Rpc.server_error ]
val set_session_filter : t -> (Rpc_transport.sockaddr -> rule) -> unit
If set, the filter function is invoked every time the beginning of a new RPC call is received, and the result of the filter function determines what to do with the call:

`Deny: TCP connections are immediately closed; UDP packets are dropped `Drop: The call is dropped (it does not allocate memory) `Reject_with: A response is sent back that the call is rejected. The parameter specified the error code `Reject: The same as `Reject_with Rpc.Auth_too_weak `Accept: The call is accepted without limitation (the default if no filter is installed) `Accept_limit_length(n,r): If the call is longer than n bytes, the rule r will be applied

The parameter of the filter function is the socket address of the client.

The intention of filters is to prevent denial of service attacks. A simple but good filter for TCP servers is set_filter srv (fun _ -> (`Accept_limit_length(n,`Deny)) which accepts messages up to n bytes without limit, and denies longer messages. n is the length of the longest sensible message.

For UDP servers, there is an implicit limit of 16K, so it is not necessary to care about this.

Another application is to restrict which systems can contact this server, based on the IP address of the client.

Note that this is not a protection against distributed denial of service attacks.

val set_session_filter_2 : t ->
(Rpc_transport.sockaddr -> connection_id -> rule) ->
unit
Same as set_session_filter, but the filter gets as second argument the connection ID.
val set_mstring_factories : t -> Netxdr_mstring.named_mstring_factories -> unit
Sets the mstring factories to use for decoding requests containing managed strings
val reply : session -> Netxdr.xdr_value -> unit
Asynchronous procedures can reply their results with this function.

NOTES:

  • As with synchronous procedures, the transfer is not reliable since the connection may be broken at any time
  • If it is already known that the connection is down, a Connection_lost exception is raised.
  • If you don't want to reply to a certain call, just don't reply. Unreplied calls do not allocate memory.
  • It is possible to reply several times ("batch mode"), but the client must support it, too. Just call reply several times for the same session.

val reply_error : session -> Rpc.server_error -> unit
Like reply, but an error condition is sent back to the caller.
val set_exception_handler : t -> (exn -> string -> unit) -> unit
Sets the exception handler for the server. The exception handler gets most exceptions raised by the functions that are bound to procedures. The exception handler does not get Abort exceptions and any exceptions resulting from I/O problems.

The string is the backtrace if present, or "" otherwise.

NOTES ABOUT EXCEPTIONS:

  • The default exception handler logs a `Crit message using Netlog.
  • I/O problems usually lead to an 'Abort' of the whole server.

val set_onclose_action : t -> (connection_id -> unit) -> unit
Every time a connection is closed, the onclose function is called with the closed connection. The default onclose action is to do nothing. The function is also called for Descriptor connectors when the socket should be closed (for these connectors the socket is not closed by this module).

Note that this action only applies to closed connections. It will not be executed for closed sockets in general (closed master socket, closed datagram socket).

If several onclose actions are set, they will be executed in reverse order.

val set_timeout : t -> float -> unit
Sets the timeout for the transport.
val stop_server : ?graceful:bool -> t -> unit
Stops the server: If a TCP server socket is listening, it is immediately closed. The shutdown procedure for the connections is initiated. Pending result messages are dropped.

graceful: If true, the shutdown procedure is deferred until all responses have been transferred back to the caller. This includes any responses added to the message queue in the current callback. New calls are not accepted.

val stop_connection : t -> connection_id -> unit
Schedules a special event that causes the connection to be stopped in the very near future. The function has only an effect for stream-oriented servers (mode = Tcp). The connection socket will be closed (unless it was passed using Descriptor). Nothing happens for datagram-oriented servers (mode = Udp).
type auth_result = 
| Auth_positive of (string * string * string * Netxdr.encoder option * Netxdr.decoder option *
Netsys_gssapi.server_props option)
(*
Successful authentication: (username, returned_verifier_flavour, returned_verifier_data, enc_opt, dec_opt, gss_opt )

Encoders and decoders are allowed to raise the exceptions Rpc_server.Late_drop and Rpc.Rpc_server.

*)
| Auth_negative of Rpc.server_error (*
Failed authentication
*)
| Auth_reply of (Netxdr_mstring.mstring list * string * string) (*
The authentication method generates the positive response of this RPC call: (data, verf_flavor, verf_data) (new in Ocamlnet-3.3)
*)
| Auth_drop (*
Authentication demands to drop the message
*)
exception Late_drop
This can be raised in encryption/decryption functions to prevent that a response is sent.
type auth_peeker = [ `None
| `Peek_descriptor of Unix.file_descr -> string option
| `Peek_multiplexer of
Rpc_transport.rpc_multiplex_controller -> string option ]
class type auth_details = object .. end
class type auth_method = object .. end
val set_auth_methods : t -> auth_method list -> unit
Sets the available authentication methods. By default, the list is set to auth_none . If none of the methods apply, the call is rejected (Auth_too_weak).
val auth_none : auth_method
The authentication method "AUTH_NONE", i.e. no user name is passed. The function get_user will return "".
val auth_too_weak : auth_method
The method that always rejects.
val auth_transport : auth_method
Authenticate by trusting the transport layer. The user returned by the multiplexer's method peer_user_name is taken. Use this for getting the user name from a client certificate.
val get_user : session -> string
Returns the user name as returned by the authentication method. See the description of the method for the format of the user name string.
val get_auth_method : session -> auth_method
Returns the method that was used to authenticate the user.
val xdr_ctx : t -> Netxdr.ctx
Get the recommended XDR context
val verbose : bool -> unit
Deprecated. Set whether you want debug messages to stderr or not
val detach : t -> unit
Internal function. Cancels all pending I/O operations, and deallocates buffers. This function has only one purpose: The RPC servers inherited by a Netplex child process return memory. The RPC server is unusable after this.
val set_debug_name : t -> string -> unit
Set a name printed with debug messages
val get_debug_name : t -> string
Get the debug name
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Nethttpd_engine.http_request_header_notification-c.html0000644000175000017500000005526012731530352027441 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_request_header_notification

Class type Nethttpd_engine.http_request_header_notification

class type http_request_header_notification = object .. end

Notification that a new request header has arrived

This object notifies the user that a new request header has arrived. The header is accessible by the environment object. The channels also contained in this object are locked at this moment. The user must now either call schedule_accept_body or schedule_reject_body. The user will get a second notification (a http_request_notification, below) when the request body has completely arrived (in case of acceptance), or immediately (in case of rejection). One can also call schedule_finish at any time to drop the current request.

method req_state : engine_req_state
Returns the request processing state which is `Received_header at the moment when this notification is delivered.
method environment : extended_async_environment
The request environment. Depending on the request processing state, parts of the environment are already set up or still unaccessible ("locked"). In the state `Received_header only the request header and the derived fields are accessible, and the input and output channels are locked. In the state `Receiving_body the input channel is unlocked, but it is not yet filled (reading from it may cause the exception Buffer_underrun). The output channel remains locked. In the state `Received_request, the input channel is unlocked and filled with data, and the output channel is unlocked, too.

This environment is not fully CGI-compatible. In particular, the following differences exist:

  • There is no cgi_path_info and no cgi_path_translated.
  • The user is always unauthenticated.
  • The Status response header works as in CGI. The Location header, however, must be a full URL when set (only browser redirects)
  • When the request body is transmitted by chunked encoding, the header Content-Length is not set. In CGI this is interpreted as missing body. It is unlikely that clients send requests with chunked encoding, as this may cause interoperability problems anyway.

method schedule_accept_body : on_request:(http_request_notification -> unit) ->
?on_error:(unit -> unit) -> unit -> unit
Schedules that the request body is accepted. In terms of HTTP, this sends the "100 Continue" response when necessary. One can reply with a positive or negative message.

This method returns immediately, and sets callbacks for certain events. When the body has completely arrived (or is empty), the function on_request is called back. The argument is the full request notification (see below).

When the request is dropped for some reason, on_error is called back instead. This can be used to free resources, for example.

Neither of the callbacks must raise exceptions.

method schedule_reject_body : on_request:(http_request_notification -> unit) ->
?on_error:(unit -> unit) -> unit -> unit
Schedules that the request body is rejected. In terms of HTTP, this prevents sending the "100 Continue" response. Any arriving request body is silently discarded. One should immediately reply with an error mesage. negative message.

This method returns immediately, and sets callbacks for certain events. When the body has completely arrived (or is empty), the function on_request is called back. The argument is the full request notification (see below).

When the request is dropped for some reason, on_error is called back instead. This can be used to free resources, for example.

Neither of the callbacks must raise exceptions.

method schedule_finish : unit -> unit
Schedules that the request is finished. This method should be called after the regular processing of the request to ensure that the HTTP protocol is fulfilled. If the request body has not been fully read, this is now done, and its data are dropped. If the response is incomplete, it is completed. If the error is not recoverable, a "Server Error" is generated.
ocamlnet-4.1.2/doc/html-main/Netmime.file_mime_body-c.html0000644000175000017500000004351612731530352022057 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.file_mime_body

Class Netmime.file_mime_body

class file_mime_body : ?fin:bool -> string -> mime_body
An implementation of mime_body where the value is stored in an external file.

The argument is the name of the file containing the (decoded) value. The method store returns `File filename. The method value loads the contents of the file and returns them as string.

Example: To create a body from the file "f", call

 new file_mime_body "f" 


fin : whether to delete the file when the finalize method is called (default: false)

ocamlnet-4.1.2/doc/html-main/type_Netplex_types.processor.html0000644000175000017500000005271712731530352023224 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.processor object
  method config_internal : (string * Netplex_types.polysocket_kind_box) list
  method container_event_system : unit -> Unixqueue.event_system
  method container_run : Unixqueue.event_system -> unit
  method global_exception_handler : exn -> bool
  method post_add_hook :
    Netplex_types.socket_service -> Netplex_types.controller -> unit
  method post_finish_hook :
    Netplex_types.socket_service ->
    Netplex_types.controller -> Netplex_types.container_id -> unit
  method post_rm_hook :
    Netplex_types.socket_service -> Netplex_types.controller -> unit
  method post_start_hook : Netplex_types.container -> unit
  method pre_finish_hook : Netplex_types.container -> unit
  method pre_start_hook :
    Netplex_types.socket_service ->
    Netplex_types.controller -> Netplex_types.container_id -> unit
  method process :
    when_done:(unit -> unit) ->
    Netplex_types.container -> Unix.file_descr -> string -> unit
  method process_internal :
    when_done:(unit -> unit) ->
    Netplex_types.container -> Netplex_types.polyserver_box -> string -> unit
  method receive_admin_message :
    Netplex_types.container -> string -> string array -> unit
  method receive_message :
    Netplex_types.container -> string -> string array -> unit
  method shutdown : unit -> unit
  method supported_ptypes : Netplex_types.parallelization_type list
  method system_shutdown : unit -> unit
  method workload_hook : Netplex_types.container -> bool -> int -> unit
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.key-c.html0000644000175000017500000004635212731530352021273 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.key

Class type Nethttp_client.key

class type key = object .. end
A key is a user/password combination for a certain realm

method user : string
The user name (UTF-8)
method password : string
The password in cleartext (UTF-8)
method realm : string
The realm
method domain : Neturl.url list
The domain URIs defining the protection space. The domain URIs are absolute URIs. For proxy access the list must be empty.

Normally, this is just a list with one element. The URI must include the protocol scheme, the host name, the port, and a path (at minimum "/"). The key is valid for all request URIs for which this domain string is a prefix of the request URI. Examples: "http://localhost:80/" would cover all of "localhost". "http://localhost:80/space/" would cover all URIs at this or below this URI. "https://localhost:443/" would cover all of "localhost" when accessed via TLS.

If the key is applicable to all domains, set this to [].

method credentials : (string * string * (string * string) list) list
The key in the common "credentials" format that is used by generic mechanisms. See Nethttp.HTTP_CLIENT_MECHANISM.init_credentials for details.

Note that since Ocamlnet-4.1 we explicitly specify that cleartext passwords are encoded in UTF-8 - independently of what the protocol assumes.

ocamlnet-4.1.2/doc/html-main/Unixqueue.html0000644000175000017500000015753312731530352017274 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue

Module Unixqueue

module Unixqueue: sig .. end
Unixqueues are one of the two forms of system event loops provided by Ocamlnet. Besides Unixqueue, there is also pollset (see Netsys_pollset). The pollsets are much simpler (there is no queuing of events), and nowadays Unixqueue bases upon pollset, and extends its functionality. Historically, however, Unixqueue precede pollset, and there are still implementations of the former in Ocamlnet not using pollset as its base data structure.

The common idea of both data structures is the generalization of watching for events, as it is also provided by the Unix.select function. Note, however, that recent implementations no longer use Unix.select, but better system interfaces for the same.

When there is something to do for a file descriptor (reading, writing, accepting out-of-band data), this is called an event, and the task of Unixqueue is to check when events happen, and to tell some consumer about the events.

There are three further types of events: Timeout events, signal events, and user-defined events.

The events are queued up, and they are presented to event handlers that may process them.

You can describe what types of event conditions are watched by adding resources. You can think a resource being a condition (bound to a real resource of the operating system) for which events are generated if the condition becomes true. Currently, only file descriptors and timers are supported as resources.



Unixqueues are one of the two forms of system event loops provided by Ocamlnet. Besides Unixqueue, there is also pollset (see Netsys_pollset). The pollsets are much simpler (there is no queuing of events), and nowadays Unixqueue bases upon pollset, and extends its functionality. Historically, however, Unixqueue precede pollset, and there are still implementations of the former in Ocamlnet not using pollset as its base data structure.

The common idea of both data structures is the generalization of watching for events, as it is also provided by the Unix.select function. Note, however, that recent implementations no longer use Unix.select, but better system interfaces for the same.

When there is something to do for a file descriptor (reading, writing, accepting out-of-band data), this is called an event, and the task of Unixqueue is to check when events happen, and to tell some consumer about the events.

There are three further types of events: Timeout events, signal events, and user-defined events.

The events are queued up, and they are presented to event handlers that may process them.

You can describe what types of event conditions are watched by adding resources. You can think a resource being a condition (bound to a real resource of the operating system) for which events are generated if the condition becomes true. Currently, only file descriptors and timers are supported as resources.

Unixqueues are one of the two forms of system event loops provided by Ocamlnet. Besides Unixqueue, there is also pollset (see Netsys_pollset). The pollsets are much simpler (there is no queuing of events), and nowadays Unixqueue bases upon pollset, and extends its functionality. Historically, however, Unixqueue precede pollset, and there are still implementations of the former in Ocamlnet not using pollset as its base data structure.

The common idea of both data structures is the generalization of watching for events, as it is also provided by the Unix.select function. Note, however, that recent implementations no longer use Unix.select, but better system interfaces for the same.

When there is something to do for a file descriptor (reading, writing, accepting out-of-band data), this is called an event, and the task of Unixqueue is to check when events happen, and to tell some consumer about the events.

There are three further types of events: Timeout events, signal events, and user-defined events.

The events are queued up, and they are presented to event handlers that may process them.

You can describe what types of event conditions are watched by adding resources. You can think a resource being a condition (bound to a real resource of the operating system) for which events are generated if the condition becomes true. Currently, only file descriptors and timers are supported as resources.

Relation to other modules. This module is thought as the primary interface to Unixqueues. If there isn't any specialty one has to deal with, just use this module:

  • It defines all required types like group, wait_id, etc. Note that these types are reexported from Unixqueue_util. Please consider this as implementation detail, and don't use it in your code.
  • It defines a standard implementation standard_event_system, which is a good default implementation, although it might not be the best available for all purposes.
  • It defines a set of access functions like add_event which simply call the methods of the event system object of the same name. Note that these functions work for all event system implementation, not only for standard_event_system.
There are further modules that have to do with Unixqueue:

  • Unixqueue_pollset is the implementation behind standard_event_system. If you want to use other pollsets than the standard one, it is possible to create Unixqueues on top of these by using this module directly.
  • Unixqueue_select is the historic default implementation. It calls directly Unix.select. It is still available because it serves as a reference implementation for now.
  • Unixqueue_util is an internal module with implementation details. Please don't call it directly.
  • Uq_gtk is an implementation of Unixqueue mapping to the GTK event loop. Useful for multiplexing event-based I/O and GTK graphics operations.
  • Uq_tcl is an implementation of Unixqueue mapping to the TCL event loop. Useful for multiplexing event-based I/O and event-based code written in TCL (especially TK).


Unixqueues are one of the two forms of system event loops provided by Ocamlnet. Besides Unixqueue, there is also pollset (see Netsys_pollset). The pollsets are much simpler (there is no queuing of events), and nowadays Unixqueue bases upon pollset, and extends its functionality. Historically, however, Unixqueue precede pollset, and there are still implementations of the former in Ocamlnet not using pollset as its base data structure.

The common idea of both data structures is the generalization of watching for events, as it is also provided by the Unix.select function. Note, however, that recent implementations no longer use Unix.select, but better system interfaces for the same.

When there is something to do for a file descriptor (reading, writing, accepting out-of-band data), this is called an event, and the task of Unixqueue is to check when events happen, and to tell some consumer about the events.

There are three further types of events: Timeout events, signal events, and user-defined events.

The events are queued up, and they are presented to event handlers that may process them.

You can describe what types of event conditions are watched by adding resources. You can think a resource being a condition (bound to a real resource of the operating system) for which events are generated if the condition becomes true. Currently, only file descriptors and timers are supported as resources.

Relation to other modules. This module is thought as the primary interface to Unixqueues. If there isn't any specialty one has to deal with, just use this module:

  • It defines all required types like group, wait_id, etc. Note that these types are reexported from Unixqueue_util. Please consider this as implementation detail, and don't use it in your code.
  • It defines a standard implementation standard_event_system, which is a good default implementation, although it might not be the best available for all purposes.
  • It defines a set of access functions like add_event which simply call the methods of the event system object of the same name. Note that these functions work for all event system implementation, not only for standard_event_system.
There are further modules that have to do with Unixqueue:

  • Unixqueue_pollset is the implementation behind standard_event_system. If you want to use other pollsets than the standard one, it is possible to create Unixqueues on top of these by using this module directly.
  • Unixqueue_select is the historic default implementation. It calls directly Unix.select. It is still available because it serves as a reference implementation for now.
  • Unixqueue_util is an internal module with implementation details. Please don't call it directly.
  • Uq_gtk is an implementation of Unixqueue mapping to the GTK event loop. Useful for multiplexing event-based I/O and GTK graphics operations.
  • Uq_tcl is an implementation of Unixqueue mapping to the TCL event loop. Useful for multiplexing event-based I/O and event-based code written in TCL (especially TK).


Thread safety. The default implementation of Unixqueue is thread-safe, and operations can be called from different threads. For other implementations, please look at the modules implementing them.

Unixqueues are one of the two forms of system event loops provided by Ocamlnet. Besides Unixqueue, there is also pollset (see Netsys_pollset). The pollsets are much simpler (there is no queuing of events), and nowadays Unixqueue bases upon pollset, and extends its functionality. Historically, however, Unixqueue precede pollset, and there are still implementations of the former in Ocamlnet not using pollset as its base data structure.

The common idea of both data structures is the generalization of watching for events, as it is also provided by the Unix.select function. Note, however, that recent implementations no longer use Unix.select, but better system interfaces for the same.

When there is something to do for a file descriptor (reading, writing, accepting out-of-band data), this is called an event, and the task of Unixqueue is to check when events happen, and to tell some consumer about the events.

There are three further types of events: Timeout events, signal events, and user-defined events.

The events are queued up, and they are presented to event handlers that may process them.

You can describe what types of event conditions are watched by adding resources. You can think a resource being a condition (bound to a real resource of the operating system) for which events are generated if the condition becomes true. Currently, only file descriptors and timers are supported as resources.

Relation to other modules. This module is thought as the primary interface to Unixqueues. If there isn't any specialty one has to deal with, just use this module:

  • It defines all required types like group, wait_id, etc. Note that these types are reexported from Unixqueue_util. Please consider this as implementation detail, and don't use it in your code.
  • It defines a standard implementation standard_event_system, which is a good default implementation, although it might not be the best available for all purposes.
  • It defines a set of access functions like add_event which simply call the methods of the event system object of the same name. Note that these functions work for all event system implementation, not only for standard_event_system.
There are further modules that have to do with Unixqueue:

  • Unixqueue_pollset is the implementation behind standard_event_system. If you want to use other pollsets than the standard one, it is possible to create Unixqueues on top of these by using this module directly.
  • Unixqueue_select is the historic default implementation. It calls directly Unix.select. It is still available because it serves as a reference implementation for now.
  • Unixqueue_util is an internal module with implementation details. Please don't call it directly.
  • Uq_gtk is an implementation of Unixqueue mapping to the GTK event loop. Useful for multiplexing event-based I/O and GTK graphics operations.
  • Uq_tcl is an implementation of Unixqueue mapping to the TCL event loop. Useful for multiplexing event-based I/O and event-based code written in TCL (especially TK).


Thread safety. The default implementation of Unixqueue is thread-safe, and operations can be called from different threads. For other implementations, please look at the modules implementing them.

Types and exceptions


type group = Unixqueue_util.group 
A group is an abstract tag for a set of events, resources, and event handlers. Usually every event handler creates a new group, and all events and resources processed by the handler are members of this group.
exception Abort of (group * exn)
Event handlers can raise this exception to cancel a group of handlers, events, and resources. If an abort action is defined for the group, it will be executed. Next, all members of the group are removed from the event system.

First argument is the group. The second argument is an arbitrary exception (must not be Abort again) which is passed to the abort action.

Abort handlers are a questionable feature of Unixqueues. You can also call the clear operation, and raise the exception directly. Do not use in new code!

type wait_id = Unixqueue_util.wait_id 
A wait identifier is used to distinguish between several timers, see type operation.
type operation = Unixqueue_util.operation = 
| Wait_in of Unix.file_descr (*
wait for input data
*)
| Wait_out of Unix.file_descr (*
wait until output can be written
*)
| Wait_oob of Unix.file_descr (*
wait for out-of-band data
*)
| Wait of wait_id (*
wait only for timeout
*)
An operation specifies the condition to wait for. Every kind of operation may have an associated timer (not only Wait).
type event = Unixqueue_util.event = 
| Input_arrived of (group * Unix.file_descr) (*
Input data has arrived
*)
| Output_readiness of (group * Unix.file_descr) (*
Output is possible now
*)
| Out_of_band of (group * Unix.file_descr) (*
OOB data has arrived
*)
| Timeout of (group * operation) (*
A timer has expired
*)
| Signal (*
A signal has happened
*)
| Extra of exn (*
User-generated event
*)
| Immediate of (group * (unit -> unit)) (*
immediate event
*)
An event is triggered when the condition of an operation becomes true, when a signal happens, or when the event is (artificially) added to the event queue (add_event, below). The events resulting from an operation carry the group of the resource with them.

The event Signal is triggered when the EINTR condition is caught; this normally means that a signal has just been delivered. The generation of Signal events should be considered as unreliable, not every signal delivery can be detected. Reasons for the unrealiability are that user-supplied code happens to get the EINTR condition and not the Unixqueue event loop, and that there are known race conditions in the O'Caml signal handling routines that may cause signals to be lost. However, it can be expected that almost all signals will trigger Signal.

The event Extra can only be artificially added to the queue, and the argument of Extra is an exception value that distinguishes between several kinds of user-generated events.

The event Immediate(g,f) also can only be artificially added to the queue. In contrast to other events, it is not passed to handlers when the event is processed. Instead, an immediate event is processed by calling f(). This is a more direct way of notification, and it is not necessary to define a handler. Even an immediate event is member of a group g, and if the clear function is called for g, the callback function f will no longer be called.

class type event_system = object .. end
The event_system manages events, handlers, resources, groups, etc.

Creating event systems


class standard_event_system : unit -> event_system
The standard implementation of an event system.
val standard_event_system : unit -> event_system
Create a new, empty, standard event system
class unix_event_system : unit -> event_system
An alternate name for standard_event_system, provided for backward compatibility.
val create_unix_event_system : unit -> event_system
An alternate name for standard_event_system, provided for backward compatibility.
class performance_event_system : unit -> event_system
The implementation using Netsys_pollset_generic.performance_pollset.
val performance_event_system : unit -> event_system
Same as function

Using event systems



Using event systems



The following functions work for all kinds of event systems, not only for the ones returned by standard_event_system.
val new_group : event_system -> group
Create a new, empty group for the event system
val new_wait_id : event_system -> wait_id
Create a new unique wait identifier
val exists_resource : event_system -> operation -> bool
Find out if a specific resource already exists (or better: is already watched by an operation).
val add_resource : event_system ->
group -> operation * float -> unit
Add a resource such that it is watched for conditions described by the operation for the period given by the float number. A negative number means that the resource is watched for an infinite period. The resource becomes a member of the group.

You cannot add the same operation several times; if you try it the second operation is silently dropped.

The resource remains even if it has generated an event. The timeout period starts again in this case.

val add_weak_resource : event_system ->
group -> operation * float -> unit
Similar to add_resource, but the resource is weak. Such resources do not keep the event system running when only weak resources remain. Normally, Unixqueue.run returns to the caller not before all resources are removed and all events are processed. Weak resources do not count for this condition, i.e. Unixqueue.run also returns when there are only weak resources left. As an example, weak resources can be used to time out unused file descriptors.

Weak resources can be removed with remove_resource.

New in Ocamlnet 3.

val add_close_action : event_system ->
group -> Unix.file_descr * (Unix.file_descr -> unit) -> unit
A close action is added for the file descriptor. The action callback (which gets the descriptor as argument) is called when there is not any watched resource remaining for this descriptor.

This may be useful if the descriptor can be closed in this case.

The close action becomes member of the passed group. The only effect of this is that the action is removed when the clear function is called.

You can only add (set) one close action for every descriptor.

Of course, the idea is to do add_close_action ... Unix.close. Note that there is a problem with multi-threaded programs, and this construct must not be used there. In particular, the close action is called from remove_resource or clear, but it is possible that the event system is running, so a watched descriptor might be closed. This has undesired effects. What you should better do is to delay the closure of the descriptor to a sane moment, e.g. by calling

 Unixqueue.once esys g 0.0 (fun () -> Unix.close fd) 
from the close action.
val add_abort_action : event_system ->
group -> (group -> exn -> unit) -> unit
An abort action is added to the group. The action callback is called when an arbitrary handler raises Abort(g,exn) where g is the group the abort action is member of. In this case, the callback function is invoked with the group and exn as arguments. After that, the group is cleared.

You can only add (set) one abort action for every group.

val remove_resource : event_system -> group -> operation -> unit
Removes the operation from the watch list of the group. It is an error if the operation is member of another group. If the operation cannot be found at all, the exception Not_found will be raised.

The removal of resources may trigger close actions.

val add_handler : event_system ->
group ->
(event_system ->
event Equeue.t -> event -> unit) ->
unit
Add an event handler that is associated to the given group. There may be several handlers for a group.

The handler callback function is invoked when there is an event that could be processeable by the handler. As outlined above, the callback function can accept or reject the event, it can terminate itself, and it can abort the whole group.

val add_event : event_system -> event -> unit
Add an additional event. The event will be processed after the current list of events is done.
val clear : event_system -> group -> unit
Terminate the whole group. This means that the handlers of the group are not called any longer, and that all resources and actions are removed. It is possible that there are pending events after termination, but these will be usually be dropped because there is no handler for them.

When a group is terminated, it is not allowed to refer to the group any longer. Functions will raise Invalid_argument if this is tried nevertheless.

val run : event_system -> unit
Starts the event loop. This means that the resources are watched, and that events are generated, and that handlers are called.

The event loop returns normally when there are not any resources and not any events in the queue. The loop raises Equeue.Out_of_handlers if there are resources but no handlers to process their events. It is possible that exceptions raised from handlers fall through to the run call.

After the exception is caught and processed, the event loop can be restarted.

val is_running : event_system -> bool
Whether the event loop is running
val once : event_system -> group -> float -> (unit -> unit) -> unit
Arranges that the callback function is called once after the passed period of time (the float argument) has elapsed.

The arrangement is member of the passed group. By clearing the group, the timer is deleted, too.

val weak_once : event_system -> group -> float -> (unit -> unit) -> unit
Same as once, but the timer does not keep the event system running if it is the only remaining resource.
val epsilon : event_system -> (unit -> unit) -> unit
The execution of the function is pushed onto the event queue (minimal delay)

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Nettls_gnutls.GNUTLS_PROVIDER.html0000644000175000017500000004344512731530352022472 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.GNUTLS_PROVIDER

Module type Nettls_gnutls.GNUTLS_PROVIDER

module type GNUTLS_PROVIDER = sig .. end

include Netsys_crypto_types.TLS_PROVIDER
val gnutls_session : endpoint -> Nettls_gnutls_bindings.gnutls_session_t
Get the gnutls_session of the endpoint
val gnutls_credentials : credentials -> Nettls_gnutls_bindings.gnutls_credentials
Get the gnutls_credentials of the generic credentials
ocamlnet-4.1.2/doc/html-main/type_Netsmtp.html0000644000175000017500000005675112731530352017777 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsmtp sig
  exception Protocol_error
  exception Authentication_error
  exception Transient_error of int * string
  exception Permanent_error of int * string
  val tcp_port : int
  class client :
    Netchannels.in_obj_channel ->
    Netchannels.out_obj_channel ->
    object
      method auth :
        Netsys_sasl.sasl_mechanism ->
        string ->
        string ->
        Netsys_sasl.credentials -> (string * string * bool) list -> unit
      method authenticated : bool
      method close : unit -> unit
      method command : string -> int * string list
      method data : Netchannels.in_obj_channel -> unit
      method expn : string -> string list option
      method gssapi_props : Netsys_gssapi.client_props option
      method helo : ?host:string -> unit -> string list
      method helo_response : string list
      method help : unit -> string list
      method mail : string -> unit
      method noop : unit -> unit
      method quit : unit -> unit
      method rcpt : string -> unit
      method rset : unit -> unit
      method starttls :
        peer_name:string option -> Netsys_crypto_types.tls_config -> unit
      method tls_endpoint : Netsys_crypto_types.tls_endpoint option
      method tls_session_props : Nettls_support.tls_session_props option
    end
  class connect :
    ?proxy:#Uq_engines.client_endpoint_connector ->
    Uq_engines.connect_address -> float -> client
  val auth_mechanisms : string list -> string list
  val authenticate :
    ?host:string ->
    ?tls_config:Netsys_crypto_types.tls_config ->
    ?tls_required:bool ->
    ?tls_peer:string ->
    ?sasl_mechs:Netsys_sasl.sasl_mechanism list ->
    ?sasl_params:(string * string * bool) list ->
    ?user:string ->
    ?authz:string -> ?creds:Netsys_sasl.credentials -> Netsmtp.client -> unit
  val sendmail : Netsmtp.client -> Netmime.complex_mime_message -> unit
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Netchannels.input_descr-c.html0000644000175000017500000004446712731530352022305 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_descr

Class Netchannels.input_descr

class input_descr : ?blocking:bool -> ?start_pos_in:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_in_channel
Creates a raw_in_channel for the passed file descriptor, which must be open for reading.

The pos_in method returns logical positions, i.e. it counts the number of read octets. It is not tried to determine the real file position.

The method close_in also closes the file descriptor.

This class also supports Win32 proxy descriptors referring to an input channel.


blocking : Whether the channel waits for data if it is not possible to read from the (non-blocking) descriptor. Defaults to true.
start_pos_in : The position to which pos_in is initialized when the channel is created, by default 0
fd_style : The descriptor style. If omitted, it is automatically determined if possible.

ocamlnet-4.1.2/doc/html-main/Netsys_gssapi.GSSAPI.html0000644000175000017500000004747712731530352021131 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.GSSAPI

Module type Netsys_gssapi.GSSAPI

module type GSSAPI = sig .. end


The General Security Services API

The General Security Services API

See also Netsys_gssapi for additional type definitions
type credential 
A credential is opaque for the caller of the GSS-API. The provider of the GSS-API can emit new credential objects, and hand them out to the caller.
type context 
A context is also opaque.
type name 
A name is also opaque

Exceptions



Exceptions



There are no defined exceptions for reporting errors.

Errors should be reported using the major_status and minor_status codes as much as possible.

Invalid_argument may be raised for clear violations of calling requirements, e.g. when an opaque object is passed to this interface that was not returned by it before.

The following three exceptions can be used to wrap the per-GSSAPI types credential, context, and name:

exception Credential of credential
exception Context of context
exception Name of name

The API


class type gss_api = [[credential, name
, context]]
Netsys_gssapi.poly_gss_api
The methods have generally a type of the form
val interface : gss_api
ocamlnet-4.1.2/doc/html-main/Netaddress.html0000644000175000017500000005136512731530352017374 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaddress

Module Netaddress

module Netaddress: sig .. end
Parsing of mail addresses


Addresses indicate the senders and recipients of messages and correspond to either an individual mailbox or a group of mailboxes.
type local_part = string 
Usually the user name
type domain = string 
The domain of the mailbox
type addr_spec = local_part * domain option 
The pair local_part@domain as O'Caml type. The domain may be missing.
class mailbox : ?name:string -> string list -> addr_spec -> object .. end
A mailbox has a name, optionally a route (not used nowadays), and a formal address specification.
class group : string -> mailbox list -> object .. end
A group has a name, and consists of a number of mailboxes.
type t = [ `Group of group | `Mailbox of mailbox ] 
The union of mailbox and group
exception Parse_error of int * string
A parsing error. The int is the position in the parsed string
val parse : string -> t list
Parse a list of addresses in string representation, and return them as list of mailboxes or groups.

Examples:

  • parse "gerd@gerd-stolpmann.de" returns a single mailbox without name and route, and the given spec
  • parse "Gerd Stolpmann <gerd@gerd-stolpmann.de>" returns a single mailbox with name and spec, but without route
  • parse "abc@def.net, ghi" returns two mailboxes without name and route, and the two specs. The second address only has a local part, but no domain.
  • parse "g:abc@def.net, Me <me@domain.net>;, gs@npc.de" returns one group g with members abc@def.net and me@domain.net, and another mailbox gs@npc.de.
Old-style naming of mailboxes is not supported (e.g. "gerd@gerd-stolpmann.de (Gerd Stolpmann)" - the part in parentheses is simply ignored.
ocamlnet-4.1.2/doc/html-main/Uq_libevent.html0000644000175000017500000004457312731530352017560 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_libevent

Module Uq_libevent

module Uq_libevent: sig .. end
Use Libevent as event loop


This gives (experimental) support for using libevent as event loop. To do so, you also need Maas-Maarten Zeeman's bindings for libevent, ocaml-event. (N.B. The current name, changed several times, is now liboevent.)

Restrictions:

  • ocaml-event is not thread-safe
  • There can only be one instance of the event loop at a time
  • It is not supported to wait for out of band data
  • Signals do not stop the event loop. As a consequence, signals are delayed until the next event occurs.

module type LIBOEVENT = sig .. end
module type POLLSET = sig .. end
module Make: 
functor (L : LIBOEVENT) -> POLLSET
Instantiate this module.
ocamlnet-4.1.2/doc/html-main/type_Netchannels_crypto.tls_layer.html0000644000175000017500000004236512731530352024200 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.tls_layer ?start_pos_in:int ->
?start_pos_out:int ->
?resume:string ->
role:[ `Client | `Server ] ->
rd:Netchannels.raw_in_channel ->
wr:Netchannels.raw_out_channel ->
peer_name:string option ->
Netsys_crypto_types.tls_config -> Netchannels_crypto.tls_channel
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.empty_environment.html0000644000175000017500000006144212731530352025135 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.empty_environment object
  val mutable config : Netcgi.config
  val mutable in_channel : Netchannels.in_obj_channel
  val mutable in_header : Nethttp.http_header
  val mutable out_channel : Netchannels.out_obj_channel
  val mutable out_header : Nethttp.http_header
  val mutable properties : (string * string) list
  val mutable protocol : Nethttp.protocol
  val mutable tls_session_props : Nettls_support.tls_session_props option
  method cgi_auth_type : string
  method cgi_gateway_interface : string
  method cgi_https : bool
  method cgi_path_info : string
  method cgi_path_translated : string
  method cgi_properties : (string * string) list
  method cgi_property : ?default:string -> string -> string
  method cgi_query_string : string
  method cgi_remote_addr : string
  method cgi_remote_host : string
  method cgi_remote_ident : string
  method cgi_remote_user : string
  method cgi_request_method : string
  method cgi_request_uri : string
  method cgi_script_name : string
  method cgi_server_name : string
  method cgi_server_port : int option
  method cgi_server_protocol : string
  method cgi_server_software : string
  method config : Netcgi.config
  method cookie : string -> Netcgi.Cookie.t
  method cookies : Netcgi.Cookie.t list
  method input_body_size : int64
  method input_channel : Netchannels.in_obj_channel
  method input_content_length : int
  method input_content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method input_content_type_string : string
  method input_header : Netmime.mime_header
  method input_header_field : ?default:string -> string -> string
  method input_header_fields : (string * string) list
  method log_error : string -> unit
  method log_props : (string * string) list -> unit
  method multiple_input_header_field : string -> string list
  method multiple_output_header_field : string -> string list
  method out_channel : Netchannels.out_obj_channel
  method output_ch : Netchannels.out_obj_channel
  method output_header : Netmime.mime_header
  method output_header_field : ?default:string -> string -> string
  method output_header_fields : (string * string) list
  method virtual output_state : output_state ref
  method protocol : Nethttp.protocol
  method virtual remote_socket_addr : Unix.sockaddr
  method request_body_rejected : bool
  method send_file : Unix.file_descr -> int64 -> unit
  method send_output_header : unit -> unit
  method virtual server_socket_addr : Unix.sockaddr
  method set_multiple_output_header_field : string -> string list -> unit
  method set_output_header_field : string -> string -> unit
  method set_output_header_fields : (string * string) list -> unit
  method set_status : Nethttp.http_status -> unit
  method tls_session_props : Nettls_support.tls_session_props option
  method user_agent : string
end
ocamlnet-4.1.2/doc/html-main/type_Uq_gtk.html0000644000175000017500000004174512731530352017574 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_gtk sig
  type runner = Unixqueue.event_system -> (unit -> unit) -> unit
  class gtk_event_system :
    ?run:Uq_gtk.runner -> unit -> Unixqueue.event_system
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.server_endpoint_acceptor-c.html0000644000175000017500000004412112731530352026235 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.server_endpoint_acceptor

Class type Uq_engines_compat.server_endpoint_acceptor

class type server_endpoint_acceptor = object .. end

method server_address : connect_address
method multiple_connections : bool
method accept : unit ->
(Unix.file_descr * inetspec option)
engine
method shut_down : unit -> unit
ocamlnet-4.1.2/doc/html-main/Nethttpd_kernel.lingering_close-c.html0000644000175000017500000004452312731530352024012 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.lingering_close

Class Nethttpd_kernel.lingering_close

class lingering_close : ?preclose:unit -> unit -> Unix.file_descr -> object .. end
Closes a file descriptor using the "lingering close" algorithm. The optional preclose function is called just before Unix.close.

Closes a file descriptor using the "lingering close" algorithm

Usage:

 while lc # lingering do lc # cycle ~block:true () done 
method cycle : ?block:bool -> unit -> unit
Reads data from the file descriptor until EOF or until a fixed timeout is over. Finally, the descriptor is closed. If block is set, the method blocks until data is available. (Default: false)
method lingering : bool
Whether the socket is still lingering
method fd : Unix.file_descr
The file descriptor
ocamlnet-4.1.2/doc/html-main/Netplex_types.controller_config-c.html0000644000175000017500000004511112731530352024062 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.controller_config

Class type Netplex_types.controller_config

class type controller_config = object .. end

method socket_directory : string
The directory where Unix domain sockets are created. For every service a subdirectory is created, and the socket has the name of the protocol.

This is always an absolute path, even if it is only given as relative path in the config file.

method create_logger : controller -> logger
Create a logger to be used for the whole Netplex system. The controller is already initialized which makes it possible to write the logger as Netplex service. Messages arriving during the creation are queued up and sent afterwards to the new logger.
method max_level : level
Return the maximum global log level
method set_max_level : level -> unit
Set the maximum global log level
ocamlnet-4.1.2/doc/html-main/Netgzip.output_inflate-c.html0000644000175000017500000004305412731530352022175 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.output_inflate

Class Netgzip.output_inflate

class output_inflate : Netchannels.out_obj_channel -> Netchannels.out_obj_channel
let ch' = new output_inflate ch: Data written to ch' is inflated and written to ch. Use this for uncompressing data while writing.

Note that ch isn't closed when ch' is closed.


ocamlnet-4.1.2/doc/html-main/Netplex_types.ctrl_message_receiver-c.html0000644000175000017500000004430112731530352024706 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.ctrl_message_receiver

Class type Netplex_types.ctrl_message_receiver

class type ctrl_message_receiver = object .. end

method name : string
The name of this receiver
method receive_message : controller -> string -> string array -> unit
This function is called when a broadcast message is received. The first string is the name of the message, and the array are the arguments.
method receive_admin_message : controller -> string -> string array -> unit
This function is called when a broadcast admin message is received. The first string is the name of the message, and the array are the arguments.
ocamlnet-4.1.2/doc/html-main/type_Netx509_pubkey_crypto.html0000644000175000017500000004500112731530352022462 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey_crypto sig
  exception Unsupported_algorithm of Netoid.t
  val is_encryption_supported : Netx509_pubkey.encrypt_alg -> bool
  val is_signing_supported : Netx509_pubkey.sign_alg -> bool
  val encrypt :
    Netx509_pubkey.encrypt_alg -> Netx509_pubkey.pubkey -> string -> string
  val decrypt :
    Netx509_pubkey.encrypt_alg -> Netx509_pubkey.privkey -> string -> string
  val verify :
    Netx509_pubkey.sign_alg ->
    Netx509_pubkey.pubkey -> string -> string -> bool
  val sign :
    Netx509_pubkey.sign_alg -> Netx509_pubkey.privkey -> string -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_mem.html0000644000175000017500000010645512731530352020465 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_mem sig
  type memory = Netsys_types.memory
  val blit_memory_to_bytes :
    Netsys_mem.memory -> int -> Bytes.t -> int -> int -> unit
  val blit_memory_to_string :
    Netsys_mem.memory -> int -> Bytes.t -> int -> int -> unit
  external blit_memory_to_bytes_unsafe :
    Netsys_mem.memory -> int -> Bytes.t -> int -> int -> unit
    = "netsys_blit_memory_to_string" "noalloc"
  external blit_memory_to_string_unsafe :
    Netsys_mem.memory -> int -> Bytes.t -> int -> int -> unit
    = "netsys_blit_memory_to_string" "noalloc"
  val blit_bytes_to_memory :
    Bytes.t -> int -> Netsys_mem.memory -> int -> int -> unit
  external blit_bytes_to_memory_unsafe :
    Bytes.t -> int -> Netsys_mem.memory -> int -> int -> unit
    = "netsys_blit_string_to_memory" "noalloc"
  val blit_string_to_memory :
    string -> int -> Netsys_mem.memory -> int -> int -> unit
  external blit_string_to_memory_unsafe :
    string -> int -> Netsys_mem.memory -> int -> int -> unit
    = "netsys_blit_string_to_memory" "noalloc"
  val memory_of_bytes : Bytes.t -> Netsys_mem.memory
  val memory_of_string : string -> Netsys_mem.memory
  val bytes_of_memory : Netsys_mem.memory -> Bytes.t
  val string_of_memory : Netsys_mem.memory -> string
  val memory_address : Netsys_mem.memory -> nativeint
  val memory_of_bigarray :
    ('a, 'b, 'c) Bigarray.Genarray.t -> Netsys_mem.memory
  val memory_of_bigarray_1 :
    ('a, 'b, 'c) Bigarray.Array1.t -> Netsys_mem.memory
  val memory_of_bigarray_2 :
    ('a, 'b, 'c) Bigarray.Array2.t -> Netsys_mem.memory
  val memory_of_bigarray_3 :
    ('a, 'b, 'c) Bigarray.Array3.t -> Netsys_mem.memory
  val getpagesize : unit -> int
  val pagesize : int
  val alloc_memory_pages :
    ?addr:nativeint -> ?exec:bool -> int -> Netsys_mem.memory
  val alloc_aligned_memory : int -> int -> Netsys_mem.memory
  val memory_map_file :
    Unix.file_descr ->
    ?pos:int64 -> ?addr:nativeint -> bool -> int -> Netsys_mem.memory
  val memory_unmap_file : Netsys_mem.memory -> unit
  val zero_pages : Netsys_mem.memory -> int -> int -> unit
  val grab : nativeint -> int -> Netsys_mem.memory
  val as_value : Netsys_mem.memory -> int -> 'a
  val as_obj : Netsys_mem.memory -> int -> Obj.t
  val value_area : Netsys_mem.memory -> unit
  val obj_address : Obj.t -> nativeint
  val hdr_address : Obj.t -> nativeint
  val cmp_bytes : Bytes.t -> Bytes.t -> int
  val cmp_string : string -> string -> int
  exception Out_of_space
  val init_header : Netsys_mem.memory -> int -> int -> int -> unit
  val init_string : Netsys_mem.memory -> int -> int -> int * int
  val init_string_bytelen : int -> int
  val init_array : Netsys_mem.memory -> int -> int -> int * int
  val init_float_array : Netsys_mem.memory -> int -> int -> int * int
  val init_array_bytelen : int -> int
  val init_float_array_bytelen : int -> int
  type custom_ops = nativeint
  type init_value_flag =
      Copy_bigarray
    | Copy_custom_int
    | Copy_atom
    | Copy_simulate
    | Copy_conditionally
    | Keep_atom
  val init_value :
    ?targetaddr:nativeint ->
    ?target_custom_ops:(string * Netsys_mem.custom_ops) list ->
    ?cc:(nativeint * nativeint) list ->
    Netsys_mem.memory ->
    int -> '-> Netsys_mem.init_value_flag list -> int * int
  val get_custom_ops : '-> string * Netsys_mem.custom_ops
  val copy_value : Netsys_mem.init_value_flag list -> '-> 'a
  type color = White | Gray | Blue | Black
  val color : Obj.t -> Netsys_mem.color
  val set_color : Obj.t -> Netsys_mem.color -> unit
  val is_bigarray : Obj.t -> bool
  val mem_read : Unix.file_descr -> Netsys_mem.memory -> int -> int -> int
  val mem_write : Unix.file_descr -> Netsys_mem.memory -> int -> int -> int
  val mem_recv :
    Unix.file_descr ->
    Netsys_mem.memory -> int -> int -> Unix.msg_flag list -> int
  val mem_send :
    Unix.file_descr ->
    Netsys_mem.memory -> int -> int -> Unix.msg_flag list -> int
  type memory_pool
  val create_pool : int -> Netsys_mem.memory_pool
  val pool_alloc_memory : Netsys_mem.memory_pool -> Netsys_mem.memory
  val pool_alloc_memory2 :
    Netsys_mem.memory_pool -> Netsys_mem.memory * (unit -> unit)
  val pool_reclaim : Netsys_mem.memory_pool -> unit
  val pool_block_size : Netsys_mem.memory_pool -> int
  val default_block_size : int
  val default_pool : Netsys_mem.memory_pool
  val small_block_size : int
  val small_pool : Netsys_mem.memory_pool
  val pool_report : Netsys_mem.memory_pool -> string
end
ocamlnet-4.1.2/doc/html-main/Netencoding.html0000644000175000017500000004411412731530352017527 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding

Module Netencoding

module Netencoding: sig .. end
Base64, Quoted Printable, URL encoding, HTML escaping

module Base64: sig .. end
module QuotedPrintable: sig .. end
module Q: sig .. end
module Url: sig .. end
module Html: sig .. end
val to_hex : ?lc:bool -> string -> string
ocamlnet-4.1.2/doc/html-main/type_Netftp_fs.ftp_fs.html0000644000175000017500000004337712731530352021555 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_fs.ftp_fs ?config_client:(Netftp_client.ftp_client -> unit) ->
?tmp_directory:string ->
?tmp_prefix:string ->
?get_password:(string -> string) ->
?get_account:(string -> string) ->
?keep_open:bool ->
?tls_config:(module Netsys_crypto_types.TLS_CONFIG->
?tls_enabled:bool ->
?tls_required:bool ->
?gssapi_provider:(module Netsys_gssapi.GSSAPI->
?gssapi_config:Netsys_gssapi.client_config ->
?gssapi_required:bool -> string -> Netftp_fs.ftp_stream_fs
ocamlnet-4.1.2/doc/html-main/Nettls_gnutls.TLS.html0000644000175000017500000013545712731530352020613 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.TLS

Module Nettls_gnutls.TLS

module TLS: Netsys_crypto_types.TLS_PROVIDER 
Same as GNUTLS, but without the extra gnutls_* functions


Provides TLS functionality.

Users should not call functions of the provider directly, but use Netsys_tls, or another higher-level layer.

type config 
type credentials 
type endpoint 
module Exc: Netsys_crypto_types.TLS_EXCEPTIONS 
Access to exceptions
val error_message : string -> string
Returns the message for humans (display, log files etc.) when called with an error or warning symbol.
type dh_params = [ `Generate of int | `PKCS3_DER of string | `PKCS3_PEM_file of string ] 
Diffie-Hellman parameters:

  • `PKCS3_PEM_file name: points to a PEM-encoded PKCS3-file ("BEGIN DH PARAMETERS")
  • `PKCS3_DER data: the parameters are in a DER-encoded PKCS3 structure
  • `Generate bits: the parameters are generated with the passed number of bits

val create_config : ?algorithms:string ->
?dh_params:dh_params ->
?verify:(endpoint -> bool -> bool -> bool) ->
peer_auth:[ `None | `Optional | `Required ] ->
credentials:credentials ->
unit -> config
The configuration includes:

  • algorithms: a string specifying which cryptographic algorithms, protocols and protocol options are enabled, and in which priority they are used in the negotiation. (GnuTLS calls this "priority string".) The syntax is implementation-defined.
  • dh_params: parameters for Diffie-Hellman key exchange (used for DH-based authentication, but only on the server side)
  • peer_auth: controls whether the peer is requested to authenticate. This can be set to `None meaning not to request authentication and to ignore credentials, or to `Optional meaning not to request authentication but to check credentials if they are sent nevertheless, or to `Required meaning to request and check credentials. For "standard clients" you should set this to `Required, and for "standard servers" to `None or `Required.
  • credentials describes our own credentials, and the accepted credentials of the peer.
  • verify is a function called to verify the peer certificate in addition to the actions of peer_auth. The function must return true in order to be successful. The arguments of the function are the TLS endpoint, and two bools indicating the success of previous checks. The first bool says whether the certificate is trusted (based on peer_auth, trust and system_trust), and the second bool says whether the host name of the peer matches the name in the certificate. If not passed, verify defaults to (fun _ cert_ok name_ok -> cert_ok && name_ok), i.e. both bools must be true.
A configuration is read-only once created, and can be used for several endpoints. In particular, it does not cache TLS sessions.
type crt_list = [ `DER of string list | `PEM_file of string ] 
Certificates are given either as:

  • `PEM_file name: The certs are stored in this file, and are PEM-encoded.
  • `DER l: The certs are given directly in their DER-encoded form
See also Credentials for TLS.
type crl_list = [ `DER of string list | `PEM_file of string ] 
Certificate revocation lists are given either as:

  • `PEM_file name: The CRLs are stored in this file, and are PEM-encoded.
  • `DER l: The CRLs are given directly in their DER-encoded form
See also Credentials for TLS.
type private_key = [ `DSA of string
| `EC of string
| `PEM_file of string
| `PKCS8 of string
| `PKCS8_encrypted of string
| `RSA of string ]
Private keys are given either as:

  • `PEM_file name: The key is stored PEM-encoded in this file. The PEM header indicates the format.
  • `RSA data: The key is a PKCS1 RSA key
  • `DSA data: The key is a DSA key
  • `EC data: The key is for an elliptic curve
  • `PKCS8 data: The key is in a PKCS8 data structure
  • `PKCS8_encrypted data: The key is in a PKCS8 data structure, and is additionally encrypted.
See also Credentials for TLS.
val create_x509_credentials : ?system_trust:bool ->
?trust:crt_list list ->
?revoke:crl_list list ->
?keys:(crt_list *
private_key * string option)
list ->
unit -> credentials
Create X.509 credentials from individual objects:
  • system_trust: if set, the system certificates are trusted
  • trust specifies the CAs of peers to trust (default: empty)
  • revoke specifies CRLs for revocation of peer certificates (default: empty)
  • keys are our own certificates, as triples (cert_path, private_key, password) (default: empty)
A client should set trust to the list of CAs it can accept on the server side. It is not required to specify a key.

A server must specify a key (but can also specify several keys). If a server requests authentication from the client, it must also set trust.

The keys must include the certificate path cert_path, starting with the endpoint certificate, and followed by all middle certificates, but omitting the certificate of the CA. The private_key is the key of the endpoint. If it is password-encrypted, the password must be given.

val create_endpoint : role:[ `Client | `Server ] ->
recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
endpoint
Creates a new endpoint for this configuration.

peer_name is the expected common name or DNS name of the peer. peer_name has an option type as it is not always required to pass it. However, keep in mind that clients normally authenticate servers (peer_auth=`Required). In order to do so, they need to check whether the name in the server certificate equals the DNS name of the service they are connected to. This check is done by comparing peer_name with the name in the certificate.

peer_name is also used for the SNI extension.

Servers normally need not to set peer_name. You can also omit it when there is no name-driven authentication at all.

The endpoint will use the functions recv and send for I/O, which must be user-supplied. recv buf is expected to read data into the buffer, and to return the number of bytes, or 0 for EOF. send buf n is expected to send the n first bytes in buf.

Both functions may raise Unix_error. The codes Unix.EAGAIN and Unix.EINTR are specially interpreted.

val stash_endpoint : endpoint -> exn
The endpoint in "stashed" form, encapsulated as an exception. This form is intended for keeping the session alive in RAM, but without keeping references to the recv and send functions.

The endpoint passed in to stash_endpoint must no longer be used!

val restore_endpoint : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
exn -> endpoint
Reconnect the stashed endpoint with recv and send functions
val resume_client : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
string -> endpoint
Creates a new endpoint that will resume an old session. This implies the client role.

The session data is passed as string, which must have been retrieved with get_session_data.

type state = [ `Accepting
| `Data_r
| `Data_rs
| `Data_rw
| `Data_w
| `End
| `Handshake
| `Refusing
| `Start
| `Switching ]
The state of a session:

  • `Start: Before the session is started
  • `Handshake: The handshake is being done (and hello needs to be called again)
  • `Data_rw: The connection exists, and is read/write
  • `Data_r: The connection exists, and is read-only
  • `Data_w: The connection exists, and is write-only
  • `Data_rs: The connection exists, and data can be read. There was a switch request (initiated by us), and a response is awaited. No data can be sent in the moment.
  • `Switching: A rehandshake is being negotiated (and switch needs to be called again)
  • `Accepting: A rehandshake is being accepted (and accept_switch needs to be called again)
  • `Refusing: A rehandshake is being refused (and refuse_switch needs to be called again)
  • `End: After finishing the session

val get_state : endpoint ->
state
Return the recorded state
type raw_credentials = [ `Anonymous | `X509 of string ] 
The encoded credentials:
  • `X509 s: The X509 certificate in DER encoding
  • `Anonymous: no certificate or other key is available

val at_transport_eof : endpoint -> bool
Whether the underlying transport channel has seen the end of input. Use this after recv or mem_recv returned 0 to check whether only the TLS enf-of-input message has been read, or the underlying channel (usually the file descriptor) has indicated EOF.
val hello : endpoint -> unit
Performs the initial handshake (exchanges credentials and establishes a session).

hello doesn't verify the peer. Use verify for that.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val bye : endpoint -> Unix.shutdown_command -> unit
Performs the final handshake (exchanges close requests).

If SHUTDOWN_SEND is set, the close request is sent to the peer, and the TLS tunnel is considered as closed for writing. The application can receive further data until recv returns zero bytes meaning that the peer responded with another close request.

If SHUTDOWN_ALL is passed, it is additionally waited until the peer responds with a close request.

A simple SHUTDOWN_RECEIVE is unimplemented and ignored.

In no case the underlying transport is closed or shut down!

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val verify : endpoint -> unit
verify ep peer_name: Checks that:
  • there is a trust chain for the peer's certificate
  • that peer_name is the common name of the certificate subject, or an alternate name
These checks are not performed if peer_auth=`None is set in the configuration!

Additionally, the verify function in the endpoint configuration is called back, and a failure is indicated if this function returns false. This callback is useful to get the certificate of the peer and to perform further checks.

The verify function will raise Failure on failed checks (and Error for internal processing errors).

val get_config : endpoint ->
config
Get the current config (possibly modified because of a rehandshake)
val get_endpoint_creds : endpoint ->
raw_credentials
Get the credentials that was actually used in the handshake, in raw format.
val get_peer_creds : endpoint ->
raw_credentials
Get the credentials of the peer, in raw format. Raises Not_found if not applicable/no credentials present.
val get_peer_creds_list : endpoint ->
raw_credentials list
Get the chain that was actually used in the handshake.
val switch : endpoint ->
config -> unit
The server can use this to request a rehandshake and to use the new configuration for cert verification. This function sends the request, and expects a soon response from the client. The state enters `Data_rs meaning that we can still read data, and at some point recv will raise TLS_switch_response.

On the client side, the request will by returned as exception TLS_switch_request by recv. The client should respond with accept_switch if it accepts the handshake, or refuse_switch if not.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val accept_switch : endpoint ->
config -> unit
On the client: Enter another handshake round with new configuration data.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val refuse_switch : endpoint -> unit
On the client: Refuse a handshake

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val send : endpoint ->
Netsys_types.memory -> int -> int
send ep buffer n: Sends the first n bytes in the buffer over the endpoint, and returns the actual number of processed bytes.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val recv : endpoint -> Netsys_types.memory -> int
recv ep buffer n: Receives data, and puts them into the memory buffer, and returns the actual number of received bytes. If 0 is returned, a close request was received by the peer. For closing the tunnel properly this request should be responded by another close request with bye (unless this has already been done).

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

The exception TLS_switch_request can only occur on the client side, and should be responded by accept_switch or refuse_switch.

The exception TLS_switch_response can only occur on the server side.

val recv_will_not_block : endpoint -> bool
If there is still unprocessed data in the endpoint buffer, recv is guaranteed not to block or raise EAGAIN.
val get_session_id : endpoint -> string
The (non-printable) session ID
val get_session_data : endpoint -> string
Get the (non-printable) marshalled session data, for later resumption with resume_client
val get_cipher_suite_type : endpoint -> string
The type of the cipher suite:
  • "X509": X509 certificates are used
  • "OPENPGP": OpenPGP certificates are used
  • "ANON": anonymous credentials
  • "SRP": SRP credentials
  • "PSK": PSK credentials

val get_cipher_algo : endpoint -> string
Get the name of the cipher
val get_kx_algo : endpoint -> string
Get the name of the key exchange method
val get_mac_algo : endpoint -> string
Get the name of the message authentication code
val get_compression_algo : endpoint -> string
Get the name of the record-level compression method
val get_cert_type : endpoint -> string
Get the type of the certificate
val get_protocol : endpoint -> string
Get the name of the tunnel protocol
type server_name = [ `Domain of string ] 
val get_addressed_servers : endpoint ->
server_name list
To be used in servers: The client can address one of several virtual servers with the SNI extension, and this function returns which was requested. Raises Not_found if there is nothing appropriate. This information is only available after a handshake, and if the client submitted it.
val set_session_cache : store:(string -> string -> unit) ->
remove:(string -> unit) ->
retrieve:(string -> string) ->
endpoint -> unit
Sets the three callbacks for storing, removing and retrieving sessions (on the server side)
val implementation_name : string
String name of the implementation. By convention this is the full OCaml module path, e.g. "Nettls_gnutls.TLS"
val implementation : unit -> exn
Implementation-defined additional functionality
ocamlnet-4.1.2/doc/html-main/type_Shell_sys.Debug.html0000644000175000017500000004100212731530352021316 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_sys.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netchannels.output_filter.html0000644000175000017500000004114412731530352023501 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_filter Netchannels.io_obj_channel ->
Netchannels.out_obj_channel -> Netchannels.out_obj_channel
ocamlnet-4.1.2/doc/html-main/Netftp_data_endpoint.ftp_data_engine-c.html0000644000175000017500000004346012731530352024754 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.ftp_data_engine

Class type Netftp_data_endpoint.ftp_data_engine

class type ftp_data_engine = object .. end
The common type of FTP data engines
Inherits
method descr : Unix.file_descr
The socket to use for data transfers. This class never closes this socket, but it may be shut down at least partially.
method descr_state : descr_state
The socket state
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.FILE_TLS_ENDPOINT.TLS.html0000644000175000017500000004061312731530352025645 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.FILE_TLS_ENDPOINT.TLS TLS_PROVIDERocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.Debug.html0000644000175000017500000004203012731530352021623 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.Debug

Module Nethttpd_reactor.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.async_in_channel.html0000644000175000017500000004225412731530352025270 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.async_in_channel object
  method can_input : bool
  method close_in : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method pos_in : int
  method request_notification : (unit -> bool) -> unit
end
ocamlnet-4.1.2/doc/html-main/index_extensions.html0000644000175000017500000004134712731530352020665 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of extensions

Index of extensions


T
Tstring [Netplex_types]
Txdr [Netplex_types]
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.TLS_CONFIG.TLS.html0000644000175000017500000004060412731530352024573 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_CONFIG.TLS TLS_PROVIDERocamlnet-4.1.2/doc/html-main/Netplex_log.multi_file_config-c.html0000644000175000017500000004420712731530352023452 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_log.multi_file_config

Class type Netplex_log.multi_file_config

class type multi_file_config = object .. end
Inherits
method log_directory : string
method log_files : (string * string *
[ `Alert
| `All
| `Crit
| `Debug
| `Emerg
| `Err
| `Info
| `Notice
| `Warning ] * string * string)
list
Triples (component, subchannel, max_level, file, format) . Use * as wildcard in component and subchannel.

Currently, `All is a synonym for the `Debug level.

ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.receiver.html0000644000175000017500000004157612731530352023607 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.receiver src:Unix.file_descr ->
dst:#Uq_engines_compat.async_out_channel ->
?close_src:bool ->
?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/type_Netgzip.deflating_pipe.html0000644000175000017500000004077012731530352022730 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.deflating_pipe ?level:int -> unit -> Netchannels.io_obj_channelocamlnet-4.1.2/doc/html-main/Netx509.x509_dn_from_ASN1-c.html0000644000175000017500000004222012731530352021654 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_dn_from_ASN1

Class Netx509.x509_dn_from_ASN1

class x509_dn_from_ASN1 : Netasn1.Value.value -> directory_name
Returns the DN object for a Name entity

ocamlnet-4.1.2/doc/html-main/Uq_engines.meta_engine-c.html0000644000175000017500000004261312731530352022063 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.meta_engine

Class Uq_engines.meta_engine

class ['a] meta_engine : 'a #engine -> ['a final_state] engine
maps the final state s to `Done s

ocamlnet-4.1.2/doc/html-main/type_Netunidata.html0000644000175000017500000004256012731530352020432 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netunidata sig
  val load : string -> unit
  val load_charset : Netconversion.charset -> unit
  val enable : unit -> unit
  val disable : unit -> unit
  val net_db_dir : unit -> string
  val set_net_db_dir : string -> unit
  val load_file : string -> string
end
ocamlnet-4.1.2/doc/html-main/Netaddress.group-c.html0000644000175000017500000004311712731530352020743 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaddress.group

Class Netaddress.group

class group : string -> mailbox list -> object .. end
A group has a name, and consists of a number of mailboxes.

Create a group with new group name mailboxes.


method name : string
The name of the group
method mailboxes : mailbox list
The member mailboxes
ocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.SHA1.html0000644000175000017500000004401212731530352021554 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SHA1

Module Netmech_scram_sasl.SHA1

module SHA1: PROFILE 
Uses SHA-1 as hash function. The iteration count is limited to 100000. The mechanism name is "SCRAM-SHA-1".

val hash_function : Netsys_digests.iana_hash_fn
The hash function. We only allow functions where IANA registered an official name. Note that SCRAM is currently only specified for SHA1, although the hash function is easily exchangable.
val iteration_count_limit : int
The maximum iteration count supported
val announce_channel_binding : bool
Whether servers announce the availability of channel binding by adding "-PLUS" to the mechanism name.
ocamlnet-4.1.2/doc/html-main/type_Netsys_win32.Debug.html0000644000175000017500000004120712731530352021667 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_win32.Debug sig val enable : bool Pervasives.ref val debug_c_wrapper : bool -> unit endocamlnet-4.1.2/doc/html-main/type_Uq_transfer.input_async_mplex.html0000644000175000017500000004130512731530352024363 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.input_async_mplex ?onshutdown:Uq_transfer.onshutdown_in_spec ->
?buffer_size:int ->
Uq_engines.multiplex_controller -> Uq_transfer.async_in_channel_engine
ocamlnet-4.1.2/doc/html-main/type_Netx509.x509_dn_from_ASN1.html0000644000175000017500000004101412731530352022475 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_dn_from_ASN1 Netasn1.Value.value -> Netx509.directory_nameocamlnet-4.1.2/doc/html-main/Netmime_channels.html0000644000175000017500000007542612731530352020555 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime_channels

Module Netmime_channels

module Netmime_channels: sig .. end
MIME: parsing and printing for channels


Parsing MIME messages


val read_mime_header : ?unfold:bool ->
?strip:bool -> ?ro:bool -> Netstream.in_obj_stream -> Netmime.mime_header
Decodes the MIME header that begins at the current position of the netstream, and returns the header as class basic_mime_header. After returning, the stream is advanced to the byte following the empty line terminating the header.

Example: To read the header at the beginning of the file "f", use:

 
 let ch = new Netchannels.input_channel (open_in "f") in
 let stream = new Netstream.input_stream ch in
 let h = read_mime_header stream in
 ...
 stream#close_in();    (* no need to close ch *)
 

Note that although the stream position after parsing is exactly known, the position of ch cannot be predicted.


unfold : whether linefeeds are replaced by spaces in the values of the header fields (Note: defaults to false here in contrast to Netmime_string.scan_header!)
strip : whether whitespace at the beginning and at the end of the header fields is stripped
ro : whether the returned header is read-only (default: false)

Hint: To write the header h into the channel ch, use
 Netmime_string.write_header ch h#fields 

Link: Netmime_string.write_header

type multipart_style = [ `Deep | `Flat | `None ] 
How to parse multipart messages:
  • `None: Do not handle multipart messages specially. Multipart bodies are not further decoded, and returned as `Body b where b is the transfer-encoded text representation.
  • `Flat: If the top-level message is a multipart message, the parts are separated and returned as list. If the parts are again multipart messages, these inner multipart messages are not furher decoded and returned as `Body b.
  • `Deep: Multipart messages are recursively decoded and returned as tree structure.
This value determines how far the complex_mime_message structure is created for a parsed MIME message. `None means that no parts are decoded, and messages have always only a simple `Body b, even if b is in reality a multi-part body. With `Flat, the top-level multi-part bodies are decoded (if found), and messages can have a structured `Parts [_, `Body b1; _, `Body b1; ...] body. Finally, `Deep allows that inner multi-part bodies are recursively decoded, and messages can have an arbitrarily complex form.
val decode_mime_body : #Netmime.mime_header_ro ->
Netchannels.out_obj_channel -> Netchannels.out_obj_channel
let ch' = decode_mime_body hdr ch: According to the value of the Content-transfer-encoding header field in hdr the encoded MIME body written to ch' is decoded and transferred to ch.

Handles 7bit, 8bit, binary, quoted-printable, base64.

Example: The file "f" contains base64-encoded data, and is to be decoded and to be stored in "g":

 
 let ch_f = new Netchannels.input_channel (open_in "f") in
 let ch_g = new Netchannels.output_channel (open_out "g") in
 let hdr = new basic_mime_header ["content-transfer-encoding", "base64" ] in
 let ch = decode_mime_body hdr ch_g in
 ch # output_channel ch_f;
 ch # close_out();
 ch_g # close_out();
 ch_f # close_in();
 

Note: This function is internally used by read_mime_message to decode bodies. There is usually no need to call it directly.

val storage : ?fin:bool -> Netmime.store -> Netmime.mime_body * Netchannels.out_obj_channel
Creates a new storage facility for a mime body according to store. This function can be used to build the storage_style argument of the class read_mime_message (below). For example, this is useful to store large attachments in external files, as in:

 
 let storage_style hdr = 
   let filename = hdr ... (* extract from hdr *) in
   storage (`File filename)
 


fin : whether to finalize bodies stored in files. Default: false
val read_mime_message : ?unfold:bool ->
?strip:bool ->
?ro:bool ->
?multipart_style:multipart_style ->
?storage_style:(Netmime.mime_header ->
Netmime.mime_body * Netchannels.out_obj_channel) ->
Netstream.in_obj_stream -> Netmime.complex_mime_message
Decodes the MIME message that begins at the current position of the passed netstream. It is expected that the message continues until EOF of the netstream.

Multipart messages are decoded as specified by multipart_style (see above).

Message bodies with content-transfer-encodings of 7bit, 8bit, binary, base64, and quoted-printable can be processed. The bodies are stored without content-transfer-encoding (i.e. in decoded form), but the content-transfer-encoding header field is not removed from the header.

The storage_style function determines where every message body is stored. The corresponding header of the body is passed to the function as argument; the result of the function is a pair of a new mime_body and an out_obj_channel writing into this body. You can create such a pair by calling storage (above).

By default, the storage_style is storage ?ro `Memory for every header. Here, the designator `Memory means that the body will be stored in an O'Caml string. The designator `File fn would mean that the body will be stored in the file fn. The file would be created if it did not yet exist, and it would be overwritten if it did already exist.

Note that the storage_style function is called for every non-multipart body part.

Large message bodies (> maximum string length) are supported if the bodies are stored in files. The memory consumption is optimized for this case, and usually only a small constant amount of memory is needed.

Example:

Parse the MIME message stored in the file f:

 let m = read_mime_message 
           (new input_stream (new input_channel (open_in f)))
 


unfold : whether linefeeds are replaced by spaces in the values of the header fields (Note: defaults to false here in contrast to Netmime_string.scan_header!)
strip : whether whitespace at the beginning and at the end of the header fields is stripped
ro : Whether the created MIME message is read-only

Printing MIME Messages


val encode_mime_body : ?crlf:bool ->
#Netmime.mime_header_ro ->
Netchannels.out_obj_channel -> Netchannels.out_obj_channel
let ch' = encode_mime_body hdr ch: According to the value of the Content-transfer-encoding header field in hdr the unencoded MIME body written to ch' is encoded and transferred to ch.

Handles 7bit, 8bit, binary, quoted-printable, base64.

For an example, see decode_mime_body which works in a similar way but performs decoding instead of encoding.


crlf : if set (this is by default the case) CR/LF will be used for end-of-line (eol) termination, if not set LF will be used. For 7bit, 8bit and binary encoding the existing eol delimiters are not rewritten, so this option has only an effect for quoted-printable and base64.
val write_mime_message : ?wr_header:bool ->
?wr_body:bool ->
?nr:int ->
?ret_boundary:string Pervasives.ref ->
?crlf:bool ->
Netchannels.out_obj_channel -> Netmime.complex_mime_message -> unit
Writes the MIME message to the output channel. The content-transfer- encoding of the leaves is respected, and their bodies are encoded accordingly. The content-transfer-encoding of multipart messages is always "fixed", i.e. set to "7bit", "8bit", or "binary" depending on the contents.

The function fails if multipart messages do not have a multipart content type field (i.e. the content type does not begin with "multipart"). If only the boundary parameter is missing, a good boundary parameter is added to the content type. "Good" means here that it is impossible that the boundary string occurs in the message body if the content-transfer-encoding is quoted-printable or base64, and that such an occurrence is very unlikely if the body is not encoded. If the whole content type field is missing, a "multipart/mixed" type with a boundary parameter is added to the printed header.

Note that already existing boundaries are used, no matter whether they are of good quality or not.

No other header fields are added, deleted or modified. The mentioned modifications are _not_ written back to the passed MIME message but only added to the generated message text.

It is possible in some cases that the boundary does not work (both the existing boundary, and the added boundary). This causes that a wrong and unparseable MIME message is written. In order to ensure a correct MIME message, it is recommended to parse the written text, and to compare the structure of the message trees. It is, however, very unlikely that a problem arises.

Note that if the passed message is a simple message like (_,`Body _), and if no content-transfer-encoding is set, the written message might not end with a linefeed character.


wr_header : If true, the outermost header is written. Inner headers of the message parts are written unless ~wr_body=false.
wr_body : If true, the body of the whole message is written; if false, no body is written at all.
nr : This argument sets the counter that is included in generated boundaries to a certain minimum value.
ret_boundary : if passed, the boundary of the outermost multipart message is written to this reference. (Internally used.)
crlf : if set (this is by default the case) CR/LF will be used for end-of-line (eol) termination, if not set LF will be used. The eol separator is used for the header, the multipart framing, and for bodies encoded as quoted-printable or base64. Other eol separators are left untouched.
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.SYMMETRIC_CRYPTO.html0000644000175000017500000005141012731530352025114 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.SYMMETRIC_CRYPTO sig
  type scipher
  val ciphers : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher list
  val find : string * string -> Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher
  val name : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> string
  val mode : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> string
  val key_lengths :
    Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> (int * int) list
  val iv_lengths :
    Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> (int * int) list
  val block_constraint : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> int
  val supports_aead : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> bool
  type scipher_ctx
  val create :
    Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher ->
    string -> Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx
  val set_iv :
    Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx -> string -> unit
  val set_header :
    Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx -> string -> unit
  val encrypt :
    Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx ->
    Netsys_types.memory -> Netsys_types.memory -> unit
  val decrypt :
    Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx ->
    Netsys_types.memory -> Netsys_types.memory -> bool
  val mac : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx -> string
end
ocamlnet-4.1.2/doc/html-main/Netplex_advanced.html0000644000175000017500000012072112731530352020535 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_advanced

Netplex_advanced


Advanced features of Netplex

Some information about advanced techniques.

Contents

Running timers in containers

With Netplex_cenv.create_timer one can start a timer that runs directly in the container event loop. This event loop is normally used for accepting new connections, and for exchanging control messages with the master process. If the processor supports it (like the RPC processor), the event loop is also used by the processor itself for protocol interpretation. Running a timer in this loop means that the expiration of the timer is first detected when the control flow of the container returns to the event loop. In the worst case, this happens only when the current connection is finished, and it is waited for the next connection.

So, this is not the kind of high-precision timer one would use for the exact control of latencies. However, these timers are still useful for things that run only infrequently, like

  • processing statistical information
  • checking whether configuration updates have arrived
  • checking whether resources have "timed out" and can be released (e.g. whether a connection to a database system can be closed)
Timers can be cancelled by called Netplex_cenv.cancel_timer. Timers are automatically cancelled at container shutdown time.

Example: Start a timer at container startup: We have to do this in the post_start_hook of the processor. It depends on the kind of processor how the hooks are set. For example, the processor factories Rpc_netplex.rpc_factory and Nethttpd_plex.nethttpd_factory have an argument hooks, and one can create it like:

  let hooks =
    ( object
        inherit Netplex_kit.empty_processor_hooks()
        method post_start_hook cont =
          let timer =
            Netplex_cenv.create_timer
              (fun timer -> ...)
              tmo in
          ...
      end
    )

Container variables

If multi-processing is used, one can simply store per-container values in global variables. This works because for every new container the whole program is forked, and thus a new instance of the variable is created.

For multi-threaded programs this is a lot more difficult. For this reason there is built-in support for per-container variables.

Example: We want to implement a statistics how often the functions foo and bar are called, per-container. We define a record

type stats =
  { mutable foo_count : int;
    mutable bar_count : int
  }

Furthermore, we need an access module that looks for the current value of the variable (get), or overwrites the value (set). We can simply create this module by using the functor Netplex_cenv.Make_var_type:

module Stats_var =
  Netplex_cenv.Make_var_type(struct type t = stats end)

Now, one can get the value of a stats-typed variable "count" by calling

let stats =
  Stats_var.get "count"

(which will raise Netplex_cenv.Container_variable_not_found if the value of "count" never has been set before), and one can set the value by

Stats_var.set "count" stats

As mentioned, the variable "count" exists once per container. One can access it only from the scope of a Netplex container (e.g. from a callback function that is invoked by a Netplex processor). It is a good idea to initialize "count" in the post_start_hook of the processor (see the timer example above).

See also below on "Storing global state" for another kind of variable that can be accessed from all containers.

Sending messages to individual containers

Sometimes it is useful when a container can directly communicate with another container, and the latter can be addressed by a unique name within the Netplex system. A normal Netplex socket is not useful here because Netplex determines which container will accept new connections on the socket, i.e. from the perspective of the message sender it is random which container receives the message.

In Ocamlnet 3, a special kind of socket, called "container socket" has been added to solve this problem. This type of socket is not created by the master process, but by the container process (hence the name). The socket is a Unix Domain socket for Unix, and a named pipe for Win32. It has a unique name, and if the message sender knows the name, it can send the message to a specific container.

One creates such sockets by adding an address section to the config file that looks like

  address {
    type = "container"
  }

If this address section is simply added to an existing protocol section, the network protocol of the container socket is the same as that of the main socket of the container. If a different network protocol is going to be used for the container socket, one can also add a second protocol section. For example, here is a main HTTP service, and a separate service control that is run over the container sockets:

  service {
    name = "sample"
    protocol {
      name = "http"
      address {
        type = "internet"
        bind = "0.0.0.0:80"
      }
    }
    protocol {
      name = "control"
      address {
        type = "container"
      }
    }
    processor { 
      type = "myproc";
      http { ... webserver config ... }
      control { ... rpc config ... }
    }
  }

One can now employ Netplex_kit.protocol_switch_factory to route incoming TCP connections arriving at "http" sockets to web server code, and to route incoming TCP connections arriving at "control" sockets to a e.g. an RPC server:

  let compound_factory =
    new Netplex_kit.protocol_switch_factory
      "myproc"
      [ "http", Nethttpd_plex.nethttpd_factory ...;
        "control", Rpc_netplex.rpc_factory ...;
      ]

The implementation of "control" would be a normal RPC server.

The remaining question is now how to get the unique names of the container sockets. There is the function Netplex_cenv.lookup_container_sockets helping here. The function is called with the service name and the protocol name as arguments:

  let cs_paths =
    Netplex_cenv.lookup_container_sockets "sample" "control"

It returns an array of Unix Domain paths, each corresponding to the container socket of one container. It is recommended to use Netplex_sockserv.any_file_client_connector for creating RPC clients:

  let clients =
    List.map
      (fun cs_path ->
        let connector = Netplex_sockserv.any_file_client_connector cs_path in
        create_client ... connector ...
      )
      cs_paths

There is no way to get more information about the cs_paths, e.g. in order to find a special container. (Of course, except by calling RPC functions and asking the containers directly.)

A container can also find out the address of its own container socket. Use the method owned_container_sockets to get a list of pairs (protocol_name, path), e.g.

  let cont = Netplex_cenv.self_cont() in
  let path = List.assoc "control" cont#owned_container_sockets

One-time initialization code

It is sometimes necessary to run some initialization code only once for all containers of a certain service. Of course, there is always the option of doing this at program startup. However, this might be too early, e.g. because some information is not yet known.

Another option is to do such initialization in the pre_start_hook of the container. The pre_start_hook is run before the container process is forked off, and executes in the master process. Because of this it is easy to have a global variable that checks whether pre_start_hook is called the first time:

  let first_time = ref true

  let pre_start_hook _ _ _ =
    if !first_time then (* do initialization *) ... ;
    first_time := false

  let hooks =
    ( object
        inherit Netplex_kit.empty_processor_hooks()
        method pre_start_hook socksrv ctrl cid =
          pre_start_hook socksrv ctrl cid
      end
    )

Last but not least there is also the possibility to run such initialization code in the post_start_hook. This is different as this hook is called from the container, i.e. from the forked-off child process. This might be convenient if the initialization routine is written for container context.

There is some additional complexity, though. One can no longer simply use a global variable to catch the first time post_start_hook is called. Instead, one has to use a storage medium that is shared by all containers, and that is accessible from all containers. There are plenty of possibilities, e.g. a file. In this example, however, we use a Netplex semaphore:

  let hooks =
    ( object
        inherit Netplex_kit.empty_processor_hooks()

        method post_add_hook socksrv ctrl =
          ctrl # add_plugin Netplex_semaphore.plugin

        method post_start_hook cont =
          let first_time =
            Netplex_semaphore.create "myinit" 0L in
          if first_time then (* do initialization *) ... ;
      end
    )

The semaphore is visible in the whole Netplex system. We use here the fact that Netplex_semaphore.create returns true when the semaphore is created at the first call of create. The semaphore is then never increased or decreased.

Storing global state

Sometimes global state is unavoidable. We mean here state variables that are accessed by all processes of the Netplex system.

Since Ocamlnet 3 there is Netplex_sharedvar. This modules provides Netplex-global string variables that are identified by a user-chosen name.

For example, to make a variable of type stats globally accessible

type stats =
  { mutable foo_count : int;
    mutable bar_count : int
  }

(see also above, "Container variables"), we can accomplish this as follows.

module Stats_var =
  Netplex_sharedvar.Make_var_type(struct type t = stats end)

Now, this defines functions Stats_var.get and Stats_var.set to get and set the value, respectively. Note that this is type-safe although Netplex_sharedvar.Make_var_type uses the Marshal module internally. If a get/set function is applied to a variable of the wrong type we will get the exception Netplex_sharedvar.Sharedvar_type_mismatch.

Before one can get/set values, one has to create the variable with

let ok =
  Netplex_sharedvar.create ~enc:true name

The parameter enc:true is required for variables accessed via Netplex_sharedvar.Make_var_type.

In order to use Netplex_sharedvar we have to add this plugin:

  let hooks =
    ( object
        inherit Netplex_kit.empty_processor_hooks()

        method post_add_hook socksrv ctrl =
          ctrl # add_plugin Netplex_sharedvar.plugin
      end
    )

Now, imagine that we want to increase the counters in a stats variable. As we have now truly parallel accesses, we have to ensure that these accesses do not overlap. We use a Netplex mutex to ensure this like in:

  let mutex = Netplex_mutex.access "mymutex" in
   Netplex_mutex.lock mutex;
   try 
     let v = Stats_var.get "mystats" in
     v.foo_count <- v.foo_count + foo_delta;
     v.bar_count <- v.bar_count + bar_delta;
     Stats_var.set "mystats" v;
     Netplex_mutex.unlock mutex;
   with
     error -> Netplex_mutex.unlock mutex; raise error

As Netplex mutexes are also plugins, we have to add them in the post_add_hook, too. Also see Netplex_mutex for more information.

Generally, shared variables should not be used to store large quantities of data. A few megabytes are probably ok. The reason is that these variables exist in the Netplex master process, and each time a child is forked off the variables are also copied although this is not necessary. (It is possible and likely that a future version of Ocamnet improves this.)

For bigger amounts of data, it is advised to store them in an external file, a shared memory segment (Netshm might help here), or even in a database system. Shared variables should then only be used to pass around the name of this file/segment/database.

Hooks, and how to pass values down

Usually, the user configures processor factories by creating hook objects. We have shown this already several times in previous sections of this chapter. Sometimes the question arises how to pass values from one hook to another.

The hooks are called in a certain order. Unfortunately, there is no easy way to pass values from one hook to another. As workaround, it is suggested to store the values in the hooks object.

For example, consider we need to allocate a database ID for each container. We do this in the pre_start_hook, so we know the ID early. Of course, the code started from the post_start_hook also needs the ID, and in the post_finish_hook we would like to delete everything in the database referenced by this ID.

This could be done in a hook object like

  let hooks =
    ( object
        inherit Netplex_kit.empty_processor_hooks()

        val db_id_tbl = Hashtbl.create 11

        method pre_start_hook _ _ cid =
          let db_id = allocate_db_id() in       (* create db ID *)
          Hashtbl.add db_id_tbl cid db_id       (* remember it for later *)

        method post_start_hook cont =
          let cid = cont # container_id in           (* the container ID *)
          let db_id = Hashtbl.find db_id_tbl cid in  (* look up the db ID *)
          ...

        method post_finish_hook _ _ cid =
          let db_id = Hashtbl.find db_id_tbl cid in  (* look up the db ID *)
          delete_db_id db_id;                        (* clean up db *)
          Hashtbl.remove db_id_tbl cid
      end
    )

We use here the container ID to identify the container. This works in all used hooks - either the container ID is passed directly, or we can get it from the container object itself.

Normally there is only one controller per program. It is imaginable that a multi-threaded program has several controllers, though. In this case one has to be careful with this technique, because it should be avoided that values from the Netplex system driven by one controller are visible in the system driven by the other controller. Often, this can be easily achieved by creating separate hook objects, one per controller.

Levers - calling controller functions from containers

In a multi-process setup, the controller runs in the master process, and the containers run in child processes. Because of this, container code cannot directly invoke functions of the controller.

For multi-threaded programs, this is quite easy to solve. With the function Netplex_cenv.run_in_controller_context it can be temporarily switched to the controller thread to run code there.

For example, to start a helper container one can do

  Netplex_cenv.run_in_controller_context ctrl
    (fun () ->
       Netplex_kit.add_helper_service ctrl "helper1" hooks
    )

which starts a new container with an empty processor that only consists of the hooks object. The post_start_hook can be considered as the "body" of the new thread. The advantage of this is (compared to Thread.start) that this thread counts as a regular container, and can e.g. use logging functions.

There is no such easy way in the multi-processing case. As a workaround, a special mechanism has been added to Netplex, the so-called levers. Levers are registered functions that are known to the controller and which can be invoked from container context. Levers have an argument and can deliver a result. The types of argument and result can be arbitrary (but must be monomorphic, and must not contain functions). (The name, lever, was chosen because it reminds of additional operating handles, as we add such handles to the controller.)

Levers are usually registered in the post_add hook of the processor. For example, let us define a lever that can start a helper container. As arguments we pass a tuple of a string and an int (s,i). The arguments do not have any meaning here, we only do this to demonstrate how to pass arguments. As result, we pass a boolean value back that says whether the helper container was started successfully.

First we need to create a type module:

module T = struct
  type s = string * int    (* argument type *)
  type r = bool            (* result type *)
end

As second step, we need to create the lever module. This means only to apply the functor Netplex_cenv.Make_lever:

module L = Netplex_cenv.Make_lever(T)

What happens behind the scene is that a function L.register is created that can marshal the argument and result values from the container process to the master process and back. This is invisible to the user, and type-safe.

Now, we have to call L.register from the post_add_hook. The result of L.register is another function that represents the lever. By calling it, the lever is activated:

  let hooks =
    ( object
        inherit Netplex_kit.empty_processor_hooks()

        method post_add_hook socksrv ctrl =
          let lever = 
            L.register ctrl
              (fun (s,i) ->
                 try
                   Netplex_kit.add_helper_service ctrl "helper1" ...;
                   true   (* successful *)
                 with error ->
                   false  (* not successful *)
              ) in
           ...
      end
    )

So, when we call lever ("X",42) from the container, the lever mechanism routes this call to the controller process, and calls there the function (fun (s,i) -> ...) that is the argument of L.register.

Finally, the question is how can we make the function lever known to containers. The hackish way to do this is to store lever in a global variable. The clean way is to store lever in a container variable, e.g.

  module LV = Netplex_cenv.Make_var_type(L)
    (* This works because L.t is the type of the lever *)

  let hooks =
    ( object
        inherit Netplex_kit.empty_processor_hooks()

        val mutable helper1_lever = (fun _ -> assert false)

        method post_add_hook socksrv ctrl =
          let lever = 
            L.register ctrl
              (fun (s,i) ->
                 try
                   Netplex_kit.add_helper_service ctrl "helper1" ...;
                   true   (* successful *)
                 with error ->
                   false  (* not successful *)
              ) in
           helper1_lever <- lever

        method post_start_hook cont =
          LV.set "helper1_lever" helper1_lever
      end
    )

and later in container code:

  let helper1_lever = LV.get "helper1_lever" in
  let success = helper1_lever ("X",42) in
  if success then
    print_endline "OK, started the new helper"
  else
    print_endline "There was an error"

ocamlnet-4.1.2/doc/html-main/Netcgi.cgi_argument-c.html0000644000175000017500000005242112731530352021366 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.cgi_argument

Class type Netcgi.cgi_argument

class type cgi_argument = object .. end
Represent a key-value pair of data passed to the script (including file uploads).

method name : string
The name of the argument.
method value : string
The value of the argument, after all transfer encodings have been removed. If the value is stored in a file, the file will be loaded.
Raises
  • Argument.Oversized if the argument was discarded.
  • Failure if the object has been finalized.
method open_value_rd : unit -> Netchannels.in_obj_channel
Open the contents of the value as an input channel. This works for all kinds of arguments, regardless of their #storage and #representation.
Raises
  • Argument.Oversized if the argument was discarded.
  • Failure if the object has been finalized.
method store : [ `File of string | `Memory ]
Tells whether the argument is stored in memory (as a string) or as a file (the argument of `File being the filename).
method content_type : unit -> string * (string * Netmime_string.s_param) list
Returns the content type of the header and its parameters as a couple (hdr, params). When the header is missing, the result is ("text/plain", []). Below you will find access method for frequently used parameters.
method charset : string
The charset parameter of the content type of the header, or "" when there is no such parameter, or no header.
method filename : string option
The filename parameter found in the header of file uploads. When present, Some name is returned, and None otherwise. (This is not to be confused with the possible local file holding the data.)
method representation : [ `MIME of Netmime.mime_message | `Simple of Netmime.mime_body ]
The representation of the argument.

  • `Simple the value of the CGI argument is an unstructured string value.
  • `MIME The argument has a MIME header in addition to the value. The MIME message is read-only.

method finalize : unit -> unit
Arguments stored in temp files must be deleted when the argument is no longer used. You can call finalize to delete such files. The method does not have any effect when store = `Memory. The method never raises any exceptions. If the file no longer exists (e.g. because it was moved away) or if there are any problems deleting the file, the error will be ignored.

The finalize method is not registered in the garbage collector. You can do that, but it is usually better to call this method manually.

ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.trace_call.html0000644000175000017500000004060712731530352023412 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.trace_call Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Netsys_oothr.condition-c.html0000644000175000017500000004412312731530352022177 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr.condition

Class type Netsys_oothr.condition

class type condition = object .. end

method wait : mutex -> unit
In a multi-threaded program: Wait for the condition to be true and use the mutex to protect this situation. In a single-threaded program: this is a no-op.
method signal : unit -> unit
In a multi-threaded program: Signal one process that the condition holds. In a single-threaded program: this is a no-op.
method broadcast : unit -> unit
In a multi-threaded program: Signal all waiting processes that the condition holds. In a single-threaded program: this is a no-op.
method repr : exn
May be used internally be the implementation
ocamlnet-4.1.2/doc/html-main/Netfs.empty_fs-c.html0000644000175000017500000004315412731530352020421 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netfs.empty_fs

Class Netfs.empty_fs

class empty_fs : string -> stream_fs
This is a class where all methods fail with ENOSYS. The string argument is the detail in the Unix_error, normally the module name of the user of this class.

empty_fs is intended as base class for implementations of stream_fs outside Ocamlnet. When stream_fs is extended by new methods, these methods are at least defined, and no build error occurs. So the definition should look like

      class my_fs ... =
        object
          inherit Netfs.empty_fs "my_fs"

          method read flags name = ...

          (* Add here all methods you can define, and omit the rest *)
        end
      


ocamlnet-4.1.2/doc/html-main/type_Netsys_pollset_win32.Debug.html0000644000175000017500000004101512731530352023426 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset_win32.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netchannels.input_filter-c.html0000644000175000017500000004364012731530352022462 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_filter

Class Netchannels.input_filter

class input_filter : in_obj_channel -> io_obj_channel -> in_obj_channel
An input_filter filters the data read from it through the io_obj_channel (usually a pipe after the data have been retrieved from the passed in_obj_channel.

An input_filter object never generates Buffer_underrun exceptions. However, if the passed in_obj_channel or io_obj_channel raises such an exception, the exception will fall through the calling chain.

If the filter is closed, the io_obj_channel will be closed, too, but not the source in_obj_channel (so you can still read further data from it).


ocamlnet-4.1.2/doc/html-main/Netsys_sasl.Info.html0000644000175000017500000004435612731530352020503 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl.Info

Module Netsys_sasl.Info

module Info: sig .. end

val mechanism_name : Netsys_sasl.sasl_mechanism -> string
val client_first : Netsys_sasl.sasl_mechanism -> [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : Netsys_sasl.sasl_mechanism -> bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : Netsys_sasl.sasl_mechanism -> bool
whether the authorization name can be transmitted
ocamlnet-4.1.2/doc/html-main/Netsmtp.Debug.html0000644000175000017500000004224212731530352017751 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsmtp.Debug

Module Netsmtp.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module By default, the exchanged Telnet commands are logged. This can be extended by setting the verbose_input and verbose_output options.
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.http_reactor_config.html0000644000175000017500000004600012731530352025662 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_reactor_config object
  method config_announce_server : Nethttpd_kernel.announcement
  method config_cgi : Netcgi.config
  method config_error_response :
    Nethttpd_types.error_response_params -> string
  method config_limit_pipeline_length : int
  method config_limit_pipeline_size : int
  method config_log_access : Nethttpd_types.full_info -> unit
  method config_log_error : Nethttpd_types.request_info -> string -> unit
  method config_max_header_length : int
  method config_max_reqline_length : int
  method config_max_trailer_length : int
  method config_reactor_synch : [ `Close | `Connection | `Flush | `Write ]
  method config_suppress_broken_pipe : bool
  method config_timeout : float
  method config_timeout_next_request : float
  method config_tls : Netsys_crypto_types.tls_config option
  method config_tls_cert_props : bool
  method config_tls_remote_user : bool
end
ocamlnet-4.1.2/doc/html-main/Netcgi_dbi.DbiPool.html0000644000175000017500000004653612731530352020662 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_dbi.DbiPool

Functor Netcgi_dbi.DbiPool

module DbiPool: 
functor (Dbi_driver : DBI_DRIVER) -> DBI_POOL with type connection = Dbi_driver.connection
module MyPool = DbiPool (Dbi_postgres)

creates a pool of PostgreSQL database handles. To use them:

let dbh = MyPool.get r "database_name"

Gets you a new or recycled database handle dbh which is valid until the end of the current Apache request.

Parameters:
Dbi_driver : DBI_DRIVER

type connection 
val get : Netcgi.cgi ->
?host:string ->
?port:string ->
?user:string -> ?password:string -> string -> connection
Example: module MyPool = DbiPool(Dbi_postgres)

let dbh = MyPool.get request "database_name"

Returns an unused Dbi.connection handle from the pool of database handles. Or it may create a new database connection and return that.

The parameters uniquely identify the database name (eg. "comments") and optional parameters. Separate pools are maintained for each combination of parameters.

The connection is automatically returned to the pool at the end of the cgi request. After this time the connection may be given away to another user. For this reason, the calling code must NEVER stash the connection across requests (instead, call get to get a new handle each time).

On returning the handle to the pool, the pool performs a ROLLBACK operation on the handle, thus losing any changes (INSERT, etc.) made to the database. If the program wants to preserve changes, it must perform a COMMIT operation itself, by calling Dbi.connection.commit.

ocamlnet-4.1.2/doc/html-main/Nethttpd_types.redirected_environment-c.html0000644000175000017500000004407012731530352025266 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.redirected_environment

Class Nethttpd_types.redirected_environment

class redirected_environment : ?in_header:Nethttp.http_header -> ?properties:(string * string) list -> ?in_channel:Netchannels.in_obj_channel -> extended_environment -> extended_environment
This class overlays the input-side containers of an existing environment. The output-side containers (out_header, and out_channel) are physically identical with the existing environment.

If one of the argument is not passed on class instantiation, the corresponding overlay container is initialized with the current value of the passed environment. As exception of this rule, the input channel is initialized with an empty input channel.


ocamlnet-4.1.2/doc/html-main/Rpc_portmapper_aux.html0000644000175000017500000042125612731530352021152 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_aux

Module Rpc_portmapper_aux

module Rpc_portmapper_aux: sig .. end

type mapping = {
   mutable prog : Netnumber.uint4;
   mutable vers : Netnumber.uint4;
   mutable prot : int;
   mutable port : int;
}
type pmaplist = {
   mutable map : mapping;
   mutable next : pmaplist option;
}
type pmaplist_p = pmaplist option 
type call_args = {
   mutable call_prog : Netnumber.uint4;
   mutable call_vers : Netnumber.uint4;
   mutable call_proc : Netnumber.uint4;
   mutable call_args : string;
}
type call_result = {
   mutable call_port : int;
   mutable call_res : string;
}
type uaddr = string 
type rpcb = {
   mutable r_prog : Netnumber.uint4;
   mutable r_vers : Netnumber.uint4;
   mutable r_netid : string;
   mutable r_addr : uaddr;
   mutable r_owner : string;
}
type rp__list = {
   mutable rpcb_map : rpcb;
   mutable rpcb_next : rp__list option;
}
type rpcblist_ptr = rp__list option 
type rpcb_rmtcallargs = call_args 
type rpcb_rmtcallres = {
   mutable call_addr : uaddr;
   mutable call_res2 : string;
}
type rpcb_entry = {
   mutable r_maddr : string;
   mutable r_nc_netid : string;
   mutable r_nc_semantics : int;
   mutable r_nc_protofmly : string;
   mutable r_nc_proto : string;
}
type rpcb_entry_list = {
   mutable rpcb_entry_map : rpcb_entry;
   mutable rpcb_entry_next : rpcb_entry_list option;
}
type rpcb_entry_list_ptr = rpcb_entry_list option 
type rpcbs_addrlist = {
   mutable al_prog : Netnumber.uint4;
   mutable al_vers : Netnumber.uint4;
   mutable al_success : int32;
   mutable al_failure : int32;
   mutable al_netid : string;
   mutable al_next : rpcbs_addrlist option;
}
type rpcbs_rmtcalllist = {
   mutable cl_prog : Netnumber.uint4;
   mutable cl_vers : Netnumber.uint4;
   mutable cl_proc : Netnumber.uint4;
   mutable cl_success : int32;
   mutable cl_failure : int32;
   mutable cl_indirect : int32;
   mutable cl_netid : string;
   mutable cl_next : rpcbs_rmtcalllist option;
}
type rpcbs_proc = Netnumber.int4 array 
type rpcbs_addrlist_ptr = rpcbs_addrlist option 
type rpcbs_rmtcalllist_ptr = rpcbs_rmtcalllist option 
type rpcb_stat = {
   mutable info : rpcbs_proc;
   mutable setinfo : int32;
   mutable unsetinfo : int32;
   mutable addrinfo : rpcbs_addrlist_ptr;
   mutable rmtinfo : rpcbs_rmtcalllist_ptr;
}
type rpcb_stat_byvers = rpcb_stat array 
type netbuf = {
   mutable maxlen : Netnumber.uint4;
   mutable buf : string;
}
type t_PMAP'V2'pmapproc_null'arg = unit 
type t_PMAP'V2'pmapproc_null'res = unit 
type t_PMAP'V2'pmapproc_set'arg = mapping 
type t_PMAP'V2'pmapproc_set'res = bool 
type t_PMAP'V2'pmapproc_unset'arg = mapping 
type t_PMAP'V2'pmapproc_unset'res = bool 
type t_PMAP'V2'pmapproc_getport'arg = mapping 
type t_PMAP'V2'pmapproc_getport'res = int 
type t_PMAP'V2'pmapproc_dump'arg = unit 
type t_PMAP'V2'pmapproc_dump'res = pmaplist_p 
type t_PMAP'V2'pmapproc_callit'arg = call_args 
type t_PMAP'V2'pmapproc_callit'res = call_result 
type t_PMAP'V3'rpcbproc_null'arg = unit 
type t_PMAP'V3'rpcbproc_null'res = unit 
type t_PMAP'V3'rpcbproc_set'arg = rpcb 
type t_PMAP'V3'rpcbproc_set'res = bool 
type t_PMAP'V3'rpcbproc_unset'arg = rpcb 
type t_PMAP'V3'rpcbproc_unset'res = bool 
type t_PMAP'V3'rpcbproc_getaddr'arg = rpcb 
type t_PMAP'V3'rpcbproc_getaddr'res = uaddr 
type t_PMAP'V3'rpcbproc_dump'arg = unit 
type t_PMAP'V3'rpcbproc_dump'res = rpcblist_ptr 
type t_PMAP'V3'rpcbproc_callit'arg = rpcb_rmtcallargs 
type t_PMAP'V3'rpcbproc_callit'res = rpcb_rmtcallres 
type t_PMAP'V3'rpcbproc_gettime'arg = unit 
type t_PMAP'V3'rpcbproc_gettime'res = Netnumber.uint4 
type t_PMAP'V3'rpcbproc_uaddr2taddr'arg = uaddr 
type t_PMAP'V3'rpcbproc_uaddr2taddr'res = netbuf 
type t_PMAP'V3'rpcbproc_taddr2uaddr'arg = netbuf 
type t_PMAP'V3'rpcbproc_taddr2uaddr'res = uaddr 
type t_PMAP'V4'rpcbproc_null'arg = unit 
type t_PMAP'V4'rpcbproc_null'res = unit 
type t_PMAP'V4'rpcbproc_set'arg = rpcb 
type t_PMAP'V4'rpcbproc_set'res = bool 
type t_PMAP'V4'rpcbproc_unset'arg = rpcb 
type t_PMAP'V4'rpcbproc_unset'res = bool 
type t_PMAP'V4'rpcbproc_getaddr'arg = rpcb 
type t_PMAP'V4'rpcbproc_getaddr'res = uaddr 
type t_PMAP'V4'rpcbproc_dump'arg = unit 
type t_PMAP'V4'rpcbproc_dump'res = rpcblist_ptr 
type t_PMAP'V4'rpcbproc_bcast'arg = rpcb_rmtcallargs 
type t_PMAP'V4'rpcbproc_bcast'res = rpcb_rmtcallres 
type t_PMAP'V4'rpcbproc_gettime'arg = unit 
type t_PMAP'V4'rpcbproc_gettime'res = Netnumber.uint4 
type t_PMAP'V4'rpcbproc_uaddr2taddr'arg = uaddr 
type t_PMAP'V4'rpcbproc_uaddr2taddr'res = netbuf 
type t_PMAP'V4'rpcbproc_taddr2uaddr'arg = netbuf 
type t_PMAP'V4'rpcbproc_taddr2uaddr'res = uaddr 
type t_PMAP'V4'rpcbproc_getversaddr'arg = rpcb 
type t_PMAP'V4'rpcbproc_getversaddr'res = uaddr 
type t_PMAP'V4'rpcbproc_indirect'arg = rpcb_rmtcallargs 
type t_PMAP'V4'rpcbproc_indirect'res = rpcb_rmtcallres 
type t_PMAP'V4'rpcbproc_getaddrlist'arg = rpcb 
type t_PMAP'V4'rpcbproc_getaddrlist'res = rpcb_entry_list_ptr 
type t_PMAP'V4'rpcbproc_getstat'arg = unit 
type t_PMAP'V4'rpcbproc_getstat'res = rpcb_stat_byvers 
val pmap_port : Netnumber.uint4
val ipproto_tcp : Netnumber.uint4
val ipproto_udp : Netnumber.uint4
val rpcb_port : Netnumber.uint4
val rpcbstat_highproc : Netnumber.uint4
val rpcbvers_stat : Netnumber.uint4
val rpcbvers_4_stat : Netnumber.uint4
val rpcbvers_3_stat : Netnumber.uint4
val rpcbvers_2_stat : Netnumber.uint4
val _to_mapping : Netxdr.xdr_value -> mapping
val _of_mapping : mapping -> Netxdr.xdr_value
val _xof_mapping : Netxdr.ctx -> mapping -> Netxdr.xdr_value
val _to_pmaplist : Netxdr.xdr_value -> pmaplist
val _of_pmaplist : pmaplist -> Netxdr.xdr_value
val _xof_pmaplist : Netxdr.ctx -> pmaplist -> Netxdr.xdr_value
val _to_pmaplist_p : Netxdr.xdr_value -> pmaplist_p
val _of_pmaplist_p : pmaplist_p -> Netxdr.xdr_value
val _xof_pmaplist_p : Netxdr.ctx -> pmaplist_p -> Netxdr.xdr_value
val _to_call_args : Netxdr.xdr_value -> call_args
val _of_call_args : call_args -> Netxdr.xdr_value
val _xof_call_args : Netxdr.ctx -> call_args -> Netxdr.xdr_value
val _to_call_result : Netxdr.xdr_value -> call_result
val _of_call_result : call_result -> Netxdr.xdr_value
val _xof_call_result : Netxdr.ctx -> call_result -> Netxdr.xdr_value
val _to_uaddr : Netxdr.xdr_value -> uaddr
val _of_uaddr : uaddr -> Netxdr.xdr_value
val _xof_uaddr : Netxdr.ctx -> uaddr -> Netxdr.xdr_value
val _to_rpcb : Netxdr.xdr_value -> rpcb
val _of_rpcb : rpcb -> Netxdr.xdr_value
val _xof_rpcb : Netxdr.ctx -> rpcb -> Netxdr.xdr_value
val _to_rp__list : Netxdr.xdr_value -> rp__list
val _of_rp__list : rp__list -> Netxdr.xdr_value
val _xof_rp__list : Netxdr.ctx -> rp__list -> Netxdr.xdr_value
val _to_rpcblist_ptr : Netxdr.xdr_value -> rpcblist_ptr
val _of_rpcblist_ptr : rpcblist_ptr -> Netxdr.xdr_value
val _xof_rpcblist_ptr : Netxdr.ctx -> rpcblist_ptr -> Netxdr.xdr_value
val _to_rpcb_rmtcallargs : Netxdr.xdr_value -> rpcb_rmtcallargs
val _of_rpcb_rmtcallargs : rpcb_rmtcallargs -> Netxdr.xdr_value
val _xof_rpcb_rmtcallargs : Netxdr.ctx -> rpcb_rmtcallargs -> Netxdr.xdr_value
val _to_rpcb_rmtcallres : Netxdr.xdr_value -> rpcb_rmtcallres
val _of_rpcb_rmtcallres : rpcb_rmtcallres -> Netxdr.xdr_value
val _xof_rpcb_rmtcallres : Netxdr.ctx -> rpcb_rmtcallres -> Netxdr.xdr_value
val _to_rpcb_entry : Netxdr.xdr_value -> rpcb_entry
val _of_rpcb_entry : rpcb_entry -> Netxdr.xdr_value
val _xof_rpcb_entry : Netxdr.ctx -> rpcb_entry -> Netxdr.xdr_value
val _to_rpcb_entry_list : Netxdr.xdr_value -> rpcb_entry_list
val _of_rpcb_entry_list : rpcb_entry_list -> Netxdr.xdr_value
val _xof_rpcb_entry_list : Netxdr.ctx -> rpcb_entry_list -> Netxdr.xdr_value
val _to_rpcb_entry_list_ptr : Netxdr.xdr_value -> rpcb_entry_list_ptr
val _of_rpcb_entry_list_ptr : rpcb_entry_list_ptr -> Netxdr.xdr_value
val _xof_rpcb_entry_list_ptr : Netxdr.ctx -> rpcb_entry_list_ptr -> Netxdr.xdr_value
val _to_rpcbs_addrlist : Netxdr.xdr_value -> rpcbs_addrlist
val _of_rpcbs_addrlist : rpcbs_addrlist -> Netxdr.xdr_value
val _xof_rpcbs_addrlist : Netxdr.ctx -> rpcbs_addrlist -> Netxdr.xdr_value
val _to_rpcbs_rmtcalllist : Netxdr.xdr_value -> rpcbs_rmtcalllist
val _of_rpcbs_rmtcalllist : rpcbs_rmtcalllist -> Netxdr.xdr_value
val _xof_rpcbs_rmtcalllist : Netxdr.ctx -> rpcbs_rmtcalllist -> Netxdr.xdr_value
val _to_rpcbs_proc : Netxdr.xdr_value -> rpcbs_proc
val _of_rpcbs_proc : rpcbs_proc -> Netxdr.xdr_value
val _xof_rpcbs_proc : Netxdr.ctx -> rpcbs_proc -> Netxdr.xdr_value
val _to_rpcbs_addrlist_ptr : Netxdr.xdr_value -> rpcbs_addrlist_ptr
val _of_rpcbs_addrlist_ptr : rpcbs_addrlist_ptr -> Netxdr.xdr_value
val _xof_rpcbs_addrlist_ptr : Netxdr.ctx -> rpcbs_addrlist_ptr -> Netxdr.xdr_value
val _to_rpcbs_rmtcalllist_ptr : Netxdr.xdr_value -> rpcbs_rmtcalllist_ptr
val _of_rpcbs_rmtcalllist_ptr : rpcbs_rmtcalllist_ptr -> Netxdr.xdr_value
val _xof_rpcbs_rmtcalllist_ptr : Netxdr.ctx -> rpcbs_rmtcalllist_ptr -> Netxdr.xdr_value
val _to_rpcb_stat : Netxdr.xdr_value -> rpcb_stat
val _of_rpcb_stat : rpcb_stat -> Netxdr.xdr_value
val _xof_rpcb_stat : Netxdr.ctx -> rpcb_stat -> Netxdr.xdr_value
val _to_rpcb_stat_byvers : Netxdr.xdr_value -> rpcb_stat_byvers
val _of_rpcb_stat_byvers : rpcb_stat_byvers -> Netxdr.xdr_value
val _xof_rpcb_stat_byvers : Netxdr.ctx -> rpcb_stat_byvers -> Netxdr.xdr_value
val _to_netbuf : Netxdr.xdr_value -> netbuf
val _of_netbuf : netbuf -> Netxdr.xdr_value
val _xof_netbuf : Netxdr.ctx -> netbuf -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_null'arg : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_null'arg
val _of_PMAP'V2'pmapproc_null'arg : t_PMAP'V2'pmapproc_null'arg -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_null'arg : Netxdr.ctx ->
t_PMAP'V2'pmapproc_null'arg -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_null'res : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_null'res
val _of_PMAP'V2'pmapproc_null'res : t_PMAP'V2'pmapproc_null'res -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_null'res : Netxdr.ctx ->
t_PMAP'V2'pmapproc_null'res -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_set'arg : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_set'arg
val _of_PMAP'V2'pmapproc_set'arg : t_PMAP'V2'pmapproc_set'arg -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_set'arg : Netxdr.ctx ->
t_PMAP'V2'pmapproc_set'arg -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_set'res : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_set'res
val _of_PMAP'V2'pmapproc_set'res : t_PMAP'V2'pmapproc_set'res -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_set'res : Netxdr.ctx ->
t_PMAP'V2'pmapproc_set'res -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_unset'arg : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_unset'arg
val _of_PMAP'V2'pmapproc_unset'arg : t_PMAP'V2'pmapproc_unset'arg -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_unset'arg : Netxdr.ctx ->
t_PMAP'V2'pmapproc_unset'arg -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_unset'res : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_unset'res
val _of_PMAP'V2'pmapproc_unset'res : t_PMAP'V2'pmapproc_unset'res -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_unset'res : Netxdr.ctx ->
t_PMAP'V2'pmapproc_unset'res -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_getport'arg : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_getport'arg
val _of_PMAP'V2'pmapproc_getport'arg : t_PMAP'V2'pmapproc_getport'arg -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_getport'arg : Netxdr.ctx ->
t_PMAP'V2'pmapproc_getport'arg -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_getport'res : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_getport'res
val _of_PMAP'V2'pmapproc_getport'res : t_PMAP'V2'pmapproc_getport'res -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_getport'res : Netxdr.ctx ->
t_PMAP'V2'pmapproc_getport'res -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_dump'arg : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_dump'arg
val _of_PMAP'V2'pmapproc_dump'arg : t_PMAP'V2'pmapproc_dump'arg -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_dump'arg : Netxdr.ctx ->
t_PMAP'V2'pmapproc_dump'arg -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_dump'res : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_dump'res
val _of_PMAP'V2'pmapproc_dump'res : t_PMAP'V2'pmapproc_dump'res -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_dump'res : Netxdr.ctx ->
t_PMAP'V2'pmapproc_dump'res -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_callit'arg : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_callit'arg
val _of_PMAP'V2'pmapproc_callit'arg : t_PMAP'V2'pmapproc_callit'arg -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_callit'arg : Netxdr.ctx ->
t_PMAP'V2'pmapproc_callit'arg -> Netxdr.xdr_value
val _to_PMAP'V2'pmapproc_callit'res : Netxdr.xdr_value -> t_PMAP'V2'pmapproc_callit'res
val _of_PMAP'V2'pmapproc_callit'res : t_PMAP'V2'pmapproc_callit'res -> Netxdr.xdr_value
val _xof_PMAP'V2'pmapproc_callit'res : Netxdr.ctx ->
t_PMAP'V2'pmapproc_callit'res -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_null'arg : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_null'arg
val _of_PMAP'V3'rpcbproc_null'arg : t_PMAP'V3'rpcbproc_null'arg -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_null'arg : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_null'arg -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_null'res : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_null'res
val _of_PMAP'V3'rpcbproc_null'res : t_PMAP'V3'rpcbproc_null'res -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_null'res : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_null'res -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_set'arg : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_set'arg
val _of_PMAP'V3'rpcbproc_set'arg : t_PMAP'V3'rpcbproc_set'arg -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_set'arg : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_set'arg -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_set'res : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_set'res
val _of_PMAP'V3'rpcbproc_set'res : t_PMAP'V3'rpcbproc_set'res -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_set'res : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_set'res -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_unset'arg : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_unset'arg
val _of_PMAP'V3'rpcbproc_unset'arg : t_PMAP'V3'rpcbproc_unset'arg -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_unset'arg : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_unset'arg -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_unset'res : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_unset'res
val _of_PMAP'V3'rpcbproc_unset'res : t_PMAP'V3'rpcbproc_unset'res -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_unset'res : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_unset'res -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_getaddr'arg : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_getaddr'arg
val _of_PMAP'V3'rpcbproc_getaddr'arg : t_PMAP'V3'rpcbproc_getaddr'arg -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_getaddr'arg : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_getaddr'arg -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_getaddr'res : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_getaddr'res
val _of_PMAP'V3'rpcbproc_getaddr'res : t_PMAP'V3'rpcbproc_getaddr'res -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_getaddr'res : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_getaddr'res -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_dump'arg : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_dump'arg
val _of_PMAP'V3'rpcbproc_dump'arg : t_PMAP'V3'rpcbproc_dump'arg -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_dump'arg : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_dump'arg -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_dump'res : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_dump'res
val _of_PMAP'V3'rpcbproc_dump'res : t_PMAP'V3'rpcbproc_dump'res -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_dump'res : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_dump'res -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_callit'arg : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_callit'arg
val _of_PMAP'V3'rpcbproc_callit'arg : t_PMAP'V3'rpcbproc_callit'arg -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_callit'arg : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_callit'arg -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_callit'res : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_callit'res
val _of_PMAP'V3'rpcbproc_callit'res : t_PMAP'V3'rpcbproc_callit'res -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_callit'res : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_callit'res -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_gettime'arg : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_gettime'arg
val _of_PMAP'V3'rpcbproc_gettime'arg : t_PMAP'V3'rpcbproc_gettime'arg -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_gettime'arg : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_gettime'arg -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_gettime'res : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_gettime'res
val _of_PMAP'V3'rpcbproc_gettime'res : t_PMAP'V3'rpcbproc_gettime'res -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_gettime'res : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_gettime'res -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_uaddr2taddr'arg : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_uaddr2taddr'arg
val _of_PMAP'V3'rpcbproc_uaddr2taddr'arg : t_PMAP'V3'rpcbproc_uaddr2taddr'arg -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_uaddr2taddr'arg : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_uaddr2taddr'arg -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_uaddr2taddr'res : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_uaddr2taddr'res
val _of_PMAP'V3'rpcbproc_uaddr2taddr'res : t_PMAP'V3'rpcbproc_uaddr2taddr'res -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_uaddr2taddr'res : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_uaddr2taddr'res -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_taddr2uaddr'arg : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_taddr2uaddr'arg
val _of_PMAP'V3'rpcbproc_taddr2uaddr'arg : t_PMAP'V3'rpcbproc_taddr2uaddr'arg -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_taddr2uaddr'arg : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_taddr2uaddr'arg -> Netxdr.xdr_value
val _to_PMAP'V3'rpcbproc_taddr2uaddr'res : Netxdr.xdr_value -> t_PMAP'V3'rpcbproc_taddr2uaddr'res
val _of_PMAP'V3'rpcbproc_taddr2uaddr'res : t_PMAP'V3'rpcbproc_taddr2uaddr'res -> Netxdr.xdr_value
val _xof_PMAP'V3'rpcbproc_taddr2uaddr'res : Netxdr.ctx ->
t_PMAP'V3'rpcbproc_taddr2uaddr'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_null'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_null'arg
val _of_PMAP'V4'rpcbproc_null'arg : t_PMAP'V4'rpcbproc_null'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_null'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_null'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_null'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_null'res
val _of_PMAP'V4'rpcbproc_null'res : t_PMAP'V4'rpcbproc_null'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_null'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_null'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_set'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_set'arg
val _of_PMAP'V4'rpcbproc_set'arg : t_PMAP'V4'rpcbproc_set'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_set'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_set'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_set'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_set'res
val _of_PMAP'V4'rpcbproc_set'res : t_PMAP'V4'rpcbproc_set'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_set'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_set'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_unset'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_unset'arg
val _of_PMAP'V4'rpcbproc_unset'arg : t_PMAP'V4'rpcbproc_unset'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_unset'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_unset'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_unset'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_unset'res
val _of_PMAP'V4'rpcbproc_unset'res : t_PMAP'V4'rpcbproc_unset'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_unset'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_unset'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_getaddr'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_getaddr'arg
val _of_PMAP'V4'rpcbproc_getaddr'arg : t_PMAP'V4'rpcbproc_getaddr'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_getaddr'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_getaddr'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_getaddr'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_getaddr'res
val _of_PMAP'V4'rpcbproc_getaddr'res : t_PMAP'V4'rpcbproc_getaddr'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_getaddr'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_getaddr'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_dump'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_dump'arg
val _of_PMAP'V4'rpcbproc_dump'arg : t_PMAP'V4'rpcbproc_dump'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_dump'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_dump'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_dump'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_dump'res
val _of_PMAP'V4'rpcbproc_dump'res : t_PMAP'V4'rpcbproc_dump'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_dump'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_dump'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_bcast'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_bcast'arg
val _of_PMAP'V4'rpcbproc_bcast'arg : t_PMAP'V4'rpcbproc_bcast'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_bcast'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_bcast'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_bcast'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_bcast'res
val _of_PMAP'V4'rpcbproc_bcast'res : t_PMAP'V4'rpcbproc_bcast'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_bcast'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_bcast'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_gettime'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_gettime'arg
val _of_PMAP'V4'rpcbproc_gettime'arg : t_PMAP'V4'rpcbproc_gettime'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_gettime'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_gettime'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_gettime'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_gettime'res
val _of_PMAP'V4'rpcbproc_gettime'res : t_PMAP'V4'rpcbproc_gettime'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_gettime'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_gettime'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_uaddr2taddr'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_uaddr2taddr'arg
val _of_PMAP'V4'rpcbproc_uaddr2taddr'arg : t_PMAP'V4'rpcbproc_uaddr2taddr'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_uaddr2taddr'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_uaddr2taddr'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_uaddr2taddr'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_uaddr2taddr'res
val _of_PMAP'V4'rpcbproc_uaddr2taddr'res : t_PMAP'V4'rpcbproc_uaddr2taddr'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_uaddr2taddr'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_uaddr2taddr'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_taddr2uaddr'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_taddr2uaddr'arg
val _of_PMAP'V4'rpcbproc_taddr2uaddr'arg : t_PMAP'V4'rpcbproc_taddr2uaddr'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_taddr2uaddr'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_taddr2uaddr'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_taddr2uaddr'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_taddr2uaddr'res
val _of_PMAP'V4'rpcbproc_taddr2uaddr'res : t_PMAP'V4'rpcbproc_taddr2uaddr'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_taddr2uaddr'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_taddr2uaddr'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_getversaddr'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_getversaddr'arg
val _of_PMAP'V4'rpcbproc_getversaddr'arg : t_PMAP'V4'rpcbproc_getversaddr'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_getversaddr'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_getversaddr'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_getversaddr'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_getversaddr'res
val _of_PMAP'V4'rpcbproc_getversaddr'res : t_PMAP'V4'rpcbproc_getversaddr'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_getversaddr'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_getversaddr'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_indirect'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_indirect'arg
val _of_PMAP'V4'rpcbproc_indirect'arg : t_PMAP'V4'rpcbproc_indirect'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_indirect'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_indirect'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_indirect'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_indirect'res
val _of_PMAP'V4'rpcbproc_indirect'res : t_PMAP'V4'rpcbproc_indirect'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_indirect'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_indirect'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_getaddrlist'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_getaddrlist'arg
val _of_PMAP'V4'rpcbproc_getaddrlist'arg : t_PMAP'V4'rpcbproc_getaddrlist'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_getaddrlist'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_getaddrlist'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_getaddrlist'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_getaddrlist'res
val _of_PMAP'V4'rpcbproc_getaddrlist'res : t_PMAP'V4'rpcbproc_getaddrlist'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_getaddrlist'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_getaddrlist'res -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_getstat'arg : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_getstat'arg
val _of_PMAP'V4'rpcbproc_getstat'arg : t_PMAP'V4'rpcbproc_getstat'arg -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_getstat'arg : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_getstat'arg -> Netxdr.xdr_value
val _to_PMAP'V4'rpcbproc_getstat'res : Netxdr.xdr_value -> t_PMAP'V4'rpcbproc_getstat'res
val _of_PMAP'V4'rpcbproc_getstat'res : t_PMAP'V4'rpcbproc_getstat'res -> Netxdr.xdr_value
val _xof_PMAP'V4'rpcbproc_getstat'res : Netxdr.ctx ->
t_PMAP'V4'rpcbproc_getstat'res -> Netxdr.xdr_value
val xdrt_mapping : Netxdr.xdr_type_term
val xdrt_pmaplist : Netxdr.xdr_type_term
val xdrt_pmaplist_p : Netxdr.xdr_type_term
val xdrt_call_args : Netxdr.xdr_type_term
val xdrt_call_result : Netxdr.xdr_type_term
val xdrt_uaddr : Netxdr.xdr_type_term
val xdrt_rpcb : Netxdr.xdr_type_term
val xdrt_rp__list : Netxdr.xdr_type_term
val xdrt_rpcblist_ptr : Netxdr.xdr_type_term
val xdrt_rpcb_rmtcallargs : Netxdr.xdr_type_term
val xdrt_rpcb_rmtcallres : Netxdr.xdr_type_term
val xdrt_rpcb_entry : Netxdr.xdr_type_term
val xdrt_rpcb_entry_list : Netxdr.xdr_type_term
val xdrt_rpcb_entry_list_ptr : Netxdr.xdr_type_term
val xdrt_rpcbs_addrlist : Netxdr.xdr_type_term
val xdrt_rpcbs_rmtcalllist : Netxdr.xdr_type_term
val xdrt_rpcbs_proc : Netxdr.xdr_type_term
val xdrt_rpcbs_addrlist_ptr : Netxdr.xdr_type_term
val xdrt_rpcbs_rmtcalllist_ptr : Netxdr.xdr_type_term
val xdrt_rpcb_stat : Netxdr.xdr_type_term
val xdrt_rpcb_stat_byvers : Netxdr.xdr_type_term
val xdrt_netbuf : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_null'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_null'res : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_set'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_set'res : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_unset'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_unset'res : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_getport'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_getport'res : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_dump'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_dump'res : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_callit'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V2'pmapproc_callit'res : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_null'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_null'res : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_set'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_set'res : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_unset'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_unset'res : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_getaddr'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_getaddr'res : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_dump'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_dump'res : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_callit'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_callit'res : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_gettime'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_gettime'res : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_uaddr2taddr'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_uaddr2taddr'res : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_taddr2uaddr'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V3'rpcbproc_taddr2uaddr'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_null'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_null'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_set'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_set'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_unset'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_unset'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_getaddr'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_getaddr'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_dump'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_dump'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_bcast'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_bcast'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_gettime'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_gettime'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_uaddr2taddr'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_uaddr2taddr'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_taddr2uaddr'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_taddr2uaddr'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_getversaddr'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_getversaddr'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_indirect'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_indirect'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_getaddrlist'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_getaddrlist'res : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_getstat'arg : Netxdr.xdr_type_term
val xdrt_PMAP'V4'rpcbproc_getstat'res : Netxdr.xdr_type_term
val program_PMAP'V2 : Rpc_program.t
val program_PMAP'V3 : Rpc_program.t
val program_PMAP'V4 : Rpc_program.t
ocamlnet-4.1.2/doc/html-main/type_Netchannels.raw_out_channel.html0000644000175000017500000004201512731530352023742 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_out_channel object
  method close_out : unit -> unit
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method pos_out : int
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.socket_service_config.html0000644000175000017500000004224212731530352025532 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.socket_service_config object
  method change_user_to : (int * int) option
  method conn_limit : int option
  method controller_config : Netplex_types.controller_config
  method gc_when_idle : bool
  method name : string
  method protocols : Netplex_types.protocol list
  method startup_timeout : float
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.delay_engine-c.html0000644000175000017500000004262612731530352023602 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.delay_engine

Class Uq_engines_compat.delay_engine

class ['a] delay_engine : float -> (unit -> 'a #engine) -> Unixqueue.event_system -> ['a] engine

ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.watchdog-c.html0000644000175000017500000004241712731530352022755 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.watchdog

Class Uq_engines_compat.watchdog

class watchdog : float -> 'a #engine -> [unit] engine

ocamlnet-4.1.2/doc/html-main/Netplex_types.config_file-c.html0000644000175000017500000004706012731530352022623 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.config_file

Class type Netplex_types.config_file

class type config_file = object .. end

method filename : string
method tree : config_tree
method root_addr : address
method root_name : string
method resolve_section : address -> string -> address list
method resolve_parameter : address -> string -> address
method print : address -> string
method string_param : address -> string
method int_param : address -> int
method float_param : address -> float
method bool_param : address -> bool
method restrict_subsections : address -> string list -> unit
method restrict_parameters : address -> string list -> unit
ocamlnet-4.1.2/doc/html-main/Netshm_array.html0000644000175000017500000005142212731530352017726 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm_array

Module Netshm_array

module Netshm_array: sig .. end
Arrays in shared memory

type 'a t 
val manage : ?pagesize:int ->
?init:int ->
'a ->
'a Netshm_data.data_manager ->
Netshm.locking_method -> Netshm.shm_descr -> 'a t
Manages a shared memory object as an array, including the representation of arbitrary O'Caml values. The first argument of type 'a is the default value of the array elements.

This bases on Netshm.manage, and the arguments pagesize, locking_method and shm_descr are documented there.

If an empty memory object is managed, it is initialized as array with zero elements. If a non-empty memory object is managed, it must contain a valid array structure. The size of the array is then the same as when the array was managed the last time.

By passing init with argument n, the array is reinitialized as array with n elements containing the default value.

It is essential that the same data managers are passed as at the time when the array was initialized.

Arrays are implemented as (int32, 'a) Netshm_hashtbl.t.

val length : 'a t -> int
Returns the length of the array
val get : 'a t -> int -> 'a
get a k: Returns the contents of the array element number k where 0 <= k < length a.

If you do module Array = Netshm_array in your code you can also use the notation a.(k).

val set : 'a t -> int -> 'a -> unit
set a k x: Sets the contents of the array element number k to x where 0 <= k < length a.

If you do module Array = Netshm_array in your code you can also use the notation a.(k) <- x.

val resize : 'a t -> int -> unit
resize a n: Resizes the array to length n. If the array is enlarged the new elements will be initialized to the default value.
val default_value : 'a t -> 'a
Returns the default value
val shm_table : 'a t -> Netshm.shm_table
Returns the underlying shared memory table used to implement hash tables
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.cache-c.html0000644000175000017500000004264012731530352022216 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.cache

Class Uq_engines_compat.cache

class ['a] cache : (Unixqueue.event_system -> 'a engine) -> Unixqueue.event_system -> ['a] cache_t

ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.pseudo_async_out_channel.html0000644000175000017500000004104712731530352025700 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.pseudo_async_out_channel #Netchannels.raw_out_channel -> Uq_transfer.async_out_channelocamlnet-4.1.2/doc/html-main/type_Nethttp_client.post_call.html0000644000175000017500000004060612731530352023300 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.post_call Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/type_Netstring_str.html0000644000175000017500000006536212731530352021210 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstring_str sig
  type regexp
  type split_result = Str.split_result = Text of string | Delim of string
  type result
  val regexp : string -> Netstring_str.regexp
  val regexp_case_fold : string -> Netstring_str.regexp
  val quote : string -> string
  val regexp_string : string -> Netstring_str.regexp
  val regexp_string_case_fold : string -> Netstring_str.regexp
  val quote_set : string -> string
  val string_match :
    Netstring_str.regexp -> string -> int -> Netstring_str.result option
  val bytes_match :
    Netstring_str.regexp -> Bytes.t -> int -> Netstring_str.result option
  val search_forward :
    Netstring_str.regexp -> string -> int -> int * Netstring_str.result
  val search_forward_bytes :
    Netstring_str.regexp -> Bytes.t -> int -> int * Netstring_str.result
  val search_backward :
    Netstring_str.regexp -> string -> int -> int * Netstring_str.result
  val search_backward_bytes :
    Netstring_str.regexp -> Bytes.t -> int -> int * Netstring_str.result
  val matched_string : Netstring_str.result -> string -> string
  val matched_bytes : Netstring_str.result -> Bytes.t -> Bytes.t
  val match_beginning : Netstring_str.result -> int
  val match_end : Netstring_str.result -> int
  val matched_group : Netstring_str.result -> int -> string -> string
  val matched_group_bytes : Netstring_str.result -> int -> Bytes.t -> Bytes.t
  val group_beginning : Netstring_str.result -> int -> int
  val group_end : Netstring_str.result -> int -> int
  val global_replace : Netstring_str.regexp -> string -> string -> string
  val replace_first : Netstring_str.regexp -> string -> string -> string
  val global_substitute :
    Netstring_str.regexp ->
    (Netstring_str.result -> string -> string) -> string -> string
  val substitute_first :
    Netstring_str.regexp ->
    (Netstring_str.result -> string -> string) -> string -> string
  val split : Netstring_str.regexp -> string -> string list
  val bounded_split : Netstring_str.regexp -> string -> int -> string list
  val split_delim : Netstring_str.regexp -> string -> string list
  val bounded_split_delim :
    Netstring_str.regexp -> string -> int -> string list
  val full_split :
    Netstring_str.regexp -> string -> Netstring_str.split_result list
  val bounded_full_split :
    Netstring_str.regexp -> string -> int -> Netstring_str.split_result list
  val string_before : string -> int -> string
  val string_after : string -> int -> string
  val first_chars : string -> int -> string
  val last_chars : string -> int -> string
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Nethttp.HTTP_CLIENT_MECHANISM.html0000644000175000017500000007124612731530352022126 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.HTTP_CLIENT_MECHANISM

Module type Nethttp.HTTP_CLIENT_MECHANISM

module type HTTP_CLIENT_MECHANISM = sig .. end

val mechanism_name : string
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
val restart_supported : bool
Whether the mechanism supports quick restarts (re-authentication)
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

The password is encoded in UTF-8. However, note that not all protocols are able to transmit all of UTF-8. If a non-transmittable character is found, the authentication will fail.

The password can have parameters:

  • "realm": the password is only applicable to this realm. The realm parameter should only occur once.
  • "domain-uri": the password is only applicable to this URI space. The URI must include the protocol scheme, the host name, and "/" as path. The port number is optional. Example: "http://localhost/". The domain-uri parameter can occur several times.

val client_match : params:(string * string * bool) list ->
Nethttp.Header.auth_challenge -> Nethttp.match_result
Checks whether this mechanism can accept the initial authentication challenge (i.e. the first challenge sent from the server to the client. The params are as for create_client_session. On success, returns `Accept(realm,id_opt). On failure, returns `Reject. This function usually does not raise exceptions.

If the mechanism does not support the notion of realms, a dummy realm should be returned.

The id_opt is the session ID (if supported). Session IDs can be used to bind reauthentications to the original session.

The challenge is from a www-authenticate or a proxy-authenticate header.

There is also the result `Reroute(realm, trans_id), meaning that the request would be acceptable if it came over the transport identified by trans_id. `Accept_reroute is the combination of accepting and rerouting, i.e. the auth protocol can start, but the second request should go over the other transport. Both `Reroute and `Accept_reroute are only allowed for initial challenges.

type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user. The credentials are creds.

user must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

Available parameters:

  • "realm"
  • "id" (if client_match returns a session ID)
  • "trans_id": the Nethttp_client.transport_layer_id of the current HTTP request
  • "conn_id": an identifier for the TCP connection
  • "https": is set to "true" if the current connection is TLS-secured
  • "target-host": the hostname from the HTTP request
  • "target-uri": the URL from the HTTP request

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : params:(string * string * bool) list ->
client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK. After the restart the session will be in state `Emit.

The params are the same as for create_client_session, but updated where needed.

val client_process_challenge : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
Nethttp.Header.auth_challenge -> client_session
client_process_challenge cs method uri header challenge:

Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.

method is the request method. uri is the request URI

val client_emit_response : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
client_session *
Nethttp.Header.auth_credentials * (string * string) list
let (creds,new_headers) = client_emit_response cs method uri header:

Emit a new response as a pair (creds,new_headers). The state must be `Emit. The creds either go into the authorization or proxy-authorization header. The new_headers are additional headers to modify.

val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_domain : client_session -> string list
After successful authentication, this function may return the URIs defining the authentication space.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. Commonly supported keys:
  • "realm"
  • "domain-uri"

val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Returns the GSSAPI props if available, or raise Not_found
ocamlnet-4.1.2/doc/html-main/Rpc_client.tls_socket_config-c.html0000644000175000017500000004244712731530352023301 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.tls_socket_config

Class Rpc_client.tls_socket_config

class tls_socket_config : (module Netsys_crypto_types.TLS_CONFIG) -> socket_config
TLS configuration as class

ocamlnet-4.1.2/doc/html-main/Unixqueue.event_system-c.html0000644000175000017500000005527312731530352022236 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.event_system

Class type Unixqueue.event_system

class type event_system = object .. end
The event_system manages events, handlers, resources, groups, etc. It is now a class type, and you may invoke the operations directly for the class. The operations are still available as functions (below).

A resource is an operation with an optional timer. The operation describes the condition to watch for, and the timer defines the maximum period of time for that. If the condition becomes true, an Input_arrived, Output_readiness, or Out_of_band event will be triggered. If the timer expires, a Timeout event will be generated. After the event the resource remains active, and the timeout period begins anew.

A resource is usually bound to a file descriptor. It is allowed to watch the same descriptor for several different conditions, but it is forbidden to watch the same descriptor for the same kind of condition several times.

As a special case, the operation Wait is not bound to a file descriptor, but simply starts a timer. The argument of Wait can be used to distinguish between several timers that are active at the same time.

Event handlers get the events one after the other, and process them. When a handler is called for an event, there are several possible reactions: (1) The handler can return normally, which means that the event has been accepted, and will not be passed to any other handler. (2) The handler can raise Equeue.Reject, which means that the handler cannot process the event, and that another handler should get it. (3) The handler can raise Equeue.Terminate which means that the event has been accepted, and that the handler is terminated (it will never be called again). (4) The handler can raise Abort which means that the event is deferred, and that a special abort mechanism is triggered (see the description for Abort above), this is also terminates the handler. The deferred event will again be processed in the future. (5) The handler can raise any other exception. This causes that the event is deferred, and the exception falls through to the caller of run.

Groups are used to simplify the association of events to handlers, and to simplify the termination of handlers (see clear). If an event is associated with a group, only handlers associated with the same group will get them.

There is a special Close handler which is useful to close file descriptors no longer needed. It is called when all resources are removed from the event system dealing with the file descriptor. The close handler should close the descriptor. Note that close handlers are only useful under certain circumstances.


method new_group : unit -> group
method new_wait_id : unit -> wait_id
method exists_resource : operation -> bool
method add_resource : group -> operation * float -> unit
method add_weak_resource : group -> operation * float -> unit
method add_close_action : group -> Unix.file_descr * (Unix.file_descr -> unit) -> unit
method add_abort_action : group -> (group -> exn -> unit) -> unit
method remove_resource : group -> operation -> unit
method add_handler : group ->
(event_system ->
event Equeue.t -> event -> unit) ->
unit
method add_event : event -> unit
method clear : group -> unit
method run : unit -> unit
method is_running : bool
method when_blocking : (unit -> unit) -> unit
ocamlnet-4.1.2/doc/html-main/index.html0000644000175000017500000017462512731530352016414 0ustar gerdgerd Ocamlnet 4 Reference Manual

Ocamlnet 4 Reference Manual

OCamlnet is an enhanced system platform library for Ocaml. As the name suggests, large parts of it have to do with network programming, but it is actually not restricted to this. Other parts deal with the management of multiple worker processes, and the interaction with other programs running on the same machine. You can also view Ocamlnet as an extension of the system interface as provided by the Unix module of the standard library.

Overview: What you can do with OCamlnet:

Domain Task Protocol/mechanism Frameworks
Web applications Dynamic web content,
Connect with web server,
Standalone web servers
Web server connectors: CGI, FastCGI, SCGI, AJP.
HTTP server
Netcgi (connector framework)
Network applications
(classic client/server)
SunRPC clients,
SunRPC servers
SunRPC binary protocol,
SunRPC stub generator,
Portmapper/RPCBIND,
RPCSEC_GSS
Network applications
(modern client/server)
Call HTTP interfaces,
Provide HTTP interfaces
HTTP client,
HTTP server,
HTTP authentication
Email applications Create emails with attachments,
Send emails,
Parse emails,
Interact with email server
SMTP client,
POP client,
SASL authentication
Network utilities Data download and upload,
Encode and decode,
Character sets,
Structured formats,
URLs,
IPv6
HTTP client,
FTP client
Netfs (filesystem framework)
System utiltities Invoke commands,
Daemonize,
Shared memory,
Logging,
Locales,
Timers
Netplex (multi-process daemons)
Authentication and security Network authentication,
Integrity protection,
Privacy
TLS (via GnuTLS),
SASL,
GSSAPI (Kerberos),
LDAP client
Pluggable security providers
for TLS, SASL, GSSAPI,
Digests,
Symmetric ciphers

Introductory chapters

Guides

  • Ocamlnet4: Changes in OCamlnet-4
  • Foreword: How Ocamlnet is organized
  • Get: How to get OCamlnet
  • Platform: Which functions are available on which platform (POSIX/Win32). Also hints for portable programming.
  • Ipv6: The state of IPv6 support
  • Tls: TLS support
  • Crypto: Cryptography
  • Authentication: Authentication frameworks
  • Credentials: How to express and store credentials
  • Gssapi: The GSSAPI security layer
  • Regexp: Regular expression backends

Contents by library

Base Libraries

Guides

External articles

The netstring library: string processing functions

netstring focuses on string processing functions, and base definitions for other libraries.


Netaccel
Accelerators for bytecode
Netaccel_link
Enables accelerator module Netaccel
Netaddress
Parsing of mail addresses
Netasn1
ASN.1 support functions
Netasn1_encode
ASN.1 encoder
Netauth
Some primitives for authentication
Netaux
Internal auxiliary functions
Netbuffer
A Netbuffer.t is a buffer that can grow and shrink dynamically.
Netchannels
Object-oriented I/O: Basic types and classes
Netchannels_crypto
Crypto extensions for Netchannels
Netcompression
Registry for compression algorithms
Netconversion
Conversion between character encodings
Netdate
Support for common date/time parsing and formatting.
Netdn
X.500 distinguished names
Netencoding
Base64, Quoted Printable, URL encoding, HTML escaping
Netfs
Class type stream_fs for filesystems with stream access to files
Netglob
Globbing
Netgssapi_auth
Authentication helpers for GSSAPI
Netgssapi_support
Support functions for GSS-API
Nethtml
Parsing of HTML
Nethttp
Basic definitions for the HTTP protocol
Netmappings
Internal access to the character conversion database
Netmech_crammd5_sasl
The CRAM-MD5 SASL mechanism (RFC 2195), which is obsolete and only provided for completeness.
Netmech_digest_http
Digest authentication for HTTP
Netmech_digest_sasl
The DIGEST-MD5 SASL mechanism (RFC 2831).
Netmech_gs2_sasl
The GS2 bridge for using GSSAPI mechanisms as SASL mechanisms
Netmech_krb5_sasl
Kerberos 5 as SASL mechanism
Netmech_plain_sasl
The PLAIN SASL mechanism (RFC 4616).
Netmech_scram
SCRAM mechanism for authentication (RFC 5802)
Netmech_scram_gssapi
The SCRAM security mechanism for GSS-API
Netmech_scram_sasl
SCRAM as SASL mechanism
Netmech_scram_http
SCRAM for HTTP (prerelease)
Netmech_spnego_http
SPNEGO (GSSAPI) authentication for HTTP
Netmime
Netmime contains high-level classes and functions to process mail and MIME messages.
Netmime_channels
MIME: parsing and printing for channels
Netmime_header
MIME: Access methods for frequent standard fields.
Netmime_string
Low-level functions to parse and print mail and MIME messages
Netnumber
Binary encodings of numbers
Netoid
X.500 Object Identifiers
Netpagebuffer
Buffer for page-aligned I/O
Netsaslprep
The SASLprep algorithm (RFC 4013)
Netsendmail
Functions to compose and send electronic mails
Netsockaddr
Parsing of socket addresses
Netstream
A netstream is an input channel that is read block by block.
Netstring_str
Wrapper for regexps with Str syntax
Netstring_tstring
Support module for tagged strings
Nettls_support
Support types and functions for TLS
Netulex
Support module for Alain Frisch's ulex lexer generator
Netunichar
Unicode character information
Neturl
Uniform Resource Locators (URLs)
Neturl_ldap
LDAP-specific URLs
Netx509
X.509 certificates
Netx509_pubkey
X.509 public key cryptography - keys and naming
Netx509_pubkey_crypto
X.509 public key cryptography - wrappers
Netxdr
External Data Representation
Netxdr_mstring
Managed Strings

The netstring-pcre library: additions for PCRE


Netstring_pcre
Wrapper for regexps with PCRE syntax

The netunidata library: Unicode tables


Netunidata
Configure how to load Unicode tables

The netzip library: compression for object channels

Support for (un)compressing data on the fly with object channels. Requires ocamlzip.


Netgzip
Gzip object channels

The equeue library: concurrent execution flows via event queues

equeue is a fundamental library for event queues. It is mainly used by a number of other libraries of Ocamlnet to parallelize network code (so-called multiplexing).


Equeue
Equeue implements generic event queues.
Unixqueue
Unixqueues are one of the two forms of system event loops provided by Ocamlnet.
Unixqueue_pollset
Unixqueue implementation on top of Netsys_pollset
Unixqueue_select
This the old Unix.select-based imeplementation of event systems which was the default one until Ocamlnet-2.2.
Uq_engines
An engine performs a certain task in an autonomous way.
Uq_socks5
This module implements a SOCKS version 5 client (see RFC 1928) for use with the Uq_engines.connector, Uq_engines.listener, and Uq_engines.datagram_provider engine factories.
Uq_resolver
Support for pluggable resolvers
Uq_io
Unified engines for stream I/O
Uq_client
Support for socket clients
Uq_server
Server sockets
Uq_multiplex
Multiplex Controllers
Uq_transfer
Transfer engines
Uq_lwt
Compatibility with Lwt
Uq_libevent
Use Libevent as event loop
Uq_mt
Using engines in multi-threaded programs

The equeue-gtk1 and equeue-gtk2 extensions

Extensions for equeue to integrate the event queue into user interfaces made with lablgtk and lablgtk2


Uq_gtk
Integration with lablgtk/lablgtk2 event systems

The equeue-tcl extension

Extension for equeue to integrate the event queue into user interfaces made with labltk


Uq_tcl
Integration with the labltk event system

The netplex library: generic server framework

The netplex library is a protocol-independent server framework. Especially, it can be used in conjunction with nethttpd to build web servers, and with rpc to build RPC servers.


Netplex_types
Types for Netplex
Netplex_config
Read the configuration file
Netplex_controller
Controller
Netplex_container
Containers
Netplex_sockserv
Socket service creation
Netplex_workload
Workload management
Netplex_kit
Netplex toolkit
Netplex_cenv
Container environment
Netplex_log
Loggers
Netplex_main
Main program for Netplex servers
Netplex_mp
Multi-processing provider
Netplex_mt
Multi-threading provider
Netplex_mutex
Netplex-wide mutexes
Netplex_semaphore
Netplex-wide semaphores
Netplex_sharedvar
Netplex-wide variables
Netplex_mbox
Netplex message boxes
Netplex_encap
Type-safe marshalling between processes of the same executable
Netplex_internal
Internal services
Rpc_netplex
Netplex support for RPC servers (TCP only)

The shell library: start external commands

The shell library allows you to start external commands. It is integrated into equeue.


Shell
Calls external programs, creates pipelines, etc.
Shell_sys
Calls external programs, creates pipelines, etc.
Shell_uq
Run shell commands within Unixqueues
Shell_fs
Shell filesystem

The netshm library: manage shared memory

The netshm library manages a shared memory object either as hash table or array. It is designed to be used in multi-processing program architectures. Note that there is now also the much better The netmulticore library: compute jobs library.


Netshm
Shared memory for O'Caml programs using multi-processing
Netshm_data
Data representation for shared memory
Netshm_hashtbl
Hash tables in shared memory
Netshm_array
Arrays in shared memory

The netsys library: system interfaces

The netsys library contains a number of low-level functions used by other Ocamlnet libraries.


Platform
Netexn
Exception registry
Netlog
Basic logging facility
Netsys
System calls missing in the Unix module
Netsys_posix
POSIX-specific system calls missing in the Unix module, and further API's from POSIX-style operating systems.
Netsys_oothr
Object-oriented thread API
Netsys_signal
Signal handler framework
Netsys_tmp
Temporary files
Netsys_mem
Bigarrays as memory buffers
Netsys_sem
Generic anonymous semaphores
Netsys_global
Global variables
Netsys_pollset
Sets of file descriptors for polling
Netsys_pollset_generic
Returns a good standard implementation of pollset for this platform.
Netsys_pollset_posix
Pollsets for POSIX operating systems
Netsys_pollset_win32
Pollsets for Win32
Netsys_win32
Primitives for Win32
Netsys_polypipe
Polymorphic message pipes
Netsys_polysocket
Polymorphic message sockets
Netsys_rng
Random-number generator
Netsys_crypto_types
Types for crypto providers
Netsys_crypto
Cryptographic providers
Netsys_crypto_modes
Helpers for crypto modes
Netsys_tls
User-level TLS API
Netsys_ciphers
Symmetric cryptographic ciphers
Netsys_digests
Cryptographic digests (hashes)
Netsys_gssapi
GSS-API Definition

The nettls-gnutls library: GnuTLS bindings


Nettls_gnutls
GnuTLS
Nettls_gnutls_bindings
Bindings of a C library
Nettls_nettle_bindings
Bindings of a C library

The netgss library: GSSAPI bindings


Netgss
This is the system-wide version of GSSAPI
Netgss_bindings
Bindings of a C library

Web Programming

Guides

The netcgi1 library

The netcgi1 library is no longer supported in Ocamlnet 3. Please switch to netcgi2.

The netcgi2 library: web application framework

This is the revised library for Web applications, now called netcgi2.


Netcgi
Common data-structures for CGI-like connectors.
Netcgi_common
Functions to develop new connectors.
Netcgi_cgi
Classical CGI connector.
Netcgi_fcgi
FastCGI connector.
Netcgi_ajp
Apache JServ Protocol (AJP) 1.3 connector.
Netcgi_scgi
SCGI connector.
Netcgi_test
Connector for testing your code.
Netcgi_dbi
Pools of connections for the ocamldbi generic database interface.
Netcgi1_compat
Compatibility module with the previous version of Netcgi.

The netcgi2-apache library: run web apps inside Apache

This is an Apache connector for the netcgi2 library.


Netcgi_apache
Netcgi Apache "mod" connector.
Netcgi_modtpl

The netcgi2-plex library: run web apps with Netplex

Netplex support for running Netcgi2 connectors:


Netcgi_plex
Netplex support for FastCGI, SCGI and AJP connectors

The nethttpd library: standalone web apps

The nethttpd library is a Web server component written in O'Caml. For a full web server, you'll also need netplex.


Nethttpd_types
Type definitions for the HTTP daemon
Nethttpd_kernel
The protocol kernel of the HTTP daemon
Nethttpd_reactor
The reactive encapsulation of the HTTP daemon
Nethttpd_engine
The event-based encapsulation of the HTTP daemon
Nethttpd_services
Service Providers for HTTP daemon
Nethttpd_plex
Netplex support
Nethttpd_util
Utility functions

Client/Server Programming

Guides

External articles

The rpc library: SunRPC

This library implements OncRPC (alias SunRPC).


Rpc
Common types and exceptions
Rpc_program
RPC programs
Rpc_client
RPC clients
Rpc_simple_client
Synchronous API for RPC clients
Rpc_proxy
RPC proxies
Rpc_server
RPC servers
Rpc_auth_sys
Authentication module AUTH_SYS
Rpc_portmapper
Portmapper/RPCBIND interface
Rpc_portmapper_aux
Rpc_portmapper_clnt
Rpc_transport
Low-level RPC transporters
Rpc_packer
Packing and Unpacking of messages; can be used by both client and server programs.
Rpc_auth_gssapi
GSS-API for RPC authentication

The rpc-auth-local extension: authentication for local sockets

Authentication for local socket connections.


Rpc_auth_local
Return the authentication method AUTH_LOCAL.

The rpc-xti extension: System V helpers

System V provides a network API called XTI in addition to the socket API. This library allows it to connect to RPC services that can only be reached over a local XTI connection ("cots" connection).


Rpc_xti_client
Minimal support for TI-RPC over the XTI API

Parallel Computing

Guides

Important change since OCaml-4.01: This OCaml version changed the semantics of the built-in primitives caml_modify and caml_initialize. Essentially, it is no longer possible to modify OCaml values residing outside the regular OCaml heap. As we do this inside Netcamlbox and Netmulticore, this change affects these libraries. Fortunately, there is a workaround on systems supporting weak symbols (all ELF systems and OS X): Here, caml_modify and caml_initialize are overridden by Ocamlnet so that they are again compatible. Note that this is a global modification of the runtime system!

The netcamlbox library: message passing

Camlbox is a fast message-passing system between processes running on the same machine. It uses shared memory for communication. A message sent to a Camlbox is only copied once, not twice.


Netcamlbox
Camlboxes are a fast IPC mechanism to send Ocaml values from one process to another.

The netmulticore library: compute jobs

Netmulticore is an experimental framework for managing multiple processes, and sending messages between them.


Netmcore
Multi-processing for compute jobs
Netmcore_process
Statically typed processes
Netmcore_mempool
Memory pools
Netmcore_heap
Shared heaps of structured values
Netmcore_array
Shared arrays
Netmcore_buffer
Shared buffer
Netmcore_hashtbl
Shared hashtables
Netmcore_matrix
Shared 2-dimensional arrays (matrices)
Netmcore_queue
Shared queues
Netmcore_ref
Shared mutable variables
Netmcore_mutex
Mutexes
Netmcore_sem
Semaphores
Netmcore_condition
Condition variables
Netmcore_camlbox
Camlboxes for use in netmulticore programs

Network Protocol Libraries

Guides

The netclient library: HTTP, FTP, Telnet, POP, SMTP, LDAP

This library includes clients for HTTP, Telnet, FTP, SMTP, POP, and LDAP.


Nethttp_client
HTTP 1.1 client
Nethttp_client_conncache
Connection cache
Nethttp_fs
HTTP filesystem
Netftp_client
FTP client
Netftp_data_endpoint
Senders and receivers for the FTP data connection
Netftp_fs
FTP filesystem
Netldap
LDAP client
Nettelnet_client
Telnet client
Netpop
This is an interface for the Post Office Protocol - Version 3 (POP3) as specifed by RFC 1939.
Netsmtp
This is an interface for the Simple Mail Tranfer Protocol (SMTP) as specified by RFC 2821.

Trailer

Index

Authors

The Ocamlnet libraries have been initially written by Gerd Stolpmann and Patrick Doane.

Contributions by

  • Nicolas George: Netdate
  • Eric Stokes: FastCGI support
  • Pierre Habouzit: SMTP client
  • Christophe Troestler: Revised version of netcgi
  • Deokhwan Kim: Support for EUC-KR
Sponsorships by

  • Baretta s.r.l: Nethttpd
  • California State University: SSL support for RPC, Netplex

ocamlnet-4.1.2/doc/html-main/type_Netsys_oothr.html0000644000175000017500000005230612731530352021035 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr sig
  class type mtprovider =
    object
      method create_condition : unit -> Netsys_oothr.condition
      method create_mutex : unit -> Netsys_oothr.mutex
      method create_thread : ('-> 't) -> '-> Netsys_oothr.thread
      method self : Netsys_oothr.thread
      method single_threaded : bool
      method yield : unit -> unit
    end
  and thread =
    object method id : int method join : unit -> unit method repr : exn end
  and mutex =
    object
      method lock : unit -> unit
      method repr : exn
      method try_lock : unit -> bool
      method unlock : unit -> unit
    end
  and condition =
    object
      method broadcast : unit -> unit
      method repr : exn
      method signal : unit -> unit
      method wait : Netsys_oothr.mutex -> unit
    end
  val provider : Netsys_oothr.mtprovider Pervasives.ref
  val serialize : Netsys_oothr.mutex -> ('-> 'b) -> '-> 'b
  val atomic_init : 'a option Pervasives.ref -> '-> 'a
  val compare_and_swap : 'Pervasives.ref -> '-> '-> bool
end
ocamlnet-4.1.2/doc/html-main/type_Netmime.mime_body_ro.html0000644000175000017500000004165312731530352022401 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.mime_body_ro object
  method finalize : unit -> unit
  method open_value_rd : unit -> Netchannels.in_obj_channel
  method store : Netmime.store
  method value : string
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.Convenience.html0000644000175000017500000006325312731530352022516 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.Convenience

Module Nethttp_client.Convenience

module Convenience: sig .. end


Convenience module for simple applications

Convenience module for simple applications

Do open Nethttp_client.Convenience for simple applications.

Convenience module for simple applications

Do open Nethttp_client.Convenience for simple applications.

The functions of this module share the following behaviour:

The environment variables http_proxy and no_proxy determine the proxy settings. http_proxy must be an http-URL that contains the proxy's name, its port, and optionally user and password. E.g. "http://eric:ericspassword@proxy:8080/". The variable no_proxy is a comma-separated list of hosts and domains for which no proxy must be used. E.g. "localhost, sun, moon, .intra.net"

There is a default behaviour for authentication. Both "basic" and "digest" methods are enabled. Two global variables, http_user and http_password set the user and password if the URL does not specify them. In the case that user and password are included in the URL, these values are always used. Note that basic authentication is by default only enabled over connections that are secured via TLS! You can change that with the function configure, see below.

There is a default error behaviour. If a request fails, it is automatically repeated. The variable http_trials specifies the number of times a request is submitted at most. Requests are not repeated if there is a HTTP return code that indicates a normal operating condition. POST and DELETE requests are never repeated.

Error codes are reported as Nethttp_client.Http_error. Note that this is different than what the pipeline core does.

Convenience module for simple applications

Do open Nethttp_client.Convenience for simple applications.

The functions of this module share the following behaviour:

The environment variables http_proxy and no_proxy determine the proxy settings. http_proxy must be an http-URL that contains the proxy's name, its port, and optionally user and password. E.g. "http://eric:ericspassword@proxy:8080/". The variable no_proxy is a comma-separated list of hosts and domains for which no proxy must be used. E.g. "localhost, sun, moon, .intra.net"

There is a default behaviour for authentication. Both "basic" and "digest" methods are enabled. Two global variables, http_user and http_password set the user and password if the URL does not specify them. In the case that user and password are included in the URL, these values are always used. Note that basic authentication is by default only enabled over connections that are secured via TLS! You can change that with the function configure, see below.

There is a default error behaviour. If a request fails, it is automatically repeated. The variable http_trials specifies the number of times a request is submitted at most. Requests are not repeated if there is a HTTP return code that indicates a normal operating condition. POST and DELETE requests are never repeated.

Error codes are reported as Nethttp_client.Http_error. Note that this is different than what the pipeline core does.

Thread safety

The Convenience module is fully thread-safe with the exception of the exported variables (http_trials, http_user, and http_password). Note that all threads share the same pipeline, and access to the pipeline is serialized. The latter simply means that it always works, but that threads may block each other (i.e. the program slows down if more than one thread wants to open http connections at the same time).

val http_trials : int Pervasives.ref
number of times every request is tried. Default: 3
val http_user : string Pervasives.ref
The default user if authentication is required
val http_password : string Pervasives.ref
The default password if authentication is required
val configure : ?insecure:bool -> unit -> unit
Configurations:
  • insecure: whether basic authentication over non-TLS connections is enabled
You can only configure before the first user.
val configure_pipeline : (Nethttp_client.pipeline -> unit) -> unit
This function will be called before the pipeline is used. This is intended for fine-grained configuration.
val http_get_message : string -> Nethttp_client.http_call
Does a "GET" request with the given URL and returns the message
val http_head_message : string -> Nethttp_client.http_call
Does a "HEAD" request with the given URL and returns the reply.
val http_post_message : string -> (string * string) list -> Nethttp_client.http_call
Does a "POST" request with the given URL and returns the reply. The list contains the parameters sent with the POST request.
val http_put_message : string -> string -> Nethttp_client.http_call
Does a "PUT" request with the given URL and returns the reply. The second argument contains the contents to be put.
val http_delete_message : string -> Nethttp_client.http_call
Does a "DELETE" request with the given URL and returns the reply.
val http_get : string -> string
Does a "GET" request with the given URL and returns the message body
val http_post : string -> (string * string) list -> string
Does a "POST" request with the given URL and returns the response body. The list contains the parameters send with the POST request.
val http_put : string -> string -> string
Does a "PUT" request with the given URL and returns the response body. The second argument contains the contents to be put.
val http_delete : string -> string
Does a "DELETE" request with the given URL and returns the response body.
val http_verbose : ?verbose_status:bool ->
?verbose_request_header:bool ->
?verbose_response_header:bool ->
?verbose_request_contents:bool ->
?verbose_response_contents:bool ->
?verbose_connection:bool -> ?verbose_events:bool -> unit -> unit
Turns on debug messages on stderr. By default, all options are turned on.
ocamlnet-4.1.2/doc/html-main/type_Uq_io.html0000644000175000017500000011253612731530352017413 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_io sig
  type in_buffer
  type out_buffer
  type in_device =
      [ `Async_in of Uq_engines.async_in_channel * Unixqueue.event_system
      | `Buffer_in of Uq_io.in_buffer
      | `Count_in of (int -> unit) * Uq_io.in_device
      | `Multiplex of Uq_engines.multiplex_controller
      | `Polldescr of
          Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ]
  type out_device =
      [ `Async_out of Uq_engines.async_out_channel * Unixqueue.event_system
      | `Buffer_out of Uq_io.out_buffer
      | `Count_out of (int -> unit) * Uq_io.out_device
      | `Multiplex of Uq_engines.multiplex_controller
      | `Polldescr of
          Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ]
  type in_bdevice = [ `Buffer_in of Uq_io.in_buffer ]
  type io_device =
      [ `Multiplex of Uq_engines.multiplex_controller
      | `Polldescr of
          Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ]
  type string_like = Netsys_types.tbuffer
  val device_supports_memory :
    [ `Async_in of Uq_engines.async_in_channel * Unixqueue.event_system
    | `Async_out of Uq_engines.async_out_channel * Unixqueue.event_system
    | `Buffer_in of Uq_io.in_buffer
    | `Buffer_out of Uq_io.out_buffer
    | `Count_in of (int -> unit) * Uq_io.in_device
    | `Count_out of (int -> unit) * Uq_io.out_device
    | `Multiplex of Uq_engines.multiplex_controller
    | `Polldescr of
        Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ] ->
    bool
  exception Line_too_long
  val input_e :
    [< Uq_io.in_device ] ->
    Netsys_types.tbuffer -> int -> int -> int Uq_engines.engine
  val really_input_e :
    [< Uq_io.in_device ] ->
    Netsys_types.tbuffer -> int -> int -> unit Uq_engines.engine
  val input_line_e :
    ?max_len:int -> Uq_io.in_bdevice -> string Uq_engines.engine
  val input_lines_e :
    ?max_len:int -> Uq_io.in_bdevice -> string list Uq_engines.engine
  val eof_as_none :
    'Uq_engines.final_state -> 'a option Uq_engines.final_state
  val in_obj_channel :
    [< Uq_io.in_device ] -> float -> Netchannels.in_obj_channel
  val output_e :
    [< Uq_io.out_device ] ->
    Netsys_types.tbuffer -> int -> int -> int Uq_engines.engine
  val really_output_e :
    [< Uq_io.out_device ] ->
    Netsys_types.tbuffer -> int -> int -> unit Uq_engines.engine
  val output_string_e :
    [< Uq_io.out_device ] -> string -> unit Uq_engines.engine
  val output_bytes_e :
    [< Uq_io.out_device ] -> Bytes.t -> unit Uq_engines.engine
  val output_memory_e :
    [< Uq_io.out_device ] -> Netsys_mem.memory -> unit Uq_engines.engine
  val output_netbuffer_e :
    [< Uq_io.out_device ] -> Netbuffer.t -> unit Uq_engines.engine
  val write_eof_e : [< Uq_io.out_device ] -> bool Uq_engines.engine
  val copy_e :
    ?small_buffer:bool ->
    ?len:int ->
    ?len64:int64 ->
    [< Uq_io.in_device ] -> [< Uq_io.out_device ] -> int64 Uq_engines.engine
  val flush_e : [< Uq_io.out_device ] -> unit Uq_engines.engine
  val out_obj_channel :
    [< Uq_io.out_device ] -> float -> Netchannels.out_obj_channel
  val io_obj_channel :
    ?start_pos_in:int ->
    ?start_pos_out:int ->
    [< Uq_io.io_device ] -> float -> Netchannels.raw_io_channel
  val shutdown_e :
    ?linger:float ->
    [< `Async_in of Uq_engines.async_in_channel * Unixqueue.event_system
     | `Async_out of Uq_engines.async_out_channel * Unixqueue.event_system
     | `Buffer_in of Uq_io.in_buffer
     | `Buffer_out of Uq_io.out_buffer
     | `Count_in of (int -> unit) * Uq_io.in_device
     | `Count_out of (int -> unit) * Uq_io.out_device
     | `Multiplex of Uq_engines.multiplex_controller
     | `Polldescr of
         Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ] ->
    unit Uq_engines.engine
  val inactivate :
    [< `Async_in of Uq_engines.async_in_channel * Unixqueue.event_system
     | `Async_out of Uq_engines.async_out_channel * Unixqueue.event_system
     | `Buffer_in of Uq_io.in_buffer
     | `Buffer_out of Uq_io.out_buffer
     | `Count_in of (int -> unit) * Uq_io.in_device
     | `Count_out of (int -> unit) * Uq_io.out_device
     | `Multiplex of Uq_engines.multiplex_controller
     | `Polldescr of
         Netsys.fd_style * Unix.file_descr * Unixqueue.event_system ] ->
    unit
  val create_in_buffer :
    ?small_buffer:bool -> [< Uq_io.in_device ] -> Uq_io.in_buffer
  val in_buffer_length : Uq_io.in_buffer -> int
  val in_buffer_blit :
    Uq_io.in_buffer -> int -> Netsys_types.tbuffer -> int -> int -> unit
  val in_buffer_fill_e : Uq_io.in_buffer -> bool Uq_engines.engine
  val create_out_buffer :
    ?small_buffer:bool ->
    max:int option -> [< Uq_io.out_device ] -> Uq_io.out_buffer
  val filter_out_buffer :
    max:int option ->
    Netchannels.io_obj_channel -> [< Uq_io.out_device ] -> Uq_io.out_buffer
end
ocamlnet-4.1.2/doc/html-main/type_Netx509_pubkey.Encryption.html0000644000175000017500000004422312731530352023220 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey.Encryption sig
  val rsa : Netx509_pubkey.encrypt_alg
  val rsaes_oaep :
    hash_function:Netx509_pubkey.hash_function ->
    maskgen_function:Netx509_pubkey.maskgen_function ->
    psource_function:string -> Netx509_pubkey.encrypt_alg
  val catalog :
    (string * string list * Netx509_pubkey.encrypt_alg * Netx509_pubkey.oid)
    list
  val encrypt_alg_of_pubkey :
    Netx509_pubkey.pubkey -> Netx509_pubkey.encrypt_alg
  val alg_id_of_encrypt_alg :
    Netx509_pubkey.encrypt_alg -> Netx509_pubkey.alg_id
  val key_oid_of_encrypt_alg :
    Netx509_pubkey.encrypt_alg -> Netx509_pubkey.oid
end
ocamlnet-4.1.2/doc/html-main/Netmech_scram.html0000644000175000017500000013575712731530352020060 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram

Module Netmech_scram

module Netmech_scram: sig .. end
SCRAM mechanism for authentication (RFC 5802)


This implements SCRAM for SASL and GSSAPI.

This module needs the SHA-1 hash function. In order to use it, initialize crypto support, e.g. by including the nettls-gnutls packages and calling Nettls_gnutls.init.

As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of SCRAM should pass user names and passwords through Netsaslprep.saslprep.

type ptype = [ `GSSAPI | `SASL ] 
Profile types:
  • `GSSAPI: as defined in RFC 5802, the gs2-header is omitted
  • `SASL: as defined in RFC 5802

type profile = {
   ptype : ptype;
   hash_function : Netsys_digests.iana_hash_fn; (*
Which hash function
*)
   return_unknown_user : bool; (*
Whether servers exhibit the fact that the user is unknown
*)
   iteration_count_limit : int; (*
Largest supported iteration number
*)
}
Profile
type cb = Netsys_sasl_types.cb 
Using the same channel binding type as for SASL
type server_error = [ `Channel_binding_not_supported
| `Channel_bindings_dont_match
| `Extension of string
| `Extensions_not_supported
| `Invalid_encoding
| `Invalid_proof
| `Invalid_username_encoding
| `No_resources
| `Other_error
| `Server_does_support_channel_binding
| `Unknown_user
| `Unsupported_channel_binding_type ]
Error codes of this protocol
type client_session 
Session context for clients
type server_session 
Session context for servers

Client exceptions: The exceptions are returned by client_error_flag, but never raised.
exception Invalid_encoding of string * string
Returned by clients when something cannot be decoded. First string is an error message, the second string the raw message that cannot be decoded
exception Invalid_username_encoding of string * string
Returned by clients when the username does not match the requirements. Arguments as for Invalid_encoding.
exception Extensions_not_supported of string * string
Returned by clients when the server enables an unsupported extension. Arguments as for Invalid_encoding.
exception Protocol_error of string
Returned by clients when the server violates the protocol. The argument is a message.
exception Invalid_server_signature
Returned by clients when the signature sent by the server is invalid (i.e. the server does not know the client password)
exception Server_error of server_error
Returned by clients when the server sent an error code
val error_of_exn : exn -> string
Converts one of the above exceptions to a human-readable string
val profile : ?return_unknown_user:bool ->
?iteration_count_limit:int ->
ptype -> Netsys_digests.iana_hash_fn -> profile
Creates a profile
val string_of_server_error : server_error -> string
val server_error_of_string : string -> server_error
Conversion
val mechanism_name : profile -> string
The official name of the mechanism

Clients



Clients



The idea is to create a client session s first. The functions client_emit_flag and client_recv_flag indicate now whether the client needs to emit a new message, or whether it needs to receive a message, respectively. Emission is done by client_emit_message, reception by client_recv_message. If everything goes well, the protocol state advances, and finally client_finish_flag is true. This indicates that the client is authenticated and that the server knows the client's password. If an error occurs, an exception is raised (see above for possibilities), and client_error_flag signals true.
val create_client_session : ?nonce:string ->
profile -> string -> string -> client_session
create_client_session p username password: Creates a new client session for profile p so that the client authenticates as user username, and proves its identity with the given password.
val create_client_session2 : ?nonce:string ->
profile ->
string -> string -> string -> client_session
create_client_session p username authzname password: Like create_client_session, but also sets the authorization name (only processed for the SASL profile).
val client_configure_channel_binding : client_session ->
cb -> client_session
Sets whether to request channel binding.
val client_restart : client_session -> string -> client_session
Restart a client session (draft-ietf-httpauth-scram-auth-15). The string is the sr attribute.
val client_restart_stale : client_session -> string -> client_session
Restart a client session after the server indicated that the session is stale. The string arg is the new "sr" attribute (draft-ietf-httpauth-scram-auth-15).
val client_emit_flag : client_session -> bool
Whether client_emit_message can now be called
val client_recv_flag : client_session -> bool
Whether client_recv_message can now be called
val client_finish_flag : client_session -> bool
Whether the client is authenticated and the server verified
val client_semifinish_flag : client_session -> bool
Whether the client is authentication
val client_error_flag : client_session -> exn option
Whether an error occurred, and the protocol cannot advance anymore
val client_channel_binding : client_session -> cb
Returns the channel binding
val client_emit_message : client_session -> client_session * string
Emits the next message to be sent to the server
val client_emit_message_kv : client_session ->
client_session * string option * (string * string) list
Emits the next message to be sent to the server. The message is not encoded as a single string, but as (gs2_opt, kv) where gs2_opt is the optional GS2 header (the production gs2-header from the RFC), and kv contains the parameters as key/value pairs.
val client_recv_message : client_session -> string -> client_session
Receives the next message from the server
val client_protocol_key : client_session -> string option
The 128-bit protocol key for encrypting messages. This is available as soon as the second client message is emitted.
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_password : client_session -> string
The password
val client_export : client_session -> string
val client_import : string -> client_session
Exports a client session as string, and imports the string again.

The export format is just a marshalled Ocaml value.

val client_prop : client_session -> string -> string
Returns a property of the client (or Not_found):
  • "snonce": server nonce
  • "cnonce": client nonce
  • "salt": password salt
  • "i": iteration count
  • "client_key": this key is derived from the salted password but cannot be derived from the stored key. Its presence proves that the password was entered. It is ideal for encrypting data with a per-user key. The client key is known both to the client and to the server (after running the protocol).
  • "protocol_key": another key defined in RFC-5801 known by both sides. The protocol key is additionally also dependent on the nonces.
  • "error"


Servers



Servers



The idea is to create a server session s first. The functions server_emit_flag and server_recv_flag indicate now whether the server needs to emit a new message, or whether it needs to receive a message, respectively. Emission is done by server_emit_message, reception by server_recv_message. If everything goes well, the protocol state advances, and finally server_finish_flag is true. This indicates that the client could be authenticated.

If an error occurs, no exception is raised, and the protocol advances nevertheless, and finally the server sends an error token to the client. After this, server_error_flag returns true.

type credentials = [ `Salted_password of string * string * int
| `Stored_creds of string * string * string * int ]
Two forms of providing credentials:
  • `Salted_password(spw,salt,iteration_count): get the salted password with spw = salt_password h password salt iteration_count
  • `Stored(stkey, srvkey, salt, iteration_count): get the pair (stkey, srvkey) with stored_key h password salt iteration_count

val create_server_session : ?nonce:string ->
profile ->
(string -> credentials) -> server_session
create_server_session p auth: Creates a new server session with profile p and authenticator function auth.

The function is auth is called when the credentials of the client have been received to check whether the client can be authenticated. It is called as

      let credentials = auth username
      

where username is the user name. The function can now raise Not_found if the user is unknown, or it can return the credentials. Note that the cleartext password needs not to be known. The credentials contain a salt and an iteration count: salt is a random string, and iteration_count a security parameter that should be at least 4096. Whereas salt should be different for each user, the iteration_count can be chosen as a constant (e.g. 4096). Now salted_password can be computed from the cleartext password and these two extra parameters. See salt_password below.

val create_server_session2 : ?nonce:string ->
profile ->
(string -> string -> credentials) ->
server_session
Same as create_server_session, but the authentication callback gets two arguments:

      let credentials = auth username authzname
      

where authzname is the passed authorization name (or "" if na).

val create_salt : unit -> string
Creates a random string suited as salt
val salt_password : Netsys_digests.iana_hash_fn -> string -> string -> int -> string
let salted_password = salt_password h password salt iteration_count

Use this now as credentials `Salted_password(salted_password,salt,iteration_count).

As we do not implement SASLprep only passwords consisting of US-ASCII characters are accepted (Invalid_encoding otherwise).

val stored_key : Netsys_digests.iana_hash_fn -> string -> string -> int -> string * string

let stkey,srvkey = stored_key h password salt iteration_count

Use this now as credentials `Stored_creds(stkey,srvkey,salt,iteration_count).

val server_emit_flag : server_session -> bool
Whether server_emit_message can now be called
val server_recv_flag : server_session -> bool
Whether server_recv_message can now be called
val server_finish_flag : server_session -> bool
Whether the client is authenticated
val server_error_flag : server_session -> bool
Whether an error occurred, and the protocol cannot advance anymore
val server_emit_message : server_session -> server_session * string
Emits the next message to be sent to the client
val server_emit_message_kv : server_session ->
server_session * (string * string) list
Emits the next message to be sent to the client. The message is returned as a list of key/value pairs.
val server_recv_message : server_session -> string -> server_session
Receives the next message from the client
val server_protocol_key : server_session -> string option
The 128-bit protocol key for encrypting messages. This is available as soon as the second client message has been received.
val server_channel_binding : server_session -> cb
Returns the channel binding requirement. It is up to the application to enforce the binding. This information is available as soon as the second client message has been received
val server_user_name : server_session -> string option
The user name as transmitted from the client. This is returned here even before the authentication is completed!
val server_authz_name : server_session -> string option
The authorization name as transmitted from the client. This is returned here even before the authentication is completed!
val server_export : server_session -> string
val server_import : string -> server_session
val server_import_any : string ->
(string -> credentials) -> server_session
val server_import_any2 : string ->
(string -> string -> credentials) ->
server_session
Exports a server session as string, and imports the string again. server_import can only import established sessions. server_import_any can also import unfinished sessions, but one needs to pass the authentication function as for server_create_session. server_import_any2 uses the modified auth function as in server_create_session2.
val server_prop : server_session -> string -> string
Returns a property of the server (or Not_found) - see also client_prop above:
  • "snonce"
  • "cnonce"
  • "salt"
  • "i" (iteration_count)
  • "client_key"
  • "protocol_key"


Confidentiality


type specific_keys = {
   kc : string;
   ke : string;
   ki : string;
}
The specific keys to use
module AES_CTS: sig .. end
This module implements AES in Ciphertext Stealing mode (see RFC 3962)
module Cryptosystem: sig .. end
This is the cryptosystem as defined in RFC 3961, so far needed here.
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Credentials.html0000644000175000017500000004061412731530352020571 0ustar gerdgerd Ocamlnet 4 Reference Manual : Credentials sig  endocamlnet-4.1.2/doc/html-main/Rpc_client.USE_CLIENT.html0000644000175000017500000004653312731530352021054 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.USE_CLIENT

Module type Rpc_client.USE_CLIENT

module type USE_CLIENT = sig .. end
This module type is what the generated "clnt" module assumes about the client interface

type t 
The client type
val use : t -> Rpc_program.t -> unit
Announcement that this program will be used. The client may reject this by raising an exception.
val unbound_sync_call : t ->
Rpc_program.t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
unbound_sync_call client pgm proc arg: Invoke the remote procedure proc of the program pgm via client. The input arguments are arg. The result arguments are returned (or an error is raised)
val unbound_async_call : t ->
Rpc_program.t ->
string -> Netxdr.xdr_value -> ((unit -> Netxdr.xdr_value) -> unit) -> unit
unbound_ssync_call client pgm proc arg emit: Invoke the remote procedure proc of the program pgm via client. The input arguments are arg. When the result r is available, the client will call emit (fun () -> r) back. When an exception e is available, the client will call emit (fun () -> raise e) back.
val xdr_ctx : t -> Netxdr.ctx
Returns the recommended XDR context
ocamlnet-4.1.2/doc/html-main/type_Shell_uq.job_handler_engine_type.html0000644000175000017500000004312312731530352024742 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_uq.job_handler_engine_type object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method job : Shell_sys.job
  method job_instance : Shell_sys.job_instance
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : ('Uq_engines.engine -> bool) -> unit
  method state : 'Uq_engines.engine_state
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.output_engine.html0000644000175000017500000004154412731530352023320 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.output_engine (Unix.file_descr -> 'a) ->
Unix.file_descr -> float -> Unixqueue.event_system -> ['a] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Netx509.AD.html0000644000175000017500000004217612731530352020000 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.AD sig
  val ad_ca_issuers : Netx509.oid
  val ad_ocsp : Netx509.oid
  val ad_ca_repository : Netx509.oid
  val ad_time_stamping : Netx509.oid
  val access_descriptions :
    (Netx509.oid * Netx509.access_description_flag * string) list
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_portmapper_aux.html0000644000175000017500000036026312731530352022213 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_aux sig
  type mapping = {
    mutable prog : Netnumber.uint4;
    mutable vers : Netnumber.uint4;
    mutable prot : int;
    mutable port : int;
  }
  and pmaplist = {
    mutable map : Rpc_portmapper_aux.mapping;
    mutable next : Rpc_portmapper_aux.pmaplist option;
  }
  and pmaplist_p = Rpc_portmapper_aux.pmaplist option
  and call_args = {
    mutable call_prog : Netnumber.uint4;
    mutable call_vers : Netnumber.uint4;
    mutable call_proc : Netnumber.uint4;
    mutable call_args : string;
  }
  and call_result = { mutable call_port : int; mutable call_res : string; }
  and uaddr = string
  and rpcb = {
    mutable r_prog : Netnumber.uint4;
    mutable r_vers : Netnumber.uint4;
    mutable r_netid : string;
    mutable r_addr : Rpc_portmapper_aux.uaddr;
    mutable r_owner : string;
  }
  and rp__list = {
    mutable rpcb_map : Rpc_portmapper_aux.rpcb;
    mutable rpcb_next : Rpc_portmapper_aux.rp__list option;
  }
  and rpcblist_ptr = Rpc_portmapper_aux.rp__list option
  and rpcb_rmtcallargs = Rpc_portmapper_aux.call_args
  and rpcb_rmtcallres = {
    mutable call_addr : Rpc_portmapper_aux.uaddr;
    mutable call_res2 : string;
  }
  and rpcb_entry = {
    mutable r_maddr : string;
    mutable r_nc_netid : string;
    mutable r_nc_semantics : int;
    mutable r_nc_protofmly : string;
    mutable r_nc_proto : string;
  }
  and rpcb_entry_list = {
    mutable rpcb_entry_map : Rpc_portmapper_aux.rpcb_entry;
    mutable rpcb_entry_next : Rpc_portmapper_aux.rpcb_entry_list option;
  }
  and rpcb_entry_list_ptr = Rpc_portmapper_aux.rpcb_entry_list option
  and rpcbs_addrlist = {
    mutable al_prog : Netnumber.uint4;
    mutable al_vers : Netnumber.uint4;
    mutable al_success : int32;
    mutable al_failure : int32;
    mutable al_netid : string;
    mutable al_next : Rpc_portmapper_aux.rpcbs_addrlist option;
  }
  and rpcbs_rmtcalllist = {
    mutable cl_prog : Netnumber.uint4;
    mutable cl_vers : Netnumber.uint4;
    mutable cl_proc : Netnumber.uint4;
    mutable cl_success : int32;
    mutable cl_failure : int32;
    mutable cl_indirect : int32;
    mutable cl_netid : string;
    mutable cl_next : Rpc_portmapper_aux.rpcbs_rmtcalllist option;
  }
  and rpcbs_proc = Netnumber.int4 array
  and rpcbs_addrlist_ptr = Rpc_portmapper_aux.rpcbs_addrlist option
  and rpcbs_rmtcalllist_ptr = Rpc_portmapper_aux.rpcbs_rmtcalllist option
  and rpcb_stat = {
    mutable info : Rpc_portmapper_aux.rpcbs_proc;
    mutable setinfo : int32;
    mutable unsetinfo : int32;
    mutable addrinfo : Rpc_portmapper_aux.rpcbs_addrlist_ptr;
    mutable rmtinfo : Rpc_portmapper_aux.rpcbs_rmtcalllist_ptr;
  }
  and rpcb_stat_byvers = Rpc_portmapper_aux.rpcb_stat array
  and netbuf = { mutable maxlen : Netnumber.uint4; mutable buf : string; }
  and t_PMAP'V2'pmapproc_null'arg = unit
  and t_PMAP'V2'pmapproc_null'res = unit
  and t_PMAP'V2'pmapproc_set'arg = Rpc_portmapper_aux.mapping
  and t_PMAP'V2'pmapproc_set'res = bool
  and t_PMAP'V2'pmapproc_unset'arg = Rpc_portmapper_aux.mapping
  and t_PMAP'V2'pmapproc_unset'res = bool
  and t_PMAP'V2'pmapproc_getport'arg = Rpc_portmapper_aux.mapping
  and t_PMAP'V2'pmapproc_getport'res = int
  and t_PMAP'V2'pmapproc_dump'arg = unit
  and t_PMAP'V2'pmapproc_dump'res = Rpc_portmapper_aux.pmaplist_p
  and t_PMAP'V2'pmapproc_callit'arg = Rpc_portmapper_aux.call_args
  and t_PMAP'V2'pmapproc_callit'res = Rpc_portmapper_aux.call_result
  and t_PMAP'V3'rpcbproc_null'arg = unit
  and t_PMAP'V3'rpcbproc_null'res = unit
  and t_PMAP'V3'rpcbproc_set'arg = Rpc_portmapper_aux.rpcb
  and t_PMAP'V3'rpcbproc_set'res = bool
  and t_PMAP'V3'rpcbproc_unset'arg = Rpc_portmapper_aux.rpcb
  and t_PMAP'V3'rpcbproc_unset'res = bool
  and t_PMAP'V3'rpcbproc_getaddr'arg = Rpc_portmapper_aux.rpcb
  and t_PMAP'V3'rpcbproc_getaddr'res = Rpc_portmapper_aux.uaddr
  and t_PMAP'V3'rpcbproc_dump'arg = unit
  and t_PMAP'V3'rpcbproc_dump'res = Rpc_portmapper_aux.rpcblist_ptr
  and t_PMAP'V3'rpcbproc_callit'arg = Rpc_portmapper_aux.rpcb_rmtcallargs
  and t_PMAP'V3'rpcbproc_callit'res = Rpc_portmapper_aux.rpcb_rmtcallres
  and t_PMAP'V3'rpcbproc_gettime'arg = unit
  and t_PMAP'V3'rpcbproc_gettime'res = Netnumber.uint4
  and t_PMAP'V3'rpcbproc_uaddr2taddr'arg = Rpc_portmapper_aux.uaddr
  and t_PMAP'V3'rpcbproc_uaddr2taddr'res = Rpc_portmapper_aux.netbuf
  and t_PMAP'V3'rpcbproc_taddr2uaddr'arg = Rpc_portmapper_aux.netbuf
  and t_PMAP'V3'rpcbproc_taddr2uaddr'res = Rpc_portmapper_aux.uaddr
  and t_PMAP'V4'rpcbproc_null'arg = unit
  and t_PMAP'V4'rpcbproc_null'res = unit
  and t_PMAP'V4'rpcbproc_set'arg = Rpc_portmapper_aux.rpcb
  and t_PMAP'V4'rpcbproc_set'res = bool
  and t_PMAP'V4'rpcbproc_unset'arg = Rpc_portmapper_aux.rpcb
  and t_PMAP'V4'rpcbproc_unset'res = bool
  and t_PMAP'V4'rpcbproc_getaddr'arg = Rpc_portmapper_aux.rpcb
  and t_PMAP'V4'rpcbproc_getaddr'res = Rpc_portmapper_aux.uaddr
  and t_PMAP'V4'rpcbproc_dump'arg = unit
  and t_PMAP'V4'rpcbproc_dump'res = Rpc_portmapper_aux.rpcblist_ptr
  and t_PMAP'V4'rpcbproc_bcast'arg = Rpc_portmapper_aux.rpcb_rmtcallargs
  and t_PMAP'V4'rpcbproc_bcast'res = Rpc_portmapper_aux.rpcb_rmtcallres
  and t_PMAP'V4'rpcbproc_gettime'arg = unit
  and t_PMAP'V4'rpcbproc_gettime'res = Netnumber.uint4
  and t_PMAP'V4'rpcbproc_uaddr2taddr'arg = Rpc_portmapper_aux.uaddr
  and t_PMAP'V4'rpcbproc_uaddr2taddr'res = Rpc_portmapper_aux.netbuf
  and t_PMAP'V4'rpcbproc_taddr2uaddr'arg = Rpc_portmapper_aux.netbuf
  and t_PMAP'V4'rpcbproc_taddr2uaddr'res = Rpc_portmapper_aux.uaddr
  and t_PMAP'V4'rpcbproc_getversaddr'arg = Rpc_portmapper_aux.rpcb
  and t_PMAP'V4'rpcbproc_getversaddr'res = Rpc_portmapper_aux.uaddr
  and t_PMAP'V4'rpcbproc_indirect'arg = Rpc_portmapper_aux.rpcb_rmtcallargs
  and t_PMAP'V4'rpcbproc_indirect'res = Rpc_portmapper_aux.rpcb_rmtcallres
  and t_PMAP'V4'rpcbproc_getaddrlist'arg = Rpc_portmapper_aux.rpcb
  and t_PMAP'V4'rpcbproc_getaddrlist'res =
      Rpc_portmapper_aux.rpcb_entry_list_ptr
  and t_PMAP'V4'rpcbproc_getstat'arg = unit
  and t_PMAP'V4'rpcbproc_getstat'res = Rpc_portmapper_aux.rpcb_stat_byvers
  val pmap_port : Netnumber.uint4
  val ipproto_tcp : Netnumber.uint4
  val ipproto_udp : Netnumber.uint4
  val rpcb_port : Netnumber.uint4
  val rpcbstat_highproc : Netnumber.uint4
  val rpcbvers_stat : Netnumber.uint4
  val rpcbvers_4_stat : Netnumber.uint4
  val rpcbvers_3_stat : Netnumber.uint4
  val rpcbvers_2_stat : Netnumber.uint4
  val _to_mapping : Netxdr.xdr_value -> Rpc_portmapper_aux.mapping
  val _of_mapping : Rpc_portmapper_aux.mapping -> Netxdr.xdr_value
  val _xof_mapping :
    Netxdr.ctx -> Rpc_portmapper_aux.mapping -> Netxdr.xdr_value
  val _to_pmaplist : Netxdr.xdr_value -> Rpc_portmapper_aux.pmaplist
  val _of_pmaplist : Rpc_portmapper_aux.pmaplist -> Netxdr.xdr_value
  val _xof_pmaplist :
    Netxdr.ctx -> Rpc_portmapper_aux.pmaplist -> Netxdr.xdr_value
  val _to_pmaplist_p : Netxdr.xdr_value -> Rpc_portmapper_aux.pmaplist_p
  val _of_pmaplist_p : Rpc_portmapper_aux.pmaplist_p -> Netxdr.xdr_value
  val _xof_pmaplist_p :
    Netxdr.ctx -> Rpc_portmapper_aux.pmaplist_p -> Netxdr.xdr_value
  val _to_call_args : Netxdr.xdr_value -> Rpc_portmapper_aux.call_args
  val _of_call_args : Rpc_portmapper_aux.call_args -> Netxdr.xdr_value
  val _xof_call_args :
    Netxdr.ctx -> Rpc_portmapper_aux.call_args -> Netxdr.xdr_value
  val _to_call_result : Netxdr.xdr_value -> Rpc_portmapper_aux.call_result
  val _of_call_result : Rpc_portmapper_aux.call_result -> Netxdr.xdr_value
  val _xof_call_result :
    Netxdr.ctx -> Rpc_portmapper_aux.call_result -> Netxdr.xdr_value
  val _to_uaddr : Netxdr.xdr_value -> Rpc_portmapper_aux.uaddr
  val _of_uaddr : Rpc_portmapper_aux.uaddr -> Netxdr.xdr_value
  val _xof_uaddr : Netxdr.ctx -> Rpc_portmapper_aux.uaddr -> Netxdr.xdr_value
  val _to_rpcb : Netxdr.xdr_value -> Rpc_portmapper_aux.rpcb
  val _of_rpcb : Rpc_portmapper_aux.rpcb -> Netxdr.xdr_value
  val _xof_rpcb : Netxdr.ctx -> Rpc_portmapper_aux.rpcb -> Netxdr.xdr_value
  val _to_rp__list : Netxdr.xdr_value -> Rpc_portmapper_aux.rp__list
  val _of_rp__list : Rpc_portmapper_aux.rp__list -> Netxdr.xdr_value
  val _xof_rp__list :
    Netxdr.ctx -> Rpc_portmapper_aux.rp__list -> Netxdr.xdr_value
  val _to_rpcblist_ptr : Netxdr.xdr_value -> Rpc_portmapper_aux.rpcblist_ptr
  val _of_rpcblist_ptr : Rpc_portmapper_aux.rpcblist_ptr -> Netxdr.xdr_value
  val _xof_rpcblist_ptr :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcblist_ptr -> Netxdr.xdr_value
  val _to_rpcb_rmtcallargs :
    Netxdr.xdr_value -> Rpc_portmapper_aux.rpcb_rmtcallargs
  val _of_rpcb_rmtcallargs :
    Rpc_portmapper_aux.rpcb_rmtcallargs -> Netxdr.xdr_value
  val _xof_rpcb_rmtcallargs :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcb_rmtcallargs -> Netxdr.xdr_value
  val _to_rpcb_rmtcallres :
    Netxdr.xdr_value -> Rpc_portmapper_aux.rpcb_rmtcallres
  val _of_rpcb_rmtcallres :
    Rpc_portmapper_aux.rpcb_rmtcallres -> Netxdr.xdr_value
  val _xof_rpcb_rmtcallres :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcb_rmtcallres -> Netxdr.xdr_value
  val _to_rpcb_entry : Netxdr.xdr_value -> Rpc_portmapper_aux.rpcb_entry
  val _of_rpcb_entry : Rpc_portmapper_aux.rpcb_entry -> Netxdr.xdr_value
  val _xof_rpcb_entry :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcb_entry -> Netxdr.xdr_value
  val _to_rpcb_entry_list :
    Netxdr.xdr_value -> Rpc_portmapper_aux.rpcb_entry_list
  val _of_rpcb_entry_list :
    Rpc_portmapper_aux.rpcb_entry_list -> Netxdr.xdr_value
  val _xof_rpcb_entry_list :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcb_entry_list -> Netxdr.xdr_value
  val _to_rpcb_entry_list_ptr :
    Netxdr.xdr_value -> Rpc_portmapper_aux.rpcb_entry_list_ptr
  val _of_rpcb_entry_list_ptr :
    Rpc_portmapper_aux.rpcb_entry_list_ptr -> Netxdr.xdr_value
  val _xof_rpcb_entry_list_ptr :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcb_entry_list_ptr -> Netxdr.xdr_value
  val _to_rpcbs_addrlist :
    Netxdr.xdr_value -> Rpc_portmapper_aux.rpcbs_addrlist
  val _of_rpcbs_addrlist :
    Rpc_portmapper_aux.rpcbs_addrlist -> Netxdr.xdr_value
  val _xof_rpcbs_addrlist :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcbs_addrlist -> Netxdr.xdr_value
  val _to_rpcbs_rmtcalllist :
    Netxdr.xdr_value -> Rpc_portmapper_aux.rpcbs_rmtcalllist
  val _of_rpcbs_rmtcalllist :
    Rpc_portmapper_aux.rpcbs_rmtcalllist -> Netxdr.xdr_value
  val _xof_rpcbs_rmtcalllist :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcbs_rmtcalllist -> Netxdr.xdr_value
  val _to_rpcbs_proc : Netxdr.xdr_value -> Rpc_portmapper_aux.rpcbs_proc
  val _of_rpcbs_proc : Rpc_portmapper_aux.rpcbs_proc -> Netxdr.xdr_value
  val _xof_rpcbs_proc :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcbs_proc -> Netxdr.xdr_value
  val _to_rpcbs_addrlist_ptr :
    Netxdr.xdr_value -> Rpc_portmapper_aux.rpcbs_addrlist_ptr
  val _of_rpcbs_addrlist_ptr :
    Rpc_portmapper_aux.rpcbs_addrlist_ptr -> Netxdr.xdr_value
  val _xof_rpcbs_addrlist_ptr :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcbs_addrlist_ptr -> Netxdr.xdr_value
  val _to_rpcbs_rmtcalllist_ptr :
    Netxdr.xdr_value -> Rpc_portmapper_aux.rpcbs_rmtcalllist_ptr
  val _of_rpcbs_rmtcalllist_ptr :
    Rpc_portmapper_aux.rpcbs_rmtcalllist_ptr -> Netxdr.xdr_value
  val _xof_rpcbs_rmtcalllist_ptr :
    Netxdr.ctx ->
    Rpc_portmapper_aux.rpcbs_rmtcalllist_ptr -> Netxdr.xdr_value
  val _to_rpcb_stat : Netxdr.xdr_value -> Rpc_portmapper_aux.rpcb_stat
  val _of_rpcb_stat : Rpc_portmapper_aux.rpcb_stat -> Netxdr.xdr_value
  val _xof_rpcb_stat :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcb_stat -> Netxdr.xdr_value
  val _to_rpcb_stat_byvers :
    Netxdr.xdr_value -> Rpc_portmapper_aux.rpcb_stat_byvers
  val _of_rpcb_stat_byvers :
    Rpc_portmapper_aux.rpcb_stat_byvers -> Netxdr.xdr_value
  val _xof_rpcb_stat_byvers :
    Netxdr.ctx -> Rpc_portmapper_aux.rpcb_stat_byvers -> Netxdr.xdr_value
  val _to_netbuf : Netxdr.xdr_value -> Rpc_portmapper_aux.netbuf
  val _of_netbuf : Rpc_portmapper_aux.netbuf -> Netxdr.xdr_value
  val _xof_netbuf :
    Netxdr.ctx -> Rpc_portmapper_aux.netbuf -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_null'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg
  val _of_PMAP'V2'pmapproc_null'arg :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_null'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_null'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res
  val _of_PMAP'V2'pmapproc_null'res :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_null'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_set'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg
  val _of_PMAP'V2'pmapproc_set'arg :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_set'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_set'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res
  val _of_PMAP'V2'pmapproc_set'res :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_set'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_unset'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg
  val _of_PMAP'V2'pmapproc_unset'arg :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_unset'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_unset'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res
  val _of_PMAP'V2'pmapproc_unset'res :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_unset'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_getport'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg
  val _of_PMAP'V2'pmapproc_getport'arg :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_getport'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_getport'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res
  val _of_PMAP'V2'pmapproc_getport'res :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_getport'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_dump'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg
  val _of_PMAP'V2'pmapproc_dump'arg :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_dump'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_dump'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res
  val _of_PMAP'V2'pmapproc_dump'res :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_dump'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_callit'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg
  val _of_PMAP'V2'pmapproc_callit'arg :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_callit'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg -> Netxdr.xdr_value
  val _to_PMAP'V2'pmapproc_callit'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res
  val _of_PMAP'V2'pmapproc_callit'res :
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res -> Netxdr.xdr_value
  val _xof_PMAP'V2'pmapproc_callit'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_null'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg
  val _of_PMAP'V3'rpcbproc_null'arg :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_null'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_null'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res
  val _of_PMAP'V3'rpcbproc_null'res :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_null'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_set'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg
  val _of_PMAP'V3'rpcbproc_set'arg :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_set'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_set'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res
  val _of_PMAP'V3'rpcbproc_set'res :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_set'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_unset'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg
  val _of_PMAP'V3'rpcbproc_unset'arg :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_unset'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_unset'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res
  val _of_PMAP'V3'rpcbproc_unset'res :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_unset'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_getaddr'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg
  val _of_PMAP'V3'rpcbproc_getaddr'arg :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_getaddr'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_getaddr'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res
  val _of_PMAP'V3'rpcbproc_getaddr'res :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_getaddr'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_dump'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg
  val _of_PMAP'V3'rpcbproc_dump'arg :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_dump'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_dump'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res
  val _of_PMAP'V3'rpcbproc_dump'res :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_dump'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_callit'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg
  val _of_PMAP'V3'rpcbproc_callit'arg :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_callit'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_callit'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res
  val _of_PMAP'V3'rpcbproc_callit'res :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_callit'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_gettime'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg
  val _of_PMAP'V3'rpcbproc_gettime'arg :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_gettime'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_gettime'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res
  val _of_PMAP'V3'rpcbproc_gettime'res :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_gettime'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_uaddr2taddr'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg
  val _of_PMAP'V3'rpcbproc_uaddr2taddr'arg :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_uaddr2taddr'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_uaddr2taddr'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res
  val _of_PMAP'V3'rpcbproc_uaddr2taddr'res :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_uaddr2taddr'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_taddr2uaddr'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg
  val _of_PMAP'V3'rpcbproc_taddr2uaddr'arg :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_taddr2uaddr'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg -> Netxdr.xdr_value
  val _to_PMAP'V3'rpcbproc_taddr2uaddr'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res
  val _of_PMAP'V3'rpcbproc_taddr2uaddr'res :
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res -> Netxdr.xdr_value
  val _xof_PMAP'V3'rpcbproc_taddr2uaddr'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_null'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg
  val _of_PMAP'V4'rpcbproc_null'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_null'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_null'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res
  val _of_PMAP'V4'rpcbproc_null'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_null'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_set'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg
  val _of_PMAP'V4'rpcbproc_set'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_set'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_set'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res
  val _of_PMAP'V4'rpcbproc_set'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_set'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_unset'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg
  val _of_PMAP'V4'rpcbproc_unset'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_unset'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_unset'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res
  val _of_PMAP'V4'rpcbproc_unset'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_unset'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_getaddr'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg
  val _of_PMAP'V4'rpcbproc_getaddr'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_getaddr'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_getaddr'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res
  val _of_PMAP'V4'rpcbproc_getaddr'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_getaddr'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_dump'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg
  val _of_PMAP'V4'rpcbproc_dump'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_dump'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_dump'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res
  val _of_PMAP'V4'rpcbproc_dump'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_dump'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_bcast'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg
  val _of_PMAP'V4'rpcbproc_bcast'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_bcast'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_bcast'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res
  val _of_PMAP'V4'rpcbproc_bcast'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_bcast'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_gettime'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg
  val _of_PMAP'V4'rpcbproc_gettime'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_gettime'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_gettime'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res
  val _of_PMAP'V4'rpcbproc_gettime'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_gettime'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_uaddr2taddr'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg
  val _of_PMAP'V4'rpcbproc_uaddr2taddr'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_uaddr2taddr'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_uaddr2taddr'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res
  val _of_PMAP'V4'rpcbproc_uaddr2taddr'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_uaddr2taddr'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_taddr2uaddr'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg
  val _of_PMAP'V4'rpcbproc_taddr2uaddr'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_taddr2uaddr'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_taddr2uaddr'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res
  val _of_PMAP'V4'rpcbproc_taddr2uaddr'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_taddr2uaddr'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_getversaddr'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg
  val _of_PMAP'V4'rpcbproc_getversaddr'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_getversaddr'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_getversaddr'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res
  val _of_PMAP'V4'rpcbproc_getversaddr'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_getversaddr'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_indirect'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg
  val _of_PMAP'V4'rpcbproc_indirect'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_indirect'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_indirect'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res
  val _of_PMAP'V4'rpcbproc_indirect'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_indirect'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_getaddrlist'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg
  val _of_PMAP'V4'rpcbproc_getaddrlist'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_getaddrlist'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_getaddrlist'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res
  val _of_PMAP'V4'rpcbproc_getaddrlist'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_getaddrlist'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_getstat'arg :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg
  val _of_PMAP'V4'rpcbproc_getstat'arg :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_getstat'arg :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg -> Netxdr.xdr_value
  val _to_PMAP'V4'rpcbproc_getstat'res :
    Netxdr.xdr_value -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res
  val _of_PMAP'V4'rpcbproc_getstat'res :
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res -> Netxdr.xdr_value
  val _xof_PMAP'V4'rpcbproc_getstat'res :
    Netxdr.ctx ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res -> Netxdr.xdr_value
  val xdrt_mapping : Netxdr.xdr_type_term
  val xdrt_pmaplist : Netxdr.xdr_type_term
  val xdrt_pmaplist_p : Netxdr.xdr_type_term
  val xdrt_call_args : Netxdr.xdr_type_term
  val xdrt_call_result : Netxdr.xdr_type_term
  val xdrt_uaddr : Netxdr.xdr_type_term
  val xdrt_rpcb : Netxdr.xdr_type_term
  val xdrt_rp__list : Netxdr.xdr_type_term
  val xdrt_rpcblist_ptr : Netxdr.xdr_type_term
  val xdrt_rpcb_rmtcallargs : Netxdr.xdr_type_term
  val xdrt_rpcb_rmtcallres : Netxdr.xdr_type_term
  val xdrt_rpcb_entry : Netxdr.xdr_type_term
  val xdrt_rpcb_entry_list : Netxdr.xdr_type_term
  val xdrt_rpcb_entry_list_ptr : Netxdr.xdr_type_term
  val xdrt_rpcbs_addrlist : Netxdr.xdr_type_term
  val xdrt_rpcbs_rmtcalllist : Netxdr.xdr_type_term
  val xdrt_rpcbs_proc : Netxdr.xdr_type_term
  val xdrt_rpcbs_addrlist_ptr : Netxdr.xdr_type_term
  val xdrt_rpcbs_rmtcalllist_ptr : Netxdr.xdr_type_term
  val xdrt_rpcb_stat : Netxdr.xdr_type_term
  val xdrt_rpcb_stat_byvers : Netxdr.xdr_type_term
  val xdrt_netbuf : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_null'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_null'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_set'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_set'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_unset'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_unset'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_getport'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_getport'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_dump'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_dump'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_callit'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V2'pmapproc_callit'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_null'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_null'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_set'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_set'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_unset'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_unset'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_getaddr'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_getaddr'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_dump'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_dump'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_callit'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_callit'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_gettime'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_gettime'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_uaddr2taddr'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_uaddr2taddr'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_taddr2uaddr'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V3'rpcbproc_taddr2uaddr'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_null'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_null'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_set'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_set'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_unset'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_unset'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_getaddr'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_getaddr'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_dump'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_dump'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_bcast'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_bcast'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_gettime'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_gettime'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_uaddr2taddr'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_uaddr2taddr'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_taddr2uaddr'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_taddr2uaddr'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_getversaddr'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_getversaddr'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_indirect'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_indirect'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_getaddrlist'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_getaddrlist'res : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_getstat'arg : Netxdr.xdr_type_term
  val xdrt_PMAP'V4'rpcbproc_getstat'res : Netxdr.xdr_type_term
  val program_PMAP'V2 : Rpc_program.t
  val program_PMAP'V3 : Rpc_program.t
  val program_PMAP'V4 : Rpc_program.t
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_gs2_sasl.PROFILE.html0000644000175000017500000004607712731530352022624 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_gs2_sasl.PROFILE sig
  val mechanism_name : string
  val announce_channel_binding : bool
  val mechanism_oid : Netsys_gssapi.oid
  val client_additional_params : string list
  val server_additional_params : string list
  val client_map_user_name :
    params:(string * string) list -> string -> string * Netsys_gssapi.oid
  val server_map_user_name :
    params:(string * string) list -> string * Netsys_gssapi.oid -> string
  val client_get_target_name :
    params:(string * string) list -> string * Netsys_gssapi.oid
  val server_bind_target_name :
    params:(string * string) list -> (string * Netsys_gssapi.oid) option
  val server_check_target_name :
    params:(string * string) list -> string * Netsys_gssapi.oid -> bool
  val client_flags :
    params:(string * string) list -> (Netsys_gssapi.req_flag * bool) list
  val server_flags :
    params:(string * string) list -> Netsys_gssapi.req_flag list
  val client_credential : exn option
end
ocamlnet-4.1.2/doc/html-main/Netmime_header.html0000644000175000017500000004653312731530352020207 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime_header

Module Netmime_header

module Netmime_header: sig .. end
MIME: Access methods for frequent standard fields.

These functions will raise Not_found if the fields are not present.

Many HTTP-specific header functions can be found in Nethttp.Header.


val get_content_length : #Netmime.mime_header_ro -> int
Returns the Content-length field as integer
val get_content_type : #Netmime.mime_header_ro -> string * (string * Netmime_string.s_param) list
Returns the Content-type as parsed value. The left value of the pair is the main type, and the right value is the list of parameters. For example, for the field value "text/plain; charset=utf-8" this method returns ("text/plain", ["charset", p]) where p is an opaque value with Netmime_string.param_value p = "utf-8".
val get_content_disposition : #Netmime.mime_header_ro -> string * (string * Netmime_string.s_param) list
Returns the Content-disposition field as parsed value. The left value is the main disposition, and the right value is the list of parameters. For example, for the field value "attachment; filename=xy.dat" this method returns ("attachment", ["filename", p]) where p is an opaque value with Netmime_string.param_value p = "xy.dat".
val get_content_transfer_encoding : #Netmime.mime_header_ro -> string
Returns the Content-transfer-encoding as string
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.client_socket_connector.html0000644000175000017500000004065212731530352026675 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.client_socket_connector Uq_engines_compat.client_endpoint_connectorocamlnet-4.1.2/doc/html-main/type_Rpc_util.html0000644000175000017500000004513212731530352020115 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_util sig
  type verbosity = [ `Name_abbrev_args | `Name_full_args | `Name_only ]
  val string_of_request :
    Rpc_util.verbosity ->
    Rpc_program.t -> string -> Netxdr.xdr_value -> string
  val string_of_response :
    Rpc_util.verbosity ->
    Rpc_program.t -> string -> Netxdr.xdr_value -> string
  val string_of_value : Netxdr.xdr_type_term -> Netxdr.xdr_value -> string
  val hex_dump_m : Netsys_mem.memory -> int -> int -> string
  val hex_dump_b : Bytes.t -> int -> int -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_sasl_types.html0000644000175000017500000010306412731530352022066 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl_types sig
  type cb =
      [ `GSSAPI of string
      | `None
      | `SASL_none_but_advertise
      | `SASL_require of string * string ]
  type server_state =
      [ `Auth_error of string | `Emit | `OK | `Restart of string | `Wait ]
  type client_state =
      [ `Auth_error of string | `Emit | `OK | `Stale | `Wait ]
  module type SASL_MECHANISM =
    sig
      val mechanism_name : string
      val client_first : [ `No | `Optional | `Required ]
      val server_sends_final_data : bool
      val supports_authz : bool
      val available : unit -> bool
      type credentials
      val init_credentials :
        (string * string * (string * string) list) list ->
        Netsys_sasl_types.SASL_MECHANISM.credentials
      type server_session
      val server_state :
        Netsys_sasl_types.SASL_MECHANISM.server_session ->
        Netsys_sasl_types.server_state
      val create_server_session :
        lookup:(string ->
                string -> Netsys_sasl_types.SASL_MECHANISM.credentials option) ->
        params:(string * string * bool) list ->
        unit -> Netsys_sasl_types.SASL_MECHANISM.server_session
      val server_configure_channel_binding :
        Netsys_sasl_types.SASL_MECHANISM.server_session ->
        (string * string) list ->
        Netsys_sasl_types.SASL_MECHANISM.server_session
      val server_process_response :
        Netsys_sasl_types.SASL_MECHANISM.server_session ->
        string -> Netsys_sasl_types.SASL_MECHANISM.server_session
      val server_process_response_restart :
        Netsys_sasl_types.SASL_MECHANISM.server_session ->
        string ->
        bool -> Netsys_sasl_types.SASL_MECHANISM.server_session * bool
      val server_emit_challenge :
        Netsys_sasl_types.SASL_MECHANISM.server_session ->
        Netsys_sasl_types.SASL_MECHANISM.server_session * string
      val server_stash_session :
        Netsys_sasl_types.SASL_MECHANISM.server_session -> string
      val server_resume_session :
        lookup:(string ->
                string -> Netsys_sasl_types.SASL_MECHANISM.credentials option) ->
        string -> Netsys_sasl_types.SASL_MECHANISM.server_session
      val server_session_id :
        Netsys_sasl_types.SASL_MECHANISM.server_session -> string option
      val server_prop :
        Netsys_sasl_types.SASL_MECHANISM.server_session -> string -> string
      val server_user_name :
        Netsys_sasl_types.SASL_MECHANISM.server_session -> string
      val server_authz_name :
        Netsys_sasl_types.SASL_MECHANISM.server_session -> string
      val server_channel_binding :
        Netsys_sasl_types.SASL_MECHANISM.server_session ->
        Netsys_sasl_types.cb
      val server_gssapi_props :
        Netsys_sasl_types.SASL_MECHANISM.server_session ->
        Netsys_gssapi.server_props
      type client_session
      val client_state :
        Netsys_sasl_types.SASL_MECHANISM.client_session ->
        Netsys_sasl_types.client_state
      val create_client_session :
        user:string ->
        authz:string ->
        creds:Netsys_sasl_types.SASL_MECHANISM.credentials ->
        params:(string * string * bool) list ->
        unit -> Netsys_sasl_types.SASL_MECHANISM.client_session
      val client_configure_channel_binding :
        Netsys_sasl_types.SASL_MECHANISM.client_session ->
        Netsys_sasl_types.cb ->
        Netsys_sasl_types.SASL_MECHANISM.client_session
      val client_restart :
        Netsys_sasl_types.SASL_MECHANISM.client_session ->
        Netsys_sasl_types.SASL_MECHANISM.client_session
      val client_process_challenge :
        Netsys_sasl_types.SASL_MECHANISM.client_session ->
        string -> Netsys_sasl_types.SASL_MECHANISM.client_session
      val client_emit_response :
        Netsys_sasl_types.SASL_MECHANISM.client_session ->
        Netsys_sasl_types.SASL_MECHANISM.client_session * string
      val client_channel_binding :
        Netsys_sasl_types.SASL_MECHANISM.client_session ->
        Netsys_sasl_types.cb
      val client_user_name :
        Netsys_sasl_types.SASL_MECHANISM.client_session -> string
      val client_authz_name :
        Netsys_sasl_types.SASL_MECHANISM.client_session -> string
      val client_stash_session :
        Netsys_sasl_types.SASL_MECHANISM.client_session -> string
      val client_resume_session :
        string -> Netsys_sasl_types.SASL_MECHANISM.client_session
      val client_session_id :
        Netsys_sasl_types.SASL_MECHANISM.client_session -> string option
      val client_prop :
        Netsys_sasl_types.SASL_MECHANISM.client_session -> string -> string
      val client_gssapi_props :
        Netsys_sasl_types.SASL_MECHANISM.client_session ->
        Netsys_gssapi.client_props
    end
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.html0000644000175000017500000004554712731530352022140 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl sig
  module type PROFILE =
    sig
      val hash_function : Netsys_digests.iana_hash_fn
      val iteration_count_limit : int
      val announce_channel_binding : bool
    end
  module SHA1 : PROFILE
  module SHA1_PLUS : PROFILE
  module SHA256 : PROFILE
  module SHA256_PLUS : PROFILE
  module SCRAM : functor (P : PROFILE-> Netsys_sasl_types.SASL_MECHANISM
  module SCRAM_SHA1 : Netsys_sasl_types.SASL_MECHANISM
  module SCRAM_SHA1_PLUS : Netsys_sasl_types.SASL_MECHANISM
  module SCRAM_SHA256 : Netsys_sasl_types.SASL_MECHANISM
  module SCRAM_SHA256_PLUS : Netsys_sasl_types.SASL_MECHANISM
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.TLS_ENDPOINT.html0000644000175000017500000004122612731530352024406 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_ENDPOINT sig module TLS : TLS_PROVIDER val endpoint : TLS.endpoint endocamlnet-4.1.2/doc/html-main/type_Netfs.empty_fs.html0000644000175000017500000004065312731530352021243 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netfs.empty_fs string -> Netfs.stream_fsocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.TLS_ENDPOINT.TLS.html0000644000175000017500000013472212731530352024012 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_ENDPOINT.TLS

Module Netsys_crypto_types.TLS_ENDPOINT.TLS

module TLS: Netsys_crypto_types.TLS_PROVIDER 


Provides TLS functionality.

Users should not call functions of the provider directly, but use Netsys_tls, or another higher-level layer.

type config 
type credentials 
type endpoint 
module Exc: Netsys_crypto_types.TLS_EXCEPTIONS 
Access to exceptions
val error_message : string -> string
Returns the message for humans (display, log files etc.) when called with an error or warning symbol.
type dh_params = [ `Generate of int | `PKCS3_DER of string | `PKCS3_PEM_file of string ] 
Diffie-Hellman parameters:

  • `PKCS3_PEM_file name: points to a PEM-encoded PKCS3-file ("BEGIN DH PARAMETERS")
  • `PKCS3_DER data: the parameters are in a DER-encoded PKCS3 structure
  • `Generate bits: the parameters are generated with the passed number of bits

val create_config : ?algorithms:string ->
?dh_params:dh_params ->
?verify:(endpoint -> bool -> bool -> bool) ->
peer_auth:[ `None | `Optional | `Required ] ->
credentials:credentials ->
unit -> config
The configuration includes:

  • algorithms: a string specifying which cryptographic algorithms, protocols and protocol options are enabled, and in which priority they are used in the negotiation. (GnuTLS calls this "priority string".) The syntax is implementation-defined.
  • dh_params: parameters for Diffie-Hellman key exchange (used for DH-based authentication, but only on the server side)
  • peer_auth: controls whether the peer is requested to authenticate. This can be set to `None meaning not to request authentication and to ignore credentials, or to `Optional meaning not to request authentication but to check credentials if they are sent nevertheless, or to `Required meaning to request and check credentials. For "standard clients" you should set this to `Required, and for "standard servers" to `None or `Required.
  • credentials describes our own credentials, and the accepted credentials of the peer.
  • verify is a function called to verify the peer certificate in addition to the actions of peer_auth. The function must return true in order to be successful. The arguments of the function are the TLS endpoint, and two bools indicating the success of previous checks. The first bool says whether the certificate is trusted (based on peer_auth, trust and system_trust), and the second bool says whether the host name of the peer matches the name in the certificate. If not passed, verify defaults to (fun _ cert_ok name_ok -> cert_ok && name_ok), i.e. both bools must be true.
A configuration is read-only once created, and can be used for several endpoints. In particular, it does not cache TLS sessions.
type crt_list = [ `DER of string list | `PEM_file of string ] 
Certificates are given either as:

  • `PEM_file name: The certs are stored in this file, and are PEM-encoded.
  • `DER l: The certs are given directly in their DER-encoded form
See also Credentials for TLS.
type crl_list = [ `DER of string list | `PEM_file of string ] 
Certificate revocation lists are given either as:

  • `PEM_file name: The CRLs are stored in this file, and are PEM-encoded.
  • `DER l: The CRLs are given directly in their DER-encoded form
See also Credentials for TLS.
type private_key = [ `DSA of string
| `EC of string
| `PEM_file of string
| `PKCS8 of string
| `PKCS8_encrypted of string
| `RSA of string ]
Private keys are given either as:

  • `PEM_file name: The key is stored PEM-encoded in this file. The PEM header indicates the format.
  • `RSA data: The key is a PKCS1 RSA key
  • `DSA data: The key is a DSA key
  • `EC data: The key is for an elliptic curve
  • `PKCS8 data: The key is in a PKCS8 data structure
  • `PKCS8_encrypted data: The key is in a PKCS8 data structure, and is additionally encrypted.
See also Credentials for TLS.
val create_x509_credentials : ?system_trust:bool ->
?trust:crt_list list ->
?revoke:crl_list list ->
?keys:(crt_list *
private_key * string option)
list ->
unit -> credentials
Create X.509 credentials from individual objects:
  • system_trust: if set, the system certificates are trusted
  • trust specifies the CAs of peers to trust (default: empty)
  • revoke specifies CRLs for revocation of peer certificates (default: empty)
  • keys are our own certificates, as triples (cert_path, private_key, password) (default: empty)
A client should set trust to the list of CAs it can accept on the server side. It is not required to specify a key.

A server must specify a key (but can also specify several keys). If a server requests authentication from the client, it must also set trust.

The keys must include the certificate path cert_path, starting with the endpoint certificate, and followed by all middle certificates, but omitting the certificate of the CA. The private_key is the key of the endpoint. If it is password-encrypted, the password must be given.

val create_endpoint : role:[ `Client | `Server ] ->
recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
endpoint
Creates a new endpoint for this configuration.

peer_name is the expected common name or DNS name of the peer. peer_name has an option type as it is not always required to pass it. However, keep in mind that clients normally authenticate servers (peer_auth=`Required). In order to do so, they need to check whether the name in the server certificate equals the DNS name of the service they are connected to. This check is done by comparing peer_name with the name in the certificate.

peer_name is also used for the SNI extension.

Servers normally need not to set peer_name. You can also omit it when there is no name-driven authentication at all.

The endpoint will use the functions recv and send for I/O, which must be user-supplied. recv buf is expected to read data into the buffer, and to return the number of bytes, or 0 for EOF. send buf n is expected to send the n first bytes in buf.

Both functions may raise Unix_error. The codes Unix.EAGAIN and Unix.EINTR are specially interpreted.

val stash_endpoint : endpoint -> exn
The endpoint in "stashed" form, encapsulated as an exception. This form is intended for keeping the session alive in RAM, but without keeping references to the recv and send functions.

The endpoint passed in to stash_endpoint must no longer be used!

val restore_endpoint : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
exn -> endpoint
Reconnect the stashed endpoint with recv and send functions
val resume_client : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
string -> endpoint
Creates a new endpoint that will resume an old session. This implies the client role.

The session data is passed as string, which must have been retrieved with get_session_data.

type state = [ `Accepting
| `Data_r
| `Data_rs
| `Data_rw
| `Data_w
| `End
| `Handshake
| `Refusing
| `Start
| `Switching ]
The state of a session:

  • `Start: Before the session is started
  • `Handshake: The handshake is being done (and hello needs to be called again)
  • `Data_rw: The connection exists, and is read/write
  • `Data_r: The connection exists, and is read-only
  • `Data_w: The connection exists, and is write-only
  • `Data_rs: The connection exists, and data can be read. There was a switch request (initiated by us), and a response is awaited. No data can be sent in the moment.
  • `Switching: A rehandshake is being negotiated (and switch needs to be called again)
  • `Accepting: A rehandshake is being accepted (and accept_switch needs to be called again)
  • `Refusing: A rehandshake is being refused (and refuse_switch needs to be called again)
  • `End: After finishing the session

val get_state : endpoint ->
state
Return the recorded state
type raw_credentials = [ `Anonymous | `X509 of string ] 
The encoded credentials:
  • `X509 s: The X509 certificate in DER encoding
  • `Anonymous: no certificate or other key is available

val at_transport_eof : endpoint -> bool
Whether the underlying transport channel has seen the end of input. Use this after recv or mem_recv returned 0 to check whether only the TLS enf-of-input message has been read, or the underlying channel (usually the file descriptor) has indicated EOF.
val hello : endpoint -> unit
Performs the initial handshake (exchanges credentials and establishes a session).

hello doesn't verify the peer. Use verify for that.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val bye : endpoint -> Unix.shutdown_command -> unit
Performs the final handshake (exchanges close requests).

If SHUTDOWN_SEND is set, the close request is sent to the peer, and the TLS tunnel is considered as closed for writing. The application can receive further data until recv returns zero bytes meaning that the peer responded with another close request.

If SHUTDOWN_ALL is passed, it is additionally waited until the peer responds with a close request.

A simple SHUTDOWN_RECEIVE is unimplemented and ignored.

In no case the underlying transport is closed or shut down!

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val verify : endpoint -> unit
verify ep peer_name: Checks that:
  • there is a trust chain for the peer's certificate
  • that peer_name is the common name of the certificate subject, or an alternate name
These checks are not performed if peer_auth=`None is set in the configuration!

Additionally, the verify function in the endpoint configuration is called back, and a failure is indicated if this function returns false. This callback is useful to get the certificate of the peer and to perform further checks.

The verify function will raise Failure on failed checks (and Error for internal processing errors).

val get_config : endpoint ->
config
Get the current config (possibly modified because of a rehandshake)
val get_endpoint_creds : endpoint ->
raw_credentials
Get the credentials that was actually used in the handshake, in raw format.
val get_peer_creds : endpoint ->
raw_credentials
Get the credentials of the peer, in raw format. Raises Not_found if not applicable/no credentials present.
val get_peer_creds_list : endpoint ->
raw_credentials list
Get the chain that was actually used in the handshake.
val switch : endpoint ->
config -> unit
The server can use this to request a rehandshake and to use the new configuration for cert verification. This function sends the request, and expects a soon response from the client. The state enters `Data_rs meaning that we can still read data, and at some point recv will raise TLS_switch_response.

On the client side, the request will by returned as exception TLS_switch_request by recv. The client should respond with accept_switch if it accepts the handshake, or refuse_switch if not.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val accept_switch : endpoint ->
config -> unit
On the client: Enter another handshake round with new configuration data.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val refuse_switch : endpoint -> unit
On the client: Refuse a handshake

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val send : endpoint ->
Netsys_types.memory -> int -> int
send ep buffer n: Sends the first n bytes in the buffer over the endpoint, and returns the actual number of processed bytes.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val recv : endpoint -> Netsys_types.memory -> int
recv ep buffer n: Receives data, and puts them into the memory buffer, and returns the actual number of received bytes. If 0 is returned, a close request was received by the peer. For closing the tunnel properly this request should be responded by another close request with bye (unless this has already been done).

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

The exception TLS_switch_request can only occur on the client side, and should be responded by accept_switch or refuse_switch.

The exception TLS_switch_response can only occur on the server side.

val recv_will_not_block : endpoint -> bool
If there is still unprocessed data in the endpoint buffer, recv is guaranteed not to block or raise EAGAIN.
val get_session_id : endpoint -> string
The (non-printable) session ID
val get_session_data : endpoint -> string
Get the (non-printable) marshalled session data, for later resumption with resume_client
val get_cipher_suite_type : endpoint -> string
The type of the cipher suite:
  • "X509": X509 certificates are used
  • "OPENPGP": OpenPGP certificates are used
  • "ANON": anonymous credentials
  • "SRP": SRP credentials
  • "PSK": PSK credentials

val get_cipher_algo : endpoint -> string
Get the name of the cipher
val get_kx_algo : endpoint -> string
Get the name of the key exchange method
val get_mac_algo : endpoint -> string
Get the name of the message authentication code
val get_compression_algo : endpoint -> string
Get the name of the record-level compression method
val get_cert_type : endpoint -> string
Get the type of the certificate
val get_protocol : endpoint -> string
Get the name of the tunnel protocol
type server_name = [ `Domain of string ] 
val get_addressed_servers : endpoint ->
server_name list
To be used in servers: The client can address one of several virtual servers with the SNI extension, and this function returns which was requested. Raises Not_found if there is nothing appropriate. This information is only available after a handshake, and if the client submitted it.
val set_session_cache : store:(string -> string -> unit) ->
remove:(string -> unit) ->
retrieve:(string -> string) ->
endpoint -> unit
Sets the three callbacks for storing, removing and retrieving sessions (on the server side)
val implementation_name : string
String name of the implementation. By convention this is the full OCaml module path, e.g. "Nettls_gnutls.TLS"
val implementation : unit -> exn
Implementation-defined additional functionality
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.server_socket_acceptor.html0000644000175000017500000004065012731530352026531 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.server_socket_acceptor Uq_engines_compat.server_endpoint_acceptorocamlnet-4.1.2/doc/html-main/type_Nettls_gnutls.TLS.html0000644000175000017500000004065012731530352021642 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.TLS Netsys_crypto_types.TLS_PROVIDERocamlnet-4.1.2/doc/html-main/Uq_engines.serializer_t-c.html0000644000175000017500000004353712731530352022312 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.serializer_t

Class type Uq_engines.serializer_t

class type ['a] serializer_t = object .. end
A serializer queues up engines, and starts the next engine when the previous one finishes.

method serialized : (Unixqueue.event_system -> 'a engine) -> 'a engine
let se = serialized f: Waits until all the previous engines reach a final state, and then runs e = f esys.

se enters a final state when e does.

ocamlnet-4.1.2/doc/html-main/type_Netcgi_common.mime_arg.html0000644000175000017500000004117612731530352022700 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.mime_arg ?work_around_backslash_bug:bool ->
?name:string -> Netmime.mime_message -> Netcgi_common.rw_cgi_argument
ocamlnet-4.1.2/doc/html-main/Netmech_scram_http.Make_SCRAM.html0000644000175000017500000007244712731530352022714 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_http.Make_SCRAM

Functor Netmech_scram_http.Make_SCRAM

module Make_SCRAM: 
Parameters:
P : PROFILE

val mechanism_name : string
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
val restart_supported : bool
Whether the mechanism supports quick restarts (re-authentication)
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

The password is encoded in UTF-8. However, note that not all protocols are able to transmit all of UTF-8. If a non-transmittable character is found, the authentication will fail.

The password can have parameters:

  • "realm": the password is only applicable to this realm. The realm parameter should only occur once.
  • "domain-uri": the password is only applicable to this URI space. The URI must include the protocol scheme, the host name, and "/" as path. The port number is optional. Example: "http://localhost/". The domain-uri parameter can occur several times.

val client_match : params:(string * string * bool) list ->
Nethttp.Header.auth_challenge -> Nethttp.match_result
Checks whether this mechanism can accept the initial authentication challenge (i.e. the first challenge sent from the server to the client. The params are as for create_client_session. On success, returns `Accept(realm,id_opt). On failure, returns `Reject. This function usually does not raise exceptions.

If the mechanism does not support the notion of realms, a dummy realm should be returned.

The id_opt is the session ID (if supported). Session IDs can be used to bind reauthentications to the original session.

The challenge is from a www-authenticate or a proxy-authenticate header.

There is also the result `Reroute(realm, trans_id), meaning that the request would be acceptable if it came over the transport identified by trans_id. `Accept_reroute is the combination of accepting and rerouting, i.e. the auth protocol can start, but the second request should go over the other transport. Both `Reroute and `Accept_reroute are only allowed for initial challenges.

type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user. The credentials are creds.

user must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

Available parameters:

  • "realm"
  • "id" (if client_match returns a session ID)
  • "trans_id": the Nethttp_client.transport_layer_id of the current HTTP request
  • "conn_id": an identifier for the TCP connection
  • "https": is set to "true" if the current connection is TLS-secured
  • "target-host": the hostname from the HTTP request
  • "target-uri": the URL from the HTTP request

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : params:(string * string * bool) list ->
client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK. After the restart the session will be in state `Emit.

The params are the same as for create_client_session, but updated where needed.

val client_process_challenge : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
Nethttp.Header.auth_challenge -> client_session
client_process_challenge cs method uri header challenge:

Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.

method is the request method. uri is the request URI

val client_emit_response : client_session ->
string ->
string ->
#Nethttp.http_header_ro ->
client_session *
Nethttp.Header.auth_credentials * (string * string) list
let (creds,new_headers) = client_emit_response cs method uri header:

Emit a new response as a pair (creds,new_headers). The state must be `Emit. The creds either go into the authorization or proxy-authorization header. The new_headers are additional headers to modify.

val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_domain : client_session -> string list
After successful authentication, this function may return the URIs defining the authentication space.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. Commonly supported keys:
  • "realm"
  • "domain-uri"

val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Returns the GSSAPI props if available, or raise Not_found
ocamlnet-4.1.2/doc/html-main/Netcgi_dbi.html0000644000175000017500000004377612731530352017336 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_dbi

Module Netcgi_dbi

module Netcgi_dbi: sig .. end
Pools of connections for the ocamldbi generic database interface.

module type DBI_DRIVER = sig .. end
module type DBI_POOL = sig .. end
module DbiPool: 
functor (Dbi_driver : DBI_DRIVER) -> DBI_POOL with type connection = Dbi_driver.connection
module MyPool = DbiPool (Dbi_postgres)
ocamlnet-4.1.2/doc/html-main/Netsys_pollset.html0000644000175000017500000004237412731530352020327 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset

Module Netsys_pollset

module Netsys_pollset: sig .. end
Sets of file descriptors for polling

class type pollset = object .. end
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_modes.CIPHERS.html0000644000175000017500000004203312731530352022440 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes.CIPHERS

Module type Netsys_crypto_modes.CIPHERS

module type CIPHERS = sig .. end

val ciphers : Netsys_crypto_modes.Symmetric_cipher.sc list
ocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.http_reactor-c.html0000644000175000017500000004757712731530352023540 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_reactor

Class Nethttpd_reactor.http_reactor

class http_reactor : ?config_hooks:Nethttpd_kernel.http_protocol_hooks -> unit -> #http_reactor_config -> Unix.file_descr -> object .. end
The http_reactor allows one to pull the next request from a connected client, and to deliver the response to the protocol engine.

method next_request : unit -> http_reactive_request option
Tries to read the next request. When the header of the request is successfully read, the method returns the request object (see above). It is connected with the socket and can read the request body.

After receiving the request, one must either call accept_body when the request is acceptable and one want to reply afer evaluating the body, or invoke reject_body when the request can be denied without looking at the body. One must also call accept_body when there is not any body (it is a no-op then). The HTTP protocol explicitly forbids to perform the request when reject_body has been invoked ("The origin server MUST NOT perform the requested method if it returns a final status code").

The response must be written to the Netcgi environment. Depending on config_reactor_synch the response is immediately transmitted to the client or at some specified time in the future (untransmitted data is buffered in this case).

While transmitting output, the reactor is able to read the next request in the background when the limits for the pipeline size allows that.

While receiving input, the reactor is able to write untransmitted response data in the background.

It is an error to call next_request again before the previous request is completely processed (you can ensure this by calling finish). In this case the HTTP connection is immediately shut down.

The method next_request returns None when all requests of the connection are processed.

method close : unit -> unit
Closes the file descriptor with a reliable method. This method must be called after next_request returned None. It can also be called at any time to shut down the connection prematurely (this means a lingering close, and may cost some time).
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.http_service.html0000644000175000017500000004211412731530352024045 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.http_service object
  method def_term : 'a
  method name : string
  method print : Format.formatter -> unit
  method process_header :
    Nethttpd_types.extended_environment ->
    Nethttpd_types.http_service_reaction
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_common.cgi_argument.html0000644000175000017500000004313012731530352023554 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.cgi_argument object
  method charset : string
  method content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method filename : string option
  method finalize : unit -> unit
  method name : string
  method open_value_rd : unit -> Netchannels.in_obj_channel
  method representation : Netcgi_common.representation
  method store : Netcgi_common.store
  method value : string
end
ocamlnet-4.1.2/doc/html-main/Netx509.x509_dn_from_string-c.html0000644000175000017500000004241612731530352022467 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_dn_from_string

Class Netx509.x509_dn_from_string

class x509_dn_from_string : string -> directory_name
Returns the DN object for an RFC 4514-encoded string

ocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.http_request_header_notification.html0000644000175000017500000004353712731530352030266 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_request_header_notification object
  method environment : Nethttpd_engine.extended_async_environment
  method req_state : Nethttpd_engine.engine_req_state
  method schedule_accept_body :
    on_request:(Nethttpd_engine.http_request_notification -> unit) ->
    ?on_error:(unit -> unit) -> unit -> unit
  method schedule_finish : unit -> unit
  method schedule_reject_body :
    on_request:(Nethttpd_engine.http_request_notification -> unit) ->
    ?on_error:(unit -> unit) -> unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netcamlbox.Debug.html0000644000175000017500000004100312731530352021446 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcamlbox.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Ocamlnet4.html0000644000175000017500000006263112731530352017124 0ustar gerdgerd Ocamlnet 4 Reference Manual : Ocamlnet4

Ocamlnet4


What's new in OCamlnet 4

Security

The main focus of this major version is the addition of strong authentication and security. In particular, TLS is now available for all protocols. In order to achieve this, and to provide better service functions, we switched from OpenSSL to GnuTLS. However, as it is uncertain which TLS library will be the best in the future, the core TLS interface has been factored out, and is now defined as module type. So, if e.g. LibreSSL will make it in the future, it is relatively easy to switch. The TLS provider is now a first-class module, and plugging in an alternate provider just means to pass a different provider module to the protocol interpreter. Read more about TLS: Tls.

There are also a lot of utility functions for TLS. In particular, there is a parser for X.509 certificates, and there are helpers for dealing with distinguished names. Netx509, Netdn.

From GnuTLS (and in particular from its crypto toolkit Nettle) we also get access to basic cryptographic functions, including hash functions and symmetric ciphers. The latter are sometimes even accelerated on modern hardware (in particular AES). Netsys_digests, Netsys_ciphers.

While TLS is good for establishing private channels, TLS client authentication is not that popular. Many protocols prefer SASL, which is now also defined as pluggable module: Netsys_sasl_types, Netsys_sasl. There are a number of mechanisms: PLAIN, CRAM-MD5, DIGEST-MD5, SCRAM-SHA1, GSSAPI, GS2-KRB5,

Many organizations use Kerberos as network login method. Access to Kerberos authentication is possible via the GSSAPI, a system interface for authentication and security modules. The GSSAPI is available directly or via SASL. Support for GSSAPI has been added to all protocols for which it is defined (HTTP clients, FTP clients, RPC clients and servers, and other protocols via SASL). Read more: Gssapi.

Completed IPv6 support

IPv6 functionality is now automatically enabled for a number of popular OS when it is obvious that IPv6 is configured (i.e. that there is an network interface with a global IPv6 address). Read more: Ipv6

For most protocols IPv6 was already available in OCamlnet-3. There was one exception, though: The RPC Portmapper protocol isn't capable of IPv6. There is the newer RPCBIND protocol, though, and we support it now.

Reorganization

There are a couple of renamings. The most important ones:

This means almost all OCamlnet modules use now the prefixes Net, Uq_, Rpc_ or Shell_ (the only exceptions are Unixqueue and Equeue).

The Unicode tables have been factored out of netstring and are now provided as netunidata library. Note that this means that the table are inaccessible unless netunidata is linked in. Get more information here: Netunidata.

A few other notable updates:

  • The pop and smtp libraries have been added to netclient
  • equeue-ssl does not exist anymore. See Tls about how to get TLS support nevertheless.
  • netcgi1 has been deleted. Use netcgi2 instead.
  • rpc-auth-dh has been deleted. Use the GSSAPI-based authentication for RPC instead.

Bytes (in 4.1)

Since OCamlnet-4.1, the new Bytes module is fully supported. All interfaces have been checked whether the typing needed to be changed from string to bytes. Also, OCamlnet-4.1 is now built with the -safe-string option if the OCaml version is new enough.

The are two new concepts making life easier in the presence of two string types (actually three types if you also count bigarrays of characters):

  • A tagged string or tstring wraps any of the three types into a single variant type:
     type tstring = [`String of string | `Bytes of bytes | `Memory of memory] 
    (note that memory is a bigarray of characters). There is a new support module, Netstring_tstring. We use tagged strings only when the string is an input to a function and not mutated.
  • A tagged buffer or tbuffer wraps a bytes or memory buffer into a variant type:
     type tbuffer = [`Bytes of bytes | `Memory of memory] 
    As we had a similar type already in previous OCamlnet versions, tbuffer got also a third variant for backward compatibility:
     type tbuffer = [`Bytes of bytes | `Memory of memory | `String of bytes] 
    This third variant looks a little bit strange, but is certainly useful for helping users to transition to bytes buffers. This variant will be removed in a later version of OCamlnet again.

More authentication (in 4.1)

The IETF recently did some work on authentication, and some results could already be incorporated into OCamlnet. The update of the HTTP Digest authentication method to the SHA-256 hash function (instead of MD5) went in and is automatically available for HTTP clients. Note that there is no update on the same-named SASL mechanism, which is now considered as "historic" in favor of the SCRAM family of mechanisms.

Regarding SCRAM for HTTP, there is an RFC draft, and the RFC is expected soon. I've added an experimental (but somewhat incomplete) implementation according to the draft (Netmech_scram_http).

In order to support public key mechanisms in later OCamlnet versions, there is now pluggable public key cryptography. For users the module Netx509_pubkey_crypto makes this feature available. However, at present there is no mechanism using this already.

Another new feature is the Netldap client, wrapping the most common LDAP client operations. This is most useful for servers wanting to authenticate against an LDAP server. Of course, it is also useful for other purposes, as LDAP can be used for storing any kind of information.

Not yet

A few things would have been good to have in OCamlnet-4, but they were not available in time:

  • HTTP authentication on the server side
  • Advanced HTTP authentication frameworks such as OAUTH
  • Support for reading passwords from files
  • Non-blocking name lookups

ocamlnet-4.1.2/doc/html-main/type_Netplex_encap.TYPE.html0000644000175000017500000004067312731530352021706 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_encap.TYPE sig type t endocamlnet-4.1.2/doc/html-main/Netplex_workload.html0000644000175000017500000005031512731530352020613 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_workload

Module Netplex_workload

module Netplex_workload: sig .. end
Workload management

Workload managers control when additional containers are started or idle containers are stopped. See Workload Management for additional documentation how they are configured.


val create_constant_workload_manager : ?restart:bool ->
?greedy_accepts:bool ->
?max_jobs_per_thread:int -> int -> Netplex_types.workload_manager
A constant number of threads is created (the int argument).

restart: If threads crash, new threads are created until the specified number is again reached. This is on by default.

greedy_accepts: whether greedy accepts are allowed (default: false)

max_jobs_per_thread: if passed, limits the number of jobs (connections) that can be simultaneously processed by a thread/process. By default there is no limit.

val constant_workload_manager_factory : Netplex_types.workload_manager_factory
Reads a workload_manager section like

 workload_manager {
      type = "constant";
      threads = <n>;
      max_jobs_per_thread = <n>;
      greedy_accepts = <bool>;
    }
 

class type dynamic_workload_config = object .. end
val create_dynamic_workload_manager : dynamic_workload_config -> Netplex_types.workload_manager
val dynamic_workload_manager_factory : Netplex_types.workload_manager_factory
Reads a workload_manager section like

 workload_manager {
      type = "dynamic";
      max_jobs_per_thread = <n>;
      min_free_jobs_capacity = <n>;
      max_free_jobs_capacity = <n>;
      max_threads = <n>;
      greedy_accepts = <bool>;
    }
 

val workload_manager_factories : Netplex_types.workload_manager_factory list
All built-in workload manager factories
ocamlnet-4.1.2/doc/html-main/Netplex_types.socket_service-c.html0000644000175000017500000005062212731530352023365 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.socket_service

Class type Netplex_types.socket_service

class type socket_service = object .. end

method name : string
The name of the socket_service is used to identify the service in the whole netplex process cluster. Names are hierarchical; name components are separated by dots (e.g. "company.product.service"). The prefix "netplex." is reserved for use by Netplex. The name "netplex.controller" refers to the service provided by the controller.
method sockets : (string * Unix.file_descr array) list
A socket_service consists of a list of supported protocols which are identified by a name. Every protocol is available on a list of sockets (which may be bound to different addresses). The sockets corresponding to `Container addresses are missing here.
method internal_sockets : (string * polyserver_box) list
The internal sockets for internal services: pairs of (protocol,server)
method socket_service_config : socket_service_config
The configuration
method processor : processor
A user-supplied object to process incoming connections
method shutdown : unit -> unit
Shuts down the master sockets
method create_container : parallelization_type ->
socket_service -> container
Internal method. Called by the controller to create a new container. The container must match the parallelization type of the controller. This call is already done in the process/thread provided for the container.
method on_add : controller -> unit
Get some runtime configuration aspects from this controller. This is called when the socket service is added to the controller
method startup_directory : string
The current directory at Netplex startup time (same view as controller)
ocamlnet-4.1.2/doc/html-main/Nethttpd_kernel.http_response_impl-c.html0000644000175000017500000004251612731530352024565 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_response_impl

Class Nethttpd_kernel.http_response_impl

class http_response_impl : ?close:bool -> ?suppress_body:bool -> int64 -> Nethttp.protocol -> announcement -> http_response
Exported for debugging and testing only

ocamlnet-4.1.2/doc/html-main/type_Netftp_fs.ftp_stream_fs.html0000644000175000017500000005337112731530352023123 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_fs.ftp_stream_fs object
  method cancel : unit -> unit
  method close : unit -> unit
  method copy : Netfs.copy_flag list -> string -> string -> unit
  method ftp_client : Netftp_client.ftp_client
  method last_ftp_state : Netftp_client.ftp_state
  method mkdir : Netfs.mkdir_flag list -> string -> unit
  method nominal_dot_dot : bool
  method path_encoding : Netconversion.encoding option
  method path_exclusions : (int * int) list
  method read : Netfs.read_flag list -> string -> Netchannels.in_obj_channel
  method read_file : Netfs.read_file_flag list -> string -> Netfs.local_file
  method readdir : Netfs.readdir_flag list -> string -> string list
  method readlink : Netfs.readlink_flag list -> string -> string
  method remove : Netfs.remove_flag list -> string -> unit
  method rename : Netfs.rename_flag list -> string -> string -> unit
  method rmdir : Netfs.rmdir_flag list -> string -> unit
  method size : Netfs.size_flag list -> string -> int64
  method symlink : Netfs.symlink_flag list -> string -> string -> unit
  method test : Netfs.test_flag list -> string -> Netfs.test_type -> bool
  method test_list :
    Netfs.test_flag list -> string -> Netfs.test_type list -> bool list
  method translate : string -> string
  method write :
    Netfs.write_flag list -> string -> Netchannels.out_obj_channel
  method write_file :
    Netfs.write_file_flag list -> string -> Netfs.local_file -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.html0000644000175000017500000016450512731530352021360 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types sig
  exception Standard_response of Nethttp.http_status *
              Nethttp.http_header option * string option
  type output_state = [ `End | `Sending | `Start ]
  val string_of_output_state : Nethttpd_types.output_state -> string
  class type virtual v_extended_environment =
    object
      method cgi_auth_type : string
      method cgi_gateway_interface : string
      method cgi_https : bool
      method cgi_path_info : string
      method cgi_path_translated : string
      method cgi_properties : (string * string) list
      method cgi_property : ?default:string -> string -> string
      method cgi_query_string : string
      method cgi_remote_addr : string
      method cgi_remote_host : string
      method cgi_remote_ident : string
      method cgi_remote_user : string
      method cgi_request_method : string
      method cgi_request_uri : string
      method cgi_script_name : string
      method cgi_server_name : string
      method cgi_server_port : int option
      method cgi_server_protocol : string
      method cgi_server_software : string
      method config : Netcgi.config
      method cookie : string -> Netcgi.Cookie.t
      method cookies : Netcgi.Cookie.t list
      method input_body_size : int64
      method input_channel : Netchannels.in_obj_channel
      method input_content_length : int
      method input_content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method input_content_type_string : string
      method input_header : Netmime.mime_header
      method input_header_field : ?default:string -> string -> string
      method input_header_fields : (string * string) list
      method log_error : string -> unit
      method log_props : (string * string) list -> unit
      method multiple_input_header_field : string -> string list
      method multiple_output_header_field : string -> string list
      method out_channel : Netchannels.out_obj_channel
      method output_ch : Netchannels.out_obj_channel
      method output_header : Netmime.mime_header
      method output_header_field : ?default:string -> string -> string
      method output_header_fields : (string * string) list
      method virtual output_state :
        Nethttpd_types.output_state Pervasives.ref
      method protocol : Nethttp.protocol
      method virtual remote_socket_addr : Unix.sockaddr
      method request_body_rejected : bool
      method send_file : Unix.file_descr -> int64 -> unit
      method send_output_header : unit -> unit
      method virtual server_socket_addr : Unix.sockaddr
      method set_multiple_output_header_field : string -> string list -> unit
      method set_output_header_field : string -> string -> unit
      method set_output_header_fields : (string * string) list -> unit
      method set_status : Nethttp.http_status -> unit
      method tls_session_props : Nettls_support.tls_session_props option
      method user_agent : string
    end
  class type extended_environment =
    object
      method cgi_auth_type : string
      method cgi_gateway_interface : string
      method cgi_https : bool
      method cgi_path_info : string
      method cgi_path_translated : string
      method cgi_properties : (string * string) list
      method cgi_property : ?default:string -> string -> string
      method cgi_query_string : string
      method cgi_remote_addr : string
      method cgi_remote_host : string
      method cgi_remote_ident : string
      method cgi_remote_user : string
      method cgi_request_method : string
      method cgi_request_uri : string
      method cgi_script_name : string
      method cgi_server_name : string
      method cgi_server_port : int option
      method cgi_server_protocol : string
      method cgi_server_software : string
      method config : Netcgi.config
      method cookie : string -> Netcgi.Cookie.t
      method cookies : Netcgi.Cookie.t list
      method input_body_size : int64
      method input_channel : Netchannels.in_obj_channel
      method input_content_length : int
      method input_content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method input_content_type_string : string
      method input_header : Netmime.mime_header
      method input_header_field : ?default:string -> string -> string
      method input_header_fields : (string * string) list
      method log_error : string -> unit
      method log_props : (string * string) list -> unit
      method multiple_input_header_field : string -> string list
      method multiple_output_header_field : string -> string list
      method out_channel : Netchannels.out_obj_channel
      method output_ch : Netchannels.out_obj_channel
      method output_header : Netmime.mime_header
      method output_header_field : ?default:string -> string -> string
      method output_header_fields : (string * string) list
      method output_state : Nethttpd_types.output_state Pervasives.ref
      method protocol : Nethttp.protocol
      method remote_socket_addr : Unix.sockaddr
      method request_body_rejected : bool
      method send_file : Unix.file_descr -> int64 -> unit
      method send_output_header : unit -> unit
      method server_socket_addr : Unix.sockaddr
      method set_multiple_output_header_field : string -> string list -> unit
      method set_output_header_field : string -> string -> unit
      method set_output_header_fields : (string * string) list -> unit
      method set_status : Nethttp.http_status -> unit
      method tls_session_props : Nettls_support.tls_session_props option
      method user_agent : string
    end
  class virtual empty_environment :
    object
      val mutable config : Netcgi.config
      val mutable in_channel : Netchannels.in_obj_channel
      val mutable in_header : Nethttp.http_header
      val mutable out_channel : Netchannels.out_obj_channel
      val mutable out_header : Nethttp.http_header
      val mutable properties : (string * string) list
      val mutable protocol : Nethttp.protocol
      val mutable tls_session_props : Nettls_support.tls_session_props option
      method cgi_auth_type : string
      method cgi_gateway_interface : string
      method cgi_https : bool
      method cgi_path_info : string
      method cgi_path_translated : string
      method cgi_properties : (string * string) list
      method cgi_property : ?default:string -> string -> string
      method cgi_query_string : string
      method cgi_remote_addr : string
      method cgi_remote_host : string
      method cgi_remote_ident : string
      method cgi_remote_user : string
      method cgi_request_method : string
      method cgi_request_uri : string
      method cgi_script_name : string
      method cgi_server_name : string
      method cgi_server_port : int option
      method cgi_server_protocol : string
      method cgi_server_software : string
      method config : Netcgi.config
      method cookie : string -> Netcgi.Cookie.t
      method cookies : Netcgi.Cookie.t list
      method input_body_size : int64
      method input_channel : Netchannels.in_obj_channel
      method input_content_length : int
      method input_content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method input_content_type_string : string
      method input_header : Netmime.mime_header
      method input_header_field : ?default:string -> string -> string
      method input_header_fields : (string * string) list
      method log_error : string -> unit
      method log_props : (string * string) list -> unit
      method multiple_input_header_field : string -> string list
      method multiple_output_header_field : string -> string list
      method out_channel : Netchannels.out_obj_channel
      method output_ch : Netchannels.out_obj_channel
      method output_header : Netmime.mime_header
      method output_header_field : ?default:string -> string -> string
      method output_header_fields : (string * string) list
      method virtual output_state : output_state ref
      method protocol : Nethttp.protocol
      method virtual remote_socket_addr : Unix.sockaddr
      method request_body_rejected : bool
      method send_file : Unix.file_descr -> int64 -> unit
      method send_output_header : unit -> unit
      method virtual server_socket_addr : Unix.sockaddr
      method set_multiple_output_header_field : string -> string list -> unit
      method set_output_header_field : string -> string -> unit
      method set_output_header_fields : (string * string) list -> unit
      method set_status : Nethttp.http_status -> unit
      method tls_session_props : Nettls_support.tls_session_props option
      method user_agent : string
    end
  class redirected_environment :
    ?in_header:Nethttp.http_header ->
    ?properties:(string * string) list ->
    ?in_channel:Netchannels.in_obj_channel ->
    Nethttpd_types.extended_environment -> extended_environment
  val output_static_response :
    #Nethttpd_types.extended_environment ->
    Nethttp.http_status -> Nethttp.http_header option -> string -> unit
  val output_file_response :
    #Nethttpd_types.extended_environment ->
    Nethttp.http_status ->
    Nethttp.http_header option -> string -> int64 -> int64 -> unit
  class type request_info =
    object
      method cgi_properties : (string * string) list
      method input_body_size : int64
      method input_header : Nethttp.http_header
      method remote_socket_addr : Unix.sockaddr
      method request_method : string
      method request_uri : string
      method server_socket_addr : Unix.sockaddr
      method tls_session_props : Nettls_support.tls_session_props option
    end
  class type full_info =
    object
      method cgi_properties : (string * string) list
      method input_body_size : int64
      method input_header : Nethttp.http_header
      method output_body_size : int64
      method output_header : Nethttp.http_header
      method remote_socket_addr : Unix.sockaddr
      method request_body_rejected : bool
      method request_method : string
      method request_uri : string
      method response_status_code : int
      method server_socket_addr : Unix.sockaddr
      method tls_session_props : Nettls_support.tls_session_props option
    end
  class create_full_info :
    response_status_code:int ->
    request_body_rejected:bool ->
    output_header:Nethttp.http_header ->
    output_body_size:int64 -> Nethttpd_types.request_info -> full_info
  class type error_response_params =
    object
      method cgi_properties : (string * string) list
      method error_message : string
      method input_body_size : int64
      method input_header : Nethttp.http_header
      method remote_socket_addr : Unix.sockaddr
      method request_method : string
      method request_uri : string
      method response_status_code : int
      method server_socket_addr : Unix.sockaddr
      method tls_session_props : Nettls_support.tls_session_props option
    end
  class type min_config =
    object
      method config_error_response :
        Nethttpd_types.error_response_params -> string
      method config_log_error : Nethttpd_types.request_info -> string -> unit
    end
  val output_std_response :
    #Nethttpd_types.min_config ->
    #Nethttpd_types.extended_environment ->
    Nethttp.http_status ->
    Nethttp.http_header option -> string option -> unit
  exception Redirect_request of string * Nethttp.http_header
  exception Redirect_response of string * Nethttp.http_header
  class type http_service_generator =
    object
      method generate_response : Nethttpd_types.extended_environment -> unit
    end
  class type http_service_receiver =
    object
      method process_body :
        Nethttpd_types.extended_environment ->
        Nethttpd_types.http_service_generator
    end
  type http_service_reaction =
      [ `Accept_body of Nethttpd_types.http_service_receiver
      | `File of
          Nethttp.http_status * Nethttp.http_header option * string * 
          int64 * int64
      | `Reject_body of Nethttpd_types.http_service_generator
      | `Static of Nethttp.http_status * Nethttp.http_header option * string
      | `Std_response of
          Nethttp.http_status * Nethttp.http_header option * string option ]
  class type ['a] http_service =
    object
      method def_term : 'a
      method name : string
      method print : Format.formatter -> unit
      method process_header :
        Nethttpd_types.extended_environment ->
        Nethttpd_types.http_service_reaction
    end
  val update_alist : ('a * 'b) list -> ('a * 'b) list -> ('a * 'b) list
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_signal.Debug.html0000644000175000017500000004100612731530352022177 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_signal.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netftp_fs.html0000644000175000017500000004562312731530352017230 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_fs

Module Netftp_fs

module Netftp_fs: sig .. end
FTP filesystem

class type ftp_stream_fs = object .. end
class ftp_fs : ?config_client:Netftp_client.ftp_client -> unit -> ?tmp_directory:string -> ?tmp_prefix:string -> ?get_password:string -> string -> ?get_account:string -> string -> ?keep_open:bool -> ?tls_config:(module Netsys_crypto_types.TLS_CONFIG) -> ?tls_enabled:bool -> ?tls_required:bool -> ?gssapi_provider:(module Netsys_gssapi.GSSAPI) -> ?gssapi_config:Netsys_gssapi.client_config -> ?gssapi_required:bool -> string -> ftp_stream_fs
ftp_fs base_url: Access the FTP file system rooted at base_url.
val ftp_fs : ?config_client:(Netftp_client.ftp_client -> unit) ->
?tmp_directory:string ->
?tmp_prefix:string ->
?get_password:(string -> string) ->
?get_account:(string -> string) ->
?keep_open:bool ->
?tls_config:(module Netsys_crypto_types.TLS_CONFIG) ->
?tls_enabled:bool ->
?tls_required:bool ->
?gssapi_provider:(module Netsys_gssapi.GSSAPI) ->
?gssapi_config:Netsys_gssapi.client_config ->
?gssapi_required:bool -> string -> ftp_stream_fs
Same as function
ocamlnet-4.1.2/doc/html-main/type_Netgssapi_auth.Auth.html0000644000175000017500000005703012731530352022212 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_auth.Auth functor (G : Netsys_gssapi.GSSAPI) (C : CONFIG->
  sig
    val check_status :
      ?fn:string -> ?minor_status:int32 -> Netsys_gssapi.major_status -> unit
    val get_initiator_name : Netsys_gssapi.client_config -> G.name
    val get_initiator_cred :
      initiator_name:G.name -> Netsys_gssapi.client_config -> G.credential
    val acquire_initiator_cred :
      initiator_name:G.name -> Netsys_gssapi.client_config -> G.credential
    val get_target_name :
      ?default:string * Netsys_gssapi.oid ->
      Netsys_gssapi.client_config -> G.name
    val get_client_flags :
      Netsys_gssapi.client_config -> Netsys_gssapi.req_flag list
    val check_client_flags :
      Netsys_gssapi.client_config -> Netsys_gssapi.ret_flag list -> unit
    val init_sec_context :
      initiator_cred:G.credential ->
      context:G.context option ->
      target_name:G.name ->
      req_flags:Netsys_gssapi.req_flag list ->
      chan_bindings:Netsys_gssapi.channel_bindings option ->
      input_token:Netsys_gssapi.token option ->
      Netsys_gssapi.client_config ->
      G.context * Netsys_gssapi.token * Netsys_gssapi.ret_flag list *
      Netsys_gssapi.client_props option
    val get_acceptor_name : Netsys_gssapi.server_config -> G.name
    val get_acceptor_cred :
      acceptor_name:G.name -> Netsys_gssapi.server_config -> G.credential
    val get_server_flags :
      Netsys_gssapi.server_config -> Netsys_gssapi.req_flag list
    val check_server_flags :
      Netsys_gssapi.server_config -> Netsys_gssapi.ret_flag list -> unit
    val accept_sec_context :
      acceptor_cred:G.credential ->
      context:G.context option ->
      chan_bindings:Netsys_gssapi.channel_bindings option ->
      input_token:Netsys_gssapi.token ->
      Netsys_gssapi.server_config ->
      G.context * Netsys_gssapi.token * Netsys_gssapi.ret_flag list *
      Netsys_gssapi.server_props option
    val get_display_name : G.name -> string * Netsys_gssapi.oid
    val get_exported_name : G.name -> string
  end
ocamlnet-4.1.2/doc/html-main/type_Netsys_oothr.condition.html0000644000175000017500000004164612731530352023027 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr.condition object
  method broadcast : unit -> unit
  method repr : exn
  method signal : unit -> unit
  method wait : Netsys_oothr.mutex -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.PROFILE.html0000644000175000017500000004133512731530352023226 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.PROFILE sig
  val hash_function : Netsys_digests.iana_hash_fn
  val iteration_count_limit : int
  val announce_channel_binding : bool
end
ocamlnet-4.1.2/doc/html-main/Netmech_krb5_sasl.Krb5_gs1.html0000644000175000017500000011651012731530352022176 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_krb5_sasl.Krb5_gs1

Functor Netmech_krb5_sasl.Krb5_gs1

module Krb5_gs1: 
This is an adapter turning the Kerberos 5 GSSAPI mechanism into a SASL mechanism. Note that there are two ways of doing this, RFC 4752 and RFC 5801, and this is the former way ("gs1"). The SASL name is "GSSAPI". Although this name may suggest that all GSSAPI mechanisms are understood, the RFC requires that this protocol is only used for Kerberos 5.

Create the final module like

module K = Netmech_krb5_sasl.Krb5_gs1(Netgss.System)
      

Remarks for clients:

This adapter doesn't need any credentials for create_client_session. You can pass the empty list. user is ignored (or better, the user is taken from the current Kerberos ticket). authz can be passed, though.

The client needs to know the service name (e.g. "imap") and the fully qualified domain name of the server. These must be passed in the "gssapi-acceptor" parameter in the form "service@fully.qualified.domain.name", e.g.

let cs =
  S.create_client_session
    ~user:"" ~authz:""
    ~creds:(S.init_credentials [])
    ~params:[ "gssapi-acceptor", "imap@mailprovider.com", false ]
    ()
      

Remarks for servers:

Usually the "realm" parameter is set to the name of the realm. In this case the realm is stripped off the principal before the lookup callback is invoked (e.g. "tim@REALM.NET" is shortened to just "tim"). If the "realm" parameter is not set, the full principal name is passed to lookup.

If lookup returns Some c for any c the user is accepted. If it returns None the user is declined.

The "gssapi-acceptor-service" parameter must be set to the name of the service. E.g.

let ss =
  S.create_server_session
    ~lookup:(fun user _ -> 
              if user_ok user then Some(S.init_credentials []) else None
            )
    ~params:[ "gssapi-acceptor-service", "imap", false;
              "realm", "SAMPLE.NET", false;
            ]
    ()
     

Parameters:

  • The parameter mutual is forwarded to the GSSAPI. Authentication fails if mutual authentication cannot be granted.
  • The parameter secure is understood but ignored (Kerberos is considered as secure method)
Statefulness:

The GSSAPI is stateful. Our SASL interface is stateless. We cannot hide the statefulness of the GSSAPI, and because of this old versions of sessions are invalidated. E.g. this does not work

let s1 = S.server_process_response s0 "some message"
let s2 = S.server_process_response s0 "another message"
      

and the second attempt to continue with the old session s0 will fail.

Parameters:
GSS : Netsys_gssapi.GSSAPI

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/Netcgi.rw_cgi_argument-c.html0000644000175000017500000004347012731530352022102 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.rw_cgi_argument

Class type Netcgi.rw_cgi_argument

class type rw_cgi_argument = object .. end
Deprecated.Arguments are read-only.
Old deprecated writable argument type.
Inherits
method ro : bool
method set_value : string -> unit
method open_value_wr : unit -> Netchannels.out_obj_channel
ocamlnet-4.1.2/doc/html-main/type_Netcgi.cgi.html0000644000175000017500000005254412731530352020313 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.cgi object
  method argument : string -> Netcgi.cgi_argument
  method argument_exists : string -> bool
  method argument_value : ?default:string -> string -> string
  method arguments : Netcgi.cgi_argument list
  method at_exit : (unit -> unit) -> unit
  method environment : Netcgi.cgi_environment
  method finalize : unit -> unit
  method multiple_argument : string -> Netcgi.cgi_argument list
  method out_channel : Netchannels.trans_out_obj_channel
  method output : Netchannels.trans_out_obj_channel
  method request_method :
    [ `DELETE | `GET | `HEAD | `POST | `PUT of Netcgi.cgi_argument ]
  method set_header :
    ?status:Nethttp.http_status ->
    ?content_type:string ->
    ?content_length:int ->
    ?set_cookie:Nethttp.cookie list ->
    ?set_cookies:Netcgi.Cookie.t list ->
    ?cache:Netcgi.cache_control ->
    ?filename:string ->
    ?language:string ->
    ?script_type:string ->
    ?style_type:string -> ?fields:(string * string list) list -> unit -> unit
  method set_redirection_header :
    ?set_cookies:Netcgi.Cookie.t list ->
    ?fields:(string * string list) list -> string -> unit
  method url :
    ?protocol:Nethttp.protocol ->
    ?with_authority:Netcgi.other_url_spec ->
    ?with_script_name:Netcgi.other_url_spec ->
    ?with_path_info:Netcgi.other_url_spec ->
    ?with_query_string:Netcgi.query_string_spec -> unit -> string
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp.http_header_ro.html0000644000175000017500000004060212731530352022745 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.http_header_ro Netmime.mime_header_roocamlnet-4.1.2/doc/html-main/type_Netxdr_mstring.html0000644000175000017500000006316412731530352021350 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netxdr_mstring sig
  class type mstring =
    object
      method as_bytes : Bytes.t * int
      method as_memory : Netsys_mem.memory * int
      method as_string : string * int
      method blit_to_bytes : int -> Bytes.t -> int -> int -> unit
      method blit_to_memory : int -> Netsys_mem.memory -> int -> int -> unit
      method blit_to_string : int -> Bytes.t -> int -> int -> unit
      method length : int
      method preferred : [ `Bytes | `Memory ]
    end
  class type mstring_factory =
    object
      method create_from_bytes :
        Bytes.t -> int -> int -> bool -> Netxdr_mstring.mstring
      method create_from_memory :
        Netsys_mem.memory -> int -> int -> bool -> Netxdr_mstring.mstring
      method create_from_string :
        string -> int -> int -> bool -> Netxdr_mstring.mstring
    end
  val bytes_based_mstrings : Netxdr_mstring.mstring_factory
  val string_based_mstrings : Netxdr_mstring.mstring_factory
  val string_to_mstring :
    ?pos:int -> ?len:int -> string -> Netxdr_mstring.mstring
  val bytes_to_mstring :
    ?pos:int -> ?len:int -> Bytes.t -> Netxdr_mstring.mstring
  val memory_based_mstrings : Netxdr_mstring.mstring_factory
  val memory_to_mstring :
    ?pos:int -> ?len:int -> Netsys_mem.memory -> Netxdr_mstring.mstring
  val paligned_memory_based_mstrings : Netxdr_mstring.mstring_factory
  val memory_pool_based_mstrings :
    Netsys_mem.memory_pool -> Netxdr_mstring.mstring_factory
  val length_mstrings : Netxdr_mstring.mstring list -> int
  val concat_mstrings : Netxdr_mstring.mstring list -> string
  val concat_mstrings_bytes : Netxdr_mstring.mstring list -> Bytes.t
  val prefix_mstrings : Netxdr_mstring.mstring list -> int -> string
  val prefix_mstrings_bytes : Netxdr_mstring.mstring list -> int -> Bytes.t
  val blit_mstrings_to_memory :
    Netxdr_mstring.mstring list -> Netsys_mem.memory -> unit
  val shared_sub_mstring :
    Netxdr_mstring.mstring -> int -> int -> Netxdr_mstring.mstring
  val shared_sub_mstrings :
    Netxdr_mstring.mstring list -> int -> int -> Netxdr_mstring.mstring list
  val copy_mstring : Netxdr_mstring.mstring -> Netxdr_mstring.mstring
  val copy_mstrings :
    Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
  val in_channel_of_mstrings :
    Netxdr_mstring.mstring list -> Netchannels.in_obj_channel
  val mstrings_of_in_channel :
    Netchannels.in_obj_channel -> Netxdr_mstring.mstring list
  type named_mstring_factories =
      (string, Netxdr_mstring.mstring_factory) Hashtbl.t
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.trace-c.html0000644000175000017500000004225712731530352021601 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.trace

Class Nethttp_client.trace

class trace : string -> int -> http_call
Arguments: URI, maximum number of hops

ocamlnet-4.1.2/doc/html-main/Netchannels.output_channel-c.html0000644000175000017500000004411512731530352023004 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_channel

Class Netchannels.output_channel

class output_channel : ?onclose:unit -> unit -> Pervasives.out_channel -> out_obj_channel
Creates an output channel writing into an out_channel.

The method pos_out reflects the real position in the channel as returned by Pervasives.pos_out. This works for both seekable and non-seekable channels.

The method close_out also closes the underlying out_channel. There is some implicit logic to either use close_out or close_out_noerr depending on whether the immediately preceding operation already reported an error.


onclose : this function is called when the close_out method is invoked, just after the underlying out_channel has been closed.

ocamlnet-4.1.2/doc/html-main/Netplex_sharedvar.VV_TYPE.html0000644000175000017500000004367512731530352022156 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sharedvar.VV_TYPE

Module type Netplex_sharedvar.VV_TYPE

module type VV_TYPE = sig .. end

type t 
type var 
val access : string -> var
val get : var -> t
val set : var -> t -> unit
val version : var -> int64
val update : var -> bool
ocamlnet-4.1.2/doc/html-main/type_Netaccel_link.html0000644000175000017500000004061612731530352021071 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaccel_link sig  endocamlnet-4.1.2/doc/html-main/Netldap.ldap_server-c.html0000644000175000017500000004335212731530352021411 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netldap.ldap_server

Class type Netldap.ldap_server

class type ldap_server = object .. end

method ldap_endpoint : Netsockaddr.socksymbol
method ldap_timeout : float
method ldap_peer_name : string option
method ldap_tls_config : (module Netsys_crypto_types.TLS_CONFIG) option
method ldap_tls_mode : tls_mode
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_kernel.http_response_impl.html0000644000175000017500000004143412731530352025404 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_response_impl ?close:bool ->
?suppress_body:bool ->
int64 ->
Nethttp.protocol ->
Nethttpd_kernel.announcement -> Nethttpd_kernel.http_response
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.copier-c.html0000644000175000017500000004253612731530352022440 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.copier

Class Uq_engines_compat.copier

class copier : copy_task -> Unixqueue.event_system -> [unit] engine

ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.trace.html0000644000175000017500000004075712731530352022425 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.trace string -> int -> Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Uq_engines_compat.sender-c.html0000644000175000017500000004263212731530352022434 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.sender

Class Uq_engines_compat.sender

class sender : src:#async_in_channel -> dst:Unix.file_descr -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system -> [unit] engine

ocamlnet-4.1.2/doc/html-main/Netplex_semaphore.html0000644000175000017500000005601112731530352020753 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_semaphore

Module Netplex_semaphore

module Netplex_semaphore: sig .. end
Netplex-wide semaphores


Semaphores are counters with atomic increment and decrement operations. They are very useful for counting the number of uses of a shared resource, and allow the identification of the first use (so the resource must be made available at all), and the last use (the resource can be released).

This implementation works in both multi-processing and multi-threading netplex environments. It is, however, not very fast, because the counters live in the controller, and the increment/decrement operations are realized by RPC's. It is good enough when these operations are only infrequently called, e.g. in the post-start and pre-finish processor callbacks.

This interface is designed so that a later re-implementation with POSIX semaphores is relatively straight-forward.

Thread safety: Full. The functions can be called from any thread.

val plugin : Netplex_types.plugin
To enable semaphores, call the controller's add_plugin method with this object as argument. This can e.g. be done in the post_add_hook of the processor.

The following functions can only be invoked in container contexts. Outside of such a context the exception Netplex_cenv.Not_in_container_thread is raised.
val increment : string -> int64
Increment the named semaphore by 1, and return the new value. If the semaphore does not exist yet, it is created with an initial value of 0, which is then incremented.

Semaphore names are global to the whole netplex system. By convention, these names are formed like "service_name.local_name", i.e. they are prefixed by the socket service to which they refer.

val decrement : ?wait:bool -> string -> int64
Decrement the named semaphore by 1, and return the new value. Semaphore values cannot become negative. If the value is already 0, it is not decremented anymore if wait = false. However, (-1) is then returned nevertheless.

If the value is already 0 and wait=true, the operation waits until the value exceeds 0, and when this happens, the semaphore is then decremented again. If several waiters exist, only one waiter gets the chance to decrement.

val get : string -> int64
Get the value of the named semaphore. Useful e.g. for monitoring the semaphore. If the semaphore does not exist, a value of 0 is returned.

get can also be invoked from the controller process.

val create : ?protected:bool -> string -> int64 -> bool
Create the semaphore with this initial value. Returns true if the creation is successful, and false if the semaphore already existed.

If protected, the semaphore is automatically decremented by some value when the container calling this function terminates. This value is pi - d where pi is the number of increments and d is the number of (successful) decrements requested by the container.

A semaphore needs not to be explicitly created by calling create. It is automatically created at the first use time with a value of 0 and protected=true.

create can also be invoked from the controller process.

val destroy : string -> unit
Destroy this semaphore. Any waiting decrement will immediately get (-1L).

Note that there is no protection against unintended re-creation after destroy.

destroy can also be invoked from the controller process.

val ctrl_increment : string -> Netplex_types.container_id -> int64
Increment the named semaphore from controller context, substituting an increment from a container (e.g. a container that terminated or is otherwise no longer able to do so). In this case the ID of the container needs to be passed

Example (code fragment):

Override the processor callbacks as follows to count the number of containers for the service:

 
    method post_add_hook sockserv ctrl =
      ctrl # add_plugin Netplex_semaphore.plugin

    method post_start_hook container =
      let sem_name = container#socket_service#name ^ ".counter" in
      let n =
        Netplex_semaphore.increment sem_name in
      if n=1 then
        prerr_endline "First container"

    method pre_finish_hook container =
      let sem_name = container#socket_service#name ^ ".counter" in
      let n =
        Netplex_semaphore.decrement sem_name in
      if n=0 then
        prerr_endline "Last container"
   

ocamlnet-4.1.2/doc/html-main/Netplex_encap.ENCAP.html0000644000175000017500000004313712731530352020710 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_encap.ENCAP

Module type Netplex_encap.ENCAP

module type ENCAP = sig .. end

type t 
val wrap : t -> Netplex_encap.encap
val unwrap : Netplex_encap.encap -> t
Raises Netplex_encap.Type_mismatch if the value does not fit
ocamlnet-4.1.2/doc/html-main/type_Foreword.html0000644000175000017500000004061112731530353020121 0ustar gerdgerd Ocamlnet 4 Reference Manual : Foreword sig  endocamlnet-4.1.2/doc/html-main/type_Nethttp.http_header.html0000644000175000017500000004057412731530353022256 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.http_header Netmime.mime_headerocamlnet-4.1.2/doc/html-main/type_Regexp.html0000644000175000017500000004060712731530353017571 0ustar gerdgerd Ocamlnet 4 Reference Manual : Regexp sig  endocamlnet-4.1.2/doc/html-main/Nethttpd_kernel.Debug.html0000644000175000017500000004202112731530353021445 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.Debug

Module Nethttpd_kernel.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module
ocamlnet-4.1.2/doc/html-main/Netcgi_apache.Apache.Request.html0000644000175000017500000011513012731530353022611 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache.Request

Module Netcgi_apache.Apache.Request

module Request: sig .. end

type t 
Apache request_rec structure.
val connection : t -> Netcgi_apache.Apache.Connection.t
request_rec connection field.
val server : t -> Netcgi_apache.Apache.Server.t
request_rec server field.
val next : t -> t
request_rec next field.
Raises Not_found if NULL.
val prev : t -> t
request_rec prev field.
Raises Not_found if NULL.
val main : t -> t
request_rec main field.
Raises Not_found if NULL.
val the_request : t -> string
request_rec the_request field.
Raises Not_found if NULL.
val assbackwards : t -> bool
request_rec assbackwards field; true if HTTP/0.9, "simple" request.
val header_only : t -> bool
request_rec header_only field. It is true when the request method is HEAD.
val protocol : t -> string
request_rec protocol field.
Raises Not_found if NULL.
val proto_num : t -> int
request_rec proto_num field. Number version of protocol; 1.1 = 1001
val hostname : t -> string
request_rec hostname field -- hostname to which the request was made.
Raises Not_found if NULL.
val request_time : t -> float
request_rec request_time field.
val status_line : t -> string
request_rec status_line field.
Raises Not_found if NULL.
val set_status_line : t -> string -> unit
Set request_rec status_line field.
val status : t -> int
request_rec status field.
val set_status : t -> int -> unit
Set request_rec status field.
val method_name : t -> string
request_rec method field.
val method_number : t ->
[ `CONNECT
| `COPY
| `DELETE
| `GET
| `INVALID
| `LOCK
| `MKCOL
| `MOVE
| `OPTIONS
| `PATCH
| `POST
| `PROPFIND
| `PROPPATCH
| `PUT
| `TRACE
| `UNLOCK ]
request_rec method_number field (given symbolically instead of a number).
val headers_in : t -> Netcgi_apache.Apache.Table.t
request_rec headers_in field.
val headers_out : t -> Netcgi_apache.Apache.Table.t
request_rec headers_out field.
val err_headers_out : t -> Netcgi_apache.Apache.Table.t
request_rec err_headers_out field.
val subprocess_env : t -> Netcgi_apache.Apache.Table.t
request_rec subprocess_env field.
val notes : t -> Netcgi_apache.Apache.Table.t
request_rec notes field.
val content_type : t -> string
request_rec content_type field.
Raises Not_found if NULL.
val set_content_type : t -> string -> unit
Set request_rec content_type field.
val uri : t -> string
request_rec uri field.
Raises Not_found if NULL.
val port : t -> int
Server port.
val set_uri : t -> string -> unit
Set request_rec uri field.
val filename : t -> string
request_rec filename field.
Raises Not_found if NULL.
val set_filename : t -> string -> unit
Set request_rec filename field.
val path_info : t -> string
request_rec path_info field.
Raises Not_found if NULL.
val set_path_info : t -> string -> unit
Set request_rec path_info field.
val args : t -> string
request_rec args field.
Raises Not_found if NULL.
val set_args : t -> string -> unit
Set request_rec args field.
val finfo : t -> Unix.stats option
request_rec finfo field.
type read_policy = 
| NO_BODY (*
Send 413 error if message has any body
*)
| CHUNKED_ERROR (*
Send 411 error if body without Content-Length
*)
| CHUNKED_DECHUNK (*
If chunked, remove the chunks for me.
*)
| CHUNKED_PASS (*
Pass the chunks to me without removal.
*)
Policy to apply by setup_client_block if the request message indicates a body.
val setup_client_block : t ->
read_policy -> unit
Setup for reading client request.
Raises Netcgi_common.HTTP in case of problems.
val should_client_block : t -> bool
Returns true if there is any client request data.
val get_client_block : t -> string
Get client request data.
Raises Netcgi_common.HTTP in case of reading error.
val get_client_block_buf : t -> Bytes.t -> int -> int -> int
get_client_block_buf r buf ofs len read a chunk of data and puts it in buf.[ofs .. ofs+len-1]. The return value i is the number of bytes actually read -- thus only buf.[ofs .. ofs+i-1] is meaningful.
Raises Netcgi_common.HTTP in case of reading error.
val discard_request_body : t -> unit
Discard client request body.
Raises Netcgi_common.HTTP in case of problems.
val user : t -> string
The authenticated user.
Raises Not_found if NULL.
val auth_type : t -> string
val note_auth_failure : t -> unit
Set headers to tell browser that authentication failed.
val note_basic_auth_failure : t -> unit
Set headers to tell browser that basic authentication failed.
val note_digest_auth_failure : t -> unit
Set headers to tell browser that digest authentication failed.
val get_basic_auth_pw : t -> string option
Get the password sent in basic authentication.
Raises Netcgi_common.HTTP in case of problems.
val internal_redirect : string -> t -> unit
Internally redirects immediately to uri.
val internal_redirect_handler : string -> t -> unit
Internally redirects immediately to uri using handler specified by r.
val send_http_header : t -> unit
Send the HTTP headers. Note that you must set the Status and Content-Type with set_status and set_content_type respectively.
val rflush : t -> unit
Flush any buffered data waiting to be written to the client.
Raises End_of_file if it is not possible.
val print_char : t -> char -> unit
Send a character back to the client.
val print_string : t -> string -> unit
Send a string back to the client.
val output : t -> Bytes.t -> int -> int -> int
output r s ofs len send s[ofs .. len-1] back to the client. Returns the number of bytes actually written, which is smaller than the number of bytes in the string if there was a failure.
val print_int : t -> int -> unit
Send a decimal number back to the client.
val print_float : t -> float -> unit
Send a floating-point number back to the client.
val print_newline : t -> unit
Send a CR LF back to the client.
val print_endline : t -> string -> unit
Send a string followed by CR LF back to the client.
val register_cleanup : t -> (unit -> unit) -> unit
Register a cleanup function which is called when the current request cycle ends.
ocamlnet-4.1.2/doc/html-main/Uq_engines.client_endpoint_connector-c.html0000644000175000017500000004347612731530353025051 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.client_endpoint_connector

Class type Uq_engines.client_endpoint_connector

class type client_endpoint_connector = object .. end

method connect : connect_address ->
Unixqueue.event_system -> connect_status engine
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.map_engine.html0000644000175000017500000004254512731530353024103 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.map_engine map_done:('-> 'Uq_engines_compat.engine_state) ->
?map_error:(exn -> 'Uq_engines_compat.engine_state) ->
?map_aborted:(unit -> 'Uq_engines_compat.engine_state) ->
?propagate_working:bool ->
'#Uq_engines_compat.engine -> ['b] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/type_Netsmtp.connect.html0000644000175000017500000004126612731530353021423 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsmtp.connect ?proxy:#Uq_engines.client_endpoint_connector ->
Uq_engines.connect_address -> float -> Netsmtp.client
ocamlnet-4.1.2/doc/html-main/type_Shell_sys.job_engine.html0000644000175000017500000004115012731530353022374 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_sys.job_engine Unixqueue.event_system ->
Shell_sys.job_instance -> [unit] Shell_sys.job_handler_engine_type
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.par_thread.html0000644000175000017500000004213212731530353023305 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.par_thread object
  method info_string : string
  method parallelizer : Netplex_types.parallelizer
  method ptype : Netplex_types.parallelization_type
  method sys_id : Netplex_types.thread_sys_id
  method watch_shutdown : Unixqueue.unix_event_system -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netmime.mime_body.html0000644000175000017500000004243612731530353021702 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.mime_body object
  method finalize : unit -> unit
  method open_value_rd : unit -> Netchannels.in_obj_channel
  method open_value_wr : unit -> Netchannels.out_obj_channel
  method ro : bool
  method set_value : string -> unit
  method store : store
  method value : string
end
ocamlnet-4.1.2/doc/html-main/type_Unixqueue_select.html0000644000175000017500000005533512731530353021672 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_select sig
  class type sb_event_system =
    object
      method add_abort_action :
        Unixqueue_util.group -> (Unixqueue_util.group -> exn -> unit) -> unit
      method add_close_action :
        Unixqueue_util.group ->
        Unix.file_descr * (Unix.file_descr -> unit) -> unit
      method add_event : Unixqueue_util.event -> unit
      method add_handler :
        Unixqueue_util.group ->
        (Unixqueue.event_system ->
         Unixqueue_util.event Equeue.t -> Unixqueue_util.event -> unit) ->
        unit
      method add_resource :
        Unixqueue_util.group -> Unixqueue_util.operation * float -> unit
      method add_weak_resource :
        Unixqueue_util.group -> Unixqueue_util.operation * float -> unit
      method clear : Unixqueue_util.group -> unit
      method exists_resource : Unixqueue_util.operation -> bool
      method is_running : bool
      method new_group : unit -> Unixqueue_util.group
      method new_wait_id : unit -> Unixqueue_util.wait_id
      method private queue_events :
        Unix.file_descr list * Unix.file_descr list * Unix.file_descr list ->
        bool
      method remove_resource :
        Unixqueue_util.group -> Unixqueue_util.operation -> unit
      method run : unit -> unit
      method private setup :
        unit ->
        Unix.file_descr list * Unix.file_descr list * Unix.file_descr list *
        float
      method private source : Unixqueue_util.event Equeue.t -> unit
      method when_blocking : (unit -> unit) -> unit
    end
  class select_based_event_system : unit -> sb_event_system
  val select_based_event_system : unit -> Unixqueue.event_system
end
ocamlnet-4.1.2/doc/html-main/type_Netmcore.compute_resource.html0000644000175000017500000004165212731530353023476 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore.compute_resource object
  method id : Netmcore.res_id
  method release : unit -> unit
  method repr : Netmcore.compute_resource_repr
  method typ : Netmcore.compute_resource_type
end
ocamlnet-4.1.2/doc/html-main/Uq_datagram.wrapped_datagram_socket-c.html0000644000175000017500000004736012731530353024617 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_datagram.wrapped_datagram_socket

Class type Uq_datagram.wrapped_datagram_socket

class type wrapped_datagram_socket = object .. end
A wrapped_datagram_socket allows datagrams to be sent via proxies. It provides versions of the sendto and recvfrom functions that use extended socket names (which are proxy-friendly).

method descriptor : Unix.file_descr
The underlying file descriptor. This descriptor must not be used to transfer data (Unix.send(to), Unix.recv(from), etc.), because the descriptor may be connected with a proxy, and the socket addresses may be wrong that are used by the low-level socket functions. The right way is to use the methods below to transfer data. It is allowed, however, to pass the descriptor to Unix.select, and to check whether transfers are possible. It is also allowed to set or clear non-blocking mode, and the close-on-exec flag, and to modify the socket options.
method sendto : Bytes.t -> int -> int -> Unix.msg_flag list -> Uq_engines.sockspec -> int
Send data over the (unconnected) socket
method recvfrom : Bytes.t -> int -> int -> Unix.msg_flag list -> int * Uq_engines.sockspec
Receive data from the (unconnected) socket. The method will raise EAGAIN if the message cannot be processed for some reason, even if the socket is in blocking mode. In this case, the received message is discarded.
method shut_down : unit -> unit
Close the descriptor, shuts down any further needed resources
method datagram_type : datagram_type
method socket_domain : Unix.socket_domain
method socket_type : Unix.socket_type
method socket_protocol : int
ocamlnet-4.1.2/doc/html-main/Netgzip.output_gzip-c.html0000644000175000017500000004246612731530353021533 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.output_gzip

Class Netgzip.output_gzip

class output_gzip : Gzip.out_channel -> Netchannels.out_obj_channel
A Gzip.out_channel turned into a Netchannels.out_obj_channel

ocamlnet-4.1.2/doc/html-main/Rpc_mapping_ref.html0000644000175000017500000013625312731530353020374 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_mapping_ref

Rpc_mapping_ref


RPC Language Mapping Reference

The OncRPC (alias SunRPC) standard consists of two parts, namely the external data representation (XDR) and the RPC protocol. They are defined in RFC 1831 and RFC 1832.

In this document we describe how the various parts of XDR and RPC are mapped to the Objective Caml language.

Representation Levels

The transformation of binary XDR messages to O'Caml values is done in several steps, corresponding to several ways of representing the values:

  • Binary level: The message is represented as byte string. In O'Caml, these byte strings are always string values.
  • Term level: The XDR type is given as Netxdr.xdr_type_term. The message is represented as structured Netxdr.xdr_value term. For example, an XDR struct with two components a and b with integer values 1 and 2 is represented as
    XV_struct [ "a", XV_int r1; "b" XV_int r2 ]
    where r1 = Netnumber.int4_of_int 1 and r2 = Netnumber.int4_of_int 2. There are sometimes several ways of representing a value on term level.
  • Fully-mapped level: The message is represented as a generated O'Caml type that closely corresponds to the XDR type. The struct example would use the type
    type name = { a : int; b : int }
    . Some details can be selected by the user, e.g. how integers are represented. The types are generated using ocamlrpcgen.
The tool ocamlrpcgen can be invoked on an input file name.x with different switches to create three modules: the type mapper Name_aux, the RPC client Name_clnt and the RPC server Name_srv. The type mapper module mainly contains the necessary definitions to convert values between the representation levels.

In particular, the type mapper module contains for every XDR type t several definitions:

  • The definition of the O'Caml type corresponding to t on the fully-mapped level.
  • The dynamic representation of the XDR type as Netxdr.xdr_type_term. This definition is named xdrt_t. The type term is required to convert a binary message to a value on term level. The conversion functions to do so are available in the Netxdr module.
  • The conversion function _of_t that turns a fully-mapped value into a term value represented as Netxdr.xdr_value.
  • The conversion function _to_t that turns a term value to a fully-mapped value.
In order to develop an RPC client or server it is usually not necessary to use these definitions. They are useful, however, to encode or decode binary XDR messages directly (e.g. outside an RPC context).

XDR: Simple Types

The following table shows:

  • how a variable x would be declared in the XDR file
  • what the corresponding term type is
  • how the type is mapped to a full OCaml type
XDR declaration for x Term-level mapping Full mapping Comment
void Netxdr.X_void unit (in some contexts omitted) -
int x Netxdr.X_int Netnumber.int4, int32, int64, or int [1] 32 bit signed integer
_abstract int x Netxdr.X_int Netnumber.int4 [6] 32 bit signed integer
_int32 int x Netxdr.X_int int32 32 bit signed integer
_int64 int x Netxdr.X_int int64 32 bit signed integer
_unboxed int x Netxdr.X_int int [2] 32 bit signed integer
unsigned int x Netxdr.X_uint Netnumber.uint4, int32, int64, or int [1] 32 bit unsigned integer
unsigned _abstract int x Netxdr.X_uint Netnumber.uint4 [6] 32 bit unsigned integer
unsigned _int32 int x Netxdr.X_uint int32 [4] 32 bit unsigned integer
unsigned _int64 int x Netxdr.X_uint int64 32 bit unsigned integer
unsigned _unboxed int x Netxdr.X_uint int [2] 32 bit unsigned integer
hyper x Netxdr.X_hyper Netnumber.int8, int64, or int [1] 64 bit signed integer
_abstract hyper x Netxdr.X_hyper Netnumber.int8 [6] 64 bit signed integer
_int64 hyper x Netxdr.X_hyper int64 64 bit signed integer
_unboxed hyper x Netxdr.X_hyper int [3] 64 bit signed integer
unsigned hyper x Netxdr.X_uhyper Netnumber.int8, int64, or int [1] 64 bit unsigned integer
unsigned _abstract hyper x Netxdr.X_uhyper Netnumber.uint8 [6] 64 bit unsigned integer
unsigned _int64 hyper x Netxdr.X_uhyper int64 [4] 64 bit unsigned integer
unsigned _unboxed hyper x Netxdr.X_uhyper int [3] 64 bit unsigned integer
bool x Netxdr.x_bool bool Boolean type
float x Netxdr.X_float float [5] 32 bit IEEE float
double x Netxdr.X_double float [5] 64 bit IEEE float
opaque x[n] Netxdr.X_opaque_fixed string Opaque data with exactly n bytes. The length n is dynamically checked
opaque x<n> Netxdr.X_opaque string Opaque data with up to n bytes. The length n is dynamically checked
string x<n> Netxdr.X_string string String consisting of up to n bytes. The length n is dynamically checked
_managed string x<n> Netxdr.X_mstring Netxdr_mstring.mstring Alternative runtime representation. See Netxdr_mstring.

Footnotes:

  1. The default is the first alternative. You can select with command-line switches of ocamlrpcgen one of the other options for the whole XDR file
  2. On 32 bit platforms only a subset of XDR values can be represented with this OCaml type. If a conversion fails, Netnumber.Cannot_represent is raised.
  3. On both 32 and 64 bit platforms only a subset of XDR values can be represented with this OCaml type. If a conversion fails, Netnumber.Cannot_represent is raised.
  4. This is a logical mapping: large XDR numbers where the MSB is set are mapped to negative OCaml numbers.
  5. The OCaml float type is a 64 bit IEEE floating point number.
  6. The module Netnumber is an extended version of the older (and now removed) Rtypes definition, and contains wrapper types for all XDR number types.

XDR: Options

The "pointer type" *t is considered as an option type in XDR corresponding to option in O'Caml, i.e. a variant with the two cases that an argument is missing or present. Option types are written

t *varname
in .x files.

On term level, the missing argument value is represented as Netxdr.xv_none. The present argument value is represented as Netxdr.xv_some v when v is the mapped argument value. Actually, xv_none and xv_some construct XDR terms that are unions over the boolean enumeration as discriminator.

On the fully-mapped level, the option type is mapped to

t' option
O'Caml type when t' is the mapped argument type.

XDR: Arrays

In XDR arrays are formed over an element type. Furthermore, there may be the size constraint that exactly or at most n elements are contained in the array. If the size constraint is missing, the array may have arbitrary many elements. However, due to the binary representation, the number is actually limited to 2 ^ 32 - 1.

XDR declaration for x Term-level mapping Full mapping Comment
t x[n] Netxdr.X_array t' array Arrays with exactly n elements
t x<n> Netxdr.X_array t' array Arrays with up to n elements
t x<> Netxdr.X_array t' array Arrays with any number of elements

The size constraints are dynamically checked in all cases when RPC message are analyzed or created.

XDR: Structs

Structs are products with named components, like record types in O'Caml. The components have, in addition to their name, a fixed order, because the order of the components determines the order in the binary message format. That means that the components can be accessed by two methods: by name and by index.

Struct are written as

 struct {
     t0 varname0;
     t1 varname1;
     ...
  }
in .x files.

For example, struct { int a; hyper b } means a struct with two components. At position 0 we find "a", and at position 1 we find "b". Of course, this type is different from struct { hyper b; int a } because the order of the components is essential.

On term level, there are two ways of representing structs Netxdr.X_struct: one identifies components by name, one by position. The latter is also called the "fast" representation (and the one used by ocamlrpcgen).

In the "by name" case, the struct value is represented as Netxdr.XV_struct components where components is an association list [(c0_name, c0_val); (c1_name, c1_val); ...] where cK_name are the names of the components and cK_val their actual values as terms. The order of the components can be arbitrary.

In the "by position" case, the struct value is represented as Netxdr.XV_struct_fast components where components is an array of terms such that components.(k) is the term value of the k-th component.

On the fully-mapped level, the struct is mapped to an O'Caml record. The order of the components remains the same, but the names of the components may be modified. First, the names are modified such that they are valid component names in O'Caml by ensuring that the first letter is lowercase. Second, the names may be changed because several structs use the same component names which is not possible in O'Caml. Thus, the generated O'Caml record type look like

   {
     mutable varname0' : t0';
     mutable varname1' : t1';
     ...
   }

where varnameK' is the component name after the mentioned renaming and tK' is the mapped component type, both for position K.

Equality constraints

Since Ocamlnet-3.6.7 the keyword _equals is understood and generates an equality constraint, e.g. struct _equals "M.t" { int a; hyper b }, meaning that this OCaml record type is the same as the one defined as M.t.

Controlling the name mapping

Ocamlnet-3.6.7 also introduces the name mapping directives for struct fields:

  • _lowercase: the XDR name is lowercased
  • _uppercase: the XDR name is uppercased
  • _capitalize: the XDR name is capitalized
  • _prefix "p": this prefix is prepended to the XDR name
For example, struct _lowercase _prefix "my_" { int A; hyper B } would generate a record type with fields my_a and my_b.

Tuples

Since Ocamlnet-3.6.7 it is possible to select an alternate mapping to OCaml tuples by specifying the _tuple keyword (e.g. struct _tuple { int a; hyper b } ).

XDR: Enumerations

In XDR it is possible to define enumerations which are considered as subtypes of int. These consist of a list of integers with associated symbolic names. In the .x file this is written as

   enum {
     Name0 = Int0,
     Name1 = Int1,
     ...
   }

where NameK are identifiers and IntK are literal numbers.

In this section we only consider the case that the enumerations are not used as discriminator for a union. (See below for the other case.)

On term level, there are again two representations. One uses the names to identify one of the enumerated values, and the other uses a positional method.

In the "by name" case, the value named NameK is represented as Netxdr.XV_enum "NameK", i.e. the name is the argument of XV_enum.

In the "by position" case, the value named NameK is represented as Netxdr.XV_enum_fast K, i.e. the position in the enum declaration is the argument of XV_enum.

On the fully-mapped level, the enumerated value named NameK is represented as O'Caml value of type Netnumber.int4 whose value is IntK, i.e. the number associated with the name. In the type mapper file generated by ocamlrpcgen there are additional definitions for every enum. In particular, there is a constant whose name is NameK (after makeing the name OCamlish) and whose value is IntK.

Controlling the name mapping

Ocamlnet-3.6.7 also introduces the name mapping directives for enum constants:

  • _lowercase: the XDR name is lowercased
  • _uppercase: the XDR name is uppercased
  • _capitalize: the XDR name is capitalized
  • _prefix "p": this prefix is prepended to the XDR name
For example, enum _lowercase _prefix "my_" { A=0, B=1 } would generate constants my_a and my_b (with the values 0 and 1, resp.).

XDR: Unions discriminated by integers

In XDR a union must always have disriminator. This can be an int, an unsigned int, or an enumeration. The latter case is described in the next section. In the integer case, the union declaration enumerates a number of arms and a default arm:

 union switch (d varname) {
     case Int0:
       t0 varname0;
     case Int1:
       t1 varname1;
     ...
     default:
       tD varnameD;
   }

Here, d is either int or unsigned int.

On term level, this is represented as Netxdr.XV_union_over_int(n,v) for the int case or Netxdr.XV_union_over_uint(n,v) for the unsigned int case. The number n is the selected arm of the union (it is not indicated whether the arm is one of the declared arms or the default arm). The value v is the mapped value of the arm.

On the fully-mapped level, the union is mapped to a polymorphic variant that corresponds to the original union declaration:

 
   [ `_Int0 of t0'
   | `_Int1 of t1'
   ...
   | `default of tD'
   ]

The labels of the variants are derived from the decimal literals of the numbers IntK associated with the arms. For example, the union

 union switch (int d) { 
     case -1: 
       hyper a;
     case 0:
       bool b;
     default:
       string s<>;
   }

is mapped to

 [ `__1 of int64 | `_0 of bool | `default of Netnumber.int4 * string ] 

Note that the default case consists of the value of the discriminant on the left and the value of the union on the right.

If an arm is simply void, the corresponding variant will not have an argument.

XDR: Unions discriminated by enumerations

If the discriminator is an enumeration, different O'Caml types are used, as a much nicer mapping is possible.

As for integer-discriminated unions, the arms are enumerated. The default arm, however, is now optional. The whole construct looks like:

 enum e {
     Name0 = Int0,
     Name1 = Int1,
     ...
   }

   union switch (e varname) {
     case Name0:
       t0 varname0;
     case Name1:
       t1 varname1;
     ...
     default:          /* optional! */
       tD varnameD;
   }

On the term level, there are again two different ways of representing a union value, namely by referring to the arm symbolically or by position.

In the first case, the value is represented as Netxdr.XV_union_over_enum(n,v) where n is the string name of the value of the discriminator (i.e. "NameK"), and v is the mapped value of the selected arm.

In the second case, the value is represented as Netxdr.XV_union_over_enum_fast(K,v) where K is the position of the value of the discriminator in the enumeration, and v is the mapped value of the selected arm.

On the fully-mapped level, the union is again mapped to a polymorphic variant:

  [ `Name0 of t0'
  | `Name1 of t1'
  | ...
  ]

Every label of an enumerated value is turned into the label of the variant. The argument is the mapped value of the corresponding arm. Note that default values do not occur in this representation as such.

For example, the union

 enum e {
     CASEA = 5,
     CASEB = 42,
     CASEC = 7,
     CASED = 81
   }

  union switch (e d) {
    case CASEB:
      int b;
    case CASEC:
      void;
    default:
      hyper ad;
  }

is mapped to the O'Caml type (the tags are all lowercase by default):

 
   [ 'casea of int64     (* expanded default case *)
   | `caseb of int32
   | `casec
   | `cased of int64     (* expanded default case *)
   ]

If an arm is simply void like for CASEC, the corresponding variant will not have an argument like `casec.

Controlling the name mapping

Ocamlnet-3.6.7 also introduces the name mapping directives for union tags:

  • _lowercase: the XDR name is lowercased
  • _uppercase: the XDR name is uppercased
  • _capitalize: the XDR name is capitalized
  • _prefix "p": this prefix is prepended to the XDR name
An example: The XDR type

  union _capitalize switch (e d) {
    case CASEB:
      int b;
    case CASEC:
      void;
    default:
      hyper ad;
  }

is mapped to

 
   [ 'Casea of int64
   | `Caseb of int32
   | `Casec
   | `Cased of int64
   ]

If there are name mapping directives in the definition of the enumeration e, these directives will be ignored. Only the directives in the union definition are used for generating the OCaml tag names.

RPC: Programs

In an .x file one can declare programs. A program consists of a number of program versions, and every version consists of a number of procedures. Every procedure takes a (possibly empty) list of arguments and yields exactly one result (which may be void, however). This is written as:

   /* type definitions come first */
   ...

   /* Now the programs: */
   program P1 {
       version V1 {
           r1 name1(arg11, arg12, ...) = L1;
           r2 name2(arg21, arg22, ...) = L2;
           ...
       } = M1;

       version V2 {
          ...
       } = M2;

       ...

   } = N1;

   program P2 {
     ...
   } = N2;

   ...

Here, P1, P2, ..., V1, V2, ...,name1, name2, ... are identifiers. r1, r2, arg11, ... are type expressions. N1, N2, ..., M1, M2, ..., L1, L2, ... are unsigned numbers.

Programs are dynamically represented using the Rpc_program module. Every Rpc_program.t value contains the full signature of exactly one version of one program.

In the generated type mapper module, the definitions for the programs are available as constants program_P'V where P is the name of the program and V is the version of the program.

RPC: Clients

To write

  • Point to Rpc_client as basis
  • Clients can be used on term level by directly calling functions of Rpc_client
  • ocamlrpcgen generates an enhanced client module containing procedure stubs. These stubs are on the fully-mapped level.

RPC: Servers

To write

  • Point to Rpc_server as basis
  • Servers can be created on term level by using functions of Rpc_server
  • ocamlrpcgen generates an enhanced server module containing a converter to/from the fully-mapped level.

ocamlnet-4.1.2/doc/html-main/Netplex_encap.html0000644000175000017500000004722412731530353020065 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_encap

Module Netplex_encap

module Netplex_encap: sig .. end
Type-safe marshalling between processes of the same executable


This is a pragmatic approach to type-safe marshalling. We define type encap as an arbitrary value that carries a type identifier with it. The type identifier is generated when the functor Netplex_encap.Make_encap is applied. Every instantiation of this functor generates a new type identifier.

The idea is then that an encap value can be marshalled to another process using Marshal, and when it is unwrapped the type identifier is checked. Unwrapping is only successful when the unwrap function from the same functor instantiation is used as the wrap function.

This module is incompatible with:

  • Marshalling to processes running a different executable
  • Marshalling to processes that are dynamically loading modules
  • The functor must be instantiated at program initialization time. Especially this must not happen in let module expressions.
Only some of these assumptions can be checked at runtime by this implementation.
exception Type_mismatch
Raised when an encapulated type is tried to be unwrapped by the wrong encapsulation module
type encap 
An encapsulated value with a type identifier
module type TYPE = sig .. end
Just a (monomorphic) type t
module type ENCAP = sig .. end
module Make_encap: 
functor (T : TYPE) -> ENCAP with type t = T.t
Create an encapsulation module
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.async_in_channel.html0000644000175000017500000004224512731530353023726 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.async_in_channel object
  method can_input : bool
  method close_in : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method pos_in : int
  method request_notification : (unit -> bool) -> unit
end
ocamlnet-4.1.2/doc/html-main/Netplex_log.syslog_config-c.html0000644000175000017500000004273512731530353022646 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_log.syslog_config

Class type Netplex_log.syslog_config

class type syslog_config = object .. end
Inherits
method log_identifier : string
method log_facility : Netsys_posix.syslog_facility
ocamlnet-4.1.2/doc/html-main/type_Netmech_plain_sasl.PLAIN.html0000644000175000017500000004065712731530353022776 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_plain_sasl.PLAIN Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/Platform.html0000644000175000017500000010367412731530353017066 0ustar gerdgerd Ocamlnet 4 Reference Manual : Platform

Platform


Platform Support

Not everything works in the same way for all operating systems. This documents describes the different levels of support for the various platforms.

POSIX

Ocamlnet has been primarily developed for POSIX systems. Most libraries should work on all systems, but there are also some more special features that are designed for certain systems only.

Banning select()

On POSIX systems, the select() system call is not used anymore. As a general-purpose replacement Ocamlnet favors poll(). In future versions of Ocamlnet, there will also be support for the improved versions of poll() some systems provide, such as epoll on Linux, kqueue on BSD, and /dev/poll on Solaris. Ocamlnet is already prepared for this change.

The reason for banning select() are the limited capabilities of this API. Especially, it cannot handle file descriptors whose numeric values exceed a system-dependent limit. Although this limit is quite high (usually 1024) there are applications that need more descriptors. (Note that it is not sufficient to simply increase the maximum number of descriptors a process can have - the select() call is still restricted in the mentioned sense, and this seems to be unfixable.) The poll() interface does not have this problem.

The poll() interface is made accessible from Ocaml in Netsys_posix.

Multi-processing and fork()

One of the main difference of the POSIX platforms compared with Windows is that there is the fork() system call. Ocamlnet provides multi-processing support in the netplex library (see Netplex_mp). This makes it easy to manage a set of child processes that are used as parallel running "workers" (e.g. for accepting network connections).

There is a registry of user functions to be run after a new child process has been forked off (see Netsys_posix.register_post_fork_handler). The intention is that the child can close descriptors it would otherwise share with the parent.

One should note that there is a basic incompatibility between code that uses fork() to achieve parallelism and multi-threading. The problem is that the state of synchronization objects like mutexes is undefined after fork(). In the C language, one can try to define special handlers that run before/after the fork() to fix up such objects. There is no such possibility in Ocaml (the mentioned registry cannot be used for this purpose). One simply should not call fork() while there is more than one thread. It is of course allowed to start threads in the sub processes.

For the multi-processing capability of netplex this means that one must not create threads in the master process (from which the worker processes are forked off). There is no such restriction for the children.

Starting programs as sub processes

There is now extended support for starting subprograms. First, there is Netsys_posix.spawn which provides a comfortable way for starting programs. The interface is patterned after the posix_spawn() system call although the implemention is not using posix_spawn() yet, but a traditional fork/exec combination. (In a later version of Ocamlnet it is planned to give the user the choice of using posix_spawn() as the underlying system interface. On some OS, posix_spawn() is highly optimized and significantly faster than fork/exec.)

Second, it is now possible to let Ocamlnet watch for the termination of child processes: Netsys_posix.watch_subprocess. This function arranges that the SIGCHLD signal is caught, and that the process termination is reported as a file descriptor event. By means of careful programming this even works for multi-threaded applications (where signal handling is notoriously difficult).

RPC integration

POSIX systems usually already provide RPC functionality, as some deeply-integrated networking protocols like NFS are based on it. Traditionally, there is a program called portmapper that acts as registry of RPC services running on a machine. Ocamlnet can register servers in portmapper, and it can also look up services there.

On some systems, there is a newer version of portmapper called rpcbind. Fortunately, rpcbind is backward-compatible, and also provides a portmapper-style interface.

There is some problem, though, on systems that also provide the XTI networking API which is a replacement for the socket API. Whereas TCP/IP can be used with both XTI and sockets, the local network connections the API's provide are incompatible: A local XTI endpoint cannot be contacted over the socket API, and a local socket endpoint (i.e. a Unix domain socket) cannot be contacted over XTI. There is the helper library Rpc_xti_client that allows to connect to a local XTI server.

Windows

Cygwin

On Cygwin Ocamlnet should behave like on a POSIX machine.

Win32

General remark: The Win32 port is still very experimental, and far from being bug-free! Development progresses very slowly. Please don't expect wonders.

There is now a lot of support for Win32, even for asynchronous network programming. The minimum Windows version is Windows XP SP2. One should also mention that some functions are only supported when the Ocaml program is compiled as multi-threaded program, as sometimes helper threads are needed to emulate a certain behavior. For example, Win32 limits the number of file handles to 64 per thread when one watches them for events. Ocamlnet includes support to overcome this limit by creating helper threads as needed.

As a substitute for Unix Domain sockets, Ocamlnet provides access to Win32 named pipes. These are, for security reasons, restricted to local connection (within the same machine). As named pipes exist in a special file system, one cannot create named pipes in arbitrary directories (unlike Unix Domain sockets). As a workaround, it is also supported to create named pipes with random names, and to write these names into text files. A number of functions that used to expect Unix Domain socket files as input can now also deal with these text files, and will automatically map these files to the referenced named pipes (see Netplex_sockserv.any_file_client_connector).

The RPC implementation supports TCP/IP sockets and named pipes, both for clients and for servers. As for POSIX, the clients and servers can be programmed in an asynchronous way.

Netplex is supported, but only for multi-threaded containers. The multi-processing containers are not available. Netplex can manage both TCP connections and named pipes.

The Shell library works, too. As for POSIX, it is possible to create complex pipelines between the started shell commands, and it is possible to read the output of and to provide input to the commands at the same time. All asynchronous command execution features are available! The only limitation is that one can redirect only stdin/stdout/stderr of the started commands, and not arbitrary descriptors as for POSIX (this is a restriction of Win32).

The Equeue library is supported. The GTK- and TclTk-specific extensions do not work, however. The SSL add-on is untested.

The Netshm library is only partially supported: The managed memory object must be file-backed and cannot (yet) live in RAM-only shared memory.

The Nethttpd library is fully supported.

XXX: Netcgi2

Win32 low-level

The missing Win32 calls are made available via Netsys_win32. The accessible objects are:

  • Events: Win32 event objects can signal a condition (and look like condition variables)
  • Named pipes: Win32 named pipes are network connections between a client endpoint and a server endpoint. Ocamlnet only supports local connections, however.
  • Pipe servers: The notion of "pipe servers" does not exist in Win32 as kernel objects. Win32 sees a pipe server as a set of endpoints one can connect to, and the user code has to manage this set. In Netsys_win32, pipe server objects are emulated to simplify this for user code, so that pipe servers look very much like socket servers.
  • Input threads: Netsys_win32 provides helper threads allowing one to read from an arbitrary file handle in an asynchronous way, even if Win32 does not support that for the type of handle. This is intended for reading from anonymous pipes (as returned by Unix.pipe).
  • Output threads: a similar kind of object writing to file handles
  • Processes
  • Consoles
As you can see, we are trying to make the Win32 calls a bit more user friendly. One of the goals of this wrapper is to make them even usable in programs that are mainly written for POSIX.

A central idea here is the concept of "proxy descriptors". Many of the mentioned objects have a complex inner structure - e.g. a pipe server can mean an open number of Win32 file handles. However, it is intended to make these objects look like in POSIX, and that means that there is only a single descriptor referencing the object. The proxy descriptors are additional file descriptors Ocamlnet allocates only for the purpose of referencing these objects. For example, a pipe server is mainly represented by the type Netsys_win32.w32_pipe_server, and there are a lot of functions dealing with such values, e.g. Netsys_win32.pipe_shutdown_server for shutting a server down. Of course, a Netsys_win32.w32_pipe_server is not a file descriptor, but a complex Ocaml record. The question is now how to pass such an object to functions that only accept file descriptors as input? The solution looks simple although the implementation causes a lot of headache: A special file descriptor is allocated, and there is a global table mapping these descriptors to the real objects. For instance, you can get the proxy descriptor of a pipe server by calling

 let (fd : Unix.file_descr) =
     Netsys_win32.pipe_server_descr psrv 

for a pipe server object psrv. You can pass fd around, and when a called function requires the pipe server object again, one can map fd back by:

 let (psrv : Netsys_win32.w32_pipe_server) =
     Netsys_win32.lookup_pipe_server fd

Like other descriptors, fd must be closed after use. The tricky part of the implementation is that unreferenced proxy descriptors are detected, and that the entry of the global mapping table is deleted then.

As mentioned, Ocamlnet supports asynchronous I/O for the supported Win32 objects. For some objects, Win32 has built-in support in the form of so-called overlapped I/O. This kind of I/O is, unfortunately, different than what POSIX provides (poll-style I/O). The analysis shows that the main difference is that in Win32 one has to start an I/O operation in order to asynchronously check whether and when it is finally possible, whereas POSIX allows one to check the possibility of I/O before one starts the operation. Ocamlnet hides this difference in the Netsys_win32 wrapper by providing additional buffering. The price is, however, that the generic read and write calls (or better, ReadFile and WriteFile in Win32) can no longer be used. As a substitute, Ocamlnet provides for each kind of object a special set of read and write operations, e.g. Netsys_win32.pipe_read for named pipes.

For simplicity of user code, there are also generalized read/write operations: Netsys.gread and Netsys.gwrite. These work for all descriptors supported by Unix.read and Unix.write, plus for sockets, plus for all of the mentioned Win32-specific objects for which reading and writing are reasonable I/O operations.

If overlapping I/O is unavailable for a kind of file handle, it is still possible to use the input and output threads in order to do asynchronous I/O for these handles. An example of such a handle type are anonymous pipes. The threads are automatically started and initiate synchronous I/O operations when needed. The completion of the operations is signalled via condition variables to the caller, so that it is possible to provide an asynchronous API to the file handle.

Hints for portable programming

Generally, the functions in Netsys are available on all platforms (but not necessarily in all variants), whereas Netsys_posix and Netsys_win32 contain the platform-specific stuff.

In order to read and write file descriptors, one should first get the kind of descriptor fd:

 let st = Netsys.get_fd_style fd 

Now, one can read and write to the file descriptor by calling Netsys.gread and Netsys.gwrite (or by some of the provided variants of these functions). These functions need st as input, and internally call the right system function to do the requested I/O operation.

There is also Netsys.gshutdown for shutting a descriptor down (possibly only half-way), and Netsys.gclose for closing a descriptor.

In order to wait for a single descriptor, one can call one of the Netsys functions doing so, e.g. Netsys.wait_until_readable. These functions block execution until the requested I/O operation is possible, or until a timeout elapses.

If several descriptors need to be waited for, there is the portable class type Netsys_pollset.pollset. One can add several descriptors to pollsets and wait until I/O operations for one of the descriptors become possible. There are implementations for both POSIX and Win32. Netsys_pollset_generic.standard_pollset automatically selects the best pollset implementation for "normal use".

For porting programs that are still written around Unix.select, there is an emulation of select on top of pollsets: Netsys_pollset_generic.select_emulation.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.output_async_descr.html0000644000175000017500000004136312731530353025713 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.output_async_descr dst:Unix.file_descr ->
?buffer_size:int ->
?close_dst:bool ->
Unixqueue.event_system -> Uq_engines_compat.async_out_channel_engine
ocamlnet-4.1.2/doc/html-main/Netplex_types.container-c.html0000644000175000017500000006314312731530353022342 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.container

Class type Netplex_types.container

class type container = object .. end
Containers encapsulate the control flow of the service components. A container is run in a separate thread or process.

Thread safety: All methods except start can be called from any thread, and provide full thread safety.


method socket_service_name : string
method socket_service : socket_service
method container_id : container_id
Return the container ID
method ptype : parallelization_type
The parallelization type actually used for this container
method event_system : Unixqueue.unix_event_system
The event system the container uses
method start : extfd -> extfd -> unit
Internal Method. Called by the controller to start the container. It is the responsibility of the container to call the post_start_hook and the pre_finish_hook.

The file descriptors are endpoints of RPC connections to the controller. The first serves calls of the Control program, and the second serves calls of the System program.

When start returns the container will be terminated.

method shutdown : unit -> unit
Initiates a shutdown of the container.
method n_connections : int
The current number of connections
method n_total : int
The sum of all connections so far
method system : Rpc_client.t
An RPC client that can be used to send messages to the controller. Only available while start is running. It is bound to System.V1.

In multi-threaded programs access to system must be governed by system_monitor. See Uq_mt for details what this means.

method system_monitor : Uq_mt.monitor
The thread monitor protecting the system RPC client
method lookup : string -> string -> string option
lookup service_name protocol_name tries to find a Unix domain socket for the service and returns it.
method lookup_container_sockets : string -> string -> string array
lookup_container_sockets service_name protocol_name: returns the Unix Domain paths of all container sockets for this service and protocol. These are the sockets declared with address type "container" in the config file.
method owned_container_sockets : (string * string) list
List of pairs (protocol_name, path) of all container sockets of this container
method send_message : string -> string -> string array -> unit
send_message service_pattern msg_name msg_arguments: Sends a message to all services and message receivers matching service_pattern. The pattern may include the wildcard *.

See the Netplex_types.controller.send_message method for the notification guarantees.

method log : level -> string -> unit
Sends a log message to the controller.
method log_subch : string -> level -> string -> unit
Sends a log message to the controller. The first string is the subchannel
method update_detail : Unix.file_descr -> string -> unit
Update the detail string output for the netplex.connections admin message
method var : string -> param_value_or_any
Returns the value of a container variable or Not_found. Container variables can be used by the user of a container to store additional values in the container. These values exist once per thread/process.
method set_var : string -> param_value_or_any -> unit
Sets the value of a container variable
method call_plugin : plugin -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
call_plugin p procname procarg: This method can be called from the container context to invoke the plugin p procedure procname. This means that the ctrl_receive_call of the same plugin is invoked in the controller context.
method activate_lever : int -> encap -> encap
Runs a lever function registered in the controller. The int argument identifies the lever. The encap argument is the parameter, and the returned exception is the result. See also Netplex_cenv.Make_lever for a convenient way to create and use levers.
method startup_directory : string
The current directory at Netplex startup time (same view as controller)
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.socket_service.html0000644000175000017500000004366112731530353024214 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.socket_service object
  method create_container :
    Netplex_types.parallelization_type ->
    Netplex_types.socket_service -> Netplex_types.container
  method internal_sockets : (string * Netplex_types.polyserver_box) list
  method name : string
  method on_add : Netplex_types.controller -> unit
  method processor : Netplex_types.processor
  method shutdown : unit -> unit
  method socket_service_config : Netplex_types.socket_service_config
  method sockets : (string * Unix.file_descr array) list
  method startup_directory : string
end
ocamlnet-4.1.2/doc/html-main/type_Uq_socks5.proxy_client.html0000644000175000017500000004362712731530353022736 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_socks5.proxy_client Uq_engines.connect_address ->
object
  method connect :
    Uq_engines.connect_address ->
    Unixqueue.event_system -> Uq_engines.connect_status Uq_engines.engine
  method create_datagram_socket :
    Uq_engines.datagram_type ->
    Unixqueue.event_system ->
    Uq_engines.wrapped_datagram_socket Uq_engines.engine
  method listen :
    Uq_engines.listen_address ->
    Unixqueue.event_system ->
    Uq_engines.server_endpoint_acceptor Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.key_handler-c.html0000644000175000017500000004467112731530353022773 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.key_handler

Class type Nethttp_client.key_handler

class type key_handler = object .. end

method inquire_key : domain:Neturl.url option -> realm:string -> auth:string -> key
The method is called when a new session must be authenticated. The domain is the URI from the request. URIs must have the form "http://host:port/path", i.e. the port is always written out. If the request doesn't have a URI, or if the request is directed to a proxy, domain will be None. The realm parameter is the realm identifier. In auth the name of the authentication method is passed (lowercase characters). The method must search (or interactively ask for) a key, and return it. The key must refer to one of the passed realms. If the method raises Not_found, authentication will fail.
method invalidate_key : key -> unit
The handler is notified that authentication failed for this key
ocamlnet-4.1.2/doc/html-main/type_Rpc_xti_client.html0000644000175000017500000004115612731530353021305 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_xti_client sig val cots_connect : string -> string -> Unix.file_descr endocamlnet-4.1.2/doc/html-main/type_Tls.html0000644000175000017500000004060412731530353017076 0ustar gerdgerd Ocamlnet 4 Reference Manual : Tls sig  endocamlnet-4.1.2/doc/html-main/type_Netmcore_hashtbl.html0000644000175000017500000006212112731530353021613 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_hashtbl sig
  type ('a, 'b, 'h) t
  type ('a, 'b, 'h) t_descr
  val create : Netmcore.res_id -> '-> ('a, 'b, 'h) Netmcore_hashtbl.t
  val clear : ('a, 'b, 'h) Netmcore_hashtbl.t -> unit
  val add : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> '-> unit
  val find_ro : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> 'b
  val find_p : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> ('-> 'r) -> 'r
  val find_c : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> 'b
  val find_all_ro : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> 'b list
  val find_all_p :
    ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> ('b list -> 'r) -> 'r
  val find_all_c : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> 'b list
  val mem_ro : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> bool
  val mem : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> bool
  val remove : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> unit
  val replace : ('a, 'b, 'h) Netmcore_hashtbl.t -> '-> '-> unit
  val iter : ('-> '-> unit) -> ('a, 'b, 'h) Netmcore_hashtbl.t -> unit
  val length : ('a, 'b, 'h) Netmcore_hashtbl.t -> int
  val header : ('a, 'b, 'h) Netmcore_hashtbl.t -> 'h
  val heap : ('a, 'b, 'h) Netmcore_hashtbl.t -> Obj.t Netmcore_heap.heap
  val descr_of_hashtbl :
    ('a, 'b, 'h) Netmcore_hashtbl.t -> ('a, 'b, 'h) Netmcore_hashtbl.t_descr
  val hashtbl_of_descr :
    Netmcore.res_id ->
    ('a, 'b, 'h) Netmcore_hashtbl.t_descr -> ('a, 'b, 'h) Netmcore_hashtbl.t
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_dbi.html0000644000175000017500000005221712731530353020366 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_dbi sig
  module type DBI_DRIVER =
    sig
      type connection
      val connect :
        ?host:string ->
        ?port:string ->
        ?user:string ->
        ?password:string -> string -> Netcgi_dbi.DBI_DRIVER.connection
      val close : Netcgi_dbi.DBI_DRIVER.connection -> unit
      val closed : Netcgi_dbi.DBI_DRIVER.connection -> bool
      val commit : Netcgi_dbi.DBI_DRIVER.connection -> unit
      val ping : Netcgi_dbi.DBI_DRIVER.connection -> bool
      val rollback : Netcgi_dbi.DBI_DRIVER.connection -> unit
    end
  module type DBI_POOL =
    sig
      type connection
      val get :
        Netcgi.cgi ->
        ?host:string ->
        ?port:string ->
        ?user:string ->
        ?password:string -> string -> Netcgi_dbi.DBI_POOL.connection
    end
  module DbiPool :
    functor (Dbi_driver : DBI_DRIVER->
      sig
        type connection = Dbi_driver.connection
        val get :
          Netcgi.cgi ->
          ?host:string ->
          ?port:string ->
          ?user:string -> ?password:string -> string -> connection
      end
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_digest_http.Digest.html0000644000175000017500000004065612731530353023542 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http.Digest Nethttp.HTTP_CLIENT_MECHANISMocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.http_engine_config.html0000644000175000017500000004525712731530353025314 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_engine_config object
  method config_announce_server : Nethttpd_kernel.announcement
  method config_cgi : Netcgi.config
  method config_error_response :
    Nethttpd_types.error_response_params -> string
  method config_input_flow_control : bool
  method config_limit_pipeline_length : int
  method config_limit_pipeline_size : int
  method config_log_access : Nethttpd_types.full_info -> unit
  method config_log_error : Nethttpd_types.request_info -> string -> unit
  method config_max_header_length : int
  method config_max_reqline_length : int
  method config_max_trailer_length : int
  method config_output_flow_control : bool
  method config_suppress_broken_pipe : bool
  method config_timeout : float
  method config_timeout_next_request : float
  method config_tls : Netsys_crypto_types.tls_config option
  method config_tls_cert_props : bool
  method config_tls_remote_user : bool
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.html0000644000175000017500000012414712731530353021652 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor sig
  class type http_processor_config =
    object
      method config_announce_server : Nethttpd_kernel.announcement
      method config_cgi : Netcgi.config
      method config_error_response :
        Nethttpd_types.error_response_params -> string
      method config_limit_pipeline_length : int
      method config_limit_pipeline_size : int
      method config_log_access : Nethttpd_types.full_info -> unit
      method config_log_error : Nethttpd_types.request_info -> string -> unit
      method config_max_header_length : int
      method config_max_reqline_length : int
      method config_max_trailer_length : int
      method config_suppress_broken_pipe : bool
      method config_timeout : float
      method config_timeout_next_request : float
      method config_tls : Netsys_crypto_types.tls_config option
      method config_tls_cert_props : bool
      method config_tls_remote_user : bool
    end
  val default_http_processor_config : Nethttpd_reactor.http_processor_config
  class modify_http_processor_config :
    ?modify_http_protocol_config:(Nethttpd_kernel.http_protocol_config ->
                                  Nethttpd_kernel.http_protocol_config) ->
    ?config_timeout_next_request:float ->
    ?config_timeout:float ->
    ?config_cgi:Netcgi.config ->
    ?config_error_response:(Nethttpd_types.error_response_params -> string) ->
    ?config_log_error:(Nethttpd_types.request_info -> string -> unit) ->
    ?config_log_access:(Nethttpd_types.full_info -> unit) ->
    ?config_tls_cert_props:bool ->
    ?config_tls_remote_user:bool ->
    Nethttpd_reactor.http_processor_config -> http_processor_config
  class type http_reactor_config =
    object
      method config_announce_server : Nethttpd_kernel.announcement
      method config_cgi : Netcgi.config
      method config_error_response :
        Nethttpd_types.error_response_params -> string
      method config_limit_pipeline_length : int
      method config_limit_pipeline_size : int
      method config_log_access : Nethttpd_types.full_info -> unit
      method config_log_error : Nethttpd_types.request_info -> string -> unit
      method config_max_header_length : int
      method config_max_reqline_length : int
      method config_max_trailer_length : int
      method config_reactor_synch :
        [ `Close | `Connection | `Flush | `Write ]
      method config_suppress_broken_pipe : bool
      method config_timeout : float
      method config_timeout_next_request : float
      method config_tls : Netsys_crypto_types.tls_config option
      method config_tls_cert_props : bool
      method config_tls_remote_user : bool
    end
  val default_http_reactor_config : Nethttpd_reactor.http_reactor_config
  class modify_http_reactor_config :
    ?modify_http_protocol_config:(Nethttpd_kernel.http_protocol_config ->
                                  Nethttpd_kernel.http_protocol_config) ->
    ?modify_http_processor_config:(Nethttpd_reactor.http_processor_config ->
                                   Nethttpd_reactor.http_processor_config) ->
    ?config_reactor_synch:[ `Close | `Connection | `Flush | `Write ] ->
    Nethttpd_reactor.http_reactor_config -> http_reactor_config
  class type internal_environment =
    object
      method cgi_auth_type : string
      method cgi_gateway_interface : string
      method cgi_https : bool
      method cgi_path_info : string
      method cgi_path_translated : string
      method cgi_properties : (string * string) list
      method cgi_property : ?default:string -> string -> string
      method cgi_query_string : string
      method cgi_remote_addr : string
      method cgi_remote_host : string
      method cgi_remote_ident : string
      method cgi_remote_user : string
      method cgi_request_method : string
      method cgi_request_uri : string
      method cgi_script_name : string
      method cgi_server_name : string
      method cgi_server_port : int option
      method cgi_server_protocol : string
      method cgi_server_software : string
      method config : Netcgi.config
      method cookie : string -> Netcgi.Cookie.t
      method cookies : Netcgi.Cookie.t list
      method input_body_size : int64
      method input_channel : Netchannels.in_obj_channel
      method input_content_length : int
      method input_content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method input_content_type_string : string
      method input_header : Netmime.mime_header
      method input_header_field : ?default:string -> string -> string
      method input_header_fields : (string * string) list
      method log_access : unit -> unit
      method log_error : string -> unit
      method log_props : (string * string) list -> unit
      method multiple_input_header_field : string -> string list
      method multiple_output_header_field : string -> string list
      method out_channel : Netchannels.out_obj_channel
      method output_ch : Netchannels.out_obj_channel
      method output_header : Netmime.mime_header
      method output_header_field : ?default:string -> string -> string
      method output_header_fields : (string * string) list
      method output_state : Nethttpd_types.output_state ref
      method protocol : Nethttp.protocol
      method remote_socket_addr : Unix.sockaddr
      method req_method : Nethttp.http_method
      method request_body_rejected : bool
      method response : Nethttpd_kernel.http_response
      method send_file : Unix.file_descr -> int64 -> unit
      method send_output_header : unit -> unit
      method server_socket_addr : Unix.sockaddr
      method set_multiple_output_header_field : string -> string list -> unit
      method set_output_header_field : string -> string -> unit
      method set_output_header_fields : (string * string) list -> unit
      method set_status : Nethttp.http_status -> unit
      method tls_session_props : Nettls_support.tls_session_props option
      method unlock : unit -> unit
      method user_agent : string
    end
  class http_environment :
    #Nethttpd_reactor.http_processor_config ->
    string ->
    string ->
    Nethttp.protocol ->
    Nethttp.http_header ->
    Unix.sockaddr ->
    Unix.sockaddr ->
    Netchannels.in_obj_channel ->
    int64 Pervasives.ref ->
    Netchannels.out_obj_channel ->
    Nethttpd_types.output_state Pervasives.ref ->
    Nethttpd_kernel.http_response ->
    (unit -> unit) ->
    bool Pervasives.ref ->
    int64 -> Nettls_support.tls_session_props option -> internal_environment
  class type http_reactive_request =
    object
      method accept_body : unit -> unit
      method environment : Nethttpd_types.extended_environment
      method finish : unit -> unit
      method finish_request : unit -> unit
      method reject_body : unit -> unit
    end
  class http_reactor :
    ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) ->
    #Nethttpd_reactor.http_reactor_config ->
    Unix.file_descr ->
    object
      method close : unit -> unit
      method next_request :
        unit -> Nethttpd_reactor.http_reactive_request option
    end
  val process_connection :
    ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) ->
    #Nethttpd_reactor.http_reactor_config ->
    Unix.file_descr -> 'Nethttpd_types.http_service -> unit
  module Debug : sig val enable : bool Pervasives.ref end
  val logged_error_response :
    Unix.sockaddr ->
    Unix.sockaddr ->
    (string * string) option ->
    int64 ->
    bool ->
    Nethttp.http_status ->
    Nethttp.http_header option ->
    string option ->
    Nethttpd_types.extended_environment option ->
    Nethttpd_kernel.http_response option ->
    Nethttpd_reactor.http_processor_config -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_pmanage.html0000644000175000017500000004761312731530353021320 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pmanage sig
  type pm_obj =
      [ `File of string
      | `Posix_sem of string
      | `Posix_shm of string
      | `Sem_cont of string ]
  class type pmanage =
    object
      method register : Netsys_pmanage.pm_obj list -> unit
      method register_file : string -> unit
      method register_posix_sem : string -> unit
      method register_posix_shm : string -> unit
      method register_sem_cont : string -> unit
      method registered : Netsys_pmanage.pm_obj list
      method unlink : unit -> unit
      method unregister_file : string -> unit
      method unregister_posix_sem : string -> unit
      method unregister_posix_shm : string -> unit
      method unregister_sem_cont : string -> unit
    end
  val pmanage : string -> Netsys_pmanage.pmanage
  val fake_pmanage : unit -> Netsys_pmanage.pmanage
  val unlink_this : Netsys_pmanage.pm_obj -> unit
end
ocamlnet-4.1.2/doc/html-main/Netglob.glob_fsys-c.html0000644000175000017500000004524612731530353021102 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.glob_fsys

Class type Netglob.glob_fsys

class type glob_fsys = object .. end
Filesystem primitives. This is intentionally not the same as Netfs.stream_fs because only a few access functions are needed here, and because the functions here should also be capable of accessing relative paths (not starting with /). It is possible to turn a Netfs.stream_fs into Netglob.glob_fs by calling Netglob.of_stream_fs.

method path_encoding : Netconversion.encoding option
Paths of filesystems may be encoded
method read_dir : string -> string list
Returns the file names contained in the directory, without path. The names "." and ".." should be returned. It is acceptable to return the empty list for an unreadable directory.
method file_is_dir : string -> bool
Whether the file name is valid and a directory, or a symlink to a directory.
method file_exists : string -> bool
Whether the file name is valid and refers to an existing file, or to a symlink pointing to an existing file.
ocamlnet-4.1.2/doc/html-main/Netaux.html0000644000175000017500000004254712731530353016547 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaux

Module Netaux

module Netaux: sig .. end
Internal auxiliary functions

This is an internal module.


module KMP: sig .. end
module ArrayAux: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netpop.connect.html0000644000175000017500000004126412731530353021234 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpop.connect ?proxy:#Uq_engines.client_endpoint_connector ->
Uq_engines.connect_address -> float -> Netpop.client
ocamlnet-4.1.2/doc/html-main/type_Gssapi.html0000644000175000017500000004060712731530353017565 0ustar gerdgerd Ocamlnet 4 Reference Manual : Gssapi sig  endocamlnet-4.1.2/doc/html-main/Netcgi.mime_argument-c.html0000644000175000017500000004242312731530353021555 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.mime_argument

Class Netcgi.mime_argument

class mime_argument : ?work_around_backslash_bug:bool -> string -> Netmime.mime_message -> rw_cgi_argument
Deprecated.Use Netcgi.Argument.mime instead.
Old deprecated MIME argument class.

ocamlnet-4.1.2/doc/html-main/type_Nethttpd_services.html0000644000175000017500000007440112731530353022033 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_services sig
  type host = {
    server_pref_name : string option;
    server_pref_port : int option;
    server_names : (string * int) list;
    server_addresses : (Unix.inet_addr * int) list;
  }
  type 'a host_distributor =
      (Nethttpd_services.host * 'Nethttpd_types.http_service) list
  val host_distributor :
    'Nethttpd_services.host_distributor ->
    [> `Host_distributor of 'Nethttpd_services.host_distributor ]
    Nethttpd_types.http_service
  val default_host :
    ?pref_name:string -> ?pref_port:int -> unit -> Nethttpd_services.host
  val options_service :
    unit -> [> `Options_service ] Nethttpd_types.http_service
  type 'a uri_distributor = (string * 'Nethttpd_types.http_service) list
  val uri_distributor :
    'Nethttpd_services.uri_distributor ->
    [> `Uri_distributor of 'Nethttpd_services.uri_distributor ]
    Nethttpd_types.http_service
  type 'a linear_distributor =
      ((Nethttpd_types.extended_environment -> bool) *
       'Nethttpd_types.http_service)
      list
  val linear_distributor :
    'Nethttpd_services.linear_distributor ->
    [> `Linear_distributor of 'Nethttpd_services.linear_distributor ]
    Nethttpd_types.http_service
  type method_filter =
      [ `Limit of string list | `Limit_except of string list ]
  type 'a method_distributor =
      (Nethttpd_services.method_filter * 'Nethttpd_types.http_service) list
  val method_distributor :
    'Nethttpd_services.method_distributor ->
    [> `Method_distributor of 'Nethttpd_services.method_distributor ]
    Nethttpd_types.http_service
  type file_option =
      [ `Enable_cooked_compression
      | `Enable_gzip
      | `Enable_index_file of string list
      | `Enable_listings of
          Nethttpd_types.extended_environment ->
          Netcgi.cgi_activation -> Nethttpd_services.file_service -> unit
      | `Override_compression_suffixes of (string * string) list ]
  and file_service = {
    file_docroot : string;
    file_uri : string;
    file_suffix_types : (string * string) list;
    file_default_type : string;
    file_options : Nethttpd_services.file_option list;
  }
  val file_service :
    Nethttpd_services.file_service ->
    [> `File_service of Nethttpd_services.file_service ]
    Nethttpd_types.http_service
  val file_translator : Nethttpd_services.file_service -> string -> string
  val simple_listing :
    ?hide:string list ->
    Nethttpd_types.extended_environment ->
    Netcgi.cgi_activation -> Nethttpd_services.file_service -> unit
  type std_activation_options = {
    stdactv_processing : Netcgi.arg_store option;
    stdactv_operating_type : Netcgi.output_type option;
  }
  type std_activation =
      [ `Std_activation of Nethttpd_services.std_activation_options
      | `Std_activation_buffered
      | `Std_activation_tempfile
      | `Std_activation_unbuffered ]
  type 'a dynamic_service = {
    dyn_handler : Nethttpd_types.extended_environment -> '-> unit;
    dyn_activation : Nethttpd_types.extended_environment -> 'a;
    dyn_uri : string option;
    dyn_translator : string -> string;
    dyn_accept_all_conditionals : bool;
  } constraint 'a = #Netcgi.cgi_activation
  val std_activation :
    Nethttpd_services.std_activation ->
    Nethttpd_types.extended_environment -> Netcgi.cgi_activation
  val dynamic_service :
    (#Netcgi.cgi_activation as 'a) Nethttpd_services.dynamic_service ->
    [> `Dynamic_service of 'Nethttpd_services.dynamic_service ]
    Nethttpd_types.http_service
  type ac_by_host_rule = [ `Allow of string list | `Deny of string list ]
  type 'a ac_by_host =
      Nethttpd_services.ac_by_host_rule * 'Nethttpd_types.http_service
  val ac_by_host :
    'Nethttpd_services.ac_by_host ->
    [> `Ac_by_host of 'Nethttpd_services.ac_by_host ]
    Nethttpd_types.http_service
  val read_media_types_file : string -> (string * string) list
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi.std_activation-c.html0000644000175000017500000004277512731530353024605 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi.std_activation

Class Netcgi1_compat.Netcgi.std_activation

class std_activation : ?env:Netcgi1_compat.Netcgi_env.cgi_environment -> ?processing:string -> Netmime.mime_header -> argument_processing -> ?operating_type:operating_type -> unit -> Netcgi1_compat.Netcgi_types.cgi_activation

ocamlnet-4.1.2/doc/html-main/Nettls_gnutls.Symmetric_crypto.html0000644000175000017500000006107312731530353023516 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.Symmetric_crypto

Module Nettls_gnutls.Symmetric_crypto

module Symmetric_crypto: Netsys_crypto_types.SYMMETRIC_CRYPTO 
Symmetric cryptography as provided by GnuTLS and its helper library Nettle


Symmetric cryptographic ciphers.

Users should not call functions of the provider directly, but use Netsys_ciphers, or another higher-level layer.

type scipher 
Describes a cipher
val ciphers : scipher list
List of supported ciphers. OCamlnet implements a number of modes anyway, and it is normally only required to implement "ECB" here. If there is special hardware acceleration, though, it is an option to provide accelerated modes too (e.g. some CPUs support AES-GCM specially).
val find : string * string -> scipher
find (name,mode): Looks up a cipher by name and mode, or raises Not_found
val name : scipher -> string
Returns the name. This should follow the convention <uppercasestring>-<size>, e.g. "AES-128" or "TWOFISH-128". The size is normally the key size.
val mode : scipher -> string
Returns the mode. Modes are "ECB", "CBC", "OFB", "CTR", "STREAM", "GCM".

Note that the mode needs not to deal with padding (this is done on a higher level).

val key_lengths : scipher -> (int * int) list
Supported key lengths as pairs min,max. If there is a recommended key length, this should be the first.
val iv_lengths : scipher -> (int * int) list
Supported iv lengths as pairs min,max. If there is a recommended iv length, this should be the first.
val block_constraint : scipher -> int
The buffers used with encrypt/decrypt must have a length that is a multiple of this number. (In ECB mode, this is the block size.)
val supports_aead : scipher -> bool
Whether this cipher integrates authentication
type scipher_ctx 
A cipher context stores processing data while encrypting or decrypting data
val create : scipher ->
string -> scipher_ctx
create c key: create a new cipher context for key. If not set, the initialization vector is zero, and the header the empty string.
val set_iv : scipher_ctx -> string -> unit
set_iv cctx iv: Sets the initialization vector. This is only allowed before encrypting or decrypting data
val set_header : scipher_ctx -> string -> unit
set_header cctx data: Sets the additional header that is authenticated for AEAD schemes. The header must have been set before starting the encryption or decryption (otherwise it is assumed to be the empty string).

For non-AEAD schemes, the header is ignored for encryption, and must be empty for decryption.

val encrypt : scipher_ctx ->
Netsys_types.memory -> Netsys_types.memory -> unit
encrypt cctx inbuf outbuf: Encrypts the data in inbuf and writes the result into outbuf. Both buffers must have the same size. It is not allowed to pass the same buffer as inbuf and outbuf.

In order to encrypt long texts, it is allowed to call encrypt several times in sequence.

val decrypt : scipher_ctx ->
Netsys_types.memory -> Netsys_types.memory -> bool
decrypt cctx inbuf outbuf: Decrypts the data in inbuf and writes the result into outbuf. Both buffers must have the same size. It is not allowed to pass the same buffer as inbuf and outbuf.

The function returns true on success, and false if a problem is detected.

In order to decrypt long texts, it is allowed to call decrypt several times in sequence.

val mac : scipher_ctx -> string
Returns the MAC for AEAD ciphers. This is updated after encrypt/decrypt. This function fails for non-AEAD ciphers.
ocamlnet-4.1.2/doc/html-main/type_Rpc_transport.Debug.html0000644000175000017500000004100612731530353022216 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_transport.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netsys_gssapi.client_config-c.html0000644000175000017500000004512012731530353023146 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.client_config

Class type Netsys_gssapi.client_config

class type client_config = object .. end

method mech_type : oid
method target_name : (string * oid) option
method initiator_name : (string * oid) option
method initiator_cred : exn option
method privacy : support_level
method integrity : support_level
method flags : (req_flag * support_level) list
ocamlnet-4.1.2/doc/html-main/Shell_uq.job_handler_engine_type-c.html0000644000175000017500000004317012731530353024124 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_uq.job_handler_engine_type

Class type Shell_uq.job_handler_engine_type

class type ['t] job_handler_engine_type = object .. end
This type of engine also returns the job and the job_instance.
Inherits
method job : Shell_sys.job
Returns the called job
method job_instance : Shell_sys.job_instance
Returns the job instance
ocamlnet-4.1.2/doc/html-main/Nethttpd_kernel.modify_http_protocol_config-c.html0000644000175000017500000004360112731530353026440 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.modify_http_protocol_config

Class Nethttpd_kernel.modify_http_protocol_config

class modify_http_protocol_config : ?config_max_reqline_length:int -> ?config_max_header_length:int -> ?config_max_trailer_length:int -> ?config_limit_pipeline_length:int -> ?config_limit_pipeline_size:int -> ?config_announce_server:announcement -> ?config_suppress_broken_pipe:bool -> ?config_tls:Netsys_crypto_types.tls_config option -> http_protocol_config -> http_protocol_config
Modifies the passed config object as specified by the optional arguments

ocamlnet-4.1.2/doc/html-main/Netcgi_dbi.DBI_DRIVER.html0000644000175000017500000004426712731530353021003 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_dbi.DBI_DRIVER

Module type Netcgi_dbi.DBI_DRIVER

module type DBI_DRIVER = sig .. end

type connection 
val connect : ?host:string ->
?port:string ->
?user:string ->
?password:string -> string -> connection
val close : connection -> unit
val closed : connection -> bool
val commit : connection -> unit
val ping : connection -> bool
val rollback : connection -> unit
ocamlnet-4.1.2/doc/html-main/Nettelnet_client.Debug.html0000644000175000017500000004234112731530353021620 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettelnet_client.Debug

Module Nettelnet_client.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module By default, the exchanged Telnet commands are logged. This can be extended by setting the verbose_input and verbose_output options.
ocamlnet-4.1.2/doc/html-main/type_Rpc_proxy.ManagedClient.html0000644000175000017500000006430512731530353023017 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_proxy.ManagedClient sig
  type mclient
  type mclient_config = {
    mclient_rcache : Rpc_proxy.ReliabilityCache.rcache;
    mclient_socket_config : Rpc_client.socket_config;
    mclient_idle_timeout : float;
    mclient_programs : Rpc_program.t list;
    mclient_msg_timeout : float;
    mclient_msg_timeout_is_fatal : bool;
    mclient_exception_handler : (exn -> unit) option;
    mclient_auth_methods : Rpc_client.auth_method list;
    mclient_user_name : string option;
    mclient_initial_ping : bool;
    mclient_max_response_length : int option;
    mclient_mstring_factories : Netxdr_mstring.named_mstring_factories option;
  }
  exception Service_unavailable
  val create_mclient_config :
    ?rcache:Rpc_proxy.ReliabilityCache.rcache ->
    ?socket_config:Rpc_client.socket_config ->
    ?idle_timeout:float ->
    ?programs:Rpc_program.t list ->
    ?msg_timeout:float ->
    ?msg_timeout_is_fatal:bool ->
    ?exception_handler:(exn -> unit) ->
    ?auth_methods:Rpc_client.auth_method list ->
    ?user_name:string option ->
    ?initial_ping:bool ->
    ?max_response_length:int ->
    ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
    unit -> Rpc_proxy.ManagedClient.mclient_config
  val create_mclient :
    Rpc_proxy.ManagedClient.mclient_config ->
    Rpc_client.connector ->
    Unixqueue.event_system -> Rpc_proxy.ManagedClient.mclient
  type state = [ `Connecting | `Down | `Up of Unix.sockaddr option ]
  val mclient_state :
    Rpc_proxy.ManagedClient.mclient -> Rpc_proxy.ManagedClient.state
  val mclient_serial : Rpc_proxy.ManagedClient.mclient -> int
  val pending_calls : Rpc_proxy.ManagedClient.mclient -> int
  val event_system :
    Rpc_proxy.ManagedClient.mclient -> Unixqueue.event_system
  val shut_down : Rpc_proxy.ManagedClient.mclient -> unit
  val sync_shutdown : Rpc_proxy.ManagedClient.mclient -> unit
  val trigger_shutdown :
    Rpc_proxy.ManagedClient.mclient -> (unit -> unit) -> unit
  val record_unavailability : Rpc_proxy.ManagedClient.mclient -> unit
  val enforce_unavailability : Rpc_proxy.ManagedClient.mclient -> unit
  val set_batch_call : Rpc_proxy.ManagedClient.mclient -> unit
  val rpc_engine :
    Rpc_proxy.ManagedClient.mclient ->
    (Rpc_proxy.ManagedClient.mclient -> '-> ((unit -> 'b) -> unit) -> unit) ->
    '-> 'Uq_engines.engine
  val compare :
    Rpc_proxy.ManagedClient.mclient -> Rpc_proxy.ManagedClient.mclient -> int
  type t = mclient
  val use : t -> Rpc_program.t -> unit
  val unbound_sync_call :
    t -> Rpc_program.t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
  val unbound_async_call :
    t ->
    Rpc_program.t ->
    string ->
    Netxdr.xdr_value -> ((unit -> Netxdr.xdr_value) -> unit) -> unit
  val xdr_ctx : t -> Netxdr.ctx
end
ocamlnet-4.1.2/doc/html-main/Netchannels.rec_out_channel_delegation-c.html0000644000175000017500000004255312731530353025304 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.rec_out_channel_delegation

Class Netchannels.rec_out_channel_delegation

class rec_out_channel_delegation : ?close:bool -> rec_out_channel -> rec_out_channel

ocamlnet-4.1.2/doc/html-main/type_Netulex_tut.html0000644000175000017500000004061412731530353020655 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netulex_tut sig  endocamlnet-4.1.2/doc/html-main/type_Netcgi_fcgi.cgi.html0000644000175000017500000005406112731530353021300 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_fcgi.cgi object
  method argument : string -> Netcgi.cgi_argument
  method argument_exists : string -> bool
  method argument_value : ?default:string -> string -> string
  method arguments : Netcgi.cgi_argument list
  method at_exit : (unit -> unit) -> unit
  method data : Netchannels.in_obj_channel
  method data_length : int
  method data_mtime : float
  method environment : Netcgi.cgi_environment
  method finalize : unit -> unit
  method multiple_argument : string -> Netcgi.cgi_argument list
  method out_channel : Netchannels.trans_out_obj_channel
  method output : Netchannels.trans_out_obj_channel
  method request_method :
    [ `DELETE | `GET | `HEAD | `POST | `PUT of Netcgi.cgi_argument ]
  method role : [ `Authorizer | `Filter | `Responder ]
  method set_header :
    ?status:Nethttp.http_status ->
    ?content_type:string ->
    ?content_length:int ->
    ?set_cookie:Nethttp.cookie list ->
    ?set_cookies:Netcgi.Cookie.t list ->
    ?cache:Netcgi.cache_control ->
    ?filename:string ->
    ?language:string ->
    ?script_type:string ->
    ?style_type:string -> ?fields:(string * string list) list -> unit -> unit
  method set_redirection_header :
    ?set_cookies:Netcgi.Cookie.t list ->
    ?fields:(string * string list) list -> string -> unit
  method url :
    ?protocol:Nethttp.protocol ->
    ?with_authority:Netcgi.other_url_spec ->
    ?with_script_name:Netcgi.other_url_spec ->
    ?with_path_info:Netcgi.other_url_spec ->
    ?with_query_string:Netcgi.query_string_spec -> unit -> string
end
ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi_types.html0000644000175000017500000005731612731530353022574 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_types

Module Netcgi1_compat.Netcgi_types

module Netcgi_types: sig .. end

class type simple_message = Netmime.mime_body
type store = [ `File of string | `Memory ] 
Embedded in the single place of use.
type representation = [ `MIME of Netmime.mime_message
| `Simple of simple_message ]
Embedded in the single place of use.
class type cgi_argument = object .. end
Portage: In addition to defining a type, the following cgi_argument also defines a conversion function that allows to connect old scripts to the new infrastructure.
val to_compat_argument : Netcgi.cgi_argument -> cgi_argument
Portage: to_compat_argument a converts a new style argument a to an old style one. Finalizing to_compat_argument a will also finalize a.
val of_compat_argument : cgi_argument -> Netcgi.cgi_argument
Portage: of_compat_argument a converts an old style argument a to a new style one. Finalizing of_compat_argument a will also finalize a.
type cgi_cookie = Nethttp.netscape_cookie = {
   cookie_name : string;
   cookie_value : string;
   cookie_expires : float option;
   cookie_domain : string option;
   cookie_path : string option;
   cookie_secure : bool;
}
type status = Nethttp.http_status 
type request_method = [ `DELETE
| `GET
| `HEAD
| `POST
| `PUT of cgi_argument ]
type cache_control = [ `Max_age of int | `No_cache | `Unspecified ] 
type query_string_spec = [ `Args of cgi_argument list
| `Current
| `Initial
| `None ]
type other_url_spec = [ `Env | `None | `This of string ] 
class type cgi_activation = object .. end
Portage: In addition to defining a type, the following cgi_activation also defines a conversion function that allows to connect old scripts to the new infrastructure.
val to_compat_activation : Netcgi.cgi -> cgi_activation
Portage: to_compat_activation converts a new style cgi object to an old cgi_activation object.
val of_compat_activation : cgi_activation -> Netcgi.cgi
Portage: of_compat_activation converts an old style cgi_activation to a new CGI-like object.
ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.async_in_channel_engine.html0000644000175000017500000004355512731530353025454 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.async_in_channel_engine object
  method abort : unit -> unit
  method can_input : bool
  method close_in : unit -> unit
  method event_system : Unixqueue.event_system
  method input : Bytes.t -> int -> int -> int
  method pos_in : int
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    (unit Uq_engines.engine -> bool) -> unit
  method state : unit Uq_engines.engine_state
end
ocamlnet-4.1.2/doc/html-main/index_exceptions.html0000644000175000017500000014725712731530353020657 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of exceptions

Index of exceptions


A
Abort [Unixqueue]
Event handlers can raise this exception to cancel a group of handlers, events, and resources.
Addressing_method_not_supported [Uq_engines_compat]
Addressing_method_not_supported [Uq_engines]
Raised by client_endpoint_connector and server_endpoint_acceptor to indicate that the passed address is not supported by the class.
Already_installed [Shell_sys]
Raised when the job handlers are already installed
Auth_error [Netldap]
Authentication error
Authentication_error [Netpop]
Authentication_error [Netsmtp]

B
Bad_glob_expr [Netglob]
An syntax error in the glob expression; the argument is the bad expression
Bad_header_field [Nethttp]
Raised when a header field cannot be parsed.
Bad_message [Nethttp_client]
The server sent a message which cannot be interpreted.
Bad_state [Netpop]
Break [Netshm]
Broken_communication [Uq_engines_compat]
Broken_communication [Uq_engines]
Some engines indicate this error when they cannot continue because the other endpoint of communication signals an error.
Buffer_underrun [Netchannels]
Raised by input methods if the internal buffer of the channel is too empty to read even one byte of data.
Byte_order_mark [Netconversion]
Raised when it is tried to get the code point of the BOM at the beginning of the string

C
Cancelled [Uq_engines_compat]
Cancelled [Uq_engines]
The callback function of a multiplex_controller is invoked with this exception if the operation is cancelled.
Cannot_represent [Netnumber]
raised if a conversion can't be done
Cannot_represent [Netconversion]
Raised when a certain Unicode code point cannot be represented in the selected output encoding
Client_is_down [Rpc_client]
The RPC call cannot be performed because the client has been shut down in the meantime.
Closed [Netsys_polypipe]
Closed_channel [Netchannels]
Raised when channel operations are called when the channel is closed
Closed_channel [Uq_engines_compat]
Closed_channel [Uq_engines]
Raised when a method of a closed channel object is called (only channel methods count).
Cluster_service_unavailable [Rpc_proxy.ManagedSet]
Raised by mset_pick when no available endpoint can be found, or all available endpoints have reached their maximum load.
Command_failure [Netchannels]
Raised by close_in or close_out if the channel is connected with another process, and the execution of that process fails.
Communication_error [Rpc_client]
an I/O error happened
Config_error [Netplex_config]
Connection_lost [Rpc_server]
raised by the 'reply' function if the connection to the original caller has been lost in the meantime.
Container_variable_not_found [Netplex_cenv]
The variable does not exist
Container_variable_type_mismatch [Netplex_cenv]
The (dynamically typed) variable has the wrong type
Context [Netsys_gssapi.GSSAPI]
Corrupt_file [Netshm]
Raised when a violation of the object format is detected
Credential [Netsys_gssapi.GSSAPI]
Cursor_out_of_range [Netconversion]
Raised when it is tried to move the cursor beyond the beginning of the string or beyond the end of the string.

D
Deadlock [Netshm]
Raised when a deadlock situation was detected.
Dest_failure [Netxdr]
raised if the dest_* function are applied to non-matching xdr_value

E
EAGAIN_RD [Netsys_types]
EAGAIN_RD [Netsys_crypto_types.TLS_EXCEPTIONS]
EAGAIN_WR [Netsys_types]
A read or write cannot be done because the descriptor is in non-blocking mode and would block.
EAGAIN_WR [Netsys_crypto_types.TLS_EXCEPTIONS]
A read or write cannot be done because the descriptor is in non-blocking mode and would block.
Empty [Netmcore_queue]
Raised when the queue is empty and the operation cannot be done
Empty [Netcamlbox]
End_of_string [Netconversion]
Raised when it is tried to access the character after the end of the string (at position n_max)
Err_status [Netpop]
Error [Rpc_transport]
Passed back as `Error.
Error [Nettls_gnutls_bindings]
Error [Netulex.Ulexing]
Lexical error
Executable_not_found [Shell_sys]
Raised when an executable file cannot be found; the argument is the search name
Extension_not_found [Netx509]
Extensions_not_supported [Netmech_scram]
Returned by clients when the server enables an unsupported extension.

F
FTP_error [Netftp_client]
Something went wrong, often on socket level
FTP_method_perm_failure [Netftp_client]
FTP_method_temp_failure [Netftp_client]
FTP_method_unexpected_reply [Netftp_client]
These exceptions may be raised during execution by the FTP method.
FTP_protocol_violation [Netftp_client]
The server violates the FTP specification
FTP_timeout [Netftp_client]
A timeout on the control or data connection (this is a fatal error)
Fatal_error [Shell_sys]
An error is fatal if it is not possible to recover from it in a predictable manner.

G
GSSAPI_error [Netftp_client]
An error on GSSAPI level

H
HTTP [Netcgi_common]
Exception raised by various functions of this library to return to the user agent an appropriate error page with the specified http-status (this exception must be caught by the connector and a default answer sent).
Header_too_short [Netasn1]
Host_not_found [Uq_resolver]
This host cannot be resolved
Http_error [Nethttp_client]
Deprecated in the scope of pipeline.
Http_protocol [Nethttp_client]
The request could not be processed because the exception condition was raised.

I
Immutable [Netmime]
Raised if it is tried to modify a read-only value.
Integrity_error [Netmech_scram.Cryptosystem]
Invalid_encoding [Netmech_scram]
Returned by clients when something cannot be decoded.
Invalid_server_signature [Netmech_scram]
Returned by clients when the signature sent by the server is invalid (i.e.
Invalid_username_encoding [Netmech_scram]
Returned by clients when the username does not match the requirements.

K
Keep_call [Rpc_client]
This exception can be raised by the callback function that is invoked when the server response arrives.

L
LDAP_error [Netldap]
The server indicates a (logical) error.
Late_drop [Rpc_server]
This can be raised in encryption/decryption functions to prevent that a response is sent.
Line_too_long [Netmime_string]
Raised when the hard limit of the line length is exceeded
Line_too_long [Uq_io]
May be raised by Uq_io.input_line_e

M
Malformed_URL [Neturl]
Raised by a number of functions when encountering a badly formed URL.
Malformed_code [Netconversion]
Raised when an illegal byte sequence is found
Malformed_code_at [Netconversion]
An illegal byte sequence is found at this byte position
Mem_not_supported [Uq_engines_compat]
Mem_not_supported [Uq_multiplex]
May be raised by multiplex controller methods start_mem_reading and start_mem_writing if these methods are not supported for the kind of file descriptor
Mem_not_supported [Uq_engines]
Message_lost [Rpc_client]
got EOF when some pending procedure calls were not replied or even sent
Message_timeout [Rpc_client]
After all retransmissions, there was still no reply
Message_too_big [Netcamlbox]

N
Name [Netsys_gssapi.GSSAPI]
Name_resolution_error [Nethttp_client]
Could not resolve this name - same as Uq_engines.Host_not_found
Next [Netshm]
No_Unix_process_group [Shell_sys]
Raised by functions referring to Unix process groups when the job has not been started in its own process group.
No_reply [Nethttp_client]
There was no response to the request because some other request failed earlier and it was not allowed to send the request again.
No_resource [Netmcore]
No such resource, or no resource of the expected type
Not_implemented [Netcgi1_compat]
Raised by some functions/exceptions when a feature of the old model cannot be implemented in the new model or vice versa
Not_in_container_thread [Netplex_cenv]
Raised when the caller's thread is not a container thread
Notification [Netldap]
An unsolicited notification.
Null_pointer [Nettls_gnutls_bindings]
Null_pointer [Netgss_bindings]

O
Out_of_handlers [Equeue]
Raised by run when the event source adds new events to the queue but there are no event handlers to process them
Out_of_pool_memory [Netmcore_mempool]
Out_of_range [Netasn1]
Out_of_range [Netnumber]
raised if string position out of range
Out_of_space [Netsys_mem]
Oversized [Netcgi.Argument]
Oversized [Netcgi_common]

P
Parse_error [Netasn1]
Byte position in string
Parse_error [Netaddress]
A parsing error.
Partial_character [Netconversion]
Raised when the last character of the string is an incomplete multi-byte character, and it is tried to get the code point (using uchar_at).
Permanent_error [Netsmtp]
Protocol_error [Netmech_scram]
Returned by clients when the server violates the protocol.
Protocol_error [Netpop]
Protocol_error [Netsmtp]
Proxy_error [Nethttp_client]
An error status from a proxy.

R
Recv_queue_empty [Nethttpd_kernel]
Redirect_request [Nethttpd_types]
The "early" redirect is only allowed in stage 1 of HTTP processing.
Redirect_response [Nethttpd_types]
The "late" redirect is only allowed in stage 3 of HTTP processing.
Reject [Equeue]
May be raised by event handlers to reject events
Response_dropped [Rpc_client]
Drop reason: The response exceeded the configured maximum message size
Response_too_large [Nethttp_client]
The length of the response exceeds the configured maximum
Rpc_cannot_unpack [Rpc]
RPC protocol error (bad data)
Rpc_server [Rpc]
an exception generated by the RPC server

S
SASLprepError [Netsaslprep]
Raised when a string cannot be transformed
Send_queue_empty [Nethttpd_kernel]
Server_error [Netmech_scram]
Returned by clients when the server sent an error code
Service_unavailable [Rpc_proxy.ManagedClient]
Procedure calls may end with this exception when the reliability cache disables the service
Sharedvar_no_permission [Netplex_sharedvar]
It is not allowed to set the value
Sharedvar_not_found [Netplex_sharedvar]
The variable does not exist.
Sharedvar_null [Netplex_sharedvar]
The initial value of a shared exception variable
Sharedvar_type_mismatch [Netplex_sharedvar]
The (dynamically typed) variable has the wrong type (string/exn)
Short_memory_buffer [Nettls_gnutls_bindings]
Shutdown_not_supported [Netsys]
See gshutdown
Socks_error [Uq_socks5]
Raised when error messages of the SOCKS proxy are received, or because of other SOCKS-related problems.
Standard_response [Nethttpd_types]
Some HTTP containers allow you to raise this exception.
Subprocess_error [Shell]
The string contains the called commands in a readable representation.

T
TLS_error [Netsys_types]
A fatal error occurred (i.e.
TLS_error [Netsys_crypto_types.TLS_EXCEPTIONS]
A fatal error occurred (i.e.
TLS_switch_request [Netsys_types]
The server requested a rehandshake (this exception is thrown in the client)
TLS_switch_request [Netsys_crypto_types.TLS_EXCEPTIONS]
The server requested a rehandshake (this exception is thrown in the client)
TLS_switch_response [Netsys_types]
The client accepted or denied a rehandshake (this exception is thrown in the server).
TLS_switch_response [Netsys_crypto_types.TLS_EXCEPTIONS]
The client accepted or denied a rehandshake (this exception is thrown in the server).
TLS_warning [Netsys_types]
A non-fatal error occurred.
TLS_warning [Netsys_crypto_types.TLS_EXCEPTIONS]
A non-fatal error occurred.
Telnet_protocol [Nettelnet_client]
Wrapper for exceptions that already passed the exception handler.
Terminate [Equeue]
May be raised by event handlers to accept events while terminating themselves
Timeout [Netldap]
Raised when the TCP connection times out.
Timeout [Nethttp_client]
A timeout.
Timeout [Uq_engines_compat]
Timeout [Uq_engines]
Used by input_engine and output_engine to indicate timeouts
Too_many_arguments [Netcgi_common]
Hit the limit max_arguments
Too_many_descriptors [Netsys_pollset_win32]
Too_many_redirections [Nethttp_client]
While following redirections the limit has been reached
Transient_error [Netsmtp]
Type_mismatch [Netplex_encap]
Raised when an encapulated type is tried to be unwrapped by the wrong encapsulation module

U
URL_syntax_error [Nethttp_client]
This URL cannot be parsed after a redirection has been followed.
Unbound_exception [Rpc_client]
This exception can be raised by the callback function that is invoked when the server response arrives.
Unsupported_algorithm [Netx509_pubkey_crypto]
Raises if the crypto backend does not support an algorithm
Unsupported_expr [Netglob]
The notations :class:, .symbol., =eqclass= inside ... are not supported by this implementation.

W
Watchdog_timeout [Uq_engines_compat]
Watchdog_timeout [Uq_engines]
Used by the watchdog engine to indicate a timeout.

X
Xdr_failure [Netxdr]
Usually a problem during packing
Xdr_format [Netxdr]
Format error found during unpacking a string
Xdr_format_message_too_long [Netxdr]
The message is too long and cannot be packed into a string
ocamlnet-4.1.2/doc/html-main/type_Netcgi_apache.Apache.Table.html0000644000175000017500000004642712731530353023265 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache.Table sig
  type t
  external get : Netcgi_apache.Apache.Table.t -> string -> string
    = "netcgi2_apache_table_get"
  external get_all : Netcgi_apache.Apache.Table.t -> string -> string list
    = "netcgi2_apache_table_get_all"
  external fields : Netcgi_apache.Apache.Table.t -> (string * string) list
    = "netcgi2_apache_table_fields"
  external clear : Netcgi_apache.Apache.Table.t -> unit
    = "netcgi2_apache_table_clear"
  external set : Netcgi_apache.Apache.Table.t -> string -> string -> unit
    = "netcgi2_apache_table_set"
  external add : Netcgi_apache.Apache.Table.t -> string -> string -> unit
    = "netcgi2_apache_table_add"
  external unset : Netcgi_apache.Apache.Table.t -> string -> unit
    = "netcgi2_apache_table_unset"
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto.html0000644000175000017500000004576212731530353021233 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto sig
  val current_tls : unit -> (module Netsys_crypto_types.TLS_PROVIDER)
  val current_tls_opt :
    unit -> (module Netsys_crypto_types.TLS_PROVIDER) option
  val current_symmetric_crypto :
    unit -> (module Netsys_crypto_types.SYMMETRIC_CRYPTO)
  val current_pubkey_crypto :
    unit -> (module Netsys_crypto_types.PUBKEY_CRYPTO)
  val current_digests : unit -> (module Netsys_crypto_types.DIGESTS)
  val set_current_tls : (module Netsys_crypto_types.TLS_PROVIDER-> unit
  val set_current_symmetric_crypto :
    (module Netsys_crypto_types.SYMMETRIC_CRYPTO-> unit
  val set_current_digests : (module Netsys_crypto_types.DIGESTS-> unit
  val set_current_pubkey_crypto :
    (module Netsys_crypto_types.PUBKEY_CRYPTO-> unit
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.get_call.html0000644000175000017500000004060512731530353023072 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.get_call Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Uq_engines.Debug.html0000644000175000017500000004216012731530353020414 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.Debug

Module Uq_engines.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.head.html0000644000175000017500000004067112731530353022224 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.head string -> Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Netlog.Debug.html0000644000175000017500000006602212731530353017552 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netlog.Debug

Module Netlog.Debug

module Debug: sig .. end


Controlling messages for debugging Ocamlnet

Controlling messages for debugging Ocamlnet

Many Ocamlnet modules can emit debug messages. For a module M (e.g. Rpc_client) there is usually a sub module M.Debug providing functions controlling the debug messages. These functions send the messages to this Debug module, and from here they are forwarded to Netlog.log (with a level of `Debug).

In this module everything is by default initialized to enable debug messages (i.e., current_dlogger is set to fwd_dlogger, and this function sends the messages to current_logger where they are printed by channel_logger stderr `Debug). However, the debugged modules also need to be enabled individually. One can do this by setting the variable M.Debug.enable to true, or by calling enable_module or enable_all (see below).

Although this debug interface is mainly intended for Ocamlnet itself, it is not restricted to this. In order to use it for a user module, one has to register the boolean variable that controls whether debug messages are enabled (see register_module below). This should be done at module initialization time, and before any thread is spawned.

type dlogger = string -> string -> unit 
Debug logger: The first string is the module name, and the second is the message
val fwd_dlogger : dlogger
The standard debug logger simply prepends the module name to the message (separated by ": "), and calls the current logger to print it
val null_dlogger : dlogger
The "logger" not printing anything
val current_dlogger : dlogger Pervasives.ref
The current debug logger. This is initialized to fwd_dlogger at program startup. Set this variable to null_logger to completely turn off debug logging of Ocamlnet.
val log : string -> string -> unit
Writes a log message
val logf : string -> ('a, unit, string, unit) Pervasives.format4 -> 'a
Writes a log message like printf
val enable_module : string -> unit
val disable_module : string -> unit
Enable or disable the passed module M (e.g. enable_module "Rpc_client"). No exception is raised when the module name is invalid! Because of this, it is usually safer to change the variable M.Debug.enable directly (e.g. Rpc_client.Debug.enable := true).
val enable_all : unit -> unit
Enable all modules
val disable_all : unit -> unit
Disable all modules (the default)
val names : unit -> string list
Return the possible module names for enable_module and disable_module

For debugged Ocamlnet modules


val register_module : string -> bool Pervasives.ref -> unit
Registers the enable variable of the named module
val mk_dlog : string -> bool Pervasives.ref -> string -> unit
let dlog = mk_dlog "M" enable: The conditional debug function
val mk_dlogr : string -> bool Pervasives.ref -> (unit -> string) -> unit
let dlogr = mk_dlog "M" enable: The conditional debug function

File descriptor tracking



File descriptor tracking



Netlog.Debug also has a little hash table that maps file descriptors to an info record. This allows it to track file descriptors more easily, and to find file descriptor leaks, and "double close" bugs. All long-living descriptors managed by Ocamlnet should go into this table.
type serial 
A serial number for the optional tracking of ownership
val new_serial : unit -> serial
Create new serial number
val track_fd : ?update:bool ->
?anchor:'a ->
?sn:serial ->
owner:string -> descr:string -> Unix.file_descr -> unit
track_fd ~owner ~descr fd: Enters the descriptor fd into the descriptor table. The owner string should be set to the module name. In descr one can give additional information, e.g. about the purpose, and details like the file name.

It is not an error if there is also an entry for the descriptor fd. However, a warning is emitted (using the debug logger). By setting update to true, this warning can be suppressed. The old entry is overwritten by the new one.

The anchor can be an arbitrary boxed value. When the garbage collector calls the finaliser for anchor the descriptor is marked as dead, and will be tagged in the fd_table as such.

By setting sn to a new serial number, the knowledge of this number is required to update the descriptor entry later, and to release the descriptor. If the entry is tried to be updated or released with the wrong serial number, a warning is emitted (to the debug logger).

val release_fd : ?sn:serial -> ?force:bool -> Unix.file_descr -> unit
Removes this descriptor from the descriptor table.

It is not an error if the descriptor does not exist in the table. However, a warning is emitted (using the debug logger).

release_fd must be invoked before the descriptor is actually closed.

force: If set, all warnings are suppressed

val fd_string : ?owner:bool -> ?descr:bool -> Unix.file_descr -> string
Return a string for generating debug messages. By default, the string only includes the numeric descriptor value.

If owner is set to true, the string also includes the owner. If descr is set to true, the string also includes the description.

The full version of this string looks like "76(Http_client - 87.65.213.67:80)". An untracked descriptor looks like "76(?)".

val fd_table : unit -> string list
Returns the table of descriptors as list of lines. One can easily print them to stdout using List.iter print_endline (fd_table()).
val enable_fd_tracking : bool Pervasives.ref
By setting to true, each track_fd and release_fd is logged.
ocamlnet-4.1.2/doc/html-main/type_Nethttp.http_trailer_ro.html0000644000175000017500000004060312731530353023161 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.http_trailer_ro Netmime.mime_header_roocamlnet-4.1.2/doc/html-main/Nethttpd_engine.http_request_notification-c.html0000644000175000017500000004511412731530353026127 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_request_notification

Class type Nethttpd_engine.http_request_notification

class type http_request_notification = object .. end

Notification that the whole request has arrived

This object notifies the user that the request has fully arrived (including the body if accepted), and can now be responded. The environment is the same as in the request header notification, but the channels are now unlocked.

method req_state : engine_req_state
Returns the request processing state which is `Received_request at the moment when this notification is delivered.
method environment : extended_async_environment
The request environment. See above.
method schedule_finish : unit -> unit
Schedules that the request is finished. See above.
ocamlnet-4.1.2/doc/html-main/type_Nettls_gnutls.GNUTLS_ENDPOINT.html0000644000175000017500000004122612731530353023515 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.GNUTLS_ENDPOINT sig module TLS : GNUTLS_PROVIDER val endpoint : TLS.endpoint endocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.async_out_channel_engine.html0000644000175000017500000004361712731530353027023 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.async_out_channel_engine object
  method abort : unit -> unit
  method can_output : bool
  method close_out : unit -> unit
  method event_system : Unixqueue.event_system
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method pos_out : int
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : (unit engine -> bool) -> unit
  method state : unit engine_state
end
ocamlnet-4.1.2/doc/html-main/Foreword.html0000644000175000017500000006006212731530353017062 0ustar gerdgerd Ocamlnet 4 Reference Manual : Foreword

Foreword


Foreword

A few words about this and that...

Organization of Ocamlnet

Ocamlnet has grown a lot, and it may look a bit confusing to beginners. Fortunately, Ocamlnet follows a few organizational principles:

String routines are often factored out

String routines like URL parsing, buffer handling, message decoding etc. are often not directly included in the protocol interpreter, but defined in separate modules. Actually, there is a whole library, Netstring, only consisting of string functions.

The advantage is obvious: String functions can be reused, for example from within clients and servers, but also from user code wishing to do certain string manipulations directly.

Common types ease plugging parts together

It is encouraged that one can plug together various parts of Ocamlnet to create new functionality. Ocamlnet tries to use the same types for the same kind of values throughout the whole library to make this easier. Examples:

  • Netmime defines mail messages, but as this data format is also used in HTTP, Nethttp_client represents requests and responses with the same classes
  • Netchannels defines object-oriented I/O channels. These are used almost everywhere in Ocamlnet.
Common infrastructure for logging, exception printing, and signal handling

All Ocamlnet modules use this infrastructure:

  • Netlog is a simple logging module and redirector
  • Netexn provides extended support for exception printing
  • Netsys_signal is a little framework for coordinating signal handlers
These modules are as simple as possible to do their task. It is up to the user to extend them, e.g. by plugging in fancier logging modules.

Pluggable name resolver

All Ocamlnet modules use a single module for network name resolution:

  • Uq_resolver defines a type for resolvers, and the current default resolver
Preference of asynchronous protocol interpreters

A number of protocol interpreters are written in asynchronous style. This is generally preferred because of better timeout and error handling, but also because it makes it possible to run several instances of these protocol interpreters in the same thread concurrently (i.e. it is a kind of micro-threading). Ocamlnet includes the Equeue library as support library for asynchronous network programming (see Equeue_intro for more information).

Nevertheless, nobody is forced to use these protocol interpreters asynchronously. There is always also a simple way for synchronous calls (i.e. where the execution of the caller blocks until the network function is completely done).

Parallelization is done at a single place

In other network environments, often every protocol interpreter defines functions for parallelizing its use, e.g. by using thread pools. In Ocamlnet we avoid that. For parallelization there is only the Netplex library which supports both multi-threading and multi-processing.

It is easy to use Netplex with the available server implementations:

  • Nethttpd_plex allows it to run a webserver inside Netplex
  • Rpc_netplex can run SunRPC servers inside Netplex
  • Netcgi_plex can run FCGI, SCGI, and AJP connectors inside Netplex
There are a number of advantages. First, one can easily create compound servers running a number of protocol interpreters at the same time. All interpreters are configured from a single place. All interpreters use the same logging mechanism. All interpreters share the same workload mechanism. All interpreters can be administered with the same command, netplex-admin.

Second, one does not need to develop the parallelization code anew for each protocol implementation. It is difficult enough.

Third, this approach makes it first possible to provide a serious implementation of multi-processing. For this kind of parallelism, more coordination between the interacting components is required than for multi-threading. For example, when child processes are forked off, it must be clear which protocol interpreter are run within them.

At Mylife, we have developed a server program that integrates dozens of different protocols under the same roof. The Netplex approach is scalable!

Pick what you like, and omit things you don't understand

Ocamlnet is modular enough that one can cherry-pick the parts one needs. After all, it is only a library, i.e. a collection of Ocaml modules, and by using one module there is no strict requirement to use another module.

Of course, there is also a "use hierarchy" in Ocamlnet - the HTTP code uses Equeue, for instance. However, the user of HTTP needs not to know this or care about it. Equeue is then simply an internally used helper library.

Future Directions

Ocamlnet is already focused on Internet protocols. Current activities especially try to

  • focus even more on datacenters as computing environments (affecting scalability, selection of protocols, etc.)
  • provide more support to get high availability (e.g. utilities to detect failed services quickly, or a common directory service)
  • improve multi-core support (especially speed up interprocess communication)

Libraries Using Ocamlnet

There a number of libraries using and extending Ocamlnet:


ocamlnet-4.1.2/doc/html-main/type_Unixqueue.standard_event_system.html0000644000175000017500000004070112731530353024726 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.standard_event_system unit -> Unixqueue.event_systemocamlnet-4.1.2/doc/html-main/Uq_engines_compat.timeout_engine-c.html0000644000175000017500000004250412731530353024166 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.timeout_engine

Class Uq_engines_compat.timeout_engine

class ['a] timeout_engine : float -> exn -> 'a engine -> ['a] engine

ocamlnet-4.1.2/doc/html-main/type_Uq_engines.async_out_channel_engine.html0000644000175000017500000004361012731530353025451 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.async_out_channel_engine object
  method abort : unit -> unit
  method can_output : bool
  method close_out : unit -> unit
  method event_system : Unixqueue.event_system
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method pos_out : int
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : (unit engine -> bool) -> unit
  method state : unit engine_state
end
ocamlnet-4.1.2/doc/html-main/Nethttp_fs.html0000644000175000017500000007724712731530353017426 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_fs

Module Nethttp_fs

module Nethttp_fs: sig .. end
HTTP filesystem


This module makes an HTTP file server accessible via a Netfs.stream_fs object, supporting

  • reading files
  • identifying and reading directories (if the server generates index pages for directories, see below for more information)
  • writing files (if the server implements PUT)
  • removing files (if the server implements DELETE)
One has to specify a base URL b, and the access of a file with path p is translated to the URL b ^ p. Note that p cannot include web parameters ("?" strings), and hash marks are also not supported.

A directory is recognized by appending a slash to the URL, and checking whether the URL exists.

The contents of a directory are determined by loading the directory URL, analyzing the HTML page, and checking for the presence of hyperlinks that do not contain slashes (or at most a trailing slash). Only hyperlinks of "A" elements are accepted.

Almost every web server can be configured to generate directory listings that conform to this format. For example, Apache provides this through the module mod_autoindex.

There is an extension to this class for WebDAV:

  • Webdav provides an extension of Nethttp_fs for the full WebDAV set of filesystem operations


This module makes an HTTP file server accessible via a Netfs.stream_fs object, supporting

  • reading files
  • identifying and reading directories (if the server generates index pages for directories, see below for more information)
  • writing files (if the server implements PUT)
  • removing files (if the server implements DELETE)
One has to specify a base URL b, and the access of a file with path p is translated to the URL b ^ p. Note that p cannot include web parameters ("?" strings), and hash marks are also not supported.

A directory is recognized by appending a slash to the URL, and checking whether the URL exists.

The contents of a directory are determined by loading the directory URL, analyzing the HTML page, and checking for the presence of hyperlinks that do not contain slashes (or at most a trailing slash). Only hyperlinks of "A" elements are accepted.

Almost every web server can be configured to generate directory listings that conform to this format. For example, Apache provides this through the module mod_autoindex.

There is an extension to this class for WebDAV:

  • Webdav provides an extension of Nethttp_fs for the full WebDAV set of filesystem operations


Examples



This module makes an HTTP file server accessible via a Netfs.stream_fs object, supporting

  • reading files
  • identifying and reading directories (if the server generates index pages for directories, see below for more information)
  • writing files (if the server implements PUT)
  • removing files (if the server implements DELETE)
One has to specify a base URL b, and the access of a file with path p is translated to the URL b ^ p. Note that p cannot include web parameters ("?" strings), and hash marks are also not supported.

A directory is recognized by appending a slash to the URL, and checking whether the URL exists.

The contents of a directory are determined by loading the directory URL, analyzing the HTML page, and checking for the presence of hyperlinks that do not contain slashes (or at most a trailing slash). Only hyperlinks of "A" elements are accepted.

Almost every web server can be configured to generate directory listings that conform to this format. For example, Apache provides this through the module mod_autoindex.

There is an extension to this class for WebDAV:

  • Webdav provides an extension of Nethttp_fs for the full WebDAV set of filesystem operations


Examples



Read an HTTP directory:

       let fs = new http_fs ~streaming:true "http://localhost/~gerd"
       let files = fs # readdir [] "/"
    

Download a file into a string:

       let ch = fs # read [] "/file"
       let s = Netchannels.string_of_in_obj_channels ch
    

Copy a file hierarchy to the local disk:

       let lfs = Netfs.local_fs()
       Netfs.copy_into (fs :> Netfs.stream_fs) "/tree" lfs "/tmp"
    

Use globbing:

       let fsys = Netglob.of_stream_fs (fs :> Netfs.stream_fs)
       let files = Netglob.glob ~fsys (`String "/*.gif")
    

The "https" protocol is also supported, so far a TLS provider is initialized (see Tls for more information).

This module makes an HTTP file server accessible via a Netfs.stream_fs object, supporting

  • reading files
  • identifying and reading directories (if the server generates index pages for directories, see below for more information)
  • writing files (if the server implements PUT)
  • removing files (if the server implements DELETE)
One has to specify a base URL b, and the access of a file with path p is translated to the URL b ^ p. Note that p cannot include web parameters ("?" strings), and hash marks are also not supported.

A directory is recognized by appending a slash to the URL, and checking whether the URL exists.

The contents of a directory are determined by loading the directory URL, analyzing the HTML page, and checking for the presence of hyperlinks that do not contain slashes (or at most a trailing slash). Only hyperlinks of "A" elements are accepted.

Almost every web server can be configured to generate directory listings that conform to this format. For example, Apache provides this through the module mod_autoindex.

There is an extension to this class for WebDAV:

  • Webdav provides an extension of Nethttp_fs for the full WebDAV set of filesystem operations


Examples



Read an HTTP directory:

       let fs = new http_fs ~streaming:true "http://localhost/~gerd"
       let files = fs # readdir [] "/"
    

Download a file into a string:

       let ch = fs # read [] "/file"
       let s = Netchannels.string_of_in_obj_channels ch
    

Copy a file hierarchy to the local disk:

       let lfs = Netfs.local_fs()
       Netfs.copy_into (fs :> Netfs.stream_fs) "/tree" lfs "/tmp"
    

Use globbing:

       let fsys = Netglob.of_stream_fs (fs :> Netfs.stream_fs)
       let files = Netglob.glob ~fsys (`String "/*.gif")
    

The "https" protocol is also supported, so far a TLS provider is initialized (see Tls for more information).

Extended stream_fs type



This module makes an HTTP file server accessible via a Netfs.stream_fs object, supporting

  • reading files
  • identifying and reading directories (if the server generates index pages for directories, see below for more information)
  • writing files (if the server implements PUT)
  • removing files (if the server implements DELETE)
One has to specify a base URL b, and the access of a file with path p is translated to the URL b ^ p. Note that p cannot include web parameters ("?" strings), and hash marks are also not supported.

A directory is recognized by appending a slash to the URL, and checking whether the URL exists.

The contents of a directory are determined by loading the directory URL, analyzing the HTML page, and checking for the presence of hyperlinks that do not contain slashes (or at most a trailing slash). Only hyperlinks of "A" elements are accepted.

Almost every web server can be configured to generate directory listings that conform to this format. For example, Apache provides this through the module mod_autoindex.

There is an extension to this class for WebDAV:

  • Webdav provides an extension of Nethttp_fs for the full WebDAV set of filesystem operations


Examples



Read an HTTP directory:

       let fs = new http_fs ~streaming:true "http://localhost/~gerd"
       let files = fs # readdir [] "/"
    

Download a file into a string:

       let ch = fs # read [] "/file"
       let s = Netchannels.string_of_in_obj_channels ch
    

Copy a file hierarchy to the local disk:

       let lfs = Netfs.local_fs()
       Netfs.copy_into (fs :> Netfs.stream_fs) "/tree" lfs "/tmp"
    

Use globbing:

       let fsys = Netglob.of_stream_fs (fs :> Netfs.stream_fs)
       let files = Netglob.glob ~fsys (`String "/*.gif")
    

The "https" protocol is also supported, so far a TLS provider is initialized (see Tls for more information).

Extended stream_fs type



There is the new flag `Header for read and write, and the new method last_response_header for getting the response header of the most recently executed operation.
type read_flag = [ `Binary
| `Dummy
| `Header of (string * string) list
| `Skip of int64
| `Streaming ]
type read_file_flag = [ `Binary | `Dummy | `Header of (string * string) list ] 
type write_flag = [ `Binary
| `Create
| `Dummy
| `Exclusive
| `Header of (string * string) list
| `Streaming
| `Truncate ]
type write_file_flag = [ `Binary
| `Create
| `Dummy
| `Exclusive
| `Header of (string * string) list
| `Link
| `Truncate ]
class type http_stream_fs = object .. end

The class


class http_fs : ?config_pipeline:Nethttp_client.pipeline -> unit -> ?streaming:bool -> ?tmp_directory:string -> ?tmp_prefix:string -> ?path_encoding:Netconversion.encoding -> ?enable_read_for_directories:bool -> ?enable_ftp:bool -> string -> http_stream_fs
http_fs base_url: Accesses the HTTP file system rooted at base_url.
val http_fs : ?config_pipeline:(Nethttp_client.pipeline -> unit) ->
?streaming:bool ->
?tmp_directory:string ->
?tmp_prefix:string ->
?path_encoding:Netconversion.encoding ->
?enable_read_for_directories:bool ->
?enable_ftp:bool -> string -> http_stream_fs
Same as normal function
ocamlnet-4.1.2/doc/html-main/type_Shell_fs.html0000644000175000017500000006547012731530353020103 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_fs sig
  type command_context = {
    sfs_command : string;
    sfs_stdin : Shell.producer;
    sfs_stdout : Shell.consumer;
    sfs_stderr : Shell.consumer;
    mutable sfs_status : Unix.process_status option;
  }
  type command_interpreter
  val local_interpreter : unit -> Shell_fs.command_interpreter
  val cmd_interpreter :
    (Shell_fs.command_context -> Shell_sys.command list) ->
    Shell_fs.command_interpreter
  val ssh_interpreter :
    ?options:string list ->
    ?user:string -> host:string -> unit -> Shell_fs.command_interpreter
  class type shell_stream_fs =
    object
      method cancel : unit -> unit
      method copy : Netfs.copy_flag list -> string -> string -> unit
      method last_stderr : string
      method mkdir : Netfs.mkdir_flag list -> string -> unit
      method nominal_dot_dot : bool
      method path_encoding : Netconversion.encoding option
      method path_exclusions : (int * int) list
      method read :
        Netfs.read_flag list -> string -> Netchannels.in_obj_channel
      method read_file :
        Netfs.read_file_flag list -> string -> Netfs.local_file
      method readdir : Netfs.readdir_flag list -> string -> string list
      method readlink : Netfs.readlink_flag list -> string -> string
      method remove : Netfs.remove_flag list -> string -> unit
      method rename : Netfs.rename_flag list -> string -> string -> unit
      method rmdir : Netfs.rmdir_flag list -> string -> unit
      method size : Netfs.size_flag list -> string -> int64
      method symlink : Netfs.symlink_flag list -> string -> string -> unit
      method test : Netfs.test_flag list -> string -> Netfs.test_type -> bool
      method test_list :
        Netfs.test_flag list -> string -> Netfs.test_type list -> bool list
      method write :
        Netfs.write_flag list -> string -> Netchannels.out_obj_channel
      method write_file :
        Netfs.write_file_flag list -> string -> Netfs.local_file -> unit
    end
  class shell_fs :
    ?encoding:Netconversion.encoding ->
    ?root:string ->
    ?dd_has_excl:bool ->
    ?tmp_directory:string ->
    ?tmp_prefix:string -> Shell_fs.command_interpreter -> shell_stream_fs
  val shell_fs :
    ?encoding:Netconversion.encoding ->
    ?root:string ->
    ?dd_has_excl:bool ->
    ?tmp_directory:string ->
    ?tmp_prefix:string ->
    Shell_fs.command_interpreter -> Shell_fs.shell_stream_fs
  val execute :
    Shell_fs.command_interpreter -> Shell_fs.command_context -> unit
  val wait : Shell_fs.command_interpreter -> unit
  val output_stream_adapter :
    ci:Shell_fs.command_interpreter ->
    close_in:(unit -> unit) ->
    skip:int64 -> Shell.consumer * Netchannels.in_obj_channel
  val input_stream_adapter :
    ci:Shell_fs.command_interpreter ->
    close_out:(unit -> unit) -> Shell.producer * Netchannels.out_obj_channel
end
ocamlnet-4.1.2/doc/html-main/Netsys_posix.Debug.html0000644000175000017500000004175512731530353021037 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_posix.Debug

Module Netsys_posix.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.http_reactive_request.html0000644000175000017500000004214712731530353026261 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_reactive_request object
  method accept_body : unit -> unit
  method environment : Nethttpd_types.extended_environment
  method finish : unit -> unit
  method finish_request : unit -> unit
  method reject_body : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/Uq_transfer.async_in_channel-c.html0000644000175000017500000004734612731530353023310 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.async_in_channel

Class type Uq_transfer.async_in_channel

class type async_in_channel = object .. end
An asynchrounous input channel provides methods to input data from a stream descriptor. It is based on raw_in_channel, which is defined by the Ocamlnet module Netchannels (see there for an introduction into the idea of using objects as I/O channels). An asynchronous channel can indicate that there is no data in the input buffer. Furthermore, one can request notification in the case that there is no data or again data in the input buffer.

method input : Bytes.t -> int -> int -> int
input s k n: Reads channel data into the substring of s beginning at index k with length n. The channel is free to fill only a portion of the string (or even nothing). The method returns the number of bytes actually read.

The exception End_of_file indicates that the end of the channel is reached. The return value 0, however, means that no data could be read.

method close_in : unit -> unit
Closes the channel
method pos_in : int
Returns the number of characters read from the channel
method can_input : bool
Whether input is possible, i.e. the input method gets at least one byte, or can signal End_of_file.
method request_notification : (unit -> bool) -> unit
After the notification has been requested, the passed function is be called whenever can_input changes its value (or might change its value). The function returns true if there is still interest in notification, and false if notification must be disabled.

There can be any number of parallel active notifications. It is allowed that a notification callback requests further notifications.

ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.seq_engine.html0000644000175000017500000004156712731530353024121 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.seq_engine '#Uq_engines_compat.engine ->
('-> '#Uq_engines_compat.engine) -> ['b] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/Netx509.X509_DN_string.html0000644000175000017500000004436312731530353021070 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.X509_DN_string

Module Netx509.X509_DN_string

module X509_DN_string: Netdn.DN_string 
Parser/printer for distnguished names as they may occur in X.509 certificates


For a given attribute lookup module L this module provides parser and printer for distinguished names in string format (RFC 4514).

This implementation is restricted to attributes using the ASN.1 types PrintableString, TeletexString, IA5String, UniversalString, BMPString, and UTF8String. It is not possible to parse hexencoded strings ('#' notation).

(NB. We'd need a generic BER printer for supporting this.)

val parse : string -> Netdn.dn
Parses the string (or fails). The string must use UTF-8 encoding.
val print : Netdn.dn -> string
Prints the DN (cannot fail), using UTF-8 encoding
ocamlnet-4.1.2/doc/html-main/Uq_engines.prioritizer_t-c.html0000644000175000017500000004504512731530353022520 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.prioritizer_t

Class type Uq_engines.prioritizer_t

class type ['a] prioritizer_t = object .. end
A prioritizer allows to prioritize the execution of engines: At any time, only engines of a certain priority p can be executed. If an engine with a higher priority ph wants to start, it prevents further engines with priority level p from being started until the higher prioritized engines with level ph are done. On the same priority level, there is no limit for the number of executed engines.

Here, higher priorities have lower numbers.


method prioritized : (Unixqueue.event_system -> 'a engine) ->
int -> 'a engine
let pe = prioritized f p: Queues up f on priority level p. The engine e = f esys can start when there is no waiting engine on a higher priority level (i.e. with a number less than p), and all running engines on lower priority levels are done.

pe enters a final state when e does.

ocamlnet-4.1.2/doc/html-main/Netsys_tls.html0000644000175000017500000010400312731530353017434 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_tls

Module Netsys_tls

module Netsys_tls: sig .. end
User-level TLS API


The following functions are a very thin layer on top of Netsys_crypto_types.TLS_PROVIDER. The provider is passed here as first-class value together with the configuration and with the endpoint (socket). In particular, we have

module type FILE_TLS_ENDPOINT =
  sig
    module TLS : TLS_PROVIDER
    val endpoint : TLS.endpoint
    val rd_file : Unix.file_descr
    val wr_file : Unix.file_descr
  end
    

(see Netsys_crypto_types). In many cases, you can consider the packed modules as opaque values. Sometimes, however, it is useful to call functions of the provider directly. You can do this as follows, demonstrated by calling the provider function get_peer_crt_list for endpoint:

let module Endpoint =
  (val endpoint : Netsys_crypto_types.FILE_TLS_ENDPOINT) in
let certificates =
  Endpoint.TLS.get_peer_crt_list Endpoint.endpoint
    

If you do this, be aware that the inner types of the provider are meaningless outside, and you get a compiler error "type ... would escape its scope" if you try to export such typed values. Exceptions thrown by the provider should be caught and translated to Error with Netsys_tls.translate_exn.

type dh_params = [ `Generate of int | `PKCS3_DER of string | `PKCS3_PEM_file of string ] 
Diffie-Hellman parameters:

  • `PKCS3_PEM_file name: points to a PEM-encoded PKCS3-file ("BEGIN DH PARAMETERS")
  • `PKCS3_DER data: the parameters are in a DER-encoded PKCS3 structure
  • `Generate bits: the parameters are generated with the passed number of bits

type crt_list = [ `DER of string list | `PEM_file of string ] 
Certificates are given either as:

  • `PEM_file name: The certs are stored in this file, and are PEM-encoded.
  • `DER l: The certs are given directly in their DER-encoded form
See also Credentials for TLS.
type crl_list = [ `DER of string list | `PEM_file of string ] 
Certificate revocation lists are given either as:

  • `PEM_file name: The CRLs are stored in this file, and are PEM-encoded.
  • `DER l: The CRLs are given directly in their DER-encoded form
See also Credentials for TLS.
type private_key = [ `DSA of string
| `EC of string
| `PEM_file of string
| `PKCS8 of string
| `PKCS8_encrypted of string
| `RSA of string ]
Private keys are given either as:

  • `PEM_file name: The key is stored PEM-encoded in this file. The PEM header indicates the format.
  • `RSA data: The key is a PKCS1 RSA key
  • `DSA data: The key is a DSA key
  • `EC data: The key is for an elliptic curve
  • `PKCS8 data: The key is in a PKCS8 data structure
  • `PKCS8_encrypted data: The key is in a PKCS8 data structure, and is additionally encrypted.
See also Credentials for TLS.
val error_message : (module Netsys_crypto_types.TLS_PROVIDER) -> string -> string
Returns the message for humans (display, log files etc.) when called with an error or warning symbol.
val create_x509_config : ?algorithms:string ->
?dh_params:dh_params ->
?verify:((module Netsys_crypto_types.TLS_ENDPOINT) -> bool -> bool -> bool) ->
?system_trust:bool ->
?trust:crt_list list ->
?revoke:crl_list list ->
?keys:(crt_list * private_key * string option) list ->
peer_auth:[ `None | `Optional | `Required ] ->
(module Netsys_crypto_types.TLS_PROVIDER) ->
(module Netsys_crypto_types.TLS_CONFIG)
The configuration includes:

  • algorithms: a string specifying which cryptographic algorithms, protocols and protocol options are enabled, and in which priority they are used in the negotiation. (GnuTLS calls this "priority string".) The syntax is implementation-defined.
  • dh_params: parameters for Diffie-Hellman key exchange (used for DH-based authentication, but only on the server side)
  • peer_auth: controls whether the peer is requested to authenticate. This can be set to `None meaning not to request authentication and to ignore credentials, or to `Optional meaning not to request authentication but to check credentials if they are sent nevertheless, or to `Required meaning to request and check credentials. For "standard clients" you should set this to `Required, and for "standard servers" to `None or `Required.
  • verify is a function called to verify the peer certificate in addition to the actions of peer_auth. The function must return true in order to be successful. The arguments of the function are the TLS endpoint, and two bools indicating the success of previous checks. The first bool says whether the certificate is trusted (based on peer_auth, trust and system_trust), and the second bool says whether the host name of the peer matches the name in the certificate. If not passed, verify defaults to (fun _ cert_ok name_ok -> cert_ok && name_ok), i.e. both bools must be true.
  • system_trust: if set, the system certificates are trusted
  • trust specifies the CAs of peers to trust (default: empty)
  • revoke specifies CRLs for revocation of peer certificates (default: empty)
  • keys are our own certificates, as triples (cert_path, private_key, password) (default: empty)
A configuration is read-only once created, and can be used for several endpoints. In particular, it does not cache TLS sessions.

A client should set trust to the list of CAs it can accept on the server side. It is not required to specify a key.

A server must specify a key (but can also specify several keys). If a server requests authentication from the client, it must also set trust.

The keys must include the full certificate path cert_path, starting with the endpoint certificate, followed by all middle certificates, and ending with the certificate of the CA. The private_key is the key of the endpoint. If it is password-encrypted, the password must be given.

val create_file_endpoint : ?resume:string ->
role:[ `Client | `Server ] ->
rd:Unix.file_descr ->
wr:Unix.file_descr ->
peer_name:string option ->
(module Netsys_crypto_types.TLS_CONFIG) ->
(module Netsys_crypto_types.FILE_TLS_ENDPOINT)
create_file_endpoint ~role ~rd ~wr ~peer_name tls_config: Creates a new TLS endpoint (encapsulated as module, together with the provider) for the case that the data flows over file descriptors. rd is used for reading data, and wr for writing (of course, both descriptors may be identical).

peer_name is the expected common name or DNS name of the peer. peer_name has an option type as it is not always required to pass it. However, keep in mind that clients normally authenticate servers (peer_auth=`Required). In order to do so, they need to check whether the name in the server certificate equals the DNS name of the service they are connected to. This check is done by comparing peer_name with the name in the certificate.

peer_name is also used for the SNI extension.

Servers normally need not to set peer_name. You can also omit it when there is no name-driven authentication at all.

resume: The endpoint resumes an old session whose data are passed here. This is only possible for client endpoints.

val endpoint : (module Netsys_crypto_types.FILE_TLS_ENDPOINT) ->
(module Netsys_crypto_types.TLS_ENDPOINT)
Coercion
val handshake : (module Netsys_crypto_types.TLS_ENDPOINT) -> unit
Procedes the TLS protocol until payload data can be exchanged. This includes the initial handshake (if not yet done), and the verification.
val recv : ?on_rehandshake:((module Netsys_crypto_types.TLS_ENDPOINT) -> bool) ->
(module Netsys_crypto_types.TLS_ENDPOINT) -> Bytes.t -> int -> int -> int
recv endpoint buffer pos len: Receives data from endpoint, and puts the received bytes into buffer at byte position pos. At most len bytes can be received. Returns the actually received number of bytes.

If the TLS protocol is not yet at the stage where data can be received, the protocol is proceeded until this point (i.e. handshake is "included"). Also, renegotiation alerts are interpreted. Both phenomenons can cause that data needs to be written first.

on_rehandshake: returns whether renegotiations are allowed. Defaults to true. Also, this function is guaranteed to be called when a renegotiation request arrives. In this case, recv will raise an exception such as Netsys_types.EAGAIN_RD or Netsys_types.EAGAIN_WR, but never return normally.

If interrupted the function can be safely invoked again.

May raise Netsys_types.EAGAIN_RD, Netsys_types.EAGAIN_WR, Unix_error(EINTR,_,_), and Error.

val mem_recv : ?on_rehandshake:((module Netsys_crypto_types.TLS_ENDPOINT) -> bool) ->
(module Netsys_crypto_types.TLS_ENDPOINT) ->
Netsys_types.memory -> int -> int -> int
Same for a memory-backed buffer
val send : (module Netsys_crypto_types.TLS_ENDPOINT) -> Bytes.t -> int -> int -> int
send endpoint buffer pos len: Sends data via endpoint, and takes the emitted bytes from buffer at byte position pos. At most len bytes can be sent. Returns the actually sent number of bytes.

If the TLS protocol is not yet at the stage where data can be received, the protocol is proceeded until this point (i.e. handshake is "included"). Also, renegotiation alerts are interpreted. Both phenomenons can cause that data needs to be received as well as sent.

If interrupted the function can be safely invoked again.

May raise Netsys_types.EAGAIN_RD, Netsys_types.EAGAIN_WR, Unix_error(EINTR,_,_), and Error.

val mem_send : (module Netsys_crypto_types.TLS_ENDPOINT) ->
Netsys_types.memory -> int -> int -> int
Same for a memory-backed buffer
val str_send : (module Netsys_crypto_types.TLS_ENDPOINT) -> string -> int -> int -> int
Same for immutable string
val shutdown : (module Netsys_crypto_types.TLS_ENDPOINT) -> Unix.shutdown_command -> unit
Ends the TLS encapsulation of data:

  • SHUTDOWN_SEND: The payload stream is closed for sending.
  • SHUTDOWN_ALL: The payload stream is closed for sending and receiving.
The mode SHUTDOWN_RECEIVE is unsupported and silently ignored.

The function does not shut down or close the underlying file descriptors.

If interrupted the function can be safely invoked again.

May raise Netsys_types.EAGAIN_RD, Netsys_types.EAGAIN_WR, Unix_error(EINTR,_,_), and Error.

val at_transport_eof : (module Netsys_crypto_types.TLS_ENDPOINT) -> bool
Whether the underlying transport channel has seen the end of input. Use this after recv or mem_recv returned 0 to check whether only the TLS enf-of-input message has been read, or the underlying channel (usually the file descriptor) has indicated EOF.
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netftp_fs.ftp_stream_fs-c.html0000644000175000017500000004376612731530353022312 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_fs.ftp_stream_fs

Class type Netftp_fs.ftp_stream_fs

class type ftp_stream_fs = object .. end
Inherits
method ftp_client : Netftp_client.ftp_client
The FTP client backing this filesystem
method last_ftp_state : Netftp_client.ftp_state
The last state of the last operation, or Not_found
method translate : string -> string
Translates a path into a URL
method close : unit -> unit
Forces that the FTP client is closed. (See keep_open option.) The client remains functional - the next operation will re-open the connection.
ocamlnet-4.1.2/doc/html-main/Rpc_portmapper_clnt.Make'PMAP.V4.html0000644000175000017500000007030112731530353023176 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt.Make'PMAP.V4

Module Rpc_portmapper_clnt.Make'PMAP.V4

module V4: sig .. end

type t = U'C.t 
val _program : Rpc_program.t
val rpcbproc_null : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res
val rpcbproc_null'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res) -> unit) -> unit
val rpcbproc_set : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res
val rpcbproc_set'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res) -> unit) -> unit
val rpcbproc_unset : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res
val rpcbproc_unset'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res) -> unit) -> unit
val rpcbproc_getaddr : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res
val rpcbproc_getaddr'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res) -> unit) -> unit
val rpcbproc_dump : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res
val rpcbproc_dump'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res) -> unit) -> unit
val rpcbproc_bcast : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res
val rpcbproc_bcast'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res) -> unit) -> unit
val rpcbproc_gettime : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res
val rpcbproc_gettime'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res) -> unit) -> unit
val rpcbproc_uaddr2taddr : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res
val rpcbproc_uaddr2taddr'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res) -> unit) ->
unit
val rpcbproc_taddr2uaddr : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res
val rpcbproc_taddr2uaddr'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res) -> unit) ->
unit
val rpcbproc_getversaddr : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res
val rpcbproc_getversaddr'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res) -> unit) ->
unit
val rpcbproc_indirect : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res
val rpcbproc_indirect'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res) -> unit) ->
unit
val rpcbproc_getaddrlist : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res
val rpcbproc_getaddrlist'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res) -> unit) ->
unit
val rpcbproc_getstat : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res
val rpcbproc_getstat'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res) -> unit) -> unit
ocamlnet-4.1.2/doc/html-main/Netplex_cenv.TYPE.html0000644000175000017500000004212312731530353020503 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.TYPE

Module type Netplex_cenv.TYPE

module type TYPE = sig .. end
Just a (monomorphic) type t

type t 
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_modes.CIPHERS.html0000644000175000017500000004111112731530353023476 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes.CIPHERS sig val ciphers : Netsys_crypto_modes.Symmetric_cipher.sc list endocamlnet-4.1.2/doc/html-main/Netchannels_crypto.tls_endpoint-c.html0000644000175000017500000004267712731530353024072 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.tls_endpoint

Class Netchannels_crypto.tls_endpoint

class tls_endpoint : ?start_pos_in:int -> ?start_pos_out:int -> ?resume:string -> role:[ `Client | `Server ] -> peer_name:string option -> Unix.file_descr -> Netsys_crypto_types.tls_config -> tls_channel
This class is slightly more efficient than tls_layer, and to preferred if you have direct access to the file descriptors.

ocamlnet-4.1.2/doc/html-main/Uq_engines.Operators.html0000644000175000017500000004624712731530353021356 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.Operators

Module Uq_engines.Operators

module Operators: sig .. end
Handy operators: ++, >>, and eps_e


The most important operators. This module should be opened.
val (++) : 'a #Uq_engines.engine ->
('a -> 'b #Uq_engines.engine) -> 'b Uq_engines.engine
Another name for qseq_engine. Use this operator to run engines in sequence:

	    e1 ++ (fun r1 -> e2) ++ (fun r2 -> e3) ++ ...

Here rK is the result of engine eK.

Change in OCamlnet-3.6.4: ++ is now qseq_engine, and no longer seq_engine, and hence it does not support progress reporting anymore. Redefine ++ as seq_engine in your own code if you need the old behavior.

val (>>) : 'a #Uq_engines.engine ->
('a Uq_engines.final_state -> 'b Uq_engines.final_state) ->
'b Uq_engines.engine
Another name for fmap_engine. Use this operator to map the final value of an engine:

	    e >> (function `Done x -> ... | `Error e -> ... | `Aborted -> ...)

val eps_e : 't Uq_engines.engine_state -> Unixqueue.event_system -> 't Uq_engines.engine
Same as epsilon_engine
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.input_engine-c.html0000644000175000017500000004257012731530353023642 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.input_engine

Class Uq_engines_compat.input_engine

class ['a] input_engine : (Unix.file_descr -> 'a) -> Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine

ocamlnet-4.1.2/doc/html-main/type_Netmcore.html0000644000175000017500000007277212731530353020123 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore sig
  type res_id = [ `Resource of int ]
  type process_id = [ `Process of int ]
  type compute_resource_type =
      [ `File
      | `Fork_point
      | `Join_point
      | `Posix_sem
      | `Posix_shm
      | `Posix_shm_preallocated
      | `Posix_shm_preallocated_sc
      | `Posix_shm_sc ]
  type inherit_request = [ `All | `Resources of Netmcore.res_id list ]
  type compute_resource_repr =
      [ `File of string
      | `Fork_point of
          Netmcore.inherit_request * Netplex_encap.encap ->
          Netmcore.process_id
      | `Join_point of Netmcore.process_id -> Netplex_encap.encap option
      | `Posix_sem of string
      | `Posix_shm of string
      | `Posix_shm_preallocated of string * Netsys_mem.memory
      | `Posix_shm_preallocated_sc of
          string * Netsys_mem.memory * Netsys_sem.container
      | `Posix_shm_sc of string * Netsys_sem.prefix ]
  exception No_resource of Netmcore.res_id
  class type compute_resource =
    object
      method id : Netmcore.res_id
      method release : unit -> unit
      method repr : Netmcore.compute_resource_repr
      method typ : Netmcore.compute_resource_type
    end
  val def_process :
    (Netplex_encap.encap -> Netplex_encap.encap) ->
    Netmcore.res_id * Netmcore.res_id
  val start :
    ?inherit_resources:Netmcore.inherit_request ->
    Netmcore.res_id -> Netplex_encap.encap -> Netmcore.process_id
  val join :
    Netmcore.res_id -> Netmcore.process_id -> Netplex_encap.encap option
  val join_nowait :
    Netmcore.res_id -> Netmcore.process_id -> Netplex_encap.encap option
  val get_resource : Netmcore.res_id -> Netmcore.compute_resource
  val release : Netmcore.res_id -> unit
  val manage_file : string -> Netmcore.compute_resource
  val get_file : Netmcore.res_id -> string
  val manage_shm : string -> Netmcore.compute_resource
  val manage_shm_sc :
    string -> Netsys_sem.container -> Netmcore.compute_resource
  val get_shm : Netmcore.res_id -> string
  val get_sem_container : Netmcore.res_id -> Netsys_sem.container
  val create_preallocated_shm :
    ?value_area:bool -> string -> int -> Netmcore.res_id * string
  val create_preallocated_shm_sc :
    ?value_area:bool ->
    string -> int -> Netmcore.res_id * string * Netsys_sem.container
  val manage_sem : string -> Netmcore.compute_resource
  val get_sem : Netmcore.res_id -> string
  val self_process_id : unit -> Netmcore.process_id
  val add_plugins : Netplex_types.controller -> unit
  val startup :
    socket_directory:string ->
    ?pidfile:string ->
    ?init_ctrl:(Netplex_types.controller -> unit) ->
    ?disable_pmanage:bool ->
    ?no_unlink:bool ->
    first_process:('-> Netmcore.process_id) -> '-> unit
  val run :
    socket_directory:string ->
    ?pidfile:string ->
    ?init_ctrl:(Netplex_types.controller -> unit) ->
    ?disable_pmanage:bool ->
    ?no_unlink:bool ->
    first_process:('-> Netmcore.process_id) ->
    extract_result:(Netplex_types.controller -> Netmcore.process_id -> 'b) ->
    '-> 'b
  val destroy_resources : unit -> unit
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Netmcore_basics.html0000644000175000017500000004062012731530353021432 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_basics sig  endocamlnet-4.1.2/doc/html-main/type_Rpc_netplex.html0000644000175000017500000004423512731530353020623 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_netplex sig
  val rpc_factory :
    configure:(Netplex_types.config_file -> Netplex_types.address -> 'a) ->
    ?socket_config:('-> Rpc_server.socket_config) ->
    ?hooks:('-> Netplex_types.processor_hooks) ->
    ?supported_ptypes:Netplex_types.parallelization_type list ->
    name:string ->
    setup:(Rpc_server.t -> '-> unit) ->
    unit -> Netplex_types.processor_factory
  val debug_rpc_internals : bool Pervasives.ref
  val debug_rpc_service : bool Pervasives.ref
end
ocamlnet-4.1.2/doc/html-main/Netmcore.html0000644000175000017500000012476012731530353017055 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore

Module Netmcore

module Netmcore: sig .. end
Multi-processing for compute jobs

This library allows it to develop parallel algorithms that can take advantage of multiple CPU cores. It does not use Ocaml's multi-threading feature because this would implicitly serialize all computations. Instead, independent processes are created, and the communication between processes is made as cheap and unproblematic as possible.

Please read Netmcore_basics for an introduction into using this module. There is also Netmcore_tut with more advanced techniques.

Before using this library, it is required to call Netmcore.startup. This turns the current process into the master process. The master process has only a supervising function, and is responsible for managing global resources, and for starting further worker processes.

The worker processes can start more workers. This is different from creating a new thread, though: The new worker does not share memory with its creator. It is also different from calling Unix.fork, because new workers are always subprocesses of the master process. This means it is not initialized with a copy of the state of the logical creator, but with its real parent process which is always the master.

Compatibility with multi-threading: You may run into big trouble when the master process starts further threads (after forking thread-related resources are in an uncontrolled state). There is no such problem in the worker processes. In this library, however, nothing is done to ease the multi-threaded life, so you should carefully check the compatibility first.

Netmcore controls the lifetime of certain system resources in addition to worker processes:

  • Temporary files
  • Shared memory objects
  • Named semaphores
These objects have kernel persistence, and continue to exist when the program ends. Because of this, there are two mechanisms to control the lifetime, and to delete these objects finally: First, if all using processes terminate normally, an object is deleted. Second, in order to also catch abnormal terminations, these objects are also managed by storing their names into an external file "netplex.pmanage" (in the socket directory). When the program is started the next time with the same socket directory, the objects from the previous run are automatically deleted. The second mechanism can be disabled by setting the
  • disable_pmanage parameter for the Netmcore.startup call, or by setting the
  • unlink parameter in the same call. This second option only disables the deletion, but the management file is updated.



Types and exceptions


type res_id = [ `Resource of int ] 
This tagged integer identifies resources. This variant type will never be extended.
type process_id = [ `Process of int ] 
This tagged integer identifies processes. This variant type will never be extended.

Note that the int argument is not the Unix PID, but just a self-generated identifier that is unique for the lifetime of the program.

type compute_resource_type = [ `File
| `Fork_point
| `Join_point
| `Posix_sem
| `Posix_shm
| `Posix_shm_preallocated
| `Posix_shm_preallocated_sc
| `Posix_shm_sc ]
type inherit_request = [ `All | `Resources of res_id list ] 
type compute_resource_repr = [ `File of string
| `Fork_point of
inherit_request * Netplex_encap.encap -> process_id
| `Join_point of process_id -> Netplex_encap.encap option
| `Posix_sem of string
| `Posix_shm of string
| `Posix_shm_preallocated of string * Netsys_mem.memory
| `Posix_shm_preallocated_sc of
string * Netsys_mem.memory * Netsys_sem.container
| `Posix_shm_sc of string * Netsys_sem.prefix ]
Centrally managed resources include:
  • `File name: (Temporary) file name (absolute name)
  • `Posix_shm name: Shared memory objects with name
  • `Posix_shm_sc(name,p): Shared memory objects with name, and attached container for semaphores with prefix p
  • `Posix_shm_preallocated(name,m): Shared memory objects already allocated by the master process. These objects are passed over to the worker processes by inheritance, and are always mapped at the same address. m is the bigarray mapping the object.
  • `Posix_shm_preallocated_sc(name,m.p): Same, plus attached container for semaphores with prefix p
  • `Posix_sem name: Semaphores with name
  • `Fork_point(inh,f): Fork points where let pid=f arg fork a new process with argument arg. pid is the process identifier. The list inh are resources inherited from the master.
  • `Joint_point f: Joint points where let res=f pid wait until the process pid terminates. If res is non-None it is the result value. If it is None, no result was passed back (including all pathological cases like crashes)
Except fork and join points, these resources are also added to the pmanage object of Netplex (see Netplex_cenv.pmanage and Netsys_pmanage).
exception No_resource of res_id
No such resource, or no resource of the expected type
class type compute_resource = object .. end

Defining processes



Defining processes



This is the lower-level version of the process API where arguments and results of processes are dynamically typed. It may have some uses when writing generic process managers, but for the normal application the statically typed API in Netmcore_process is easier to use (and less verbose).
val def_process : (Netplex_encap.encap -> Netplex_encap.encap) ->
res_id * res_id
let fork_point, join_point = def_process f: Defines process types, i.e. ways of starting and finishing processes. The definition must be done in the master process, e.g. before the first worker is started.

Once the process type is defined, new processes can be started, and these processes will run the function f. When f is finished, the process will terminate. Starting processes is possible from other worker processes.

f is supplied with its argument by the process starter start. The result value of f can be retrieved with join (by any process, but only the first join for this process will be successful).

If f throws exceptions, these will be caught and logged, but not be passed back to the caller (which just gets None as result of join). The same happens for any unplanned termination of the process.

It is allowed to immediately release the join_point if there is no interest in catching the termination of started processes.

Here is an example how to define a process that takes a string argument and returns an int:

      module String_encap = Netplex_encap.Make_encap(struct type t=string end)
      module Int_encap = Netplex_encap.Make_encap(struct type t=int end)

      let my_process_fork, my_process_join =
        Netmcore.def_process
          (fun s_encap ->
            let (s:string) = String_encap.unwrap s_encap in
            let (r:int) = ... in
            Int_encap.wrap r
          )
      

The wrapping and unwrapping is required for ensuring type-safety (see Netplex_encap for the details of the idea).

Calling this process is done with (also see below):

      let pid = Netmcore.start my_process_fork (String_encap.wrap s) in
      let r_encap_opt = Netmcore.join my_process_join pid in
      match r_encap_opt with
        | None -> failwith "Something went wrong"
        | Some r_encap -> Int_encap.unwrap r_encap
      


The following functions can also be called from worker processes (i.e. Netplex containers)
val start : ?inherit_resources:inherit_request ->
res_id -> Netplex_encap.encap -> process_id
let pid = start fork_point arg: Starts the process with the given fork_point and the argument arg.

Raises No_resource if there is no such resource.

The function returns a process identifier. This is not the Unix PID, but a sequentially generated number that is unique for a running program.

Option inherit_resources: Certain resources are only accessible by the process when they are inherited to it. This is the case for `Posix_shm_preallocated. This can be set to `All to inherit all inheritable resources, or to `Resources l to only inherit the resources of l. By default, all resources are inherited. (This changed in Ocamlnet-3.5 - before, no resources were inherited, which turned out to be quite dangerous as default.)

val join : res_id -> process_id -> Netplex_encap.encap option
let res_opt = join join_point pid: Waits until the process pid is done, and returns the result value if any. You can only join (or join_nowait) once per process.

Raises No_resource if there is no such resource.

It is not possible to call join from the master process (as this process must not block). You can, however, get the result of an already terminated process with join_nowait, e.g. after Netmcore.run returned.

val join_nowait : res_id -> process_id -> Netplex_encap.encap option
let res_opt = join_nowait join_point pid: Checks if the process pid is done, and returns the result value if so. Otherwise return None.

Managing resources from worker processes



Managing resources from worker processes



The following functions can also be called from worker processes (i.e. Netplex containers)
val get_resource : res_id -> compute_resource
Retrieves the resource by ID. This implicitly also marks this resource as being used by this process. Don't forget to call release when your are done with the resource.

Raises No_resource if there is no such resource.

val release : res_id -> unit
Release the resource with this ID. (Same as calling the release method on the object.)
val manage_file : string -> compute_resource
hands over a file to the manager
val get_file : res_id -> string
Gets the file with this ID (or raises No_resource). As for get_resource the file is marked as being used by the process.
val manage_shm : string -> compute_resource
hands over a named shm object to the manager
val manage_shm_sc : string -> Netsys_sem.container -> compute_resource
hands over a named shm object plus semaphore container to the manager
val get_shm : res_id -> string
Gets the shm object with this ID (or raises No_resource). As for get_resource the shm object is marked as being used by the process.
val get_sem_container : res_id -> Netsys_sem.container
Get the semaphore container

Shared memory objects can be created with Netsys_posix.shm_create, and opened with Netsys_posix.shm_open.
val create_preallocated_shm : ?value_area:bool -> string -> int -> res_id * string
create_preallocated_shm prefix size: Creates a new preallocated shm object with a unique name based on prefix, and a length of size bytes. The object is created and mapped into the master process, and will be available to any newly started process when the resource ID is inherited to the process.

Returns (res_id,shm_name) where res_id identifies the new resource, and shm_name is the name of the POSIX shared memory object.

Note that the process calling this function cannot look up this resource (using get_shm or get_resource) because the shm block cannot be mapped at the right address. Nevertheless, the calling process counts as a user of the object, and needs to release the object.

Option value_area: if set, the new memory is marked as value area, so the ocaml runtime allows value comparisons in this memory area.

val create_preallocated_shm_sc : ?value_area:bool ->
string -> int -> res_id * string * Netsys_sem.container
Same as create_preallocated_shm with the extension that a semaphore container is also allocated and returned
val manage_sem : string -> compute_resource
hands over a named semaphore to the manager
val get_sem : res_id -> string
gets the semaphore with this ID (or raises No_resource). As for get_resource the semaphore is marked as being used by the process.

Semaphores can be opened with Netsys_posix.sem_open, and created with Netsys_posix.sem_create.
val self_process_id : unit -> process_id
Returns the process ID of a worker

Initialization and system start



Initialization and system start



This module can either be used as Netplex plugin and integrated into any existing Netplex program, or it can be started in stand-alone mode
val add_plugins : Netplex_types.controller -> unit
To enable compute processes for any Netplex program, call this function with the controller object as argument. This can e.g. be done in the post_add_hook of the processor.
val startup : socket_directory:string ->
?pidfile:string ->
?init_ctrl:(Netplex_types.controller -> unit) ->
?disable_pmanage:bool ->
?no_unlink:bool -> first_process:('a -> process_id) -> 'a -> unit
This function makes the current process the master process. It starts immediately a new worker process, called the first process. The startup function returns first when this process is finished, in which case the whole Netplex system is shut down (which may lead to killing the remaining processes, following the usual shutdown procedure).

The first process is created by calling first_process at the right moment. This function normally just invokes start.

Passing a socket_directory is mandatory. This directory will contain helper files. The must be a separate socket_directory for each running Computeplex instance.

pidfile: If passed, the Unix PID of the master process is written to this file.

disable_pmanage: Disable that persistent kernel objects are managed via the "netplex.pmanage" file in the socket directory.

no_unlink: Disable that old persistent kernel objects are deleted at startup. This may be useful when startup is called a second time from the same program.

val run : socket_directory:string ->
?pidfile:string ->
?init_ctrl:(Netplex_types.controller -> unit) ->
?disable_pmanage:bool ->
?no_unlink:bool ->
first_process:('a -> process_id) ->
extract_result:(Netplex_types.controller -> process_id -> 'b) ->
'a -> 'b
This function fixes a design error in startup, namely that it was difficult to get the result of the process(es) back. Here, the additional callback extract_result can be used to retrieve the results from processes, especially from the first process.

You need to call Netmcore.join_nowait to get the results from processes.

The result of extract_result is the result of run.

val destroy_resources : unit -> unit
Destroys all resources that may be left
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netshm.html0000644000175000017500000006600312731530353017573 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm sig
  type shm_descr
  type shm_type = [ `File | `POSIX ]
  val supported_types : Netshm.shm_type list
  type shm_name = [ `File of string | `POSIX of string * string ]
  val shm_type_of_name : Netshm.shm_name -> Netshm.shm_type
  val open_shm :
    ?unique:bool ->
    Netshm.shm_name -> Unix.open_flag list -> int -> Netshm.shm_descr
  val create_unique_shm : Netshm.shm_name -> int -> Netshm.shm_descr
  val name_of_shm : Netshm.shm_descr -> Netshm.shm_name
  val close_shm : Netshm.shm_descr -> unit
  val unlink_shm : Netshm.shm_name -> unit
  val chmod_shm : Netshm.shm_descr -> int -> unit
  val chown_shm : Netshm.shm_descr -> int -> int -> unit
  type locking_method = [ `No_locking | `Record_locking ]
  val best_locking_method : Netshm.shm_type -> Netshm.locking_method
  type shm_table
  type int32_array =
      (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array1.t
  exception Corrupt_file of string
  exception Deadlock
  val manage :
    ?pagesize:int ->
    ?init:int ->
    Netshm.locking_method -> Netshm.shm_descr -> Netshm.shm_table
  val group : Netshm.shm_table -> ('-> 'b) -> '-> 'b
  val add : Netshm.shm_table -> int32 -> Netshm.int32_array -> unit
  val find : Netshm.shm_table -> int32 -> Netshm.int32_array
  val find_all : Netshm.shm_table -> int32 -> Netshm.int32_array list
  val mem : Netshm.shm_table -> int32 -> bool
  val remove : Netshm.shm_table -> int32 -> unit
  val replace : Netshm.shm_table -> int32 -> Netshm.int32_array -> unit
  val iter :
    (int32 -> Netshm.int32_array -> unit) -> Netshm.shm_table -> unit
  val iter_keys : (int32 -> unit) -> Netshm.shm_table -> unit
  val fold :
    (int32 -> Netshm.int32_array -> '-> 'a) -> Netshm.shm_table -> '-> 'a
  val length : Netshm.shm_table -> int
  exception Next
  exception Break
  val read_blocks :
    Netshm.shm_table -> int32 -> (Netshm.int32_array option -> unit) -> unit
  type write_op = [ `Remove_binding ]
  type ctrl_op = [ `Nop | `Remove_binding ]
  val write_blocks :
    Netshm.shm_table ->
    Netshm.write_op list ->
    int32 -> (Netshm.int32_array option -> Netshm.ctrl_op) -> unit
  val dump : Netshm.shm_table -> unit
  val bigarray : int array -> Netshm.int32_array
  val memory :
    Netshm.shm_table ->
    (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array2.t
end
ocamlnet-4.1.2/doc/html-main/Rpc_server.tls_socket_config-c.html0000644000175000017500000004217312731530353023326 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.tls_socket_config

Class Rpc_server.tls_socket_config

class tls_socket_config : (module Netsys_crypto_types.TLS_CONFIG) -> socket_config
TLS configuration as class

ocamlnet-4.1.2/doc/html-main/type_Netplex_mt.html0000644000175000017500000004136412731530353020457 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mt sig
  class mt : unit -> Netplex_types.parallelizer
  val mt : unit -> Netplex_types.parallelizer
end
ocamlnet-4.1.2/doc/html-main/Netmime.memory_mime_body-c.html0000644000175000017500000004305612731530353022450 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.memory_mime_body

Class Netmime.memory_mime_body

class memory_mime_body : string -> mime_body
An implementation of mime_body where the value is stored in-memory.

The argument is the initial (decoded) value of the body. The method store returns `Memory.

Example: To create a body from a string, call

 new memory_mime_body "The value as string" 


ocamlnet-4.1.2/doc/html-main/type_Netplex_mt.mt.html0000644000175000017500000004066312731530353021077 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mt.mt unit -> Netplex_types.parallelizerocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.TLS_CONFIG.TLS.html0000644000175000017500000013470612731530353023542 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_CONFIG.TLS

Module Netsys_crypto_types.TLS_CONFIG.TLS

module TLS: Netsys_crypto_types.TLS_PROVIDER 


Provides TLS functionality.

Users should not call functions of the provider directly, but use Netsys_tls, or another higher-level layer.

type config 
type credentials 
type endpoint 
module Exc: Netsys_crypto_types.TLS_EXCEPTIONS 
Access to exceptions
val error_message : string -> string
Returns the message for humans (display, log files etc.) when called with an error or warning symbol.
type dh_params = [ `Generate of int | `PKCS3_DER of string | `PKCS3_PEM_file of string ] 
Diffie-Hellman parameters:

  • `PKCS3_PEM_file name: points to a PEM-encoded PKCS3-file ("BEGIN DH PARAMETERS")
  • `PKCS3_DER data: the parameters are in a DER-encoded PKCS3 structure
  • `Generate bits: the parameters are generated with the passed number of bits

val create_config : ?algorithms:string ->
?dh_params:dh_params ->
?verify:(endpoint -> bool -> bool -> bool) ->
peer_auth:[ `None | `Optional | `Required ] ->
credentials:credentials ->
unit -> config
The configuration includes:

  • algorithms: a string specifying which cryptographic algorithms, protocols and protocol options are enabled, and in which priority they are used in the negotiation. (GnuTLS calls this "priority string".) The syntax is implementation-defined.
  • dh_params: parameters for Diffie-Hellman key exchange (used for DH-based authentication, but only on the server side)
  • peer_auth: controls whether the peer is requested to authenticate. This can be set to `None meaning not to request authentication and to ignore credentials, or to `Optional meaning not to request authentication but to check credentials if they are sent nevertheless, or to `Required meaning to request and check credentials. For "standard clients" you should set this to `Required, and for "standard servers" to `None or `Required.
  • credentials describes our own credentials, and the accepted credentials of the peer.
  • verify is a function called to verify the peer certificate in addition to the actions of peer_auth. The function must return true in order to be successful. The arguments of the function are the TLS endpoint, and two bools indicating the success of previous checks. The first bool says whether the certificate is trusted (based on peer_auth, trust and system_trust), and the second bool says whether the host name of the peer matches the name in the certificate. If not passed, verify defaults to (fun _ cert_ok name_ok -> cert_ok && name_ok), i.e. both bools must be true.
A configuration is read-only once created, and can be used for several endpoints. In particular, it does not cache TLS sessions.
type crt_list = [ `DER of string list | `PEM_file of string ] 
Certificates are given either as:

  • `PEM_file name: The certs are stored in this file, and are PEM-encoded.
  • `DER l: The certs are given directly in their DER-encoded form
See also Credentials for TLS.
type crl_list = [ `DER of string list | `PEM_file of string ] 
Certificate revocation lists are given either as:

  • `PEM_file name: The CRLs are stored in this file, and are PEM-encoded.
  • `DER l: The CRLs are given directly in their DER-encoded form
See also Credentials for TLS.
type private_key = [ `DSA of string
| `EC of string
| `PEM_file of string
| `PKCS8 of string
| `PKCS8_encrypted of string
| `RSA of string ]
Private keys are given either as:

  • `PEM_file name: The key is stored PEM-encoded in this file. The PEM header indicates the format.
  • `RSA data: The key is a PKCS1 RSA key
  • `DSA data: The key is a DSA key
  • `EC data: The key is for an elliptic curve
  • `PKCS8 data: The key is in a PKCS8 data structure
  • `PKCS8_encrypted data: The key is in a PKCS8 data structure, and is additionally encrypted.
See also Credentials for TLS.
val create_x509_credentials : ?system_trust:bool ->
?trust:crt_list list ->
?revoke:crl_list list ->
?keys:(crt_list *
private_key * string option)
list ->
unit -> credentials
Create X.509 credentials from individual objects:
  • system_trust: if set, the system certificates are trusted
  • trust specifies the CAs of peers to trust (default: empty)
  • revoke specifies CRLs for revocation of peer certificates (default: empty)
  • keys are our own certificates, as triples (cert_path, private_key, password) (default: empty)
A client should set trust to the list of CAs it can accept on the server side. It is not required to specify a key.

A server must specify a key (but can also specify several keys). If a server requests authentication from the client, it must also set trust.

The keys must include the certificate path cert_path, starting with the endpoint certificate, and followed by all middle certificates, but omitting the certificate of the CA. The private_key is the key of the endpoint. If it is password-encrypted, the password must be given.

val create_endpoint : role:[ `Client | `Server ] ->
recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
endpoint
Creates a new endpoint for this configuration.

peer_name is the expected common name or DNS name of the peer. peer_name has an option type as it is not always required to pass it. However, keep in mind that clients normally authenticate servers (peer_auth=`Required). In order to do so, they need to check whether the name in the server certificate equals the DNS name of the service they are connected to. This check is done by comparing peer_name with the name in the certificate.

peer_name is also used for the SNI extension.

Servers normally need not to set peer_name. You can also omit it when there is no name-driven authentication at all.

The endpoint will use the functions recv and send for I/O, which must be user-supplied. recv buf is expected to read data into the buffer, and to return the number of bytes, or 0 for EOF. send buf n is expected to send the n first bytes in buf.

Both functions may raise Unix_error. The codes Unix.EAGAIN and Unix.EINTR are specially interpreted.

val stash_endpoint : endpoint -> exn
The endpoint in "stashed" form, encapsulated as an exception. This form is intended for keeping the session alive in RAM, but without keeping references to the recv and send functions.

The endpoint passed in to stash_endpoint must no longer be used!

val restore_endpoint : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
exn -> endpoint
Reconnect the stashed endpoint with recv and send functions
val resume_client : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
string -> endpoint
Creates a new endpoint that will resume an old session. This implies the client role.

The session data is passed as string, which must have been retrieved with get_session_data.

type state = [ `Accepting
| `Data_r
| `Data_rs
| `Data_rw
| `Data_w
| `End
| `Handshake
| `Refusing
| `Start
| `Switching ]
The state of a session:

  • `Start: Before the session is started
  • `Handshake: The handshake is being done (and hello needs to be called again)
  • `Data_rw: The connection exists, and is read/write
  • `Data_r: The connection exists, and is read-only
  • `Data_w: The connection exists, and is write-only
  • `Data_rs: The connection exists, and data can be read. There was a switch request (initiated by us), and a response is awaited. No data can be sent in the moment.
  • `Switching: A rehandshake is being negotiated (and switch needs to be called again)
  • `Accepting: A rehandshake is being accepted (and accept_switch needs to be called again)
  • `Refusing: A rehandshake is being refused (and refuse_switch needs to be called again)
  • `End: After finishing the session

val get_state : endpoint ->
state
Return the recorded state
type raw_credentials = [ `Anonymous | `X509 of string ] 
The encoded credentials:
  • `X509 s: The X509 certificate in DER encoding
  • `Anonymous: no certificate or other key is available

val at_transport_eof : endpoint -> bool
Whether the underlying transport channel has seen the end of input. Use this after recv or mem_recv returned 0 to check whether only the TLS enf-of-input message has been read, or the underlying channel (usually the file descriptor) has indicated EOF.
val hello : endpoint -> unit
Performs the initial handshake (exchanges credentials and establishes a session).

hello doesn't verify the peer. Use verify for that.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val bye : endpoint -> Unix.shutdown_command -> unit
Performs the final handshake (exchanges close requests).

If SHUTDOWN_SEND is set, the close request is sent to the peer, and the TLS tunnel is considered as closed for writing. The application can receive further data until recv returns zero bytes meaning that the peer responded with another close request.

If SHUTDOWN_ALL is passed, it is additionally waited until the peer responds with a close request.

A simple SHUTDOWN_RECEIVE is unimplemented and ignored.

In no case the underlying transport is closed or shut down!

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val verify : endpoint -> unit
verify ep peer_name: Checks that:
  • there is a trust chain for the peer's certificate
  • that peer_name is the common name of the certificate subject, or an alternate name
These checks are not performed if peer_auth=`None is set in the configuration!

Additionally, the verify function in the endpoint configuration is called back, and a failure is indicated if this function returns false. This callback is useful to get the certificate of the peer and to perform further checks.

The verify function will raise Failure on failed checks (and Error for internal processing errors).

val get_config : endpoint ->
config
Get the current config (possibly modified because of a rehandshake)
val get_endpoint_creds : endpoint ->
raw_credentials
Get the credentials that was actually used in the handshake, in raw format.
val get_peer_creds : endpoint ->
raw_credentials
Get the credentials of the peer, in raw format. Raises Not_found if not applicable/no credentials present.
val get_peer_creds_list : endpoint ->
raw_credentials list
Get the chain that was actually used in the handshake.
val switch : endpoint ->
config -> unit
The server can use this to request a rehandshake and to use the new configuration for cert verification. This function sends the request, and expects a soon response from the client. The state enters `Data_rs meaning that we can still read data, and at some point recv will raise TLS_switch_response.

On the client side, the request will by returned as exception TLS_switch_request by recv. The client should respond with accept_switch if it accepts the handshake, or refuse_switch if not.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val accept_switch : endpoint ->
config -> unit
On the client: Enter another handshake round with new configuration data.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val refuse_switch : endpoint -> unit
On the client: Refuse a handshake

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val send : endpoint ->
Netsys_types.memory -> int -> int
send ep buffer n: Sends the first n bytes in the buffer over the endpoint, and returns the actual number of processed bytes.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val recv : endpoint -> Netsys_types.memory -> int
recv ep buffer n: Receives data, and puts them into the memory buffer, and returns the actual number of received bytes. If 0 is returned, a close request was received by the peer. For closing the tunnel properly this request should be responded by another close request with bye (unless this has already been done).

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

The exception TLS_switch_request can only occur on the client side, and should be responded by accept_switch or refuse_switch.

The exception TLS_switch_response can only occur on the server side.

val recv_will_not_block : endpoint -> bool
If there is still unprocessed data in the endpoint buffer, recv is guaranteed not to block or raise EAGAIN.
val get_session_id : endpoint -> string
The (non-printable) session ID
val get_session_data : endpoint -> string
Get the (non-printable) marshalled session data, for later resumption with resume_client
val get_cipher_suite_type : endpoint -> string
The type of the cipher suite:
  • "X509": X509 certificates are used
  • "OPENPGP": OpenPGP certificates are used
  • "ANON": anonymous credentials
  • "SRP": SRP credentials
  • "PSK": PSK credentials

val get_cipher_algo : endpoint -> string
Get the name of the cipher
val get_kx_algo : endpoint -> string
Get the name of the key exchange method
val get_mac_algo : endpoint -> string
Get the name of the message authentication code
val get_compression_algo : endpoint -> string
Get the name of the record-level compression method
val get_cert_type : endpoint -> string
Get the type of the certificate
val get_protocol : endpoint -> string
Get the name of the tunnel protocol
type server_name = [ `Domain of string ] 
val get_addressed_servers : endpoint ->
server_name list
To be used in servers: The client can address one of several virtual servers with the SNI extension, and this function returns which was requested. Raises Not_found if there is nothing appropriate. This information is only available after a handshake, and if the client submitted it.
val set_session_cache : store:(string -> string -> unit) ->
remove:(string -> unit) ->
retrieve:(string -> string) ->
endpoint -> unit
Sets the three callbacks for storing, removing and retrieving sessions (on the server side)
val implementation_name : string
String name of the implementation. By convention this is the full OCaml module path, e.g. "Nettls_gnutls.TLS"
val implementation : unit -> exn
Implementation-defined additional functionality
ocamlnet-4.1.2/doc/html-main/type_Netgzip.input_deflate.html0000644000175000017500000004105612731530353022600 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.input_deflate ?level:int -> Netchannels.in_obj_channel -> Netchannels.in_obj_channelocamlnet-4.1.2/doc/html-main/type_Nethttp.html0000644000175000017500000025236012731530353017766 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp sig
  type protocol_version = int * int
  type protocol_attribute = [ `Secure_https ]
  type protocol =
      [ `Http of Nethttp.protocol_version * Nethttp.protocol_attribute list
      | `Other ]
  val string_of_protocol : Nethttp.protocol -> string
  val protocol_of_string : string -> Nethttp.protocol
  type http_status =
      [ `Accepted
      | `Bad_gateway
      | `Bad_request
      | `Conflict
      | `Continue
      | `Created
      | `Expectation_failed
      | `Forbidden
      | `Found
      | `Gateway_timeout
      | `Gone
      | `Http_version_not_supported
      | `Internal_server_error
      | `Length_required
      | `Method_not_allowed
      | `Moved_permanently
      | `Multiple_choices
      | `No_content
      | `Non_authoritative
      | `Not_acceptable
      | `Not_found
      | `Not_implemented
      | `Not_modified
      | `Ok
      | `Partial_content
      | `Payment_required
      | `Precondition_failed
      | `Proxy_auth_required
      | `Request_entity_too_large
      | `Request_timeout
      | `Request_uri_too_long
      | `Requested_range_not_satisfiable
      | `Reset_content
      | `See_other
      | `Service_unavailable
      | `Switching_protocols
      | `Temporary_redirect
      | `Unauthorized
      | `Unsupported_media_type
      | `Use_proxy ]
  val int_of_http_status : Nethttp.http_status -> int
  val http_status_of_int : int -> Nethttp.http_status
  val string_of_http_status : Nethttp.http_status -> string
  val base_code : int -> int
  type http_method = string * string
  type cache_control_token =
      [ `Extension of string * string option
      | `Max_age of int
      | `Max_stale of int option
      | `Min_fresh of int
      | `Must_revalidate
      | `No_cache of string list
      | `No_store
      | `No_transform
      | `Only_if_cached
      | `Private of string list
      | `Proxy_revalidate
      | `Public
      | `S_maxage of int ]
  type etag = [ `Strong of string | `Weak of string ]
  val weak_validator_match : Nethttp.etag -> Nethttp.etag -> bool
  val strong_validator_match : Nethttp.etag -> Nethttp.etag -> bool
  exception Bad_header_field of string
  class type http_header = Netmime.mime_header
  class type http_header_ro = Netmime.mime_header_ro
  class type http_trailer = Netmime.mime_header
  class type http_trailer_ro = Netmime.mime_header_ro
  val status_of_cgi_header : Nethttp.http_header -> int * string
  type netscape_cookie = {
    cookie_name : string;
    cookie_value : string;
    cookie_expires : float option;
    cookie_domain : string option;
    cookie_path : string option;
    cookie_secure : bool;
  }
  type cookie = Nethttp.netscape_cookie
  val decode_query : string -> string * string
  val split_host_port : string -> string * int option
  val uripath_encode : string -> string
  val uripath_decode : string -> string
  module Cookie :
    sig
      type t
      val make :
        ?max_age:int ->
        ?domain:string ->
        ?path:string ->
        ?secure:bool ->
        ?comment:string ->
        ?comment_url:string ->
        ?ports:int list -> string -> string -> Nethttp.Cookie.t
      val name : Nethttp.Cookie.t -> string
      val value : Nethttp.Cookie.t -> string
      val domain : Nethttp.Cookie.t -> string option
      val path : Nethttp.Cookie.t -> string option
      val ports : Nethttp.Cookie.t -> int list option
      val max_age : Nethttp.Cookie.t -> int option
      val secure : Nethttp.Cookie.t -> bool
      val comment : Nethttp.Cookie.t -> string
      val comment_url : Nethttp.Cookie.t -> string
      val set_value : Nethttp.Cookie.t -> string -> unit
      val set_max_age : Nethttp.Cookie.t -> int option -> unit
      val set_domain : Nethttp.Cookie.t -> string option -> unit
      val set_path : Nethttp.Cookie.t -> string option -> unit
      val set_secure : Nethttp.Cookie.t -> bool -> unit
      val set_comment : Nethttp.Cookie.t -> string -> unit
      val set_comment_url : Nethttp.Cookie.t -> string -> unit
      val set_ports : Nethttp.Cookie.t -> int list option -> unit
      val of_netscape_cookie : Nethttp.netscape_cookie -> Nethttp.Cookie.t
      val to_netscape_cookie : Nethttp.Cookie.t -> Nethttp.netscape_cookie
    end
  module Header :
    sig
      type param_value = [ `Q of string | `V of string ]
      type auth_challenge =
          string * (string * Nethttp.Header.param_value) list
      type auth_credentials =
          string * (string * Nethttp.Header.param_value) list
      val parse_quoted_parameters : string -> (string * string) list
      val get_accept :
        #Nethttp.http_header_ro ->
        (string * (string * string) list * (string * string) list) list
      val best_media_type :
        #Nethttp.http_header_ro ->
        string list -> string * (string * string) list
      val set_accept :
        #Nethttp.http_header ->
        (string * (string * string) list * (string * string) list) list ->
        unit
      val get_accept_charset :
        #Nethttp.http_header_ro -> (string * (string * string) list) list
      val best_charset : #Nethttp.http_header_ro -> string list -> string
      val set_accept_charset :
        #Nethttp.http_header ->
        (string * (string * string) list) list -> unit
      val get_accept_encoding :
        #Nethttp.http_header_ro -> (string * (string * string) list) list
      val best_encoding : #Nethttp.http_header_ro -> string list -> string
      val set_accept_encoding :
        #Nethttp.http_header ->
        (string * (string * string) list) list -> unit
      val get_accept_language :
        #Nethttp.http_header_ro -> (string * (string * string) list) list
      val set_accept_language :
        #Nethttp.http_header ->
        (string * (string * string) list) list -> unit
      val get_accept_ranges : #Nethttp.http_header_ro -> string list
      val set_accept_ranges : #Nethttp.http_header -> string list -> unit
      val get_age : #Nethttp.http_header_ro -> float
      val set_age : #Nethttp.http_header -> float -> unit
      val get_allow : #Nethttp.http_header_ro -> string list
      val set_allow : #Nethttp.http_header -> string list -> unit
      val get_authorization :
        #Nethttp.http_header_ro -> Nethttp.Header.auth_credentials
      val set_authorization :
        #Nethttp.http_header -> Nethttp.Header.auth_credentials -> unit
      val get_cache_control :
        #Nethttp.http_header_ro -> Nethttp.cache_control_token list
      val set_cache_control :
        #Nethttp.http_header -> Nethttp.cache_control_token list -> unit
      val get_connection : #Nethttp.http_header_ro -> string list
      val set_connection : #Nethttp.http_header -> string list -> unit
      val get_content_encoding : #Nethttp.http_header_ro -> string list
      val set_content_encoding : #Nethttp.http_header -> string list -> unit
      val get_content_language : #Nethttp.http_header_ro -> string list
      val set_content_language : #Nethttp.http_header -> string list -> unit
      val get_content_length : #Nethttp.http_header_ro -> int64
      val set_content_length : #Nethttp.http_header -> int64 -> unit
      val get_content_location : #Nethttp.http_header_ro -> string
      val set_content_location : #Nethttp.http_header -> string -> unit
      val get_content_md5 : #Nethttp.http_header_ro -> string
      val set_content_md5 : #Nethttp.http_header -> string -> unit
      val get_content_range :
        #Nethttp.http_header_ro ->
        [ `Bytes of (int64 * int64) option * int64 option ]
      val set_content_range :
        #Nethttp.http_header ->
        [ `Bytes of (int64 * int64) option * int64 option ] -> unit
      val get_content_type :
        #Nethttp.http_header_ro -> string * (string * string) list
      val set_content_type :
        #Nethttp.http_header -> string * (string * string) list -> unit
      val get_date : #Nethttp.http_header_ro -> float
      val set_date : #Nethttp.http_header -> float -> unit
      val get_etag : #Nethttp.http_header_ro -> Nethttp.etag
      val set_etag : #Nethttp.http_header -> Nethttp.etag -> unit
      val get_expect :
        #Nethttp.http_header_ro ->
        (string * string option * (string * string) list) list
      val set_expect :
        #Nethttp.http_header ->
        (string * string option * (string * string) list) list -> unit
      val get_expires : #Nethttp.http_header_ro -> float
      val set_expires : #Nethttp.http_header -> float -> unit
      val get_from : #Nethttp.http_header_ro -> string
      val set_from : #Nethttp.http_header -> string -> unit
      val get_host : #Nethttp.http_header_ro -> string * int option
      val set_host : #Nethttp.http_header -> string * int option -> unit
      val get_if_match : #Nethttp.http_header_ro -> Nethttp.etag list option
      val set_if_match :
        #Nethttp.http_header -> Nethttp.etag list option -> unit
      val get_if_modified_since : #Nethttp.http_header_ro -> float
      val set_if_modified_since : #Nethttp.http_header -> float -> unit
      val get_if_none_match :
        #Nethttp.http_header_ro -> Nethttp.etag list option
      val set_if_none_match :
        #Nethttp.http_header -> Nethttp.etag list option -> unit
      val get_if_range :
        #Nethttp.http_header_ro -> [ `Date of float | `Etag of Nethttp.etag ]
      val set_if_range :
        #Nethttp.http_header ->
        [ `Date of float | `Etag of Nethttp.etag ] -> unit
      val get_if_unmodified_since : #Nethttp.http_header_ro -> float
      val set_if_unmodified_since : #Nethttp.http_header -> float -> unit
      val get_last_modified : #Nethttp.http_header_ro -> float
      val set_last_modified : #Nethttp.http_header -> float -> unit
      val get_location : #Nethttp.http_header_ro -> string
      val set_location : #Nethttp.http_header -> string -> unit
      val get_max_forwards : #Nethttp.http_header_ro -> int
      val set_max_forwards : #Nethttp.http_header -> int -> unit
      val get_pragma :
        #Nethttp.http_header_ro -> (string * string option) list
      val set_pragma :
        #Nethttp.http_header -> (string * string option) list -> unit
      val get_proxy_authenticate :
        #Nethttp.http_header_ro -> Nethttp.Header.auth_challenge list
      val set_proxy_authenticate :
        #Nethttp.http_header -> Nethttp.Header.auth_challenge list -> unit
      val get_proxy_authorization :
        #Nethttp.http_header_ro -> Nethttp.Header.auth_credentials
      val set_proxy_authorization :
        #Nethttp.http_header -> Nethttp.Header.auth_credentials -> unit
      val get_range :
        #Nethttp.http_header_ro ->
        [ `Bytes of (int64 option * int64 option) list ]
      val set_range :
        #Nethttp.http_header ->
        [ `Bytes of (int64 option * int64 option) list ] -> unit
      val get_referer : #Nethttp.http_header_ro -> string
      val get_referrer : #Nethttp.http_header_ro -> string
      val set_referer : #Nethttp.http_header -> string -> unit
      val set_referrer : #Nethttp.http_header -> string -> unit
      val get_retry_after :
        #Nethttp.http_header_ro -> [ `Date of float | `Seconds of int ]
      val set_retry_after :
        #Nethttp.http_header -> [ `Date of float | `Seconds of int ] -> unit
      val get_server : #Nethttp.http_header_ro -> string
      val set_server : #Nethttp.http_header -> string -> unit
      val get_te :
        #Nethttp.http_header_ro ->
        (string * (string * string) list * (string * string) list) list
      val set_te :
        #Nethttp.http_header ->
        (string * (string * string) list * (string * string) list) list ->
        unit
      val get_trailer : #Nethttp.http_header_ro -> string list
      val set_trailer : #Nethttp.http_header -> string list -> unit
      val get_transfer_encoding :
        #Nethttp.http_header_ro -> (string * (string * string) list) list
      val set_transfer_encoding :
        #Nethttp.http_header ->
        (string * (string * string) list) list -> unit
      val get_upgrade : #Nethttp.http_header_ro -> string list
      val set_upgrade : #Nethttp.http_header -> string list -> unit
      val get_user_agent : #Nethttp.http_header_ro -> string
      val set_user_agent : #Nethttp.http_header -> string -> unit
      val get_vary :
        #Nethttp.http_header_ro -> [ `Fields of string list | `Star ]
      val set_vary :
        #Nethttp.http_header -> [ `Fields of string list | `Star ] -> unit
      val get_www_authenticate :
        #Nethttp.http_header_ro -> Nethttp.Header.auth_challenge list
      val set_www_authenticate :
        #Nethttp.http_header -> Nethttp.Header.auth_challenge list -> unit
      val get_cookie : #Nethttp.http_header_ro -> (string * string) list
      val get_cookie_ct : #Nethttp.http_header_ro -> Nethttp.Cookie.t list
      val set_cookie : #Nethttp.http_header -> (string * string) list -> unit
      val get_set_cookie :
        #Nethttp.http_header_ro -> Nethttp.netscape_cookie list
      val set_set_cookie :
        #Nethttp.http_header -> Nethttp.netscape_cookie list -> unit
      val set_set_cookie_ct :
        #Nethttp.http_header -> Nethttp.Cookie.t list -> unit
    end
  type transport_layer_id = int
  val new_trans_id : unit -> Nethttp.transport_layer_id
  val http_trans_id : Nethttp.transport_layer_id
  val https_trans_id : Nethttp.transport_layer_id
  val spnego_trans_id : Nethttp.transport_layer_id
  val proxy_only_trans_id : Nethttp.transport_layer_id
  type match_result =
      [ `Accept of string * string option
      | `Accept_reroute of
          string * string option * Nethttp.transport_layer_id
      | `Reject
      | `Reroute of string * Nethttp.transport_layer_id ]
  module type HTTP_CLIENT_MECHANISM =
    sig
      val mechanism_name : string
      val available : unit -> bool
      val restart_supported : bool
      type credentials
      val init_credentials :
        (string * string * (string * string) list) list ->
        Nethttp.HTTP_CLIENT_MECHANISM.credentials
      val client_match :
        params:(string * string * bool) list ->
        Nethttp.Header.auth_challenge -> Nethttp.match_result
      type client_session
      val client_state :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
        Netsys_sasl_types.client_state
      val create_client_session :
        user:string ->
        creds:Nethttp.HTTP_CLIENT_MECHANISM.credentials ->
        params:(string * string * bool) list ->
        unit -> Nethttp.HTTP_CLIENT_MECHANISM.client_session
      val client_configure_channel_binding :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
        Netsys_sasl_types.cb -> Nethttp.HTTP_CLIENT_MECHANISM.client_session
      val client_restart :
        params:(string * string * bool) list ->
        Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
        Nethttp.HTTP_CLIENT_MECHANISM.client_session
      val client_process_challenge :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
        string ->
        string ->
        #Nethttp.http_header_ro ->
        Nethttp.Header.auth_challenge ->
        Nethttp.HTTP_CLIENT_MECHANISM.client_session
      val client_emit_response :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
        string ->
        string ->
        #Nethttp.http_header_ro ->
        Nethttp.HTTP_CLIENT_MECHANISM.client_session *
        Nethttp.Header.auth_credentials * (string * string) list
      val client_channel_binding :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session -> Netsys_sasl_types.cb
      val client_user_name :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string
      val client_stash_session :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string
      val client_resume_session :
        string -> Nethttp.HTTP_CLIENT_MECHANISM.client_session
      val client_session_id :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string option
      val client_domain :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string list
      val client_prop :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string -> string
      val client_gssapi_props :
        Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
        Netsys_gssapi.client_props
    end
  val rev_split : (char -> bool) -> string -> string list
  val qstring_of_value : string -> string
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_kernel.http_protocol_hooks.html0000644000175000017500000004170612731530353025574 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_protocol_hooks object
  method tls_set_cache :
    store:(string -> string -> unit) ->
    remove:(string -> unit) -> retrieve:(string -> string) -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Shell_uq.html0000644000175000017500000004610212731530353020107 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_uq sig
  class type ['t] job_handler_engine_type =
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method job : Shell_sys.job
      method job_instance : Shell_sys.job_instance
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        ('Uq_engines.engine -> bool) -> unit
      method state : 'Uq_engines.engine_state
    end
  class call_engine :
    ?ignore_error_code:bool ->
    ?mode:Shell_sys.group_mode ->
    ?stdin:Shell.producer ->
    ?stdout:Shell.consumer ->
    ?stderr:Shell.consumer ->
    Shell_sys.command list ->
    Unixqueue.event_system -> [Shell_sys.job_status] job_handler_engine_type
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.socket_descr.html0000644000175000017500000004143212731530353023245 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.socket_descr ?blocking:bool ->
?start_pos_in:int ->
?start_pos_out:int ->
?fd_style:Netsys.fd_style -> Unix.file_descr -> Netchannels.raw_io_channel
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram.Cryptosystem.html0000644000175000017500000004562012731530353023633 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram.Cryptosystem sig
  exception Integrity_error
  val derive_keys : string -> int -> Netmech_scram.specific_keys
  val encrypt_and_sign : Netmech_scram.specific_keys -> string -> string
  val encrypt_and_sign_mstrings :
    Netmech_scram.specific_keys ->
    Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
  val decrypt_and_verify : Netmech_scram.specific_keys -> string -> string
  val decrypt_and_verify_mstrings :
    Netmech_scram.specific_keys ->
    Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
  val get_ec : Netmech_scram.specific_keys -> int -> int
  val get_mic : Netmech_scram.specific_keys -> string -> string
  val get_mic_mstrings :
    Netmech_scram.specific_keys -> Netxdr_mstring.mstring list -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.augment_raw_in_channel.html0000644000175000017500000004353312731530353025270 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.augment_raw_in_channel object
  method virtual close_in : unit -> unit
  method virtual input : Bytes.t -> int -> int -> int
  method input_byte : unit -> int
  method input_char : unit -> char
  method input_line : unit -> string
  method virtual pos_in : int
  method really_input : Bytes.t -> int -> int -> unit
  method really_input_string : int -> string
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.watchdog.html0000644000175000017500000004115412731530353022231 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.watchdog float -> '#Uq_engines.engine -> [unit] Uq_engines.engineocamlnet-4.1.2/doc/html-main/Netcgi_common.rw_cgi_argument-c.html0000644000175000017500000004346312731530353023455 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.rw_cgi_argument

Class type Netcgi_common.rw_cgi_argument

class type rw_cgi_argument = object .. end
Deprecated.Arguments are read-only.
See Netcgi.rw_cgi_argument.
Inherits
method ro : bool
method set_value : string -> unit
method open_value_wr : unit -> Netchannels.out_obj_channel
ocamlnet-4.1.2/doc/html-main/Nethttp.Cookie.html0000644000175000017500000006740612731530353020142 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.Cookie

Module Nethttp.Cookie

module Cookie: sig .. end

type t 
Functions to manipulate cookies.

You should know that besides the name and value attribute, user agents will send at most the path, domain and port and usually will not send them at all.

For interoperability, cookies are set using version 0 (by Netscape) unless version 1 (RFC 2965 and the older RFC 2109) fields are set. While version 0 is well supported by browsers, RFC 2109 requires a recent browser and RFC 2965 is usually not supported. You do not have to worry however, cookies are always sent in such a way older browsers understand them -- albeit not all attributes of course -- so your application can be ready for the time RFC 2965 will be the norm.

This cookie representation is preferred over the Netscape-only type Nethttp.netscape_cookie.

N.B. This module appears also as Netcgi.Cookie.

Mutable cookie type

val make : ?max_age:int ->
?domain:string ->
?path:string ->
?secure:bool ->
?comment:string ->
?comment_url:string ->
?ports:int list -> string -> string -> t
make ?expires ?domain ?path ?secure name value creates a new cookie with name name holding value.
max_age : see Netcgi.Cookie.set_max_age. Default: when user agent exits.
domain : see Netcgi.Cookie.set_domain. Default: hostname of the server.
path : see Netcgi.Cookie.set_path. Default: script name + path_info.
secure : see Netcgi.Cookie.set_secure. Default: false.
comment : see Netcgi.Cookie.set_comment. Default: "".
comment_url : see Netcgi.Cookie.set_comment_url. Default: "".
ports : see Netcgi.Cookie.set_ports. Default: same port the cookie was sent.
val name : t -> string
The name of the cookie.
val value : t -> string
The value of the cookie.
val domain : t -> string option
The domain of the cookie, if set.
val path : t -> string option
The path of the cookie, if set.
val ports : t -> int list option
port c the ports to which the cookie may be returned or [] if not set.
val max_age : t -> int option
The expiration time of the cookie, in seconds. None means that the cookie will be discarded when the browser exits. This information is not returned by the browser.
val secure : t -> bool
Tells whether the cookie is secure. This information is not returned by the browser.
val comment : t -> string
Returns the comment associated to the cookie or "" if it does not exists. This information is not returned by the browser.
val comment_url : t -> string
Returns the comment URL associated to the cookie or "" if it does not exists. This information is not returned by the browser.
val set_value : t -> string -> unit
set_value c v sets the value of the cookie c to v.
val set_max_age : t -> int option -> unit
set_max_age c (Some t) sets the lifetime of the cookie c to t seconds. If t <= 0, it means that the cookie should be discarded immediately. set_expires c None tells the cookie to be discarded when the user agent exits. (Despite the fact that the name is borrowed from the version 1 of the specification, it works transparently with version 0.)
val set_domain : t -> string option -> unit
Cookies are bound to a certain domain, i.e. the browser sends them only when web pages of the domain are requested:
  • None: the domain is the hostname of the server.
  • Some domain: the domain is domain.

val set_path : t -> string option -> unit
Cookies are also bound to certain path prefixes, i.e. the browser sends them only when web pages at the path or below are requested.
  • None: the path is script name + path_info
  • Some p: the path is p. With Some "/" you can disable the path restriction completely.

val set_secure : t -> bool -> unit
Cookies are also bound to the type of the web server: set_secure false means servers without SSL, set_secure true means servers with activated SSL ("https").
val set_comment : t -> string -> unit
set_comment c s sets the comment of the cookie c to s which must be UTF-8 encoded (RFC 2279). Because cookies can store personal information, the comment should describe how the cookie will be used so the client can decide whether to allow the cookie or not. To cancel a comment, set it to "".

Cookie version 1 (RFC 2109).

val set_comment_url : t -> string -> unit
set_comment_url c url same as Netcgi.Cookie.set_comment except that the cookie comment is available on the page pointed by url. To cancel, set it to "".

Cookie version 1 (RFC 2965).

val set_ports : t -> int list option -> unit
set ports c (Some p) says that the cookie c must only be returned if the server request comes from one of the listed ports. If p = [], the cookie will only be sent to the request-port it was received from. set_ports c None says that the cookie may be sent to any port.

Cookie version 1 (RFC 2965).

val of_netscape_cookie : Nethttp.netscape_cookie -> t
Convert a Netscape cookie to the new representation
val to_netscape_cookie : t -> Nethttp.netscape_cookie
Convert to Netscape cookie (with information loss)
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_modes.Add_modes.html0000644000175000017500000006234112731530353023227 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes.Add_modes

Functor Netsys_crypto_modes.Add_modes

module Add_modes: 
Returns a new crypto module where missing modes are added for all ECB ciphers. The added modes are CBC, OFB, and CTR. Existing ciphers are returned unchanged.
Parameters:
SC : Netsys_crypto_types.SYMMETRIC_CRYPTO


Symmetric cryptographic ciphers.

Users should not call functions of the provider directly, but use Netsys_ciphers, or another higher-level layer.

type scipher 
Describes a cipher
val ciphers : scipher list
List of supported ciphers. OCamlnet implements a number of modes anyway, and it is normally only required to implement "ECB" here. If there is special hardware acceleration, though, it is an option to provide accelerated modes too (e.g. some CPUs support AES-GCM specially).
val find : string * string -> scipher
find (name,mode): Looks up a cipher by name and mode, or raises Not_found
val name : scipher -> string
Returns the name. This should follow the convention <uppercasestring>-<size>, e.g. "AES-128" or "TWOFISH-128". The size is normally the key size.
val mode : scipher -> string
Returns the mode. Modes are "ECB", "CBC", "OFB", "CTR", "STREAM", "GCM".

Note that the mode needs not to deal with padding (this is done on a higher level).

val key_lengths : scipher -> (int * int) list
Supported key lengths as pairs min,max. If there is a recommended key length, this should be the first.
val iv_lengths : scipher -> (int * int) list
Supported iv lengths as pairs min,max. If there is a recommended iv length, this should be the first.
val block_constraint : scipher -> int
The buffers used with encrypt/decrypt must have a length that is a multiple of this number. (In ECB mode, this is the block size.)
val supports_aead : scipher -> bool
Whether this cipher integrates authentication
type scipher_ctx 
A cipher context stores processing data while encrypting or decrypting data
val create : scipher ->
string -> scipher_ctx
create c key: create a new cipher context for key. If not set, the initialization vector is zero, and the header the empty string.
val set_iv : scipher_ctx -> string -> unit
set_iv cctx iv: Sets the initialization vector. This is only allowed before encrypting or decrypting data
val set_header : scipher_ctx -> string -> unit
set_header cctx data: Sets the additional header that is authenticated for AEAD schemes. The header must have been set before starting the encryption or decryption (otherwise it is assumed to be the empty string).

For non-AEAD schemes, the header is ignored for encryption, and must be empty for decryption.

val encrypt : scipher_ctx ->
Netsys_types.memory -> Netsys_types.memory -> unit
encrypt cctx inbuf outbuf: Encrypts the data in inbuf and writes the result into outbuf. Both buffers must have the same size. It is not allowed to pass the same buffer as inbuf and outbuf.

In order to encrypt long texts, it is allowed to call encrypt several times in sequence.

val decrypt : scipher_ctx ->
Netsys_types.memory -> Netsys_types.memory -> bool
decrypt cctx inbuf outbuf: Decrypts the data in inbuf and writes the result into outbuf. Both buffers must have the same size. It is not allowed to pass the same buffer as inbuf and outbuf.

The function returns true on success, and false if a problem is detected.

In order to decrypt long texts, it is allowed to call decrypt several times in sequence.

val mac : scipher_ctx -> string
Returns the MAC for AEAD ciphers. This is updated after encrypt/decrypt. This function fails for non-AEAD ciphers.
ocamlnet-4.1.2/doc/html-main/Netmcore_heap.Debug.html0000644000175000017500000004160212731530353021070 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_heap.Debug

Module Netmcore_heap.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/Rpc_proxy.html0000644000175000017500000012060712731530353017262 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_proxy

Module Rpc_proxy

module Rpc_proxy: sig .. end
RPC proxies


The Rpc_proxy module provides an improved reliability layer on top of Rpc_client. This layer especially features:
  • automatic connection management: TCP connections are started and terminated as needed
  • multiple connections can be held in parallel to a remote server to increase concurrency on the server
  • failover to other servers when the orignal servers time out
  • support for an initial ping at connection establishment time to test the availability of the connection
  • retransmission of idempotent RPC calls
Proxies can only handle stream connections (TCP and Unix Domain). Also, the remote endpoints must already be specified by socket addresses. (No portmapper and other indirect lookup methods.)

The proxy functionality is implemented in two layers, the managed clients, and the managed sets. The former layer can handle only one TCP connection (with reconnect), whereas the latter is able to manage a bunch of connections to the same service. Both layers can profit from a reliability cache that knows which services had errors in the past.

See below for a tutorial.

There is also a blog article explaining RPC proxies: The next server, please!

module ReliabilityCache: sig .. end
module ManagedClient: sig .. end
module ManagedSet: sig .. end

The Rpc_proxy tutorial

Managed clients

A normal RPC client has a very limited lifecylce: It is created, then a connection is made to an RPC service, messages are exchanged, and finally the connection is terminated. After that the client becomes unusable. In short, it is "use once" client.

In contrast to this, managed clients can be recycled. This is especially useful for dealing with socket errors, and connection terminations triggered by the RPC server.

How to use managed clients: For a normal RPC client the generator ocamlrpcgen creates all required glue code to easily start RPC calls. For example, if a file proto.x is taken as input for ocamlrpcgen, a piece of code doing a call could look like:

 
      let client =
        Proto_clnt.PROG.VERS.create_client connector protocol
      let result =
        Proto_clnt.PROG.VERS.procedure client argument
   

(Here, PROG, VERS, procedure are just placeholders for the name of the program, the version identifier, and the procedure name.)

For RPC proxies, however, this is slightly more complicated. ocamlrpcgen does not produce a managed client that is ready for use. Instead, only a functor is provided that can take the Rpc_proxy.ManagedlClient module as input:

      module M = Proto_clnt.Make'PROG(Rpc_proxy.ManagedClient)

      let esys =
        Unixqueue.create_unix_event_system()
      let mclient_config =
        Rpc_proxy.ManagedClient.create_mclient_config
          ~programs:[ Proto_clnt.PROG.VERS._program ]
          () in
      let mclient =
        Rpc_proxy.ManagedClient.create_mclient mclient_config connector esys
      let result =
        M.VERS.procedure mclient argument
   

(The functor approach has been chosen, because it gives the user more flexibility - it is possible to apply the functor on other implementations of improved clients than Rpc_proxy.ManagedClient.)

Note that esys is always explicit, even in the case the user only performs synchronous calls - the user should create a new esys then, pass it to mclient, and ignore it otherwise.

Now, how does the recycling feature work? The managed client can be in one of three states:

  • `Down: The client is not connected. This is the initial state, and the state after errors and terminated connections (no matter whether triggered by the client or by the server)
  • `Connecting: The client is busy (re)connecting (only used in some cases)
  • `Up sockaddr: The client is connected and has the socket address sockaddr
The state can be queried with Rpc_proxy.ManagedClient.mclient_state. When it is `Down, the next RPC call automatically starts the reconnect to the service. When the connection is established, the call is done, and the messages are exchanged that are representing the call. After that, the state remains `Up after the call.

When the call stops because of an error, the error is reported to the user in the normal way, and the client is shut down, i.e. after an error the state is `Down. If the user decides to try the call again, the client automatically reconnects following the outlined rules. Note that managed clients never automatically retry calls by themselves.

When the TCP connection is regularly shut down (either by the server or by the client calling Rpc_proxy.ManagedClient.shut_down), the client state is changed to `Down at the next opportunity. Especially a server-driven shutdown may first be detected when the next RPC call is tried on the connection. This may or may not lead to an error depending on the exact timing. In any way, the connection is finally established again.

Of course, managed clients must be shut down after use, because there is no other (automatic) way of recognizing that they are no longer used. Call Rpc_proxy.ManagedClient.shut_down for this.

Managed client also have a few more features that can be enabled in mclient_config, especially:

  • Initial ping: This means that the TCP connection is tested before being used for user operations. The test is done by pinging the service once (via the RPC null procedure). This is recommended because some connectivity problems can first be detected when the TCP connection is actually used.
  • Idle timeout: The TCP connection is closed after it is idle for some period of time. "Idle" means here that nothing is being transmitted, and that no response from the server is expected. The connection is closed at the first opportunity. The user should be aware that this can only happen when the event loop for esys is running. Especially for synchronous calls this is typically not the case, so one would have to call Unixqueue.run esys now and then to create opportunities for detecting the idle timeout.
  • Reliability cache: The cache object counts errors, and can disable certain service endpoints if they only produce errors. This mostly makes sense when there are alternative endpoints, i.e. in the context of a managed set (see below).


The Rpc_proxy tutorial

Managed clients

A normal RPC client has a very limited lifecylce: It is created, then a connection is made to an RPC service, messages are exchanged, and finally the connection is terminated. After that the client becomes unusable. In short, it is "use once" client.

In contrast to this, managed clients can be recycled. This is especially useful for dealing with socket errors, and connection terminations triggered by the RPC server.

How to use managed clients: For a normal RPC client the generator ocamlrpcgen creates all required glue code to easily start RPC calls. For example, if a file proto.x is taken as input for ocamlrpcgen, a piece of code doing a call could look like:

 
      let client =
        Proto_clnt.PROG.VERS.create_client connector protocol
      let result =
        Proto_clnt.PROG.VERS.procedure client argument
   

(Here, PROG, VERS, procedure are just placeholders for the name of the program, the version identifier, and the procedure name.)

For RPC proxies, however, this is slightly more complicated. ocamlrpcgen does not produce a managed client that is ready for use. Instead, only a functor is provided that can take the Rpc_proxy.ManagedlClient module as input:

      module M = Proto_clnt.Make'PROG(Rpc_proxy.ManagedClient)

      let esys =
        Unixqueue.create_unix_event_system()
      let mclient_config =
        Rpc_proxy.ManagedClient.create_mclient_config
          ~programs:[ Proto_clnt.PROG.VERS._program ]
          () in
      let mclient =
        Rpc_proxy.ManagedClient.create_mclient mclient_config connector esys
      let result =
        M.VERS.procedure mclient argument
   

(The functor approach has been chosen, because it gives the user more flexibility - it is possible to apply the functor on other implementations of improved clients than Rpc_proxy.ManagedClient.)

Note that esys is always explicit, even in the case the user only performs synchronous calls - the user should create a new esys then, pass it to mclient, and ignore it otherwise.

Now, how does the recycling feature work? The managed client can be in one of three states:

  • `Down: The client is not connected. This is the initial state, and the state after errors and terminated connections (no matter whether triggered by the client or by the server)
  • `Connecting: The client is busy (re)connecting (only used in some cases)
  • `Up sockaddr: The client is connected and has the socket address sockaddr
The state can be queried with Rpc_proxy.ManagedClient.mclient_state. When it is `Down, the next RPC call automatically starts the reconnect to the service. When the connection is established, the call is done, and the messages are exchanged that are representing the call. After that, the state remains `Up after the call.

When the call stops because of an error, the error is reported to the user in the normal way, and the client is shut down, i.e. after an error the state is `Down. If the user decides to try the call again, the client automatically reconnects following the outlined rules. Note that managed clients never automatically retry calls by themselves.

When the TCP connection is regularly shut down (either by the server or by the client calling Rpc_proxy.ManagedClient.shut_down), the client state is changed to `Down at the next opportunity. Especially a server-driven shutdown may first be detected when the next RPC call is tried on the connection. This may or may not lead to an error depending on the exact timing. In any way, the connection is finally established again.

Of course, managed clients must be shut down after use, because there is no other (automatic) way of recognizing that they are no longer used. Call Rpc_proxy.ManagedClient.shut_down for this.

Managed client also have a few more features that can be enabled in mclient_config, especially:

  • Initial ping: This means that the TCP connection is tested before being used for user operations. The test is done by pinging the service once (via the RPC null procedure). This is recommended because some connectivity problems can first be detected when the TCP connection is actually used.
  • Idle timeout: The TCP connection is closed after it is idle for some period of time. "Idle" means here that nothing is being transmitted, and that no response from the server is expected. The connection is closed at the first opportunity. The user should be aware that this can only happen when the event loop for esys is running. Especially for synchronous calls this is typically not the case, so one would have to call Unixqueue.run esys now and then to create opportunities for detecting the idle timeout.
  • Reliability cache: The cache object counts errors, and can disable certain service endpoints if they only produce errors. This mostly makes sense when there are alternative endpoints, i.e. in the context of a managed set (see below).


Managed Sets

Managed sets are another layer on top of the managed clients. These sets are able to manage several connections where each is implemented as managed client. The connections can go to the same server endpoint in order to parallelize RPCs at the client side, or to several server endpoints that provide the same service. The latter can be used for client-driven load balancing, and for client-driven failover management of HA setups (HA = high availability).

For creating a managed set, the code looks like

      module M = Proto_clnt.Make'PROG(Rpc_proxy.ManagedClient)

      let esys =
        Unixqueue.create_unix_event_system()
      let mclient_config =
        Rpc_proxy.ManagedClient.create_mclient_config
          ~programs:[ Proto_clnt.PROG.VERS._program ]
          () in
      let mset_config =
        Rpc_proxy.ManagedSet.create_mset_config
          ~mclient_config
          () in
      let services =
        [| connector, n_connections; ... |] in
      let mset =
        Rpc_proxy.ManagedSet.create_mset 
          mset_config 
          services
          esys in
      let mclient, idx =
        Rpc_proxy.ManagedSet.mset_pick mset in
      let result =
        M.VERS.procedure mclient argument
    

The managed clients are internally created by the set - one only should pass in mclient_config so the set knows what kind of client is preferred. For the simple application of maintaining several connections to the same server, one would create the mset with a one-element service array:

       let services =
          [| connector, n_connections |]
    

where connector describes the server port, and n_connections is the maximum number of connections to create and maintain. The Rpc_proxy.ManagedSet.mset_pick function creates internally up to n_connections managed clients, and returns one of them. By default, it is not guaranteed that the client is idle (meaning no previous call is pending) - if the connections are all already busy, mset_pick starts returning busy connections (but the least busy one first).

There are a number of options allowing to modify the default behavior:

  • One can enforce that only idle clients are returned by mset_pick. To do this, pass the argument ~mset_pending_calls_max:1 to Rpc_proxy.ManagedSet.create_mset_config. It can then happen that no client is idle, and mset_pick will raise Rpc_proxy.ManagedSet.Cluster_service_unavailable.
  • If the services array has more than one element, they are considered as equivalent service endpoints. mset_pick will pick one of the endpoints. There are two policies controlling the selection: With ~policy:`Balance_load it is aimed at sending roughly the same number of calls to all endpoints. With ~policy:`Failover the services are assigned precedences by the position in the array (i.e. the first service is used as long as possible, then the second service is used, etc.). The policy argument is again to be passed to Rpc_proxy.ManagedSet.create_mset_config.
Of course, managed sets must be shut down after use, because there is no other (automatic) way of recognizing that they are no longer used. Call Rpc_proxy.ManagedSet.shut_down for this.

Caching reliability data

The cache allows to disable certain hosts or ports when the error counter reaches a limit. The service is disabled for a limited time span. This is especially useful when there is an alternate port that can jump in for the failing one, i.e. when the services array of a managed set has two or more elements.

There is a single global cache object, but one can also create specific cache objects. Generally, cache objects can be shared by many managed clients and managed sets. The hope is that sharing is useful because more data can be made available to users of services. If you do not want to use the global cache object, you can create your own, and configure it in mclient_config.

The global cache object is automatically used when nothing else is specified. The global cache object is by default configured in a way so it does not have any effect, though. So we have to change this in order to enable the cache:

     let rcache_config =
       Rpc_proxy.ReliabilityCache.create_rcache_config
        ~policy:`Independent
        ~threshold:3
        () in
     Rpc_proxy.ReliabilityCache.set_global_rcache_config rcache_config
   

This means that 3 errors in sequence disable a service port. `Independent means that each port is handled independently in this respect.

At the first time, the port is only disabled for one second. The duration of the time span is increased by each additional error until it reaches 64 seconds. These durations can be changed, of course.

As the impact of changing the global cache object is sometimes unpredictable, one can also create a private cache object (Rpc_proxy.ReliabilityCache.create_rcache). Another way is to derive a semi-private object from the global one. This means that the error counters are global, but the interpretation can be set individually in each use. This would look like:

    let rcache_config =
      Rpc_proxy.ReliabilityCache.create_rcache_config
        ~policy:`Independent
        ~threshold:3
        () in
    let rcache =
      Rpc_proxy.ReliabilityCache.derive_rcache
        (Rpc_proxy.ReliabilityCache.global_rcache())
        rcache_config in
    ...
    let mclient_config =
      Rpc_proxy.ManagedClient.create_mclient_config
        ...
        ~rcache
        ...
        ()
    

Idempotent calls

In the layer of managed sets there is some limited support for automatically repeating failing idempotent RPC calls.

Instead of calling the RPC with

      let mclient, idx =
        Rpc_proxy.ManagedSet.mset_pick mset in
      let result =
        M.VERS.procedure mclient argument
    

one uses

      let result =
        Rpc_proxy.ManagedSet.idempotent_sync_call
          mset
          M.VERS.procedure'async
          argument
    

The effet is that Rpc_proxy.ManagedSet.idempotent_sync_call repeats automatically the call when an error occurs. It is assumed that the call is idempotent so it can be repeated without changing the meaning.

The call may be repeated several times. This is configured in the managed set mset (parameter mset_idempotent_max).

Note that one has to pass the asynchronous version (suffix 'async) of the RPC wrapper even when doing a synchronous call.

Also see the documentation for Rpc_proxy.ManagedSet.idempotent_async_call.
ocamlnet-4.1.2/doc/html-main/type_Netshm_data.html0000644000175000017500000004672512731530353020575 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm_data sig
  type 'a data_manager = {
    to_int32_array : '-> Netshm.int32_array;
    of_int32_array : Netshm.int32_array list -> 'a;
    of_int32_array_prefix : (Netshm.int32_array list -> 'a option) option;
    hash_fn : '-> int32;
  }
  val int32_manager : int32 Netshm_data.data_manager
  val int64_manager : int64 Netshm_data.data_manager
  val nativeint_manager : nativeint Netshm_data.data_manager
  val int_manager : int Netshm_data.data_manager
  val int32_array_manager : Netshm.int32_array Netshm_data.data_manager
  val string_manager : string Netshm_data.data_manager
  val pair_manager :
    'Netshm_data.data_manager ->
    'Netshm_data.data_manager -> ('a * 'b) Netshm_data.data_manager
  val left_pair_manager :
    'Netshm_data.data_manager -> 'Netshm_data.data_manager
  val option_manager :
    'Netshm_data.data_manager -> 'a option Netshm_data.data_manager
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_digest_http.Make_digest.html0000644000175000017500000004115012731530353024525 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http.Make_digest functor (P : PROFILE-> Nethttp.HTTP_CLIENT_MECHANISMocamlnet-4.1.2/doc/html-main/type_Netcgi.simple_argument.html0000644000175000017500000004105412731530353022737 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.simple_argument ?ro:bool -> string -> string -> Netcgi.rw_cgi_argumentocamlnet-4.1.2/doc/html-main/Uq_engines.cache-c.html0000644000175000017500000004272612731530353020661 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.cache

Class Uq_engines.cache

class ['a] cache : (Unixqueue.event_system -> 'a engine) -> Unixqueue.event_system -> ['a] cache_t
new cache f esys: A cache that runs f esys to obtain values

ocamlnet-4.1.2/doc/html-main/Uq_transfer.input_async_mplex-c.html0000644000175000017500000004342212731530353023545 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.input_async_mplex

Class Uq_transfer.input_async_mplex

class input_async_mplex : ?onshutdown:onshutdown_in_spec -> ?buffer_size:int -> Uq_engines.multiplex_controller -> async_in_channel_engine
Creates an asynchronous input channel reading from the multiplex controller.

onshutdown: See output_async_mplex.

buffer_size: The size of the internal buffer. By default unlimited.

Note that the engine is done when the input channel is closed. The socket is not shut down, and the underlying file descriptor is not closed! You can define the shutdown callback to do something in this case.


ocamlnet-4.1.2/doc/html-main/type_Netmime.wrap_mime_header.html0000644000175000017500000004101112731530353023212 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.wrap_mime_header #Netmime.mime_header -> Netmime.mime_headerocamlnet-4.1.2/doc/html-main/Uq_engines_compat.input_async_mplex-c.html0000644000175000017500000004244412731530353024717 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.input_async_mplex

Class Uq_engines_compat.input_async_mplex

class input_async_mplex : ?onshutdown:onshutdown_in_spec -> ?buffer_size:int -> multiplex_controller -> async_in_channel_engine

ocamlnet-4.1.2/doc/html-main/Netcgi_cgi.html0000644000175000017500000004612712731530353017334 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_cgi

Module Netcgi_cgi

module Netcgi_cgi: sig .. end
Classical CGI connector.

CGI scripts have poor performance as they are entirely re-run for each request (so it is not possible to cache in the running program database connections for example). Still they are suitable for moderate frequented websites (especially because they run everywhere) and for development.


val run : ?config:Netcgi.config ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?exn_handler:Netcgi.exn_handler -> (Netcgi.cgi -> unit) -> unit
run f executes f cgi for each cgi request. Contrarily to the other connectors, CGI execute the whole code (even the one outside f) each time the script is accessed. Therefore, one cannot easily cache database connections,...
config : Default: Netcgi.default_config
output_type : Default: `Direct ""
arg_store : Default: `Automatic for all arguments.
exn_handler : See Netcgi.exn_handler. Default: delegate all exceptions to the default handler.
val is_cgi : unit -> bool
is_cgi says whether the script is run in a CGI environment. This allows for example to call the Netcgi_test module if it is not.
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.async_in_channel_engine-c.html0000644000175000017500000004314112731530353025771 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.async_in_channel_engine

Class type Uq_engines_compat.async_in_channel_engine

class type async_in_channel_engine = object .. end
Inherits
ocamlnet-4.1.2/doc/html-main/type_Nettls_nettle_bindings.html0000644000175000017500000006166612731530353023050 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_nettle_bindings sig
  type net_nettle_cipher_t
  type net_nettle_cipher_ctx_t
  type net_nettle_gcm_aes_ctx_t
  type net_nettle_hash_t
  type net_nettle_hash_ctx_t
  val net_nettle_ciphers :
    unit -> Nettls_nettle_bindings.net_nettle_cipher_t array
  val net_ext_ciphers :
    unit -> Nettls_nettle_bindings.net_nettle_cipher_t array
  val net_nettle_cipher_name :
    Nettls_nettle_bindings.net_nettle_cipher_t -> string
  val net_nettle_create_cipher_ctx :
    Nettls_nettle_bindings.net_nettle_cipher_t ->
    Nettls_nettle_bindings.net_nettle_cipher_ctx_t
  val net_nettle_set_encrypt_key :
    Nettls_nettle_bindings.net_nettle_cipher_t ->
    Nettls_nettle_bindings.net_nettle_cipher_ctx_t -> Bytes.t -> unit
  val net_nettle_set_decrypt_key :
    Nettls_nettle_bindings.net_nettle_cipher_t ->
    Nettls_nettle_bindings.net_nettle_cipher_ctx_t -> Bytes.t -> unit
  val net_nettle_encrypt :
    Nettls_nettle_bindings.net_nettle_cipher_t ->
    Nettls_nettle_bindings.net_nettle_cipher_ctx_t ->
    int -> Netsys_mem.memory -> Netsys_mem.memory -> unit
  val net_nettle_decrypt :
    Nettls_nettle_bindings.net_nettle_cipher_t ->
    Nettls_nettle_bindings.net_nettle_cipher_ctx_t ->
    int -> Netsys_mem.memory -> Netsys_mem.memory -> unit
  val net_nettle_gcm_aes_init :
    unit -> Nettls_nettle_bindings.net_nettle_gcm_aes_ctx_t
  val nettle_gcm_aes_set_key :
    Nettls_nettle_bindings.net_nettle_gcm_aes_ctx_t -> Bytes.t -> unit
  val nettle_gcm_aes_set_iv :
    Nettls_nettle_bindings.net_nettle_gcm_aes_ctx_t -> Bytes.t -> unit
  val nettle_gcm_aes_update :
    Nettls_nettle_bindings.net_nettle_gcm_aes_ctx_t -> Bytes.t -> unit
  val nettle_gcm_aes_encrypt :
    Nettls_nettle_bindings.net_nettle_gcm_aes_ctx_t ->
    int -> Netsys_mem.memory -> Netsys_mem.memory -> unit
  val nettle_gcm_aes_decrypt :
    Nettls_nettle_bindings.net_nettle_gcm_aes_ctx_t ->
    int -> Netsys_mem.memory -> Netsys_mem.memory -> unit
  val nettle_gcm_aes_digest :
    Nettls_nettle_bindings.net_nettle_gcm_aes_ctx_t -> Bytes.t -> unit
  val net_have_gcm_aes : unit -> bool
  val net_nettle_hashes :
    unit -> Nettls_nettle_bindings.net_nettle_hash_t array
  val net_nettle_hash_name :
    Nettls_nettle_bindings.net_nettle_hash_t -> string
  val net_nettle_create_hash_ctx :
    Nettls_nettle_bindings.net_nettle_hash_t ->
    Nettls_nettle_bindings.net_nettle_hash_ctx_t
  val net_nettle_hash_init :
    Nettls_nettle_bindings.net_nettle_hash_t ->
    Nettls_nettle_bindings.net_nettle_hash_ctx_t -> unit
  val net_nettle_hash_update :
    Nettls_nettle_bindings.net_nettle_hash_t ->
    Nettls_nettle_bindings.net_nettle_hash_ctx_t -> Netsys_mem.memory -> unit
  val net_nettle_hash_digest :
    Nettls_nettle_bindings.net_nettle_hash_t ->
    Nettls_nettle_bindings.net_nettle_hash_ctx_t -> Bytes.t -> unit
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_util.html0000644000175000017500000004433012731530353020122 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_util

Module Nethttpd_util

module Nethttpd_util: sig .. end
Utility functions

val std_error_response : Nethttpd_types.error_response_params -> string
Returns the HTML text of the standard error response
val std_error_log_string : Nethttpd_types.request_info -> string -> string
Returns a log line for error logging
val std_access_log_string : Nethttpd_types.full_info -> string
Returns a log line for access logging
val std_debug_access_log_string : Nethttpd_types.full_info -> string
Returns a log string for extended access logging (multi-line)
ocamlnet-4.1.2/doc/html-main/Netsys_posix.html0000644000175000017500000046666112731530353020021 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_posix

Module Netsys_posix

module Netsys_posix: sig .. end
POSIX-specific system calls missing in the Unix module, and further API's from POSIX-style operating systems.


Files, Processes, TTYs, Users, Groups


val int_of_file_descr : Unix.file_descr -> int
Return the file descriptor as integer. See also Netsys.int64_of_file_descr which works for all OS.
val file_descr_of_int : int -> Unix.file_descr
Make a file descriptor from an integer
val sysconf_open_max : unit -> int
Return the maximum number of open file descriptor per process. It is also ensured that for every file descriptor fd: fd < sysconf_open_max()
val get_nonblock : Unix.file_descr -> bool
Returns whether the nonblock flag is set
val fchdir : Unix.file_descr -> unit
Set the current directory to the directory referenced by the file descriptor
val fdopendir : Unix.file_descr -> Unix.dir_handle
Make a directory handle from a file descriptor. The descriptor is then "owned" by the directory handle, and will be closed by Unix.closedir.

This function is useful in conjunction with Netsys_posix.openat to read directories relative to a parent directory.

This is a recent addition to the POSIX standard; be prepared to get Invalid_argument because it is unavailable.

val realpath : string -> string
Returns a pathname pointing to the same filesystem object so that the pathname does not include "." or ".." or symbolic links.
val getpgid : int -> int
Return the process group ID of the process with the passed PID. For the number 0, the process group ID of the current process is returned.
val getpgrp : unit -> int
Same as getpgid 0, i.e. returns the process group ID of the current process.
val setpgid : int -> int -> unit
setpgid pid pgid: Set the process group ID of the process pid to pgid. If pid = 0, the process group ID of the current process is changed. If pgid = 0, as process group ID the process ID of the process referenced by pid is used.

It is only possible for a process to join a process group if both belong to the same session.

val setpgrp : unit -> unit
Same as setpgid 0 0: A new process group ID is created, and the current process becomes its sole member.
val tcgetpgrp : Unix.file_descr -> int
Return the process group ID of the foreground process group of the session associated with the file descriptor, which must be a tty.
val tcsetpgrp : Unix.file_descr -> int -> unit
Sets the foreground process group ID of the session associated with the file descriptor, which must be a tty.
val ctermid : unit -> string
Returns the name of the controlling tty of the current process as pathname to a device file
val ttyname : Unix.file_descr -> string
Returns the name of the controlling tty referred to by the file descriptor.
val getsid : int -> int
Returns the session ID of the process with the passed PID. For the PID 0, the session ID of the current process is returned.
val with_tty : (Unix.file_descr -> unit) -> unit
with_tty f: Runs f fd where fd is the terminal of the process. If the process does not have a terminal (because it is a daemon) with_tty will fail.
val tty_read_password : ?tty:Unix.file_descr -> string -> string
tty_read_password prompt: If tty is a terminal, the prompt is printed, and a password is read from the terminal (echo off). If tty is not a terminal, no prompt is printed, and just a line is read from the tty descriptor (non-interactive case).

tty defaults to Unix.stdin. If this function is used in a program where stdin is not redirected, and the program is started in a terminal, it will read the password with prompt and echo disabled. If stdin is redirected, it is assumed that the program is used in a script, and the password is piped into it.

Use in conjunction with with_tty to ensure that tty is the terminal even if a redirection is in effect, e.g.

 with_tty (fun tty -> tty_read_password ~tty prompt) 

Raises Sys.Break if the user triggers SIGINT (i.e. presses CTRL-C) to abort the input of a password.

val posix_openpt : bool -> Unix.file_descr
posix_openpt noctty: Opens an unused PTY master.

noctty: If true, the descriptor will not become the controlling terminal.

If this function is not provided by the OS, an emulation is used.

On some OS, System V style PTY's are unavailable (but they get rare).

val grantpt : Unix.file_descr -> unit
Grant access to this PTY
val unlockpt : Unix.file_descr -> unit
Unlock a PTY master/slave pair
val ptsname : Unix.file_descr -> string
Get the name of the slave PTY
type node_type = 
| S_IFREG
| S_IFCHR of int
| S_IFBLK of int
| S_IFIFO
| S_IFSOCK
val mknod : string -> int -> node_type -> unit
Creates the node with the given permissions and the given type
val setreuid : int -> int -> unit
Changes both the real and the effective user ID of the current process.
val setregid : int -> int -> unit
Changes both the real and the effective group ID of the current process.
val initgroups : string -> int -> unit
See initgroups(3). This is a non-POSIX function but widely available.

The "at" variants of system calls



The "at" variants of system calls



Note that a few "at" calls have been omitted because the same functionality can be achieved by first opening the file with openat and then by using a function that references the file by descriptor. An example for this is fstatat: After the openat call one can use fstat to get the stat record of the file.
val have_at : unit -> bool
Whether the *at functions are available (they were only recently standardized and cannot be expected on all OS yet)
val at_fdcwd : Unix.file_descr
Pseudo descriptor value to be used as first argument of *at functions
type at_flag = 
| AT_EACCESS
| AT_SYMLINK_NOFOLLOW
| AT_SYMLINK_FOLLOW
| AT_REMOVEDIR (*
Flags one can pass to "at" functions. Not all functions support all flags
*)
val openat : Unix.file_descr ->
string -> Unix.open_flag list -> Unix.file_perm -> Unix.file_descr
Same as Unix.openfile but open relative to the directory given by first argument
val faccessat : Unix.file_descr ->
string -> Unix.access_permission list -> at_flag list -> unit
Same as Unix.access but the file is taken relative to the directory given by first argument
val mkdirat : Unix.file_descr -> string -> int -> unit
Same as Unix.mkdir but the file is taken relative to the directory given by first argument
val renameat : Unix.file_descr -> string -> Unix.file_descr -> string -> unit
renameat olddirfd oldpath newdirfd newpath
val linkat : Unix.file_descr ->
string -> Unix.file_descr -> string -> at_flag list -> unit
linkat olddirfd oldpath newdirfd newpath flags
val unlinkat : Unix.file_descr -> string -> at_flag list -> unit
Same as Unix.unlink but unlink the file relative to the directory given by first argument
val symlinkat : string -> Unix.file_descr -> string -> unit
symlinkat oldpath newdirfd newpath flags
val mkfifoat : Unix.file_descr -> string -> int -> unit
mkfifoat dirfd path mode

NB. MacOS 10.10 doesn't support mkfifoat although the other "at" functions are implemented. Be prepared to get Invalid_argument.

val readlinkat : Unix.file_descr -> string -> string
readlinkat dirfd path

File descriptor polling


type poll_array 
The array of poll_cell entries
type poll_req_events 
type poll_act_events 
Poll events. poll_req_events is used to request that certain event types are observed. poll_act_event shows which event types are actually possible
type poll_cell = {
   mutable poll_fd : Unix.file_descr;
   mutable poll_req_events : poll_req_events;
   mutable poll_act_events : poll_act_events;
}
The poll cell refers to the descriptor poll_fd. The poll_req_events are the events the descriptor is polled for. The poll_act_events are the actually reported events.
val have_poll : unit -> bool
Whether there is a native poll implementation on this OS
val poll_req_events : bool -> bool -> bool -> poll_req_events
poll_req_events rd wr pri: Create a set of in events consisting of the bits rd, wr, and pri. rd means to poll for input data, wr to poll for output data, and pri to poll for urgent input data.
val poll_req_triple : poll_req_events -> bool * bool * bool
Looks into a poll_req_events value, and returns the triple (rd,wr,pri).
val poll_null_events : unit -> poll_act_events
Create an empty set of poll_act_events, for initilization of poll cells.
val poll_result : poll_act_events -> bool
Look whether there is any event in poll_out_events
val poll_rd_result : poll_act_events -> bool
val poll_wr_result : poll_act_events -> bool
val poll_pri_result : poll_act_events -> bool
val poll_err_result : poll_act_events -> bool
val poll_hup_result : poll_act_events -> bool
val poll_nval_result : poll_act_events -> bool
Look for the bit in poll_act_events and return the status
val create_poll_array : int -> poll_array
Create a poll array with the given size. The poll_fd member is initialized with Unix.stdin, and the two event members are empty.
val set_poll_cell : poll_array -> int -> poll_cell -> unit
set_poll_cell a k c: Sets the poll cell k to c. The index k must be in the range from 0 to N-1 when N is the length of the poll array.
val get_poll_cell : poll_array -> int -> poll_cell
get_poll_cell a k: Returns the poll cell k. The index k must be in the range from 0 to N-1 when N is the length of the poll array.
val blit_poll_array : poll_array ->
int -> poll_array -> int -> int -> unit
blit_poll_array a1 p1 a2 p2 len: Copies the len cells at index p1 from a1 to a2 at index p2.
val poll_array_length : poll_array -> int
Return the number of cells in the poll array
val poll : poll_array -> int -> float -> int
poll a n tmo: Poll for the events of the cells 0 to n-1 of poll array a, and set the poll_act_events member of all cells. Wait for at most tmo seconds (a negative value means there is no timeout). Returns the number of ready file descriptors.

On platforms without native support for poll the function is emulated using Unix.select. Note, however, that there is a performance penalty for the emulation, and that the output flags poll_error_result, poll_hangup_result, and poll_invalid_result are not emulated.

val restarting_poll : poll_array -> int -> float -> int
A wrapper around poll that handles the EINTR condition
val poll_single : Unix.file_descr -> bool -> bool -> bool -> float -> bool
poll_single fd rd wr pri tmo: Polls a single descriptor for the events given by rd, wr, and pri. In tmo the timeout can be passed. Returns true if one of the requested events is indicated for the descriptor. The EINTR case is not handled.

Actually, poll_req_events and poll_act_events are integers that are bitmasks of some constants. The following functions allow access to this detail.
val int_of_req_events : poll_req_events -> int
val int_of_act_events : poll_act_events -> int
val req_events_of_int : int -> poll_req_events
val act_events_of_int : int -> poll_act_events
val const_rd_event : int
val const_wr_event : int
val const_pri_event : int
val const_err_event : int
val const_hup_event : int
val const_nval_event : int

Event aggregation



Event aggregation



Support for "high-speed" poll implementations. Currently, only epoll for Linux is supported.

The model exhibited in this API is the smallest common denominator of Linux epoll, BSD kqueue, and Solaris ports. The event_aggregator represents the set of monitored event sources. There is, so far, only one source, namely file descriptors, i.e. one can check whether a descriptor is readable or writable (like poll). The source can be added to the event_aggregator to monitor the source.

By calling poll_event_sources one can determine sources that are currently active (i.e. in signalling state).

It is undefined what happens when a file descriptor is closed while being member of the aggregator.

type event_aggregator 
type event_source 
val have_event_aggregation : unit -> bool
Whether there is an implementation for this OS
val create_event_aggregator : bool -> event_aggregator
create_event_aggregator is_interruptible: Creates a new aggregator, and allocates the required OS resources.

If is_interruptible, the aggregator can be interrupted from a different thread. See interrupt_event_aggregator below.

val destroy_event_aggregator : event_aggregator -> unit
Frees all OS resources
val fd_event_source : Unix.file_descr -> poll_req_events -> event_source
Wraps a file descriptor as event_source, and monitors the events in poll_req_events.

The event_source contains state about the relation to the aggregator, and because of this, the event_source should only be used together with one aggregator (at a time).

val modify_fd_event_source : event_source -> poll_req_events -> unit
Modifies the set of events monitored at this event source
val get_fd_of_event_source : event_source -> Unix.file_descr
Get the file descriptor wrapped by this event source
val act_events_of_event_source : event_source -> poll_act_events
Return the actual events of the source. This is updated when poll_event_sources returns the source.
val add_event_source : event_aggregator -> event_source -> unit
Adds the event source to the aggregator
val del_event_source : event_aggregator -> event_source -> unit
Removes the source from the aggregator
val interrupt_event_aggregator : event_aggregator -> unit
If create_event_aggregator was called with true as argument, the aggregator is interruptible, and this function interrupts it. The effect is that a currently running poll_event_sources, or, if it is not running, the next invocation of poll_event_sources returns immediately.

If the aggregator is not interruptible, this function is a NOP.

val push_event_updates : event_aggregator -> unit
Pushes all modifications of the sources to the kernel
val poll_event_sources : event_aggregator -> float -> event_source list
poll_event_sources ea tmo: First, all modifications are pushed to the kernel, and polling is set up to get events. If no events can currently be delivered, the function waits up to tmo seconds (or endlessly if negative) for events. The function returns only a limited number of events at a time. It is allowed that the function returns fewer events than are currently in signalled state, even none.

Call the function with tmo=0.0 for non-blocking behavior.

Note that this is the "level-triggered" behavior: If a source remains active it will be reported again by the next poll_event_sources, just as poll would do.

val event_aggregator_fd : event_aggregator -> Unix.file_descr
Returns the underlying file descriptor. It is implementation-defined whether this descriptor can also be polled for events. Generally, you should run push_event_updates before polling from the descriptor.

Fork helpers



Fork helpers



Ocamlnet invokes Unix.fork at some places to create child processes for doing real work. The following functions allow it to register a handler that is run in the forked child process. Note that this is done by the O'caml code calling fork, and not via the POSIX atfork() facility.

The handler should release OS resources like file descriptors that are by default shared with the parent process.

The handler are not invoked when the only purpose of the fork is to exec a different process.

class type post_fork_handler = object .. end
A post_fork_handler is a named function unit -> unit
val register_post_fork_handler : post_fork_handler -> unit
Registers a new post fork handler (MT-Safe)
val remove_post_fork_handler : post_fork_handler -> unit
Removes a post fork handler from the registry (MT-Safe)
val run_post_fork_handlers : unit -> unit
Runs all post fork handlers. Exceptions are caught and printed to stderr.

Fork+exec



Fork+exec



The following function has some similarity with posix_spawn, but is extended to our needs, Only special (although frequent) cases are implemented with posix_spawn.
type wd_spec = 
| Wd_keep (*
Keep the current working directory in the spawned process
*)
| Wd_chdir of string (*
Change to this directory in the spawned process
*)
| Wd_fchdir of Unix.file_descr (*
Change to the directory which has been previously been opened
*)
type pg_spec = 
| Pg_keep (*
The new process will be member of the same process group as this process
*)
| Pg_new_bg_group (*
A new background process group is created, and the spawned process will be its single member
*)
| Pg_new_fg_group (*
A new foreground process group is created, and the spawned process will be its single member
*)
| Pg_join_group of int (*
The spawned process will be member of this process group
*)
type fd_action = 
| Fda_close of Unix.file_descr (*
Close the descriptor
*)
| Fda_close_ignore of Unix.file_descr (*
Close the descriptor but ignore EBADF errors
*)
| Fda_close_except of bool array (*
Closes all descriptors except those for which except.(k) is true where k = int_of_file_descr fd. Descriptors outside the array index range are closed.
*)
| Fda_dup2 of Unix.file_descr * Unix.file_descr (*
Duplicate the first descriptor to the second as dup2 does
*)
type sig_action = 
| Sig_default of int (*
Resets this signal to default behavior in the spawned process
*)
| Sig_ignore of int (*
Ignores the signal in the spawned process
*)
| Sig_mask of int list (*
Set the signal mask in the spawned process
*)
val spawn : ?chdir:wd_spec ->
?pg:pg_spec ->
?fd_actions:fd_action list ->
?sig_actions:sig_action list ->
?env:string array -> ?no_posix_spawn:bool -> string -> string array -> int
spawn cmd args: Fork the process and exec cmd which gets the arguments args. On success, the PID of the new process is returned. This function does not wait for the completion of the process; use Unix.waitpid for this purpose.

  • chdir: If set, the new process starts with this working directory (this is done before anything else)
  • pg: If set, the new process will be a member of this process group
  • fd_actions: If set, these descriptor actions are executed sequentially
  • sig_actions: If set, these signal actions are executed sequentially
  • env: If set, the process gets this environment instead of the current one
  • no_posix_spawn: If set, the posix_spawn family of library functions is not used to spawn even if possible, and always a fork/exec approach is taken. This may be slower, but there is normally better error reporting.
Any exceptions in the subprocess are detected, and reported. However, if Fda_close_ignore leads to EBADF for a descriptor, this error is ignored.

If pg=Pg_new_fg_group, one should include Sig_ignore Sys.sigttou in sig_actions.

There are two implementations for spawn: One calls fork and exec directly, and one uses the posix_spawn family of library functions. The latter is faster on certain conditions, but this is very OS-specific. A number of features are not supported by posix_spawn and will force that fork/exec is used: Wd_chdir, Wd_fchdir, Pg_new_fg_group, and Sig_ignore. However, note some implementations of posix_spawn also fall back to fork/exec internally for some combinations of flags, and it is hard to predict which spawn calls can actually be accelerated. The tendency, though, is that recent OS have sped up posix_spawn so far possible (e.g. by using vfork internally, or even by making posix_spawn a system call).


Notification via file descriptor events



Notification via file descriptor events



Often, it is advantageous to report asynchronous events via file descriptors. On Linux, this is available via the eventfd system call. On other platforms, pipes are used for emulation.

A not_event can have two states: off and on. Initially, the not_event is off. By signalling it, the state changes to on, and the underlying real file descriptor becomes readable. By consuming the event, the state is switched back to off.

Note that a similar API exists for Win32: See Netsys_win32.w32_event.

type not_event 
val create_event : unit -> not_event
Creates a new event file descriptor.
val set_nonblock_event : not_event -> unit
Sets the event fd to non-blocking mode
val get_event_fd : not_event -> Unix.file_descr
Returns a duplicate of the underlying file descriptor. This should only be used for one thing: checking whether the desciptor becomes readable. As this is a duplicate, the caller has to close the descriptor.
val set_event : not_event -> unit
Signals the event
val wait_event : not_event -> unit
If the event fd is not signalled, the function blocks until it gets signalled, even in non-blocking mode.
val consume_event : not_event -> unit
Consumes the event, and switches the event fd to off again. If the event fd is not signalled, the function blocks until it gets signalled (in blocking mode), or it raises EAGAIN or EWOULDBLOCK (in non-blocking mode).

This is effectively an atomic "wait-and-reset" operation.

val destroy_event : not_event -> unit
Releases the OS resources. Note that there can be a hidden second file descriptor, so closing the descriptor returned by get_event_fd is not sufficient.
val report_signal_as_event : not_event -> int -> unit
report_signal_as_event ev sig Installs a new signal handler for signal sig so that ev is signalled when a signal arrives.

Notification queues



Notification queues



Unimplemented, but a spec exists. Notification queues are intended for forwarding events from C level to OCaml level. Possible uses:
  • POSIX timers
  • Realtime signals
  • Subprocess monitoring
  • AIO completion


Notification queues



Unimplemented, but a spec exists. Notification queues are intended for forwarding events from C level to OCaml level. Possible uses:
  • POSIX timers
  • Realtime signals
  • Subprocess monitoring
  • AIO completion


Subprocesses and signals



Notification queues



Unimplemented, but a spec exists. Notification queues are intended for forwarding events from C level to OCaml level. Possible uses:
  • POSIX timers
  • Realtime signals
  • Subprocess monitoring
  • AIO completion


Subprocesses and signals



Watching subprocesses requires that the right signal handler is installed: install_subprocess_handler
type watched_subprocess 
val watch_subprocess : int -> int -> bool -> Unix.file_descr * watched_subprocess
let fd, ws = watch_subprocess pid pgid kill_flag: Enters the subprocess pid into the watch list. If pgid > 0, the process group ID is pgid (for killpg_subprocess and killpg_all_subprocesses). The kill_flag controls the process selection of kill_all_subprocesses and killpg_all_subprocesses.

The returned descriptor fd is open for reading and will indicate EOF when the subprocess is terminated. Via ws it is possible to query information about the subprocess. The installed signal handler will wait for the subprocess and put the process status into ws.

The caller has to close fd after the termination is signaled.

val ignore_subprocess : watched_subprocess -> unit
Changes the arrangement so that the termination of the subprocess is no longer reported by the file descriptor. The file descriptor indicates EOF immediately (and can be closed by the caller). Nevertheless, the signal handler still waits for the subprocess to avoid zombies.

Any further access to ws will fail.

val forget_subprocess : watched_subprocess -> unit
Frees OS resources. Any further access to the ws will fail.
val get_subprocess_status : watched_subprocess -> Unix.process_status option
If the subprocess is terminated, this function returns the status. Otherwise None is returned
val kill_subprocess : int -> watched_subprocess -> unit
Sends this signal to the subprocess if this process still exists. Never throws an exception.
val killpg_subprocess : int -> watched_subprocess -> unit
Sends this signal to the process group of the subprocess if there is still a watched subprocess belonging to this group. Never throws an exception.
val kill_all_subprocesses : int -> bool -> bool -> unit
kill_all_subprocess signal override nogroup: Sends a signal to potentially all subprocesses. The signal is sent to a watched process if the process still exists, and these two conditions hold both:
  • not nogroup || pgid = 0: Processes with pgid > 0 are excluded if nogroup is set
  • kill_flag || override: A process needs to have kill_flag set, or override is specified
Never throws an exception if the signal handler is installed.
val killpg_all_subprocesses : int -> bool -> unit
killpg_all_subprocess signal override: Sends a signal to potentially all subprocesses belonging to a process group (i.e. pgid>0). . The signal is sent to a process group if there are still watched subprocesses belonging to the group, and if either the kill_flag of any of the subprocesses process was set to true, or override is true.

Never throws an exception if the signal handler is installed.

val install_subprocess_handler : unit -> unit
Installs a SIGCHLD handler for watching subprocesses. Note that only processes are waited for that are registered with watch_subprocess.

The handler works both in the single-threaded and the multi-threaded case. install_subprocess_handler can safely called several times. The handler is installed every time the function is called, but the required data structures are only initialized at the first call.

val register_subprocess_handler : unit -> unit
Uses the Netsys_signal framework to manage the installation of the SIGCHLD handler.

This is the preferred method of installing the SIGCHLD handler.


Further notes.

Further notes.

The subprocess handler and fork(): The subprocess handler uses pipes for notification, and because of this it is sensitive to unpredicted duplicates of the pipe descriptors. fork() duplicates these pipe descriptors. If nothing is done about this issue, it can happen that the notification does not work anymore as it relies on detecting closed pipes.

If fork() is immediately followed by exec() (as it is done to run subcommands), the problem does not occur, because the relevant descriptors are closed at exec() time.

If fork() is used to start worker processes, however, we have to be careful. The descriptors need to be closed, so that the parent can continue to monitor subprocesses, and to allow the worker processes to use this mechanism. This module defines post fork handlers (see above), and a handler is automatically added that cleans the descriptors up. All user code has to do is to call run_post_fork_handlers immediately after fork() has spawned the new child, from the new child. This completely resets everything.

Further notes.

The subprocess handler and fork(): The subprocess handler uses pipes for notification, and because of this it is sensitive to unpredicted duplicates of the pipe descriptors. fork() duplicates these pipe descriptors. If nothing is done about this issue, it can happen that the notification does not work anymore as it relies on detecting closed pipes.

If fork() is immediately followed by exec() (as it is done to run subcommands), the problem does not occur, because the relevant descriptors are closed at exec() time.

If fork() is used to start worker processes, however, we have to be careful. The descriptors need to be closed, so that the parent can continue to monitor subprocesses, and to allow the worker processes to use this mechanism. This module defines post fork handlers (see above), and a handler is automatically added that cleans the descriptors up. All user code has to do is to call run_post_fork_handlers immediately after fork() has spawned the new child, from the new child. This completely resets everything.

The subprocess handler and multi-threading: The handler has been carefully designed, and works even in multi-threaded programs. However, one should know that multi-threading and fork() do not interact well with each other. Again, the problems do not occur if fork() is followed by exec(). There is no solution for the case that worker processes are started with fork(), though. The (very generic) problem is that the state of mutexes and other multi-threading primitives is not well-defined after a fork().

Further notes.

The subprocess handler and fork(): The subprocess handler uses pipes for notification, and because of this it is sensitive to unpredicted duplicates of the pipe descriptors. fork() duplicates these pipe descriptors. If nothing is done about this issue, it can happen that the notification does not work anymore as it relies on detecting closed pipes.

If fork() is immediately followed by exec() (as it is done to run subcommands), the problem does not occur, because the relevant descriptors are closed at exec() time.

If fork() is used to start worker processes, however, we have to be careful. The descriptors need to be closed, so that the parent can continue to monitor subprocesses, and to allow the worker processes to use this mechanism. This module defines post fork handlers (see above), and a handler is automatically added that cleans the descriptors up. All user code has to do is to call run_post_fork_handlers immediately after fork() has spawned the new child, from the new child. This completely resets everything.

The subprocess handler and multi-threading: The handler has been carefully designed, and works even in multi-threaded programs. However, one should know that multi-threading and fork() do not interact well with each other. Again, the problems do not occur if fork() is followed by exec(). There is no solution for the case that worker processes are started with fork(), though. The (very generic) problem is that the state of mutexes and other multi-threading primitives is not well-defined after a fork().

Syslog


type level = Netlog.level 

The log levels
type syslog_facility = [ `Authpriv
| `Cron
| `Daemon
| `Default
| `Ftp
| `Kern
| `Local0
| `Local1
| `Local2
| `Local3
| `Local4
| `Local5
| `Local6
| `Local7
| `Lpr
| `Mail
| `News
| `Syslog
| `User
| `Uucp ]
The facilities. Only `User and `Local0 to `Local7 are standard POSIX. If a facility is unavailable it is silently substituted by `Local0. The value `Default leaves this unspecified.
type syslog_option = [ `Cons | `Ndelay | `Nowait | `Odelay | `Pid ] 
The syslog options:
  • `Cons: Fall back to console logging if syslog is unavailable
  • `Ndelay: Open the connection immediately
  • `Odelay: Open the connection at the first call syslog (default)
  • `Nowait: Do not wait until it is ensured that the message is sent
  • `Pid: Log the PID with every message

val openlog : string option ->
syslog_option list -> syslog_facility -> unit
openlog ident options facility: Opens a log stream. ident is prepended to every message if given (usually the program name). The facility is the default facility for syslog calls.
val syslog : syslog_facility -> level -> string -> unit
syslog facility level message: Logs message at level for facility
val closelog : unit -> unit
Closes the log stream

Usually, the log stream is redirected to syslog by either:
  • setting Netlog.current_logger to syslog facility, e.g.
     Netlog.current_logger := Netsys_posix.syslog `User 
  • using the Netplex class for sending message to syslog (XXX)


Usually, the log stream is redirected to syslog by either:
  • setting Netlog.current_logger to syslog facility, e.g.
     Netlog.current_logger := Netsys_posix.syslog `User 
  • using the Netplex class for sending message to syslog (XXX)


Sync


val fsync : Unix.file_descr -> unit
Sync data and metadata to disk
val fdatasync : Unix.file_descr -> unit
Syncs only data to disk. If this is not implemented, same effect as fsync

Sending file descriptors over Unix domain sockets



Sending file descriptors over Unix domain sockets



These functions can be used to send file descriptors from one process to another one. The descriptor sock must be a connected Unix domain socket.

The functionality backing this is non-standard but widely available.

Not yet implemented, but spec exists.

Sending file descriptors over Unix domain sockets



These functions can be used to send file descriptors from one process to another one. The descriptor sock must be a connected Unix domain socket.

The functionality backing this is non-standard but widely available.

Not yet implemented, but spec exists.

Optional POSIX functions


val have_fadvise : unit -> bool
Returns whether the OS supports the fadvise POSIX option
type advice = 
| POSIX_FADV_NORMAL
| POSIX_FADV_SEQUENTIAL
| POSIX_FADV_RANDOM
| POSIX_FADV_NOREUSE
| POSIX_FADV_WILLNEED
| POSIX_FADV_DONTNEED
| FADV_NORMAL
| FADV_SEQUENTIAL
| FADV_RANDOM
| FADV_NOREUSE
| FADV_WILLNEED
| FADV_DONTNEED (*
Possible advices for fadvise. The names starting with "POSIX_" and the ones lacking the prefix have the same meaning. In new code, the names starting with "POSIX_" should be preferred (for better compaibility with other libraries).
*)
val fadvise : Unix.file_descr -> int64 -> int64 -> advice -> unit
Advises to load pages into the page table from the file, or to remove such pages.
val have_fallocate : unit -> bool
Returns whether the OS supports the fallocate POSIX option
val fallocate : Unix.file_descr -> int64 -> int64 -> unit
Allocate space for the file and the specified file region

POSIX Shared Memory


val have_posix_shm : unit -> bool
Returns whether the OS supports POSIX shared memory
type shm_open_flag = 
| SHM_O_RDONLY
| SHM_O_RDWR
| SHM_O_CREAT
| SHM_O_EXCL
| SHM_O_TRUNC
val shm_open : string -> shm_open_flag list -> int -> Unix.file_descr
Opens a shared memory object. The first arg is the name of the object. The name must begin with a slash, but there must be no further slash in it (e.g. "/sample"). The second arg are the open flags. The third arg are the permission bits.

The open flags are interpreted as follows:

  • SHM_O_RDONLY: Open the object for read access
  • SHM_O_RDWR: Open the object for read-write access
  • SHM_O_CREAT: Create the object if it does not exist
  • SHM_O_EXCL: If SHM_O_CREAT was also specified, and a an object with the given name already exists, return an error (Unix.EEXIST).
  • SHM_O_TRUNC: If the object already exists, truncate it to zero bytes
One of SHM_O_RDONLY or SHM_O_RDWR must be given.

On success, the function returns a file descriptor representing the object. To access the object, one has to memory-map this file use one of the map_file functions in the Bigarray module, or in Netsys_mem). Use Unix.ftruncate to resize the object.

Note that it is unspecified whether this file pops up somewhere in the file system, and if so, where.

If a system error occurs, the function raises a Unix.Unix_error exception.

val shm_unlink : string -> unit
Unlinks the name for a shared memory object
val shm_create : string -> int -> Unix.file_descr * string
let (fd,name) = shm_create prefix size: Creates an shm object with a unique name. The name has the passed prefix. The prefix must start with "/" but must not contain any further "/". The object has a length of size bytes. The object has a permissions 0o600 (independent of umask).

POSIX semaphores


val have_named_posix_semaphores : unit -> bool
Returns true if named POSIX semaphores are supported on this system
val have_anon_posix_semaphores : unit -> bool
Returns true if anonymous POSIX semaphores are supported on this system
val have_posix_semaphores : unit -> bool
Returns true if both kinds of semaphores are supported on this system

Constants.
val sem_value_max : int
The maximum value of a semaphore, but at most max_int
val sem_size : int
The size of an anonymous semaphore in bytes (sizeof(sem_t))

Types.
type sem_kind = [ `Anonymous | `Named ] 
type 'sem_kind semaphore 
type named_semaphore = [ `Named ] semaphore 
type anon_semaphore = [ `Anonymous ] semaphore 
type sem_open_flag = 
| SEM_O_CREAT
| SEM_O_EXCL

Named semaphores.
val sem_open : string ->
sem_open_flag list -> int -> int -> named_semaphore
sem_open name flags mode init_value: Opens a named semaphore which is optionally created. Sempahore names usually begin with a slash followed by a single name component (not containing a further slash).

Interpretation of flags:

  • SEM_O_CREAT: The semaphore is created if not yet existing. The mode and init_value are interpreted if the creation actually occurs. mode is the permission of the semaphore. init_value is the (non-negative) initial value, up to sem_value_max.
  • SEM_O_EXCL: The semaphore is only opened if the semaphore does not exist yet. Othwerwise an EEXIST error is returned

val sem_close : named_semaphore -> unit
Closes a named semaphore. Semaphores are also automatically closed when the GC finds that the semaphore is unreachable.
val sem_unlink : string -> unit
Unlinks the semaphore name
val sem_create : string -> int -> named_semaphore * string
let (sem,name) = sem_create prefix init_value: Creates a new semaphore with a unique name. The name has the passed prefix. The prefix must start with "/" but must not contain any further "/". The semaphore is initialized with init_value. The object has permissions 0o600 (modulo umask).

Anonymous semaphores.
val sem_init : Netsys_types.memory -> int -> bool -> int -> anon_semaphore
sem_init mem pos pshared init_value: Initializes the memory at position pos to pos + sem_size() - 1 as anonymous semaphore. If pshared the semaphore is shared between processes. init_value is the initial non-negative value (max is sem_value_max.
val sem_destroy : anon_semaphore -> unit
Destroys the anonymous semaphore
val as_sem : Netsys_types.memory -> int -> anon_semaphore
as_sem mem pos: Interprets the memory at position pos to pos + sem_size() - 1 as anonymous semaphore. The memory region must already have been initialized.

Operations.
val sem_getvalue : 'kind semaphore -> int
Returns the value of the semaphore. If the value is bigger than what can be represented as int, an EINVAL error is returned.

The returned value is non-negative - if the underlying POSIX function reports a negative value zero is returned instead.

Unavailable on MacOS.

val sem_post : 'kind semaphore -> unit
Unlocks the semaphore (increases the value by 1)
type sem_wait_behavior = 
| SEM_WAIT_BLOCK
| SEM_WAIT_NONBLOCK
val sem_wait : 'kind semaphore -> sem_wait_behavior -> unit
Locks the semaphore (decreases the value by 1). If the semaphore value is already zero, and SEM_WAIT_BLOCK is given, the function waits until another process or thread posts. If SEM_WAIT_NONBLOCK the error EAGAIN is returned.

sem_wait may be interrupted by signals.


Semaphores and notification



Semaphores and notification



Not yet implemented.

Semaphores and notification



Not yet implemented.

Locales


type langinfo = {
   nl_CODESET : string; (*
from LC_CTYPE: codeset name
*)
   nl_D_T_FMT : string; (*
from LC_TIME: string for formatting date and time
*)
   nl_D_FMT : string; (*
from LC_TIME: date format string
*)
   nl_T_FMT : string; (*
from LC_TIME: time format string
*)
   nl_T_FMT_AMPM : string; (*
from LC_TIME: a.m. or p.m. time format string
*)
   nl_AM_STR : string; (*
from LC_TIME: Ante Meridian affix
*)
   nl_PM_STR : string; (*
from LC_TIME: Post Meridian affix
*)
   nl_DAY_1 : string; (*
from LC_TIME: name of the first day of the week (for example, Sunday)
*)
   nl_DAY_2 : string; (*
from LC_TIME: name of the second day of the week (for example, Monday)
*)
   nl_DAY_3 : string; (*
from LC_TIME: name of the third day of the week (for example, Tuesday)
*)
   nl_DAY_4 : string; (*
from LC_TIME: name of the fourth day of the week (for example, Wednesday)
*)
   nl_DAY_5 : string; (*
from LC_TIME: name of the fifth day of the week (for example, Thursday)
*)
   nl_DAY_6 : string; (*
from LC_TIME: name of the sixth day of the week (for example, Friday)
*)
   nl_DAY_7 : string; (*
from LC_TIME: name of the seventh day of the week (for example, Saturday)
*)
   nl_ABDAY_1 : string; (*
from LC_TIME: abbreviated name of the first day of the week
*)
   nl_ABDAY_2 : string; (*
from LC_TIME: abbreviated name of the second day of the week
*)
   nl_ABDAY_3 : string; (*
from LC_TIME: abbreviated name of the third day of the week
*)
   nl_ABDAY_4 : string; (*
from LC_TIME: abbreviated name of the fourth day of the week
*)
   nl_ABDAY_5 : string; (*
from LC_TIME: abbreviated name of the fifth day of the week
*)
   nl_ABDAY_6 : string; (*
from LC_TIME: abbreviated name of the sixth day of the week
*)
   nl_ABDAY_7 : string; (*
from LC_TIME: abbreviated name of the seventh day of the week
*)
   nl_MON_1 : string; (*
from LC_TIME: name of the first month of the year
*)
   nl_MON_2 : string; (*
from LC_TIME: name of the second month
*)
   nl_MON_3 : string; (*
from LC_TIME: name of the third month
*)
   nl_MON_4 : string; (*
from LC_TIME: name of the fourth month
*)
   nl_MON_5 : string; (*
from LC_TIME: name of the fifth month
*)
   nl_MON_6 : string; (*
from LC_TIME: name of the sixth month
*)
   nl_MON_7 : string; (*
from LC_TIME: name of the seventh month
*)
   nl_MON_8 : string; (*
from LC_TIME: name of the eighth month
*)
   nl_MON_9 : string; (*
from LC_TIME: name of the ninth month
*)
   nl_MON_10 : string; (*
from LC_TIME: name of the tenth month
*)
   nl_MON_11 : string; (*
from LC_TIME: name of the eleventh month
*)
   nl_MON_12 : string; (*
from LC_TIME: name of the twelfth month
*)
   nl_ABMON_1 : string; (*
from LC_TIME: abbreviated name of the first month
*)
   nl_ABMON_2 : string; (*
from LC_TIME: abbreviated name of the second month
*)
   nl_ABMON_3 : string; (*
from LC_TIME: abbreviated name of the third month
*)
   nl_ABMON_4 : string; (*
from LC_TIME: abbreviated name of the fourth month
*)
   nl_ABMON_5 : string; (*
from LC_TIME: abbreviated name of the fifth month
*)
   nl_ABMON_6 : string; (*
from LC_TIME: abbreviated name of the sixth month
*)
   nl_ABMON_7 : string; (*
from LC_TIME: abbreviated name of the seventh month
*)
   nl_ABMON_8 : string; (*
from LC_TIME: abbreviated name of the eighth month
*)
   nl_ABMON_9 : string; (*
from LC_TIME: abbreviated name of the ninth month
*)
   nl_ABMON_10 : string; (*
from LC_TIME: abbreviated name of the tenth month
*)
   nl_ABMON_11 : string; (*
from LC_TIME: abbreviated name of the eleventh month
*)
   nl_ABMON_12 : string; (*
from LC_TIME: abbreviated name of the twelfth month
*)
   nl_ERA : string; (*
from LC_TIME: era description segments
*)
   nl_ERA_D_FMT : string; (*
from LC_TIME: era date format string
*)
   nl_ERA_D_T_FMT : string; (*
from LC_TIME: era date and time format string
*)
   nl_ERA_T_FMT : string; (*
from LC_TIME: era time format string
*)
   nl_ALT_DIGITS : string; (*
from LC_TIME: alternative symbols for digits
*)
   nl_RADIXCHAR : string; (*
from LC_NUMERIC: radix character
*)
   nl_THOUSEP : string; (*
from LC_NUMERIC: separator for thousands
*)
   nl_YESEXPR : string; (*
from LC_MESSAGES: affirmative response expression
*)
   nl_NOEXPR : string; (*
from LC_MESSAGES: negative response expression
*)
   nl_CRNCYSTR : string; (*
from LC_MONETARY: currency
*)
}
val query_langinfo : string -> langinfo
query_langinfo locale: Temporarily sets the passed locale and determines the language attributes. After that the orignal locale is restored. Pass "" as locale to get the locale requested in the environment.

The value for "" is cached.


Clocks



Clocks



Support for clocks can be assumed to exist on all current POSIX systems.
type timespec = float * int 
(t,t_nanos): Specifies a time by a base time t to which the nanoseconds t_nanos are added.

If this pair is returned by a function t will always be integral. If a pair is passed to a function, it does not matter whether this is the case or not, but using integral values for t ensure maximum precision.

val nanosleep : timespec -> timespec Pervasives.ref -> unit
nanosleep t t_rem: Sleeps for t seconds. The sleep can either be finished, or the sleep can be interrupted by a signal. In the latter case, the function will raise EÃNTR, and write to t_rem the remaining seconds.
type clock_id 
type clock = 
| CLOCK_REALTIME (*
A clock measuring wallclock time
*)
| CLOCK_MONOTONIC (*
A clock measuring kernel time (non-settable). Optional, i.e. not supported by all OS
*)
| CLOCK_ID of clock_id (*
A clock ID
*)
val clock_gettime : clock -> timespec
Get the time of this clock
val clock_settime : clock -> timespec -> unit
Set the time of this clock
val clock_getres : clock -> timespec
Get the resolution of this clock
val clock_getcpuclockid : int -> clock_id
Return the ID of a clock that counts the CPU seconds of the given process. Pass the PID or 0 for the current process.

This function is not supported on all OS.


POSIX timers


type posix_timer 
type timer_expiration = 
| TEXP_NONE
| TEXP_EVENT of not_event
| TEXP_EVENT_CREATE
| TEXP_SIGNAL of int
val have_posix_timer : unit -> bool
val timer_create : clock ->
timer_expiration -> posix_timer
Create a new timer that will report expiration as given by the arg:
  • TEXP_NONE: no notification
  • TEXP_EVENT e: the not_event e is signalled
  • TEXP_EVENT_CREATE: a special not_event is created for the timer. (Get the event via timer_event, see below.)
  • TEXP_SIGNAL n: the signal n is sent to the process
Note that TEXP_EVENT_CREATE is much faster on Linux than TEXP_EVENT, because it can be avoided to start a new thread whenever the timer expires. Instead, the timerfd machinery is used.

TEXP_EVENT and TEXP_EVENT_CREATE are only supported on systems with pthreads.

val timer_settime : posix_timer ->
bool -> timespec -> timespec -> unit
timer_settime tm abstime interval value:

If value=(0.0,0), the timer is stopped.

If value is a positive time, the timer is started (or the timeout is changed if it is already started). If abstime, value is interpreted as the absolute point in time of the expiration. Otherwise value sets the number of seconds until the expiration.

If interval is positive, the started timer will repeat to expire after this many seconds once it has expired for the first time. If interval=(0.0,0), the timer is a one-shot timer.

val timer_gettime : posix_timer -> timespec
Returns the number of seconds until the expiration, or (0.0,0) if the timer is off
val timer_delete : posix_timer -> unit
Deletes the timer
val timer_event : posix_timer -> not_event
Returns the notification event for the timer styles TEXP_EVENT and TEXP_EVENT_CREATE.

Note that the latter type of event does not allow to call set_event.


Intentionally there is no wrapper for timer_getoverrun. Additional overruns can occur because of the further processing of the notifications: The OCaml runtime can merge signals, which would not be noticed by the kernel overrun counter, and events can also be merged. The workaround is to use one-shot timers with absolute expiration timestamps, and to check for overruns manually. Once we have TEXP_NQ the issue is solved.

Intentionally there is no wrapper for timer_getoverrun. Additional overruns can occur because of the further processing of the notifications: The OCaml runtime can merge signals, which would not be noticed by the kernel overrun counter, and events can also be merged. The workaround is to use one-shot timers with absolute expiration timestamps, and to check for overruns manually. Once we have TEXP_NQ the issue is solved.

Linux I/O Priorities



Intentionally there is no wrapper for timer_getoverrun. Additional overruns can occur because of the further processing of the notifications: The OCaml runtime can merge signals, which would not be noticed by the kernel overrun counter, and events can also be merged. The workaround is to use one-shot timers with absolute expiration timestamps, and to check for overruns manually. Once we have TEXP_NQ the issue is solved.

Linux I/O Priorities



These system calls are only available on Linux since kernel 2.6.13, and not even on every architecture. i386, x86_64, ia64, and PPC are known to work.

Per-process I/O priorities are currently only supported by the CFQ I/O scheduler.

val have_ioprio : unit -> bool
Returns true if the system call ioprio_get is supported
type ioprio_target = 
| Ioprio_process of int (*
A single process
*)
| Ioprio_pgrp of int (*
A process group
*)
| Ioprio_user of int (*
All processes owned by this user
*)
type ioprio = 
| Noprio (*
I/O prioritization is unsupported by block layer
*)
| Real_time of int (*
0..7 (higest..lowest prio)
*)
| Best_effort of int (*
0..7 (higest..lowest prio)
*)
| Idle
val ioprio_get : ioprio_target -> ioprio
Retrieve the priority of the target. If several processes match the target, the highest priority is returned. If no process matches, the unix error ESRCH will be raised.
val ioprio_set : ioprio_target -> ioprio -> unit
Sets the priority of the target processes.

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.workload_manager_factory.html0000644000175000017500000004203412731530353026240 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.workload_manager_factory object
  method create_workload_manager :
    Netplex_types.controller_config ->
    Netplex_types.config_file ->
    Netplex_types.address -> Netplex_types.workload_manager
  method name : string
end
ocamlnet-4.1.2/doc/html-main/Netplex_workload.dynamic_workload_config-c.html0000644000175000017500000004557312731530353025720 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_workload.dynamic_workload_config

Class type Netplex_workload.dynamic_workload_config

class type dynamic_workload_config = object .. end

method max_jobs_per_thread : int
How many jobs every thread can execute concurrently until it is considered as fully loaded. For configurations where the threads can only handle one connection at a time this number must be 1.
method recommended_jobs_per_thread : int
The number of jobs every thread can execute with normal service quality. Must be less than or equal to max_jobs_per_thread
method min_free_job_capacity : int
The manager starts as many threads as required to ensure that this number of jobs can be executed. Must be at least 1.
method max_free_job_capacity : int
If more job capacity is available than this number, threads are terminated. Must be greater than or equal to min_free_job_capacity.
method inactivity_timeout : int
After this number of seconds a free thread can be terminated
method max_threads : int
The manager does not start more threads than this number
method greedy_accepts : bool
Whether greedy accepts are permitted
ocamlnet-4.1.2/doc/html-main/Nethttpd_services.html0000644000175000017500000012645212731530353020776 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_services

Module Nethttpd_services

module Nethttpd_services: sig .. end

Service Providers for HTTP daemon

This module defines the basic service providers that handle requests and generate responses. The service providers can be used with both the reactive and the event-based daemon encapsulations.


type host = {
   server_pref_name : string option; (*
The preferred name of the host. This can be a DNS name or an IP address.
*)
   server_pref_port : int option; (*
The preferred port of the host
*)
   server_names : (string * int) list; (*
Names and ports that match this host definition, for name-based virtual hosting. The name "*" matches any name, and the port 0 matches any port.
*)
   server_addresses : (Unix.inet_addr * int) list; (*
IP addresses and ports that also match this host definition, for IP-based virtual hosting. The address Unix.inet_addr_any matches any address, and the port 0 matches any port.
*)
}
For name- and IP-based virtual hosting this record describes the individual host. An incoming request matches this host if:
  • The Host header is mentioned in server_names, or if
  • The request has been accepted on the port contained in server_addresses
If server_pref_name is set, the name of the host is set to this string for further processing (esp. cgi_server_name). If not set, the name of the host is set to the name corresponding to the matching entry of server_names or server_addresses, or if this does not succeed, to the real IP address.

If server_pref_port is set, the port of the host is set to this string for further processing (esp. cgi_server_port). If not set, the port of the host is set to the port corresponding to the matching entry of server_names or server_addresses, or if this does not succeed, to the real port number.

type 'a host_distributor = (host * 'a Nethttpd_types.http_service) list 
Describes virtual hosting by pairs (host,service): If host matches the incoming request, the corresponding service is performed to generate the response.
val host_distributor : 'a host_distributor ->
[> `Host_distributor of 'a host_distributor ]
Nethttpd_types.http_service
Configures virtual hosting
val default_host : ?pref_name:string -> ?pref_port:int -> unit -> host
Creates a host record that matches any request. pref_name and pref_port can be used to specify preferred names.
val options_service : unit -> [> `Options_service ] Nethttpd_types.http_service
This service responds to "OPTIONS *" requests, and nothing else
type 'a uri_distributor = (string * 'a Nethttpd_types.http_service) list 
Describes that services are bound to URI prefixes. The strings are URI paths (without URI escaping). For an incoming request URI, the longest matching prefix is selected, and the corresponding service is carried out.

If the URI path in the list ends with a slash, it can only be selected if the incoming request URI also includes the slash.

If the URI path in the list does not end with a slash, it can only be selected if the incoming request URI is exactly identical, or continues the path with a slash.

val uri_distributor : 'a uri_distributor ->
[> `Uri_distributor of 'a uri_distributor ]
Nethttpd_types.http_service
Configures URI distribution. The incoming request URI is normalized before being matched, and the request is rewritten to the normalized URI.

Normalization includes:

  • Removal of . path components
  • Resolution of .. path components
If the path starts with .. after normalization, the request is rejected.
type 'a linear_distributor = ((Nethttpd_types.extended_environment -> bool) *
'a Nethttpd_types.http_service)
list
Services are selected by calling the selector function. The first service for which the function returns true is selected.
val linear_distributor : 'a linear_distributor ->
[> `Linear_distributor of 'a linear_distributor ]
Nethttpd_types.http_service
Configures linear distribution
type method_filter = [ `Limit of string list | `Limit_except of string list ] 
The request is only accepted if listed (for `Limit), or if not listed (for `Limit_except).
type 'a method_distributor = (method_filter * 'a Nethttpd_types.http_service) list 
The first service is selected for which the method filter accepts the request
val method_distributor : 'a method_distributor ->
[> `Method_distributor of 'a method_distributor ]
Nethttpd_types.http_service
Configures method distribution
type file_option = [ `Enable_cooked_compression
| `Enable_gzip
| `Enable_index_file of string list
| `Enable_listings of
Nethttpd_types.extended_environment ->
Netcgi.cgi_activation -> file_service -> unit
| `Override_compression_suffixes of (string * string) list ]
Add-on features for file services:
  • `Enable_gzip: Deprecated. Same as `Enable_cooked_compression.
  • `Enable_cooked_compression: Modifies the way compressed files are handled. Normally it is required that one accesses the compressed file (with suffix such as "gz") directly to get it in compressed form. If this option is enabled, though, the server also compresses the base file (without suffix such as "gz"), but only if the base file is accompanied by a compressed version (with suffix). E.g. if there is "foo" and "foo.gz", this enables that the accesses to "foo" can make use of compression.
  • `Enable_index_file: If enabled, accesses to directories are redirected to index files. The possible file names are given in the string list. E.g. `Enable_index_file ["index.html"; "index.htm"]. It is redirected to these files, so these can be handled by different services if neccessary.
  • `Enable_listings: If enabled, directory listings are generated by calling the argument function. The PATH_TRANSLATED property of the environment contains the absolute name of the directory to list. The PATH_INFO property is the corresponding URI path. SCRIPT_NAME is meaningless.
  • `Override_compression_suffixes l: Tags the file suffixes in l as compression schemes. A pair (suffix,ce) sets that the suffix means the content encoding ce. Knowing this is important for determining the media type of the file.

type file_service = {
   file_docroot : string; (*
The document root for this file service
*)
   file_uri : string; (*
The URI prefix corresponding to the document root. Escapes are not allowed
*)
   file_suffix_types : (string * string) list; (*
Maps the file suffixes (after the dot) to media types
*)
   file_default_type : string; (*
The media type to use if suffix mapping fails
*)
   file_options : file_option list; (*
Further options for files
*)
}
Describes a file service
val file_service : file_service ->
[> `File_service of file_service ]
Nethttpd_types.http_service
Configures a file service
val file_translator : file_service -> string -> string
Translates an URI path to a file name. Raises Not_found if not possible. It is not checked whether the resulting file exists.

This function removes a trailing slash of the translated path, if any, and if resulting from appending the path info component. Trailing slashes must not be used to deduce that directories are accessed.

val simple_listing : ?hide:string list ->
Nethttpd_types.extended_environment ->
Netcgi.cgi_activation -> file_service -> unit
Simple listing generator for `Enable_listings

hide: An optional list of Str regular expressions. File names matching one of the regexps are hidden in the listing. Defaults to hiding files starting with a dot, and files ending in a tilde character. (Changed in Ocamlnet-3.3: hide uses now Str regexps, and no longer PCRE regexps.)

type std_activation_options = {
   stdactv_processing : Netcgi.arg_store option;
   stdactv_operating_type : Netcgi.output_type option;
}
These are options for `Std_activation. For explanations, see the Netcgi module.
type std_activation = [ `Std_activation of std_activation_options
| `Std_activation_buffered
| `Std_activation_tempfile
| `Std_activation_unbuffered ]
The way the Netcgi_types.cgi_activation object is created. For typical usage, just take:
  • `Std_activation_unbuffered: Creates a Netcgi.std_activation without output buffer (type `Direct "") and memory-based argument processing
  • `Std_activation_buffered: Creates a Netcgi.std_activation with a transactions buffer in memory, and memory-based argument processing
  • `Std_activation_tempfile: Creates a Netcgi.std_activation with a file as transactions buffer, and memory-based argument processing
The following option is provided for detailed control:
  • `Std_activation opt: Creates a Netcgi.std_activation with the given options

type #Netcgi.cgi_activation dynamic_service = {
   dyn_handler : Nethttpd_types.extended_environment -> (#Netcgi.cgi_activation as 'a) -> unit; (*
A dynamic service is carried out by calling this function with the environment and the CGI activation. The function can use all CGI features, including setting the Location handler to redirect responses.
*)
   dyn_activation : Nethttpd_types.extended_environment -> 'a; (*
The way the Netcgi_types.cgi_activation is created. Look below for std_activation.
*)
   dyn_uri : string option; (*
The URI prefix corresponding to this service. This is only used to compute cgi_path. Leave it to None if not needed.
*)
   dyn_translator : string -> string; (*
The function computing cgi_path_translated from cgi_path. Set it to (fun _ -> "") if not needed.
*)
   dyn_accept_all_conditionals : bool; (*
Whether to pass requests with If-Match and If-Unmodified-Since headers to this service. If set to true, the service can optimize the caching behaviour by interpreting these fields. It is even obliged to interpret them. If false, requests containing these headers are rejected.

The other condition fields If-None-Match, If-Modified-Since, and If-Ranges are not affected by this option. One can safely ignore these headers.

*)
}
val std_activation : std_activation ->
Nethttpd_types.extended_environment -> Netcgi.cgi_activation
Create the function for dyn_activation from a std_activation tag. Example: let dyn_actv = std_activation `Std_activation_unbuffered
val dynamic_service : (#Netcgi.cgi_activation as 'a) dynamic_service ->
[> `Dynamic_service of 'a dynamic_service ]
Nethttpd_types.http_service
Configures the dynamic service.
type ac_by_host_rule = [ `Allow of string list | `Deny of string list ] 
Access control by host:
  • `Allow: Only the listed hosts are allowed; all other are denied
  • `Deny: The listed hosts are denied; all other are allowed

type 'a ac_by_host = ac_by_host_rule * 'a Nethttpd_types.http_service 
The service is protected by the access control rule
val ac_by_host : 'a ac_by_host ->
[> `Ac_by_host of 'a ac_by_host ]
Nethttpd_types.http_service
Configures host-based access control
val read_media_types_file : string -> (string * string) list
Reads a text file with two columns where the left column is the media type and the right column the corresponding suffix. Returns the contents as pairs (suffix, type) .
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Uq_engines.input_engine-c.html0000644000175000017500000004505712731530353022302 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.input_engine

Class Uq_engines.input_engine

class ['a] input_engine : (Unix.file_descr -> 'a) -> Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
Generic input engine for reading from a file descriptor: let e = new input_engine f fd tmo - Waits until the file descriptor becomes readable, and calls then let x = f fd to read from the descriptor. The result x is the result of the engine.

If the file descriptor does not become readable within tmo seconds, the resulting engine transitions to `Error Timeout.

Use this class to construct engines reading via Unix.read or comparable I/O functions:

      let read_engine fd tmo esys =
        new input_engine (fun fd ->
                            let buf = String.create 4096 in
                            let n = Unix.read fd buf 0 (String.length buf) in
                            String.sub buf 0 n
                         )
                         fd tmo esys
      

This engine returns the read data as string.

See also Uq_io.input_e for a more generic way of reading with engines.


ocamlnet-4.1.2/doc/html-main/Netasn1.html0000644000175000017500000011051312731530353016601 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netasn1

Module Netasn1

module Netasn1: sig .. end
ASN.1 support functions


See below for a little intro into ASN.1: The Abstract Syntax Notation 1 (ASN.1)
exception Out_of_range
exception Parse_error of int
Byte position in string
exception Header_too_short
module Type_name: sig .. end
module Value: sig .. end
val decode_ber : ?pos:int -> ?len:int -> string -> int * Value.value
Decodes a BER-encoded ASN.1 value. Note that DER is a subset of BER, and can also be decoded.

pos and len may select a substring for the decoder. By default, pos=0, and len as large as necessary to reach to the end of the string.

The function returns the number of interpreted bytes, and the value. It is not considered as an error if less than len bytes are consumed.

The returned value represents implicitly tagged values as Tagptr(class,tag,pc,pos,len). pos and len denote the substring containting the contents. Use Netasn1.decode_ber_contents to further decode the value. You can use ITag to put the decoded value back into the tree.

A number of values are not verified (i.e. nonsense values can be returned):

  • for all string types it is not checked whether the constraints are satisfied (e.g. whether an UTF8String really contains UTF-8).
  • External, Embedded_PDV and Real are unchecked
  • Other values may first be checked on first access (e.g. GeneralizedTime).

val decode_ber_tstring : ?pos:int -> ?len:int -> Netsys_types.tstring -> int * Value.value
Same for tagged strings
val decode_ber_poly : ?pos:int ->
?len:int ->
's Netstring_tstring.tstring_ops -> 's -> int * Value.value
polymorphic version
val decode_ber_contents : ?pos:int ->
?len:int ->
?indefinite:bool ->
string ->
Value.pc -> Type_name.type_name -> int * Value.value
Decodes the BER-encoded contents of a data field. The contents are assumed to have the type denoted by type_name.

pos and len may select a substring for the decoder. By default, pos=0, and len as large as necessary to reach to the end of the string.

If indefinite, the extent of the contents region is considered as indefinite, and the special end marker is required. This is only allowed when pc = Constructed.

The function returns the number of interpreted bytes, and the value. It is not considered as an error if less than len bytes are consumed.

You need to use this function to recursively decode tagged values. If you get a Tagptr(class,tag,pc,s,pos,len) value, it depends on the kind of the tag how to proceed:

The BER encoding doesn't include whether the tag is implicit or explicit, so the decode cannot do by itself the right thing here.
val decode_ber_contents_tstring : ?pos:int ->
?len:int ->
?indefinite:bool ->
Netsys_types.tstring ->
Value.pc -> Type_name.type_name -> int * Value.value
Same for tagged strings
val decode_ber_contents_poly : ?pos:int ->
?len:int ->
?indefinite:bool ->
's Netstring_tstring.tstring_ops ->
's ->
Value.pc -> Type_name.type_name -> int * Value.value
Polymorphic version
val decode_ber_length : ?pos:int -> ?len:int -> string -> int
Like decode_ber, but returns only the length.

This function skips many consistency checks.

val decode_ber_length_tstring : ?pos:int -> ?len:int -> Netsys_types.tstring -> int
Same for tagged strings
val decode_ber_length_poly : ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> int
Polymorphic version
val decode_ber_header : ?pos:int ->
?len:int ->
?skip_length_check:bool ->
string -> int * Value.tag_class * Value.pc * int * int option
let (hdr_len, tc, pc, tag, len_opt) = decode_ber_header s: Decodes only the header:
  • hdr_len will be the length of the header in bytes
  • tc is the tag class
  • pc whether primitive or constructed
  • tag is the numeric tag value
  • len_opt is the length field, or None if the header selects indefinite length
If skip_length_check is set, the function does not check whether the string is long enough to hold the whole data part.

If the string is a valid beginning of a header, the special exception Header_too_short is raised (instead of Parse_error).

val decode_ber_header_tstring : ?pos:int ->
?len:int ->
?skip_length_check:bool ->
Netsys_types.tstring ->
int * Value.tag_class * Value.pc * int * int option
Same for tagged strings
val decode_ber_header_poly : ?pos:int ->
?len:int ->
?skip_length_check:bool ->
's Netstring_tstring.tstring_ops ->
's -> int * Value.tag_class * Value.pc * int * int option
Polymorphic version
val streamline_seq : (Value.tag_class * int * Type_name.type_name) list ->
Value.value list -> Value.value option list
streamline_seq expected seq: This function can be called for a list of values Value.Seq seq, and will compare the list seq with the expected list, and will mark missing elements in the sequence, and will recursively decode the occurring elements with the type information from expected.

For example, if expected is

 [Context,0,Integer; Context,1,Octetstring; Context,2,IA5String] 
and the passed seq is just
 [Tagptr(Context,1,...)] 
the function assumes that the elements with tags 0 and 2 are optional and it assumes that the element with tag 1 is decoded as Octetstring, leading to
 None; Some(Octetstring ...); None 

It is allowed to put Universal tags into the expected list. The tag number is ignored in this case (for simplicity).

val streamline_set : (Value.tag_class * int * Type_name.type_name) list ->
Value.value list -> Value.value list
streamline_set typeinfo set: This function can be called for a list of values Value.Set seq, and decodes the list with the type information from typeinfo.

For example, if typeinfo is

 [Context,0,Integer; Context,1,Octetstring; Context,2,IA5String] 
and the passed set is just
 [Tagptr(Context,1,...); Tagptr(Context 0,...)] 
the function decodes the elements as
 [ Octetstring ...; Integer ... ] 


The Abstract Syntax Notation 1 (ASN.1)

ASN.1 allows you to represent structured values as octet streams. The values can be composed from a wide range of base types (e.g. numbers and many different kinds of strings) and can be arranged as sequences (records and arrays), sets, and tagged values (a concept fairly close to OCaml variant types). There is a definition language allowing you to define types and values. This language is not covered here (and there is no IDL compiler). Look for ITU X.680 standard if you want to know more. We focus here on the octet representation, which is sufficient for parsing and printing ASN.1 values.

Encoding rules

There are three variants on the representation level:

  • BER: Basic Encoding Rules
  • CER: Canonical Encoding Rules
  • DER: Distinguished Encoding Rules
BER describes the basic way how the octets are obtained, but leaves several details up to the sender of an ASN.1 message. CER and DER use stricter rules that are subsets of BER so that a given value can only be represented in a single way. CER targets at large messages, whereas DER is optimized for small messages. This module includes a generic decoder for all BER messages, and Netasn1_encode supports DER encoding. The ASN.1 octet representations are described in ITU X.690.

The TLV representation

ASN.1 uses a type-length-value (TLV) style representation, i.e. there is a header containing type information and the length of the data, followed by the payload data. The data can be primitive (e.g. a number) or "constructed" (i.e. a composition of further values). For certain data types the user can choose whether to prefer a primitive representation or a construction from several part values (e.g. a very long string can be given as a sequence of string chunks). Because of this, there is a Netasn1.Value.pc bit in the representation so that this choice is available at runtime.

The type is given as a numeric tag (a small number), and a tag class (Netasn1.Value.tag_class). There are four tag classes:

  • Universal: These tags are used for types defined by the ASN.1 standard, and should not be used for anything else. For example the type OctetString gets the universal tag 3.
  • Application: These tags are intended for marking newly defined types. E.g. if you have a definition type filename = string and you would like to have filenames specially tagged to distinguish them from other uses of strings, the runtime representation of filenames could get an application tag (e.g. the number 8). In ASN.1 syntax:
       Filename ::= [APPLICATION 8] IA5String
       
  • Context-specific: These tags are intended for marking variants, i.e. tags that are local to a specific use. An example in ASN.1 syntax:
    CustomerRecord ::= SET { name            [0] VisibleString,
                             mailingAddress  [1] VisibleString,
                             accountNumber   [2] INTEGER,
                             balanceDue      [3] INTEGER }
       
    The numbers in brackets are the context-specific tags.
  • Private: These are reserved for site-specific extensions of standardized message formats.
Conceptionally, universal and application tags identify types, whereas context-specific tags identify variants (local cases). Both concepts are not cleanly separated, though. If you e.g. define a set of values, and one value variant is a string and another variant is an integer, there is no strict need to use context-specific tags, because the tags for the type "string" and for the type "integer" are already different. In ASN.1 syntax:

Example ::= SET { x VisibleString,
                  y INTEGER }

A VisibleString has universal tag 26, and an INTEGER has universal tag 3.

Note that the bracket notation includes a keyword "UNIVERSAL", "APPLICATION", or "PRIVATE" for these three classes, and that a plain number indicates context-specific tags.

Finally, there are two ways of applying tags: Explicit and implicit. Explicit tagging is used when the binary values should retain the complete type information: If a tag is applied to an existing value, another header with tag and length field is created, and the value is seen as the contents of this construction. In other words, tagging is an explicit construction like others (e.g. like a record).

Implicit tagging means that the tag of the existing value is replaced by the new tag. As tags also encode the types, this means that type information is lost, and you need apriori knowledge about the possible tags to decode such values (e.g. that an application tag 8 always means an IA5String).

How to decode values

The function Netasn1.decode_ber will happily decode any BER data and return a complex Netasn1.Value.value unless implicit tagging is used. Implicit tags cannot be decoded in one go because the type information is missing. Instead of completely decoding such tags, only a marker Tagptr(tag_class,tag,pc,data,pos,len) is created. Here, tag_class and tag describe the tag. The value to which the tag is applied is not yet parsed, but only a "pointer" in form of the string data, the position pos and the byte length len is returned. This range inside data represents the inner value.

After determining the type of this value (by knowing which type is applicable for tag and tag_class), you can call Netasn1.decode_ber_contents to decode the value. This function is different from Netasn1.decode_ber because it doesn't start at the header of the BER representation but after the header. The type needs to be passed explicitly because it isn't retrieved from the header.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.cache_t.html0000644000175000017500000004233012731530353022014 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.cache_t object
  method abort : unit -> unit
  method get_engine : unit -> 'Uq_engines.engine
  method get_opt : unit -> 'a option
  method invalidate : unit -> unit
  method put : '-> unit
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_portmapper_clnt.Make'PMAP.V3.html0000644000175000017500000006444412731530353024251 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt.Make'PMAP.V3 sig
  type t = U'C.t
  val _program : Rpc_program.t
  val rpcbproc_null :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res
  val rpcbproc_null'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res) -> unit) ->
    unit
  val rpcbproc_set :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res
  val rpcbproc_set'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res) -> unit) -> unit
  val rpcbproc_unset :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res
  val rpcbproc_unset'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res) -> unit) ->
    unit
  val rpcbproc_getaddr :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res
  val rpcbproc_getaddr'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res) -> unit) ->
    unit
  val rpcbproc_dump :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res
  val rpcbproc_dump'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res) -> unit) ->
    unit
  val rpcbproc_callit :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res
  val rpcbproc_callit'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res) -> unit) ->
    unit
  val rpcbproc_gettime :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res
  val rpcbproc_gettime'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res) -> unit) ->
    unit
  val rpcbproc_uaddr2taddr :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res
  val rpcbproc_uaddr2taddr'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res) -> unit) ->
    unit
  val rpcbproc_taddr2uaddr :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res
  val rpcbproc_taddr2uaddr'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res) -> unit) ->
    unit
end
ocamlnet-4.1.2/doc/html-main/Rpc_program.html0000644000175000017500000005242312731530353017550 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_program

Module Rpc_program

module Rpc_program: sig .. end
RPC programs


An RPC server offers its procedures as parts of a "program". Here, the notion of programs is introduced. A program is identified by a program number and a version number. The service of a program is a set of procedures that are described by procedure numbers and signatures. The signature of a procedure is a pair (s,u) of XDR types that should be interpreted as function s -> u. To make work easier, programs are encapsulated as an opaque type t. This data structure can store procedure names in addition to the plain numbers, so you can refer to procedures by their names. But note that these names are only local identifiers that are not transferred in the RPC protocol. The signature can be formulated upon a type system (a set of definitions of type names).
type t 
Type of RPC programs
val create : Netnumber.uint4 ->
Netnumber.uint4 ->
Netxdr.xdr_type_system ->
(string * (Netnumber.uint4 * Netxdr.xdr_type_term * Netxdr.xdr_type_term))
list -> t
create program_nr version_nr type_system procedures
val id : t -> int
The ID identifies the program (used in Rpc_client)
val update : ?program_number:Netnumber.uint4 ->
?version_number:Netnumber.uint4 -> t -> t
Modifies program and/or version number. The modified program is returned. The program keeps its identity, i.e. the id function returns the same number.
val program_number : t -> Netnumber.uint4
Return the program number
val version_number : t -> Netnumber.uint4
Return the version number
val null_proc_name : t -> string option
Returns the name of procedure 0 (or None if not found)
val signature : t ->
string -> Netnumber.uint4 * Netxdr.xdr_type * Netxdr.xdr_type

signature p name returns the triple (proc_nr, in_t, out_t) for the procedure name. proc_nr is the procedure number, in_t the argument type and out_t the result type.
val procedure_number : t -> string -> Netnumber.uint4
procedure_number p name returns only the procedure number of the procedure called name.
ocamlnet-4.1.2/doc/html-main/Netsys_win32.html0000644000175000017500000024427712731530353017616 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_win32

Module Netsys_win32

module Netsys_win32: sig .. end
Primitives for Win32


Files


val get_full_path_name : string -> string
Calls GetFullPathName
val get_long_path_name : string -> string
Calls GetLongPathName

Event objects


type w32_event 
val create_event : unit -> w32_event
Create an event object
val set_event : w32_event -> unit
Set the object to "signaled" state
val reset_event : w32_event -> unit
Set the object to "non-signaled" state
val test_event : w32_event -> bool
Test whether the object is in signaled state
val event_wait : w32_event -> float -> bool
Wait until the event is set to signaled state. The float argument is the timeout in seconds. The function returns whether the object is in signaled state.
val event_descr : w32_event -> Unix.file_descr
Returns the proxy descriptor for the event. See lookup below for more on proxy descriptors. This function always returns the same descriptor. The user has to close this descriptor if this function is called.

Primitives for sockets


val wsa_event_select : w32_event ->
Unix.file_descr -> Netsys_posix.poll_req_events -> unit
associate event objects with socket conditions
val wsa_maximum_wait_events : unit -> int
max size of the array passed to wsa_wait_for_multiple_events
val wsa_wait_for_multiple_events : w32_event array -> int -> int option
Waits until one of the events in the array is in signaled state, or until a timeout happens. The int is the timeout in milliseconds. A negative timeout means infinity.

The function returns the first index in the array that is signaled.

On timeout, None is returned.

The return value WSA_WAIT_IO_COMPLETION is mapped to the Unix error EINTR.

val wsa_enum_network_events : Unix.file_descr -> w32_event -> Netsys_posix.poll_act_events
Checks whether an event has been recorded
val real_select : Unix.file_descr list ->
Unix.file_descr list ->
Unix.file_descr list ->
float -> Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
Up to Ocaml 3.10, this function is identical to Unix.select. In 3.11, the latter was changed to a smart implementation that promises to handle other types of handles in addition to sockets. As we do the same in Netsys, this would be a duplication of work. Also, the older implementation is more mature.

Support for named pipes



Support for named pipes



Win32 named pipes work very much like Unix Domain sockets, only that the Win32 interface is different. This wrapper, however, mimicks socket behaviour as far as possible (and we also use an socket-like API with listen and accept). There is a w32_pipe_server representing pipe servers. An individual pipe is wrapped into a w32_pipe.

Win32 named pipes do not allow to check whether an operation would block before starting the operation. There is so-called overlapped I/O, but it works differently than Unix-style multiplexing.

The following functions add a layer to the Win32 primitives that helps using pipes in a way similar to multiplexing. We allocate buffers for input and output, and the functions pipe_read and pipe_write access these buffers in the first place. When reading, but the read buffer is empty, we start an overlapped read operation from the pipe handle. The arriving data refills the read buffer, and a w32_event is signaled to wake up any pending event loop. During the pending read from the pipe handle, the read buffer is locked, and pipe_read will return EWOULDBLOCK.

Writing is slightly more difficult. The first pipe_write puts the data into the write buffer, and immediately starts an overlapped I/O operation to write the data to the pipe handle. During this operation the write buffer is locked, and cannot be further used to accumulate data, even if there is space. So pipe_write will return EWOULDBLOCK while the operation takes place. A w32_event is signaled when the write operation is over.

The only downside of this approach is that the caller has to use pipe_read and pipe_write to access pipes, instead of Unix.read and Unix.write. If generic r/w functions are required that work for numerous kinds of descriptors, there are Netsys.gread and Netsys.gwrite which support named pipes.

type w32_pipe_server 
A pipe server. Note that there is no such thing in the Win32 API. Actually, a w32_pipe_server contains the server endpoints of a number of pipes, and a few helper objects.
type w32_pipe 
A pipe endpoint
type pipe_mode = 
| Pipe_in
| Pipe_out
| Pipe_duplex
val rev_mode : pipe_mode -> pipe_mode
Reverses the direction
val create_local_pipe_server : string -> pipe_mode -> int -> w32_pipe_server

create_local_named_pipe name mode n: Create a pipe server. The name must have the format "\\.\pipe\<name>". In n the maximum number of instances is passed. The server is set up with a security descriptor so only clients on the same system can connect.

create_local_named_pipe name mode n: Create a pipe server. The name must have the format "\\.\pipe\<name>". In n the maximum number of instances is passed. The server is set up with a security descriptor so only clients on the same system can connect.

In the following, a terminology has been chosen that is similar to those of the socket API. The terms are different from those Microsoft prefers, however.
val pipe_listen : w32_pipe_server -> int -> unit
Creates the backlog queue with n prepared server endpoints.

One can check for new client connections by looking at the pipe_connect_event.

val pipe_accept : w32_pipe_server -> w32_pipe
Waits until the connect event is signaled (usually meaning that a new client connection is available), and returns the new pipe.
val pipe_connect : string -> pipe_mode -> w32_pipe
pipe_connect name mode: Creates a client pipe handle, and tries to connect to the pipe server name. The function fails with the Unix error EAGAIN if there are currently no listening instances of the pipe at the server.

The name must be of the form "\\.\pipe\<name>" (excluding connects to pipes on remote systems). This function allows only connects to local pipe servers, and enforces anonymous impersonation.

Note that you also can connect to named pipes using open_in and Unix.openfile, and that these functions do not protect against malicious servers that impersonate as the caller.

val pipe_pair : pipe_mode -> w32_pipe * w32_pipe
Returns a pair of connected pipes (using automatically generated names). The left pipe is in the passed pipe_mode, and the right pipe is in the matching complementaty mode.
val pipe_read : w32_pipe -> Bytes.t -> int -> int -> int
pipe_read p s pos len: Tries to read data from the pipe. If data is available, it is put into the len bytes at position pos of the string s, and the actual number of read bytes is returned.

If no data is available, the function fails with a Unix error of EAGAIN.

If the end of the pipe is reached, the function returns 0.

val pipe_write : w32_pipe -> Bytes.t -> int -> int -> int
pipe_write p s pos len: Tries to write data to the pipe. If space is available, the data is taken from the len bytes at position pos of the string s, and the actual number of written bytes is returned.

If no space is available, the function fails with a Unix error of EAGAIN.

val pipe_write_string : w32_pipe -> string -> int -> int -> int
Same for immutable string
val pipe_shutdown : w32_pipe -> unit
Cancels all pending I/O operations and closes the pipe handle.

Note that there is no way to close only one direction of bidirectional pipes.

See the comments on closing pipes below.

val pipe_shutdown_server : w32_pipe_server -> unit
Closes the pipe server: All endpoints in the backlog queue are shutdown. Note that this can result in crashed connections - if the kernel establishes a connection but it is not yet pipe_accepted, it is simply destroyed by this function.
val pipe_connect_event : w32_pipe_server -> w32_event
The event object signals when a new client connection is available
val pipe_rd_event : w32_pipe -> w32_event
val pipe_wr_event : w32_pipe -> w32_event
The event objects signaling that read and write operations are possible. The read event is in signaled state when the read buffer is non-empty (even for write-only pipes). The write event is in signaled state when the pipe is connected and the write buffer is empty (even for read-only pipes).
val pipe_wait_connect : w32_pipe_server -> float -> bool
Wait until a client connects to this server. The float argument is the timeout in seconds. The function returns whether there is data to read or write. If not, a timeout has occurred.
val pipe_wait_rd : w32_pipe -> float -> bool
val pipe_wait_wr : w32_pipe -> float -> bool
Wait until the pipe becomes readable or writable. The float argument is the timeout in seconds. The function returns whether there is data to read or write. If not, a timeout has occurred.
val pipe_server_descr : w32_pipe_server -> Unix.file_descr
Returns the proxy descriptor for the pipe server. See lookup below for more on proxy descriptors. This function always returns the same descriptor. The user has to close this descriptor if this function is called.
val pipe_descr : w32_pipe -> Unix.file_descr
Returns the proxy descriptor for the pipe. See lookup below for more on proxy descriptors. This function always returns the same descriptor. The user has to close this descriptor if this function is called.
val pipe_name : w32_pipe -> string
val pipe_server_name : w32_pipe_server -> string
Returns the name of the pipe
val pipe_mode : w32_pipe -> pipe_mode
val pipe_server_mode : w32_pipe_server -> pipe_mode
Returns the pipe/server mode
val unpredictable_pipe_name : unit -> string
Returns a valid pipe name that can practically not be predicted

Shutting down pipes. The suggested model is that the client shuts down the pipe first. A pipe client ensures that all data are transmitted by waiting until the pipe becomes writable again, and then calling pipe_shutdown. The server then sees EOF when reading from the pipe, or gets an EPIPE error when writing to the pipe. The server should then also pipe_shutdown the endpoint.

When servers start the closure of connections, there is no clean way of ensuring that all written data are transmitted. There is the FlushFileBuffers Win32 function, but it is blocking.

Shutting down pipes. The suggested model is that the client shuts down the pipe first. A pipe client ensures that all data are transmitted by waiting until the pipe becomes writable again, and then calling pipe_shutdown. The server then sees EOF when reading from the pipe, or gets an EPIPE error when writing to the pipe. The server should then also pipe_shutdown the endpoint.

When servers start the closure of connections, there is no clean way of ensuring that all written data are transmitted. There is the FlushFileBuffers Win32 function, but it is blocking.

I/O threads



Shutting down pipes. The suggested model is that the client shuts down the pipe first. A pipe client ensures that all data are transmitted by waiting until the pipe becomes writable again, and then calling pipe_shutdown. The server then sees EOF when reading from the pipe, or gets an EPIPE error when writing to the pipe. The server should then also pipe_shutdown the endpoint.

When servers start the closure of connections, there is no clean way of ensuring that all written data are transmitted. There is the FlushFileBuffers Win32 function, but it is blocking.

I/O threads



I/O threads can be used to do read/write-based I/O in an asynchronous way for file handles that do not support asynchronous I/O by themselves, e.g. anonymous pipes.

I/O threads are only available if the application is compiled as multi-threaded program.

type w32_input_thread 
val create_input_thread : Unix.file_descr -> w32_input_thread
Creates the input thread for this file descriptor. Data is being pumped from this handle to an internal buffer, and can be read from there by input_thread_read.

The thread continues to run until EOF is reached, an I/O error occurs, or until the thread is cancelled (cancel_input_thread).

After starting the input thread, the file descriptor must not be used anymore. It is now owned by the input thread.

val input_thread_event : w32_input_thread -> w32_event
This event is signaled when there is data to read, or the EOF is reached, or there is an error condition
val input_thread_read : w32_input_thread -> Bytes.t -> int -> int -> int
input_thread_read t s pos len: Tries to read data from the buffer. If data is available, it is put into the len bytes at position pos of the string s, and the actual number of read bytes is returned.

If no data is available, the function fails with a Unix error of EAGAIN (non-blocking).

If the end of the data is reached, the function returns 0.

For cancelled requests, the function raises EPERM.

val cancel_input_thread : w32_input_thread -> unit
Stops the input thread. No more data will be pumped from the handle to the internal buffer. It is no error to cancel a thread that is already cancelled. There is no way to restart the thread later.

The thread is automatically cancelled by the GC finaliser. However, users are encouraged to call cancel_input_thread as soon as the thread is no longer needed, because a thread is an expensive resource.

Implementation note: Actually, cancellation is only fully implemented on Windows Vista. On XP the actual cancellation may be delayed indefinetely.

val input_thread_proxy_descr : w32_input_thread -> Unix.file_descr
Returns the proxy descriptor
type w32_output_thread 
val create_output_thread : Unix.file_descr -> w32_output_thread
Creates the output thread for this file descriptor. Data is being pumped an internal buffer to this descriptor, and can be written there by output_thread_read.

The thread continues to run until it is explicitly closed, or an I/O error occurs, or until the thread is cancelled (cancel_output_thread).

After starting the output thread, the file descriptor must not be used anymore. It is now owned by the output thread.

val output_thread_event : w32_output_thread -> w32_event
This event is signaled when there is space in the buffer, or when there is an error condition
val output_thread_write : w32_output_thread -> Bytes.t -> int -> int -> int
output_thread_write t s pos len: Tries to write data to the buffer. If this is possible, the substring starting at position pos of the string s with a length of len is appended to the buffer. The actual number of written bytes is returned.

If no space is available in the buffer, the function fails with a Unix error of EAGAIN (non-blocking).

For cancelled requests, the function raises EPERM.

val output_thread_write_string : w32_output_thread -> string -> int -> int -> int
Same for immutable strings
val close_output_thread : w32_output_thread -> unit
Adds the EOF condition to the buffer. When the buffer is written to the descriptor, the descriptor will be closed.

Note that this is also an asynchronous operation, like output_thread_write. If closing is not possible at a certain moment, the Unix error EGAIN is raised. This ensures that all errors of previous writes can be reported.

The output thread terminates after a successful close.

For cancelled requests, the function raises EPERM.

val cancel_output_thread : w32_output_thread -> unit
Stops the output thread. This is different from closing as the data that is still in the buffer but not yet written may be dropped (if possible). Also, there is no error reporting.

It is no error to cancel a thread that is already cancelled or closed. There is no way to restart the thread later.

The thread is automatically cancelled by the GC finaliser. However, users are encouraged to call cancel_output_thread or close_output_thread as soon as the thread is no longer needed, because a thread is an expensive resource.

Implementation note: Actually, cancellation is only fully implemented on Windows Vista. On XP the actual cancellation may be delayed indefinetely.

val output_thread_proxy_descr : w32_output_thread -> Unix.file_descr
Returns the proxy descriptor

Processes



Processes



Keep in mind that Win32 distinguishes between two kinds of executables: console applications, and GUI applications. The kind is set at link time, and stored in the executable file. Years ago, these kinds meant different worlds, and a GUI application could not act like a console application, and vice versa. Nowaways, however, the distinction is mostly gone, and the application kind only affects defaults at program startup:

  • Console: A GUI application starts without console. However, it is possible to allocate a console later. A console application always starts with a console which is created by the OS if missing.
  • Standard handles: For a GUI application, stdin/stdout/stderr are initially set to the invalid file handle. Nevertheless, this feature of standard handles exists, and one can set these handles later. Also, the handles can be inherited by the parent process. For console applications, the standard handles are normally set to the console, and applications can redirect them.
  • Main program: Of course, there is also the difference which C function is called at program startup - hey, but this is O'Caml!
  • Waiting for completion: It is uncommon to wait for the completion of GUI applications. The command interpreter seems to implement a magic so that it is not waited until the program is finished when a GUI application is started. For console applications this is of course done. (Note that this feature is the main reason why programmers still have to link applications as console applications, and cannot simply get the same effect from a application that is linked as GUI and then opens a console.)

type create_process_option = 
| CP_change_directory of string (*
The initial working directory is set to this path. By default the new process starts with the current working directory of the caller.
*)
| CP_set_env of string (*
The process environment is set to this encoded array of environment variables. By default the current environment is passed down to the new process.

The string is created from an array of "name=value" settings by separating all elements by null bytes, and by putting two null bytes at the end.

*)
| CP_std_handles of Unix.file_descr * Unix.file_descr * Unix.file_descr (*
Sets the standard handles of the new console process.
*)
| CP_create_console (*
Creates a new console window. The standard handles of the new process may also be modified - however, the exact effect is not well documented by Microsoft. I have the impression that the logic is this: handles pointing to the parent console are replaced by handles pointing to the new console. Also, invalid handles are replaced by handles of the new console. It does not matter how the standard handles are passed down - either implicitly or by CP_std_handles. So you cannot create a new console, and keep standard handles that are connected to the old console. Best practice is to avoid the combination of CP_std_handles and CP_create_console when there is already a console.

This flag does not have any effect when the started app is a GUI app.

*)
| CP_detach_from_console (*
The new process detaches from the console at startup, even if it is a console application. Unless CP_std_handles is specified, the new process will initially not have standard handles (i.e. the standard handles are invalid handles)! GUI apps detach from the console anyway.
*)
| CP_inherit_console (*
The new console process inherits the console from the caller, if present. Otherwise the new console process starts without console. For GUI apps there is not any effect: They do not have a console anyway.
*)
| CP_inherit_or_create_console (*
If present, the console is inherited from the caller. If not present, a new console is created for console applications. This mode is the default.
*)
| CP_unicode_environment (*
Indicates that the environment is a Unicode environment
*)
| CP_ansi_environment (*
Indicates that the environment is an ANSI environment. This is the default.
*)
| CP_new_process_group (*
The new process is run in a new process group
*)
| CP_inherit_process_group (*
The new process is run in the same process group as the caller. This is the default
*)
val cp_set_env : string array -> create_process_option
Returns the CP_set_env option for this array of environment variables (in the Unix.environment format)
val search_path : string option -> string -> string option -> string
search_path path_opt name ext_opt: Uses the SearchPath function to locate a file. If name does not end with ext_opt, this extension is added during the search. If path_opt is None, the default search path is used.
type w32_process 
A handle to spawned processes
val create_process : string ->
string -> create_process_option list -> w32_process
create_process cmd cmdline options: Spawns a new process that runs concurrently with the calling process. cmd is the command to execute (it is not searched by path, and the file suffix must be given). cmdline is the full command-line.

If the exit code of the new process does not play any role, it is ok to just ignore the returned process handle (which will be automatically closed by a GC finalizer).

val close_process : w32_process -> unit
Closes the handle in the w32_process value, if it is still open
val get_process_status : w32_process -> Unix.process_status option
Returns the process result if the process is finished, and None otherwise
val as_process_event : w32_process -> w32_event
Casts the process handle to an event handle. The process handle is in signaled state as soon as the spawned process is terminated. The event handle can be used in event_wait (above) and wsa_wait_for_multiple_events to wait for the termination of the process.
val emulated_pid : w32_process -> int
Returns the MSVCRT.DLL notion of the process identifier (pid). This kind of pid is used in the Unix library to refer to processes, especially in waitpid. Note that the pid is actually a handle, and it must be closed by calling Unix.waitpid.

Each call of emulated_pid returns a new handle.

val win_pid : w32_process -> int
Returns the Windows notion of the process identifier (pid)
val process_descr : w32_process -> Unix.file_descr
Returns the proxy descriptor of the process
val terminate_process : w32_process -> unit
Terminates the process

Consoles


val has_console : unit -> bool
True if there is a console
val is_console : Unix.file_descr -> bool
Tests whether the descriptor is the input or the output stream of the console.
val get_console_input : unit -> Unix.file_descr
Get the input stream of the console. If there is no console yet, a new one is opened.

The returned descriptor needs to be closed by the caller when done with it.

val get_console_output : unit -> Unix.file_descr
Get the output stream of the console. If there is no console yet, a new one is opened

The returned descriptor needs to be closed by the caller when done with it.


We use a simplified model of the console where only the visible part of the buffer is represented. All coordinates are relative to the visible part of the buffer.
type w32_console_attr = {
   mutable cursor_x : int; (*
from 0 (leftmost) to width-1 (rightmost)
*)
   mutable cursor_y : int; (*
from 0 (topmost) to height-1 (bottommost)
*)
   mutable cursor_size : int; (*
from 1 to 100
*)
   mutable cursor_visible : bool;
   mutable text_attr : int;
}
type w32_console_info = {
   mutable width : int; (*
screen width of the console in chars
*)
   mutable height : int; (*
screen height in lines
*)
}
val get_console_attr : unit -> w32_console_attr
val set_console_attr : w32_console_attr -> unit
Get/set console attributes.
val get_console_info : unit -> w32_console_info
Get r/o console info.
val fg_blue : int
val fg_green : int
val fg_red : int
val fg_intensity : int
val bg_blue : int
val bg_green : int
val bg_red : int
val bg_intensity : int
Bits of text_attr
type w32_console_mode = {
   mutable enable_echo_input : bool;
   mutable enable_insert_mode : bool;
   mutable enable_line_input : bool;
   mutable enable_processed_input : bool;
   mutable enable_quick_edit_mode : bool;
   mutable enable_processed_output : bool;
   mutable enable_wrap_at_eol_output : bool;
}
See the msdn docs for GetConsoleMode for details
val get_console_mode : unit -> w32_console_mode
val set_console_mode : w32_console_mode -> unit
Get/set the console mode.
val init_console_codepage : unit -> unit
Sets the code page of the console to the ANSI code page of the system. Unfortunately, the console uses the OEM code page by default (e.g. code page 437 instead of 1252). This function changes the code page back to the ANSI version.

Note, however, that the docs say: "If the current font is a raster font, SetConsoleOutputCP does not affect how extended characters are displayed." (grrmmpf) So you should also switch to a different font - otherwise you get input in the ANSI code page, and do output in the OEM code page.

For Windows novices: Historically, there were two types of 8 bit character sets. The older type is an IBM code page, and predates the ISO-8859 series of character sets. This code page was used at MS-DOS times. Microsoft calls this code page the "OEM" code page. Later, when ISO-8859 was created, Microsoft switched to code pages that are similar to this standard, but also do not fully match them. These newer code pages have names like "Windows-1252", and are now called ANSI code pages by Microsoft. The 8-bit versions of the Win32 calls (which are used by the Ocaml runtime)normally use the ANSI code page.

val clear_until_end_of_line : unit -> unit
Writes a space character from the current cursor position to the end of the line
val clear_until_end_of_screen : unit -> unit
Writes a space character from the current cursor position to the end of the screen
val clear_console : unit -> unit
Clears the screen and the buffer, and sets the cursor to (0,0).

Miscelleneous


val get_active_code_page : unit -> int
Get the active code page. See http://msdn.microsoft.com/en-us/library/dd317756%28v=VS.85%29.aspx for a list of codes. Also see Netconversion.win32_code_pages.

Proxy Descriptors



Proxy Descriptors



For a number of objects (w32_event, w32_pipe, and w32_pipe_server) it is possible to obtain proxy descriptors. These have type Unix.file_descr and they contain a real file handle. The purpose of these descriptors is to be used as proxy objects that can be passed to functions expecting file descriptors as input. However, you cannot do anything with the proxies except looking the corresponding real objects up. Proxy descriptors are used in interfaces that only allow to pass Unix.file_descr values in and out.

Proxy descriptors have to be closed by the caller once they have been handed out to the caller. Closing the proxy descriptor does not make the descriptor unusable (lookups still work), and the referenced object is also unaffected. It is up to the user when Unix.close is best called - it is even allowed to do it immediately after requesting the proxy descriptor, e.g. via pipe_descr. After closing the proxy, however, it is possible that the system generates another file descriptor that looks equal to the closed proxy. It is often best to close at the moment when one is really done with the proxy.

type w32_object = 
| W32_event of w32_event
| W32_pipe of w32_pipe
| W32_pipe_server of w32_pipe_server
| W32_process of w32_process
| W32_input_thread of w32_input_thread
| W32_output_thread of w32_output_thread
val lookup : Unix.file_descr -> w32_object
Returns the real object behind a proxy descriptor, or raises Not_found. Note that the returned object needs not to be physically identical to the original object. It behaves, however, exactly the same way.
val lookup_event : Unix.file_descr -> w32_event
val lookup_pipe : Unix.file_descr -> w32_pipe
val lookup_pipe_server : Unix.file_descr -> w32_pipe_server
val lookup_process : Unix.file_descr -> w32_process
val lookup_input_thread : Unix.file_descr -> w32_input_thread
val lookup_output_thread : Unix.file_descr -> w32_output_thread
Returns the real object. If not found, or if the object is of unexpected type, Failure is raised.
val unregister : Unix.file_descr -> unit
Removes this descriptor from the lookup table. This should only be done after it is closed. Calling unregister is optional, and the removal will take place anyway when the descriptor is collected by the GC.

Miscelleneous


val test_close_on_exec : Unix.file_descr -> bool
Tests whether the handle is not inheritable
val modify_close_on_exec : Unix.file_descr -> bool -> unit
Sets the close-on-exec flag, i.e. whether the handle is not inheritable. Note that Unix.set_close_on_exec and Unix.clear_close_on_exec have a serious problem, and do not always work.
val is_crt_fd : Unix.file_descr -> int -> bool
Tests whether the descriptor has a certain CRT counterpart. E.g. use is_crt_fd 0 to check whether fd is Unix.stdin (physically)
val fill_random : Bytes.t -> unit
Fills the string with random bytes. A cryptographically secure RNG is used

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.v_extended_environment.html0000644000175000017500000005702212731530353026124 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.v_extended_environment object
  method cgi_auth_type : string
  method cgi_gateway_interface : string
  method cgi_https : bool
  method cgi_path_info : string
  method cgi_path_translated : string
  method cgi_properties : (string * string) list
  method cgi_property : ?default:string -> string -> string
  method cgi_query_string : string
  method cgi_remote_addr : string
  method cgi_remote_host : string
  method cgi_remote_ident : string
  method cgi_remote_user : string
  method cgi_request_method : string
  method cgi_request_uri : string
  method cgi_script_name : string
  method cgi_server_name : string
  method cgi_server_port : int option
  method cgi_server_protocol : string
  method cgi_server_software : string
  method config : Netcgi.config
  method cookie : string -> Netcgi.Cookie.t
  method cookies : Netcgi.Cookie.t list
  method input_body_size : int64
  method input_channel : Netchannels.in_obj_channel
  method input_content_length : int
  method input_content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method input_content_type_string : string
  method input_header : Netmime.mime_header
  method input_header_field : ?default:string -> string -> string
  method input_header_fields : (string * string) list
  method log_error : string -> unit
  method log_props : (string * string) list -> unit
  method multiple_input_header_field : string -> string list
  method multiple_output_header_field : string -> string list
  method out_channel : Netchannels.out_obj_channel
  method output_ch : Netchannels.out_obj_channel
  method output_header : Netmime.mime_header
  method output_header_field : ?default:string -> string -> string
  method output_header_fields : (string * string) list
  method virtual output_state : Nethttpd_types.output_state Pervasives.ref
  method protocol : Nethttp.protocol
  method virtual remote_socket_addr : Unix.sockaddr
  method request_body_rejected : bool
  method send_file : Unix.file_descr -> int64 -> unit
  method send_output_header : unit -> unit
  method virtual server_socket_addr : Unix.sockaddr
  method set_multiple_output_header_field : string -> string list -> unit
  method set_output_header_field : string -> string -> unit
  method set_output_header_fields : (string * string) list -> unit
  method set_status : Nethttp.http_status -> unit
  method tls_session_props : Nettls_support.tls_session_props option
  method user_agent : string
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.signal_engine.html0000644000175000017500000004311212731530353024572 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.signal_engine Unixqueue.event_system ->
object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : ('a engine -> bool) -> unit
  method signal : 'Uq_engines_compat.final_state -> unit
  method state : 'a engine_state
end
ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.html0000644000175000017500000007562712731530353020642 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer sig
  class type async_out_channel =
    object
      method can_output : bool
      method close_out : unit -> unit
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method pos_out : int
      method request_notification : (unit -> bool) -> unit
    end
  class type async_in_channel =
    object
      method can_input : bool
      method close_in : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method pos_in : int
      method request_notification : (unit -> bool) -> unit
    end
  class pseudo_async_out_channel :
    #Netchannels.raw_out_channel -> async_out_channel
  class pseudo_async_in_channel :
    #Netchannels.raw_in_channel -> async_in_channel
  class receiver :
    src:Unix.file_descr ->
    dst:#Uq_transfer.async_out_channel ->
    ?close_src:bool ->
    ?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines.engine
  class sender :
    src:#Uq_transfer.async_in_channel ->
    dst:Unix.file_descr ->
    ?close_src:bool ->
    ?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines.engine
  class type async_out_channel_engine =
    object
      method abort : unit -> unit
      method can_output : bool
      method close_out : unit -> unit
      method event_system : Unixqueue.event_system
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method pos_out : int
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        (unit Uq_engines.engine -> bool) -> unit
      method state : unit Uq_engines.engine_state
    end
  class type async_in_channel_engine =
    object
      method abort : unit -> unit
      method can_input : bool
      method close_in : unit -> unit
      method event_system : Unixqueue.event_system
      method input : Bytes.t -> int -> int -> int
      method pos_in : int
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        (unit Uq_engines.engine -> bool) -> unit
      method state : unit Uq_engines.engine_state
    end
  class output_async_descr :
    dst:Unix.file_descr ->
    ?buffer_size:int ->
    ?close_dst:bool -> Unixqueue.event_system -> async_out_channel_engine
  class input_async_descr :
    src:Unix.file_descr ->
    ?buffer_size:int ->
    ?close_src:bool -> Unixqueue.event_system -> async_in_channel_engine
  type copy_task =
      [ `Bidirectional of Unix.file_descr * Unix.file_descr
      | `Tridirectional of
          Unix.file_descr * Unix.file_descr * Unix.file_descr
      | `Uni_socket of Unix.file_descr * Unix.file_descr
      | `Unidirectional of Unix.file_descr * Unix.file_descr ]
  class copier :
    Uq_transfer.copy_task ->
    Unixqueue.event_system -> [unit] Uq_engines.engine
  type onshutdown_out_spec =
      [ `Action of
          Uq_transfer.async_out_channel_engine ->
          Uq_engines.multiplex_controller ->
          unit Uq_engines.engine_state -> unit
      | `Ignore
      | `Initiate_shutdown ]
  type onshutdown_in_spec =
      [ `Action of
          Uq_transfer.async_in_channel_engine ->
          Uq_engines.multiplex_controller ->
          unit Uq_engines.engine_state -> unit
      | `Ignore
      | `Initiate_shutdown ]
  class output_async_mplex :
    ?onclose:[ `Ignore | `Write_eof ] ->
    ?onshutdown:Uq_transfer.onshutdown_out_spec ->
    ?buffer_size:int ->
    Uq_engines.multiplex_controller -> async_out_channel_engine
  class input_async_mplex :
    ?onshutdown:Uq_transfer.onshutdown_in_spec ->
    ?buffer_size:int ->
    Uq_engines.multiplex_controller -> async_in_channel_engine
end
ocamlnet-4.1.2/doc/html-main/type_Netgzip.output_inflate.html0000644000175000017500000004076512731530353023025 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.output_inflate Netchannels.out_obj_channel -> Netchannels.out_obj_channelocamlnet-4.1.2/doc/html-main/type_Netx509_pubkey.html0000644000175000017500000010373512731530353021074 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey sig
  type oid = Netoid.t
  type alg_id = Alg_id of Netx509_pubkey.oid * Netasn1.Value.value option
  type pubkey = {
    pubkey_type : Netx509_pubkey.alg_id;
    pubkey_data : Netasn1.Value.bitstring_value;
  }
  type hash_function = [ `SHA_1 | `SHA_224 | `SHA_256 | `SHA_384 | `SHA_512 ]
  type maskgen_function = [ `MGF1 of Netx509_pubkey.hash_function ]
  type alg_param =
      P_PSS of Netx509_pubkey.hash_function *
        Netx509_pubkey.maskgen_function * int
    | P_OAEP of Netx509_pubkey.hash_function *
        Netx509_pubkey.maskgen_function * string
  type encrypt_alg =
      Encrypt of Netx509_pubkey.oid * Netx509_pubkey.alg_param option
  type sign_alg =
      Sign of Netx509_pubkey.oid * Netx509_pubkey.alg_param option
  type kex_alg = Kex of Netx509_pubkey.oid * Netx509_pubkey.alg_param option
  val decode_pubkey_from_der : string -> Netx509_pubkey.pubkey
  val encode_pubkey_to_der : Netx509_pubkey.pubkey -> string
  val read_pubkey_from_pem :
    Netchannels.in_obj_channel -> Netx509_pubkey.pubkey
  type privkey = Privkey of string * string
  val read_privkey_from_pem :
    Netchannels.in_obj_channel -> Netx509_pubkey.privkey
  module Key :
    sig
      val rsa_key : Netx509_pubkey.oid
      val rsassa_pss_key : Netx509_pubkey.oid
      val rsaes_oaep_key : Netx509_pubkey.oid
      val dsa_key : Netx509_pubkey.oid
      val dh_key : Netx509_pubkey.oid
      val ec_key : Netx509_pubkey.oid
      val ecdh_key : Netx509_pubkey.oid
      val ecmqv_key : Netx509_pubkey.oid
      val kea_key : Netx509_pubkey.oid
      val eddsa_key : Netx509_pubkey.oid
      val catalog : (string * string list * string * Netx509_pubkey.oid) list
      val private_key_format_of_key : Netx509_pubkey.oid -> string
      val create_rsassa_pss_alg_id :
        hash_function:Netx509_pubkey.hash_function ->
        maskgen_function:Netx509_pubkey.maskgen_function ->
        salt_length:int -> unit -> Netx509_pubkey.alg_id
      val create_rsassa_pss_key :
        hash_function:Netx509_pubkey.hash_function ->
        maskgen_function:Netx509_pubkey.maskgen_function ->
        salt_length:int -> Netx509_pubkey.pubkey -> Netx509_pubkey.pubkey
      val create_rsaes_oaep_alg_id :
        hash_function:Netx509_pubkey.hash_function ->
        maskgen_function:Netx509_pubkey.maskgen_function ->
        psource_function:string -> unit -> Netx509_pubkey.alg_id
      val create_rsaes_oaep_key :
        hash_function:Netx509_pubkey.hash_function ->
        maskgen_function:Netx509_pubkey.maskgen_function ->
        psource_function:string ->
        Netx509_pubkey.pubkey -> Netx509_pubkey.pubkey
    end
  module Encryption :
    sig
      val rsa : Netx509_pubkey.encrypt_alg
      val rsaes_oaep :
        hash_function:Netx509_pubkey.hash_function ->
        maskgen_function:Netx509_pubkey.maskgen_function ->
        psource_function:string -> Netx509_pubkey.encrypt_alg
      val catalog :
        (string * string list * Netx509_pubkey.encrypt_alg *
         Netx509_pubkey.oid)
        list
      val encrypt_alg_of_pubkey :
        Netx509_pubkey.pubkey -> Netx509_pubkey.encrypt_alg
      val alg_id_of_encrypt_alg :
        Netx509_pubkey.encrypt_alg -> Netx509_pubkey.alg_id
      val key_oid_of_encrypt_alg :
        Netx509_pubkey.encrypt_alg -> Netx509_pubkey.oid
    end
  module Keyagreement :
    sig
      val dh : Netx509_pubkey.kex_alg
      val ec : Netx509_pubkey.kex_alg
      val ecdh : Netx509_pubkey.kex_alg
      val ecmqv : Netx509_pubkey.kex_alg
      val kea : Netx509_pubkey.kex_alg
      val catalog :
        (string * string list * Netx509_pubkey.kex_alg * Netx509_pubkey.oid)
        list
      val alg_id_of_kex_alg : Netx509_pubkey.kex_alg -> Netx509_pubkey.alg_id
      val key_oid_of_kex_alg : Netx509_pubkey.kex_alg -> Netx509_pubkey.oid
    end
  module Signing :
    sig
      val rsa_with_sha1 : Netx509_pubkey.sign_alg
      val rsa_with_sha224 : Netx509_pubkey.sign_alg
      val rsa_with_sha256 : Netx509_pubkey.sign_alg
      val rsa_with_sha384 : Netx509_pubkey.sign_alg
      val rsa_with_sha512 : Netx509_pubkey.sign_alg
      val rsassa_pss :
        hash_function:Netx509_pubkey.hash_function ->
        maskgen_function:Netx509_pubkey.maskgen_function ->
        salt_length:int -> Netx509_pubkey.sign_alg
      val dsa_with_sha1 : Netx509_pubkey.sign_alg
      val dsa_with_sha224 : Netx509_pubkey.sign_alg
      val dsa_with_sha256 : Netx509_pubkey.sign_alg
      val ecdsa_with_sha1 : Netx509_pubkey.sign_alg
      val ecdsa_with_sha224 : Netx509_pubkey.sign_alg
      val ecdsa_with_sha256 : Netx509_pubkey.sign_alg
      val ecdsa_with_sha384 : Netx509_pubkey.sign_alg
      val ecdsa_with_sha512 : Netx509_pubkey.sign_alg
      val eddsa : Netx509_pubkey.sign_alg
      val catalog :
        (string * string list * Netx509_pubkey.sign_alg * Netx509_pubkey.oid)
        list
      val alg_id_of_sign_alg :
        Netx509_pubkey.sign_alg -> Netx509_pubkey.alg_id
      val key_oid_of_sign_alg : Netx509_pubkey.sign_alg -> Netx509_pubkey.oid
    end
end
ocamlnet-4.1.2/doc/html-main/Netchannels.socket_descr-c.html0000644000175000017500000004556312731530353022435 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.socket_descr

Class Netchannels.socket_descr

class socket_descr : ?blocking:bool -> ?start_pos_in:int -> ?start_pos_out:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_io_channel
Creates a raw_io_channel for the passed socket descriptor, which must be open for reading and writing, and not yet shut down in either direction. The raw_io_channel is used to represent a bidirectional channel: close_out shuts the socket down for sending, close_in shuts the socket down for reading, and when both directions are down, the descriptor is closed.

The pos_in and pos_out methods returns logical positions.

This class supports sockets and Win32 named pipes. Note, however, that for Win32 named pipes it is not possible to shut down only one direction of the bidirectional data channel.


start_pos_in : The position to which pos_in is initialized when the channel is created, by default 0
start_pos_out : The position to which pos_out is initialized when the channel is created, by default 0
fd_style : The descriptor style. If omitted, it is automatically determined if possible.

ocamlnet-4.1.2/doc/html-main/type_Uq_engines.stream_seq_engine.html0000644000175000017500000004163712731530353024127 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.stream_seq_engine '->
('-> '#Uq_engines.engine) Stream.t ->
Unixqueue.event_system -> ['a] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Netshm_intro.html0000644000175000017500000004061512731530353021007 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm_intro sig  endocamlnet-4.1.2/doc/html-main/Nethttpd_engine.http_engine-c.html0000644000175000017500000004472512731530353023145 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_engine

Class Nethttpd_engine.http_engine

class http_engine : ?config_hooks:Nethttpd_kernel.http_protocol_hooks -> unit -> on_request_header:(http_request_header_notification -> unit) -> unit -> #http_engine_config -> Unix.file_descr -> Unixqueue.unix_event_system -> [unit] Uq_engines.engine
This engine processes the requests arriving on the file descriptor using the Unix event system. Whenever a new request header arrives, the function on_request_header is called back, and must handle the request.

Unless aborted using the abort method, this engine is always successful. Errors are logged, but not returned as result.

The file descriptor is closed after processing all HTTP requests and responses. It is also closed on error and when the engine is aborted.

An aborted engine does not try to clean up resources external to the engine, e.g. by calling the on_error functions. This is up to the user.


ocamlnet-4.1.2/doc/html-main/Nethttp.http_trailer_ro-c.html0000644000175000017500000004203512731530353022341 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.http_trailer_ro

Class type Nethttp.http_trailer_ro

class type http_trailer_ro = Netmime.mime_header_ro
The HTTP trailer is represented as MIME header

ocamlnet-4.1.2/doc/html-main/Netcgi.Argument.html0000644000175000017500000004774512731530353020302 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.Argument

Module Netcgi.Argument

module Argument: sig .. end
Operations on arguments and lists of thereof.

exception Oversized
val simple : string -> string -> Netcgi.cgi_argument
simple_arg name value creates an unstructured CGI argument called name with contents value.
val mime : ?work_around_backslash_bug:bool ->
?name:string -> Netmime.mime_message -> Netcgi.cgi_argument
mime_arg ?name msg creates a MIME-structured CGI argument called name with contents msg. You can create msg by either Netmime.memory_mime_message or Netmime.file_mime_message.
work_around_backslash_bug : Whether to work around a bug found in almost all browsers regarding the treatment of backslashes. The browsers do not quote backslashes in file names. This breaks RFC standards, however. This argument is true by default.
name : set the name of the argument. If it is not given, the name is extracted from the "Content-Disposition" field of the msg header or it "" if this field is not found.

It is easy to manipulate lists of arguments with the List module. For example, List.filter (fun a -> a#name <> n) args will remove from args all occurrences of the argument with name n. The following functions are helpers for operations specific to arguments.
val clone : ?name:string ->
?value:string ->
?msg:Netmime.mime_message -> Netcgi.cgi_argument -> Netcgi.cgi_argument
val set : Netcgi.cgi_argument list ->
Netcgi.cgi_argument list -> Netcgi.cgi_argument list
set new_args args creates a list of argument from args deleting the arguments whose name appears in new_args and adding the new_args arguments.
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.html0000644000175000017500000015362712731530353020745 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat

Module Uq_engines_compat

module Uq_engines_compat: sig .. end
Compatibility with OCamlnet-3

In Ocamlnet-4 many definitions were moved to separate modules that once used to reside in Uq_engines. In order to ease the transition, this module here provides the old version of Uq_engines.

In order to use it, just put this line at the beginnging of the ml file:

 module Uq_engines = Uq_engines_compat 

Note that this is really meant as a help for getting through transition phases. This module will disappear in future versions of OCamlnet.


exception Closed_channel
exception Broken_communication
exception Watchdog_timeout
exception Timeout
exception Addressing_method_not_supported
exception Cancelled
type 't engine_state = [ `Aborted | `Done of 't | `Error of exn | `Working of int ] 
type 't final_state = [ `Aborted | `Done of 't | `Error of exn ] 
val string_of_state : 'a engine_state -> string
class type ['t] engine = object .. end
class ['t] delegate_engine : 't #engine -> ['t] engine
val when_state : ?is_done:('a -> unit) ->
?is_error:(exn -> unit) ->
?is_aborted:(unit -> unit) ->
?is_progressing:(int -> unit) -> 'a #engine -> unit
class ['a] signal_engine : Unixqueue.event_system -> object .. end
val signal_engine : Unixqueue.event_system ->
'a engine * ('a final_state -> unit)
class [['a, 'b]] map_engine : map_done:('a -> 'b engine_state) -> ?map_error:exn -> 'b engine_state -> ?map_aborted:unit -> 'b engine_state -> ?propagate_working:bool -> 'a #engine -> ['b] engine
val map_engine : map_done:('a -> 'b engine_state) ->
?map_error:(exn -> 'b engine_state) ->
?map_aborted:(unit -> 'b engine_state) ->
?propagate_working:bool ->
'a #engine -> 'b engine
class [['a, 'b]] fmap_engine : 'a #engine -> ('a final_state -> 'b final_state) -> ['b] engine
val fmap_engine : 'a #engine ->
('a final_state -> 'b final_state) ->
'b engine
class ['a] meta_engine : 'a #engine -> ['a final_state] engine
val meta_engine : 'a #engine ->
'a final_state engine
class ['t] epsilon_engine : 't engine_state -> Unixqueue.event_system -> ['t] engine
val epsilon_engine : 't engine_state ->
Unixqueue.event_system -> 't engine
class [['a, 'b]] seq_engine : 'a #engine -> ('a -> 'b #engine) -> ['b] engine
val seq_engine : 'a #engine ->
('a -> 'b #engine) -> 'b engine
class [['a, 'b]] qseq_engine : 'a #engine -> ('a -> 'b #engine) -> ['b] engine
val qseq_engine : 'a #engine ->
('a -> 'b #engine) -> 'b engine
class ['a] stream_seq_engine : 'a -> ('a -> 'a #engine) Stream.t -> Unixqueue.event_system -> ['a] engine
val stream_seq_engine : 'a ->
('a -> 'a #engine) Stream.t ->
Unixqueue.event_system -> 'a engine
class [['a, 'b]] sync_engine : 'a #engine -> 'b #engine -> [('a * 'b)] engine
val sync_engine : 'a #engine ->
'b #engine -> ('a * 'b) engine
class [['a, 'b]] msync_engine : 'a #engine list -> ('a -> 'b -> 'b) -> 'b -> Unixqueue.event_system -> ['b] engine
val msync_engine : 'a #engine list ->
('a -> 'b -> 'b) ->
'b -> Unixqueue.event_system -> 'b engine
class ['a] delay_engine : float -> (unit -> 'a #engine) -> Unixqueue.event_system -> ['a] engine
val delay_engine : float ->
(unit -> 'a #engine) ->
Unixqueue.event_system -> 'a engine
class ['a] timeout_engine : float -> exn -> 'a engine -> ['a] engine
val timeout_engine : float -> exn -> 'a engine -> 'a engine
class watchdog : float -> 'a #engine -> [unit] engine
val watchdog : float -> 'a #engine -> unit engine
class type ['a] serializer_t = object .. end
class ['a] serializer : Unixqueue.event_system -> ['a] serializer_t
val serializer : Unixqueue.event_system -> 'a serializer_t
class type ['a] prioritizer_t = object .. end
class ['a] prioritizer : Unixqueue.event_system -> ['a] prioritizer_t
val prioritizer : Unixqueue.event_system -> 'a prioritizer_t
class type ['a] cache_t = object .. end
class ['a] cache : (Unixqueue.event_system -> 'a engine) -> Unixqueue.event_system -> ['a] cache_t
val cache : (Unixqueue.event_system -> 'a engine) ->
Unixqueue.event_system -> 'a cache_t
class ['t] engine_mixin : 't engine_state -> Unixqueue.event_system -> object .. end
module Operators: sig .. end
class poll_engine : ?extra_match:exn -> bool -> (Unixqueue.operation * float) list -> Unixqueue.event_system -> object .. end
class ['a] input_engine : (Unix.file_descr -> 'a) -> Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
class ['a] output_engine : (Unix.file_descr -> 'a) -> Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
class poll_process_engine : ?period:float -> pid:int -> Unixqueue.event_system -> [Unix.process_status] engine
class type async_out_channel = object .. end
class type async_in_channel = object .. end
class pseudo_async_out_channel : #Netchannels.raw_out_channel -> async_out_channel
class pseudo_async_in_channel : #Netchannels.raw_in_channel -> async_in_channel
class receiver : src:Unix.file_descr -> dst:#async_out_channel -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system -> [unit] engine
class sender : src:#async_in_channel -> dst:Unix.file_descr -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system -> [unit] engine
class type async_out_channel_engine = object .. end
class type async_in_channel_engine = object .. end
class output_async_descr : dst:Unix.file_descr -> ?buffer_size:int -> ?close_dst:bool -> Unixqueue.event_system -> async_out_channel_engine
class input_async_descr : src:Unix.file_descr -> ?buffer_size:int -> ?close_src:bool -> Unixqueue.event_system -> async_in_channel_engine
type copy_task = [ `Bidirectional of Unix.file_descr * Unix.file_descr
| `Tridirectional of Unix.file_descr * Unix.file_descr * Unix.file_descr
| `Uni_socket of Unix.file_descr * Unix.file_descr
| `Unidirectional of Unix.file_descr * Unix.file_descr ]
class copier : copy_task -> Unixqueue.event_system -> [unit] engine
type inetspec = [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
| `Sock_inet_byname of Unix.socket_type * string * int ]
type sockspec = [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
| `Sock_inet_byname of Unix.socket_type * string * int
| `Sock_unix of Unix.socket_type * string ]
val sockspec_of_sockaddr : Unix.socket_type -> Unix.sockaddr -> sockspec
val sockspec_of_socksymbol : Unix.socket_type -> Netsockaddr.socksymbol -> sockspec
type connect_address = [ `Command of string * (int -> Unixqueue.event_system -> unit)
| `Socket of sockspec * connect_options
| `W32_pipe of Netsys_win32.pipe_mode * string ]
type connect_options = Uq_engines.connect_options = {
   conn_bind : sockspec option; (*
Bind the connecting socket to this address (same family as the connected socket required). None: Use an anonymous port.
*)
}
val default_connect_options : connect_options
type connect_status = [ `Command of Unix.file_descr * int
| `Socket of Unix.file_descr * sockspec
| `W32_pipe of Unix.file_descr ]
val client_endpoint : connect_status -> Unix.file_descr
val client_socket : connect_status -> Unix.file_descr
class type client_endpoint_connector = object .. end
class type client_socket_connector = client_endpoint_connector
val connector : ?proxy:#client_socket_connector ->
connect_address ->
Unixqueue.event_system ->
connect_status engine
type listen_options = Uq_engines.listen_options = {
   lstn_backlog : int;
   lstn_reuseaddr : bool;
}
type listen_address = [ `Socket of sockspec * listen_options
| `W32_pipe of
Netsys_win32.pipe_mode * string * listen_options ]
val default_listen_options : listen_options
class type server_endpoint_acceptor = object .. end
class type server_socket_acceptor = server_endpoint_acceptor
class direct_acceptor : ?close_on_shutdown:bool -> ?preclose:unit -> unit -> Unix.file_descr -> Unixqueue.event_system -> server_endpoint_acceptor
class direct_socket_acceptor : Unix.file_descr -> Unixqueue.event_system -> server_endpoint_acceptor
class type server_endpoint_listener = object .. end
class type server_socket_listener = server_endpoint_listener
val listener : ?proxy:#server_socket_listener ->
listen_address ->
Unixqueue.event_system ->
server_socket_acceptor engine
type datagram_type = [ `Inet6_udp | `Inet_udp | `Unix_dgram ] 
class type wrapped_datagram_socket = object .. end
class type datagram_socket_provider = object .. end
val datagram_provider : ?proxy:#datagram_socket_provider ->
datagram_type ->
Unixqueue.event_system ->
wrapped_datagram_socket engine
class type multiplex_controller = object .. end
exception Mem_not_supported
val create_multiplex_controller_for_connected_socket : ?close_inactive_descr:bool ->
?preclose:(unit -> unit) ->
?supports_half_open_connection:bool ->
?timeout:float * exn ->
Unix.file_descr ->
Unixqueue.unix_event_system -> multiplex_controller
class type datagram_multiplex_controller = object .. end
val create_multiplex_controller_for_datagram_socket : ?close_inactive_descr:bool ->
?preclose:(unit -> unit) ->
?timeout:float * exn ->
Unix.file_descr ->
Unixqueue.unix_event_system ->
datagram_multiplex_controller
type onshutdown_out_spec = [ `Action of
async_out_channel_engine ->
multiplex_controller ->
unit engine_state -> unit
| `Ignore
| `Initiate_shutdown ]
type onshutdown_in_spec = [ `Action of
async_in_channel_engine ->
multiplex_controller ->
unit engine_state -> unit
| `Ignore
| `Initiate_shutdown ]
class output_async_mplex : ?onclose:[ `Ignore | `Write_eof ] -> ?onshutdown:onshutdown_out_spec -> ?buffer_size:int -> multiplex_controller -> async_out_channel_engine
class input_async_mplex : ?onshutdown:onshutdown_in_spec -> ?buffer_size:int -> multiplex_controller -> async_in_channel_engine
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netchannels.output_null-c.html0000644000175000017500000004313112731530353022344 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_null

Class Netchannels.output_null

class output_null : ?onclose:unit -> unit -> unit -> out_obj_channel
This output channel discards all written data.

The method pos_out returns the number of discarded bytes.


onclose : this function is called when the close_out method is invoked, just after the underlying descriptor has been closed.

ocamlnet-4.1.2/doc/html-main/type_Netmime_tut.html0000644000175000017500000004061412731530353020627 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime_tut sig  endocamlnet-4.1.2/doc/html-main/type_Netmech_spnego_http.html0000644000175000017500000004373212731530353022336 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_spnego_http sig
  module type PROFILE =
    sig
      val acceptable_transports_http : Nethttp.transport_layer_id list
      val acceptable_transports_https : Nethttp.transport_layer_id list
      val enable_delegation : bool
      val deleg_credential : exn option
    end
  module Default : PROFILE
  module SPNEGO :
    functor (P : PROFILE) (G : Netsys_gssapi.GSSAPI->
      Nethttp.HTTP_CLIENT_MECHANISM
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.cache_t-c.html0000644000175000017500000004621512731530353021201 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.cache_t

Class type Uq_engines.cache_t

class type ['a] cache_t = object .. end
A cache contains a mutable value that is obtained by running an engine.

method get_engine : unit -> 'a engine
Requests the value. If it is not already in the cache, the engine for getting the value is started, and it is waited until the value is available.
method get_opt : unit -> 'a option
Returns the cached value if available
method put : 'a -> unit
Puts a value immediately into the cache. It replaces an existing value. If it is currently tried to obtain a new value by running an engine, this engine is kept running, and get_engine will return its result. Only future calls of get_engine will return the value just put into the cache.
method invalidate : unit -> unit
Invalidates the cache - if a value exists in the cache, it is removed. If in the future the cache value is requested via get_engine the engine will be started anew to get the value.

Note that (as for put) any already running get_engine is not interrupted.

method abort : unit -> unit
Any engine running to get the cache value is aborted, and the contents of the cache are invalidated. Note that also the engines returned by get_engine are aborted.
ocamlnet-4.1.2/doc/html-main/Netcgi_porting.html0000644000175000017500000007327412731530353020257 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_porting

Netcgi_porting


Porting netcgi1 programs to netcgi2

The library netcgi2 is a revised version of the old cgi library which is now also referred to as netcgi1. As any software, netcgi1 aged, and suffered more and more from inadequate interfaces. Because of this it became necessary to improve the interfaces from grounds up. The result is netcgi2, a new major version that tries to continue the good parts of netcgi1 while replacing its problematic edges.

When this text is written, netcgi2 is still being developed, and subject of discussion.

Why porting and when?

It is not possible to use netcgi1 and netcgi2 at the same time in the same application. This means that one cannot gradually upgrade from netcgi1 to netcgi2 by using more and more of the netcgi2 features. Instead of this, it is necessary to switch from netcgi1 to netcgi2 at one point in the lifetime of the web application.

The main benefit is that you have access to the newest netcgi2 features. There are already a number of connectors that are not present in netcgi1 (newer AJP protocol version, SCGI). Furthermore, new features will only be added to netcgi2.

However, if your application is already at or near its end of lifetime, there is no need to port it to netcgi2. The netcgi1 library will remain in Ocamlnet 2, and bugs will be fixed.

Module Organization

The new organization is very simple:

  • Netcgi defines all basic types. Previously, this was done in the two modules Netcgi_env and Netcgi_types
  • For every connector c there is one module Netcgi_c implementing it. Especially the classic CGI connector is now in Netcgi_cgi. Previously, the CGI connector was defined in Netcgi, and there used to be several modules per connector.
  • Netcgi_common defines service functions to define new connectors.
There is also a module Netcgi1_compat trying to ease porting. See below for a discussion.

Interface Changes

Most of the types remain the same, or almost the same. A few changes have been done:

  • Immutability of arguments: A Netcgi.cgi_argument is no longer writable. Furthermore, the list of arguments in a Netcgi.cgi_activation can no longer be modified. There are some new service functions to modify lists of arguments in case one needs such a list.
  • Enhanced cookie API: Cookie formats newer than the old Netscape format are supported. Old and new cookie types can be transformed into each other. See the module Netcgi.Cookie.
  • Exception Handling: The Netcgi_common.HTTP exception can be used to exit from a processor at any time. There is the notion of an exception handler for web-related exceptions.
  • Simplified Environments: The CGI environments Netcgi.cgi_environment have been simplified. It is only distinguished between two states: Output headers have been/ have not been sent. Other processing states are hidden by the implementation.
  • Improved finalization: All CGI arguments are finalized at the end of the request ensuring that temporary files are deleted. It is also possible to register further finalizers using the Netcgi.cgi_activation.at_exit method.
The connectors, however, are now created in very different ways. This is mainly driven by uniformity: There should be a method of creating web connectors that works for every kind of connector. Because of this, the code instantiating connectors in application must always be changed so it matches the new, uniform conventions. Fortunately, this code is usually not very extensive.

Porting strategies

Strategy: Use new API

In the long term this is the best strategy. In principle, one has to distinguish between

  • program parts that access netcgi values, and
  • program parts that connect the netcgi application with the web server.
Porting the first parts is fairly simple, because the types of the netcgi values do not change much. For example, the function web_page for netcgi1

 
(* This is [netcgi1] code! *)
let web_page (cgi : Netcgi_types.cgi_activation) =
  let webarg = cgi # argument_value "webarg" in
  cgi # set_header();
  cgi # output # output_string ("The argument is: " ^ webarg)

would read in the version for netcgi2 as follows:

 
(* This is [netcgi2] code! *)
let web_page (cgi : Netcgi.cgi_activation) =
  let webarg = cgi # argument_value "webarg" in
  cgi # set_header();
  cgi # output # output_string ("The argument is: " ^ webarg)

The only change is that the type cgi_activation is now defined in the module Netcgi and no longer in Netcgi_types. It is expected that this simple way of porting applies to almost all parts of netcgi applications.

By the way, the type cgi_activation can now be abbreviated as cgi, as this is the type name that needs to be written down most frequently.

The new CGI connector

In netcgi1, the CGI connector is selected by instantiating the class Netcgi.std_activation, as in:

(* This is [netcgi1] code! *)
let cgi = new Netcgi.std_activation() in 
process cgi

It is assumed that process is a function taking a cgi_activation as argument, and processing the request.

The corresponding netcgi2 call is:

(* This is [netcgi2] code! *)
Netcgi_cgi.run process

As you see, Netcgi_cgi.run is now responsible for calling process.

The new FastCGI connector

In netcgi1 there are several ways of using FastCGI. The most common is to call Netcgi_fcgi.serv as in:

(* This is [netcgi1] code! *)
Netcgi_fcgi.serv process optype

It is assumed that process is a function taking a cgi_activation as argument, and processing the request. optype is a valid operating type.

The corresponding netcgi2 call is:

(* This is [netcgi2] code! *)
let process' cgi = process (cgi :> Netcgi.cgi_activation) in
Netcgi_fcgi.run ~output_type:optype process'

Note that the argument of process' is a slightly extended version of cgi_activation, so you usually need the coercion to cut off the additional part of the object interface.

The new AJP connector

The new connector supports now the AJP version 1.3 - this is the default version used by Jakarta and mod_jk. In netcgi1, only version 1.2 of the AJP protocol was supported. The new protocol version is no big improvement, however. It uses a slightly more compact representation of the data. The biggest plus is better support of SSL.

In netcgi1 there was some special machinery around the AJP connector to create worker processes. This code has been completely removed in favor of netplex, the new general-purpose server framework. Because of that, porting AJP applications is probably a bit of work, and we cannot give a receipt here how to do that.

Strategy: Use Netcgi1_compat

If you want to use the new connectors but currently do not have time to check all your code for changes, there is a special helper module called Netcgi1_compat that provides a netcgi1-compatible API on top of either netcgi1 or netcgi2.

Because Netcgi1_compat is available in both netcgi1 and netcgi2 you can write code that can be compiled for both versions without needing to change anything. Note, however, that this module is not 100% identical in both versions - the netcgi2 version includes some additional functions that converts values from their netcgi1 representation to their netcgi2 representation and vice versa. Unfortunately, this makes the two versions of this module binary-incompatible, so you have to recompile your code for either netcgi1 or netcgi2.

The Netcgi1_compat module simply contains the relevant parts of the netcgi1 API as submodules. That means you can access

  • the netcgi1 version of the module Netcgi_types as Netcgi1_compat.Netcgi_types
  • the netcgi1 version of the module Netcgi_env as Netcgi1_compat.Netcgi_env
  • the netcgi1 version of the module Netcgi as Netcgi1_compat.Netcgi
Other modules of netcgi1 are not covered by the compatibility API. In Netcgi, the custom_activation class has been left out.

You can usually port code to using this API by either

  • prefixing these module names in source code with Netcgi1., e.g. new Netcgi.std_activation() would be turned into new Netcgi1_compat.Netcgi.std_activation()
  • opening the module Netcgi1 at the beginning of each .ml and .mli file by an open Netcgi1_compat.
Except Netcgi.std_activation, the netcgi1 way of creating a connector for classic CGI, there are no connectors in the compatibility API. If you need one, you must take it directly from either netcgi1 or netcgi2. For example, to connect using FastCGI:

(* This is code for both [netcgi1] and [netcgi2]! *)
let process (cgi : Netcgi1_compat.Netcgi.cgi_activation) =
  ...

(* This is [netcgi2] code! *)
let process_netcgi2 cgi2 =
  let cgi1 = Netcgi1_compat.Netcgi_types.to_compat_activation cgi2 in
  process cgi1
Netcgi_fcgi.run ~output_type process'

ocamlnet-4.1.2/doc/html-main/type_Uq_engines.server_endpoint_acceptor.html0000644000175000017500000004215212731530353025516 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.server_endpoint_acceptor object
  method accept :
    unit -> (Unix.file_descr * Uq_engines.inetspec option) Uq_engines.engine
  method multiple_connections : bool
  method server_address : Uq_engines.connect_address
  method shut_down : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/Intro.html0000644000175000017500000017462512731530353016401 0ustar gerdgerd Ocamlnet 4 Reference Manual

Ocamlnet 4 Reference Manual

OCamlnet is an enhanced system platform library for Ocaml. As the name suggests, large parts of it have to do with network programming, but it is actually not restricted to this. Other parts deal with the management of multiple worker processes, and the interaction with other programs running on the same machine. You can also view Ocamlnet as an extension of the system interface as provided by the Unix module of the standard library.

Overview: What you can do with OCamlnet:

Domain Task Protocol/mechanism Frameworks
Web applications Dynamic web content,
Connect with web server,
Standalone web servers
Web server connectors: CGI, FastCGI, SCGI, AJP.
HTTP server
Netcgi (connector framework)
Network applications
(classic client/server)
SunRPC clients,
SunRPC servers
SunRPC binary protocol,
SunRPC stub generator,
Portmapper/RPCBIND,
RPCSEC_GSS
Network applications
(modern client/server)
Call HTTP interfaces,
Provide HTTP interfaces
HTTP client,
HTTP server,
HTTP authentication
Email applications Create emails with attachments,
Send emails,
Parse emails,
Interact with email server
SMTP client,
POP client,
SASL authentication
Network utilities Data download and upload,
Encode and decode,
Character sets,
Structured formats,
URLs,
IPv6
HTTP client,
FTP client
Netfs (filesystem framework)
System utiltities Invoke commands,
Daemonize,
Shared memory,
Logging,
Locales,
Timers
Netplex (multi-process daemons)
Authentication and security Network authentication,
Integrity protection,
Privacy
TLS (via GnuTLS),
SASL,
GSSAPI (Kerberos),
LDAP client
Pluggable security providers
for TLS, SASL, GSSAPI,
Digests,
Symmetric ciphers

Introductory chapters

Guides

  • Ocamlnet4: Changes in OCamlnet-4
  • Foreword: How Ocamlnet is organized
  • Get: How to get OCamlnet
  • Platform: Which functions are available on which platform (POSIX/Win32). Also hints for portable programming.
  • Ipv6: The state of IPv6 support
  • Tls: TLS support
  • Crypto: Cryptography
  • Authentication: Authentication frameworks
  • Credentials: How to express and store credentials
  • Gssapi: The GSSAPI security layer
  • Regexp: Regular expression backends

Contents by library

Base Libraries

Guides

External articles

The netstring library: string processing functions

netstring focuses on string processing functions, and base definitions for other libraries.


Netaccel
Accelerators for bytecode
Netaccel_link
Enables accelerator module Netaccel
Netaddress
Parsing of mail addresses
Netasn1
ASN.1 support functions
Netasn1_encode
ASN.1 encoder
Netauth
Some primitives for authentication
Netaux
Internal auxiliary functions
Netbuffer
A Netbuffer.t is a buffer that can grow and shrink dynamically.
Netchannels
Object-oriented I/O: Basic types and classes
Netchannels_crypto
Crypto extensions for Netchannels
Netcompression
Registry for compression algorithms
Netconversion
Conversion between character encodings
Netdate
Support for common date/time parsing and formatting.
Netdn
X.500 distinguished names
Netencoding
Base64, Quoted Printable, URL encoding, HTML escaping
Netfs
Class type stream_fs for filesystems with stream access to files
Netglob
Globbing
Netgssapi_auth
Authentication helpers for GSSAPI
Netgssapi_support
Support functions for GSS-API
Nethtml
Parsing of HTML
Nethttp
Basic definitions for the HTTP protocol
Netmappings
Internal access to the character conversion database
Netmech_crammd5_sasl
The CRAM-MD5 SASL mechanism (RFC 2195), which is obsolete and only provided for completeness.
Netmech_digest_http
Digest authentication for HTTP
Netmech_digest_sasl
The DIGEST-MD5 SASL mechanism (RFC 2831).
Netmech_gs2_sasl
The GS2 bridge for using GSSAPI mechanisms as SASL mechanisms
Netmech_krb5_sasl
Kerberos 5 as SASL mechanism
Netmech_plain_sasl
The PLAIN SASL mechanism (RFC 4616).
Netmech_scram
SCRAM mechanism for authentication (RFC 5802)
Netmech_scram_gssapi
The SCRAM security mechanism for GSS-API
Netmech_scram_sasl
SCRAM as SASL mechanism
Netmech_scram_http
SCRAM for HTTP (prerelease)
Netmech_spnego_http
SPNEGO (GSSAPI) authentication for HTTP
Netmime
Netmime contains high-level classes and functions to process mail and MIME messages.
Netmime_channels
MIME: parsing and printing for channels
Netmime_header
MIME: Access methods for frequent standard fields.
Netmime_string
Low-level functions to parse and print mail and MIME messages
Netnumber
Binary encodings of numbers
Netoid
X.500 Object Identifiers
Netpagebuffer
Buffer for page-aligned I/O
Netsaslprep
The SASLprep algorithm (RFC 4013)
Netsendmail
Functions to compose and send electronic mails
Netsockaddr
Parsing of socket addresses
Netstream
A netstream is an input channel that is read block by block.
Netstring_str
Wrapper for regexps with Str syntax
Netstring_tstring
Support module for tagged strings
Nettls_support
Support types and functions for TLS
Netulex
Support module for Alain Frisch's ulex lexer generator
Netunichar
Unicode character information
Neturl
Uniform Resource Locators (URLs)
Neturl_ldap
LDAP-specific URLs
Netx509
X.509 certificates
Netx509_pubkey
X.509 public key cryptography - keys and naming
Netx509_pubkey_crypto
X.509 public key cryptography - wrappers
Netxdr
External Data Representation
Netxdr_mstring
Managed Strings

The netstring-pcre library: additions for PCRE


Netstring_pcre
Wrapper for regexps with PCRE syntax

The netunidata library: Unicode tables


Netunidata
Configure how to load Unicode tables

The netzip library: compression for object channels

Support for (un)compressing data on the fly with object channels. Requires ocamlzip.


Netgzip
Gzip object channels

The equeue library: concurrent execution flows via event queues

equeue is a fundamental library for event queues. It is mainly used by a number of other libraries of Ocamlnet to parallelize network code (so-called multiplexing).


Equeue
Equeue implements generic event queues.
Unixqueue
Unixqueues are one of the two forms of system event loops provided by Ocamlnet.
Unixqueue_pollset
Unixqueue implementation on top of Netsys_pollset
Unixqueue_select
This the old Unix.select-based imeplementation of event systems which was the default one until Ocamlnet-2.2.
Uq_engines
An engine performs a certain task in an autonomous way.
Uq_socks5
This module implements a SOCKS version 5 client (see RFC 1928) for use with the Uq_engines.connector, Uq_engines.listener, and Uq_engines.datagram_provider engine factories.
Uq_resolver
Support for pluggable resolvers
Uq_io
Unified engines for stream I/O
Uq_client
Support for socket clients
Uq_server
Server sockets
Uq_multiplex
Multiplex Controllers
Uq_transfer
Transfer engines
Uq_lwt
Compatibility with Lwt
Uq_libevent
Use Libevent as event loop
Uq_mt
Using engines in multi-threaded programs

The equeue-gtk1 and equeue-gtk2 extensions

Extensions for equeue to integrate the event queue into user interfaces made with lablgtk and lablgtk2


Uq_gtk
Integration with lablgtk/lablgtk2 event systems

The equeue-tcl extension

Extension for equeue to integrate the event queue into user interfaces made with labltk


Uq_tcl
Integration with the labltk event system

The netplex library: generic server framework

The netplex library is a protocol-independent server framework. Especially, it can be used in conjunction with nethttpd to build web servers, and with rpc to build RPC servers.


Netplex_types
Types for Netplex
Netplex_config
Read the configuration file
Netplex_controller
Controller
Netplex_container
Containers
Netplex_sockserv
Socket service creation
Netplex_workload
Workload management
Netplex_kit
Netplex toolkit
Netplex_cenv
Container environment
Netplex_log
Loggers
Netplex_main
Main program for Netplex servers
Netplex_mp
Multi-processing provider
Netplex_mt
Multi-threading provider
Netplex_mutex
Netplex-wide mutexes
Netplex_semaphore
Netplex-wide semaphores
Netplex_sharedvar
Netplex-wide variables
Netplex_mbox
Netplex message boxes
Netplex_encap
Type-safe marshalling between processes of the same executable
Netplex_internal
Internal services
Rpc_netplex
Netplex support for RPC servers (TCP only)

The shell library: start external commands

The shell library allows you to start external commands. It is integrated into equeue.


Shell
Calls external programs, creates pipelines, etc.
Shell_sys
Calls external programs, creates pipelines, etc.
Shell_uq
Run shell commands within Unixqueues
Shell_fs
Shell filesystem

The netshm library: manage shared memory

The netshm library manages a shared memory object either as hash table or array. It is designed to be used in multi-processing program architectures. Note that there is now also the much better The netmulticore library: compute jobs library.


Netshm
Shared memory for O'Caml programs using multi-processing
Netshm_data
Data representation for shared memory
Netshm_hashtbl
Hash tables in shared memory
Netshm_array
Arrays in shared memory

The netsys library: system interfaces

The netsys library contains a number of low-level functions used by other Ocamlnet libraries.


Platform
Netexn
Exception registry
Netlog
Basic logging facility
Netsys
System calls missing in the Unix module
Netsys_posix
POSIX-specific system calls missing in the Unix module, and further API's from POSIX-style operating systems.
Netsys_oothr
Object-oriented thread API
Netsys_signal
Signal handler framework
Netsys_tmp
Temporary files
Netsys_mem
Bigarrays as memory buffers
Netsys_sem
Generic anonymous semaphores
Netsys_global
Global variables
Netsys_pollset
Sets of file descriptors for polling
Netsys_pollset_generic
Returns a good standard implementation of pollset for this platform.
Netsys_pollset_posix
Pollsets for POSIX operating systems
Netsys_pollset_win32
Pollsets for Win32
Netsys_win32
Primitives for Win32
Netsys_polypipe
Polymorphic message pipes
Netsys_polysocket
Polymorphic message sockets
Netsys_rng
Random-number generator
Netsys_crypto_types
Types for crypto providers
Netsys_crypto
Cryptographic providers
Netsys_crypto_modes
Helpers for crypto modes
Netsys_tls
User-level TLS API
Netsys_ciphers
Symmetric cryptographic ciphers
Netsys_digests
Cryptographic digests (hashes)
Netsys_gssapi
GSS-API Definition

The nettls-gnutls library: GnuTLS bindings


Nettls_gnutls
GnuTLS
Nettls_gnutls_bindings
Bindings of a C library
Nettls_nettle_bindings
Bindings of a C library

The netgss library: GSSAPI bindings


Netgss
This is the system-wide version of GSSAPI
Netgss_bindings
Bindings of a C library

Web Programming

Guides

The netcgi1 library

The netcgi1 library is no longer supported in Ocamlnet 3. Please switch to netcgi2.

The netcgi2 library: web application framework

This is the revised library for Web applications, now called netcgi2.


Netcgi
Common data-structures for CGI-like connectors.
Netcgi_common
Functions to develop new connectors.
Netcgi_cgi
Classical CGI connector.
Netcgi_fcgi
FastCGI connector.
Netcgi_ajp
Apache JServ Protocol (AJP) 1.3 connector.
Netcgi_scgi
SCGI connector.
Netcgi_test
Connector for testing your code.
Netcgi_dbi
Pools of connections for the ocamldbi generic database interface.
Netcgi1_compat
Compatibility module with the previous version of Netcgi.

The netcgi2-apache library: run web apps inside Apache

This is an Apache connector for the netcgi2 library.


Netcgi_apache
Netcgi Apache "mod" connector.
Netcgi_modtpl

The netcgi2-plex library: run web apps with Netplex

Netplex support for running Netcgi2 connectors:


Netcgi_plex
Netplex support for FastCGI, SCGI and AJP connectors

The nethttpd library: standalone web apps

The nethttpd library is a Web server component written in O'Caml. For a full web server, you'll also need netplex.


Nethttpd_types
Type definitions for the HTTP daemon
Nethttpd_kernel
The protocol kernel of the HTTP daemon
Nethttpd_reactor
The reactive encapsulation of the HTTP daemon
Nethttpd_engine
The event-based encapsulation of the HTTP daemon
Nethttpd_services
Service Providers for HTTP daemon
Nethttpd_plex
Netplex support
Nethttpd_util
Utility functions

Client/Server Programming

Guides

External articles

The rpc library: SunRPC

This library implements OncRPC (alias SunRPC).


Rpc
Common types and exceptions
Rpc_program
RPC programs
Rpc_client
RPC clients
Rpc_simple_client
Synchronous API for RPC clients
Rpc_proxy
RPC proxies
Rpc_server
RPC servers
Rpc_auth_sys
Authentication module AUTH_SYS
Rpc_portmapper
Portmapper/RPCBIND interface
Rpc_portmapper_aux
Rpc_portmapper_clnt
Rpc_transport
Low-level RPC transporters
Rpc_packer
Packing and Unpacking of messages; can be used by both client and server programs.
Rpc_auth_gssapi
GSS-API for RPC authentication

The rpc-auth-local extension: authentication for local sockets

Authentication for local socket connections.


Rpc_auth_local
Return the authentication method AUTH_LOCAL.

The rpc-xti extension: System V helpers

System V provides a network API called XTI in addition to the socket API. This library allows it to connect to RPC services that can only be reached over a local XTI connection ("cots" connection).


Rpc_xti_client
Minimal support for TI-RPC over the XTI API

Parallel Computing

Guides

Important change since OCaml-4.01: This OCaml version changed the semantics of the built-in primitives caml_modify and caml_initialize. Essentially, it is no longer possible to modify OCaml values residing outside the regular OCaml heap. As we do this inside Netcamlbox and Netmulticore, this change affects these libraries. Fortunately, there is a workaround on systems supporting weak symbols (all ELF systems and OS X): Here, caml_modify and caml_initialize are overridden by Ocamlnet so that they are again compatible. Note that this is a global modification of the runtime system!

The netcamlbox library: message passing

Camlbox is a fast message-passing system between processes running on the same machine. It uses shared memory for communication. A message sent to a Camlbox is only copied once, not twice.


Netcamlbox
Camlboxes are a fast IPC mechanism to send Ocaml values from one process to another.

The netmulticore library: compute jobs

Netmulticore is an experimental framework for managing multiple processes, and sending messages between them.


Netmcore
Multi-processing for compute jobs
Netmcore_process
Statically typed processes
Netmcore_mempool
Memory pools
Netmcore_heap
Shared heaps of structured values
Netmcore_array
Shared arrays
Netmcore_buffer
Shared buffer
Netmcore_hashtbl
Shared hashtables
Netmcore_matrix
Shared 2-dimensional arrays (matrices)
Netmcore_queue
Shared queues
Netmcore_ref
Shared mutable variables
Netmcore_mutex
Mutexes
Netmcore_sem
Semaphores
Netmcore_condition
Condition variables
Netmcore_camlbox
Camlboxes for use in netmulticore programs

Network Protocol Libraries

Guides

The netclient library: HTTP, FTP, Telnet, POP, SMTP, LDAP

This library includes clients for HTTP, Telnet, FTP, SMTP, POP, and LDAP.


Nethttp_client
HTTP 1.1 client
Nethttp_client_conncache
Connection cache
Nethttp_fs
HTTP filesystem
Netftp_client
FTP client
Netftp_data_endpoint
Senders and receivers for the FTP data connection
Netftp_fs
FTP filesystem
Netldap
LDAP client
Nettelnet_client
Telnet client
Netpop
This is an interface for the Post Office Protocol - Version 3 (POP3) as specifed by RFC 1939.
Netsmtp
This is an interface for the Simple Mail Tranfer Protocol (SMTP) as specified by RFC 2821.

Trailer

Index

Authors

The Ocamlnet libraries have been initially written by Gerd Stolpmann and Patrick Doane.

Contributions by

  • Nicolas George: Netdate
  • Eric Stokes: FastCGI support
  • Pierre Habouzit: SMTP client
  • Christophe Troestler: Revised version of netcgi
  • Deokhwan Kim: Support for EUC-KR
Sponsorships by

  • Baretta s.r.l: Nethttpd
  • California State University: SSL support for RPC, Netplex

ocamlnet-4.1.2/doc/html-main/Rpc_portmapper_clnt.Make'PMAP.V3.html0000644000175000017500000006165112731530353023205 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt.Make'PMAP.V3

Module Rpc_portmapper_clnt.Make'PMAP.V3

module V3: sig .. end

type t = U'C.t 
val _program : Rpc_program.t
val rpcbproc_null : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res
val rpcbproc_null'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res) -> unit) -> unit
val rpcbproc_set : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res
val rpcbproc_set'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res) -> unit) -> unit
val rpcbproc_unset : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res
val rpcbproc_unset'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res) -> unit) -> unit
val rpcbproc_getaddr : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res
val rpcbproc_getaddr'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res) -> unit) -> unit
val rpcbproc_dump : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res
val rpcbproc_dump'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res) -> unit) -> unit
val rpcbproc_callit : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res
val rpcbproc_callit'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res) -> unit) -> unit
val rpcbproc_gettime : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res
val rpcbproc_gettime'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res) -> unit) -> unit
val rpcbproc_uaddr2taddr : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res
val rpcbproc_uaddr2taddr'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res) -> unit) ->
unit
val rpcbproc_taddr2uaddr : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res
val rpcbproc_taddr2uaddr'async : U'C.t ->
Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg ->
((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res) -> unit) ->
unit
ocamlnet-4.1.2/doc/html-main/Netcgi_ajp.html0000644000175000017500000006347712731530353017353 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_ajp

Module Netcgi_ajp

module Netcgi_ajp: sig .. end
Apache JServ Protocol (AJP) 1.3 connector.

See the Setup section at the end of this file to know how to configure your web server.


val arg_parse : (Arg.key * Arg.spec * Arg.doc) list ->
Arg.anon_fun -> Arg.usage_msg -> (string * string) list
arg_parse speclist anon_fun usage_msg parses the command line and return an associative list describing the content of the property file (see Netcgi_ajp.props_of_file). This function allows to fakes the "java" command (JVM startup):

  • the option -classpath <path> is ignored;
  • the first anonymous argument (Java class name) is ignored;
  • the second anonymous argument is the name of the property file;
  • other options are interpreted according to the speclist.

Raises Failure and prints a usage message if the property file cannot be read.
val props_of_file : string -> (string * string) list
props_of_file fname parses the property file fname and returns it as an associative list. The following properties are used:

  • "bindaddress": The address the server socket is bound to. Can be specified as IP address or hostname or "*" (default: "localhost").
  • "port": The port number the server socket is bound to. Defaults to 8007.
  • "security.authentication": If "true", the server expects that the web server authenticates itself. Defaults to "true".
  • "security.challengeSize": The length of the challenge string. Defaults to 5.
  • "security.secretKey": The file containing the secret key used for authentication.
  • "security.allowHost": Only the web server with this IP address is allowed to connect (this option can occur several times). DNS names are resolved at startup time.
  • "jakarta.servletSubString": The substring that is used as indicator for the servlet name (for mod_jk only). Defaults to "/servlets/".
  • "ocamlnet.https": Whether HTTPS is assumed as basic protocol or not. Defaults to "false".
Other properties are ignored.
Raises Invalid_argument if the file does not exist or is not readable.
val run : ?props:(string * string) list ->
?config:Netcgi.config ->
?script_name:string ->
?allow:(Unix.sockaddr -> bool) ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?exn_handler:Netcgi.exn_handler ->
?socket:Unix.file_descr ->
?sockaddr:Unix.sockaddr -> ?port:int -> (Netcgi.cgi -> unit) -> unit
run f executes f cgi for each AJP request.
config : Default: Netcgi.default_config
allow : Tells whether a connection from the socket is allowed. Default: allow from all.
output_type : Default: `Direct ""
arg_store : Default: `Automatic for all arguments.
exn_handler : See Netcgi.exn_handler. Default: delegate all exceptions to the default handler.
socket : is a listening socket to use. Overrides sockaddr and port
sockaddr : The sockaddress (overrides port)
port : The port used by the web server to send the requests (Default: 8009).
val handle_request : ?script_name:string ->
Netcgi.config ->
Netcgi.output_type ->
Netcgi.arg_store ->
Netcgi.exn_handler ->
(Netcgi.cgi -> unit) ->
log:(string -> unit) option -> Unix.file_descr -> Netcgi.connection_directive
handle_request config output_type arg_store eh f ~log fd: This is a lower-level interface that processes exactly one request arriving on the existing connection fd.

log is the error logger function or None, in which case errors are passed through to the FCGI client.

The other arguments are just like for run.

The return value indicates whether the connection can be kept open or must be closed.

val handle_connection : Netcgi.config ->
Netcgi.output_type ->
Netcgi.arg_store ->
Netcgi.exn_handler ->
(Netcgi.cgi -> unit) -> ?script_name:string -> Unix.file_descr -> unit
handle_connection config output_type arg_store eh f ?script_name fd: This is a lower-level interface that processes exactly one connection fd. The descriptor is closed (even on error).

The other arguments are just like for run.


Setup

Apache

You need to use mod_jk to have support for AJP/1.3. To install it, please see Working with mod_jk.

In httpd.conf or in a file, say mod_jk.conf, in /etc/apache2/conf.d/ (or /etc/apache2/conf.d/ for Apache 1.x), add the following:

    # Shared memory file name (Unix only).  The parent dir must exist.
    JkShmFile  /var/tmp/jk-runtime-status
    LoadModule jk_module mod_jk.so
    # Declare the module for <IfModule> (remove this line on Apache 2.x)
    AddModule  mod_jk.c

    <IfModule mod_jk.c>
      # Configure mod_jk
      # Apache 1.x
      #JkWorkersFile /etc/libapache-mod-jk/workers.properties
      #JkLogFile     /var/log/apache/mod_jk.log
      # Apache 2.x
      JkWorkersFile /etc/libapache2-mod-jk/workers.properties
      JkLogFile     /var/log/apache2/mod_jk.log
      JkLogLevel    info

      # JkMount [URL prefix] [Worker name]
      JkMount /*.jsp ajp13_worker
      JkMount /servlet/* ajp13_worker
    </IfModule>
   

Other web severs

Please go to this configuration page. Mail us specific instructions or tips for other web servers so we can include them here.

Workers.properties

Here is an example of workers.properties:

    # Comma separated list of worker names:
    worker.list=ajp13_worker
    # Set properties for ajp13_worker
    worker.ajp13_worker.type=ajp13
    worker.ajp13_worker.host=localhost
    worker.ajp13_worker.port=8009
    worker.ajp13_worker.cachesize=1
   

ocamlnet-4.1.2/doc/html-main/Nethttp.http_header-c.html0000644000175000017500000004164712731530353021437 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.http_header

Class type Nethttp.http_header

class type http_header = Netmime.mime_header

ocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi_env.html0000644000175000017500000007315412731530353023257 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_env sig
  type input_mode = [ `Standard ]
  type input_state =
      [ `Received_body
      | `Received_header
      | `Receiving_body
      | `Receiving_header
      | `Start ]
  type output_mode = [ `Standard ]
  type output_state =
      [ `End
      | `Sending_body
      | `Sending_header
      | `Sending_part_body
      | `Sending_part_header
      | `Sent_body
      | `Sent_header
      | `Sent_part_body
      | `Sent_part_header
      | `Start ]
  type protocol_version = Nethttp.protocol_version
  type protocol_attribute = Nethttp.protocol_attribute
  type protocol = Nethttp.protocol
  type workaround =
      [ `Work_around_MSIE_Content_type_bug | `Work_around_backslash_bug ]
  type cgi_config = {
    tmp_directory : string;
    tmp_prefix : string;
    permitted_http_methods : string list;
    permitted_input_content_types : string list;
    input_content_length_limit : int;
    workarounds : Netcgi1_compat.Netcgi_env.workaround list;
  }
  val default_config : Netcgi1_compat.Netcgi_env.cgi_config
  val of_compat_config :
    Netcgi1_compat.Netcgi_env.cgi_config -> Netcgi.config
  val to_compat_config :
    Netcgi.config -> Netcgi1_compat.Netcgi_env.cgi_config
  class type cgi_environment =
    object
      method cgi_auth_type : string
      method cgi_gateway_interface : string
      method cgi_https : bool
      method cgi_path_info : string
      method cgi_path_translated : string
      method cgi_properties : (string * string) list
      method cgi_property : ?default:string -> string -> string
      method cgi_query_string : string
      method cgi_remote_addr : string
      method cgi_remote_host : string
      method cgi_remote_ident : string
      method cgi_remote_user : string
      method cgi_request_method : string
      method cgi_request_uri : string
      method cgi_script_name : string
      method cgi_server_name : string
      method cgi_server_port : int option
      method cgi_server_protocol : string
      method cgi_server_software : string
      method config : Netcgi1_compat.Netcgi_env.cgi_config
      method cookies : (string * string) list
      method input_ch : Netchannels.in_obj_channel
      method input_content_length : int
      method input_content_type :
        string * (string * Netmime_string.s_param) list
      method input_content_type_string : string
      method input_header : Netmime.mime_header
      method input_header_field : ?default:string -> string -> string
      method input_header_fields : (string * string) list
      method input_state : Netcgi1_compat.Netcgi_env.input_state
      method log_error : string -> unit
      method multiple_input_header_field : string -> string list
      method multiple_output_header_field : string -> string list
      method output_ch : Netchannels.out_obj_channel
      method output_header : Netmime.mime_header
      method output_header_field : ?default:string -> string -> string
      method output_header_fields : (string * string) list
      method output_state : Netcgi1_compat.Netcgi_env.output_state
      method protocol : Netcgi1_compat.Netcgi_env.protocol
      method send_output_header : unit -> unit
      method set_input_state : Netcgi1_compat.Netcgi_env.input_state -> unit
      method set_multiple_output_header_field : string -> string list -> unit
      method set_output_header_field : string -> string -> unit
      method set_output_header_fields : (string * string) list -> unit
      method set_output_state :
        Netcgi1_compat.Netcgi_env.output_state -> unit
      method set_status : Nethttp.http_status -> unit
      method user_agent : string
    end
  val to_compat_environment :
    Netcgi.cgi_environment -> Netcgi1_compat.Netcgi_env.cgi_environment
  val of_compat_environment :
    Netcgi1_compat.Netcgi_env.cgi_environment -> Netcgi.cgi_environment
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_digests.html0000644000175000017500000005723312731530353021351 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_digests sig
  type iana_hash_fn =
      [ `MD2 | `MD5 | `SHA_1 | `SHA_224 | `SHA_256 | `SHA_384 | `SHA_512 ]
  class type digest_ctx =
    object
      method add_memory : Netsys_types.memory -> unit
      method add_subbytes : Bytes.t -> int -> int -> unit
      method add_substring : string -> int -> int -> unit
      method add_tstring : Netsys_types.tstring -> int -> int -> unit
      method finish : unit -> string
    end
  class type digest =
    object
      method block_length : int
      method create : unit -> Netsys_digests.digest_ctx
      method iana_hash_fn : Netsys_digests.iana_hash_fn option
      method iana_name : string option
      method name : string
      method oid : int array option
      method size : int
    end
  val digests :
    ?impl:(module Netsys_crypto_types.DIGESTS->
    unit -> Netsys_digests.digest list
  val find :
    ?impl:(module Netsys_crypto_types.DIGESTS->
    string -> Netsys_digests.digest
  val digest_tstring :
    Netsys_digests.digest -> Netsys_types.tstring -> string
  val digest_bytes : Netsys_digests.digest -> Bytes.t -> string
  val digest_string : Netsys_digests.digest -> string -> string
  val digest_mstrings :
    Netsys_digests.digest -> Netsys_types.mstring list -> string
  val hmac : Netsys_digests.digest -> string -> Netsys_digests.digest
  val iana_find :
    ?impl:(module Netsys_crypto_types.DIGESTS->
    Netsys_digests.iana_hash_fn -> Netsys_digests.digest
  val iana_alist : (string * Netsys_digests.iana_hash_fn) list
  val iana_rev_alist : (Netsys_digests.iana_hash_fn * string) list
  val oid_alist : (int array * Netsys_digests.iana_hash_fn) list
  val oid_rev_alist : (Netsys_digests.iana_hash_fn * int array) list
  val name_alist : (string * Netsys_digests.iana_hash_fn) list
  val name_rev_alist : (Netsys_digests.iana_hash_fn * string) list
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.engine.html0000644000175000017500000004255612731530353023250 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.engine object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification :
    ('Uq_engines_compat.engine -> bool) -> unit
  method state : 'Uq_engines_compat.engine_state
end
ocamlnet-4.1.2/doc/html-main/Netmcore_queue.html0000644000175000017500000005743212731530353020262 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_queue

Module Netmcore_queue

module Netmcore_queue: sig .. end
Shared queues

type ('e, 'h) squeue 
Queues where the elements have type 'e and the header has type 'h
type ('e, 'h) squeue_descr 
The marshallble descriptor of queues
exception Empty
Raised when the queue is empty and the operation cannot be done
val create : Netmcore.res_id -> 'h -> ('e, 'h) squeue
create pool h: Creates an empty queue in the pool, with header h
val push : 'e -> ('e, 'h) squeue -> unit
push x q: Pushes a copy of x to the end of the queue q
val pop_p : ('e, 'h) squeue -> ('e -> 'a) -> 'a
pop_p q f: Takes the first element x from the queue, removes it there, and calls f x. During the execution of f the value x is pinned and cannot be garbage-collected.

Raises Empty if the queue is empty.

val pop_c : ('e, 'h) squeue -> 'e
pop_c q: Takes the first element x from the queue, removes it there, and returns a copy of x in normal memory.

Raises Empty if the queue is empty.

val top_p : ('e, 'h) squeue -> ('e -> 'a) -> 'a
pop_p q f: Takes the first element x of the queue, and calls f x, without removing x from the queue. During the execution of f the value x is pinned and cannot be garbage-collected.

Raises Empty if the queue is empty.

val top_c : ('e, 'h) squeue -> 'e
pop_p q f: Takes the first element x of the queue, and calls f x, without removing x from the queue. Returns a copy of x in normal memory.

Raises Empty if the queue is empty.

val clear : ('e, 'h) squeue -> unit
Removes all elements from the queue
val is_empty : ('e, 'h) squeue -> bool
Tests whether the queue is empty
val length : ('e, 'h) squeue -> int
Returns the number of elements in the queue (O(1))
val iter : ('e -> unit) -> ('e, 'h) squeue -> unit
iter f q: Iterates over the elements of the queue and calls f x for each element x. The function considers the list of elements at the time of calling iter as the list to iterate over. The queue is not locked during the iteration, and hence elements can be popped from the queue and pushed to the queue in parallel. The iteration does not take these modifications into account, though.

The elements x are pinned during the execution of f and will not be garbage-collected, even if a parallel pop removes them from the queue.

val fold : ('a -> 'e -> 'a) -> 'a -> ('e, 'h) squeue -> 'a
fold f accu q
val header : ('e, 'h) squeue -> 'h
Returns the header
val heap : ('a, 'b) squeue -> Obj.t Netmcore_heap.heap
Returns the underlying heap
val descr_of_squeue : ('e, 'h) squeue -> ('e, 'h) squeue_descr
Returns the descriptor
val squeue_of_descr : Netmcore.res_id ->
('e, 'h) squeue_descr -> ('e, 'h) squeue
Look up the queue for this descriptor
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.html0000644000175000017500000023565212731530353021331 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client sig
  exception Bad_message of string
  exception No_reply
  exception Too_many_redirections
  exception Name_resolution_error of string
  exception URL_syntax_error of string
  exception Timeout of string
  exception Proxy_error of int
  exception Response_too_large
  exception Http_protocol of exn
  exception Http_error of (int * string)
  type status =
      [ `Client_error
      | `Http_protocol_error of exn
      | `Redirection
      | `Server_error
      | `Successful
      | `Unserved ]
  type 'a auth_status =
      [ `Auth_error
      | `Continue of 'a
      | `Continue_reroute of 'a * int
      | `None
      | `OK
      | `Reroute of int ]
  type 'message_class how_to_reconnect =
      Send_again
    | Request_fails
    | Inquire of ('message_class -> bool)
    | Send_again_if_idem
  type 'message_class how_to_redirect =
      Redirect
    | Do_not_redirect
    | Redirect_inquire of ('message_class -> bool)
    | Redirect_if_idem
  type private_api
  type response_body_storage =
      [ `Body of unit -> Netmime.mime_body
      | `Device of unit -> Uq_io.out_device
      | `File of unit -> string
      | `Memory ]
  type synchronization = Sync | Pipeline of int
  type resolver =
      Unixqueue.unix_event_system ->
      string -> (Unix.inet_addr option -> unit) -> unit
  type transport_layer_id = int
  type http_options = {
    synchronization : Nethttp_client.synchronization;
    maximum_connection_failures : int;
    maximum_message_errors : int;
    inhibit_persistency : bool;
    connection_timeout : float;
    number_of_parallel_connections : int;
    maximum_redirections : int;
    handshake_timeout : float;
    resolver : Nethttp_client.resolver;
    configure_socket : Unix.file_descr -> unit;
    tls : Netsys_crypto_types.tls_config option;
    schemes :
      (string * Neturl.url_syntax * int option *
       Nethttp_client.transport_layer_id)
      list;
    verbose_status : bool;
    verbose_request_header : bool;
    verbose_response_header : bool;
    verbose_request_contents : bool;
    verbose_response_contents : bool;
    verbose_connection : bool;
    verbose_events : bool;
  }
  type header_kind = [ `Base | `Effective ]
  class type http_call =
    object
      method assoc_multi_req_header : string -> string list
      method assoc_multi_resp_header : string -> string list
      method assoc_req_header : string -> string
      method assoc_resp_header : string -> string
      method auth_status : unit Nethttp_client.auth_status
      method dest_status : unit -> string * int * string
      method effective_request_uri : string
      method empty_path_replacement : string
      method get_host : unit -> string
      method get_path : unit -> string
      method get_port : unit -> int
      method get_reconnect_mode :
        Nethttp_client.http_call Nethttp_client.how_to_reconnect
      method get_redirect_mode :
        Nethttp_client.http_call Nethttp_client.how_to_redirect
      method get_req_body : unit -> string
      method get_req_header : unit -> (string * string) list
      method get_req_method : unit -> string
      method get_resp_body : unit -> string
      method get_resp_header : unit -> (string * string) list
      method get_uri : unit -> string
      method gssapi_props : Netsys_gssapi.client_props option
      method has_req_body : bool
      method has_resp_body : bool
      method is_idempotent : bool
      method is_proxy_allowed : unit -> bool
      method is_served : bool
      method max_response_body_length : int64
      method no_proxy : unit -> unit
      method private_api : Nethttp_client.private_api
      method proxy_enabled : bool
      method proxy_use_connect : bool
      method request_body : Netmime.mime_body
      method request_header :
        Nethttp_client.header_kind -> Netmime.mime_header
      method request_method : string
      method request_uri : string
      method response_body : Netmime.mime_body
      method response_body_storage : Nethttp_client.response_body_storage
      method response_header : Netmime.mime_header
      method response_protocol : string
      method response_status : Nethttp.http_status
      method response_status_code : int
      method response_status_text : string
      method same_call : unit -> Nethttp_client.http_call
      method set_accept_encoding : unit -> unit
      method set_chunked_request : unit -> unit
      method set_expect_handshake : unit -> unit
      method set_max_response_body_length : int64 -> unit
      method set_proxy_enabled : bool -> unit
      method set_reconnect_mode :
        Nethttp_client.http_call Nethttp_client.how_to_reconnect -> unit
      method set_redirect_mode :
        Nethttp_client.http_call Nethttp_client.how_to_redirect -> unit
      method set_req_header : string -> string -> unit
      method set_request_body : Netmime.mime_body -> unit
      method set_request_device : (unit -> Uq_io.in_device) -> unit
      method set_request_header : Netmime.mime_header -> unit
      method set_request_uri : string -> unit
      method set_response_body_storage :
        Nethttp_client.response_body_storage -> unit
      method set_transport_layer : Nethttp_client.transport_layer_id -> unit
      method status : Nethttp_client.status
      method tls_session_props : Nettls_support.tls_session_props option
    end
  class type tls_cache =
    object
      method clear : unit -> unit
      method get :
        domain:string ->
        port:int -> trans:Nethttp_client.transport_layer_id -> string
      method set :
        domain:string ->
        port:int ->
        trans:Nethttp_client.transport_layer_id -> data:string -> unit
    end
  val null_tls_cache : unit -> Nethttp_client.tls_cache
  val unlim_tls_cache : unit -> Nethttp_client.tls_cache
  class type transport_channel_type =
    object
      method continue :
        Unix.file_descr ->
        Nethttp_client.transport_layer_id ->
        float ->
        exn ->
        string ->
        int ->
        Unixqueue.event_system ->
        exn option -> Uq_engines.multiplex_controller
      method default_port : int option
      method identify_conn_by_name : bool
      method setup_e :
        Unix.file_descr ->
        Nethttp_client.transport_layer_id ->
        float ->
        exn ->
        string ->
        int ->
        Unixqueue.event_system ->
        Nethttp_client.tls_cache ->
        Uq_engines.multiplex_controller Uq_engines.engine
    end
  class virtual generic_call :
    object
      method assoc_multi_req_header : string -> string list
      method assoc_multi_resp_header : string -> string list
      method assoc_req_header : string -> string
      method assoc_resp_header : string -> string
      method auth_status : unit auth_status
      method private virtual def_empty_path_replacement : string
      method private virtual def_has_req_body : bool
      method private virtual def_has_resp_body : bool
      method private virtual def_is_idempotent : bool
      method private virtual def_request_method : string
      method dest_status : unit -> string * int * string
      method effective_request_uri : string
      method empty_path_replacement : string
      method private virtual fixup_request : unit -> unit
      method get_host : unit -> string
      method get_path : unit -> string
      method get_port : unit -> int
      method get_reconnect_mode : http_call how_to_reconnect
      method get_redirect_mode : http_call how_to_redirect
      method get_req_body : unit -> string
      method get_req_header : unit -> (string * string) list
      method get_req_method : unit -> string
      method get_resp_body : unit -> string
      method get_resp_header : unit -> (string * string) list
      method get_uri : unit -> string
      method gssapi_props : Netsys_gssapi.client_props option
      method has_req_body : bool
      method has_resp_body : bool
      method is_idempotent : bool
      method is_proxy_allowed : unit -> bool
      method is_served : bool
      method max_response_body_length : int64
      method no_proxy : unit -> unit
      method private_api : private_api
      method proxy_enabled : bool
      method proxy_use_connect : bool
      method request_body : Netmime.mime_body
      method request_header : header_kind -> Netmime.mime_header
      method request_method : string
      method request_uri : string
      method response_body : Netmime.mime_body
      method response_body_storage : response_body_storage
      method response_header : Netmime.mime_header
      method response_protocol : string
      method response_status : Nethttp.http_status
      method response_status_code : int
      method response_status_text : string
      method same_call : unit -> http_call
      method set_accept_encoding : unit -> unit
      method set_chunked_request : unit -> unit
      method set_expect_handshake : unit -> unit
      method set_max_response_body_length : int64 -> unit
      method set_proxy_enabled : bool -> unit
      method set_reconnect_mode : http_call how_to_reconnect -> unit
      method set_redirect_mode : http_call how_to_redirect -> unit
      method set_req_header : string -> string -> unit
      method set_request_body : Netmime.mime_body -> unit
      method set_request_device : (unit -> Uq_io.in_device) -> unit
      method set_request_header : Netmime.mime_header -> unit
      method set_request_uri : string -> unit
      method set_response_body_storage : response_body_storage -> unit
      method set_transport_layer : transport_layer_id -> unit
      method status : status
      method tls_session_props : Nettls_support.tls_session_props option
    end
  class get_call : http_call
  class trace_call : http_call
  class options_call : http_call
  class head_call : http_call
  class post_call : http_call
  class put_call : http_call
  class delete_call : http_call
  class get : string -> http_call
  class trace : string -> int -> http_call
  class options : string -> http_call
  class head : string -> http_call
  class post : string -> (string * string) list -> http_call
  class post_raw : string -> string -> http_call
  class put : string -> string -> http_call
  class delete : string -> http_call
  class type key =
    object
      method credentials : (string * string * (string * string) list) list
      method domain : Neturl.url list
      method password : string
      method realm : string
      method user : string
    end
  val key :
    user:string ->
    password:string ->
    realm:string -> domain:Neturl.url list -> Nethttp_client.key
  val key_creds :
    user:string ->
    creds:(string * string * (string * string) list) list ->
    Nethttp_client.http_options -> Nethttp_client.key
  class type key_handler =
    object
      method inquire_key :
        domain:Neturl.url option ->
        realm:string -> auth:string -> Nethttp_client.key
      method invalidate_key : Nethttp_client.key -> unit
    end
  class key_ring :
    ?uplink:#Nethttp_client.key_handler ->
    ?no_invalidation:bool ->
    unit ->
    object
      method add_key : Nethttp_client.key -> unit
      method clear : unit -> unit
      method inquire_key :
        domain:Neturl.url option -> realm:string -> auth:string -> key
      method invalidate_key : key -> unit
      method keys : Nethttp_client.key list
    end
  class type auth_session =
    object
      method auth_domain : Neturl.url list * int
      method auth_realm : string
      method auth_scheme : string
      method auth_session_id : string option
      method auth_user : string
      method authenticate :
        Nethttp_client.http_call ->
        bool -> (string * string) list Nethttp_client.auth_status
      method invalidate : Nethttp_client.http_call -> unit
    end
  class type auth_handler =
    object
      method create_proxy_session :
        Nethttp_client.http_call ->
        Nethttp_client.http_options Pervasives.ref ->
        Nethttp_client.auth_session option
      method create_session :
        secure:bool ->
        Nethttp_client.http_call ->
        Nethttp_client.http_options Pervasives.ref ->
        Nethttp_client.auth_session option
      method identify_proxy_session :
        Nethttp_client.http_call ->
        Nethttp_client.http_options Pervasives.ref ->
        (string * string * string * int) option
      method identify_session :
        Nethttp_client.http_call ->
        Nethttp_client.http_options Pervasives.ref ->
        (string * string * string * int) option
      method skip_challenge : bool
      method skip_challenge_session :
        Nethttp_client.http_call ->
        Nethttp_client.http_options Pervasives.ref ->
        Nethttp_client.auth_session option
    end
  class basic_auth_handler :
    ?enable_reauth:bool ->
    ?skip_challenge:bool -> #Nethttp_client.key_handler -> auth_handler
  class digest_auth_handler : #Nethttp_client.key_handler -> auth_handler
  class unified_auth_handler :
    ?insecure:bool -> #Nethttp_client.key_handler -> auth_handler
  class generic_auth_handler :
    #Nethttp_client.key_handler ->
    (module Nethttp.HTTP_CLIENT_MECHANISM) list -> auth_handler
  type connection_cache = Nethttp_client_conncache.connection_cache
  val close_connection_cache : Nethttp_client.connection_cache -> unit
  val create_restrictive_cache : unit -> Nethttp_client.connection_cache
  val create_aggressive_cache : unit -> Nethttp_client.connection_cache
  val http_trans_id : Nethttp_client.transport_layer_id
  val https_trans_id : Nethttp_client.transport_layer_id
  val spnego_trans_id : Nethttp_client.transport_layer_id
  val proxy_only_trans_id : Nethttp_client.transport_layer_id
  val new_trans_id : unit -> Nethttp_client.transport_layer_id
  val http_transport_channel_type : Nethttp_client.transport_channel_type
  val https_transport_channel_type :
    Netsys_crypto_types.tls_config -> Nethttp_client.transport_channel_type
  type proxy_type = [ `Http_proxy | `Socks5 ]
  class pipeline :
    object
      method add : Nethttp_client.http_call -> unit
      method add_auth_handler : Nethttp_client.auth_handler -> unit
      method add_e :
        Nethttp_client.http_call ->
        Nethttp_client.http_call Uq_engines.engine
      method add_with_callback :
        Nethttp_client.http_call ->
        (Nethttp_client.http_call -> unit) -> unit
      method avoid_proxy_for : string list -> unit
      method cnt_crashed_connections : int
      method cnt_failed_connections : int
      method cnt_new_connections : int
      method cnt_server_eof_connections : int
      method cnt_successful_connections : int
      method cnt_timed_out_connections : int
      method configure_transport :
        Nethttp_client.transport_layer_id ->
        Nethttp_client.transport_channel_type -> unit
      method connection_cache : Nethttp_client.connection_cache
      method connections : (string * int * int) list
      method event_system : Unixqueue.event_system
      method get_options : Nethttp_client.http_options
      method number_of_open_connections : int
      method number_of_open_messages : int
      method proxy_type : string -> Nethttp_client.proxy_type option
      method proxy_type_of_call :
        Nethttp_client.http_call -> Nethttp_client.proxy_type option
      method reset : unit -> unit
      method reset_counters : unit -> unit
      method run : unit -> unit
      method set_connection_cache : Nethttp_client.connection_cache -> unit
      method set_event_system : Unixqueue.event_system -> unit
      method set_options : Nethttp_client.http_options -> unit
      method set_proxy : string -> int -> unit
      method set_proxy_auth : insecure:bool -> string -> string -> unit
      method set_proxy_from_environment : insecure:bool -> unit -> unit
      method set_socks5_proxy : string -> int -> unit
      method set_tls_cache : Nethttp_client.tls_cache -> unit
      method set_transport_proxy :
        Nethttp_client.transport_layer_id ->
        string ->
        int ->
        (string * string * bool) option -> Nethttp_client.proxy_type -> unit
      method set_transport_proxy_from_environment :
        insecure:bool ->
        (string * Nethttp_client.transport_layer_id) list -> unit
      method transport_layer :
        Nethttp_client.http_call -> Nethttp_client.transport_layer_id
    end
  val parse_proxy_setting :
    insecure:bool -> string -> string * int * (string * string * bool) option
  val parse_no_proxy : string -> string list
  module Convenience :
    sig
      val http_trials : int Pervasives.ref
      val http_user : string Pervasives.ref
      val http_password : string Pervasives.ref
      val configure : ?insecure:bool -> unit -> unit
      val configure_pipeline : (Nethttp_client.pipeline -> unit) -> unit
      val http_get_message : string -> Nethttp_client.http_call
      val http_head_message : string -> Nethttp_client.http_call
      val http_post_message :
        string -> (string * string) list -> Nethttp_client.http_call
      val http_put_message : string -> string -> Nethttp_client.http_call
      val http_delete_message : string -> Nethttp_client.http_call
      val http_get : string -> string
      val http_post : string -> (string * string) list -> string
      val http_put : string -> string -> string
      val http_delete : string -> string
      val http_verbose :
        ?verbose_status:bool ->
        ?verbose_request_header:bool ->
        ?verbose_response_header:bool ->
        ?verbose_request_contents:bool ->
        ?verbose_response_contents:bool ->
        ?verbose_connection:bool -> ?verbose_events:bool -> unit -> unit
    end
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Netplex_types.controller-c.html0000644000175000017500000006275212731530353022550 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.controller

Class type Netplex_types.controller

class type controller = object .. end
The controller is the object in the Netplex master process/thread that manages the containers, logging, and service definitions

method ptype : parallelization_type
The actually effective parallelization type
method sys_id : thread_sys_id
The thread running the controller
method controller_config : controller_config
method services : (socket_service * socket_controller *
workload_manager)
list
The list of controlled services
method add_service : socket_service -> workload_manager -> unit
Adds a new service. Containers for these services will be started soon. It is allowed to add several services with the same name (but it will be hard to distinguish them later).
method add_message_receiver : ctrl_message_receiver -> unit
Adds a message receiver. This receiver runs in the context of the controller and receives all messages sent to it. The name method must return the name.
method add_plugin : plugin -> unit
Adds a plugin. If the plugin object has already been added, this is a no-op.

Plugins must have been added before the first container is started. This is not checked, however. You are on the safe side when the plugin is added in the create_processor factory method, or in the post_add_hook of the processor.

method add_admin : (Rpc_server.t -> unit) -> unit
add_admin setup: Allows to bind another RPC program to the admin socket. The function setup will be called whenever a connection to the admin socket is established, and this function can call Rpc_server.bind to bind another RPC program. By default, only the Admin interface is available as described in netplex_ctrl.x.

Note that this RPC server runs in the scope of the controller! No additional process or thread is created.

method logger : logger
The logger
method event_system : Unixqueue.unix_event_system
The event system used by the controller. It must not be used from a container.
method restart : unit -> unit
Initiates a restart of all containers: All threads/processes are terminated and replaced by newly initialized ones.
method shutdown : unit -> unit
Initiates a shutdown of all containers. It is no longer possible to add new services. When the shutdown has been completed, the controller will terminate itself. Note that the shutdown is performed asynchronously, i.e. this method returns immediately, and the messaging required to do the shutdown is done in the background.
method send_message : string -> string -> string array -> unit
send_message destination msgname msgargs: Sends a message to destination. When this method returns, it is only ensured that the receivers registered in the controller have been notified about the message (so it can be made sure that any newly forked containers know about the message). It is not guaranteed that the existing containers are notified when this method returns. This can (and usually will) happen at any time in the future.
method send_admin_message : string -> string -> string array -> unit
send_message destination msgname msgargs: Sends an admin message to destination.

See send_message for the notification guarantees.

method register_lever : (controller -> encap -> encap) ->
int
let id = register_lever f: It is possible to register a function f in the controller, and run it over the internal RPC interface from any container. These functions are called levers. See activate_lever below. See also Netplex_cenv.Make_lever for a convenient way to create and use levers.
method activate_lever : int -> encap -> encap
Runs the registered lever directly
method containers : container_id list
Lists the containers
method containers_for : string -> container_id list
Lists the containers for a certain socket service name
method container_count : string -> int
The number of containers for a certain socket service name
method free_resources : unit -> unit
Should be called when the controller is finished, in order to free resources again. E.g. plugins are unplugged, and the master sockets are closed.
method startup_directory : string
The current directory at startup time
ocamlnet-4.1.2/doc/html-main/Netcgi_common.cgi_environment-c.html0000644000175000017500000006741412731530353023471 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.cgi_environment

Class Netcgi_common.cgi_environment

class cgi_environment : config:config -> properties:(string * string) list -> input_header:(string * string) list -> Netchannels.out_obj_channel -> object .. end
new cgi_environment ~config ~properties ~input_header out_obj generates a Netcgi.cgi_environment object, from the arguments. The creation of such an object does not raise any exception. The method #out_channel of the created environment returns out_obj.
config : give the configuration options. Of particular interest here is config.workarounds. If `MSIE_Content_type_bug is present, a fix will be applied to input_header.
properties : CGI-like properties as (name, value) pairs. Examples: ("REQUEST_METHOD", "POST"), ("SERVER_PROTOCOL", "HTTP/1.1"). Note that "CONTENT_TYPE" and "CONTENT_LENGTH" are part of the input header. It is highly recommended to use Netcgi_common.update_props_inheader to build this list.
input_header : is a list of (field, value) pairs of the HTTP input request. It is ASSUMED that field names in input_header are lowercase in order to apply a fix to the MSIE Content-Type bug. Also remember that the separator is '-', not '_'. Both requirements will be stafisfied if you use Netcgi_common.update_props_inheader to build input_header.

Notes: The header is kept into variables and #send_output_header sents it directly to out_obj. This has several advantages:

  • It is possible to change header fields at every moment before the commitment happens. For example, it is possible to set the content-length field which is normally only known just at the time of the commit operation.
  • The environment object can process the header; for example it can fix header fields.
  • It is simpler to connect to environments which transport the header in non-standard ways. Example: Assume that the environment is the web server process (e.g. we are an Apache module). Typically the header must be stored in different structures than the body of the message.

val mutable header_not_sent : bool
true iff the output headers have not been sent. #send_output_header must set it to false once it did its job.
method cgi_gateway_interface : string
method cgi_server_name : string
method cgi_server_port : int option
method cgi_server_protocol : string
method cgi_server_software : string
method cgi_request_method : string
method cgi_script_name : string
method cgi_path_info : string
method cgi_path_translated : string
method cgi_auth_type : string
method cgi_remote_addr : string
method cgi_remote_host : string
method cgi_remote_user : string
method cgi_remote_ident : string
method cgi_query_string : string
method protocol : Nethttp.protocol
method cgi_property : ?default:string -> string -> string
method cgi_properties : (string * string) list
Return the parameter properties.
method cgi_https : bool
Raises HTTP if the HTTPS property is not understood.
method input_header : Netmime.mime_header
For special header structures, just override this method.
method input_header_field : ?default:string -> string -> string
method multiple_input_header_field : string -> string list
method input_header_fields : (string * string) list
method cookie : string -> Cookie.t
method cookies : Cookie.t list
method user_agent : string
method input_content_length : int
method input_content_type_string : string
method input_content_type : unit -> string * (string * Netmime_string.s_param) list
method output_header : Netmime.mime_header
For special header structures, override this method and maybe #send_output_header.
method output_header_field : ?default:string -> string -> string
method multiple_output_header_field : string -> string list
method output_header_fields : (string * string) list
method set_output_header_field : string -> string -> unit
method set_multiple_output_header_field : string -> string list -> unit
method set_output_header_fields : (string * string) list -> unit
method set_status : Nethttp.http_status -> unit
method send_output_header : unit -> unit
method output_ch : Netchannels.out_obj_channel
Deprecated.Use #out_channel instead.
method out_channel : Netchannels.out_obj_channel
method log_error : string -> unit
You may want to override this with your custom logging method. By default, #log_error msg adds a timestamp to msg and sends th result to stderr.
method config : config
ocamlnet-4.1.2/doc/html-main/type_Netchannels.tempfile_trans_channel.html0000644000175000017500000004140412731530353025300 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.tempfile_trans_channel ?close_mode:Netchannels.close_mode ->
?tmp_directory:string ->
?tmp_prefix:string ->
Netchannels.out_obj_channel -> Netchannels.trans_out_obj_channel
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.meta_engine-c.html0000644000175000017500000004256612731530353023436 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.meta_engine

Class Uq_engines_compat.meta_engine

class ['a] meta_engine : 'a #engine -> ['a final_state] engine

ocamlnet-4.1.2/doc/html-main/Shell_fs.shell_stream_fs-c.html0000644000175000017500000004220112731530353022416 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_fs.shell_stream_fs

Class type Shell_fs.shell_stream_fs

class type shell_stream_fs = object .. end
Inherits
method last_stderr : string
The stderr output of the last operation
ocamlnet-4.1.2/doc/html-main/type_Uq_multiplex.datagram_multiplex_controller.html0000644000175000017500000005262612731530353027160 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_multiplex.datagram_multiplex_controller object
  method alive : bool
  method cancel_reading : unit -> unit
  method cancel_shutting_down : unit -> unit
  method cancel_writing : unit -> unit
  method event_system : Unixqueue.event_system
  method inactivate : unit -> unit
  method mem_supported : bool
  method read_eof : bool
  method reading : bool
  method received_from : Unix.sockaddr
  method send_to : Unix.sockaddr -> unit
  method shutting_down : bool
  method start_mem_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_mem_writing :
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_shutting_down :
    ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
  method start_writing :
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit
  method supports_half_open_connection : bool
  method tls_session : (string * string) option
  method tls_session_props : Nettls_support.tls_session_props option
  method tls_stashed_endpoint : unit -> exn
  method writing : bool
  method wrote_eof : bool
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client_conncache.aggressive_cache-c.html0000644000175000017500000004310312731530353025756 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client_conncache.aggressive_cache

Class Nethttp_client_conncache.aggressive_cache

class aggressive_cache : unit -> connection_cache
This type of cache tries to keep connections as long open as possible. The consequence is that users are responsible for closing the descriptors (by calling close_connection_cache) when the cache is no longer in use. It is also possible to derive a special version of the cache from this class, e.g. for closing descriptors when they are idle for some time.

ocamlnet-4.1.2/doc/html-main/type_Netgssapi_auth.CONFIG.html0000644000175000017500000004105712731530353022261 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_auth.CONFIG sig val raise_error : string -> 'endocamlnet-4.1.2/doc/html-main/type_Netcgi_apache.Apache.Connection.html0000644000175000017500000004227412731530353024331 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache.Connection sig
  type t
  external remote_ip : Netcgi_apache.Apache.Connection.t -> string
    = "netcgi2_apache_connection_remote_ip"
  external remote_host : Netcgi_apache.Apache.Connection.t -> string
    = "netcgi2_apache_connection_remote_host"
end
ocamlnet-4.1.2/doc/html-main/Netmech_crammd5_sasl.CRAM_MD5.html0000644000175000017500000011161712731530353022501 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_crammd5_sasl.CRAM_MD5

Module Netmech_crammd5_sasl.CRAM_MD5

module CRAM_MD5: Netsys_sasl_types.SASL_MECHANISM 
The CRAM-MD5 SASL mechanism (RFC 2195), which is obsolete and only provided for completeness.

Key facts:

  • The password is checked with a challenge-response mechanism, and does not appear in the clear.
  • The mechanism is vulnerable to man-in-the-middle attacks.
  • The client does not authenticate the server in any way.
  • The hash function MD5 counts as broken.
  • There is no support for channel binding within the mechanism.
  • There is no support for authorization names.
  • The mechanism provides at best medium security, and should only be used over channels that are otherwise secured.
This implementation checks whether the server receives user names and passwords in UTF-8 encoding. Note that the mechanism predates the widespread use of Unicode, so this may cause interoperability issues with old implementations.

Parameters:

  • Both create_client_session and create_server_session accept the boolean parameter "mutual". If true, however, authentication fails immediately, as mutual authentication cannot be supported.
  • The boolean parameter "secure" is ignored (i.e. we regard this mechanism as secure)
As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of CRAM-MD5 should pass user names and passwords through Netsaslprep.saslprep.

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/Netmcore_mempool.html0000644000175000017500000005604512731530353020605 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_mempool

Module Netmcore_mempool

module Netmcore_mempool: sig .. end
Memory pools

A memory pool is a block of shared memory that is set aside for storing shared data structures. The pool needs to be created before the worker processes are forked off that are going to use the pool. The worker processes do not map the pool to some random address, but rather the processes inherit the pool from the common master process which ensures that all processes will see the pool at the same address.

In order to allow inheritance, the function Netmcore.start for starting workers needs to get an additional argument ~inherit_resources. The resource ID of the pool must be put into this list - otherwise the worker does not get access to the pool.

It is not possible to enlarge the pool later (because of the inheritance method for making the pool accessible). It is advised to make the pool large enough for all possible data cases, and to let the user configure this size.


exception Out_of_pool_memory
val create_mempool : ?alloc_really:bool -> int -> Netmcore.res_id
Creates the memory pool as shared memory object of the passed size (rounded up to the next multiple of pages) and returns the resource ID.

Note that the process calling this function cannot use the pool, but only worker processes that are forked later. It is possible to call create_mempool before running Netmcore.startup.

Option alloc_really: On some operating systems (namely Linux) shared memory is not fully included into the memory bookkeeping as long as nothing is written into it (so-called overcommitment). This means that the memory is not reserved, and when something is written for the first time, it might happen that the system cannot grant the request. The consequence is a bus error. By setting alloc_really to true, all allocated memory pages are immediately written to, and thus the problem is avoided (or better, if memory is really tight, you get the bus error now immediately, at least).

Note that memory pools have kernel persistence! They are not automatically deleted when the process finishes. Call unlink_mempool to delete memory pools.

val alloc_mem : Netmcore.res_id -> int -> Netsys_mem.memory
Allocate memory in this pool. The passed int the size of the returned memory object. The size is rounded up to the next multiple of pages.

Blocks are actually allocated in units of pages.

Raises Out_of_pool_memory if there is not enough contiguous space in the pool.

val size_mem : Netmcore.res_id -> Netsys_mem.memory -> int
Returns the size of this block, or raises Not_found
val size_mem_at_addr : Netmcore.res_id -> nativeint -> int
Returns the size of the block at this address, or raises Not_found
val free_mem : Netmcore.res_id -> Netsys_mem.memory -> unit
Frees this allocated block
val stats : Netmcore.res_id -> int * int * int
Returns (total, free, contiguous) where
  • total is the total size of the pool
  • free is the number of free bytes
  • contiguous is the size of the largest contiguous free block

val debug_info : Netmcore.res_id -> string
Returns a string describing the allocations etc.
val shm_name : Netmcore.res_id -> string
Returns the name of the shared memory object
val sem_container : Netmcore.res_id -> Netsys_sem.container
Returns the semaphore container
val unlink_mempool : Netmcore.res_id -> unit
Deletes the persistent objects of this pool
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Rpc_client.default_socket_config.html0000644000175000017500000004061612731530353024741 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.default_socket_config Rpc_client.socket_configocamlnet-4.1.2/doc/html-main/type_Netplex_types.processor_hooks.html0000644000175000017500000005146512731530353024427 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.processor_hooks object
  method config_internal : (string * Netplex_types.polysocket_kind_box) list
  method container_event_system : unit -> Unixqueue.event_system
  method container_run : Unixqueue.event_system -> unit
  method global_exception_handler : exn -> bool
  method post_add_hook :
    Netplex_types.socket_service -> Netplex_types.controller -> unit
  method post_finish_hook :
    Netplex_types.socket_service ->
    Netplex_types.controller -> Netplex_types.container_id -> unit
  method post_rm_hook :
    Netplex_types.socket_service -> Netplex_types.controller -> unit
  method post_start_hook : Netplex_types.container -> unit
  method pre_finish_hook : Netplex_types.container -> unit
  method pre_start_hook :
    Netplex_types.socket_service ->
    Netplex_types.controller -> Netplex_types.container_id -> unit
  method process_internal :
    when_done:(unit -> unit) ->
    Netplex_types.container -> Netplex_types.polyserver_box -> string -> unit
  method receive_admin_message :
    Netplex_types.container -> string -> string array -> unit
  method receive_message :
    Netplex_types.container -> string -> string array -> unit
  method shutdown : unit -> unit
  method system_shutdown : unit -> unit
  method workload_hook : Netplex_types.container -> bool -> int -> unit
end
ocamlnet-4.1.2/doc/html-main/Authentication.html0000644000175000017500000007512212731530353020255 0ustar gerdgerd Ocamlnet 4 Reference Manual : Authentication

Authentication


Authentication

One of the bigger changes of Ocamlnet-4 is the focus on security topics, which also includes authentication. There are now four modular authentication frameworks:

  • SASL (Simple Authentication and Security Layer). SASL focuses on challenge/response password-checking. The IETF extended many network protocols in order to support SASL. Among these protocols there are SMTP, POP, IMAP, and LDAP.
  • HTTP Authentication. Traditionally there were only two authentication methods for HTTP ("basic" and "digest"), but recently the IETF paced forward and defined not only principles for any HTTP method, but also ported a number of SASL methods (SCRAM, updated DIGEST).
  • GSSAPI (General Security Services API). This is a stricter approach for an authentication and security framework than SASL. It is not directly defined as a protocol, but as an API, which improves the precision and extends the functionality. In particular, GSSAPI also includes integrity and privacy protection of the application messages as option. It is up to the application protocol how to adopt the API. GSSAPI is often used for system authentication (e.g. by wrapping the Kerberos suite), but not limited to that. Many SASL mechanisms are also available as GSSAPI mechanisms. Note that there is some confusion about the relationship between GSSAPI and Kerberos, and sometimes GSSAPI is used as synonym for Kerberos. In reality, however, GSSAPI means the API (and framework) that is used as primary API for Kerberos. It is just not limited to it. GSSAPI is widely deployed (e.g. MIT Kerberos and Heimdal for Linux/BSD/Unix/Windows, and Windows integrates a version of GSSAPI with a proprietary interface called SSPI). Especially system-oriented protocols support the GSSAPI, e.g. SSH, FTP, and ONC-RPC. There is also a somewhat questionable way of using GSSAPI together with HTTP ("negotiate" method). Read more about the GSSAPI here: Gssapi.
  • TLS (Transport Level Security). TLS is often misunderstood as a way to encrypt TCP connections. However, this is just a consequence of its primary purpose, namely authenticating the endpoints. Normally, only the server is authenticated in the sense that an agency (the trust center) approved the credentials (then called "certificate"). TLS includes options to strengthen this quite weak authentication: Clients may only accept certain server certificates (e.g. those with extended validation attributes, or from a certain trust center, or with some other specific attributes). Also, it is possible that servers authenticate clients, also using certificates. Read more about TLS here: Tls

Modularity

For all these frameworks, Ocamlnet defines mechanism types in a modular way. There is a provider of the mechanism and a user (i.e. a protocol interpreter). The user code can be written so it can generically work with any mechanism of the expected type.

Technically, the mechanism type is usually an OCaml module type, and the mechanism is an OCaml module. As OCaml supports first-class modules, the mechanisms can be passed as normal function arguments to the user code. Let us demonstrate this for the SASL mechanism SCRAM:

  • SASL mechanisms are defined as this module type: Netsys_sasl_types.SASL_MECHANISM
  • The SCRAM mechanism is available for several frameworks. For SASL, there is the module Netmech_scram_sasl.SCRAM_SHA1 (more precisely, this is SCRAM with SHA1 as hash function).
  • In this example, let us use the POP network protocol. We can use the POP protocol interpreter together with SCRAM as follows:
    let user = ... in     (* see below *)
    let creds = ... in    (* see below *)
    let client = new Netpop.connect ... in
    Netpop.authenticate
      ~sasl_mechs:[ (module Netmech_scram_sasl.SCRAM_SHA1 ) ]
      ~user
      ~creds
      client in
    (* now the user is logged in and access POP objects, e.g. *)
    let channel = client#retr ~msgno:0 in
    ...
       
Of course, you can also use any other SASL method together with POP. Note however, that POP servers usually do not implement all SASL methods, but just a subset. Because of that it is good practice to specify several methods in the sasl_mechs argument. The POP client will use the first mechanism of this list that is also supported by the server. This is called mechanism negotiation. More about that later.

Module types:

Mechanisms:

Credentials

We've left out what to pass as user and as creds in this example. It depends on the framework how user names and how credentials can be expressed:

  • For SASL, user names are simply UTF-8 encoded strings. Credentials can be specified in many forms (see the separate page about Credentials). For Ocamlnet, SASL credentials are expressed as list of credential elements, and every element includes a type, a value, and optional parameters:
    type credentials =
      (string * string * (string * string) list) list
       
    For clients, passwords are normally given in the cleartext form:
    ("password", password, [])
       
    Note that the string "password" is the element type, and must always be literally "password", and should not be confused with the actual password which is the second value. For servers, passwords may be given in different forms (i.e. after applying a key derivation function), which saves computation time. See Credentials for SASL for details.
  • HTTP Authentication expresses user names and credentials in the same way as SASL.
  • GSSAPI can use several schemes for identifying users. Credentials are opaque in the API. It is not specified how credentials look like, and there are private mechanism-specific functions covering how to submit and how to check credentials. This is usually no problem for system authentication where the credentials are implicitly known (e.g. as Kerberos tickets), but it is impractical for application-level identity checking. In Ocamlnet GSSAPI mechanisms can be either written in OCaml, or the system libraries can be used. In the former case, the credentials are usually specified when the GSSAPI object is instantiated (in a mechanism-specific way). In the latter case, there is so far no way to specify credentials from OCaml code (but this may change in the future, as there is a GSSAPI extension for specifying passwords). See Credentials for the GSSAPI for details.
  • TLS uses certificates as (extended) user names, and credentials are public/private key pairs. The public key is embedded in the certificate. Normally certificates and private keys are stored in specially encoded files. See Credentials for TLS for details.

Cleartext passwords

Some warnings about using "mechanisms" that only transmit a cleartext password, including

  • the HTTP "basic" authentication (or even form-based password submission)
  • the PLAIN SASL mechanism
  • protocol-specific login methods (e.g. for POP or FTP)
Even if TLS is enabled for the underlying transport channel, it is a very bad idea to use such methods, simply because the server will get the password in the clear. This allows a number of attack vectors that are very dangerous:

  • Phishing: the client is tricked into connecting to the wrong server. This server may even have a valid TLS certificate from a trust center (criminals are not systematically excluded here). You can only be safe if you also deploy a strong check on the server certificate.
  • The server may be compromised so that the passwords are intercepted directly after they were sent by the client.
  • As good key derivation functions are computationally expensive, password databases cannot be protected well (it would consume too much CPU).
Cleartext passwords are like an invitation to hackers: Don't use them at all.

Password checking with challenge/response mechanisms

The other password-based mechanisms are much better:

  • SCRAM (best and newest)
  • DIGEST (widely available)
  • CRAM (try to avoid)
If the client connects to the wrong server this server will not get the password directly. The client only proves that it knows the password without transmitting it. DIGEST and SCRAM add even more protection:

  • Both "salt" the challenges. This makes it more difficult to crack the password if an attacker can spoof the authentication exchange.
  • Both authenticate the server, i.e. the client can check whether the server has access to the legitimate password database.
  • SCRAM even implements a fairly expensive key derivation function. The interesting point is that only the client needs to actually run this function. The server can simply store the derived key in the password database. If an attacker gets access to this database, it is very hard to crack the passwords, because the attacker can only try out passwords at a low rate.
Note that SASL does not protect the TCP connection. It is advisable to run SASL over TLS, because:

  • this encrypts the connection
  • this prevents man-in-the-middle attacks (if basic server authentication is enabled for TLS)
  • this prevents subtle downgrade attacks, e.g. a man-in-the-middle could otherwise modify the protocol stream so that a weaker authentication scheme is used than possible

Public key mechanisms

At the moment, these mechanisms are only indirectly available via:

  • TLS, or
  • GSS-API system authentication (so far available, e.g. LIPKEY)

Mechanism negotiation

There are more or less two common ways how client and server negotiate a certain authentication mechanism:

  • The "relaxed" way, used for SASL and HTTP: The server offers a few authentication options, and the client picks one.
  • The "strict" way, used for GSSAPI (in the form of SPNEGO) and TLS: There is a multi-step negotiation protocol between client and server. Both parties can express preferences. The protocol is protected, so that a man-in-the-middle cannot take influence on the outcome.
The "relaxed" negotiation is unprotected, which may have a serious effect on the overall security of the mechanism. In particular, a man-in-the-middle can run a downgrade attack, so that client and server negotiate a weaker mechanism than they actually support. This is in particular dangerous when the mechanism is downgraded to a plaintext mechanism, as the attacker can then easily sniff the password.

In particular you should keep in mind that the HTTP negotiation is always relaxed, and that it is often not possible to turn completely off cleartext authentication. This means that offering more secure options makes only sense when the communication channel is secure (i.e. when TLS is on). Or in other words: you should always use TLS when authentication comes into play.
ocamlnet-4.1.2/doc/html-main/type_Netstring_str.Debug.html0000644000175000017500000004100612731530353022223 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstring_str.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netdn.html0000644000175000017500000004511512731530353016345 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdn

Module Netdn

module Netdn: sig .. end
X.500 distinguished names

type oid = Netoid.t 
type dn = (oid * Netasn1.Value.value) list list 
This is the raw version of the DN: a sequence of relative DNs, and a relative DN is a set of (type,value) pairs. The types are things like cn, country, organization, ...
module type AT_LOOKUP = sig .. end
module type DN_string = sig .. end
module DN_string_generic: 
functor (L : AT_LOOKUP) -> DN_string
For a given attribute lookup module L this module provides parser and printer for distinguished names in string format (RFC 4514).
ocamlnet-4.1.2/doc/html-main/type_Nethttp_fs.http_stream_fs.html0000644000175000017500000005355012731530353023477 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_fs.http_stream_fs object
  method cancel : unit -> unit
  method copy : Netfs.copy_flag list -> string -> string -> unit
  method last_response_header : Nethttp.http_header
  method last_response_status : Nethttp.http_status * int * string
  method mkdir : Netfs.mkdir_flag list -> string -> unit
  method nominal_dot_dot : bool
  method path_encoding : Netconversion.encoding option
  method path_exclusions : (int * int) list
  method pipeline : Nethttp_client.pipeline
  method read :
    Nethttp_fs.read_flag list -> string -> Netchannels.in_obj_channel
  method read_file :
    Nethttp_fs.read_file_flag list -> string -> Netfs.local_file
  method readdir : Netfs.readdir_flag list -> string -> string list
  method readlink : Netfs.readlink_flag list -> string -> string
  method remove : Netfs.remove_flag list -> string -> unit
  method rename : Netfs.rename_flag list -> string -> string -> unit
  method rmdir : Netfs.rmdir_flag list -> string -> unit
  method size : Netfs.size_flag list -> string -> int64
  method symlink : Netfs.symlink_flag list -> string -> string -> unit
  method test : Netfs.test_flag list -> string -> Netfs.test_type -> bool
  method test_list :
    Netfs.test_flag list -> string -> Netfs.test_type list -> bool list
  method translate : string -> string
  method write :
    Nethttp_fs.write_flag list -> string -> Netchannels.out_obj_channel
  method write_file :
    Nethttp_fs.write_file_flag list -> string -> Netfs.local_file -> unit
end
ocamlnet-4.1.2/doc/html-main/Uq_transfer.async_in_channel_engine-c.html0000644000175000017500000004253312731530353024626 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.async_in_channel_engine

Class type Uq_transfer.async_in_channel_engine

class type async_in_channel_engine = object .. end
Combination of engine + async_in_channel
Inherits
ocamlnet-4.1.2/doc/html-main/type_Netcgi_apache.Apache.html0000644000175000017500000014732712731530353022240 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache sig
  module Table :
    sig
      type t
      external get : Netcgi_apache.Apache.Table.t -> string -> string
        = "netcgi2_apache_table_get"
      external get_all :
        Netcgi_apache.Apache.Table.t -> string -> string list
        = "netcgi2_apache_table_get_all"
      external fields :
        Netcgi_apache.Apache.Table.t -> (string * string) list
        = "netcgi2_apache_table_fields"
      external clear : Netcgi_apache.Apache.Table.t -> unit
        = "netcgi2_apache_table_clear"
      external set : Netcgi_apache.Apache.Table.t -> string -> string -> unit
        = "netcgi2_apache_table_set"
      external add : Netcgi_apache.Apache.Table.t -> string -> string -> unit
        = "netcgi2_apache_table_add"
      external unset : Netcgi_apache.Apache.Table.t -> string -> unit
        = "netcgi2_apache_table_unset"
    end
  module Server :
    sig
      type t
      external hostname : Netcgi_apache.Apache.Server.t -> string
        = "netcgi2_apache_server_hostname"
      external admin : Netcgi_apache.Apache.Server.t -> string
        = "netcgi2_apache_server_admin"
      external is_virtual : Netcgi_apache.Apache.Server.t -> bool
        = "netcgi2_apache_server_is_virtual"
    end
  module Connection :
    sig
      type t
      external remote_ip : Netcgi_apache.Apache.Connection.t -> string
        = "netcgi2_apache_connection_remote_ip"
      external remote_host : Netcgi_apache.Apache.Connection.t -> string
        = "netcgi2_apache_connection_remote_host"
    end
  module Request :
    sig
      type t
      external connection :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Connection.t
        = "netcgi2_apache_request_connection"
      external server :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Server.t
        = "netcgi2_apache_request_server"
      external next :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Request.t
        = "netcgi2_apache_request_next"
      external prev :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Request.t
        = "netcgi2_apache_request_prev"
      external main :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Request.t
        = "netcgi2_apache_request_main"
      external the_request : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_the_request"
      external assbackwards : Netcgi_apache.Apache.Request.t -> bool
        = "netcgi2_apache_request_assbackwards"
      external header_only : Netcgi_apache.Apache.Request.t -> bool
        = "netcgi2_apache_request_header_only"
      external protocol : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_protocol"
      external proto_num : Netcgi_apache.Apache.Request.t -> int
        = "netcgi2_apache_request_proto_num"
      external hostname : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_hostname"
      external request_time : Netcgi_apache.Apache.Request.t -> float
        = "netcgi2_apache_request_request_time"
      external status_line : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_status_line"
      external set_status_line :
        Netcgi_apache.Apache.Request.t -> string -> unit
        = "netcgi2_apache_request_set_status_line"
      external status : Netcgi_apache.Apache.Request.t -> int
        = "netcgi2_apache_request_status"
      external set_status : Netcgi_apache.Apache.Request.t -> int -> unit
        = "netcgi2_apache_request_set_status"
      external method_name : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_method"
      val method_number :
        Netcgi_apache.Apache.Request.t ->
        [ `CONNECT
        | `COPY
        | `DELETE
        | `GET
        | `INVALID
        | `LOCK
        | `MKCOL
        | `MOVE
        | `OPTIONS
        | `PATCH
        | `POST
        | `PROPFIND
        | `PROPPATCH
        | `PUT
        | `TRACE
        | `UNLOCK ]
      external headers_in :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
        = "netcgi2_apache_request_headers_in"
      external headers_out :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
        = "netcgi2_apache_request_headers_out"
      external err_headers_out :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
        = "netcgi2_apache_request_err_headers_out"
      external subprocess_env :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
        = "netcgi2_apache_request_subprocess_env"
      external notes :
        Netcgi_apache.Apache.Request.t -> Netcgi_apache.Apache.Table.t
        = "netcgi2_apache_request_notes"
      external content_type : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_content_type"
      external set_content_type :
        Netcgi_apache.Apache.Request.t -> string -> unit
        = "netcgi2_apache_request_set_content_type"
      external uri : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_uri"
      external port : Netcgi_apache.Apache.Request.t -> int
        = "netcgi2_apache_request_port"
      external set_uri : Netcgi_apache.Apache.Request.t -> string -> unit
        = "netcgi2_apache_request_set_uri"
      external filename : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_filename"
      external set_filename :
        Netcgi_apache.Apache.Request.t -> string -> unit
        = "netcgi2_apache_request_set_filename"
      external path_info : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_path_info"
      external set_path_info :
        Netcgi_apache.Apache.Request.t -> string -> unit
        = "netcgi2_apache_request_set_path_info"
      external args : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_args"
      external set_args : Netcgi_apache.Apache.Request.t -> string -> unit
        = "netcgi2_apache_request_set_args"
      external finfo : Netcgi_apache.Apache.Request.t -> Unix.stats option
        = "netcgi2_apache_request_finfo"
      type read_policy =
          NO_BODY
        | CHUNKED_ERROR
        | CHUNKED_DECHUNK
        | CHUNKED_PASS
      val setup_client_block :
        Netcgi_apache.Apache.Request.t ->
        Netcgi_apache.Apache.Request.read_policy -> unit
      external should_client_block : Netcgi_apache.Apache.Request.t -> bool
        = "netcgi2_apache_request_should_client_block"
      val get_client_block : Netcgi_apache.Apache.Request.t -> string
      val get_client_block_buf :
        Netcgi_apache.Apache.Request.t -> Bytes.t -> int -> int -> int
      val discard_request_body : Netcgi_apache.Apache.Request.t -> unit
      external user : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_request_user"
      external auth_type : Netcgi_apache.Apache.Request.t -> string
        = "netcgi2_apache_auth_type"
      external note_auth_failure : Netcgi_apache.Apache.Request.t -> unit
        = "netcgi2_apache_request_note_auth_failure"
      external note_basic_auth_failure :
        Netcgi_apache.Apache.Request.t -> unit
        = "netcgi2_apache_request_note_basic_auth_failure"
      external note_digest_auth_failure :
        Netcgi_apache.Apache.Request.t -> unit
        = "netcgi2_apache_request_note_digest_auth_failure"
      val get_basic_auth_pw : Netcgi_apache.Apache.Request.t -> string option
      external internal_redirect :
        string -> Netcgi_apache.Apache.Request.t -> unit
        = "netcgi2_apache_request_internal_redirect"
      external internal_redirect_handler :
        string -> Netcgi_apache.Apache.Request.t -> unit
        = "netcgi2_apache_request_internal_redirect_handler"
      external send_http_header : Netcgi_apache.Apache.Request.t -> unit
        = "netcgi2_apache_request_send_http_header"
      val rflush : Netcgi_apache.Apache.Request.t -> unit
      external print_char : Netcgi_apache.Apache.Request.t -> char -> unit
        = "netcgi2_apache_request_print_char"
      val print_string : Netcgi_apache.Apache.Request.t -> string -> unit
      val output :
        Netcgi_apache.Apache.Request.t -> Bytes.t -> int -> int -> int
      val print_int : Netcgi_apache.Apache.Request.t -> int -> unit
      val print_float : Netcgi_apache.Apache.Request.t -> float -> unit
      val print_newline : Netcgi_apache.Apache.Request.t -> unit
      val print_endline : Netcgi_apache.Apache.Request.t -> string -> unit
      external register_cleanup :
        Netcgi_apache.Apache.Request.t -> (unit -> unit) -> unit
        = "netcgi2_apache_request_register_cleanup"
    end
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.SCRAM_SHA1_PLUS.html0000644000175000017500000004067112731530353024415 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM_SHA1_PLUS Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/Netgzip.inflating_pipe-c.html0000644000175000017500000004233712731530353022127 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.inflating_pipe

Class Netgzip.inflating_pipe

class inflating_pipe : unit -> Netchannels.io_obj_channel
An inflating (uncompressing) pipe for gzip data, to be used in filters

ocamlnet-4.1.2/doc/html-main/Netsys_win32.Debug.html0000644000175000017500000004241512731530353020631 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_win32.Debug

Module Netsys_win32.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of the Ocaml wrapper
val debug_c_wrapper : bool -> unit
Sets whether to debug the C wrapper part. The debug messages are simply written to stderr
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.create_full_info.html0000644000175000017500000004151112731530353024647 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.create_full_info response_status_code:int ->
request_body_rejected:bool ->
output_header:Nethttp.http_header ->
output_body_size:int64 ->
Nethttpd_types.request_info -> Nethttpd_types.full_info
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.modify_http_engine_config.html0000644000175000017500000004310012731530353026644 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.modify_http_engine_config ?modify_http_protocol_config:(Nethttpd_kernel.http_protocol_config ->
                              Nethttpd_kernel.http_protocol_config) ->
?modify_http_processor_config:(Nethttpd_reactor.http_processor_config ->
                               Nethttpd_reactor.http_processor_config) ->
?config_input_flow_control:bool ->
?config_output_flow_control:bool ->
Nethttpd_engine.http_engine_config -> Nethttpd_engine.http_engine_config
ocamlnet-4.1.2/doc/html-main/type_Netcamlbox.html0000644000175000017500000005756412731530353020445 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcamlbox sig
  type camlbox_address = string
  type 'a camlbox
  type 'a camlbox_sender
  exception Empty
  exception Message_too_big
  val create_camlbox :
    Netcamlbox.camlbox_address -> int -> int -> 'Netcamlbox.camlbox
  val unlink_camlbox : Netcamlbox.camlbox_address -> unit
  val format_camlbox :
    Netcamlbox.camlbox_address ->
    Unix.file_descr -> int -> int -> 'Netcamlbox.camlbox
  val camlbox_addr : 'Netcamlbox.camlbox -> Netcamlbox.camlbox_address
  val camlbox_saddr :
    'Netcamlbox.camlbox_sender -> Netcamlbox.camlbox_address
  val camlbox_fd : Netcamlbox.camlbox_address -> Unix.file_descr
  val camlbox_capacity : Netcamlbox.camlbox_address -> int
  val camlbox_bcapacity : 'Netcamlbox.camlbox -> int
  val camlbox_scapacity : 'Netcamlbox.camlbox_sender -> int
  val camlbox_msg_size : Netcamlbox.camlbox_address -> int
  val camlbox_bmsg_size : 'Netcamlbox.camlbox -> int
  val camlbox_smsg_size : 'Netcamlbox.camlbox_sender -> int
  val camlbox_messages : Netcamlbox.camlbox_address -> int
  val camlbox_bmessages : 'Netcamlbox.camlbox -> int
  val camlbox_smessages : 'Netcamlbox.camlbox_sender -> int
  val camlbox_get : 'Netcamlbox.camlbox -> int -> 'a
  val camlbox_get_copy : 'Netcamlbox.camlbox -> int -> 'a
  val camlbox_delete : 'Netcamlbox.camlbox -> int -> unit
  val camlbox_wait : 'Netcamlbox.camlbox -> int list
  val camlbox_cancel_wait : 'Netcamlbox.camlbox -> unit
  val camlbox_sender :
    Netcamlbox.camlbox_address -> 'Netcamlbox.camlbox_sender
  val camlbox_sender_of_fd :
    Netcamlbox.camlbox_address ->
    Unix.file_descr -> 'Netcamlbox.camlbox_sender
  val camlbox_send :
    ?prefer:int ->
    ?slot:int Pervasives.ref -> 'Netcamlbox.camlbox_sender -> '-> unit
  val camlbox_wake : 'Netcamlbox.camlbox_sender -> unit
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Netulex.ULB.html0000644000175000017500000005726212731530353020411 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netulex.ULB sig
  type unicode_lexbuf = private {
    mutable ulb_encoding : Netconversion.encoding;
    mutable ulb_encoding_start : int;
    mutable ulb_rawbuf : Bytes.t;
    mutable ulb_rawbuf_len : int;
    mutable ulb_rawbuf_end : int;
    mutable ulb_rawbuf_const : bool;
    mutable ulb_chars : int array;
    mutable ulb_chars_pos : int array;
    mutable ulb_chars_len : int;
    mutable ulb_eof : bool;
    mutable ulb_refill : Bytes.t -> int -> int -> int;
    mutable ulb_enc_change_hook : Netulex.ULB.unicode_lexbuf -> unit;
    mutable ulb_cursor : Bytes.t Netconversion.poly_cursor;
  }
  val from_function :
    ?raw_size:int ->
    ?char_size:int ->
    ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
    refill:(Bytes.t -> int -> int -> int) ->
    Netconversion.encoding -> Netulex.ULB.unicode_lexbuf
  val from_in_obj_channel :
    ?raw_size:int ->
    ?char_size:int ->
    ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
    Netconversion.encoding ->
    Netchannels.in_obj_channel -> Netulex.ULB.unicode_lexbuf
  val from_string :
    ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
    Netconversion.encoding -> string -> Netulex.ULB.unicode_lexbuf
  val from_bytes :
    ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
    Netconversion.encoding -> Bytes.t -> Netulex.ULB.unicode_lexbuf
  val from_bytes_inplace :
    ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
    Netconversion.encoding -> Bytes.t -> Netulex.ULB.unicode_lexbuf
  val delete : int -> Netulex.ULB.unicode_lexbuf -> unit
  val refill : Netulex.ULB.unicode_lexbuf -> unit
  val set_encoding :
    Netconversion.encoding -> Netulex.ULB.unicode_lexbuf -> unit
  val close : Netulex.ULB.unicode_lexbuf -> unit
  val utf8_sub_string : int -> int -> Netulex.ULB.unicode_lexbuf -> string
  val utf8_sub_string_length :
    int -> int -> Netulex.ULB.unicode_lexbuf -> int
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.sync_engine.html0000644000175000017500000004152112731530353024273 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.sync_engine '#Uq_engines_compat.engine ->
'#Uq_engines_compat.engine -> ['a * 'b] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/Netplex_types.netplex_config-c.html0000644000175000017500000004363112731530353023364 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.netplex_config

Class type Netplex_types.netplex_config

class type netplex_config = object .. end

method ptype : parallelization_type
method controller_config : controller_config
method services : (socket_service_config *
(address * processor_factory) *
(address * workload_manager_factory))
list
ocamlnet-4.1.2/doc/html-main/type_Netsys_oothr.thread.html0000644000175000017500000004121712731530353022303 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr.thread object method id : int method join : unit -> unit method repr : exn endocamlnet-4.1.2/doc/html-main/type_Netgzip.output_gzip.html0000644000175000017500000004074712731530353022354 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.output_gzip Gzip.out_channel -> Netchannels.out_obj_channelocamlnet-4.1.2/doc/html-main/Netchannels.rec_in_channel_delegation-c.html0000644000175000017500000004246512731530353025105 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.rec_in_channel_delegation

Class Netchannels.rec_in_channel_delegation

class rec_in_channel_delegation : ?close:bool -> rec_in_channel -> rec_in_channel

ocamlnet-4.1.2/doc/html-main/Netgss.System.html0000644000175000017500000004755012731530353020030 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgss.System

Module Netgss.System

module System: Netsys_gssapi.GSSAPI 
This is the system-wide version of GSSAPI


The General Security Services API

The General Security Services API

See also Netsys_gssapi for additional type definitions
type credential 
A credential is opaque for the caller of the GSS-API. The provider of the GSS-API can emit new credential objects, and hand them out to the caller.
type context 
A context is also opaque.
type name 
A name is also opaque

Exceptions



Exceptions



There are no defined exceptions for reporting errors.

Errors should be reported using the major_status and minor_status codes as much as possible.

Invalid_argument may be raised for clear violations of calling requirements, e.g. when an opaque object is passed to this interface that was not returned by it before.

The following three exceptions can be used to wrap the per-GSSAPI types credential, context, and name:

exception Credential of credential
exception Context of context
exception Name of name

The API


class type gss_api = [[credential, name
, context]]
Netsys_gssapi.poly_gss_api
The methods have generally a type of the form
val interface : gss_api
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.request_info-c.html0000644000175000017500000004655012731530353023241 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.request_info

Class type Nethttpd_types.request_info

class type request_info = object .. end

method server_socket_addr : Unix.sockaddr
The socket address of this server. May raise Not_found if there is no such address
method remote_socket_addr : Unix.sockaddr
The socket address of the client. May raise Not_found if there is no such address
method request_method : string
The method like GET. May raise Not_found
method request_uri : string
The URI of the client request. This is often without the server designation, i.e. just /path?query. May raise Not_found
method input_header : Nethttp.http_header
The request header. May raise Not_found
method cgi_properties : (string * string) list
The distilled CGI properties
method input_body_size : int64
The size of the input body. May raise Not_found
method tls_session_props : Nettls_support.tls_session_props option
The TLS properties
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.seq_engine-c.html0000644000175000017500000004257212731530353023275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.seq_engine

Class Uq_engines_compat.seq_engine

class [['a, 'b]] seq_engine : 'a #engine -> ('a -> 'b #engine) -> ['b] engine

ocamlnet-4.1.2/doc/html-main/type_Netftp_data_endpoint.data_converter.html0000644000175000017500000004121612731530353025464 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.data_converter fromrepr:Netftp_data_endpoint.text_data_repr ->
torepr:Netftp_data_endpoint.text_data_repr -> Netchannels.io_obj_channel
ocamlnet-4.1.2/doc/html-main/type_Netchannels.rec_out_channel.html0000644000175000017500000004167412731530353023735 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.rec_out_channel object
  method close_out : unit -> unit
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
end
ocamlnet-4.1.2/doc/html-main/Netftp_data_endpoint.data_converter-c.html0000644000175000017500000004361612731530353024651 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.data_converter

Class Netftp_data_endpoint.data_converter

class data_converter : fromrepr:text_data_repr -> torepr:text_data_repr -> Netchannels.io_obj_channel
Creates a data conversion pipe converting fromrepr to torepr.

For simplicity, in an `ASCII input stream the CR characters are discarded, and the LF characters are taken as newline characters. In an output `ASCII stream, the CR/LF sequence is correctly created for newline characters.


ocamlnet-4.1.2/doc/html-main/type_Nettls_support.tls_session_props.html0000644000175000017500000004376412731530353025202 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_support.tls_session_props object
  method addressed_server : string option
  method cipher_algo : string
  method cipher_suite_type : string
  method compression_algo : string
  method endpoint_credentials : Nettls_support.credentials
  method endpoint_credentials_raw : Nettls_support.raw_credentials
  method endpoint_credentials_type : Nettls_support.cred_type
  method id : string
  method kx_algo : string
  method mac_algo : string
  method peer_credentials : Nettls_support.credentials
  method peer_credentials_raw : Nettls_support.raw_credentials
  method peer_credentials_type : Nettls_support.cred_type
  method protocol : string
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.raw_io_channel.html0000644000175000017500000004277012731530353023553 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_io_channel object
  method close_in : unit -> unit
  method close_out : unit -> unit
  method flush : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method output : Bytes.t -> int -> int -> int
  method pos_in : int
  method pos_out : int
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_polypipe.html0000644000175000017500000005055412731530353021547 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_polypipe sig
  exception Closed
  type 'a polypipe
  val create :
    int -> 'Netsys_polypipe.polypipe * 'Netsys_polypipe.polypipe
  val length : 'Netsys_polypipe.polypipe -> int
  val eof : 'Netsys_polypipe.polypipe -> bool
  val read : nonblock:bool -> 'Netsys_polypipe.polypipe -> 'a option
  val write :
    nonblock:bool -> 'Netsys_polypipe.polypipe -> 'a option -> unit
  val close : 'Netsys_polypipe.polypipe -> unit
  val set_read_notify : 'Netsys_polypipe.polypipe -> (unit -> unit) -> unit
  val set_write_notify :
    'Netsys_polypipe.polypipe -> (unit -> unit) -> unit
  val read_descr : 'Netsys_polypipe.polypipe -> Unix.file_descr
  val write_descr : 'Netsys_polypipe.polypipe -> Unix.file_descr
  val set_exception : 'Netsys_polypipe.polypipe -> exn -> unit
  val get_exception : 'Netsys_polypipe.polypipe -> exn option
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Netencoding.QuotedPrintable.decoding_pipe.html0000644000175000017500000004070512731530353026464 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.QuotedPrintable.decoding_pipe unit -> Netchannels.pipeocamlnet-4.1.2/doc/html-main/Netplex_sockserv.html0000644000175000017500000004653012731530353020635 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sockserv

Module Netplex_sockserv

module Netplex_sockserv: sig .. end
Socket service creation

A socket service object is an encapsulation of a user-defined processor for a list of sockets.


val create_socket_service : Netplex_types.processor ->
Netplex_types.socket_service_config -> Netplex_types.socket_service
Create the socket service (usually only internally used)
val create_server_socket : string ->
Netplex_types.protocol -> Netplex_types.extended_address -> Unix.file_descr
create_server_socket service_name proto addr: Creates a server socket as specified in proto for the address addr and returns it.

Addresses of type `Container are not supported.

val close_server_socket : Unix.file_descr -> unit
Closes a socket as opened with create_server_socket
val any_file_client_connector : string -> Rpc_client.connector
Interprets a file name as connector for a local RPC service. The file must either be a Unix Domain socket, or it must be a text file as written by Netplex with the details of the service endpoint.
val client_connector : Netplex_types.extended_address -> Rpc_client.connector
Returns the RPC client connector for this Netplex address
ocamlnet-4.1.2/doc/html-main/Netcgi.Cookie.html0000644000175000017500000006722712731530353017726 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.Cookie

Module Netcgi.Cookie

module Cookie: sig .. end
Functions to manipulate cookies.

You should know that besides the name and value attribute, user agents will send at most the path, domain and port and usually will not send them at all.

For interoperability, cookies are set using version 0 (by Netscape) unless version 1 (RFC 2965 and the older RFC 2109) fields are set. While version 0 is well supported by browsers, RFC 2109 requires a recent browser and RFC 2965 is usually not supported. You do not have to worry however, cookies are always sent in such a way older browsers understand them -- albeit not all attributes of course -- so your application can be ready for the time RFC 2965 will be the norm.

N.B. This module appears also as Nethttp.Cookie.


type t = Nethttp.Cookie.t 
Mutable cookie type.
val make : ?max_age:int ->
?domain:string ->
?path:string ->
?secure:bool ->
?comment:string ->
?comment_url:string -> ?ports:int list -> string -> string -> t
make ?expires ?domain ?path ?secure name value creates a new cookie with name name holding value.
max_age : see Netcgi.Cookie.set_max_age. Default: when user agent exits.
domain : see Netcgi.Cookie.set_domain. Default: hostname of the server.
path : see Netcgi.Cookie.set_path. Default: script name + path_info.
secure : see Netcgi.Cookie.set_secure. Default: false.
comment : see Netcgi.Cookie.set_comment. Default: "".
comment_url : see Netcgi.Cookie.set_comment_url. Default: "".
ports : see Netcgi.Cookie.set_ports. Default: same port the cookie was sent.
val name : t -> string
The name of the cookie.
val value : t -> string
The value of the cookie.
val domain : t -> string option
The domain of the cookie, if set.
val path : t -> string option
The path of the cookie, if set.
val ports : t -> int list option
port c the ports to which the cookie may be returned or [] if not set.
val max_age : t -> int option
The expiration time of the cookie, in seconds. None means that the cookie will be discarded when the browser exits. This information is not returned by the browser.
val secure : t -> bool
Tells whether the cookie is secure. This information is not returned by the browser.
val comment : t -> string
Returns the comment associated to the cookie or "" if it does not exists. This information is not returned by the browser.
val comment_url : t -> string
Returns the comment URL associated to the cookie or "" if it does not exists. This information is not returned by the browser.
val set_value : t -> string -> unit
set_value c v sets the value of the cookie c to v.
val set_max_age : t -> int option -> unit
set_max_age c (Some t) sets the lifetime of the cookie c to t seconds. If t <= 0, it means that the cookie should be discarded immediately. set_expires c None tells the cookie to be discarded when the user agent exits. (Despite the fact that the name is borrowed from the version 1 of the specification, it works transparently with version 0.)
val set_domain : t -> string option -> unit
Cookies are bound to a certain domain, i.e. the browser sends them only when web pages of the domain are requested:
  • None: the domain is the hostname of the server.
  • Some domain: the domain is domain.

val set_path : t -> string option -> unit
Cookies are also bound to certain path prefixes, i.e. the browser sends them only when web pages at the path or below are requested.
  • None: the path is script name + path_info
  • Some p: the path is p. With Some "/" you can disable the path restriction completely.

val set_secure : t -> bool -> unit
Cookies are also bound to the type of the web server: set_secure false means servers without SSL, set_secure true means servers with activated SSL ("https").
val set_comment : t -> string -> unit
set_comment c s sets the comment of the cookie c to s which must be UTF-8 encoded (RFC 2279). Because cookies can store personal information, the comment should describe how the cookie will be used so the client can decide whether to allow the cookie or not. To cancel a comment, set it to "".

Cookie version 1 (RFC 2109).

val set_comment_url : t -> string -> unit
set_comment_url c url same as Netcgi.Cookie.set_comment except that the cookie comment is available on the page pointed by url. To cancel, set it to "".

Cookie version 1 (RFC 2965).

val set_ports : t -> int list option -> unit
set ports c (Some p) says that the cookie c must only be returned if the server request comes from one of the listed ports. If p = [], the cookie will only be sent to the request-port it was received from. set_ports c None says that the cookie may be sent to any port.

Cookie version 1 (RFC 2965).

val of_netscape_cookie : Nethttp.netscape_cookie -> t
Convert a Netscape cookie to the new representation
val to_netscape_cookie : t -> Nethttp.netscape_cookie
Convert to Netscape cookie (with information loss)
ocamlnet-4.1.2/doc/html-main/Netsys_gssapi.server_props-c.html0000644000175000017500000004521612731530353023102 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.server_props

Class type Netsys_gssapi.server_props

class type server_props = object .. end
Return properties of the server context

method mech_type : oid
Actual mechanism
method flags : ret_flag list
Actual flags
method time : time
Actual context lifetime
method initiator_name : string * oid
The name of the initiator. string and oid may be empty
method initiator_name_exported : string
The name of the initiator in exported format
method deleg_credential : (exn * time) option
If a credential was delegated it is returned here as (e,t). e is the exception G.Credential from the GSSAPI provider.
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.auth_handler.html0000644000175000017500000004602112731530353023754 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.auth_handler object
  method create_proxy_session :
    Nethttp_client.http_call ->
    Nethttp_client.http_options Pervasives.ref ->
    Nethttp_client.auth_session option
  method create_session :
    secure:bool ->
    Nethttp_client.http_call ->
    Nethttp_client.http_options Pervasives.ref ->
    Nethttp_client.auth_session option
  method identify_proxy_session :
    Nethttp_client.http_call ->
    Nethttp_client.http_options Pervasives.ref ->
    (string * string * string * int) option
  method identify_session :
    Nethttp_client.http_call ->
    Nethttp_client.http_options Pervasives.ref ->
    (string * string * string * int) option
  method skip_challenge : bool
  method skip_challenge_session :
    Nethttp_client.http_call ->
    Nethttp_client.http_options Pervasives.ref ->
    Nethttp_client.auth_session option
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_client.auth_protocol.html0000644000175000017500000004436112731530353023303 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.auth_protocol object
  method auth_method : Rpc_client.auth_method
  method destroy : unit -> unit
  method emit :
    Netnumber.uint4 ->
    Netnumber.uint4 -> Netnumber.uint4 -> Rpc_packer.packed_value
  method gssapi_props : Netsys_gssapi.client_props option
  method receive : Rpc_packer.packed_value -> unit
  method state :
    [ `Done of Rpc_client.auth_session
    | `Emit
    | `Error
    | `Receive of Netnumber.uint4 ]
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp.HTTP_CLIENT_MECHANISM.html0000644000175000017500000005741012731530353023165 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.HTTP_CLIENT_MECHANISM sig
  val mechanism_name : string
  val available : unit -> bool
  val restart_supported : bool
  type credentials
  val init_credentials :
    (string * string * (string * string) list) list ->
    Nethttp.HTTP_CLIENT_MECHANISM.credentials
  val client_match :
    params:(string * string * bool) list ->
    Nethttp.Header.auth_challenge -> Nethttp.match_result
  type client_session
  val client_state :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
    Netsys_sasl_types.client_state
  val create_client_session :
    user:string ->
    creds:Nethttp.HTTP_CLIENT_MECHANISM.credentials ->
    params:(string * string * bool) list ->
    unit -> Nethttp.HTTP_CLIENT_MECHANISM.client_session
  val client_configure_channel_binding :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
    Netsys_sasl_types.cb -> Nethttp.HTTP_CLIENT_MECHANISM.client_session
  val client_restart :
    params:(string * string * bool) list ->
    Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
    Nethttp.HTTP_CLIENT_MECHANISM.client_session
  val client_process_challenge :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
    string ->
    string ->
    #Nethttp.http_header_ro ->
    Nethttp.Header.auth_challenge ->
    Nethttp.HTTP_CLIENT_MECHANISM.client_session
  val client_emit_response :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
    string ->
    string ->
    #Nethttp.http_header_ro ->
    Nethttp.HTTP_CLIENT_MECHANISM.client_session *
    Nethttp.Header.auth_credentials * (string * string) list
  val client_channel_binding :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session -> Netsys_sasl_types.cb
  val client_user_name :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string
  val client_stash_session :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string
  val client_resume_session :
    string -> Nethttp.HTTP_CLIENT_MECHANISM.client_session
  val client_session_id :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string option
  val client_domain :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string list
  val client_prop :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session -> string -> string
  val client_gssapi_props :
    Nethttp.HTTP_CLIENT_MECHANISM.client_session ->
    Netsys_gssapi.client_props
end
ocamlnet-4.1.2/doc/html-main/Crypto.html0000644000175000017500000005430612731530353016557 0ustar gerdgerd Ocamlnet 4 Reference Manual : Crypto

Crypto


Cryptography

OCamlnet-4 does not include any implementations of cryptographic ciphers or hashes. It does, however, include a binding to GnuTLS and GNU Nettle, providing cryptography, and it defines a number of helper functions to use cryptography efficiently.

Before OCamlnet-4, some modules used Xavier Leroy's Cryptokit. This dependency is gone now.

Cryptography providers

Like for TLS (see Tls), first-class modules are used to modularize the provider of the crypto functions:

There are default providers:

If not initialized, these providers are empty, i.e. the lists of available ciphers and digests are empty. This can be changed by initializing a provider. So far, there is only GnuTLS/Nettle, and you can enable this by

  • linking with the package nettls-gnutls
  • calling Nettls_gnutls.init()

Using cryptography

It is not advised to call any functions of the providers directly: the API is not yet stable, and may change, and there are some inconveniences in the buffer management. Instead, use the following functionality:

Examples

Encrypt a string s with AES-128 in CBC mode and length-style padding:

let key = "0123456789abcdef"
let iv = "0123456789abcdef"
let cipher = Netsys_ciphers.find ("AES-128", "CBC")
let ctx = cipher # create key `Length
let () = ctx # set_iv iv
let s_enc = ctx # encrypt_string s

Compute the SHA1 digest of a string s:

let digest = Netsys_digests.find "SHA1-160"
let ctx = digest # create()
let () = ctx # add_substring s 0 (String.length s)
let result = ctx # finish()

Supported ciphers

If using nettls-gnutls as provider, you can normally expect:

  • AES (key sizes: 128, 192, 256)
  • ARCFOUR (key size: 128) . RC2 (key sizes: 40, 64, 128)
  • BLOWFISH (key size variable)
  • CAMELLIA (key sizes: 128, 192, 256)
  • CAST (key size: 128)
  • DES (key size: 56)
  • 3DES (key size: 112)
  • SERPENT (key sizes: 128, 192, 256)
  • TWOFISH (key sizes: 128, 192, 256)
All ciphers are supported in ECB, CBC, CTR, and OFB modes.

If using a recent version of GnuTLS/Nettls:

  • AES in CBC mode is accelerated if the CPU supports it (Intel AES-NI, or VIA Padlock)
  • AES in GCM mode, also with an acceleration option
  • CAMELLIA in GCM mode

Supported digests

If using nettls-gnutls as provider, you can normally expect:

  • MD2
  • MD4
  • MD5
  • SHA1
  • SHA2-256
If using a recent version of GnuTLS/Nettls:

  • SHA2 with block sizes 224, 256, 384 and 512 bits
  • SHA3 with block sizes 224, 256, 384 and 512 bits
  • RIPEMD (160 bits)
  • GOSTHASH94 (256 bits)

Supported public key ciphers

You can normally use for encryption:

  • RSA
You can use for signing:

  • RSA
  • DSA
  • ECDSA
Currently, there isn't an interface for key agreement yet, so all Diffie-Hellman variants are out of reach at the moment.
ocamlnet-4.1.2/doc/html-main/type_Rpc_portmapper_clnt.Make'PMAP.V4.html0000644000175000017500000007523012731530353024245 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt.Make'PMAP.V4 sig
  type t = U'C.t
  val _program : Rpc_program.t
  val rpcbproc_null :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res
  val rpcbproc_null'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res) -> unit) ->
    unit
  val rpcbproc_set :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res
  val rpcbproc_set'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res) -> unit) -> unit
  val rpcbproc_unset :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res
  val rpcbproc_unset'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res) -> unit) ->
    unit
  val rpcbproc_getaddr :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res
  val rpcbproc_getaddr'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res) -> unit) ->
    unit
  val rpcbproc_dump :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res
  val rpcbproc_dump'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res) -> unit) ->
    unit
  val rpcbproc_bcast :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res
  val rpcbproc_bcast'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res) -> unit) ->
    unit
  val rpcbproc_gettime :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res
  val rpcbproc_gettime'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res) -> unit) ->
    unit
  val rpcbproc_uaddr2taddr :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res
  val rpcbproc_uaddr2taddr'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res) -> unit) ->
    unit
  val rpcbproc_taddr2uaddr :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res
  val rpcbproc_taddr2uaddr'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res) -> unit) ->
    unit
  val rpcbproc_getversaddr :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res
  val rpcbproc_getversaddr'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res) -> unit) ->
    unit
  val rpcbproc_indirect :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res
  val rpcbproc_indirect'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res) -> unit) ->
    unit
  val rpcbproc_getaddrlist :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res
  val rpcbproc_getaddrlist'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res) -> unit) ->
    unit
  val rpcbproc_getstat :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res
  val rpcbproc_getstat'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res) -> unit) ->
    unit
end
ocamlnet-4.1.2/doc/html-main/Netglob.of_stream_fs-c.html0000644000175000017500000004174612731530353021563 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.of_stream_fs

Class Netglob.of_stream_fs

class of_stream_fs : #Netfs.stream_fs -> glob_fsys

ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.TLS_PROVIDER.Exc.html0000644000175000017500000004544012731530353024100 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_PROVIDER.Exc

Module Netsys_crypto_types.TLS_PROVIDER.Exc

module Exc: Netsys_crypto_types.TLS_EXCEPTIONS 
Access to exceptions

exception EAGAIN_RD
exception EAGAIN_WR
A read or write cannot be done because the descriptor is in non-blocking mode and would block. This corresponds to the Unix.EAGAIN error but includes whether it was a read or write.

When the read or write is possible, the interrupted function should simply be again called.

These two exceptions are preferred by TLS providers.

exception TLS_switch_request
The server requested a rehandshake (this exception is thrown in the client)
exception TLS_switch_response of bool
The client accepted or denied a rehandshake (this exception is thrown in the server). true means acceptance.
exception TLS_error of string
A fatal error occurred (i.e. the session needs to be terminated). The string is a symbol identifying the error.
exception TLS_warning of string
A non-fatal error occurred. The interrupted function should be called again. The string is a symbol identifying the warning.
ocamlnet-4.1.2/doc/html-main/Netnumber.LE.html0000644000175000017500000006441712731530353017541 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber.LE

Module Netnumber.LE

module LE: ENCDEC 
Encoders/decoders for little endian


Encode/decode numbers as strings. These functions exist in two flavors:
val read_int4 : Bytes.t -> int -> Netnumber.int4
val read_int8 : Bytes.t -> int -> Netnumber.int8
val read_uint4 : Bytes.t -> int -> Netnumber.uint4
val read_uint8 : Bytes.t -> int -> Netnumber.uint8
read_<t> create integer values from the characters found at a certain position in the string. Raises Out_of_range if the position is bad
val read_int4_unsafe : Bytes.t -> int -> Netnumber.int4
val read_int8_unsafe : Bytes.t -> int -> Netnumber.int8
val read_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4
val read_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8
Same, but no index check
val read_string_int4 : string -> int -> Netnumber.int4
val read_string_int8 : string -> int -> Netnumber.int8
val read_string_uint4 : string -> int -> Netnumber.uint4
val read_string_uint8 : string -> int -> Netnumber.uint8
val read_string_int4_unsafe : string -> int -> Netnumber.int4
val read_string_int8_unsafe : string -> int -> Netnumber.int8
val read_string_uint4_unsafe : string -> int -> Netnumber.uint4
val read_string_uint8_unsafe : string -> int -> Netnumber.uint8
For immutable strings
val write_int4 : Bytes.t -> int -> Netnumber.int4 -> unit
val write_int8 : Bytes.t -> int -> Netnumber.int8 -> unit
val write_uint4 : Bytes.t -> int -> Netnumber.uint4 -> unit
val write_uint8 : Bytes.t -> int -> Netnumber.uint8 -> unit
write_<t> copies the characters corresponding to the integer values into the string at the given positions. Raises Out_of_range if the position is bad.
val write_int4_unsafe : Bytes.t -> int -> Netnumber.int4 -> unit
val write_int8_unsafe : Bytes.t -> int -> Netnumber.int8 -> unit
val write_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4 -> unit
val write_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8 -> unit
write_<t>_unsafe: Same, but no index check.
val int4_as_bytes : Netnumber.int4 -> Bytes.t
val int8_as_bytes : Netnumber.int8 -> Bytes.t
val uint4_as_bytes : Netnumber.uint4 -> Bytes.t
val uint8_as_bytes : Netnumber.uint8 -> Bytes.t
<t>_as_bytes: Returns the corresponding bytes for an integer value
val int4_as_string : Netnumber.int4 -> string
val int8_as_string : Netnumber.int8 -> string
val uint4_as_string : Netnumber.uint4 -> string
val uint8_as_string : Netnumber.uint8 -> string
<t>_as_string: Returns the corresponding string for an integer value
val write_fp4 : Bytes.t -> int -> Netnumber.fp4 -> unit
val write_fp8 : Bytes.t -> int -> Netnumber.fp8 -> unit
val fp4_as_string : Netnumber.fp4 -> string
val fp8_as_string : Netnumber.fp8 -> string
val fp4_as_bytes : Netnumber.fp4 -> Bytes.t
val fp8_as_bytes : Netnumber.fp8 -> Bytes.t
val read_fp4 : Bytes.t -> int -> Netnumber.fp4
val read_fp8 : Bytes.t -> int -> Netnumber.fp8
val read_string_fp4 : string -> int -> Netnumber.fp4
val read_string_fp8 : string -> int -> Netnumber.fp8
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.v_extended_environment-c.html0000644000175000017500000005140312731530353025300 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.v_extended_environment

Class type virtual Nethttpd_types.v_extended_environment

class type virtual v_extended_environment = object .. end
An extension of cgi_environment for use with the daemon. The methods retrieving the socket addresses are virtual.
Inherits
method virtual server_socket_addr : Unix.sockaddr
method virtual remote_socket_addr : Unix.sockaddr
These are always the physical IP addresses and ports of the two endpoints of the current connection.
method cgi_request_uri : string
The full request URI. Identical to the CGI property "REQUEST_URI"
method log_props : (string * string) list -> unit
Remember this version of cgi_properties as the one sent to the config_log_access function
method input_channel : Netchannels.in_obj_channel
The input channel for reading the body of the request
method input_body_size : int64
so far known, or 0L
method request_body_rejected : bool
so far known, or false
method send_file : Unix.file_descr -> int64 -> unit
Sends the output header with a file as body. The file must already be open, and positioned where the transmission begins. The number is the length of the transmission.

This method may return immediately when it is possible to open the file, and to set the kernel up for file transmission. Otherwise a Unix_error is raised. It is also allowed that this method blocks until the file is actually transmitted.

It is not allowed to print to the output channel and to call send_file. Only one transmission method must be invoked.

method virtual output_state : output_state Pervasives.ref
Reflects the state of the output generation:
  • `Start: Nothing is generated yet
  • `Sending: Output is already being sent
  • `End: The response (for a single request) has been fully sent

method tls_session_props : Nettls_support.tls_session_props option
The TLS session properties if TLS is active
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.protocol.html0000644000175000017500000004256112731530353023043 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.protocol object
  method addresses : Netplex_types.extended_address array
  method configure_slave_socket : Unix.file_descr -> unit
  method local_chmod : int option
  method local_chown : (int * int) option
  method lstn_backlog : int
  method lstn_reuseaddr : bool
  method name : string
  method so_keepalive : bool
  method tcp_nodelay : bool
end
ocamlnet-4.1.2/doc/html-main/Netasn1.Value.html0000644000175000017500000013462412731530353017665 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netasn1.Value

Module Netasn1.Value

module Value: sig .. end

type pc = 
| Primitive
| Constructed
type value = 
| Bool of bool (*
Boolean (primitive)
*)
| Integer of int_value (*
Integer (primitive)
*)
| Enum of int_value (*
Enumeration (primitive)
*)
| Real of real_value (*
Floating-point number, using either base 2 or base 10 (primitive)
*)
| Bitstring of bitstring_value (*
Bit strings (primitive or constructed)
*)
| Octetstring of string (*
Octet strings (primitive or constructed)
*)
| Null (*
Null (primitive)
*)
| Seq of value list (*
Sequences (records or arrays) (constructed)
*)
| Set of value list (*
Sets (constructed)
*)
| Tagptr of tag_class * int * pc
* Netstring_tstring.tstring_polybox * int * int
(*
Pointer to an undecoded value that was implicitly tagged. The tag_class can be Application, Context, or Private.
*)
| Tag of tag_class * int * pc * value (*
Explicit tag (primitive or constructed depending on inner value)
*)
| ITag of tag_class * int * value (*
Implicit tag (never returned by the decoder, but needed for encoding such tags)
*)
| OID of int array
| ROID of int array
| ObjectDescriptor of string (*
A placeholder with a comment (primitive)
*)
| External of value list (*
Something complex I don't understand (constructed)
*)
| Embedded_PDV of value list (*
Something complex I don't understand (constructed)
*)
| NumericString of string (*
String made of digits and spaces (primitive or constructed)
*)
| PrintableString of string (*
A small subset of ASCII (primitive or constructed)
*)
| TeletexString of string
| VideotexString of string
| VisibleString of string (*
7 bit ASCII w/o control characters (primitive or constructed)
*)
| IA5String of string (*
7 bit ASCII (primitive or constructed)
*)
| GraphicString of string (*
ISO-2022-encoded string w/o control characters
*)
| GeneralString of string (*
ISO-2022-encoded string
*)
| UniversalString of string (*
Any ISO-10646-1 character string represented as UTF-32-BE (primitive or constructed). Roughly, ISO-10646-1 equals to Unicode.
*)
| BMPString of string (*
Any ISO-10646-1 character string from only the basic multilingual plane, i.e. with code points <= 65535, represented as UTF-16-BE (primitive or constructed)
*)
| UTF8String of string (*
Any ISO-10646-1 character string represented as UTF-8 (primitive or constructed)
*)
| CharString of string (*
A complicated description of an arbitrary charset encoding (primitive or constructed)
*)
| UTCTime of time_value (*
Like GeneralizedTime but less precise, and with 2-digit year
*)
| GeneralizedTime of time_value (*
Calendar date with time of day, including timezone (primitive)
*)
type tag_class = 
| Universal
| Application
| Context
| Private
type int_value 
type real_value 
type bitstring_value 
type time_value 
type time_subtype = [ `G | `U ] 
val type_of_value : value -> Netasn1.Type_name.type_name option
Returns the type, or None for Tag, ITag and Tagptr

Integer


val get_int_repr : int_value -> string
Get an integer as bytes
val get_int_b256 : int_value -> int array
Get an integer in base 256 notation, big endian. Negative values are represented using two's complement (i.e. the first array element is >= 128). The empty array means 0.
val get_int : int_value -> int
Get an integer as int if representable, or raise Out_of_range
val get_int32 : int_value -> int32
Get an integer as int32 if representable, or raise Out_of_range
val get_int64 : int_value -> int64
Get an integer as int64 if representable, or raise Out_of_range
val int : int -> int_value
Create an int
val int32 : int32 -> int_value
Create an int
val int64 : int64 -> int_value
Create an int
val int_b256 : int array -> int_value
Create an int from a base 256 number, big endian, signed

Real



Real



Reals are not really supported ;-(
val get_real_repr : real_value -> string
Get the byte representation of the real

Bitstring



Bitstring



In some contexts it is usual that trailing zero bits are truncated.
val get_bitstring_size : bitstring_value -> int
Get the number of bits
val get_bitstring_data : bitstring_value -> string
Get the data. The last byte may be partial. The order of the bits in every byte: bit 7 (MSB) contains the first bit
val get_bitstring_bits : ?size:int -> bitstring_value -> bool array
Get the bitstring as bool array. If size is specified the array will have exactly this number of bits (by dropping exceeding data, or by adding false at the end)
val get_bitstring_repr : bitstring_value -> string
Get the representation
val bitstring_of_bits : bool array -> bitstring_value
Get the bitstring from a bool array
val bitstring_of_string : string -> int -> bitstring_value
Get the bitstring from a string and the total number of bits. The bits are taken from the beginning of the string (MSB first). If the string is shorter than the number of bits suggests, the remaining bits are assumed to be zero. If the string is longer than the number of bits suggests, the exceeding data is ignored.
val truncate_trailing_zero_bits : bitstring_value -> bitstring_value
Truncates the biggest trailing part that only consist of 0 bits

Time



Time



Time values referring to the local time zone are not supported
val get_time_subtype : time_value -> time_subtype
Whether this is for UTCTime (`U) or GeneralizedTime (`G)
val get_time_repr : time_value -> string
Get the raw time string
val get_time : time_value -> Netdate.t
Get the time. Notes:

  • UTCTime years are two-digit years, and interpreted so that 0-49 is understood as 2000-2049, and 50-99 is understood as 1950-1999 (as required by X.509).
  • This function is restricted to the time formats occurring in DER (string terminates with "Z", i.e. UTC time zone)

val utctime : Netdate.t -> time_value
Create a time value for UTCTime. This function is restricted to years between 1950 and 2049.
val gentime : digits:int -> Netdate.t -> time_value
Create a time value for GeneralizedTime. digits is the number of fractional (subsecond) digits

Equality


val equal : value -> value -> bool
Checks for equality. Notes:

  • Tag and Tagptr are considered different
  • Tagptr is checked by comparing the equality of the substring
  • Set is so far not compared as set, but as sequence (i.e. order matters)

ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_gssapi.client_key_ring.html0000644000175000017500000004124512731530353025620 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_gssapi.client_key_ring object
  method default_user_name : string option
  method password_of_user_name : string -> string
end
ocamlnet-4.1.2/doc/html-main/Netplex_types.socket_service_config-c.html0000644000175000017500000004631412731530353024716 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.socket_service_config

Class type Netplex_types.socket_service_config

class type socket_service_config = object .. end

method name : string
The proposed name for the socket_service
method protocols : protocol list
This list describes the sockets to create in detail
method change_user_to : (int * int) option
Instructs the container to change the user of the process after starting the service. This is only possible in multi-processing mode. In multi-threading mode, this parameter is ignored.
method startup_timeout : float
After this many seconds the container must have finished the post_start_hook. It is usually 60 seconds.
method conn_limit : int option
An optional limit of the number of connections this container can accept. If the limit is reached, the container will not accept any further connections, and shut down when all connections are processed.
method gc_when_idle : bool
If set, idle containers run a Gc.full_major cycle.
method controller_config : controller_config
Make this config accessible here too, for convenience
ocamlnet-4.1.2/doc/html-main/Netglob.local_user_info-c.html0000644000175000017500000004167512731530353022260 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.local_user_info

Class Netglob.local_user_info

class local_user_info : unit -> user_info

ocamlnet-4.1.2/doc/html-main/type_Uq_engines.cache.html0000644000175000017500000004140312731530353021471 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.cache (Unixqueue.event_system -> 'Uq_engines.engine) ->
Unixqueue.event_system -> ['a] Uq_engines.cache_t
ocamlnet-4.1.2/doc/html-main/Nethttpd_engine.extended_async_environment-c.html0000644000175000017500000004632412731530353026257 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.extended_async_environment

Class type Nethttpd_engine.extended_async_environment

class type extended_async_environment = object .. end
Inherits
  • extended_environment

method input_ch_async : Uq_engines.async_in_channel
This is the input_ch channel taken as asynchonous channel. This type of channel indicates when data is available to read, and also sends notifications. Note that this is only an alternate interface of the input_ch object.

The method can_input returns true when there is at least one byte of the body to read, or the EOF has been seen. The channel buffers any arriving data (which can be limited in amount by config_pipeline_size).

The behaviour of this channel is influenced by the configuration option config_input_flow_control.

method output_ch_async : Uq_engines.async_out_channel
This is the output_ch channel taken as asynchronous channel. This type of channel indicates when space is available for further output, and also sends notifications. Note that this is only an alternate interface of the output_ch object.

The method can_output returns true only when the internal buffer is empty, i.e. all data have been transmitted to the client. Independent of this, the channel buffers all data written to it.

The behaviour of this channel is influenced by the configuration option config_output_flow_control.

ocamlnet-4.1.2/doc/html-main/Uq_transfer.async_out_channel_engine-c.html0000644000175000017500000004300712731530353025024 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.async_out_channel_engine

Class type Uq_transfer.async_out_channel_engine

class type async_out_channel_engine = object .. end
Combination of engine + async_out_channel
Inherits
ocamlnet-4.1.2/doc/html-main/type_Netulex.Ulexing.html0000644000175000017500000005011212731530353021365 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netulex.Ulexing sig
  type lexbuf
  exception Error
  val from_ulb_lexbuf : Netulex.ULB.unicode_lexbuf -> Netulex.Ulexing.lexbuf
  val lexeme_start : Netulex.Ulexing.lexbuf -> int
  val lexeme_end : Netulex.Ulexing.lexbuf -> int
  val lexeme_length : Netulex.Ulexing.lexbuf -> int
  val lexeme : Netulex.Ulexing.lexbuf -> int array
  val lexeme_char : Netulex.Ulexing.lexbuf -> int -> int
  val sub_lexeme : Netulex.Ulexing.lexbuf -> int -> int -> int array
  val utf8_lexeme : Netulex.Ulexing.lexbuf -> string
  val utf8_sub_lexeme : Netulex.Ulexing.lexbuf -> int -> int -> string
  val utf8_sub_lexeme_length : Netulex.Ulexing.lexbuf -> int -> int -> int
  val start : Netulex.Ulexing.lexbuf -> unit
  val next : Netulex.Ulexing.lexbuf -> int
  val mark : Netulex.Ulexing.lexbuf -> int -> unit
  val backtrack : Netulex.Ulexing.lexbuf -> int
end
ocamlnet-4.1.2/doc/html-main/type_Netshm_hashtbl.html0000644000175000017500000005353212731530353021303 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm_hashtbl sig
  type ('a, 'b) t
  val manage :
    ?pagesize:int ->
    ?init:int ->
    'Netshm_data.data_manager ->
    'Netshm_data.data_manager ->
    Netshm.locking_method -> Netshm.shm_descr -> ('a, 'b) Netshm_hashtbl.t
  val add : ('a, 'b) Netshm_hashtbl.t -> '-> '-> unit
  val find : ('a, 'b) Netshm_hashtbl.t -> '-> 'b
  val find_all : ('a, 'b) Netshm_hashtbl.t -> '-> 'b list
  val mem : ('a, 'b) Netshm_hashtbl.t -> '-> bool
  val remove : ('a, 'b) Netshm_hashtbl.t -> '-> unit
  val replace : ('a, 'b) Netshm_hashtbl.t -> '-> '-> unit
  val iter : ('-> '-> unit) -> ('a, 'b) Netshm_hashtbl.t -> unit
  val iter_keys : ('-> unit) -> ('a, 'b) Netshm_hashtbl.t -> unit
  val fold : ('-> '-> '-> 'c) -> ('a, 'b) Netshm_hashtbl.t -> '-> 'c
  val length : ('a, 'b) Netshm_hashtbl.t -> int
  val shm_table : ('a, 'b) Netshm_hashtbl.t -> Netshm.shm_table
end
ocamlnet-4.1.2/doc/html-main/Netchannels.in_obj_channel-c.html0000644000175000017500000004303312731530353022703 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.in_obj_channel

Class type Netchannels.in_obj_channel

class type in_obj_channel = object .. end
The application-level input channel supports raw and complemented methods
Inherits
ocamlnet-4.1.2/doc/html-main/Uq_engines.async_in_channel-c.html0000644000175000017500000004400312731530353023077 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.async_in_channel

Class type Uq_engines.async_in_channel

class type async_in_channel = object .. end

method input : Bytes.t -> int -> int -> int
method close_in : unit -> unit
method pos_in : int
method can_input : bool
method request_notification : (unit -> bool) -> unit
ocamlnet-4.1.2/doc/html-main/Nethttp_client.auth_handler-c.html0000644000175000017500000005025412731530353023136 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.auth_handler

Class type Nethttp_client.auth_handler

class type auth_handler = object .. end
An authentication handler has the capability of adding the necessary headers to messages.

method create_session : secure:bool ->
http_call ->
http_options Pervasives.ref ->
auth_session option
Create a new authentication session. The passed call has status 401. The secure flag is set when the connection is secured by TLS.
method create_proxy_session : http_call ->
http_options Pervasives.ref ->
auth_session option
Same for proxy authentication (status 407)
method identify_session : http_call ->
http_options Pervasives.ref ->
(string * string * string * int) option
Extracts (mech_name,realm,sess_id,trans_id) if possible. Only needed for multi-step challenge/response authentication. THIS IS STILL EXPERIMENTAL.
method identify_proxy_session : http_call ->
http_options Pervasives.ref ->
(string * string * string * int) option
Same for proxies. THIS IS STILL EXPERIMENTAL
method skip_challenge : bool
If true, this method allows to skip the challenge entirely for authentication. This means that the credentials are added to the HTTP request before any previous response was seen from the server. This adds additional security risks, and may cause that credentials are sent to servers that forge their identity. This is only supported for basic authentication. As no challenge is known, the realm string is simply assumed to be "anywhere".
method skip_challenge_session : http_call ->
http_options Pervasives.ref ->
auth_session option
Create a session for the case that the challenge was skipped
ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi_types.cgi_activation-c.html0000644000175000017500000005672412731530353026000 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_types.cgi_activation

Class type Netcgi1_compat.Netcgi_types.cgi_activation

class type cgi_activation = object .. end
Portage: In addition to defining a type, the following cgi_activation also defines a conversion function that allows to connect old scripts to the new infrastructure. Renamed simply cgi as this is the main cgi-like abstraction.

method environment : Netcgi1_compat.Netcgi_env.cgi_environment
method request_method : request_method
method initial_arguments : (string * cgi_argument) list
method initial_argument : string -> cgi_argument
method initial_argument_value : ?default:string -> string -> string
method initial_multiple_argument : string -> cgi_argument list
method arguments : (string * cgi_argument) list
Mutability of arguments has been dropped. We indeed believe that how to deal with arguments is the role of a higher level library, so it is unconvenient that they are mutable (force copying even if unecessary). Netcgi.Argument has a few helper functions to help manipulating lists of immutable arguments. Moreover, mutable arguments send the wrong message to the user (imagine one wants to keep a cache of args -> response) and unnecessarily complicate the interface.

It has type argument list as the name is redundant and this is better suited for the Netcgi.query_string_spec optional arguments.

method argument : string -> cgi_argument
method argument_value : ?default:string -> string -> string
method multiple_argument : string -> cgi_argument list
method set_arguments : ?fin:bool -> cgi_argument list -> unit
method update_argument : ?fin:bool -> cgi_argument -> unit
method update_multiple_argument : ?fin:bool -> cgi_argument list -> unit
method delete_argument : ?fin:bool -> string -> unit
method url : ?protocol:Netcgi1_compat.Netcgi_env.protocol ->
?with_authority:other_url_spec ->
?with_script_name:other_url_spec ->
?with_path_info:other_url_spec ->
?with_query_string:query_string_spec ->
unit -> string
method output : Netchannels.trans_out_obj_channel
Deprecated.in favor of out_channel for coherence with the standard library --- this is also to avoid cgi#output#output ... which looks odd.
method set_header : ?status:status ->
?content_type:string ->
?cache:cache_control ->
?filename:string ->
?language:string ->
?script_type:string ->
?style_type:string ->
?set_cookie:cgi_cookie list ->
?fields:(string * string list) list -> unit -> unit
Added ?content_length for user convenience and deprecated ?set_cookie in favor of ?set_cookies for coherence e.g. with ?fields.
method set_redirection_header : string -> unit
method finalize : unit -> unit
ocamlnet-4.1.2/doc/html-main/type_Rpc_server.tls_socket_config.html0000644000175000017500000004110712731530353024143 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.tls_socket_config (module Netsys_crypto_types.TLS_CONFIG-> Rpc_server.socket_configocamlnet-4.1.2/doc/html-main/Uq_engines.qseq_engine-c.html0000644000175000017500000004243412731530353022110 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.qseq_engine

Class Uq_engines.qseq_engine

class [['a, 'b]] qseq_engine : 'a #engine -> ('a -> 'b #engine) -> ['b] engine

ocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.SHA1_PLUS.html0000644000175000017500000004433412731530353022427 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SHA1_PLUS

Module Netmech_scram_sasl.SHA1_PLUS

module SHA1_PLUS: PROFILE 
Same as Netmech_scram_sasl.SHA1, only that the mechanism name is "SCRAM-SHA-1-PLUS"

val hash_function : Netsys_digests.iana_hash_fn
The hash function. We only allow functions where IANA registered an official name. Note that SCRAM is currently only specified for SHA1, although the hash function is easily exchangable.
val iteration_count_limit : int
The maximum iteration count supported
val announce_channel_binding : bool
Whether servers announce the availability of channel binding by adding "-PLUS" to the mechanism name.
ocamlnet-4.1.2/doc/html-main/type_Netftp_fs.html0000644000175000017500000006430412731530353020267 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_fs sig
  class type ftp_stream_fs =
    object
      method cancel : unit -> unit
      method close : unit -> unit
      method copy : Netfs.copy_flag list -> string -> string -> unit
      method ftp_client : Netftp_client.ftp_client
      method last_ftp_state : Netftp_client.ftp_state
      method mkdir : Netfs.mkdir_flag list -> string -> unit
      method nominal_dot_dot : bool
      method path_encoding : Netconversion.encoding option
      method path_exclusions : (int * int) list
      method read :
        Netfs.read_flag list -> string -> Netchannels.in_obj_channel
      method read_file :
        Netfs.read_file_flag list -> string -> Netfs.local_file
      method readdir : Netfs.readdir_flag list -> string -> string list
      method readlink : Netfs.readlink_flag list -> string -> string
      method remove : Netfs.remove_flag list -> string -> unit
      method rename : Netfs.rename_flag list -> string -> string -> unit
      method rmdir : Netfs.rmdir_flag list -> string -> unit
      method size : Netfs.size_flag list -> string -> int64
      method symlink : Netfs.symlink_flag list -> string -> string -> unit
      method test : Netfs.test_flag list -> string -> Netfs.test_type -> bool
      method test_list :
        Netfs.test_flag list -> string -> Netfs.test_type list -> bool list
      method translate : string -> string
      method write :
        Netfs.write_flag list -> string -> Netchannels.out_obj_channel
      method write_file :
        Netfs.write_file_flag list -> string -> Netfs.local_file -> unit
    end
  class ftp_fs :
    ?config_client:(Netftp_client.ftp_client -> unit) ->
    ?tmp_directory:string ->
    ?tmp_prefix:string ->
    ?get_password:(string -> string) ->
    ?get_account:(string -> string) ->
    ?keep_open:bool ->
    ?tls_config:(module Netsys_crypto_types.TLS_CONFIG->
    ?tls_enabled:bool ->
    ?tls_required:bool ->
    ?gssapi_provider:(module Netsys_gssapi.GSSAPI->
    ?gssapi_config:Netsys_gssapi.client_config ->
    ?gssapi_required:bool -> string -> ftp_stream_fs
  val ftp_fs :
    ?config_client:(Netftp_client.ftp_client -> unit) ->
    ?tmp_directory:string ->
    ?tmp_prefix:string ->
    ?get_password:(string -> string) ->
    ?get_account:(string -> string) ->
    ?keep_open:bool ->
    ?tls_config:(module Netsys_crypto_types.TLS_CONFIG->
    ?tls_enabled:bool ->
    ?tls_required:bool ->
    ?gssapi_provider:(module Netsys_gssapi.GSSAPI->
    ?gssapi_config:Netsys_gssapi.client_config ->
    ?gssapi_required:bool -> string -> Netftp_fs.ftp_stream_fs
end
ocamlnet-4.1.2/doc/html-main/Rpc_transport.rpc_multiplex_controller-c.html0000644000175000017500000006272012731530353025507 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_transport.rpc_multiplex_controller

Class type Rpc_transport.rpc_multiplex_controller

class type rpc_multiplex_controller = object .. end

method alive : bool
If the controller is alive, the socket is not yet completely down.
method event_system : Unixqueue.event_system
Returns the event system
method getsockname : sockaddr
The address of this socket
method getpeername : sockaddr
The address of the peer's socket. Only available if the socket is connected. (Fails otherwise.)
method protocol : Rpc.protocol
The protocol encapsulation
method tls_session_props : Nettls_support.tls_session_props option
The TLS session properties (if TLS is enabled)
method peer_user_name : string option
If the transport mechanism provides a way to authenticate the peer, it can return the name here.
method file_descr : Unix.file_descr option
If the transport mechanism is on top of a file descriptor, this is returned here. This can be useful for getting more information about the descriptor (e.g. credentials associated with it).
method reading : bool
True iff there is a reader
method read_eof : bool
Whether the EOF marker has been read
method start_reading : ?peek:(unit -> unit) ->
?before_record:(int -> sockaddr -> in_rule) ->
when_done:((in_record * sockaddr)
result_eof -> unit) ->
unit -> unit
Start reading from the connection. When a whole message has been received, the when_done callback is invoked. The in_record passed to when_done is usually `Accept m when m is the undecoded message string. For other types of in_record see the comments to before_record below.

This starts one-time read job only, i.e. it is not restarted after when_done has been invoked.

It is an error to start reading several times at once.

peek: This function is called immediately before a data chunk is read from the underlying data connection.

before_record: If passed, this function is called back whenever a fragment of data is started. The integer is the so-far known size of the message in bytes. It is guaranteed that the function is invoked once for every message fragment as long as the previous fragments were accepted, and in total at least once before when_done. The result of the last before_record call determines what is returned as in_record, e.g. a `Deny rule causes that a `Deny result is passed to when_done. Also, for `Deny and `Drop no message buffer is allocated (i.e. no memory consumption). For `Reject, only a very small buffer is allocated that only provides space for the session identifier (xid). When there is no before_record function, `Accept is passed to when_done.

method writing : bool
True iff there is a writer
method start_writing : when_done:(unit result -> unit) ->
Rpc_packer.packed_value -> sockaddr -> unit
Starts writing the message. Invoked when_done when it is written, or an error condition is reached.

This starts one-time write job only, i.e. it is not restarted after when_done has been invoked.

It is an error to start writing several times at once.

method cancel_rd_polling : unit -> unit
Cancels polling for the next input message. This method must not be called from the before_record callback function. Polling can be resumed by calling start_reading again.
method abort_rw : unit -> unit
Aborts the current reader and/or writer forever. Note that there is no clean way of resuming reading and/or writing. The readers/writers are not notified about cancellation.

This method also deallocates buffers, so far possible.

It is allowed to go on with the shutdown, and to inactivate.

method start_shutting_down : when_done:(unit result -> unit) -> unit -> unit
Start shutting down the connection. After going through the shutdown procedure, the when_done callback is invoked reporting the success or failure.

The underlying file descriptor (if any) is not closed. A shutdown is only a protocol handshake. After a shutdown,read_eof is true. Call inactivate to close the descriptor.

This method also deallocates buffers, so far possible.

method cancel_shutting_down : unit -> unit
Cancels the shutdown procedure. After that, the state of the connection is undefined. The when_done callback is invoked with the `Cancelled.

It is no error if no shutdown is in progress.

method set_timeout : notify:(unit -> unit) -> float -> unit
If there is no read or write activity for the passed number of seconds, the notify callback is invoked.
method inactivate : unit -> unit
Inactivates the connection immediately, and releases any resources the controller is responsible for (e.g. closes file descriptors). Note that this is more than cancelling all pending operations and shutting the connection down. However, the details of this method are implementation-defined. Callbacks are not invoked.
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.basic_auth_handler.html0000644000175000017500000004125212731530353025116 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.basic_auth_handler ?enable_reauth:bool ->
?skip_challenge:bool ->
#Nethttp_client.key_handler -> Nethttp_client.auth_handler
ocamlnet-4.1.2/doc/html-main/Netcgi_test.html0000644000175000017500000004326712731530353017553 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_test

Module Netcgi_test

module Netcgi_test: sig .. end
Connector for testing your code.

This is to be developed. There are several ways to go about this and it is not clear which one to take.


Version: $Id: netcgi_test.mli,v 1.7 2005/10/13 17:54:49 chris_77 Exp $


val run : ?config:Netcgi.config ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?args:Netcgi.cgi_argument list -> (Netcgi.cgi -> unit) -> unit
ocamlnet-4.1.2/doc/html-main/type_Netmcore_array.html0000644000175000017500000005477412731530353021323 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_array sig
  type ('e, 'h) sarray
  type ('e, 'h) sarray_descr
  val create :
    Netmcore.res_id -> 'e array -> '-> ('e, 'h) Netmcore_array.sarray
  val make :
    Netmcore.res_id -> int -> '-> '-> ('e, 'h) Netmcore_array.sarray
  val init :
    Netmcore.res_id ->
    int -> (int -> 'e) -> '-> ('e, 'h) Netmcore_array.sarray
  val grow : ('e, 'a) Netmcore_array.sarray -> int -> '-> unit
  val set : ('e, 'a) Netmcore_array.sarray -> int -> '-> unit
  val get_ro : ('e, 'a) Netmcore_array.sarray -> int -> 'e
  val get_p : ('e, 'b) Netmcore_array.sarray -> int -> ('-> 'a) -> 'a
  val get_c : ('e, 'a) Netmcore_array.sarray -> int -> 'e
  val length : ('a, 'b) Netmcore_array.sarray -> int
  val header : ('a, 'h) Netmcore_array.sarray -> 'h
  val deref : ('e, 'a) Netmcore_array.sarray -> 'e array
  val heap : ('a, 'b) Netmcore_array.sarray -> Obj.t Netmcore_heap.heap
  val descr_of_sarray :
    ('e, 'h) Netmcore_array.sarray -> ('e, 'h) Netmcore_array.sarray_descr
  val sarray_of_descr :
    Netmcore.res_id ->
    ('e, 'h) Netmcore_array.sarray_descr -> ('e, 'h) Netmcore_array.sarray
end
ocamlnet-4.1.2/doc/html-main/Rpc_client.auth_session-c.html0000644000175000017500000004766712731530353022320 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.auth_session

Class type Rpc_client.auth_session

class type auth_session = object .. end
An auth_session object is normally created for every client instance. It contains the current state of authentication. The methods are only interesting for implementors of authentication methods.

This class type might be revised in the future to allow asynchronous authentication (authentication often uses some network service).


method next_credentials : t ->
Rpc_program.t ->
string ->
Netnumber.uint4 ->
string * string * string * string * Netxdr.encoder option *
Netxdr.decoder option
Called with client prog proc xid. Returns (cred_flavour, cred_data, verifier_flavor, verifier_data, enc_opt, dec_opt).

Changed in Ocamlnet-3.3: Additional arguments prog, proc, xid. New return values enc_opt and dec_opt.

method server_rejects : t -> Netnumber.uint4 -> Rpc.server_error -> reject_code
Called if the server rejects the credentials or the verifier (Auth_xxx). This method indicates how to react on errors.

Changed in Ocamlnet-3.3: Additional arg xid. New return value.

method server_accepts : t -> Netnumber.uint4 -> string -> string -> unit
Called if the server accepts the credentials. The two strings are the returned verifier_flavor and verifier_data. This method may raise Rpc_server Rpc_invalid_resp to indicate that the returned verifier is wrong.

Changed in Ocamlnet-3.3: Additional arg xid

method auth_protocol : auth_protocol
Return the corresponding protocol
ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi.simple_argument-c.html0000644000175000017500000004222212731530353024750 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi.simple_argument

Class Netcgi1_compat.Netcgi.simple_argument

class simple_argument : ?ro:bool -> string -> string -> Netcgi1_compat.Netcgi_types.cgi_argument

ocamlnet-4.1.2/doc/html-main/type_Nettelnet_client.telnet_session.html0000644000175000017500000005455112731530353024677 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettelnet_client.telnet_session object
  method attach : unit -> unit
  method disable_local_option :
    Nettelnet_client.telnet_negotiated_option -> unit
  method disable_remote_option :
    Nettelnet_client.telnet_negotiated_option -> unit
  method enable_local_option :
    Nettelnet_client.telnet_negotiated_option -> unit
  method enable_remote_option :
    Nettelnet_client.telnet_negotiated_option -> unit
  method expect_input : bool -> unit
  method fetch_subnegotiation : string option
  method get_local_option :
    Nettelnet_client.telnet_negotiated_option ->
    Nettelnet_client.telnet_option_state
  method get_options : Nettelnet_client.telnet_options
  method get_remote_option :
    Nettelnet_client.telnet_negotiated_option ->
    Nettelnet_client.telnet_option_state
  method input_queue : Nettelnet_client.telnet_command Queue.t
  method offer_local_option :
    Nettelnet_client.telnet_negotiated_option -> unit
  method option_negotiation_is_over : bool
  method output_queue : Nettelnet_client.telnet_command Queue.t
  method process_option_command : Nettelnet_client.telnet_command -> unit
  method request_remote_option :
    Nettelnet_client.telnet_negotiated_option -> unit
  method reset : unit -> unit
  method reset_local_option :
    Nettelnet_client.telnet_negotiated_option -> unit
  method reset_remote_option :
    Nettelnet_client.telnet_negotiated_option -> unit
  method run : unit -> unit
  method send_synch : Nettelnet_client.telnet_command list -> unit
  method set_callback : (bool -> unit) -> unit
  method set_connection : Nettelnet_client.telnet_connector -> unit
  method set_event_system : Unixqueue.event_system -> unit
  method set_exception_handler : (exn -> unit) -> unit
  method set_options : Nettelnet_client.telnet_options -> unit
  method start_tls :
    (module Netsys_crypto_types.TLS_CONFIG->
    peer_name:string option -> unit
  method tls_session_data : string option
  method tls_session_props : Nettls_support.tls_session_props option
  method update : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netmcore_mempool.Debug.html0000644000175000017500000004123412731530353022665 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_mempool.Debug sig
  val enable : bool Pervasives.ref
  val enable_alloc : bool Pervasives.ref
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.prioritizer_t.html0000644000175000017500000004163512731530353023342 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.prioritizer_t object
  method prioritized :
    (Unixqueue.event_system -> 'Uq_engines.engine) ->
    int -> 'Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_auth_sys.html0000644000175000017500000004553512731530353021007 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_auth_sys sig
  type identity =
      [ `Effective_user
      | `Real_user
      | `This_user of int * int * int array * string ]
  val client_auth_method :
    ?identity:Rpc_auth_sys.identity -> unit -> Rpc_client.auth_method
  type user_name_format =
      [ `Custom of int32 -> int32 -> int32 array -> string -> string
      | `Full
      | `UID ]
  val server_auth_method :
    ?lookup_hostname:bool ->
    ?require_privileged_port:bool ->
    ?user_name_as:Rpc_auth_sys.user_name_format ->
    unit -> Rpc_server.auth_method
  val parse_user_name : string -> int * int * int array * string
end
ocamlnet-4.1.2/doc/html-main/Netcgi_fcgi.html0000644000175000017500000005711312731530353017477 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_fcgi

Module Netcgi_fcgi

module Netcgi_fcgi: sig .. end
FastCGI connector.

Remark: This connector does not allow requests to be multiplexed (and let it know to the web server via FCGI_MPXS_CONNS=0). Multiplexing requests is seldom done by FastCGI modules and is even sometimes impossible because of bugs in them. Moreover, multiplexing is mostly useful if concurrent requests are handled by different threads while this library use a single thread to process all requests coming on a given connection. If the need is felt (speak out!), a multithreaded connector can be built on the side of this one.


class type cgi = object .. end
The usual Netcgi.cgi class with FCGI specific methods.
val run : ?config:Netcgi.config ->
?allow:(Unix.sockaddr -> bool) ->
?output_type:Netcgi.output_type ->
?arg_store:Netcgi.arg_store ->
?exn_handler:Netcgi.exn_handler ->
?socket:Unix.file_descr ->
?sockaddr:Unix.sockaddr -> ?port:int -> (cgi -> unit) -> unit
run f register the function f as a main function of the script. Each call to the script will execute f cgi. The code outside f will be executed only once (when the script is loaded into memory) which allows to cache database connections, etc.
config : Default: Netcgi.default_config
allow : Tells whether a connection from the socket is allowed. Default: Use the comma separated list given in the environment variable FCGI_WEB_SERVER_ADDRS or allow all if it does not exist.
output_type : Default: `Direct ""
arg_store : Default: `Automatic for all arguments.
exn_handler : See Netcgi.exn_handler. Default: delegate all exceptions to the default handler.
socket : is a listening socket to use. Overrides sockaddr and port.
sockaddr : tells on what socket to contact the script. If not specified, the script expects to be launched by the web server and to communicate with it through stdin. For external scripts (launched independently of the web server and possibly on a different machine), set sockaddr to the address the web server needs to connect to to talk to the script (this address must also be specified in the web server config file).
port : alternative way to specify sockaddr listening to localhost only. If you would like your FastCGI program to be accessed from a different machine, use sockaddr instead.

Your application should be ready handle SIGUSR1, used to resquest a "graceful" process shutdown, and SIGTERM to request a quick shutdown.

val handle_request : Netcgi.config ->
Netcgi.output_type ->
Netcgi.arg_store ->
Netcgi.exn_handler ->
(cgi -> unit) ->
max_conns:int ->
log:(string -> unit) option -> Unix.file_descr -> Netcgi.connection_directive
handle_request config output_type arg_store eh f ~max_conns ~log fd: This is a lower-level interface that processes exactly one request arriving on the existing connection fd.

max_conns is passed to the FCGI client and indicates how many connections this server can process in parallel.

log is the error logger function or None, in which case errors are passed through to the FCGI client.

The other arguments are just like for run.

The return value indicates whether the connection can be kept open or must be closed.

val handle_connection : Netcgi.config ->
Netcgi.output_type ->
Netcgi.arg_store ->
Netcgi.exn_handler ->
(cgi -> unit) ->
max_conns:int -> one_shot:bool -> Unix.file_descr -> unit
handle_connection config output_type arg_store eh f ~max_conns ~one_shot fd: This is a lower-level interface that processes exactly one connection fd. The descriptor is closed (even on error).

max_conns is passed to the FCGI client and indicates how many connections this server can process in parallel.

one_shot: if true, only one request is processed over this connection, overriding any indication by the web server.

The other arguments are just like for run.

ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.DIGESTS.html0000644000175000017500000004504212731530353023547 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.DIGESTS sig
  type digest
  val digests : Netsys_crypto_types.DIGESTS.digest list
  val find : string -> Netsys_crypto_types.DIGESTS.digest
  val name : Netsys_crypto_types.DIGESTS.digest -> string
  val size : Netsys_crypto_types.DIGESTS.digest -> int
  val block_length : Netsys_crypto_types.DIGESTS.digest -> int
  type digest_ctx
  val create :
    Netsys_crypto_types.DIGESTS.digest ->
    Netsys_crypto_types.DIGESTS.digest_ctx
  val add :
    Netsys_crypto_types.DIGESTS.digest_ctx -> Netsys_types.memory -> unit
  val finish : Netsys_crypto_types.DIGESTS.digest_ctx -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_cenv.Make_var_type.html0000644000175000017500000004172112731530353023554 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.Make_var_type functor (T : TYPE->
  sig type t = T.t val get : string -> t val set : string -> t -> unit end
ocamlnet-4.1.2/doc/html-main/Netunidata.html0000644000175000017500000004765112731530353017400 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netunidata

Module Netunidata

module Netunidata: sig .. end
Configure how to load Unicode tables


The Netconversion module implements the conversion between various character sets. By default, this module knows only a few built-in characters sets (in particular ISO-8859-1 and US-ASCII). Conversions to other character sets can be enabled by linking in the netunidata library.

There are two options to load the required tables. First, the table can be linked with the executable (static table). Second, the table can be loaded at runtime when needed (dynamic table).

For getting static tables, just specify one or several of the following findlib packages:

  • netunidata.iso: Links in the whole ISO-8859 series
  • netunidata.jp: Links in Japanese character sets (JIS-X-0201 and EUC-JP)
  • netunidata.kr: Links in Korean character sets (EUC-KR)
  • netunidata.other: Links in other characters sets (e.g. the whole Windows series)
  • netunidata.all: Links in all
If static tables are linked in, this does not automatically disable that remaining tables are dynamically loaded. You need to explicitly disable this: Netunidata.disable.

If you want to load all tables dynamically, just specify this package:

  • netunidata: Only links in the dynamic loaders for the tables

val load : string -> unit
load key: Loads the table for this key, if not already loaded or statically linked in. The key is the internal name of the mapping table (e.g. "cmapf.koi8r")
val load_charset : Netconversion.charset -> unit
load_charset enc: Loads the forward and backward mapping tables for this charset.
val enable : unit -> unit
Enables the dynamic loader. This is the default.
val disable : unit -> unit
Disables the dynamic loader
val net_db_dir : unit -> string
Returns the directory where the dynamic tables can be found
val set_net_db_dir : string -> unit
Change the directory where the dynamic tables can be found
ocamlnet-4.1.2/doc/html-main/Netsys_gssapi.GSSAPI.gss_api-c.html0000644000175000017500000004540312731530353022761 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.GSSAPI.gss_api

Class type Netsys_gssapi.GSSAPI.gss_api

class type gss_api = [[credential, name
, context]]
Netsys_gssapi.poly_gss_api
The methods have generally a type of the form

 
       m : 't . arg1 -> ... -> argN -> out:( ret1 -> ... -> retM -> 't ) -> 't 
    

where args are input arguments (with the exception of context which is in/out), and where outputs are passed back by calling the out functions with the outputs. The return value of out is the return value of the method call.

For example, if only output_token of the accept_sec_context method is needed, one could call this method as in

      let output_token =
	gss_api # accept_sec_context 
	   ... 
	   ~out:(fun ~src_name ~mech_type ~output_token ~ret_flags
		     ~time_rec ~delegated_cred_handle ~minor_status
		     ~major_status ->
		  output_token
		)
    

Output values may not be defined when major_status indicates an error. (But see the RFC for details; especially init_sec_contect and accept_sec_context may emit tokens even when major_status indicates an error.)

The names of the parameters are taken from RFC 2744, only suffixes like _handle have been removed. When the prefixes input_ and output_ are meaningless, they are also removed. All prefixes like "GSS" are removed anyway.


ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.output_async_descr.html0000644000175000017500000004134712731530353024546 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.output_async_descr dst:Unix.file_descr ->
?buffer_size:int ->
?close_dst:bool ->
Unixqueue.event_system -> Uq_transfer.async_out_channel_engine
ocamlnet-4.1.2/doc/html-main/Netgssapi_auth.html0000644000175000017500000004452212731530353020254 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_auth

Module Netgssapi_auth

module Netgssapi_auth: sig .. end
Authentication helpers for GSSAPI

module type CONFIG = sig .. end
module Manage: 
functor (G : Netsys_gssapi.GSSAPI) -> sig .. end
module Auth: 
functor (G : Netsys_gssapi.GSSAPI) ->
functor (C : CONFIG) -> sig .. end
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.TLS_EXCEPTIONS.html0000644000175000017500000004614612731530353023615 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_EXCEPTIONS

Module type Netsys_crypto_types.TLS_EXCEPTIONS

module type TLS_EXCEPTIONS = sig .. end
The exceptions the TLS provider may use (in addition to OCaml's built-in exception). In Ocamlnet, these exceptions are actually defined in Netsys_types.

exception EAGAIN_RD
exception EAGAIN_WR
A read or write cannot be done because the descriptor is in non-blocking mode and would block. This corresponds to the Unix.EAGAIN error but includes whether it was a read or write.

When the read or write is possible, the interrupted function should simply be again called.

These two exceptions are preferred by TLS providers.

exception TLS_switch_request
The server requested a rehandshake (this exception is thrown in the client)
exception TLS_switch_response of bool
The client accepted or denied a rehandshake (this exception is thrown in the server). true means acceptance.
exception TLS_error of string
A fatal error occurred (i.e. the session needs to be terminated). The string is a symbol identifying the error.
exception TLS_warning of string
A non-fatal error occurred. The interrupted function should be called again. The string is a symbol identifying the warning.
ocamlnet-4.1.2/doc/html-main/type_Rpc_server.auth_details.html0000644000175000017500000004326412731530353023120 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.auth_details object
  method client_addr : Unix.sockaddr option
  method credential : string * string
  method frame_len : int
  method message : Rpc_packer.packed_value
  method procedure : Netnumber.uint4
  method program : Netnumber.uint4
  method server_addr : Unix.sockaddr option
  method transport_user : string option
  method verifier : string * string
  method version : Netnumber.uint4
  method xid : Netnumber.uint4
end
ocamlnet-4.1.2/doc/html-main/Netmime.mime_header-c.html0000644000175000017500000004633612731530353021357 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.mime_header

Class type Netmime.mime_header

class type mime_header = object .. end
A MIME header with both read and write method. It is still possible, however, to set the read-only flag to make this kind of header immutable, too.
Inherits
method ro : bool
whether the header is read-only or not
method set_fields : (string * string) list -> unit
method update_field : string -> string -> unit
method update_multiple_field : string -> string list -> unit
method delete_field : string -> unit
These methods modify the fields of the header. If the header is read-only, the exception Immutable will be raised.

set_fields replaces the current fields with a new list of (name,value) pairs. update_field name value replaces all fields of the passed name with the single setting (name,value), or adds this setting to the list. update_multiple_field name values replaces all fields of the passed name with the list of values, or adds this list. Finally, delete_field name deletes all fields of the passed name. Nothing happens if there is no such field.

Both update_field and update_multiple_field first replace existing values by the new ones without changing the order of the fields in the header. Additional values are inserted after the last existing value, or at the end of the header.

ocamlnet-4.1.2/doc/html-main/Uq_resolver.engine-c.html0000644000175000017500000004347612731530353021277 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_resolver.engine

Class type Uq_resolver.engine

class type ['t] engine = object .. end

method state : 't engine_state
method abort : unit -> unit
method request_notification : (unit -> bool) -> unit
method request_proxy_notification : ('t engine -> bool) -> unit
method event_system : Unixqueue.event_system
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.output_engine.html0000644000175000017500000004156112731530353024663 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.output_engine (Unix.file_descr -> 'a) ->
Unix.file_descr ->
float -> Unixqueue.event_system -> ['a] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.map_engine-c.html0000644000175000017500000004314112731530353023253 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.map_engine

Class Uq_engines_compat.map_engine

class [['a, 'b]] map_engine : map_done:('a -> 'b engine_state) -> ?map_error:exn -> 'b engine_state -> ?map_aborted:unit -> 'b engine_state -> ?propagate_working:bool -> 'a #engine -> ['b] engine

ocamlnet-4.1.2/doc/html-main/type_Netplex_internal.html0000644000175000017500000004215712731530353021654 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_internal sig
  val register_server : string -> Netplex_types.polyserver_box -> unit
  val connect_client :
    'Netplex_types.kind_check ->
    int -> string -> 'Netsys_polysocket.polyclient
end
ocamlnet-4.1.2/doc/html-main/Netsys_gssapi.html0000644000175000017500000011222612731530353020126 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi

Module Netsys_gssapi

module Netsys_gssapi: sig .. end
GSS-API Definition


This is mainly a translation of RFC 2743/2744 to Ocaml.

The following other modules are also interesting in this context:



This is mainly a translation of RFC 2743/2744 to Ocaml.

The following other modules are also interesting in this context:



Types


type oid = int array 
OIDs like "1.3.6.1.5.6.2" as array of int's. The empty array means GSS_C_NO_OID. See also Netoid.
type oid_set = oid list 
A set of OID's. These lists should not contain OID's twice. The empty list means GSS_C_NO_OID_SET.
type token = string 
Authentication tokens. These are also opaque to the caller, but have a string representation so that they can be sent over the wire.
type interprocess_token = string 
Interprocess tokens. These are also opaque to the caller, but have a string representation so that they can be sent over the wire.
type calling_error = [ `Bad_structure | `Inaccessible_read | `Inaccessible_write | `None ] 
Possible errors caused by the caller
type routine_error = [ `Bad_QOP
| `Bad_bindings
| `Bad_mech
| `Bad_mic
| `Bad_name
| `Bad_nametype
| `Bad_status
| `Context_expired
| `Credentials_expired
| `Defective_credential
| `Defective_token
| `Duplicate_element
| `Failure
| `Name_not_mn
| `No_context
| `No_cred
| `None
| `Unauthorized
| `Unavailable ]
Possible errors caused by the provider
type suppl_status = [ `Continue_needed
| `Duplicate_token
| `Gap_token
| `Old_token
| `Unseq_token ]
Further flags
type major_status = calling_error * routine_error *
suppl_status list
The major status consists of these three elements. The bits of the supplementary status field are represented as list
type minor_status = int32 
The minor status is provider-specific. Note that GSS-API defines it as unsigned 32-bit integer whereas int32 is signed.
type address = [ `Inet of Unix.inet_addr
| `Local of string
| `Nulladdr
| `Other of int32 * string
| `Unspecified of string ]
Addresses tagged by address types
type channel_bindings = address * address * string 
Channel binding as tuple (initiator_address, acceptor_address, application_data)
type cred_usage = [ `Accept | `Both | `Initiate ] 
type qop = int32 
Quality-of-proctection parameters are mechanism-specific. The value 0 can always be used for a default protection level.
type message = Netsys_types.mstring list 
Messages are represented as lists of mstring
type ret_flag = [ `Anon_flag
| `Conf_flag
| `Deleg_flag
| `Integ_flag
| `Mutual_flag
| `Prot_ready_flag
| `Replay_flag
| `Sequence_flag
| `Trans_flag ]
Flags for the accept_sec_context method
type req_flag = [ `Anon_flag
| `Conf_flag
| `Deleg_flag
| `Integ_flag
| `Mutual_flag
| `Replay_flag
| `Sequence_flag ]
Flags for the init_sec_context method
type time = [ `Indefinite | `This of float ] 
class type [['credential, 'name, 'context]] poly_gss_api = object .. end
module type GSSAPI = sig .. end

Utility functions



Utility functions



These functions convert values to strings. Useful for generating log messages.
val string_of_calling_error : calling_error -> string
val string_of_routine_error : routine_error -> string
val string_of_suppl_status : suppl_status -> string
val string_of_major_status : major_status -> string
val string_of_flag : ret_flag -> string

Common OID's for name types



Common OID's for name types



See RFC 2078, section 4
val nt_hostbased_service : oid
names like "service@hostname"
val nt_hostbased_service_alt : oid
another OID for the same (RFC 1964 mentions it)
val nt_user_name : oid
names like "username"
val nt_machine_uid_name : oid
user ID in host byte order
val nt_string_uid_name : oid
user ID as string of digits
val nt_anonymous : oid
anonymous name
val nt_export_name : oid
an export name
val nt_krb5_principal_name : oid
a Kerberos 5 principal name (see Netgssapi_support for parsers
val parse_hostbased_service : string -> string * string
Returns (service,host) for "service@host". Fails if not parseable

Configuring clients


type support_level = [ `If_possible | `None | `Required ] 
class type client_config = object .. end
val create_client_config : ?mech_type:oid ->
?initiator_name:string * oid ->
?initiator_cred:exn ->
?target_name:string * oid ->
?privacy:support_level ->
?integrity:support_level ->
?flags:(req_flag * support_level) list ->
unit -> client_config
mech_type is the GSSAPI mechanism to use. If left unspecified, a default is used. target_name is the name of the service to connect to. initiator_name identifies and authenticates the client. Note that you normally can omit all of mech_type, target_name, and initiator_name as GSSAPI already substitutes reasonable defaults (at least if Kerberos is available as mechanism).

If you have a delegated credential you can also pass it as initiator_cred. This must be a Credential exception from the GSSAPI provider. initiator_cred has precedence over initiator_name.

privacy and integrity specify the desired level of protection. By default, both integrity and privacy are enabled if available, but it is no error if the mechanism doesn't support these features.

flags: additional GSSAPI flags. These should not contain `Conf_flag and `Integ_flag (instead use privacy and integrity, resp.).

class type client_props = object .. end
Return properties of the client context
val marshal_client_props : client_props -> string
val unmarshal_client_props : string -> client_props

Configuring servers


class type server_config = object .. end
val create_server_config : ?mech_types:oid list ->
?acceptor_name:string * oid ->
?privacy:support_level ->
?integrity:support_level ->
?flags:(req_flag * support_level) list ->
unit -> server_config
mech_types is the list of GSSAPI mechanism that are acceptable. If left unspecified, a default is used. acceptor_name is the name of the service to offer.

Note that you normally can omit mech_types as GSSAPI already substitutes reasonable defaults (at least if Kerberos is available as mechanism). acceptor_name should normally be specified.

privacy and integrity specify the desired level of protection. By default, both integrity and privacy are enabled if available, but it is no error if the mechanism doesn't support these features.

flags: additional GSSAPI flags. These should not contain `Conf_flag and `Integ_flag (instead use privacy and integrity, resp.).

class type server_props = object .. end
Return properties of the server context
val marshal_server_props : server_props -> string
val unmarshal_server_props : string -> server_props
This doesn't restore deleg_credential which is unmarshallable!

Encodings



Encodings



Some conversions have been moved to Netoid:

The remaining functions can now be found in Netgssapi_support.

Encodings



Some conversions have been moved to Netoid:

The remaining functions can now be found in Netgssapi_support.

Create tokens



Encodings



Some conversions have been moved to Netoid:

The remaining functions can now be found in Netgssapi_support.

Create tokens



All functions have been moved to Netgssapi_support
ocamlnet-4.1.2/doc/html-main/type_Rpc_server.Debug.html0000644000175000017500000004222612731530353021475 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.Debug sig
  val enable : bool Pervasives.ref
  val enable_ctrace : bool Pervasives.ref
  val enable_ptrace : bool Pervasives.ref
  val ptrace_verbosity : Rpc_util.verbosity Pervasives.ref
  val disable_for_server : Rpc_server.t -> unit
end
ocamlnet-4.1.2/doc/html-main/Netaux.ArrayAux.html0000644000175000017500000004325512731530353020277 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaux.ArrayAux

Module Netaux.ArrayAux

module ArrayAux: sig .. end

val int_blit : int array -> int -> int array -> int -> int -> unit
A specialisation of Array.blit for int arrays. (Performance reasons.)
val int_series : int array -> int -> int array -> int -> int -> int -> unit
int_series src srcpos dst dstpos len n: Computes for every i, 0 <= i < len: dst.(dstpos+i) = n + SUM(j=0..(i-1): src.(srcpos+j))

It is expected that src == dst implies srcpos >= dstpos.

ocamlnet-4.1.2/doc/html-main/Netulex_tut.html0000644000175000017500000004737312731530353017625 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netulex_tut

Netulex_tut


Netulex Tutorial

Of course, you need Alain Frisch's ulex utility first. It installs itself under the name ulex as findlib library.

Next, write your lexer, e.g. (line numbers in brackets):

[1] open Netulex
[2] let digits = lexer
[3]   | ['0'-'9']+ -> `Number(int_of_string(Ulexing.utf8_lexeme lexbuf))
[4]   | 8364       -> `Euro_sign   (* Code point #8364 in Unicode *)

This is a very trivial example. The lexer accepts sequences of digits, and returns them as `Number tokens. Furthermore, the euro sign is recognized and returned as `Euro_sign. Note that in the first case Netulex.Ulexing.utf8_lexeme is called to retrieve the current lexeme as UTF-8 string. (Well, digits are a bad example, as they are only ASCII, and UTF-8 is not really needed. Imagine you want to extend the scanner to other number systems represented in the Unicode character set.)

Line 1 is quite important. If you don't open Netulex, the generated ulex code will use the version of the Ulexing module coming with ulex, and not this one.

Call the lexer as follows (line numbers in brackets):

[5] let sample = "42543\226\130\172";;
[6] let ulb = Netulex.ULB.from_string `Enc_utf8 sample;;
[7] let lexbuf = Netulex.Ulexing.from_ulb_lexbuf ulb;;
[8] let first_token = digits lexbuf;;

Now, first_token is `Number 42543. After

[9] let second_token = digits lexbuf;;

this variable is set to `Euro_sign, because the three-byte sequence "\226\130\172" represents the euro sign in UTF-8.

In line 6, the encoding `Enc_utf8 selects that sample is an UTF-8 string. You can pass here any encoding the Netconversion module understands.

If you would like to scan from another source, just change line 6, e.g.

[6'] let ulb = Netulex.ULB.from_in_obj_channel ch

where ch is any input channel the Netchannels module supports. For example, to read from a file:

let ch = new Netchannels.input_channel (open_in "filename")

You should compile the examples with

ocamlfind ... -package ulex,netstring -syntax camlp4o ...

For the syntax of the lexer rules, see the documentation coming with ulex.


ocamlnet-4.1.2/doc/html-main/type_Rpc_simple_client.html0000644000175000017500000004273612731530353021777 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_simple_client sig
  type t
  val create :
    Rpc_client.connector ->
    Rpc.protocol -> Rpc_program.t -> Rpc_simple_client.t
  val call :
    Rpc_simple_client.t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
  val shut_down : Rpc_simple_client.t -> unit
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.post_raw-c.html0000644000175000017500000004224612731530353022340 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.post_raw

Class Nethttp_client.post_raw

class post_raw : string -> string -> http_call
Arguments: URI, body

ocamlnet-4.1.2/doc/html-main/type_Shell_fs.shell_fs.html0000644000175000017500000004155012731530353021672 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_fs.shell_fs ?encoding:Netconversion.encoding ->
?root:string ->
?dd_has_excl:bool ->
?tmp_directory:string ->
?tmp_prefix:string ->
Shell_fs.command_interpreter -> Shell_fs.shell_stream_fs
ocamlnet-4.1.2/doc/html-main/type_Netasn1.Value.html0000644000175000017500000007420212731530353020721 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netasn1.Value sig
  type pc = Primitive | Constructed
  type value =
      Bool of bool
    | Integer of Netasn1.Value.int_value
    | Enum of Netasn1.Value.int_value
    | Real of Netasn1.Value.real_value
    | Bitstring of Netasn1.Value.bitstring_value
    | Octetstring of string
    | Null
    | Seq of Netasn1.Value.value list
    | Set of Netasn1.Value.value list
    | Tagptr of Netasn1.Value.tag_class * int * Netasn1.Value.pc *
        Netstring_tstring.tstring_polybox * int * int
    | Tag of Netasn1.Value.tag_class * int * Netasn1.Value.pc *
        Netasn1.Value.value
    | ITag of Netasn1.Value.tag_class * int * Netasn1.Value.value
    | OID of int array
    | ROID of int array
    | ObjectDescriptor of string
    | External of Netasn1.Value.value list
    | Embedded_PDV of Netasn1.Value.value list
    | NumericString of string
    | PrintableString of string
    | TeletexString of string
    | VideotexString of string
    | VisibleString of string
    | IA5String of string
    | GraphicString of string
    | GeneralString of string
    | UniversalString of string
    | BMPString of string
    | UTF8String of string
    | CharString of string
    | UTCTime of Netasn1.Value.time_value
    | GeneralizedTime of Netasn1.Value.time_value
  and tag_class = Universal | Application | Context | Private
  and int_value
  and real_value
  and bitstring_value
  and time_value
  type time_subtype = [ `G | `U ]
  val type_of_value :
    Netasn1.Value.value -> Netasn1.Type_name.type_name option
  val get_int_repr : Netasn1.Value.int_value -> string
  val get_int_b256 : Netasn1.Value.int_value -> int array
  val get_int : Netasn1.Value.int_value -> int
  val get_int32 : Netasn1.Value.int_value -> int32
  val get_int64 : Netasn1.Value.int_value -> int64
  val int : int -> Netasn1.Value.int_value
  val int32 : int32 -> Netasn1.Value.int_value
  val int64 : int64 -> Netasn1.Value.int_value
  val int_b256 : int array -> Netasn1.Value.int_value
  val get_real_repr : Netasn1.Value.real_value -> string
  val get_bitstring_size : Netasn1.Value.bitstring_value -> int
  val get_bitstring_data : Netasn1.Value.bitstring_value -> string
  val get_bitstring_bits :
    ?size:int -> Netasn1.Value.bitstring_value -> bool array
  val get_bitstring_repr : Netasn1.Value.bitstring_value -> string
  val bitstring_of_bits : bool array -> Netasn1.Value.bitstring_value
  val bitstring_of_string : string -> int -> Netasn1.Value.bitstring_value
  val truncate_trailing_zero_bits :
    Netasn1.Value.bitstring_value -> Netasn1.Value.bitstring_value
  val get_time_subtype :
    Netasn1.Value.time_value -> Netasn1.Value.time_subtype
  val get_time_repr : Netasn1.Value.time_value -> string
  val get_time : Netasn1.Value.time_value -> Netdate.t
  val utctime : Netdate.t -> Netasn1.Value.time_value
  val gentime : digits:int -> Netdate.t -> Netasn1.Value.time_value
  val equal : Netasn1.Value.value -> Netasn1.Value.value -> bool
end
ocamlnet-4.1.2/doc/html-main/Netplex_mbox.html0000644000175000017500000004627312731530353017747 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mbox

Module Netplex_mbox

module Netplex_mbox: sig .. end
Netplex message boxes


This plugin implements a message box, following a simple model: Receivers wait until messages are put into the box. Senders wait until the box is free again.

This is actually an extension of Netplex_sharedvar, and the same caveats apply.

val plugin : Netplex_types.plugin
To enable message boxes, call the controller's add_plugin method with this object as argument. This can e.g. be done in the post_add_hook of the processor.

How to use this module:

  • Encapsulate the type of the messages:
     module Msg_type = struct type t = <some_type> end 
  • Create the box module for this type:
     module Mbox_type = Netplex_mbox.Make_mbox_type(Msg_type) 
  • Call functions of this module, e.g.
    let box = Mbox_type.create "my_box"
    let msg = Mbox_type.receive box
          

module type MBOX = sig .. end
The type of mailboxes mbox with messages of type t
module Make_mbox_type: 
functor (T : Netplex_cenv.TYPE) -> MBOX with type t = T.t
Create a new mailbox access module for message type T.t
ocamlnet-4.1.2/doc/html-main/Netgzip.input_inflate-c.html0000644000175000017500000004304112731530353021771 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.input_inflate

Class Netgzip.input_inflate

class input_inflate : Netchannels.in_obj_channel -> Netchannels.in_obj_channel
let ch' = new input_inflate ch: Reading data from ch' inflates data read from ch. Use this for uncompressing data while reading.

Note that ch isn't closed when ch' is closed.


ocamlnet-4.1.2/doc/html-main/type_Netnumber.HO.html0000644000175000017500000004055012731530353020600 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber.HO ENCDECocamlnet-4.1.2/doc/html-main/Netglob.html0000644000175000017500000014450412731530353016671 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob

Module Netglob

module Netglob: sig .. end
Globbing


Globbing resolves shell wildcards like "*" and "?". For example,

    let files = Netglob.glob (`String "*.cm[iox]")
    

would return all files matching this pattern (e.g. module.cmi, module.cmo).

The main user function is Netglob.glob. Globbing accesses the local filesystem by default, but one can also run the globbing algorithm on any other filesystem, provided the access primitives of Netglob.glob_fsys are available.

Globbing resolves shell wildcards like "*" and "?". For example,

    let files = Netglob.glob (`String "*.cm[iox]")
    

would return all files matching this pattern (e.g. module.cmi, module.cmo).

The main user function is Netglob.glob. Globbing accesses the local filesystem by default, but one can also run the globbing algorithm on any other filesystem, provided the access primitives of Netglob.glob_fsys are available.

Types and exceptions


type glob_expr = glob_expr_atom list 
type glob_expr_atom = [ `Brace of glob_expr list
| `Bracket of bool * glob_set
| `Literal of string
| `Qmark
| `Star
| `Tilde of string ]
Atoms:

  • `Literal s: Matches the string literally. The string must not be empty. The backslash is not an escape character, but matches the backslash character.
  • `Star: The "*" operator
  • `Qmark: The "?" operator
  • `Bracket(negated,set): The [...] operator. The set argument describes the characters that are matched. The negated argument is true when the expression is negated (i.e. [^...]).
  • `Brace l: The {e1,e2,...} operator
  • `Tilde t: The ~username operator. If t="" the current user is meant. The `Tilde atom may only occur at the beginning of the list. The `Tilde atom always matches a directory, and must be followed by a literal slash (if anything follows).
Compatibility: Conforms to POSIX with extensions (braces). Shells often implement brace expressions in a slightly different way (braces are parsed and expanded in a separate step before the other pattern constructors are handled). The cases where this leads to different results are quite exotic (e.g. "{~g,~h}1" would mean "~g1 ~h1", but this implementation rejects the pattern).
type glob_set = <
   set : (int * int) list;
>
A set of code points is given as a list of ranges (from,to), with from <= to. It is allowed that ranges overlap.
type valid_glob_expr 
A validated glob_expr
class type user_info = object .. end
Access to the user database
class type glob_fsys = object .. end
Filesystem primitives.
type glob_mode = [ `All_paths | `All_words | `Existing_paths ] 
Modes:
  • `Existing_paths: Only paths are returned that really exist
  • `All_paths: Generated paths not including *, ? and bracket expressions are returned even if they do not exist. For example, globbing for "fictive{1,2,3}" would return ["ficitve1";"fictive2";"fictive3"] independent of whether these files exist.
  • `All_words: Patterns that cannot be resolved are returned as-is (like the shell does)

type pattern = [ `Expr of valid_glob_expr | `String of string ] 
Input for Netglob.glob
exception Bad_glob_expr of string
An syntax error in the glob expression; the argument is the bad expression
exception Unsupported_expr of string
The notations :class:, .symbol., =eqclass= inside ... are not supported by this implementation. If they are found, this exception will be raised, and the argument is the whole glob expression

Parsing and printing


val parse_glob_expr : ?encoding:Netconversion.encoding ->
?enable_star:bool ->
?enable_qmark:bool ->
?enable_brackets:bool ->
?enable_braces:bool ->
?enable_tilde:bool ->
?enable_escape:bool -> string -> valid_glob_expr
Parses the glob expression. By default, all syntax features are enabled. May raise Bad_glob_expr or Unsupported_expr.

The glob expressions are POSIX-compliant with the extension of brace expressions, and tildes, and the omission of internationalized bracket expressions:

  • *: Matches a sequence of zero or more arbitrary characters
  • ?: Matches one arbitrary character
  • [abc]: Matches one of the mentioned characters
  • [a-z]: Matches one of the characters of the range. This is here only permitted when the range falls into the ASCII set. (Otherwise the interpretation would be dependent on the encoding.) Note that the ASCII restriction does not comply to POSIX.
  • [!expr] or [^expr]: Negates the bracket expression
  • {expr,expr,...}: Generates a string for each of the alternatives. A brace expression is even recognized if there is no comma, or even no contents (i.e. "{expr}" and "{}"). The elements of brace expressions may be again glob expressions; nested brace expressions are allowed.
  • ~username: Generates the home directory of this user
  • ~: Generates the home directory of the current user
  • If enabled, the backslash character is the escape character. Within bracket expressions, the backslash character never escapes.
  • Not supported: Collating symbols [.a.], equivalence classes [=a=], and character classes [:name:]. If they are found, the exception Unsupported_expr will be raised.
Glob expressions have a character encoding. This defaults to `Enc_iso88591. Encodings must be ASCII-compatible.
val validate_glob_expr : Netconversion.encoding -> glob_expr -> valid_glob_expr
Checks whether the passed expression is syntactically valid. If so, a validated expression is returned. Otherwise, this function fails.
val recover_glob_expr : valid_glob_expr -> glob_expr
Returns the explicit representation
val encoding_of_glob_expr : valid_glob_expr -> Netconversion.encoding
Returns the encoding
val literal_glob_expr : Netconversion.encoding -> string -> valid_glob_expr
Returns an expression that matches literally the passed string
val print_glob_expr : ?escape_in_literals:bool -> valid_glob_expr -> string
Prints the glob expression as string. Meta characters are escaped by a backslash when possible. Meta characters are: "*", "?", "["], ["]", "{", "}", ",", "~" and "\\"

  • escape_in_literals: Whether meta characters in `Literal subexpressions are escaped. This is true by default.


Operations on valid_glob_expr


val expand_glob_expr : ?user_info:user_info ->
?expand_brace:bool ->
?expand_tilde:bool -> valid_glob_expr -> valid_glob_expr list
Resolve generative sub expressions by expanding them. The returned list of glob expr no longer contains the expanded constructions.

  • expand_brace: Expands `Brace subexpressions.
  • expand_tilde: Expands `Tilde subexpressions.
  • user_info: The subset of file system operations needed for tilde expansion. Defaults to Netglob.local_user_info (see below).
Both expand_* options are enabled by default.
val match_glob_expr : ?protect_period:bool ->
?protect_slash:bool ->
?encoding:Netconversion.encoding -> valid_glob_expr -> string -> bool
Matches the glob_expr against a string.

The input must neither contain brace expressions nor tildes (i.e. call expand_glob_expr first). The function fails if it encounters such an expression.

  • protect_period: If true, a leading period cannot be not matched by *, ?, [...], but only by a literal .. A leading period is a . at the beginning of the string to be matched against, or if also protect_slash a . after a /
  • protect_slash: If true, a slash cannot be matched by *, ?, [...], but only by a literal /
Both options are enabled by default.

  • encoding: The encoding of the string argument. Defaults to the encoding of the glob pattern.

val split_glob_expr : valid_glob_expr -> valid_glob_expr list
Splits the glob expression into filename components separated by literal / characters. For example, for the glob expression "a*b/c/d?", the list ["a*b"; "c"; "d?"] is returned.

If the first component begins with a slash, the slash is not removed from the first returned list element, e.g. for "/ab/c*", the list [ "/ab"; "c*" ] is computed. Use check_rooted_glob_expr to test this case.

Several adjacent slashes are handled like a single slash. E.g. for "a//b", the list ["a"; "b"] is returned.

If the last component ends with a slash, it is not removed from the returned list element, e.g. for "a/b/", the list [ "a"; "b/" ] is returned. Use check_directory_glob_expr to test this case.

The glob expression passed to this function must not contain brace or tilde expressions.

val check_rooted_glob_expr : valid_glob_expr -> valid_glob_expr option
If the glob expression matches the root directory (i.e. the expression begins with a literal /), the function returns Some expr', where expr' matches the path relative to the root directory (i.e. the expression without the / at the beginning).

Otherwise, None is returned.

Example: For "/a/b*", the expression "a/b*" is returned.

Special case: for "/", the expression "" (only matching the empty string) is returned.

The glob expression passed to this function must not contain brace or tilde expressions.

val check_directory_glob_expr : valid_glob_expr -> valid_glob_expr option
If the last component of the glob expression matches only directories because it ends with a literal / character, the value Some expr' is returned where expr' matches the same path without the trailing /.

Otherwise, None is returned.

Example: For "a/b*/", the expression "a/b*" is returned.

Special case: for "/", the expression "" (only matching the empty string) is returned.

The glob expression passed to this function must not contain brace or tilde expressions.


Globbing


val glob : ?encoding:Netconversion.encoding ->
?base_dir:string ->
?protect_period:bool ->
?fsys:glob_fsys ->
?user_info:user_info ->
?mode:glob_mode -> pattern -> string list
Forms a set of filenames as described below, and matches this set against the pattern. The pattern can be given as a `String s in which case s is parsed (with all features enabled, and it is assumed it has the passed encoding). Alternatively, an already parsed `Expr e can be given. (Note that encoding is ignored in this case.)

Slashes must be explicitly matched: "/" must literally occur in order to be a candidate for matching. It is not matched by * or ? or a bracket expression.

Periods: The leading period is protected if protect_period. It must then also literally occur to be matched.

Anchoring: If the glob_expr begins with a literal "/", the set of filenames is anchored at the root directory; otherwise the set is anchored at the current directory or, if base_dir is passed, at this directory. (If fsys is passed, it is required to also set base_dir.)

Initially, the set contains all files of the anchor directory (for the root directory, a "/" is prepended).

After that, the set is extended by adding the paths of subdirectories relative to the anchor directory. Note that the constructed set is always infinite, because "." and ".." are not handled specially, and are also regarded as "subdirectories". However, after applying the matching criterion, the returned list is always finite.

Note that the anchor directory itself is not part of the generated set. For example, for the expression "/*" the root directory "/" is not returned. As an exception of this rule, for the glob expression "/" the file "/" is returned.

Braces: Brace expressions are handled by expanding them first, even before filename generation starts.

Mode: By default, only existing paths are returned (mode=`Existing_paths). If no files match, the empty list is returned (and not the pattern as the shell does). By passing a different mode, this can be changed:

  • `All_paths: It is allowed that non-existing paths are returned when the paths do not contain *, ?, or [ metacharacters after the brace expansion. Path expressions with these metacharacters are still checked for existence.
  • `All_words: When an expression does not refer to existing paths, it is returned as such, leaving the metacharacters *, ?, [ unexpanded (i.e., what the Bourne shell does). Note that either all metacharacters are resolved, or none, but not a subset of them.
Encodings: Often, only the pattern has an encoding, but not the filesystem (as in Unix). In this case, no conversion is attempted, and the byte representation of the pattern is matched with the byte representation of the filenames. Good luck.

If the filesystem has an encoding, however, conversions may be required, and this can cause problems. Usually, network filesystems provide an encoding, and the Win32 local filesystem. (For Unix, one can pass a custom fsys with encoding knowledge.) Conversion problems can be avoided if (1) the encoding of the pattern is a superset of the filename encoding. Also, (2) one should not use literals in the pattern that cannot be represented in the filename encoding. If (2) cannot be satisfied, ensure you have at least mode=`Existing_paths, i.e. the default mode (this removes results from the returned list when a conversion problem occurs).

The return value of glob is encoded in the encoding of the filesystem if the filesystem provides an encoding. (If you want to check this encoding, pass fsys, e.g. as local_fsys(), and call the path_encoding method of fsys.)


Remarks



Remarks



Examples demonstrating the effect of encodings: (Linux)

       let fsys = local_fsys ~encoding:`Enc_utf8()
       let l = glob ~fsys (`String "\214*")
    

The byte 214 is O-umlaut in ISO-8859-1 (the default encoding for patterns). By passing an fsys argument we change the encoding for filenames to UTF-8. For example, if

"\195\150ffentlich"

was a file in the current directory, it would be found and returned in l.

Conversions: For example, assume we have a file "\226\130\172uro" (EUR-uro in UTF-8). The glob

       let fsys = local_fsys ~encoding:`Enc_utf8()
       let l = glob ~fsys (`String "*")
    

finds it although the euro sign cannot be represented in ISO-8859-1, the default pattern encoding.

We run into a problem, however, if we want to generate the euro sign even if the file is not present, and the filesystem uses an encoding that does not include this sign:

       let fsys = local_fsys ~encoding:`Enc_iso88591()
       let l = glob ~fsys ~encoding:`Enc_utf8 ~mode:`All_paths 
                  (`String "\226\130\172uro")
    

This raises an exception Netconversion.Cannot_represent 8364.

Remarks



Examples demonstrating the effect of encodings: (Linux)

       let fsys = local_fsys ~encoding:`Enc_utf8()
       let l = glob ~fsys (`String "\214*")
    

The byte 214 is O-umlaut in ISO-8859-1 (the default encoding for patterns). By passing an fsys argument we change the encoding for filenames to UTF-8. For example, if

"\195\150ffentlich"

was a file in the current directory, it would be found and returned in l.

Conversions: For example, assume we have a file "\226\130\172uro" (EUR-uro in UTF-8). The glob

       let fsys = local_fsys ~encoding:`Enc_utf8()
       let l = glob ~fsys (`String "*")
    

finds it although the euro sign cannot be represented in ISO-8859-1, the default pattern encoding.

We run into a problem, however, if we want to generate the euro sign even if the file is not present, and the filesystem uses an encoding that does not include this sign:

       let fsys = local_fsys ~encoding:`Enc_iso88591()
       let l = glob ~fsys ~encoding:`Enc_utf8 ~mode:`All_paths 
                  (`String "\226\130\172uro")
    

This raises an exception Netconversion.Cannot_represent 8364.

Notes for Win32:

  • Globbing only supports forward slashes, not backslashes as path separators
  • Globbing does neither recognize drive letters nor UNC paths as special cases. This may lead to subtle bugs. Glob expressions like "c:/file.*" may or may not work depending on the context.
  • The usually case-insensitive file system is not taken into account. (To be fixed.)


Remarks



Examples demonstrating the effect of encodings: (Linux)

       let fsys = local_fsys ~encoding:`Enc_utf8()
       let l = glob ~fsys (`String "\214*")
    

The byte 214 is O-umlaut in ISO-8859-1 (the default encoding for patterns). By passing an fsys argument we change the encoding for filenames to UTF-8. For example, if

"\195\150ffentlich"

was a file in the current directory, it would be found and returned in l.

Conversions: For example, assume we have a file "\226\130\172uro" (EUR-uro in UTF-8). The glob

       let fsys = local_fsys ~encoding:`Enc_utf8()
       let l = glob ~fsys (`String "*")
    

finds it although the euro sign cannot be represented in ISO-8859-1, the default pattern encoding.

We run into a problem, however, if we want to generate the euro sign even if the file is not present, and the filesystem uses an encoding that does not include this sign:

       let fsys = local_fsys ~encoding:`Enc_iso88591()
       let l = glob ~fsys ~encoding:`Enc_utf8 ~mode:`All_paths 
                  (`String "\226\130\172uro")
    

This raises an exception Netconversion.Cannot_represent 8364.

Notes for Win32:

  • Globbing only supports forward slashes, not backslashes as path separators
  • Globbing does neither recognize drive letters nor UNC paths as special cases. This may lead to subtle bugs. Glob expressions like "c:/file.*" may or may not work depending on the context.
  • The usually case-insensitive file system is not taken into account. (To be fixed.)


Default access objects


class local_user_info : unit -> user_info
val local_user_info : unit -> user_info
Get the home directory of a user from the local user database.
class local_fsys : ?encoding:Netconversion.encoding -> unit -> glob_fsys
val local_fsys : ?encoding:Netconversion.encoding -> unit -> glob_fsys
Accesses the local filesystem
class of_stream_fs : #Netfs.stream_fs -> glob_fsys
val of_stream_fs : #Netfs.stream_fs -> glob_fsys
Use an arbitrary network filesystem for globbing

Compatibility

This implementation is not fully compatible with the POSIX specs. The differences:

  • Missing support for character classes, equivalence classes and collating symbols.
  • Ranges in brackets are restricted to ASCII.
  • Unparseable patterns are indicated by exceptions. POSIX, however, requires that such patterns are taken literally. E.g. a pattern "[" would match a left bracket in POSIX, but this module throws a syntax error.
  • If the slash character is protected, it is still allowed inside brackets. POSIX, however, requires that the pattern is scanned for slashes before brackets. For instance, the pattern "[a/b*]" is scanned as [`Literal "[a/b]"; `Star] following the POSIX rules while this implementation sees a bracket expression with "a", "b", "/" and "*" characters.
  • The "^" character negates the set if used at the beginning of bracket expressions. POSIX leaves this unspecified.
  • Brace expresions are an extension (although commonly implemented in shells).
  • The default globbing mode is `Existing_paths which is not defined by POSIX. Use `All_paths for getting POSIX behavior.
Compared with popular shells, there are some subtle differences in how the various syntax elements (wildcards, braces, tildes) are parsed and processed. Shells do it in this order:
  • Parse and expand brace expressions
  • Parse and expand tildes
  • Split the paths at slashes into path components
  • Parse and expand wildcards
For example, after expanding braces it is possible to see totally new tilde or wildcard expressions, e.g. "~user{1,2}/file" would be legal. This implementation here does not support this - we first parse the expression, and then interpret it. However, users interested in a higher degree of compatibility can call the Netglob parsing, processing and printing functions in the required order, and emulate the shell behavior. For example,

  let alt_glob pat =
    let g1 = 
       parse_glob_expr 
         ~enable_star:false ~enable_qmark:false ~enable_brackets:false
         ~enable_tilde:false        (* only braces remain enabled *)
          pat in
    let g2_list = 
       expand_glob_expr g1 in
    let pat2_list = 
       List.map (print_glob_expr ~escape_in_literals:false) g2_list in
    let g3_list =
       List.map
         (fun pat2 -> parse_glob_expr ~enable_braces:false pat2) 
         pat2_list in
    List.flatten
      (List.map (fun g3 -> glob (`Expr g3)) g3_list)
    

would parse and expand brace expressions in a separate step before running glob on the remaining syntactic elements.
ocamlnet-4.1.2/doc/html-main/Netstream.in_obj_stream-c.html0000644000175000017500000004650012731530353022270 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstream.in_obj_stream

Class type Netstream.in_obj_stream

class type in_obj_stream = object .. end
An in_obj_stream extends in_obj_channel by look-ahead methods
Inherits
  • Netchannels.in_obj_channel The normal input operations work as usual. The window is moved after every read sequence of bytes by exactly the number of bytes, and if the window length becomes smaller than the block size, it will be ensured that the window will be enlarged to the block size (or to the rest of the stream until EOF, whatever is smaller).

method block_size : int
The block size of the stream
method window : Netbuffer.t
The look-ahead window. The first byte of the window is the byte that would be read next by input_char. The length of the window is returned by the method window_length. This length may be smaller than the current length of the netbuffer, i.e. the netbuffer may contain additional data that must be ignored.
method want : int -> unit
Increases the length of the window such that the length is at least the passed number of bytes or that the window reaches EOF (whatever happens first).
method want_another_block : unit -> unit
The same as: want block_size
method window_length : int
Returns the length of the window
method window_at_eof : bool
Whether the window is at eof
method skip : int -> unit
Skip the n bytes of the stream. It is not an error to skip more bytes than available in the remaining stream.
ocamlnet-4.1.2/doc/html-main/Netftp_data_endpoint.html0000644000175000017500000007113412731530353021426 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint

Module Netftp_data_endpoint

module Netftp_data_endpoint: sig .. end
Senders and receivers for the FTP data connection


Types and Exceptions


type ftp_data_prot = [ `C | `E | `P | `S ] 
type ftp_protector = {
   ftp_wrap_limit : unit -> int;
   ftp_wrap_s : string -> string;
   ftp_wrap_m : Netsys_types.memory -> Netsys_types.memory -> int;
   ftp_unwrap_s : string -> string;
   ftp_unwrap_m : Netsys_types.memory -> Netsys_types.memory -> int;
   ftp_prot_level : ftp_data_prot;
   ftp_close : unit -> unit;
   mutable ftp_gssapi_props : Netsys_gssapi.client_props option;
   mutable ftp_auth_loop : bool;
}
The functions for encrypting (wrapping) and decrypting (unwrapping) messages when an RFC 2228 security layer is active.
class type out_record_channel = object .. end
An out_record_channel can be used to output files with record structure.
class type in_record_channel = object .. end
An in_record_channel can be used to read files with record structure.
type local_receiver = [ `File_structure of Netchannels.out_obj_channel
| `Record_structure of out_record_channel ]
The local_receiver is the object that gets the data received over the data connection.

Page structure is not supported.

type local_sender = [ `File_structure of Netchannels.in_obj_channel
| `Record_structure of in_record_channel ]
The local_sender is the object that provides the data sent over the data connection.

Page structure is not supported.

type transmission_mode = [ `Block_mode | `Stream_mode ] 
The transmission mode as described in RFC 959. Compressed mode is not supported.
type descr_state = [ `Clean | `Down | `Transfer_in_progress ] 
Describes the state of the socket used for data transfers. The state `Clean means that a new data transfer may be started, either because the socket is new, or the last block transfer was properly finished. The state `Transfer_in_progress means that data is being transferred, but also that the transfer is aborted. The state `Down means that the socket is already at least half-closed, i.e. EOF was sent in one direction.
type text_data_repr = [ `ASCII of Netconversion.encoding
| `ASCII_unix of Netconversion.encoding
| `EBCDIC of Netconversion.encoding ]
Possible representation of text data: `ASCII means an ASCII-compatible encoding where the newline character is represented by CR/LF. `ASCII_unix is the same but newline is only LF. `EBCDIC is an EBCDIC variant.

The argument specifies the exact variant to be used, e.g. `ASCII `Enc_iso88591 or `EBCDIC `Enc_cp1047.

It is illegal to use `ASCII or `ASCII_unix with an ASCII- incompatible encoding, as well as combining `EBCDIC with a non-EBCDIC encoding. Wrong conversions would be the result of this.


Data Stream Converters


class write_out_record_channel : repr:text_data_repr -> Netchannels.out_obj_channel -> out_record_channel
Provides an out_record_channel that represents EOR as newline character.
class read_in_record_channel : repr:text_data_repr -> Netchannels.in_obj_channel -> in_record_channel
Provides an in_record_channel that takes newline characters as EOR representation.
class data_converter : fromrepr:text_data_repr -> torepr:text_data_repr -> Netchannels.io_obj_channel
Creates a data conversion pipe converting fromrepr to torepr.

Engines


class type ftp_data_engine = object .. end
The common type of FTP data engines
class ftp_data_receiver : ?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option * string option -> ?protector:ftp_protector -> esys:Unixqueue.event_system -> mode:transmission_mode -> local_receiver:local_receiver -> descr:Unix.file_descr -> timeout:float -> timeout_exn:exn -> unit -> object .. end
This engine receives data on a FTP data connection, and forwards them to a local receiver.
class ftp_data_sender : ?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option * string option -> ?protector:ftp_protector -> esys:Unixqueue.event_system -> mode:transmission_mode -> local_sender:local_sender -> descr:Unix.file_descr -> timeout:float -> timeout_exn:exn -> unit -> object .. end
This engine sends data over a FTP data connection coming from a local sender.
ocamlnet-4.1.2/doc/html-main/type_Rpc_proxy.ManagedSet.html0000644000175000017500000005634512731530353022341 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_proxy.ManagedSet sig
  type mset
  type mset_policy = [ `Balance_load | `Failover ]
  type mset_config = {
    mset_mclient_config : Rpc_proxy.ManagedClient.mclient_config;
    mset_policy : Rpc_proxy.ManagedSet.mset_policy;
    mset_pending_calls_max : int;
    mset_pending_calls_norm : int;
    mset_idempotent_max : int;
    mset_idempotent_wait : float;
  }
  exception Cluster_service_unavailable
  val create_mset_config :
    ?mclient_config:Rpc_proxy.ManagedClient.mclient_config ->
    ?policy:Rpc_proxy.ManagedSet.mset_policy ->
    ?pending_calls_max:int ->
    ?pending_calls_norm:int ->
    ?idempotent_max:int ->
    ?idempotent_wait:float -> unit -> Rpc_proxy.ManagedSet.mset_config
  val create_mset :
    Rpc_proxy.ManagedSet.mset_config ->
    (Rpc_client.connector * int) array ->
    Unixqueue.event_system -> Rpc_proxy.ManagedSet.mset
  val mset_pick :
    ?from:int list ->
    Rpc_proxy.ManagedSet.mset -> Rpc_proxy.ManagedClient.mclient * int
  val mset_services :
    Rpc_proxy.ManagedSet.mset -> (Rpc_client.connector * int) array
  val mset_load : Rpc_proxy.ManagedSet.mset -> int array
  val event_system : Rpc_proxy.ManagedSet.mset -> Unixqueue.event_system
  val shut_down : Rpc_proxy.ManagedSet.mset -> unit
  val sync_shutdown : Rpc_proxy.ManagedSet.mset -> unit
  val trigger_shutdown : Rpc_proxy.ManagedSet.mset -> (unit -> unit) -> unit
  val idempotent_async_call :
    ?from:int list ->
    Rpc_proxy.ManagedSet.mset ->
    (Rpc_proxy.ManagedClient.mclient -> '-> ((unit -> 'b) -> unit) -> unit) ->
    '-> ((unit -> 'b) -> unit) -> unit
  val idempotent_sync_call :
    ?from:int list ->
    Rpc_proxy.ManagedSet.mset ->
    (Rpc_proxy.ManagedClient.mclient -> '-> ((unit -> 'b) -> unit) -> unit) ->
    '-> 'b
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_encap.ENCAP.html0000644000175000017500000004172212731530353021750 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_encap.ENCAP sig
  type t
  val wrap : Netplex_encap.ENCAP.t -> Netplex_encap.encap
  val unwrap : Netplex_encap.encap -> Netplex_encap.ENCAP.t
end
ocamlnet-4.1.2/doc/html-main/Netftp_data_endpoint.ftp_data_receiver-c.html0000644000175000017500000004531412731530353025314 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.ftp_data_receiver

Class Netftp_data_endpoint.ftp_data_receiver

class ftp_data_receiver : ?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option * string option -> ?protector:ftp_protector -> esys:Unixqueue.event_system -> mode:transmission_mode -> local_receiver:local_receiver -> descr:Unix.file_descr -> timeout:float -> timeout_exn:exn -> unit -> object .. end
This engine receives data on a FTP data connection, and forwards them to a local receiver. The socket must already be open.

It is ensured that local_receiver is always closed after operation (whether successful or not). The socket descr remains open.

tls: may be set to (config, peer_name, resume_data)

Inherits
method local_receiver : local_receiver
The local receiver. It is closed when the logical EOF is found in the data connection
ocamlnet-4.1.2/doc/html-main/Rpc_xti_client.html0000644000175000017500000004311112731530353020235 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_xti_client

Module Rpc_xti_client

module Rpc_xti_client: sig .. end
Minimal support for TI-RPC over the XTI API

This library has been developed for Solaris only. I do not know whether it works on other System V flavors, too.


val cots_connect : string -> string -> Unix.file_descr
The first parameter is the name of the TLI/XTI device. The second parameter is the address of the endpoint to connect. The own endpoint has always an anonymous address. The "tirdwr" module is pushed onto the STREAM such that the "read" and "write" syscalls work.
ocamlnet-4.1.2/doc/html-main/Equeue_intro.html0000644000175000017500000025674612731530353017757 0ustar gerdgerd Ocamlnet 4 Reference Manual : Equeue_intro

Equeue_intro


Introduction into programming with equeue (formerly known as "Equeue User's Guide").

Contents

Introduction into event-driven programming

Event-driven programming is an advanced way of organizing programs around I/O channels. This may be best explained by an example: Consider you want to read from a pipeline, convert all arriving lowercase letters to their corresponding uppercase letters, and finally write the result into a second pipeline.

A conventional solution works as follows: A number of bytes is read from the input pipeline into a buffer, converted, and then written into the output pipeline. Because we do not know at the beginning how many bytes will arrive, we do not know how big the buffer must be to store all bytes; so we simply decide to repeat the whole read/convert/write cycle until the end of input is signaled.

In O'Caml code:

let buffer_length = 1024 in
let buffer = String.create buffer_length in
try
  while true do
    (* Read up to buffer_length bytes into the buffer: *)
    let n = Unix.read Unix.stdin buffer 0 buffer_length in
    (* If n=0, the end of input is reached. Otherwise we have 
     * read n bytes. 
     *)
    if n=0 then
      raise End_of_file;
    (* Convert: *)
    let buffer' = String.uppercase (String.sub buffer 0 n) in
    (* Write the buffer' contents: *)
    let m = ref 0 in
    while !m < n do
      m := !m + Unix.write Unix.stdout buffer' !m (n - !m)
    done
  done
with 
  End_of_file -> ()

The input and output pipelines may be connected with any other endpoint of pipelines, and may be arbitrary slow. Because of this, there are two interesting phenomenons. First, it is possible that the Unix.read system call returns less than buffer_length bytes, even if we are not almost at the end of the data stream. The reason might be that the pipeline works across a network connection, and that just a network packet arrived with less than buffer_length bytes. In this case, the operating system may decide to forward this packet to the application as soon as possible (but it is free not to decide so). The same may happen when Unix.write is called; because of this the inner while loop invokes Unix.write repeatedly until all bytes are actually written.

Nevertheless, Unix.read guarantees to read at least one byte (unless the end of the stream is reached), and Unix.write always writes at least one byte. But what happens if there is currently no byte to return? In this case, the second phenomenon happens: The program stops until at least one byte is available; this is called blocking.

Consider that the output pipeline is very fast, and that the input pipeline is rather slow. In this case, blocking slows down the program such that it is as slow as the input pipeline delivers data.

Consider that both pipelines are slow: Now, the program may block because it is waiting on input, but the output pipeline would accept data. Or, the program blocks because it waits until the output side is ready, but there have already input bytes arrived which cannot be read in because the program blocks. In these cases, the program runs much slower than it could do if it would react on I/O possibilities in an optimal way.

The operating systems indicates the I/O possibilities by the Unix.select system call. It works as follows: We pass lists of file descriptors on which we want to react. Unix.select also blocks, but the program continues to run already if one of the file descriptors is ready to perform I/O. Furthermore, we can pass a timeout value.

Here is the improved program:

let buffer_length = 1024 in
let in_buffer = String.create buffer_length in
let out_buffer = String.create buffer_length in
let out_buffer_length = ref 0 in
let end_of_stream = ref false in
let waiting_for_input = ref true in
let waiting_for_output = ref false in

while !waiting_for_input or !waiting_for_output do
  (* If !waiting_for_input, we are interested whether input arrives.
   * If !waiting_for_output, we are interested whether output is 
   * possible.
   *)
  let (in_fd, out_fd, oob_fd) = 
    Unix.select (if !waiting_for_input then [ Unix.stdin] else [])
                (if !waiting_for_output then [ Unix.stdout] else [])
                []
                (-.1.0) in

  (* If in_fd is non-empty, input is immediately possible and will 
   * not block. 
   *)
  if in_fd <> [] then begin
    (* How many bytes we can read in depends on the amount of 
     * free space in the output buffer.
     *)
    let n = buffer_length - !out_buffer_length in
    assert(n > 0);
    let n' = Unix.read Unix.stdin in_buffer 0 n in
    end_of_stream := (n' = 0);
    (* Convert the bytes, and append them to the output buffer. *)
    let converted = String.uppercase (String.sub in_buffer 0 n') in
    String.blit converted 0 out_buffer !out_buffer_length n';
    out_buffer_length := !out_buffer_length + n';
  end;

  (* If out_fd is non-empty, output is immediately possible and 
   * will not block.
   *)
  if out_fd <> [] then begin
    (* Try to write !out_buffer_length bytes. *)
    let n' = Unix.write Unix.stdout out_buffer 0 !out_buffer_length in
    (* Remove the written bytes from the out_buffer: *)
    String.blit out_buffer n' out_buffer 0 (!out_buffer_length - n');
    out_buffer_length := !out_buffer_length - n'
  end;

  (* Now find out which event is interesting next: *)

  waiting_for_input :=                   (* Input is interesting if...*)
    not !end_of_stream &&                (* ...we are before the end *)
    !out_buffer_length < buffer_length;  (* ...there is space in the out buf *)

  waiting_for_output :=                  (* Output is interesting if... *)
    !out_buffer_length > 0;              (* ...there is material to output *)

done

Most important, we must now track the states of the I/O connections ourselves. The variable end_of_stream stores whether the end of the input stream has been reached. In waiting_for_input it is stored whether we are ready to accept input data. We can only accept input if there is space in the output buffer. The variable waiting_for_output indicates whether we have data to output or not. In the previous program, these states were implicitly encoded by the "program counter", i.e. which next statement was to be executed: After the Unix.read was done we knew that we had data to output; after the Unix.write we knew that there was again space in the buffer. Now, these states must be explicitly stored in variables because the structure of the program does not contain such information anymore.

This program is already an example of event-driven programming. We have two possible events: "Input arrived", and "output is possible". The Unix.select statement is the event source, it produces a sequence of events. There are two resources which cause the events, namely the two file descriptors. We have two event handlers: The statements after if in_fd <> [] then form the input event handler, and the statements after if out_fd <> [] then are the output event handler.

The Equeue module now provides these concepts as abstractions you can program with. It is a general-purpose event queue, allowing to specify an arbitrary event source, to manage event handlers, and offering a system how the events are sent to the event handlers that can process them. The Unixqueue module is a layer above Equeue and deals with file descriptor events. It has already an event source generating file descriptor events using the Unix.select system call, and it provides a way to manage file descriptor resources.

Especially the Unixqueue abstraction is an interesting link between the operating system and components offering services on file descriptors. For example, it is possible to create one event queue, and to attach several, independent components to this queue, and to invoke these components in parallel. For instance, consider a HTTP proxy. Such proxies accept connections and forward them to the service that can best deal with the requests arriving. These services are typically a disk cache, a HTTP client, and an FTP client. Using the Unixqueue model, you can realize this constellation by creating one event queue, and by attaching the services to it which can be independently programmed and tested; finally these components communicate either directly with the outer world or with other components only by putting events onto the queue and receiving events from this queue.

The Equeue module

Description

The (abbreviated) interface of the Equeue module

type 'a t              (* Event systems over events of type 'a *)

exception Reject       (* Possible reaction of an event handler *)
exception Terminate    (* Possible reaction of an event handler *)

exception Out_of_handlers     (* Error condition *)

val create      : ('a t -> unit) -> 'a t
val add_event   : 'a t -> 'a -> unit
val add_handler : 'a t -> ('a t -> 'a -> unit) -> unit
val run         : 'a t -> unit

See also the full interface of Equeue.

The values of type Equeue.t are called event systems, and contain:

  • An event source, which is simply a function that gets the event system as argument and that may add further events to the system by invoking Equeue.add_event. The event source must be passed to Equeue.create as argument; it is not possible to change the source later.
  • A list of event handlers. Handlers are added to the system by calling Equeue.add_handler.
  • A queue of events waiting to be delivered to one of the handlers. You can add an event to the queue by invoking Equeue.add_event.
The module is intended to be used as follows: First, an event system is created, and initialized with an event source. Some event handlers are added:

let some_source esys = ... in

let handler1 esys e = ... in
let handler2 esys e = ... in
... (* more handlers *)

let esys = Equeue.create some_source in
Equeue.add_handler esys handler1;
Equeue.add_handler esys handler2;
... (* more handlers *)

It is necessary that at least one handler is added. In the second step, the event system can be started:

Equeue.run esys

This means the following:

  • At the beginning, the function realizing the event source is called once. The function has the chance to add the first event(s) to the event queue by calling Equeue.add_event.
  • If the event queue is not empty: It is iterated over all events currently in the queue. Every event is tried to be delivered to a handler by the simplest possible algorithm: The handlers are tried in turn, and the first handler that wants to consume the event gets the event.
  • After one round of iteration over all events, it is possible that the handlers did already add further events to the queue, or it is possible that the queue is now empty. In the first case, the iteration is simply repeated with the newly added events. In the second case, the event source is called. If there are now events, they are iterated.
  • Otherwise, the event system terminates.
A handler can indicate either that it wants to consume the event, or that it rejects the event, or that it wants to be removed from the list of handlers. Consumption is indicated by returning normally. Rejection is indicated by raising the Equeue.Reject exception. If the handler raises the Equeue.Terminate exception, the event is consumed and the handler is removed from the list of handlers.

Other exceptions, either raised within the event source function or within a handler function, simply fall through the event loop; they are not caught. However, the event system is restartable, which means:

  • If the exception happened within the event source, the source is called again.
  • If the exception happened within a handler function, the current event is scheduled again.
The event source is called when there are no events in the equeue. Note that the event source may not only add events, but also event handlers. It is an error if after the invocation of the event source there are events in the queue, but no handlers are defined. In this case, the exception Out_of_handlers is raised.

A silly example

Two kinds of events:

type event = 
  A of int
| B

This event source produces ten events from A 1 to A 10:

let n = ref 1
let source esys =
  if !n <= 10 then begin
    Equeue.add_event esys (A !n);
    incr n
  end

The handler for type A events puts as many type B events on the queue as the argument counts.

let handler_a esys e =
  match e with 
    A n ->
      for i = 1 to n do
        Equeue.add_event esys B
      done
  | _ ->
      raise Equeue.Reject

The handler for type B events simply prints the events:

let handler_b esys e =
  match e with
    B ->
      print_endline "B"
  | _ ->
      raise Equeue.Reject

Finally, we set up the event system and start it:

let esys = Equeue.create source in
Equeue.add_handler esys handler_a;
Equeue.add_handler esys handler_b;
Equeue.run esys;

As result, the program prints 55 Bs.

The Unixqueue module

Description

The (abbreviated) interface of the Unixqueue module

open Unix
open Sys

type group                          (* Groups of events *)
type wait_id                        (* Wait ticket *)

type operation =
    Wait_in  of file_descr          (* wait for input data *)
  | Wait_out of file_descr          (* wait until output can be written *)
  | Wait_oob of file_descr          (* wait for out-of-band data *)
  | Wait of wait_id                 (* wait only for timeout *)

type event =
    Input_arrived of (group * file_descr)
  | Output_readiness of (group * file_descr)
  | Out_of_band of (group * file_descr)
  | Timeout of (group * operation)
  | Signal
  | Extra of exn

type event_system

val create_unix_event_system : unit -> event_system
val new_group : event_system -> group
val new_wait_id : event_system -> wait_id
val add_resource : event_system -> group -> (operation * float) -> unit
val remove_resource : event_system -> group -> operation -> unit
val add_handler : 
          event_system -> group -> 
          (event_system -> event Equeue.t -> event -> unit) 
             -> unit
val add_event : event_system -> event -> unit
val clear : event_system -> group -> unit
val run : event_system -> unit

See also the full interface of Unixqueue.

Subject of this module are four types of operations: Waiting for input data Wait_in, waiting for output readiness Wait_out, waiting for out-of-band data Wait_oob, and waiting for a period of time Wait. You can associate resources with the operations which simply means that it is waited until one of the operations becomes possible or is timed out. Resources are the combination of an operation and a time-out value.

This module already implements an event source which checks whether the operations are possible or timed-out, and which generates events describing what has happended. As with Equeue you can add events yourself, and you can add handlers which perform actions on certain events. As Unixqueue is based on Equeue, the queue model is simply the same.

Resources, handlers and events are grouped, i.e. you can reference to a bundle of resources/events by specifying the group they belong to. Groups are created by Unixqueue.new_group, and every resource must belong to a group. The events caused by a resource belong to the same group as the resource. Handlers have a group, too, and the handlers only get events of the same group.

The groups simplify clean-up actions. Especially, it is possible to remove all handlers and resouces belonging to a group with only one function call (clear).

Object-oriented interface

In addition to the functional interface, there is also an object-oriented interface. Instead of calling one of the above functions <replaceable>f</replaceable>, one can also invoke the method with the same name. For example, the call

add_resource ues g (op,t)

can also be written as

ues # add_resource g (op,t)

Both styles can be used in the same program, and there is absolutely no difference (actually, the object-oriented interface is even the fundamental interface, and the functions are just wrappers for the method calls).

Instead of creating the event system with

let ues = create_unix_event_system()

one can also use

let ues = new unix_event_system()

Again, both calls do exactly the same.

The object-oriented interface has been introduced to support other implementations of file descriptor polling than Unix.select. The integration into the Tcl and Glib event systems has been implemented by defining additional classes that are compatible with Unixqueue.unix_event_system, but internally base on different polling mechanisms.

Example: Copying several files in parallel

We present here a function which adds a file copy engine to an event system. It is simple to add the engine several times to the event system to copy several files in parallel.

open Unixqueue

type copy_state =
    { copy_ues    : Unixqueue.event_system;      
      copy_group  : Unixqueue.group;             
      copy_infd   : Unix.file_descr;             
      copy_outfd  : Unix.file_descr;
      copy_size   : int;
      copy_inbuf  : string;
      copy_outbuf : string;
      mutable copy_outlen      : int;
      mutable copy_eof         : bool;
      mutable copy_have_inres  : bool;
      mutable copy_have_outres : bool;
      mutable copy_cleared     : bool;
    }

This record type contains the state of the engine.

  • copy_ues: The event system to which the engine is attached
  • copy_group: The group to which all the entities belong
  • copy_infd: The file descriptor of the source file
  • copy_outfd: The file descriptor of the copy file
  • copy_size: The size of copy_inbuf and copy_outbuf
  • copy_inbuf: The string buffer used to read the bytes of the source file
  • copy_outbuf: The string buffer used to write the bytes to the copy file
  • copy_outlen: The portion of copy_outbuf that is actually used
  • copy_eof: Whether the EOF marker has been read or not
  • copy_have_inres: Whether there is currently an input resource for the input file
  • copy_have_outres: Whether there is currently an output resource for the output file
  • copy_cleared: Whether the copy is over or not
Now the core function begins:

let copy_file ues old_name new_name =
  (* Adds the necessary handlers and actions to the Unixqueue.event_system
   * ues that copy the file 'old_name' to 'new_name'.
   *)

Several inner functions are defined now. First, update_resources adds or removes the resources involved into copying. The record components copy_have_inres and copy_have_outres store whether there is currently a resource for input and for output, respectively. It is computed whether a input or output resource is wanted; and then the resource is added or removed as needed. If both resources are deleted, the file descriptors are closed, and the event system is cleaned.

We want input if there is space in the output buffer, and the end of the input file has not yet been reached. If this is true, it is ensured that an input resource is defined for the input file such that input events are generated.

We want output if there is something in the output buffer. In the same manner it is ensured that an output resource is defined for the output file.

Note that normally the input and output resources are added and removed several times until the complete file is copied.

  let update_resources state ues =
    let want_input_resource =
      not state.copy_eof && state.copy_outlen < state.copy_size in
    let want_output_resource =
      state.copy_outlen > 0 in
    if want_input_resource && not state.copy_have_inres then
      add_resource ues state.copy_group (Wait_in state.copy_infd, -.1.0);
    if not want_input_resource && state.copy_have_inres then
      remove_resource ues state.copy_group (Wait_in state.copy_infd);
    if want_output_resource && not state.copy_have_outres then
      add_resource ues state.copy_group (Wait_out state.copy_outfd, -.1.0);
    if not want_output_resource && state.copy_have_outres then
      remove_resource ues state.copy_group (Wait_out state.copy_outfd);
    state.copy_have_inres <- want_input_resource;
    state.copy_have_outres <- want_output_resource;
    if not want_input_resource && not want_output_resource && 
      not state.copy_cleared 
    then begin
      (* Close file descriptors at end: *)
      Unix.close state.copy_infd;
      Unix.close state.copy_outfd;
      (* Remove everything: *)
      clear ues state.copy_group;
      state.copy_cleared <- true;   (* avoid to call 'clear' twice *)
    end
  in

The input handler is called only for input events belonging to our own group. It is very similar to the example in the introductory chapter.

The input handler calls update_resource after the work is done. It is now possible that the output buffer contentains data after it was previously empty, and update_resource will then add the output resource. Or, it is possible that the output buffer is now full, and update_resource will then remove the input resource such that no more input data will be accepted. Of course, both conditions can happen at the same time.

  let handle_input state ues esys e =
    (* There is data on the input file descriptor. *)
    (* Calculate the available space in the output buffer: *)
    let n = state.copy_size - state.copy_outlen in
    assert(n > 0);
    (* Read the data: *)
    let n' = Unix.read state.copy_infd state.copy_inbuf 0 n in
    (* End of stream reached? *)
    state.copy_eof <- n' = 0;
    (* Append the read data to the output buffer: *)
    String.blit state.copy_inbuf 0 state.copy_outbuf state.copy_outlen n';
    state.copy_outlen <- state.copy_outlen + n';
    (* Add or remove resources: *)
    update_resources state ues
  in

The output handler is called only for output events of our own group, too.

The output handler calls update_resource after the work is done. It is now possible that the output buffer has space again, and update_resource will add the input resource again. Or, th output buffer is even empty, and update_resource will also remove the output resource.

  let handle_output state ues esys e =
    (* The file descriptor is ready to output data. *)
    (* Write as much as possible: *)
    let n' = Unix.write state.copy_outfd state.copy_outbuf 0 state.copy_outlen 
    in
    (* Remove the written bytes from the output buffer: *)
    String.blit 
      state.copy_outbuf n' state.copy_outbuf 0 (state.copy_outlen - n');
    state.copy_outlen <- state.copy_outlen - n';
    (* Add or remove resources: *)
    update_resources state ues
  in

This is the main event handler. It accepts only Input_arrived and Output_readiness events belonging to our own group. All other events are rejected.

  let handle state ues esys e =
    (* Only accept events associated with our own group. *)
    match e with
	Input_arrived (g,fd) ->
	  handle_input state ues esys e
      | Output_readiness (g,fd) ->
	  handle_output state ues esys e
      | _ ->
	  raise Equeue.Reject
  in

Now the body of the copy_file function follows. It contains only initializations.

  let g = new_group ues in
  let infd = Unix.openfile 
	       old_name 
	       [ Unix.O_RDONLY; Unix.O_NONBLOCK ] 
	       0 in
  let outfd = Unix.openfile 
		new_name 
		[ Unix.O_WRONLY; Unix.O_NONBLOCK; Unix.O_CREAT; Unix.O_TRUNC ] 
		0o666 in
  Unix.clear_nonblock infd;
  Unix.clear_nonblock outfd;
  let size = 1024 in
  
  let state =
    { copy_ues = ues;
      copy_group = g;
      copy_infd = infd;
      copy_outfd = outfd;
      copy_size = size; 
      copy_inbuf = String.create size;
      copy_outbuf = String.create size;
      copy_outlen = 0;
      copy_eof = false; 
      copy_have_inres = false;
      copy_have_outres = false;
      copy_cleared = false;
    } in
  
  update_resources state ues;
  add_handler ues g (handle state);
;;

Note that the files are opened in "non-blocking" mode. This ensures that the Unix.openfile system call does not block itself. After the files have been opened, the non-blocking flag is reset; the event system already guarantees that I/O will not block.

Now we can add our copy engine to an event system, e.g.

let ues = create_unix_event_system() in
copy_file ues "a.old" "a.new";
copy_file ues "b.old" "b.new";
run ues
;;

This piece of code will copy both files in parallel. Note that the concept of "groups" is very helpful to avoid that several instances of the same engine interfer with each other.

Engines

Programming directly with Unixqueues can be quite ineffective. One needs a lot of code to perform even simple problems. The question arises whether there is a way to construct event-driven code from larger units that do more complicated tasks than just looking at the possible I/O operations of file descriptors. Ideally, there would be a construction principle that scales with the problems the programmer wants to solve.

An engine is an object bound to an event system that performs a task in an autonomous way. After the engine has started, the user of the engine can leave it alone, and let it do what it has been designed for, and simply wait until the engine has completed its task. The user can start several engines at once, and all run in parallel. It is also possible to construct larger engines from more primitive ones: One can run engines in sequence (the output of the first engine is the input of the next), one can run synchronize engines (when two engines are done the results of both engines are combined into a single result), and map the results of engines to different values.

Modelling the abstract properties of engines

The formalization of engines assumes that there are four major states (see the module Uq_engines):

  type 't engine_state =
    [ `Working of int
    | `Done of 't
    | `Error of exn
    | `Aborted
    ]

A `Working engine is actively performing its task. The number argument counts the events that are processed while progressing. The state `Done indicates that the task is completed. The argument of `Done is the result value of the engine. The state `Error means that the engine ran into a problem, and cannot continue. Usually an exception was raised, and in order to be able to pass the exception to the outside world, it becomes the argument of `Error. Finally, an engine can be explictly `Aborted by calling the abort method. This forces that the engine stops and releases the resources it has allocated.

The last three states are called final states because they indicate that the engine has stopped. Once it is in a final state, the engine will never go back to `Working, and will also not transition into another final state.

There is no state for the situation that the engine has not yet begun operation. It is assumed that an engine starts performing its task right when it has been created, so the initial state is usually `Working 0.

Engines are objects that implement this class type:

  class type [ 't ] engine = object
    method state : 't engine_state
    method abort : unit -> unit
    method request_notification : (unit -> bool) -> unit
    method event_system : Unixqueue.event_system
  end

The method state reports the state the engine currently has. By calling abort the engine is aborted. The method request_notification will be explained later. Finally, event_system reports the Unixqueue event system the engine is attached to.

Examples for engine primitives and engine construction

Fortunately, there are already some primitive engines we can just instantiate, and see what they are doing. The function connector creates an engine that connects to a TCP service in the network, and returns the connected socket as result:

  val connector : ?proxy:#client_socket_connector ->
		  connect_address ->
		  Unixqueue.event_system ->
		    connect_status engine

To create and setup the engine, just call this function, as in:

  let ues = Unixqueue.create_unix_event_system() in
  let addr = `Socket(`Sock_inet_byname(Unix.SOCK_STREAM, "www.npc.de", 80)) in
  let eng = connector addr ues in
  ...

The engine will connect to the web server (port 80) on www.npc.de. It has added handlers and resources to the event system ues such that the action of connecting will be triggered when Unixqueue.run becomes active. To see the effect, just activate the event system:

  Unixqueue.run ues

When the connection is established, eng#state changes to `Done(`Socket(fd,addr)) where fd is the socket, and addr is the logical address of the client socket (which may be different than the physical address because connect supports network proxies). It is also possible that the state changes to `Error e where e is the problematic exception. Note that there is no timeout value; to limit the time of engine actions one has to attach a watchdog to the engine.

This is not yet very impressive, because we have only a single engine. As mentioned, engines run in parallel, so we can connect to several web services in parallel by just creating several engines:

  let ues = Unixqueue.create_unix_event_system() in
  let addr1 = `Socket(`Sock_inet_byname(Unix.SOCK_STREAM, "www.npc.de", 80)) in
  let addr2 = `Socket(`Sock_inet_byname(Unix.SOCK_STREAM, "caml.inria.fr", 80)) in
  let addr3 = `Socket(`Sock_inet_byname(Unix.SOCK_STREAM, "ocaml-programming.de", 80)) in

  let eng1 = connector addr1 ues in
  let eng2 = connector addr2 ues in
  let eng3 = connector addr3 ues in
  Unixqueue.run ues

Note that the resolution of DNS names is not done in the background, and may block the whole event system for a moment.

As a variant, we can also connect to one service after the other:

  let eng1 = connector addr1 ues in
  let eng123 = new seq_engine
                 eng1
                 (fun result1 ->
	            let eng2 = connector addr2 ues in
                    new seq_engine
	              eng2
                      (fun result2 ->
                         let eng3 = connector addr3 ues in
                         eng3)))

The constructor for sequential engine execution, seq_engine, expects one engine and a function as arguments. When the engine is done, the function is invoked with the result of the engine, and the function must return a second engine. The result of seq_engine is the result of the second engine.

As seq_engine occurs frequently, there is a special operator for it, ++:

  open Uq_engines.Operators

  let eng1 = connector addr1 ues in
  let eng123 = 
     eng1 ++
       (fun result1 ->
	  let eng2 = connector addr2 ues in
	  eng2 ++
            (fun result2 ->
               let eng3 = connector addr3 ues in
               eng3)))

In these examples, we have called Unixqueue.run to start the event system. This function returns when all actions are completed; this implies that finally all engines are synchronized again (i.e. in a final state). We can also synchronize in the middle of the execution by using sync_engine. In the following code snipped, two services are connected in parallel, and when both connections have been established, a third connection is started:

  let eng1 = connector addr1 ues in
  let eng2 = connector addr2 ues in
  let eng12 = new sync_engine eng1 eng2 in
  let eng123 = eng12 ++
                 (fun result12 ->
                    let eng3 = connector addr3 ues in
                    eng3)

The notification mechanism

Often, one just wants to watch an engine, and to perform a special action when it reaches a final state. There is a simple way to configure a callback:

  val when_state : ?is_done:('a -> unit) ->
		   ?is_error:(exn -> unit) ->
		   ?is_aborted:(unit -> unit) ->
		   'a #engine ->
		     unit

For example, to output a message when eng1 is connected:

  when_state ~is_done:(fun _ -> prerr_endline "eng1 connected") eng1

The argument of is_done is the result of the engine (not needed in this example).

The function when_state is implemented with the notification mechanism all engines must support. The method request_notification can be used to request a callback whenever the state of the engine changes:

  method request_notification : (unit -> bool) -> unit

The callback function returns whether it is still interested in being called (true) or not (false). In the latter case, the engine must not call the function again.

For example, the connection message can also be output by:

  eng1 # request_notification 
           (fun () -> 
	      match eng1#state with
	        `Done _ -> prerr_endline "eng1 connected"; false
              | `Error _
              | `Aborted -> false
              | `Working _ -> true
           )

Some more details: The callback function should be even called when only minor state changes occur, e.g. when `Working n changes to `Working (n+1). The engine is free to invoke the callback function even more frequently.

Another detail: It is allowed that more callbacks are requested when a callback function is running.

Asynchronous channels

Editorial note: This section describes a feature that is now seen as outdated, and often not the optimal way of doing async I/O. Asynchronous channels are still available, though. Readers may skip this section.

Because engines are based on Unixqueues, one can imagine that complex operations on file descriptors are executed by engines. Actually, there is a primitive that copies the whole byte stream arriving at one descriptor to another descriptor: The class copier. We do not discuss this class in detail, it is explained in the reference manual. From the outside it works like every engine: One specifies the task, creates the engine, and waits until it is finished. Internally, the class has to watch both file descriptors, check when data can be read and written, and to actually copy chunk by chunk.

Now imagine we do not only want to copy from descriptor to descriptor, but to copy from a descriptor into a data object. Of course, we have the phenomenon that the descriptor sometimes has data to be read and sometimes not, this is well-known and can be effectively handled by Unixqueue means. In addition to this, we assume that there is only limited processing capacity in the data object, so it can sometimes accept data and sometimes not. This sounds the same, but it is not, because there is no descriptor to which this phenomenon is bound. We have to develop our own interface to mimick this behaviour on a higher programming level: The asynchronous output channel.

The term channel is used by the O'Caml runtime system to refer to buffered I/O descriptors. The Ocamlnet library has extended the meaning of the term to objects that handle I/O in a configurable way. As this is what we are going to do, we adopt this meaning.

An asynchronous output channel is a class with the type:

class type async_out_channel = object
  method output : string -> int -> int -> int
  method close_out : unit -> unit
  method pos_out : int
  method flush : unit -> unit
  method can_output : bool
  method request_notification : (unit -> bool) -> unit

The first four methods are borrowed from Ocamlnet's class type raw_out_channel:

  • output s k n prints into the channel n bytes that can be found at position k of string s. The method returns the number of bytes that have been accepted
  • close_out() closes the channel
  • flush() causes that bytes found in internal buffers are immediately processed. Note that it is questionable what this means in an asynchronous programming environment, and because of this, we ignore this method.
  • pos_out returns the number of bytes that have been written into the channel since its creation (as object)
Originally, these methods have been specified for synchronous channels. These are allowed to wait until a needed resource is again available - this is not possible for an asynchronous channel. For example, output ensures to accept at least one byte in the original specification. An implementation is free to wait until this is possible. Here, we should not do so because this would block the whole event system. Instead, there are two additional methods helping to cope with these difficulties:

  • can_output returns true when output accepts at least one byte, and false otherwise
  • request_notification f requests that the function f is called back whenever can_output changes its value
The point is that now the user of an asynchronous channel is able to defer the output operation into the future when it is currently not possible. Of course, it is required that the user knows this - using an asynchronous channel is not as easy as using a synchronous channel.

We show now two examples: The first always accepts output and appends it to a buffer. Of course, the two methods can_output and request_notification are trivial in this case. The second example illustrates these methods: The channel pauses for one second after one kilobyte of data have been accepted. This is of little practical use, but quite simple to implement, and has the right niveau for an example.

Example 1: We just inherit from an Ocamlnet class that implements the buffer:

   class async_buffer b =
   object (self)
     inherit Netchannels.output_buffer b
     method can_output = true
     method request_notification (f : unit->bool) = ()
   end

I insist that this is a good example because it demonstrates why the class type async_out_channel bases on an Ocamlnet class type. (Note that async_buffer defines more methods than necessary. It might be necessary to coerce objects of this class to async_out_channel if required by typing.)

Example 2: Again we use an Ocamlnet class to implement the buffer, but we do not directly inherit from this class. Instead we instantiate it as an instance variable real_buf. The variable barrier_enabled is true as long as no more than 1024 bytes have been written into the buffer, and the sleep second is not yet over. The variable barrier_reached is true if at least 1024 bytes have been written into the buffer.

   class funny_async_buffer b ues =
   object (self)
     val real_buf = new Netchannels.output_buffer b
     val mutable barrier_enabled = true
     val mutable barrier_reached = false
     val mutable notify_list = []
     val mutable notify_list_new = []
 
     method output s k n =
       if barrier_enabled then (
	 let m = 1024 - real_buf#pos_out in
         let r = real_buf # output s k (min n m) in
         if m > 0 && real_buf#pos_out = 1024 then (
           barrier_reached <- true;
           self # configure_sleep_second();
           self # notify()
         );
         r
       )
       else 
         real_buf # output s k n

     method flush() = ()

     method pos_out = real_buf#pos_out

     method close_out() = real_buf#close_out()

     method can_output =
       if barrier_enabled then
         not barrier_reached
       else
         true

     method request_notification f =
       notify_list_new <- f :: notify_list_new

     method private notify() =
       notify_list <- notify_list @ notify_list_new;
       notify_list_new <- [];
       notify_list <- List.filter (fun f -> f()) notify_list

     method private configure_sleep_second() =
       let g = Unixqueue.new_group ues in
       Unixqueue.once ues g 1.0 self#wake_up

     method private wake_up() =
       barrier_enabled <- false;
       self # notify()
   end

Initially, the barrier is enabled, and can_output returns true. The logic in output ensures that no more than 1024 bytes are added to the buffer. When the 1024th byte is printed, the barrier is reached, and the sleep second begins. can_output changes to false, and because of this, we must notify the functions that have requested that. The timer is implemented by a call of Unixqueue.once; this function performs a callback after a period of time has elapsed. Here, wake_up is called back. It disables the barrier, and because can_output is now again true, the notifications have to be done again.

The complete example can be found in the "examples/engines" directory of the equeue distribution.

An implementation of a useful asynchronous channel is output_async_descr that outputs the channel data to a file descriptor. This class is also an engine. See the reference manual for a description.

Receivers

Editorial note: This section describes a feature that is now seen as outdated, and often not the optimal way of doing async I/O. Asynchronous channels are still available, though. Readers may skip this section.

The question is what one can do with asynchronous channels. We have mentioned that these objects were designed with copy tasks in mind that transfer data from file descriptors into data objects. Of course, the asynchronous channels play the role of these data objects. In addition to these, we need an engine that actually performs this kind of data transfer: The receiver engine.

The receiver class has this signature:

   class receiver : src:Unix.file_descr ->
		    dst:#async_out_channel ->
		    ?close_src:bool ->
		    ?close_dst:bool ->
		    Unixqueue.event_system ->
		      [unit] engine

Obviously, src is the descriptor to get the data from, and dst is the asynchronous channel to write the data into. After the receiver has been created, it copies the data stream from src to dst until EOF is found.

The receiver is an engine, and this means that it reports its state to the outer world. When the copy task has been completed, it transitions into the state `Done().

The I/O functions in Uq_io

The functions in Uq_io are patterned after the I/O functions in the standard library, only that they use the engine paradigm. For example, we have in Pervasives

val input : in_channel -> string -> int -> int -> int

for reading data from an in_channel and putting it into the string, and the corresponding function Uq_io.input_e has the signature

val input_e : [< in_device ] -> string_like -> int -> int -> 
                int Uq_engines.engine

Instead from an in_channel it gets data from an in_device. There are several kinds of Uq_io.in_device, especially:

  • `Polldescr(fd_style, fd, esys) is a device reading data from the file descriptor fd via the event queue esys. The fd_style indicates how to read data (whether it is Unix.read, Unix.recv, or another system call).
  • `Buffer_in b is a device reading data from a buffer b, and b is in turn connected to another device serving as data source. Buffers b are created with Uq_io.create_in_buffer.
The type string_like allows the values `String s for a string s, and `Memory m for a bigarray of chars m.

There is, of course, also an Uq_io.out_device for the other data flow direction. I/O functions include:

For example, let's develop a function reading line-by-line from a file descriptor to check whether the special line "pearl" exists:

let find_pearl fd esys =
  let d1 = `Polldescr(Netsys.get_fd_style fd, fd, eys) in
  let d2 = `Buffer_in(Uq_io.create_in_buffer d1) in
  let found = ref false in

  let rec loop () =
    Uq_io.input_line_e d2 ++
      (fun line ->
        if line = "pearl" then found := true;
	loop()
      ) in

  Uq_engines.map_engine
    ~map_done:(fun _ -> `Done !found)
    ~map_error:(fun err -> 
                  if err = End_of_file then `Done !found else `Error err)
    (loop())

The result type of find_pearl is bool engine.

We exploit here that input_line_e raises End_of_file when the end of the input stream is reached. This exception is, of course, not directly raised, but rather the engine state `Error End_of_file is entered. Because of this, there is no test for the end of the recursion in loop. The exception is caught by a map_engine, and mapped to a regular result.

Example: A simple HTTP client

The HTTP protocol is used to get web pages from web servers. Its principle is very simple: A request is sent to the server, and the server replies with the document (well, actually HTTP can be very complicated, but it can also still be used in this simple way). For example, the request could be

  GET / HTTP/1.0
  --empty line--

Note there is a second line which is empty. The server responds with a header, an empty line, and the document. In HTTP/1.0 we can assume that the server sends EOF after the document.

The first part of our client connects to the web server. This is not new:

  let ues = Unixqueue.create_unix_event_system();;
  let c = connector (`Socket(`Sock_inet_byname(Unix.SOCK_STREAM,
					       "www.npc.de", 80),
			     default_connect_options
		    )) ues;;

Furthermore, we need an asynchronous output channel that stores the incoming server reply. This is also a known code snippet:

   class async_buffer b =
   object (self)
     inherit Netchannels.output_buffer b
     method can_output = true
     method request_notification (f : unit->bool) = ()
   end

We also create a buffer:

  let b = Buffer.create 10000;;

Now we are interested in the moment when the connection is established. In this moment, we send the request using Uq_io.output_string_e. Furthermore, we create an async_buffer object that collects the HTTP response, which can arrive at any time from now on.

  let e =
    c ++ 
      (fun connstat ->
	 match connstat with
	  | `Socket(fd, _) ->
	       prerr_endline "CONNECTED";     (* debug output *)
	       let d = `Polldescr(Netsys.get_fd_style fd, fd, ues) in
	       Uq_io.output_string_e d "GET / HTTP/1.0\n\n" ++
		 (fun () ->
		    Uq_io.write_eof_e d ++
                      (fun _ ->
			let buffer = new async_buffer b in
			new receiver ~src:fd ~dst:buffer ues
                      )
		 )
	  | _ -> assert false
      ) in

  when_state
    ~is_done:(fun _ ->
                prerr_endline "HTTP RESPONSE RECEIVED!")
    ~is_error:(fun _ ->
                prerr_endline "ERROR!")
    e

One important line is missing: Up to now we have only set up the client, but it is not yet running. To invoke it we need:

  Unixqueue.run ues;;

This client is not perfect, not only, because it is restricted to the most basic form of the HTTP protocol. The error handling could be better: The descriptor fd is not closed in this case.

Event-driven programming vs. multi-threaded programming

One of the tasks of event-driven programming is to avoid blocking situations, another is to schedule the processor activities. Another approach to achieve these goals is multi-threaded programming.

The fundamental difference between both approaches is that in the case of event-driven programming the application controls itself, while in the case of multi-threaded programming additional features of the operating system are applied. The latter seems to have major advantages, for example blocking is impossible at all (if one thread blocks, the other threads may continue running), and scheduling is one of the native tasks of an operating system.

This is not the whole truth. First of all, multi-threaded programming has the disadvantage that every line of the program must follow certain programming guidelines, especially shared storage must be protected by mutexes such that everything is "reentrant". This is not very simple. On the contrary, event-driven programs can be "plugged together" from a set of basic components, and you do not need to know how the components are programmed.

Scheduling: Multi-threaded programs sometimes lead to situations where there are many runnable threads. Despite the capabilities of the operating system, every modern hardware has the restriction that it performs badly if the code to execute is wide-spread over the whole memory. This is mainly caused by limited cache memory. Many operating systems are not well enough designed to efficiently get around this bottleneck.

Furthermore, I think that scheduling controlled by the application that knows best its own requirements cannot be worse than scheduling controlled by the operating system. (But this may be wrong in special situations.)

Avoid blocking: Of course, an event-driven program blocks if it gets into an endless loop. A multi-threaded application does not block in this case, but it wastes CPU time. It is normally not possible to kill single wild-running threads because most programs are not "cancellation-safe" (a very high requirement). In O'Caml, the latter is only possible for the bytecode thread emulation.

Of course, if you must combine some non-blocking I/O with time-consuming computations, the multi-threaded program will block "less" (it becomes only slower) than the event-driven program, which is unavailable for a period of time.

To come to an end, I think that there are many tasks where event-driven programs perform as well as multi-threaded programs, but where the first style has fewer requirements on the quality of the code.

Combining both styles

Since Equeue 1.2, it is possible to use Equeue in a multi-threaded environment. The fundamental Equeue module is reentrant, and the Unixqueue module even serializes the execution of functions if necessary, such that the same event system may be used from different threads.

One idea is to program a hybrid server in the following way: One thread does all network I/O (using event systems), and the other threads execute the operations the server provides. For example, consider a server doing remote procedures (as most servers do). Such a server receives requests, and every request is responded. When the server starts up, the networking thread begins to wait for requests. When a complete request has been received, a new thread is started performing the requested operation. The network thread continues immediately, normally doing other network I/O. When the operation is over, an artificial event is generated indicating this situation (see below on artificial events). The artificial event carries the result of the operation, and is added to the event system directly from the thread that executed the operation. This thread can now stop working. The network thread receives this artificial event like every other event, and can start sending the result over the network back to the client.

Artificial events are new in Equeue 1.2, too. The idea is to use O'Caml exceptions as dynamically extensible sum type. For example:

exception Result of result_type ;;
...
add_event esys (Extra (Result r))

The Extra event constructor can carry every exception value.

Caveat

The Extra events are not associated to any group. Every event handler will get them.

Pitfalls

There are some situations where the program may still block, if it is not programmed very carefully.

  • Besides the open system call, the connect system call may also block. To avoid blocking, you must first set the socket to non-blocking mode. E.g.
      let s = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
      Unix.set_nonblock s;
      Unix.connect s some_address;
      
  • Other blocking candidates are the name-server functions, in O'Caml Unix.inet_addr_of_string. This is very hard to solve because the underlying C library performs the DNS lookup. The POSIX thread implemention does not help, because special DNS functions needs to be called to avoid blocking (these functions have a reentrant function interface), and the O'Caml Unix module does not use them. A possible solution is to fork a new process, and let the new process perform the DNS lookup.

Using Unixqueue together with Tcl (labltk) and Glib (lablgtk)

The Tcl programming language has already an event queue implementation, and the Tk toolkit applies it to realize event queues for graphical user interfaces (GUIs). In the O'Caml world, Tcl/Tk is available through the packages camltk and labltk.

The same holds for the Glib library which is used by the gtk GUI toolkit to implement event queues. In the O'Caml world, gtk bindings are provided by lablgtk (and lablgtk2).

While the GUI queues mainly process GUI events (e.g. mouse and keyboard events), they can also watch files in the same way as Unixqueue does it. It is, however, not possible to run both types of queues in parallel, because there is the problem that when one type of queue blocks, the other is implicitly also blocked, even when there would be events to process. The solution is to integrate both queues, and because the GUI queues can subsume the functionality of Unixqueue, the GUI queues are the more fundamental ones, and Unixqueue must integrate its event processing into the GUI queues.

This type of integration into the GUI queues is implemented by defining the alternate classes Uq_tcl.tcl_event_system and Uq_gtk.gtk_event_system. These classes can be used in the same way as Unixqueue.unix_event_system, but automatically arrange the event queue integration.

For example, a labltk program uses

let ues = new Uq_tcl.tcl_event_system()
to create the event system object, which can be used in the same way as event systems created with create_unix_event_system or new unix_event_system. There is one important difference, however. One must no longer call Unixqueue.run to start the processing. The reason is that the TCL queue is already started, and remains active during the runtime of the program. Remember that when the GUI function
Tk.mainLoop()
is entered, the TCL queue becomes active, and all subsequent execution of O'Caml code is triggered by callback functions. The integrated queue now behaves as follows: When handlers, resources, or events are added to ues, they are automatically considered for processing when the current callback function returns. For example, this might look as follows:
let b1 = Button.create 
           ~text:"Start function" 
           ~command:(fun () ->
                      Unixqueue.add_handler ues ...; ...) widget in
let b2 = Button.create 
           ~text:"Stop function" 
           ~command:(fun () ->
                      Unixqueue.remove_handler ues ...; ...) widget in
...
When the button is pressed, the function is triggered, and the callback function passed as command starts executing. This adds handlers, resources, and what ever is needed to start the activated function. The callback function returns immediately, and the processing of the event queue is performed by the regular GUI event system. Of course, it is still possible to press other buttons etc., because GUI and Unixqueue events are processed in an interweaved way. So the user is able to press the "Stop" button to stop the further execution of the activated function.

API change

In Equeue-2.1, the interface for the Tcl queue integration was changed. It works now as described above; the function Unixqueue.attach_to_tcl_queue no longer exists. The new scheme has the advantage that the Glib-type queues (and probably any other event queue implementation) can be also easily supported.

Sample code

The example discussed before, copying files in an event-driven way, has been extended to show how Unixqueue and Tcl can cooperate. While the file is being copied, a window informs about the progress and offers a "Stop" button which immediately aborts the copy procedure. See the directory "filecopy_labltk" in the distributed tarball. There is also a variant that works with lablgtk or lablgtk2, see the directory "filecopy_lablgtk".

Pitfalls

If you call Unixqueue functions from Unixqueue event handlers, the functions behave exactly as described in the previous chapters. However, it is also possible to call Unixqueue functions from TCL/Glib event handlers. In this case, not all change requests will be immediately honoured. Especially, add_event does not immediately invoke the appropriate event handler; the event is just recorded, and the handler will be called when the next system event happens (either a GUI event, a file descriptor event, or a timeout event). You can force to respect the new event as soon as possible by adding an empty handler using Unixqueue.once with a timeout of 0 seconds. - The other Unixqueue functions should not behave differently (although the actually performed operations are very different). Especially you can call add_resource and remove_resource and the change will be respected immediately.
ocamlnet-4.1.2/doc/html-main/Uq_engines.map_engine-c.html0000644000175000017500000005002212731530353021704 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.map_engine

Class Uq_engines.map_engine

class [['a, 'b]] map_engine : map_done:('a -> 'b engine_state) -> ?map_error:exn -> 'b engine_state -> ?map_aborted:unit -> 'b engine_state -> ?propagate_working:bool -> 'a #engine -> ['b] engine
The map_engine observes the argument engine, and when the state changes to `Done, `Error, or `Aborted, the corresponding mapping function is called, and the resulting state becomes the state of the mapped engine. If the engine is already in one of the mentioned states, the map functions are also called (unlike when_state).

After the state change to `Done, `Error, or `Aborted has been observed, the map engine detaches from the argument engine, and no further state changes are recognized.

The state `Working cannot be mapped to another state. It is an error to map final states to `Working. The result type of the map_* functions is engine_state and not final_state because of historic reasons.

If the mapped engine is aborted, this request will be forwarded to the argument engine.

If one of the mapping functions raises an exception, this causes a transiton to `Error.


map_done : Maps the `Done state of the argument engine to another state. The argument of map_done is the argument of the `Done state. Note that map_done is non-optional only because of typing. If it were optional, the type checker would infer 'a = 'b.
map_error : Maps the `Error state of the argument engine to another state. The argument of map_error is the argument of the `Error state.
map_aborted : Maps the `Aborted state of the argument engine to another state.
propagate_working : Specifies whether changes of the `Working state in the argument engine are propagated. Defaults to true. If set to false, the mapped engine remains in `Working 0 until it transitions to a final state.

ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.min_config.html0000644000175000017500000004160712731530353023465 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.min_config object
  method config_error_response :
    Nethttpd_types.error_response_params -> string
  method config_log_error : Nethttpd_types.request_info -> string -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_workload.dynamic_workload_config.html0000644000175000017500000004205712731530353026533 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_workload.dynamic_workload_config object
  method greedy_accepts : bool
  method inactivity_timeout : int
  method max_free_job_capacity : int
  method max_jobs_per_thread : int
  method max_threads : int
  method min_free_job_capacity : int
  method recommended_jobs_per_thread : int
end
ocamlnet-4.1.2/doc/html-main/Netencoding.Url.html0000644000175000017500000004770112731530353020276 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Url

Module Netencoding.Url

module Url: sig .. end


Encoding/Decoding within URLs:

The following two functions perform the '%'-substitution for characters that may otherwise be interpreted as metacharacters.

According to: RFC 1738, RFC 1630

Option plus: This option has been added because there are some implementations that do not map ' ' to '+', for example Javascript's escape function. The default is true because this is the RFC- compliant definition.

Encoding/Decoding within URLs:

The following two functions perform the '%'-substitution for characters that may otherwise be interpreted as metacharacters.

According to: RFC 1738, RFC 1630

Option plus: This option has been added because there are some implementations that do not map ' ' to '+', for example Javascript's escape function. The default is true because this is the RFC- compliant definition.

There are no tstring and polymorphic versions of the encode and decode functions, as URLs are comparatively short, and it is considered as acceptable for the user to convert types as needed, even if strings need to be copied for that.

val decode : ?plus:bool -> ?pos:int -> ?len:int -> string -> string
Option plus: Whether '+' is converted to space. The default is true. If false, '+' is returned as it is.

The optional arguments pos and len may restrict the string to process to this substring.

val encode : ?plus:bool -> string -> string
Option plus: Whether spaces are converted to '+'. The default is true. If false, spaces are converted to "%20", and only %xx sequences are produced.

URL-encoded parameters:

The following two functions create and analyze URL-encoded parameters. Format: name1=val1&name2=val2&...

val mk_url_encoded_parameters : (string * string) list -> string
The argument is a list of (name,value) pairs. The result is the single URL-encoded parameter string.
val dest_url_encoded_parameters : string -> (string * string) list
The argument is the URL-encoded parameter string. The result is the corresponding list of (name,value) pairs. Note: Whitespace within the parameter string is ignored. If there is a format error, the function fails.
ocamlnet-4.1.2/doc/html-main/Uq_resolver.html0000644000175000017500000005755512731530353017616 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_resolver

Module Uq_resolver

module Uq_resolver: sig .. end
Support for pluggable resolvers


A resolver maps several kinds of names to addresses, or vice versa. Currently, only DNS host lookups are supported (but this can be extended if needed).

The plugin mechanism allows one to change the name resovler Ocamlnet uses. Resolvers can be both synchronous or asynchronous. Note however, that the default resolver is synchronous and simply bases on Unix.gethostbyname.

Requirements of the resolver:

  • IP addresses may be enclosed in square brackets, but also given without such brackets. If such an IP address is passed to the resolver, the string address is just converted to a Unix.inet_addr.


A resolver maps several kinds of names to addresses, or vice versa. Currently, only DNS host lookups are supported (but this can be extended if needed).

The plugin mechanism allows one to change the name resovler Ocamlnet uses. Resolvers can be both synchronous or asynchronous. Note however, that the default resolver is synchronous and simply bases on Unix.gethostbyname.

Requirements of the resolver:

  • IP addresses may be enclosed in square brackets, but also given without such brackets. If such an IP address is passed to the resolver, the string address is just converted to a Unix.inet_addr.


Asynchronous Interface



A resolver maps several kinds of names to addresses, or vice versa. Currently, only DNS host lookups are supported (but this can be extended if needed).

The plugin mechanism allows one to change the name resovler Ocamlnet uses. Resolvers can be both synchronous or asynchronous. Note however, that the default resolver is synchronous and simply bases on Unix.gethostbyname.

Requirements of the resolver:

  • IP addresses may be enclosed in square brackets, but also given without such brackets. If such an IP address is passed to the resolver, the string address is just converted to a Unix.inet_addr.


Asynchronous Interface



The following types are the same as in Uq_engines, here only redefined for systematic reasons
type 't engine_state = [ `Aborted | `Done of 't | `Error of exn | `Working of int ] 
class type ['t] engine = object .. end

Exceptions
exception Host_not_found of string
This host cannot be resolved

The type of resolvers:
class type resolver = object .. end

Synchronous Interface


val get_host_by_name : ?resolver:resolver -> string -> Unix.host_entry
Look up the host, and return the host entry or raise the exception Host_not_found.

If a resolver is passed, this resolver is used, otherwise the pluggable resolver is used.

val sockaddr_of_socksymbol : ?resolver:resolver -> Netsockaddr.socksymbol -> Unix.sockaddr
Use the resolver to look up names in Netsockaddr.socksymbol, and convert the symbol to a Unix.sockaddr only containing IP addresses.

If a resolver is passed, this resolver is used, otherwise the pluggable resolver is used.


Resolvers


val default_resolver : unit -> resolver
The default resolver uses Unix.gethostbyname to look up names. Note that this means that no IPv6 addresses are returned.
val gai_resolver : ?ipv4:bool -> ?ipv6:bool -> unit -> resolver
This resolver uses Unix.getaddrinfo. One can set whether IPv4 or IPv6 addresses may be returned (only one type is returned). The order of addresses cannot be set, but there is a global config file /etc/gai.info.

The h_aliases field of the result is not set.

By default, both ipv4 and ipv6 are enabled.


Plugins


val current_resolver : unit -> resolver
Returns the pluggable resolver. Unless overridden by set_current_resolver, the returned resolver depends on the result of Netsys.is_ipv6_system.
val set_current_resolver : resolver -> unit
Set the pluggable resolver
ocamlnet-4.1.2/doc/html-main/Netftp_data_endpoint.ftp_data_sender-c.html0000644000175000017500000004470312731530353024771 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.ftp_data_sender

Class Netftp_data_endpoint.ftp_data_sender

class ftp_data_sender : ?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option * string option -> ?protector:ftp_protector -> esys:Unixqueue.event_system -> mode:transmission_mode -> local_sender:local_sender -> descr:Unix.file_descr -> timeout:float -> timeout_exn:exn -> unit -> object .. end
This engine sends data over a FTP data connection coming from a local sender. The socket must already be open.

It is ensured that local_sender is always closed after operation (whether successful or not). The socket descr remains open.

tls: may be set to (config, peer_name, resume_data)

Inherits
method local_sender : local_sender
The local sender. It is closed after usage.
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.Debug.html0000644000175000017500000004100712731530353022343 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netxdr.html0000644000175000017500000014205212731530353017600 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netxdr sig
  type xdr_value =
      XV_int of Netnumber.int4
    | XV_uint of Netnumber.uint4
    | XV_hyper of Netnumber.int8
    | XV_uhyper of Netnumber.uint8
    | XV_enum of string
    | XV_float of Netnumber.fp4
    | XV_double of Netnumber.fp8
    | XV_opaque of string
    | XV_string of string
    | XV_array of Netxdr.xdr_value array
    | XV_struct of (string * Netxdr.xdr_value) list
    | XV_union_over_int of (Netnumber.int4 * Netxdr.xdr_value)
    | XV_union_over_uint of (Netnumber.uint4 * Netxdr.xdr_value)
    | XV_union_over_enum of (string * Netxdr.xdr_value)
    | XV_void
    | XV_enum_fast of int
    | XV_struct_fast of Netxdr.xdr_value array
    | XV_union_over_enum_fast of (int * Netxdr.xdr_value)
    | XV_array_of_string_fast of string array
    | XV_mstring of Netxdr_mstring.mstring
    | XV_direct of exn * int * (exn -> Netxdr.xdr_value)
  val xv_true : Netxdr.xdr_value
  val xv_false : Netxdr.xdr_value
  val xv_none : Netxdr.xdr_value
  val xv_some : Netxdr.xdr_value -> Netxdr.xdr_value
  type xdr_type_term =
      X_int
    | X_uint
    | X_hyper
    | X_uhyper
    | X_enum of (string * Netnumber.int4) list
    | X_float
    | X_double
    | X_opaque_fixed of Netnumber.uint4
    | X_opaque of Netnumber.uint4
    | X_string of Netnumber.uint4
    | X_mstring of string * Netnumber.uint4
    | X_array_fixed of Netxdr.xdr_type_term * Netnumber.uint4
    | X_array of Netxdr.xdr_type_term * Netnumber.uint4
    | X_struct of (string * Netxdr.xdr_type_term) list
    | X_union_over_int of (Netnumber.int4 * Netxdr.xdr_type_term) list *
        Netxdr.xdr_type_term option
    | X_union_over_uint of (Netnumber.uint4 * Netxdr.xdr_type_term) list *
        Netxdr.xdr_type_term option
    | X_union_over_enum of Netxdr.xdr_type_term *
        (string * Netxdr.xdr_type_term) list * Netxdr.xdr_type_term option
    | X_void
    | X_type of string
    | X_param of string
    | X_rec of (string * Netxdr.xdr_type_term)
    | X_refer of string
    | X_direct of Netxdr.xdr_type_term *
        (Bytes.t -> int Pervasives.ref -> int -> exn) *
        (exn -> Bytes.t -> int Pervasives.ref -> unit) * (exn -> int) *
        (exn -> Netxdr.xdr_value)
  type xdr_type
  type xdr_type_term_system = (string * Netxdr.xdr_type_term) list
  type xdr_type_system
  val x_bool : Netxdr.xdr_type_term
  val x_optional : Netxdr.xdr_type_term -> Netxdr.xdr_type_term
  val x_opaque_max : Netxdr.xdr_type_term
  val x_string_max : Netxdr.xdr_type_term
  val x_mstring_max : string -> Netxdr.xdr_type_term
  val x_array_max : Netxdr.xdr_type_term -> Netxdr.xdr_type_term
  exception Dest_failure
  val dest_xv_int : Netxdr.xdr_value -> Netnumber.int4
  val dest_xv_uint : Netxdr.xdr_value -> Netnumber.uint4
  val dest_xv_hyper : Netxdr.xdr_value -> Netnumber.int8
  val dest_xv_uhyper : Netxdr.xdr_value -> Netnumber.uint8
  val dest_xv_enum : Netxdr.xdr_value -> string
  val dest_xv_enum_fast : Netxdr.xdr_value -> int
  val dest_xv_float : Netxdr.xdr_value -> Netnumber.fp4
  val dest_xv_double : Netxdr.xdr_value -> Netnumber.fp8
  val dest_xv_opaque : Netxdr.xdr_value -> string
  val dest_xv_string : Netxdr.xdr_value -> string
  val dest_xv_mstring : Netxdr.xdr_value -> Netxdr_mstring.mstring
  val dest_xv_array : Netxdr.xdr_value -> Netxdr.xdr_value array
  val dest_xv_array_of_string_fast : Netxdr.xdr_value -> string array
  val dest_xv_struct : Netxdr.xdr_value -> (string * Netxdr.xdr_value) list
  val dest_xv_struct_fast : Netxdr.xdr_value -> Netxdr.xdr_value array
  val dest_xv_union_over_int :
    Netxdr.xdr_value -> Netnumber.int4 * Netxdr.xdr_value
  val dest_xv_union_over_uint :
    Netxdr.xdr_value -> Netnumber.uint4 * Netxdr.xdr_value
  val dest_xv_union_over_enum : Netxdr.xdr_value -> string * Netxdr.xdr_value
  val dest_xv_union_over_enum_fast :
    Netxdr.xdr_value -> int * Netxdr.xdr_value
  val dest_xv_void : Netxdr.xdr_value -> unit
  val map_xv_enum_fast : Netxdr.xdr_type -> Netxdr.xdr_value -> int32
  val map_xv_struct_fast :
    Netxdr.xdr_type -> Netxdr.xdr_value -> Netxdr.xdr_value array
  val map_xv_union_over_enum_fast :
    Netxdr.xdr_type -> Netxdr.xdr_value -> int * int32 * Netxdr.xdr_value
  exception Xdr_format of string
  exception Xdr_format_message_too_long of Netxdr.xdr_value
  exception Xdr_failure of string
  val validate_xdr_type : Netxdr.xdr_type_term -> Netxdr.xdr_type
  val validate_xdr_type_system :
    Netxdr.xdr_type_term_system -> Netxdr.xdr_type_system
  val params : Netxdr.xdr_type -> string list
  val xdr_type_term : Netxdr.xdr_type -> Netxdr.xdr_type_term
  val xdr_type_term_system :
    Netxdr.xdr_type_system -> Netxdr.xdr_type_term_system
  val expanded_xdr_type :
    Netxdr.xdr_type_system -> Netxdr.xdr_type_term -> Netxdr.xdr_type
  val expanded_xdr_type_term :
    Netxdr.xdr_type_term_system ->
    Netxdr.xdr_type_term -> Netxdr.xdr_type_term
  val are_compatible : Netxdr.xdr_type -> Netxdr.xdr_type -> bool
  val value_matches_type :
    Netxdr.xdr_value ->
    Netxdr.xdr_type -> (string * Netxdr.xdr_type) list -> bool
  type encoder = Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
  type decoder = Bytes.t -> int -> int -> Bytes.t * int
  val pack_xdr_value :
    ?encode:(string * Netxdr.encoder) list ->
    Netxdr.xdr_value ->
    Netxdr.xdr_type ->
    (string * Netxdr.xdr_type) list -> (Bytes.t -> unit) -> unit
  val pack_xdr_value_as_bytes :
    ?rm:bool ->
    ?encode:(string * Netxdr.encoder) list ->
    Netxdr.xdr_value ->
    Netxdr.xdr_type -> (string * Netxdr.xdr_type) list -> Bytes.t
  val pack_xdr_value_as_string :
    ?rm:bool ->
    ?encode:(string * Netxdr.encoder) list ->
    Netxdr.xdr_value ->
    Netxdr.xdr_type -> (string * Netxdr.xdr_type) list -> string
  val pack_xdr_value_as_mstrings :
    ?rm:bool ->
    ?encode:(string * Netxdr.encoder) list ->
    Netxdr.xdr_value ->
    Netxdr.xdr_type ->
    (string * Netxdr.xdr_type) list -> Netxdr_mstring.mstring list
  type xdr_value_version = [ `Ocamlrpcgen | `V1 | `V2 | `V3 | `V4 ]
  val unpack_xdr_value :
    ?pos:int ->
    ?len:int ->
    ?fast:bool ->
    ?prefix:bool ->
    ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
    ?xv_version:Netxdr.xdr_value_version ->
    ?decode:(string * Netxdr.decoder) list ->
    Bytes.t ->
    Netxdr.xdr_type -> (string * Netxdr.xdr_type) list -> Netxdr.xdr_value
  val unpack_xdr_value_l :
    ?pos:int ->
    ?len:int ->
    ?fast:bool ->
    ?prefix:bool ->
    ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
    ?xv_version:Netxdr.xdr_value_version ->
    ?decode:(string * Netxdr.decoder) list ->
    Bytes.t ->
    Netxdr.xdr_type ->
    (string * Netxdr.xdr_type) list -> Netxdr.xdr_value * int
  val unpack_xdr_value_str :
    ?pos:int ->
    ?len:int ->
    ?fast:bool ->
    ?prefix:bool ->
    ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
    ?xv_version:Netxdr.xdr_value_version ->
    ?decode:(string * Netxdr.decoder) list ->
    string ->
    Netxdr.xdr_type ->
    (string * Netxdr.xdr_type) list -> Netxdr.xdr_value * int
  val get_string_decoration_size : int -> Netnumber.uint4 -> int
  val sizefn_string : Netnumber.uint4 -> string -> int
  val sizefn_mstring : Netnumber.uint4 -> Netxdr_mstring.mstring -> int
  val write_string_fixed :
    int -> string -> Bytes.t -> int Pervasives.ref -> unit
  val write_string : string -> Bytes.t -> int Pervasives.ref -> unit
  val read_string_fixed :
    int -> Bytes.t -> int Pervasives.ref -> int -> string
  val read_string :
    Netnumber.uint4 -> Bytes.t -> int Pervasives.ref -> int -> string
  val raise_xdr_format_too_short : unit -> 'a
  val raise_xdr_format_value_not_included : unit -> 'a
  val raise_xdr_format_maximum_length : unit -> 'a
  val raise_xdr_format_undefined_descriminator : unit -> 'a
  val safe_add : int -> int -> int
  val safe_mul : int -> int -> int
  type ctx = {
    ctx_direct : bool;
    ctx_direct_sub : bool;
    ctx_copy_string : string -> string;
  }
  val default_ctx : Netxdr.ctx
  val expand_ctx : Netxdr.ctx
  val direct_ctx : Netxdr.ctx
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.http_call-c.html0000644000175000017500000011537112731530353022454 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.http_call

Class type Nethttp_client.http_call

class type http_call = object .. end
The container for HTTP calls

http_call is the runtime container for HTTP method calls. It contains the request message, the response message, and the current transmission status.

In previous versions of netclient, this class type was called message. This was quite inexact because this class embraces both messages that are part of a call.

Incompatible changes:

  • using_proxy has been removed. This simply isn't a property of an individual call.
  • get_req_uri has been removed from the public interface for similar reasons.
  • The request and response messages are now primarily stored as Netmime.mime_header and Netmime.mime_body objects. The old style access methods remain in the API for now. The advantage is that it is possible to use external files as body containers.
  • There are two request headers, `Base and `Effective.
method is_served : bool
true if request/response cycle(s) have been finished, i.e. the call was successful, or a final error state has been reached.
method status : status
The condensed status
method auth_status : unit auth_status
Authenticaton status. This status code is important for mutual authentication (i.e. when the client also authenticates the server), which can be enabled for some generic authentication handlers. In this case status and all the other methods just report about the last message from the server. They will not indicate whether the authentication failed on the side of the client (in particular, no exception is thrown). It is required to check that auth_status=`OK.

An example of a mechanism with mutual authentication is Netmech_digest_http.Digest_mutual.

method tls_session_props : Nettls_support.tls_session_props option
If TLS is enabled, this returns the session properties
method gssapi_props : Netsys_gssapi.client_props option
If GSSAPI is active, return the properties
method request_method : string
The HTTP method as string
method request_uri : string
The request URI as string. This is always an absolute URI in the form "http://server/path" or "https://server/path".
method set_request_uri : string -> unit
Sets the request URI. This implicitly also sets the transport layer ID (see below).

Changed in Ocamlnet-3.3: The URI is no longer immediately parsed, but first when the call is submitted to a pipeline. This means that parsing errors will first be reported by the add method. The background is that parsing now depends on pipeline options.

method request_header : header_kind -> Netmime.mime_header
The whole header of the request. Users of this class should only modify the `Base header. After the call has been processed, the `Effective header contains the version of the header that has actually been transmitted.

The user should set the following headers:

  • Content-length: Set this to the length of the request body if known. (The client falls back to HTTP 1.0 if not set!)
  • Content-type: Set this to the media type of the request body
  • Expect: Set this to "100-continue" to enable a handshake before the body is sent. Recommended for large bodies. (See also set_expect_handshake below.)
The following headers may be set, but there are reasonable defaults:
  • Date
  • User-agent
The following headers must not be set:
  • Connection

method set_request_header : Netmime.mime_header -> unit
Replaces the whole `Base header object
method set_expect_handshake : unit -> unit
Configures that a handshake is done before sending the request body. This is useful when the request body can be large, and authentication or response indirections are possible. New since Ocamlnet-3.3.
method set_chunked_request : unit -> unit
Configures that the request is transmitted using chunked encoding. This has advantages when the size of the request is not known in advance. However, this works only for true HTTP/1.1 servers. New since Ocamlnet-3.3.
method effective_request_uri : string
The URI actually sent to the server in the request line of the protocol.
method request_body : Netmime.mime_body
The whole body of the request. This method fails after set_request_device has been called (no body then).
method set_request_body : Netmime.mime_body -> unit
Replaces the whole body object
method set_request_device : (unit -> Uq_io.in_device) -> unit
Sets that the request data is read from the passed device instead of taking it from a body object. The device must be connected with the same event loop as the HTTP client.
method set_accept_encoding : unit -> unit
Sets the Accept-Encoding field in the request header, and includes all decompression algorithms registered in Netcompression. Additionally, the automatic decompression of the response body is enabled.

Note that you need to ensure that the algorithms are really registered at Netcompression. For example, to get gzip support, run

 Netgzip.init() 
, and include netzip as library.
method response_status_code : int
The three-digit status code
method response_status_text : string
The text transmitted along with the code
method response_status : Nethttp.http_status
The decoded code. Unknown codes are mapped to the generic status values `Ok, `Multiple_choices, `Bad_request, and `Internal_server_error.
method response_protocol : string
The HTTP version indicated in the response
method response_header : Netmime.mime_header
The whole header of the response. If the call has not succeeded, Http_protocol will be raised.
method response_body : Netmime.mime_body
The whole body of the response. If the call has not succeeded, Http_protocol will be raised. If the call has succeeded, but no body has been transmitted, the empty body is substituted.

If the response is directly forwarded to a device (after calling set_response_body_storage (`Device d)), there is no accessible response body, and this method will fail.

method response_body_storage : response_body_storage
How to create the response body. Defaults to `Memory.
method set_response_body_storage : response_body_storage -> unit
Sets how to create the response body
method max_response_body_length : int64
Returns the current maximum length (initially Int64.max_int)
method set_max_response_body_length : int64 -> unit
Sets a new maximum length. When the body exceeds this maximum by more than the size of the internal buffer, the reception of the response is interrupted, and the error is set to Response_too_large.
method get_reconnect_mode : http_call how_to_reconnect
Get what to do if the server needs to be reconnected, i.e. if the request must be sent repeatedly. By default, this is Send_again_if_idem.
method set_reconnect_mode : http_call how_to_reconnect -> unit
Sets the reconnect mode
method get_redirect_mode : http_call how_to_redirect
By default, the redirect mode is Redirect_if_idem.
method set_redirect_mode : http_call how_to_redirect -> unit
Sets the redirect mode
method proxy_enabled : bool
Returns the proxy mode
method set_proxy_enabled : bool -> unit
Sets the proxy mode
method no_proxy : unit -> unit
Same as set_proxy_enabled false
method is_proxy_allowed : unit -> bool
Deprecated. Same as proxy_enabled
method proxy_use_connect : bool
Whether to use the CONNECT method if the connection is made via a web proxy. This is normally true if the transport layer is Nethttp_client.https_trans_id
method empty_path_replacement : string
The string to substitute in the request line for the empty path. This is usually "/", and for OPTIONS it is "*".
method is_idempotent : bool
Whether the method is to be considered as idempotent ( = repeated invocations have the same result and no side effect). This is true for GET and HEAD.
method has_req_body : bool
Whether the method allows to send a request body
method has_resp_body : bool
Whether the method allows to reply with a body. This is true except for HEAD.
method set_transport_layer : transport_layer_id -> unit
Sets the transport layer. Note that set_request_uri also sets this ID, but always to the default for the type of URL.
method same_call : unit -> http_call
This method returns a new object that will perform the same call as this object (this function is called "reload" in browsers). The new object is initialized as follows:
  • The state is set to `Unserved
  • The request method remains the same (the class of the returned object remains the same)
  • The request URI is the same string as the original URI
  • The transport layer ID is the same
  • The base request header is the same object
  • The request body is the same object
  • Options like reconnect, redirect mode, and proxy mode are copied.

method get_req_method : unit -> string
Get the name of the request method. Same as request_method.
method get_host : unit -> string
The host name of the content server, extracted from the URI.

Changed in Ocamlnet-3.3: The host can first be extracted after the call is submitted to a pipeline.

method get_port : unit -> int
The port number of the content server, extracted from the URI.

Changed in Ocamlnet-3.3: The port can first be extracted after the call is submitted to a pipeline.

method get_path : unit -> string
The path (incl. query, if any) extracted from the URI.

Changed in Ocamlnet-3.3: The path can first be extracted after the call is submitted to a pipeline.

method get_uri : unit -> string
the full URI of this message: http://server:port/path. If the path is empty, it is omitted. - Same as request_uri.
method get_req_body : unit -> string
What has been sent as body in the (last) request. Same as request_body # value.
method get_req_header : unit -> (string * string) list
Deprecated. What has been sent as header in the (last) request. Returns (key, value) pairs, where the keys are all in lowercase.

In new code, the request_header object should be accessed instead.

method assoc_req_header : string -> string
Query a specific header entry, or raise Not_found
method assoc_multi_req_header : string -> string list
Return all header values for a given field name (header entries which allow several values separated by commas can also be transmitted by several header lines with the same name).
method set_req_header : string -> string -> unit
method get_resp_header : unit -> (string * string) list
Deprecated. Get the header of the last response. The keys are in lowercase characters again.
method assoc_resp_header : string -> string
Query a specific header entry of the response.
method assoc_multi_resp_header : string -> string list
Return all response header values for a given field name (header entries which allow several values separated by commas can also be transmitted by several header lines with the same name).
method get_resp_body : unit -> string
Deprecated. Returns the body of the last response if the response status is OK (i.e. the code is in the range 200 to 299).

Otherwise, Http_error (code, body) is raised where 'code' is the response code and 'body' is the body of the (errorneous) response.

method dest_status : unit -> string * int * string
Returns the status line of the last response (but status lines with code 100 are ignored). The returned triple is (http_string, code, text)
method private_api : private_api
ocamlnet-4.1.2/doc/html-main/Netcgi_apache.cgi-c.html0000644000175000017500000004244312731530353020771 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.cgi

Class type Netcgi_apache.cgi

class type cgi = object .. end
The usual cgi class with an additional method to access Apache specificities.
Inherits
method request : Apache.Request.t
The underlying apache request structure.
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.html0000644000175000017500000011232012731530353021446 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine sig
  type engine_req_state =
      [ `Finishing | `Received_header | `Received_request | `Receiving_body ]
  class type http_engine_config =
    object
      method config_announce_server : Nethttpd_kernel.announcement
      method config_cgi : Netcgi.config
      method config_error_response :
        Nethttpd_types.error_response_params -> string
      method config_input_flow_control : bool
      method config_limit_pipeline_length : int
      method config_limit_pipeline_size : int
      method config_log_access : Nethttpd_types.full_info -> unit
      method config_log_error : Nethttpd_types.request_info -> string -> unit
      method config_max_header_length : int
      method config_max_reqline_length : int
      method config_max_trailer_length : int
      method config_output_flow_control : bool
      method config_suppress_broken_pipe : bool
      method config_timeout : float
      method config_timeout_next_request : float
      method config_tls : Netsys_crypto_types.tls_config option
      method config_tls_cert_props : bool
      method config_tls_remote_user : bool
    end
  val default_http_engine_config : Nethttpd_engine.http_engine_config
  class modify_http_engine_config :
    ?modify_http_protocol_config:(Nethttpd_kernel.http_protocol_config ->
                                  Nethttpd_kernel.http_protocol_config) ->
    ?modify_http_processor_config:(Nethttpd_reactor.http_processor_config ->
                                   Nethttpd_reactor.http_processor_config) ->
    ?config_input_flow_control:bool ->
    ?config_output_flow_control:bool ->
    Nethttpd_engine.http_engine_config -> http_engine_config
  class type extended_async_environment =
    object
      method cgi_auth_type : string
      method cgi_gateway_interface : string
      method cgi_https : bool
      method cgi_path_info : string
      method cgi_path_translated : string
      method cgi_properties : (string * string) list
      method cgi_property : ?default:string -> string -> string
      method cgi_query_string : string
      method cgi_remote_addr : string
      method cgi_remote_host : string
      method cgi_remote_ident : string
      method cgi_remote_user : string
      method cgi_request_method : string
      method cgi_request_uri : string
      method cgi_script_name : string
      method cgi_server_name : string
      method cgi_server_port : int option
      method cgi_server_protocol : string
      method cgi_server_software : string
      method config : Netcgi.config
      method cookie : string -> Netcgi.Cookie.t
      method cookies : Netcgi.Cookie.t list
      method input_body_size : int64
      method input_ch_async : Uq_engines.async_in_channel
      method input_channel : Netchannels.in_obj_channel
      method input_content_length : int
      method input_content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method input_content_type_string : string
      method input_header : Netmime.mime_header
      method input_header_field : ?default:string -> string -> string
      method input_header_fields : (string * string) list
      method log_error : string -> unit
      method log_props : (string * string) list -> unit
      method multiple_input_header_field : string -> string list
      method multiple_output_header_field : string -> string list
      method out_channel : Netchannels.out_obj_channel
      method output_ch : Netchannels.out_obj_channel
      method output_ch_async : Uq_engines.async_out_channel
      method output_header : Netmime.mime_header
      method output_header_field : ?default:string -> string -> string
      method output_header_fields : (string * string) list
      method output_state : Nethttpd_types.output_state ref
      method protocol : Nethttp.protocol
      method remote_socket_addr : Unix.sockaddr
      method request_body_rejected : bool
      method send_file : Unix.file_descr -> int64 -> unit
      method send_output_header : unit -> unit
      method server_socket_addr : Unix.sockaddr
      method set_multiple_output_header_field : string -> string list -> unit
      method set_output_header_field : string -> string -> unit
      method set_output_header_fields : (string * string) list -> unit
      method set_status : Nethttp.http_status -> unit
      method tls_session_props : Nettls_support.tls_session_props option
      method user_agent : string
    end
  class type http_request_header_notification =
    object
      method environment : Nethttpd_engine.extended_async_environment
      method req_state : Nethttpd_engine.engine_req_state
      method schedule_accept_body :
        on_request:(Nethttpd_engine.http_request_notification -> unit) ->
        ?on_error:(unit -> unit) -> unit -> unit
      method schedule_finish : unit -> unit
      method schedule_reject_body :
        on_request:(Nethttpd_engine.http_request_notification -> unit) ->
        ?on_error:(unit -> unit) -> unit -> unit
    end
  and http_request_notification =
    object
      method environment : Nethttpd_engine.extended_async_environment
      method req_state : Nethttpd_engine.engine_req_state
      method schedule_finish : unit -> unit
    end
  class http_engine :
    ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) ->
    on_request_header:(Nethttpd_engine.http_request_header_notification ->
                       unit) ->
    unit ->
    #Nethttpd_engine.http_engine_config ->
    Unix.file_descr ->
    Unixqueue.unix_event_system -> [unit] Uq_engines.engine
  class type http_engine_processing_config =
    object
      method config_synch_input :
        (Netchannels.in_obj_channel -> unit) ->
        Uq_engines.async_in_channel -> unit
      method config_synch_output :
        (Netchannels.out_obj_channel -> unit) ->
        Uq_engines.async_out_channel -> unit
    end
  class buffering_engine_processing_config : http_engine_processing_config
  class type http_engine_processing_context =
    object method engine : unit Uq_engines.engine end
  val process_connection :
    ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) ->
    #Nethttpd_reactor.http_processor_config ->
    #Nethttpd_engine.http_engine_processing_config ->
    Unix.file_descr ->
    Unixqueue.unix_event_system ->
    'Nethttpd_types.http_service ->
    Nethttpd_engine.http_engine_processing_context
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Netmcore_array.html0000644000175000017500000006267112731530353020255 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_array

Module Netmcore_array

module Netmcore_array: sig .. end
Shared arrays


This type of array is to some degree comparable with Array, but there are a few extensions:
  • There is a so-called header. The header can have any type, and is typically used for managing concurrent access (e.g. mutexes). The header also lives in shared memory.
  • The arrays can be grown in size

type ('e, 'h) sarray 
Arrays where the elements have type 'e and the header has type 'h
type ('e, 'h) sarray_descr 
The marshallable descriptor of a shared array
val create : Netmcore.res_id -> 'e array -> 'h -> ('e, 'h) sarray
create pool_id a h: Creates a shared array by deeply copying a normal array a and using the copy of h as header
val make : Netmcore.res_id -> int -> 'e -> 'h -> ('e, 'h) sarray
make pool_id n x h: Creates a shared array of the passed number of elements, copies the element x, and initializes each element of the new array with the single copy of x. The value h is copied and used as header.
val init : Netmcore.res_id -> int -> (int -> 'e) -> 'h -> ('e, 'h) sarray
init pool_id n f h: Creates a shared array of the passed number of elements, and for getting the element at position k the function f k is run, and the copy of the result is written to the position. The header is set to the copy of h.
val grow : ('e, 'a) sarray -> int -> 'e -> unit
grow sa n x: Grows the array to n elements. The new elements are initialized to a (single) copy of x.

If n is smaller than the current length, the function will do nothing, and keep the length.

val set : ('e, 'a) sarray -> int -> 'e -> unit
set sa k x: Sets the k-th element of the array sa to a deep copy of x.
val get_ro : ('e, 'a) sarray -> int -> 'e
get_ro sa k: Gets the k-th element of the shared array sa. Note that there is no guarantee that this value still exists if it is returned, and a parallely running set changes this element. If such values are accessed the program may crash!
val get_p : ('e, 'b) sarray -> int -> ('e -> 'a) -> 'a
get_p sa k f: Gets the k-th element of the shared array sa and call f with this element, and returns the result of f. During the execution of f the requested element cannot be garbage collected.
val get_c : ('e, 'a) sarray -> int -> 'e
get_c sa k: Gets a copy of the k-th element of the shared array sæ
val length : ('a, 'b) sarray -> int
Returns the length
val header : ('a, 'h) sarray -> 'h
Returns the header
val deref : ('e, 'a) sarray -> 'e array
Returns the raw array in shared memory for unprotected access
val heap : ('a, 'b) sarray -> Obj.t Netmcore_heap.heap
Return the backing heap structure
val descr_of_sarray : ('e, 'h) sarray -> ('e, 'h) sarray_descr
Returns the descriptor
val sarray_of_descr : Netmcore.res_id ->
('e, 'h) sarray_descr -> ('e, 'h) sarray
Look up the buffer for this descriptor

Mutating header fields

Special care has to be taken when mutating header fields. The header must completely live in the same heap. For adding new values, one has to use Netmcore_heap.modify. Example for a header of type:

    type header =
      { mutable n : int;
        mutable name : string
      }
    

Here, the field n can be directly assigned because an int is always an unboxed value. So,

    h.n <- new_value
    

is legal. However, strings are heap-allocated. For an assignment to name we need to use Netmcore_heap.modify, as in

    Netmcore_heap.modify
      (Netmcore_array.heap sa)
      (fun mutator ->
        h.name <- Netmcore_heap.add mutator new_value
      )
    

The function Netmcore_heap.add pushes a copy of the new_value to the heap, and this allows us to do the assignment.

During Netcore_heap.modify certain operations are prohibited because they would cause a deadlock:

  • grow
  • set
  • get_p
  • get_c
(This may be relaxed in a future version.)
ocamlnet-4.1.2/doc/html-main/Netcgi_dbi.DBI_POOL.html0000644000175000017500000004474512731530353020562 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_dbi.DBI_POOL

Module type Netcgi_dbi.DBI_POOL

module type DBI_POOL = sig .. end

type connection 
val get : Netcgi.cgi ->
?host:string ->
?port:string ->
?user:string -> ?password:string -> string -> connection
Example: module MyPool = DbiPool(Dbi_postgres)

let dbh = MyPool.get request "database_name"

Returns an unused Dbi.connection handle from the pool of database handles. Or it may create a new database connection and return that.

The parameters uniquely identify the database name (eg. "comments") and optional parameters. Separate pools are maintained for each combination of parameters.

The connection is automatically returned to the pool at the end of the cgi request. After this time the connection may be given away to another user. For this reason, the calling code must NEVER stash the connection across requests (instead, call get to get a new handle each time).

On returning the handle to the pool, the pool performs a ROLLBACK operation on the handle, thus losing any changes (INSERT, etc.) made to the database. If the program wants to preserve changes, it must perform a COMMIT operation itself, by calling Dbi.connection.commit.

ocamlnet-4.1.2/doc/html-main/Netdn.AT_LOOKUP.html0000644000175000017500000004377312731530353017751 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdn.AT_LOOKUP

Module type Netdn.AT_LOOKUP

module type AT_LOOKUP = sig .. end

val attribute_types : (Netdn.oid * string * string list) list
The above types in the format (oid, full_name, short_names)
val lookup_attribute_type_by_oid : Netdn.oid -> string * string list
Looks the OID up, and returns (full_name, short_names). May raise Not_found.
val lookup_attribute_type_by_name : string -> Netdn.oid * string * string list
Looks the name up, which can either be a full name or a short name. Returns the whole triple (oid, full_name, short_names), or raises Not_found.
ocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi_types.cgi_activation.html0000644000175000017500000005531612731530353026615 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_types.cgi_activation object
  method argument : string -> Netcgi1_compat.Netcgi_types.cgi_argument
  method argument_value : ?default:string -> string -> string
  method arguments : (string * Netcgi1_compat.Netcgi_types.cgi_argument) list
  method delete_argument : ?fin:bool -> string -> unit
  method environment : Netcgi1_compat.Netcgi_env.cgi_environment
  method finalize : unit -> unit
  method initial_argument :
    string -> Netcgi1_compat.Netcgi_types.cgi_argument
  method initial_argument_value : ?default:string -> string -> string
  method initial_arguments :
    (string * Netcgi1_compat.Netcgi_types.cgi_argument) list
  method initial_multiple_argument :
    string -> Netcgi1_compat.Netcgi_types.cgi_argument list
  method multiple_argument :
    string -> Netcgi1_compat.Netcgi_types.cgi_argument list
  method output : Netchannels.trans_out_obj_channel
  method request_method : Netcgi1_compat.Netcgi_types.request_method
  method set_arguments :
    ?fin:bool -> Netcgi1_compat.Netcgi_types.cgi_argument list -> unit
  method set_header :
    ?status:Netcgi1_compat.Netcgi_types.status ->
    ?content_type:string ->
    ?cache:Netcgi1_compat.Netcgi_types.cache_control ->
    ?filename:string ->
    ?language:string ->
    ?script_type:string ->
    ?style_type:string ->
    ?set_cookie:Netcgi1_compat.Netcgi_types.cgi_cookie list ->
    ?fields:(string * string list) list -> unit -> unit
  method set_redirection_header : string -> unit
  method update_argument :
    ?fin:bool -> Netcgi1_compat.Netcgi_types.cgi_argument -> unit
  method update_multiple_argument :
    ?fin:bool -> Netcgi1_compat.Netcgi_types.cgi_argument list -> unit
  method url :
    ?protocol:Netcgi1_compat.Netcgi_env.protocol ->
    ?with_authority:Netcgi1_compat.Netcgi_types.other_url_spec ->
    ?with_script_name:Netcgi1_compat.Netcgi_types.other_url_spec ->
    ?with_path_info:Netcgi1_compat.Netcgi_types.other_url_spec ->
    ?with_query_string:Netcgi1_compat.Netcgi_types.query_string_spec ->
    unit -> string
end
ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi_types.simple_message-c.html0000644000175000017500000004214012731530353025775 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_types.simple_message

Class type Netcgi1_compat.Netcgi_types.simple_message

class type simple_message = Netmime.mime_body

ocamlnet-4.1.2/doc/html-main/type_Netplex_controller.html0000644000175000017500000004403312731530353022216 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_controller sig
  val create_controller :
    Netplex_types.parallelizer ->
    Netplex_types.controller_config -> Netplex_types.controller
  val create_controller_for_esys :
    Unixqueue.event_system ->
    Netplex_types.parallelizer ->
    Netplex_types.controller_config -> Netplex_types.controller
  val extract_config :
    Netplex_types.logger_factory list ->
    Netplex_types.config_file -> Netplex_types.controller_config
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/index_class_types.html0000644000175000017500000015610212731530353021014 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of class types

Index of class types


A
async_in_channel [Uq_engines_compat]
async_in_channel [Uq_transfer]
An asynchrounous input channel provides methods to input data from a stream descriptor.
async_in_channel [Uq_engines]
async_in_channel_engine [Uq_engines_compat]
async_in_channel_engine [Uq_transfer]
Combination of engine + async_in_channel
async_in_channel_engine [Uq_engines]
async_out_channel [Uq_engines_compat]
async_out_channel [Uq_transfer]
An asynchrounous output channel provides methods to output data to a stream descriptor.
async_out_channel [Uq_engines]
async_out_channel_engine [Uq_engines_compat]
async_out_channel_engine [Uq_transfer]
Combination of engine + async_out_channel
async_out_channel_engine [Uq_engines]
auth_details [Rpc_server]
auth_handler [Nethttp_client]
An authentication handler has the capability of adding the necessary headers to messages.
auth_method [Rpc_server]
auth_method [Rpc_client]
An auth_method object represents a method of authentication.
auth_protocol [Rpc_client]
An authentication protocol is used for creating an authentication session.
auth_session [Rpc_client]
An auth_session object is normally created for every client instance.
auth_session [Nethttp_client]
An auth_session represents an authenticated session

C
cache_t [Uq_engines_compat]
cache_t [Uq_engines]
A cache contains a mutable value that is obtained by running an engine.
cgi [Netcgi_fcgi]
The usual Netcgi.cgi class with FCGI specific methods.
cgi [Netcgi]
Object symbolizing a CGI-like request/response cycle.
cgi [Netcgi_apache]
The usual cgi class with an additional method to access Apache specificities.
cgi_activation [Netcgi1_compat.Netcgi_types]
Portage: In addition to defining a type, the following cgi_activation also defines a conversion function that allows to connect old scripts to the new infrastructure.
cgi_activation [Netcgi]
Alternate, more descriptive name for cgi
cgi_argument [Netcgi1_compat.Netcgi_types]
Portage: In addition to defining a type, the following cgi_argument also defines a conversion function that allows to connect old scripts to the new infrastructure.
cgi_argument [Netcgi]
Represent a key-value pair of data passed to the script (including file uploads).
cgi_argument [Netcgi_common]
cgi_environment [Netcgi1_compat.Netcgi_env]
cgi_environment [Netcgi]
The environment of a request consists of the information available besides the data sent by the user (as key-value pairs).
cipher [Netsys_ciphers]
cipher_ctx [Netsys_ciphers]
client_config [Netsys_gssapi]
client_endpoint_connector [Uq_engines_compat]
client_endpoint_connector [Uq_client]
This class type provides engines to connect to a service.
client_endpoint_connector [Uq_engines]
client_key_ring [Netmech_scram_gssapi]
A client_key_ring identifies the user on the client side
client_props [Netsys_gssapi]
Return properties of the client context
client_socket_connector [Uq_engines_compat]
compl_in_channel [Netchannels]
Further methods usually supported by ocamlnet channel implementations.
compl_out_channel [Netchannels]
Further methods usually supported by ocamlnet channel implementations.
compute_resource [Netmcore]
condition [Netsys_oothr]
config_file [Netplex_types]
connection_cache [Nethttp_client_conncache]
container [Netplex_types]
Containers encapsulate the control flow of the service components.
controller [Netplex_types]
The controller is the object in the Netplex master process/thread that manages the containers, logging, and service definitions
controller_config [Netplex_types]
crypto_in_filter [Netchannels_crypto]
Encrypt or decrypt data while reading from a channel
crypto_out_filter [Netchannels_crypto]
Encrypt or decrypt data while writing to a channel
ctrl_message_receiver [Netplex_types]

D
datagram_multiplex_controller [Uq_engines_compat]
datagram_multiplex_controller [Uq_multiplex]
Additional methods for unconnected datagram handling
datagram_multiplex_controller [Uq_engines]
datagram_socket_provider [Uq_engines_compat]
datagram_socket_provider [Uq_datagram]
This is a factory for wrapped_datagram_socket objects.
datagram_socket_provider [Uq_engines]
digest [Netsys_digests]
digest_ctx [Netsys_digests]
directory_name [Netx509]
Directory names are also known as distinguished names.
dynamic_workload_config [Netplex_workload]

E
engine [Uq_engines_compat]
engine [Uq_engines]
This class type defines the interface an engine must support.
engine [Uq_resolver]
enhanced_raw_in_channel [Netchannels]
Defines private methods reading text line by line
error_response_params [Nethttpd_types]
event_system [Unixqueue]
The event_system manages events, handlers, resources, groups, etc.
extended_async_environment [Nethttpd_engine]
extended_environment [Nethttpd_types]
Same as v_extended_environment, but no virtual methods

F
ftp_client_pi [Netftp_client]
The client protocol interpreter...
ftp_data_engine [Netftp_data_endpoint]
The common type of FTP data engines
ftp_stream_fs [Netftp_fs]
full_info [Nethttpd_types]

G
generic_config [Netplex_log]
glob_fsys [Netglob]
Filesystem primitives.
gss_api [Netsys_gssapi.GSSAPI]
The methods have generally a type of the form

H
http_call [Nethttp_client]
The container for HTTP calls
http_engine_config [Nethttpd_engine]
http_engine_processing_config [Nethttpd_engine]
http_engine_processing_context [Nethttpd_engine]
http_header [Nethttp]
http_header_ro [Nethttp]
The HTTP header is represented as MIME header
http_processor_config [Nethttpd_reactor]
http_protocol_config [Nethttpd_kernel]
Configuration values for the HTTP kernel
http_protocol_hooks [Nethttpd_kernel]
Allows it to set hooks for Nethttpd_kernel.http_protocol
http_reactive_request [Nethttpd_reactor]
http_reactor_config [Nethttpd_reactor]
http_request_header_notification [Nethttpd_engine]
http_request_notification [Nethttpd_engine]
http_response [Nethttpd_kernel]
Encapsultation of the HTTP response for a single request
http_service [Nethttpd_types]
http_service_generator [Nethttpd_types]
http_service_receiver [Nethttpd_types]
http_stream_fs [Nethttp_fs]
http_trailer [Nethttp]
http_trailer_ro [Nethttp]
The HTTP trailer is represented as MIME header

I
in_obj_channel [Netchannels]
The application-level input channel supports raw and complemented methods
in_obj_stream [Netstream]
An in_obj_stream extends in_obj_channel by look-ahead methods
in_record_channel [Netftp_data_endpoint]
An in_record_channel can be used to read files with record structure.
internal_environment [Nethttpd_reactor]
For private use only
io_obj_channel [Netchannels]
A channel supporting both input and output.

J
job_handler_engine_type [Shell_uq]
This type of engine also returns the job and the job_instance.
job_handler_engine_type [Shell_sys]
This type of engine also returns the job and the job_instance.

K
key [Nethttp_client]
A key is a user/password combination for a certain realm
key_handler [Nethttp_client]

L
ldap_result [Netldap]
A class type for encapsulating results
ldap_server [Netldap]
local_file [Netfs]
logger [Netplex_types]
A logger receives log messages
logger_factory [Netplex_types]

M
mime_body [Netmime]
A MIME body with both read and write method.
mime_body_ro [Netmime]
This is the read-only version of a MIME body.
mime_header [Netmime]
A MIME header with both read and write method.
mime_header_ro [Netmime]
This is the read-only version of a MIME header.
min_config [Nethttpd_types]
Minimal configuration needed for output_std_response
mstring [Netsys_types]
See Netxdr_mstring.mstring for documentation
mstring [Netxdr_mstring]
The object holding the string value
mstring_factory [Netxdr_mstring]
The object creating new mstring objects
mtprovider [Netsys_oothr]
multi_file_config [Netplex_log]
multiplex_controller [Uq_engines_compat]
multiplex_controller [Uq_multiplex]
A multiplex_controller is a quite low-level device to abstract bidirectional socket connections.
multiplex_controller [Uq_engines]
This definition has now been moved to Uq_multiplex.multiplex_controller
mutex [Netsys_oothr]

N
netplex_config [Netplex_types]

O
out_obj_channel [Netchannels]
The application-level output channel supports raw and complemented methods
out_record_channel [Netftp_data_endpoint]
An out_record_channel can be used to output files with record structure.

P
par_thread [Netplex_types]
parallelizer [Netplex_types]
plugin [Netplex_types]
Plugins are extensions of the Netplex system that run in the controller and can be invoked from containers
pmanage [Netsys_pmanage]
pollset [Netsys_pollset]
poly_gss_api [Netsys_gssapi]
post_fork_handler [Netsys_posix]
A post_fork_handler is a named function unit -> unit
prioritizer_t [Uq_engines_compat]
prioritizer_t [Uq_engines]
A prioritizer allows to prioritize the execution of engines: At any time, only engines of a certain priority p can be executed.
processor [Netplex_types]
The processor is the object that is notified when a new TCP connection is accepted.
processor_factory [Netplex_types]
processor_hooks [Netplex_types]
Processor hooks can be used to modify the behavior of a processor.
propagator [Netsys_global]
protocol [Netplex_types]

R
raw_in_channel [Netchannels]
Basic Unix-level class type for input channels as used by ocamlnet.
raw_io_channel [Netchannels]
A channel supporting both input and output.
raw_out_channel [Netchannels]
Basic Unix-level class type for output channels as used by ocamlnet.
rec_in_channel [Netchannels]
Recommended input class type for library interoperability.
rec_out_channel [Netchannels]
Recommended output class type for library interoperability.
request_info [Nethttpd_types]
resolver [Uq_resolver]
rpc_multiplex_controller [Rpc_transport]
rw_cgi_argument [Netcgi]
Old deprecated writable argument type.
rw_cgi_argument [Netcgi_common]

S
sb_event_system [Unixqueue_select]
serializer_t [Uq_engines_compat]
serializer_t [Uq_engines]
A serializer queues up engines, and starts the next engine when the previous one finishes.
server_config [Netsys_gssapi]
server_endpoint_acceptor [Uq_engines_compat]
server_endpoint_acceptor [Uq_server]
This class type is for service providers that listen for connections.
server_endpoint_acceptor [Uq_engines]
server_endpoint_listener [Uq_engines_compat]
server_endpoint_listener [Uq_engines]
Moved to Uq_server.server_endpoint_listener
server_key_verifier [Netmech_scram_gssapi]
A server_key_verifier verifies on the server side that the users exist and have the right authentication credentials
server_props [Netsys_gssapi]
Return properties of the server context
server_socket_acceptor [Uq_engines_compat]
server_socket_listener [Uq_engines_compat]
shell_stream_fs [Shell_fs]
simple_message [Netcgi1_compat.Netcgi_types]
socket_config [Rpc_server]
socket_config [Rpc_client]
Configuration for `Socket (see below).
socket_controller [Netplex_types]
socket_service [Netplex_types]
socket_service_config [Netplex_types]
stream_fs [Netfs]
syslog_config [Netplex_log]

T
thread [Netsys_oothr]
tls_cache [Nethttp_client]
A cache object for storing TLS session data
tls_channel [Netchannels_crypto]
A TLS channel is a layer on top of a bidirectional channel that adds the TLS protocol.
tls_session_props [Nettls_support]
Direct access to TLS properties of a session
trans_out_obj_channel [Netchannels]
A transactional output channel has a buffer for uncommitted data.
transport_channel_type [Nethttp_client]

U
user_info [Netglob]
Access to the user database

V
v_extended_environment [Nethttpd_types]
An extension of cgi_environment for use with the daemon.
v_processor [Netplex_kit]
Same as processor, but the methods process and supported_ptypes are flagged as virtual

W
workload_manager [Netplex_types]
See Netplex_workload for definitions of workload managers
workload_manager_factory [Netplex_types]
wrapped_datagram_socket [Uq_engines_compat]
wrapped_datagram_socket [Uq_datagram]
A wrapped_datagram_socket allows datagrams to be sent via proxies.
wrapped_datagram_socket [Uq_engines]

X
x509_certificate [Netx509]
An X.509 certificate in decoded form.
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.SCRAM.html0000644000175000017500000004114412731530353022772 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM functor (P : PROFILE-> Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/Netplex_kit.html0000644000175000017500000005603112731530353017562 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit

Module Netplex_kit

module Netplex_kit: sig .. end
Netplex toolkit

class type virtual v_processor = object .. end
Same as processor, but the methods process and supported_ptypes are flagged as virtual
class empty_processor_hooks : unit -> Netplex_types.processor_hooks
This is an empty set of processor hooks, i.e.
class processor_hooks_delegation : Netplex_types.processor_hooks -> Netplex_types.processor_hooks
Takes a hooks object, and makes a class of it.
class virtual processor_base : Netplex_types.processor_hooks -> v_processor
A virtual (incomplete) base class for processors.
class protocol_switch_processor : (string * Netplex_types.processor) list -> Netplex_types.processor
The arg is a list of pairs (proto_name, proto_proc).
class protocol_switch_factory : string -> (string * Netplex_types.processor_factory) list -> Netplex_types.processor_factory
protocol_switch_factory name merge_list: Merges the factories in merge_list to a single factory.
val add_helper_service : Netplex_types.controller -> string -> Netplex_types.processor_hooks -> unit
add_helper_service ctrl name hooks: Adds a helper service name to the controller ctrl. The helper service does not have any externally accessible socket, but starts a single regular container that looks like any other container. Whatever needs to be initialized must be done in the pre_start_hook or the post_start_hook.

This function must be called in controller context, for example in the late_initializer of Netplex_main.startup, but it can also be started later.

For an example, look at examples/netplex/helper_container.ml in the distributed source tarball.

For multi-threaded programs, Netplex_cenv.run_in_controller_context is the required companion function to start helper threads at any time. Multi-processing programs do not have such an easy way to add helpers. They should it at program startup time.

Known bug. The the helper component will be in "starting" state as long as the post_start_hook runs.

val create_protocol : ?lstn_backlog:int ->
?lstn_reuseaddr:bool ->
?so_keepalive:bool ->
?tcp_nodelay:bool ->
?local_chmod:int ->
?local_chown:int * int ->
?configure_slave_socket:(Unix.file_descr -> unit) ->
string -> Netplex_types.extended_address array -> Netplex_types.protocol
create_protocol name addresses: Creates a protocol object from the passed arguments
val create_socket_service_config : ?startup_timeout:float ->
?change_user_to:int * int ->
?gc_when_idle:bool ->
?conn_limit:int ->
string ->
Netplex_types.protocol list ->
Netplex_types.controller_config -> Netplex_types.socket_service_config
create_socket_service_config name protos ctrl_conf: Creates a socket_service_config object from the passed arguments
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_kernel.html0000644000175000017500000011672712731530353021500 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel sig
  type fatal_error =
      [ `Broken_pipe
      | `Broken_pipe_ignore
      | `Message_too_long
      | `Server_error
      | `TLS_error of string * string
      | `Timeout
      | `Unix_error of Unix.error ]
  val string_of_fatal_error : Nethttpd_kernel.fatal_error -> string
  type bad_request_error =
      [ `Bad_header
      | `Bad_header_field of string
      | `Bad_request_line
      | `Bad_trailer
      | `Format_error of string
      | `Protocol_not_supported
      | `Request_line_too_long
      | `Unexpected_eof ]
  val string_of_bad_request_error :
    Nethttpd_kernel.bad_request_error -> string
  val status_of_bad_request_error :
    Nethttpd_kernel.bad_request_error -> Nethttp.http_status
  type data_chunk = Bytes.t * int * int
  type status_line = int * string
  type transfer_coding = [ `Chunked | `Identity ]
  type resp_token =
      [ `Resp_action of unit -> unit
      | `Resp_body of Nethttpd_kernel.data_chunk
      | `Resp_end
      | `Resp_header of Nethttp.http_header
      | `Resp_info_line of Nethttpd_kernel.status_line * Nethttp.http_header
      | `Resp_status_line of Nethttpd_kernel.status_line
      | `Resp_trailer of Nethttp.http_trailer ]
  val resp_100_continue : Nethttpd_kernel.resp_token
  type resp_state =
      [ `Active | `Dropped | `Error | `Inhibited | `Processed | `Queued ]
  type front_token =
      [ `Resp_end | `Resp_wire_data of Nethttpd_kernel.data_chunk ]
  exception Send_queue_empty
  type announcement =
      [ `As of string | `Ignore | `Ocamlnet | `Ocamlnet_and of string ]
  class type http_response =
    object
      method advance : int -> unit
      method bidirectional_phase : bool
      method body_size : int64
      method close_connection : bool
      method front_token : Nethttpd_kernel.front_token
      method protocol : Nethttp.protocol
      method send : Nethttpd_kernel.resp_token -> unit
      method send_queue_empty : bool
      method set_callback : (unit -> unit) -> unit
      method set_state : Nethttpd_kernel.resp_state -> unit
      method state : Nethttpd_kernel.resp_state
      method transfer_encoding : Nethttpd_kernel.transfer_coding
    end
  class http_response_impl :
    ?close:bool ->
    ?suppress_body:bool ->
    int64 ->
    Nethttp.protocol -> Nethttpd_kernel.announcement -> http_response
  val send_static_response :
    Nethttpd_kernel.http_response ->
    Nethttp.http_status -> Nethttp.http_header option -> Bytes.t -> unit
  val send_file_response :
    Nethttpd_kernel.http_response ->
    Nethttp.http_status ->
    Nethttp.http_header option -> Unix.file_descr -> int64 -> unit
  type request_line = Nethttp.http_method * Nethttp.protocol
  type req_token =
      [ `Bad_request_error of
          Nethttpd_kernel.bad_request_error * Nethttpd_kernel.http_response
      | `Eof
      | `Fatal_error of Nethttpd_kernel.fatal_error
      | `Req_body of Nethttpd_kernel.data_chunk
      | `Req_end
      | `Req_expect_100_continue
      | `Req_header of
          Nethttpd_kernel.request_line * Nethttp.http_header *
          Nethttpd_kernel.http_response
      | `Req_trailer of Nethttp.http_trailer
      | `Timeout ]
  val string_of_req_token : Nethttpd_kernel.req_token -> string
  exception Recv_queue_empty
  class type http_protocol_config =
    object
      method config_announce_server : Nethttpd_kernel.announcement
      method config_limit_pipeline_length : int
      method config_limit_pipeline_size : int
      method config_max_header_length : int
      method config_max_reqline_length : int
      method config_max_trailer_length : int
      method config_suppress_broken_pipe : bool
      method config_tls : Netsys_crypto_types.tls_config option
    end
  val default_http_protocol_config : Nethttpd_kernel.http_protocol_config
  class modify_http_protocol_config :
    ?config_max_reqline_length:int ->
    ?config_max_header_length:int ->
    ?config_max_trailer_length:int ->
    ?config_limit_pipeline_length:int ->
    ?config_limit_pipeline_size:int ->
    ?config_announce_server:Nethttpd_kernel.announcement ->
    ?config_suppress_broken_pipe:bool ->
    ?config_tls:Netsys_crypto_types.tls_config option ->
    Nethttpd_kernel.http_protocol_config -> http_protocol_config
  class type http_protocol_hooks =
    object
      method tls_set_cache :
        store:(string -> string -> unit) ->
        remove:(string -> unit) -> retrieve:(string -> string) -> unit
    end
  class http_protocol :
    #Nethttpd_kernel.http_protocol_config ->
    Unix.file_descr ->
    object
      method abort : Nethttpd_kernel.fatal_error -> unit
      method config : Nethttpd_kernel.http_protocol_config
      method cycle : ?block:float -> unit -> unit
      method do_input : bool
      method do_output : bool
      method fd : Unix.file_descr
      method hooks : Nethttpd_kernel.http_protocol_hooks
      method input_timeout_class : [ `Next_message | `None | `Normal ]
      method need_linger : bool
      method peek_recv : unit -> Nethttpd_kernel.req_token
      method pipeline_len : int
      method receive : unit -> Nethttpd_kernel.req_token
      method recv_queue_byte_size : int
      method recv_queue_len : int
      method resp_queue_filled : bool
      method resp_queue_len : int
      method shutdown : unit -> unit
      method test_coverage : string list
      method timeout : unit -> unit
      method tls_session_props : Nettls_support.tls_session_props option
      method waiting_for_next_message : bool
    end
  class lingering_close :
    ?preclose:(unit -> unit) ->
    Unix.file_descr ->
    object
      method cycle : ?block:bool -> unit -> unit
      method fd : Unix.file_descr
      method lingering : bool
    end
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels_crypto.tls_channel.html0000644000175000017500000004322012731530353024464 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.tls_channel object
  method close_in : unit -> unit
  method close_out : unit -> unit
  method flush : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method output : Bytes.t -> int -> int -> int
  method pos_in : int
  method pos_out : int
  method tls_endpoint : Netsys_crypto_types.tls_endpoint
end
ocamlnet-4.1.2/doc/html-main/Netplex_types.parallelizer-c.html0000644000175000017500000004723612731530353023053 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.parallelizer

Class type Netplex_types.parallelizer

class type parallelizer = object .. end

method ptype : parallelization_type
method init : unit -> unit
Initializes the main process for usage with this parallelizer. This method must not be called outside the internal Netplex implementation!
method start_thread : (par_thread -> unit) ->
Unix.file_descr list ->
Unix.file_descr list ->
string -> logger -> par_thread
start_thread f l_close l_share name logger: Starts a new thread or process and calls f thread in that context. Before this is done, file descriptors are closed, controlled by the parameters l_close and l_share. The descriptors in l_close are always closed. The descriptors in l_share are not closed. The implementation of the parallelizer is free to close a reasonable set of descriptors, and l_close is the minimum, and all - l_share is the maximum.

There is no way to check when the thread terminates.

It is allowed that the par_thread object passed to f is a different object as the returned par_thread object.

method create_mem_mutex : unit -> (unit -> unit) * (unit -> unit)
let lock, unlock = par#create_mem_locker(): Creates a mutex that is sufficient to protect process memory from uncoordinated access. The function lock obtains the lock, and unlock releases it.
method current_sys_id : [ `Process of int | `Thread of int ]
Returns the system-dependent thread identifier of the caller
ocamlnet-4.1.2/doc/html-main/Netmech_scram.Cryptosystem.html0000644000175000017500000005234412731530353022573 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram.Cryptosystem

Module Netmech_scram.Cryptosystem

module Cryptosystem: sig .. end
This is the cryptosystem as defined in RFC 3961, so far needed here. This uses AES_CTS as cipher, and SHA1-96 for signing.

exception Integrity_error
val derive_keys : string -> int -> Netmech_scram.specific_keys
derive_keys protocol_key usage: Returns the specific keys for this protocol_key and this usage numbers. See RFC 4121 for applicable usage numbers
val encrypt_and_sign : Netmech_scram.specific_keys -> string -> string
Encrypts the plaintext message and adds a signature to the ciphertext.

Returns ciphertext_with_signature.

val encrypt_and_sign_mstrings : Netmech_scram.specific_keys ->
Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
Same, but with data representation as mstring list
val decrypt_and_verify : Netmech_scram.specific_keys -> string -> string
Decrypts the ciphertext and verifies the attached signature. Returns the restored plaintext.

For very short plaintexts (< 16 bytes) there will be some padding at the end ("residue"), as returned as ec above. We ignore this problem generally, because GSS-API adds a 16-byte header to the plaintext anyway, so these short messages do not occur.

If the signature is not valid, the exception Integrity_error is raised.

val decrypt_and_verify_mstrings : Netmech_scram.specific_keys ->
Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
Same, but with data representation as mstring list
val get_ec : Netmech_scram.specific_keys -> int -> int
let ec = get_ec e_keys n: Returns the required value for the "extra count" field of RFC 4121 if the plaintext message has size n. Here, n is the size of the payload message plus the token header of 16 bytes, i.e. the function is always called with n >= 16.

Here, the returned ec value is always 0.

val get_mic : Netmech_scram.specific_keys -> string -> string
Returns a message integrity code
val get_mic_mstrings : Netmech_scram.specific_keys -> Netxdr_mstring.mstring list -> string
Same, but with data representation as mstring list
ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi.html0000644000175000017500000004700412731530353021341 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi

Module Netcgi1_compat.Netcgi

module Netcgi: sig .. end

type argument_processing = [ `Automatic | `File | `Memory ] 
type operating_type = [ `Direct of string
| `Transactional of
Netcgi1_compat.Netcgi_env.cgi_config ->
Netchannels.out_obj_channel -> Netchannels.trans_out_obj_channel ]
class simple_argument : ?ro:bool -> string -> string -> Netcgi1_compat.Netcgi_types.cgi_argument
class mime_argument : ?work_around_backslash_bug:bool -> string -> Netmime.mime_message -> Netcgi1_compat.Netcgi_types.cgi_argument
class std_activation : ?env:Netcgi1_compat.Netcgi_env.cgi_environment -> ?processing:string -> Netmime.mime_header -> argument_processing -> ?operating_type:operating_type -> unit -> Netcgi1_compat.Netcgi_types.cgi_activation
val buffered_transactional_optype : operating_type
val tempfile_transactional_optype : operating_type
ocamlnet-4.1.2/doc/html-main/Netplex_cenv.Make_var_type.html0000644000175000017500000004464612731530353022524 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.Make_var_type

Functor Netplex_cenv.Make_var_type

module Make_var_type: 
functor (T : TYPE) -> VAR_TYPE with type t = T.t
Creates get and set like make_var_type. Call it like

         module Foo_var = 
           Make_var_type(struct t = foo end)
      

and use Foo_var.get and Foo_var.set to access the container variables of type foo.

Parameters:
T : TYPE

type t 
val get : string -> t
val set : string -> t -> unit
ocamlnet-4.1.2/doc/html-main/type_Netchannels.io_obj_channel.html0000644000175000017500000004750512731530353023535 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.io_obj_channel object
  method close_in : unit -> unit
  method close_out : unit -> unit
  method flush : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method input_byte : unit -> int
  method input_char : unit -> char
  method input_line : unit -> string
  method output : Bytes.t -> int -> int -> int
  method output_buffer : Buffer.t -> unit
  method output_byte : int -> unit
  method output_bytes : Bytes.t -> unit
  method output_channel : ?len:int -> in_obj_channel -> unit
  method output_char : char -> unit
  method output_string : string -> unit
  method pos_in : int
  method pos_out : int
  method really_input : Bytes.t -> int -> int -> unit
  method really_input_string : int -> string
  method really_output : Bytes.t -> int -> int -> unit
  method really_output_string : string -> int -> int -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netx509.x509_certificate.html0000644000175000017500000004457212731530353022566 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_certificate object
  method extensions : (Netx509.oid * string * bool) list
  method issuer : Netx509.directory_name
  method issuer_unique_id : Netasn1.Value.bitstring_value option
  method public_key : Netasn1.Value.bitstring_value
  method public_key_algorithm : Netx509.oid * Netasn1.Value.value option
  method serial_number : string
  method signature : Netasn1.Value.bitstring_value
  method signature_algorithm : Netx509.oid * Netasn1.Value.value option
  method subject : Netx509.directory_name
  method subject_unique_id : Netasn1.Value.bitstring_value option
  method valid_not_after : float
  method valid_not_before : float
  method version : int
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_kernel.Debug.html0000644000175000017500000004101012731530353022503 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netsys_sasl.Info.html0000644000175000017500000004276712731530353021551 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl.Info sig
  val mechanism_name : Netsys_sasl.sasl_mechanism -> string
  val client_first :
    Netsys_sasl.sasl_mechanism -> [ `No | `Optional | `Required ]
  val server_sends_final_data : Netsys_sasl.sasl_mechanism -> bool
  val supports_authz : Netsys_sasl.sasl_mechanism -> bool
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.datagram_multiplex_controller-c.html0000644000175000017500000004357612731530353025750 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.datagram_multiplex_controller

Class type Uq_engines.datagram_multiplex_controller

class type datagram_multiplex_controller = object .. end
Inherits
method received_from : Unix.sockaddr
method send_to : Unix.sockaddr -> unit
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.FILE_TLS_ENDPOINT.TLS.html0000644000175000017500000013476012731530353024614 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.FILE_TLS_ENDPOINT.TLS

Module Netsys_crypto_types.FILE_TLS_ENDPOINT.TLS

module TLS: Netsys_crypto_types.TLS_PROVIDER 


Provides TLS functionality.

Users should not call functions of the provider directly, but use Netsys_tls, or another higher-level layer.

type config 
type credentials 
type endpoint 
module Exc: Netsys_crypto_types.TLS_EXCEPTIONS 
Access to exceptions
val error_message : string -> string
Returns the message for humans (display, log files etc.) when called with an error or warning symbol.
type dh_params = [ `Generate of int | `PKCS3_DER of string | `PKCS3_PEM_file of string ] 
Diffie-Hellman parameters:

  • `PKCS3_PEM_file name: points to a PEM-encoded PKCS3-file ("BEGIN DH PARAMETERS")
  • `PKCS3_DER data: the parameters are in a DER-encoded PKCS3 structure
  • `Generate bits: the parameters are generated with the passed number of bits

val create_config : ?algorithms:string ->
?dh_params:dh_params ->
?verify:(endpoint -> bool -> bool -> bool) ->
peer_auth:[ `None | `Optional | `Required ] ->
credentials:credentials ->
unit -> config
The configuration includes:

  • algorithms: a string specifying which cryptographic algorithms, protocols and protocol options are enabled, and in which priority they are used in the negotiation. (GnuTLS calls this "priority string".) The syntax is implementation-defined.
  • dh_params: parameters for Diffie-Hellman key exchange (used for DH-based authentication, but only on the server side)
  • peer_auth: controls whether the peer is requested to authenticate. This can be set to `None meaning not to request authentication and to ignore credentials, or to `Optional meaning not to request authentication but to check credentials if they are sent nevertheless, or to `Required meaning to request and check credentials. For "standard clients" you should set this to `Required, and for "standard servers" to `None or `Required.
  • credentials describes our own credentials, and the accepted credentials of the peer.
  • verify is a function called to verify the peer certificate in addition to the actions of peer_auth. The function must return true in order to be successful. The arguments of the function are the TLS endpoint, and two bools indicating the success of previous checks. The first bool says whether the certificate is trusted (based on peer_auth, trust and system_trust), and the second bool says whether the host name of the peer matches the name in the certificate. If not passed, verify defaults to (fun _ cert_ok name_ok -> cert_ok && name_ok), i.e. both bools must be true.
A configuration is read-only once created, and can be used for several endpoints. In particular, it does not cache TLS sessions.
type crt_list = [ `DER of string list | `PEM_file of string ] 
Certificates are given either as:

  • `PEM_file name: The certs are stored in this file, and are PEM-encoded.
  • `DER l: The certs are given directly in their DER-encoded form
See also Credentials for TLS.
type crl_list = [ `DER of string list | `PEM_file of string ] 
Certificate revocation lists are given either as:

  • `PEM_file name: The CRLs are stored in this file, and are PEM-encoded.
  • `DER l: The CRLs are given directly in their DER-encoded form
See also Credentials for TLS.
type private_key = [ `DSA of string
| `EC of string
| `PEM_file of string
| `PKCS8 of string
| `PKCS8_encrypted of string
| `RSA of string ]
Private keys are given either as:

  • `PEM_file name: The key is stored PEM-encoded in this file. The PEM header indicates the format.
  • `RSA data: The key is a PKCS1 RSA key
  • `DSA data: The key is a DSA key
  • `EC data: The key is for an elliptic curve
  • `PKCS8 data: The key is in a PKCS8 data structure
  • `PKCS8_encrypted data: The key is in a PKCS8 data structure, and is additionally encrypted.
See also Credentials for TLS.
val create_x509_credentials : ?system_trust:bool ->
?trust:crt_list list ->
?revoke:crl_list list ->
?keys:(crt_list *
private_key * string option)
list ->
unit -> credentials
Create X.509 credentials from individual objects:
  • system_trust: if set, the system certificates are trusted
  • trust specifies the CAs of peers to trust (default: empty)
  • revoke specifies CRLs for revocation of peer certificates (default: empty)
  • keys are our own certificates, as triples (cert_path, private_key, password) (default: empty)
A client should set trust to the list of CAs it can accept on the server side. It is not required to specify a key.

A server must specify a key (but can also specify several keys). If a server requests authentication from the client, it must also set trust.

The keys must include the certificate path cert_path, starting with the endpoint certificate, and followed by all middle certificates, but omitting the certificate of the CA. The private_key is the key of the endpoint. If it is password-encrypted, the password must be given.

val create_endpoint : role:[ `Client | `Server ] ->
recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
endpoint
Creates a new endpoint for this configuration.

peer_name is the expected common name or DNS name of the peer. peer_name has an option type as it is not always required to pass it. However, keep in mind that clients normally authenticate servers (peer_auth=`Required). In order to do so, they need to check whether the name in the server certificate equals the DNS name of the service they are connected to. This check is done by comparing peer_name with the name in the certificate.

peer_name is also used for the SNI extension.

Servers normally need not to set peer_name. You can also omit it when there is no name-driven authentication at all.

The endpoint will use the functions recv and send for I/O, which must be user-supplied. recv buf is expected to read data into the buffer, and to return the number of bytes, or 0 for EOF. send buf n is expected to send the n first bytes in buf.

Both functions may raise Unix_error. The codes Unix.EAGAIN and Unix.EINTR are specially interpreted.

val stash_endpoint : endpoint -> exn
The endpoint in "stashed" form, encapsulated as an exception. This form is intended for keeping the session alive in RAM, but without keeping references to the recv and send functions.

The endpoint passed in to stash_endpoint must no longer be used!

val restore_endpoint : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
exn -> endpoint
Reconnect the stashed endpoint with recv and send functions
val resume_client : recv:(Netsys_types.memory -> int) ->
send:(Netsys_types.memory -> int -> int) ->
peer_name:string option ->
config ->
string -> endpoint
Creates a new endpoint that will resume an old session. This implies the client role.

The session data is passed as string, which must have been retrieved with get_session_data.

type state = [ `Accepting
| `Data_r
| `Data_rs
| `Data_rw
| `Data_w
| `End
| `Handshake
| `Refusing
| `Start
| `Switching ]
The state of a session:

  • `Start: Before the session is started
  • `Handshake: The handshake is being done (and hello needs to be called again)
  • `Data_rw: The connection exists, and is read/write
  • `Data_r: The connection exists, and is read-only
  • `Data_w: The connection exists, and is write-only
  • `Data_rs: The connection exists, and data can be read. There was a switch request (initiated by us), and a response is awaited. No data can be sent in the moment.
  • `Switching: A rehandshake is being negotiated (and switch needs to be called again)
  • `Accepting: A rehandshake is being accepted (and accept_switch needs to be called again)
  • `Refusing: A rehandshake is being refused (and refuse_switch needs to be called again)
  • `End: After finishing the session

val get_state : endpoint ->
state
Return the recorded state
type raw_credentials = [ `Anonymous | `X509 of string ] 
The encoded credentials:
  • `X509 s: The X509 certificate in DER encoding
  • `Anonymous: no certificate or other key is available

val at_transport_eof : endpoint -> bool
Whether the underlying transport channel has seen the end of input. Use this after recv or mem_recv returned 0 to check whether only the TLS enf-of-input message has been read, or the underlying channel (usually the file descriptor) has indicated EOF.
val hello : endpoint -> unit
Performs the initial handshake (exchanges credentials and establishes a session).

hello doesn't verify the peer. Use verify for that.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val bye : endpoint -> Unix.shutdown_command -> unit
Performs the final handshake (exchanges close requests).

If SHUTDOWN_SEND is set, the close request is sent to the peer, and the TLS tunnel is considered as closed for writing. The application can receive further data until recv returns zero bytes meaning that the peer responded with another close request.

If SHUTDOWN_ALL is passed, it is additionally waited until the peer responds with a close request.

A simple SHUTDOWN_RECEIVE is unimplemented and ignored.

In no case the underlying transport is closed or shut down!

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val verify : endpoint -> unit
verify ep peer_name: Checks that:
  • there is a trust chain for the peer's certificate
  • that peer_name is the common name of the certificate subject, or an alternate name
These checks are not performed if peer_auth=`None is set in the configuration!

Additionally, the verify function in the endpoint configuration is called back, and a failure is indicated if this function returns false. This callback is useful to get the certificate of the peer and to perform further checks.

The verify function will raise Failure on failed checks (and Error for internal processing errors).

val get_config : endpoint ->
config
Get the current config (possibly modified because of a rehandshake)
val get_endpoint_creds : endpoint ->
raw_credentials
Get the credentials that was actually used in the handshake, in raw format.
val get_peer_creds : endpoint ->
raw_credentials
Get the credentials of the peer, in raw format. Raises Not_found if not applicable/no credentials present.
val get_peer_creds_list : endpoint ->
raw_credentials list
Get the chain that was actually used in the handshake.
val switch : endpoint ->
config -> unit
The server can use this to request a rehandshake and to use the new configuration for cert verification. This function sends the request, and expects a soon response from the client. The state enters `Data_rs meaning that we can still read data, and at some point recv will raise TLS_switch_response.

On the client side, the request will by returned as exception TLS_switch_request by recv. The client should respond with accept_switch if it accepts the handshake, or refuse_switch if not.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val accept_switch : endpoint ->
config -> unit
On the client: Enter another handshake round with new configuration data.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val refuse_switch : endpoint -> unit
On the client: Refuse a handshake

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val send : endpoint ->
Netsys_types.memory -> int -> int
send ep buffer n: Sends the first n bytes in the buffer over the endpoint, and returns the actual number of processed bytes.

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

val recv : endpoint -> Netsys_types.memory -> int
recv ep buffer n: Receives data, and puts them into the memory buffer, and returns the actual number of received bytes. If 0 is returned, a close request was received by the peer. For closing the tunnel properly this request should be responded by another close request with bye (unless this has already been done).

May raise EAGAIN_RD, EAGAIN_WR, Unix_error(EINTR,_,_), Error or Warning.

The exception TLS_switch_request can only occur on the client side, and should be responded by accept_switch or refuse_switch.

The exception TLS_switch_response can only occur on the server side.

val recv_will_not_block : endpoint -> bool
If there is still unprocessed data in the endpoint buffer, recv is guaranteed not to block or raise EAGAIN.
val get_session_id : endpoint -> string
The (non-printable) session ID
val get_session_data : endpoint -> string
Get the (non-printable) marshalled session data, for later resumption with resume_client
val get_cipher_suite_type : endpoint -> string
The type of the cipher suite:
  • "X509": X509 certificates are used
  • "OPENPGP": OpenPGP certificates are used
  • "ANON": anonymous credentials
  • "SRP": SRP credentials
  • "PSK": PSK credentials

val get_cipher_algo : endpoint -> string
Get the name of the cipher
val get_kx_algo : endpoint -> string
Get the name of the key exchange method
val get_mac_algo : endpoint -> string
Get the name of the message authentication code
val get_compression_algo : endpoint -> string
Get the name of the record-level compression method
val get_cert_type : endpoint -> string
Get the type of the certificate
val get_protocol : endpoint -> string
Get the name of the tunnel protocol
type server_name = [ `Domain of string ] 
val get_addressed_servers : endpoint ->
server_name list
To be used in servers: The client can address one of several virtual servers with the SNI extension, and this function returns which was requested. Raises Not_found if there is nothing appropriate. This information is only available after a handshake, and if the client submitted it.
val set_session_cache : store:(string -> string -> unit) ->
remove:(string -> unit) ->
retrieve:(string -> string) ->
endpoint -> unit
Sets the three callbacks for storing, removing and retrieving sessions (on the server side)
val implementation_name : string
String name of the implementation. By convention this is the full OCaml module path, e.g. "Nettls_gnutls.TLS"
val implementation : unit -> exn
Implementation-defined additional functionality
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_http.PROFILE.html0000644000175000017500000004131712731530353023244 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_http.PROFILE sig
  val mutual : bool
  val hash_function : Netsys_digests.iana_hash_fn
  val test_nonce : string option
end
ocamlnet-4.1.2/doc/html-main/Netgzip.input_gzip-c.html0000644000175000017500000004222312731530353021321 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.input_gzip

Class Netgzip.input_gzip

class input_gzip : Gzip.in_channel -> Netchannels.in_obj_channel
A Gzip.in_channel turned into a Netchannels.in_obj_channel

ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.direct_socket_acceptor.html0000644000175000017500000004116212731530353026475 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.direct_socket_acceptor Unix.file_descr ->
Unixqueue.event_system -> Uq_engines_compat.server_endpoint_acceptor
ocamlnet-4.1.2/doc/html-main/Netgzip.output_deflate-c.html0000644000175000017500000004264712731530353022167 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.output_deflate

Class Netgzip.output_deflate

class output_deflate : ?level:int -> Netchannels.out_obj_channel -> Netchannels.out_obj_channel
let ch' = new output_deflate ch: Data written to ch' is deflated and written to ch. Use this for compressing data while writing.

Note that ch isn't closed when ch' is closed.


ocamlnet-4.1.2/doc/html-main/type_Equeue_intro.html0000644000175000017500000004061512731530353021002 0ustar gerdgerd Ocamlnet 4 Reference Manual : Equeue_intro sig  endocamlnet-4.1.2/doc/html-main/Nethttpd_engine.http_engine_processing_context-c.html0000644000175000017500000004262512731530353027142 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_engine_processing_context

Class type Nethttpd_engine.http_engine_processing_context

class type http_engine_processing_context = object .. end

method engine : unit Uq_engines.engine
The engine doing HTTP
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.multiplex_controller.html0000644000175000017500000005212712731530353024721 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.multiplex_controller object
  method alive : bool
  method cancel_reading : unit -> unit
  method cancel_shutting_down : unit -> unit
  method cancel_writing : unit -> unit
  method event_system : Unixqueue.event_system
  method inactivate : unit -> unit
  method mem_supported : bool
  method read_eof : bool
  method reading : bool
  method shutting_down : bool
  method start_mem_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_mem_writing :
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_shutting_down :
    ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
  method start_writing :
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit
  method supports_half_open_connection : bool
  method tls_session : (string * string) option
  method tls_session_props : Nettls_support.tls_session_props option
  method tls_stashed_endpoint : unit -> exn
  method writing : bool
  method wrote_eof : bool
end
ocamlnet-4.1.2/doc/html-main/Netchannels.tempfile_trans_channel-c.html0000644000175000017500000004365412731530353024470 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.tempfile_trans_channel

Class Netchannels.tempfile_trans_channel

class tempfile_trans_channel : ?close_mode:close_mode -> ?tmp_directory:string -> ?tmp_prefix:string -> out_obj_channel -> trans_out_obj_channel
A transactional output channel with a transaction buffer implemented as temporary file


close_mode : Specifies the semantics of close_out, by default `Commit
tmp_directory : See make_temporary_file
tmp_prefix : See make_temporary_file

ocamlnet-4.1.2/doc/html-main/Netchannels.in_obj_channel_delegation-c.html0000644000175000017500000004254212731530353025102 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.in_obj_channel_delegation

Class Netchannels.in_obj_channel_delegation

class in_obj_channel_delegation : ?close:bool -> in_obj_channel -> in_obj_channel

ocamlnet-4.1.2/doc/html-main/Nethttpd_types.min_config-c.html0000644000175000017500000004342112731530353022640 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.min_config

Class type Nethttpd_types.min_config

class type min_config = object .. end
Minimal configuration needed for output_std_response

method config_error_response : error_response_params -> string
method config_log_error : request_info -> string -> unit
ocamlnet-4.1.2/doc/html-main/index_attributes.html0000644000175000017500000004475712731530353020665 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of class attributes

Index of class attributes


C
config [Nethttpd_types.empty_environment]

H
header_not_sent [Netcgi_common.cgi_environment]
true iff the output headers have not been sent.

I
in_channel [Nethttpd_types.empty_environment]
in_header [Nethttpd_types.empty_environment]

O
out_channel [Nethttpd_types.empty_environment]
out_header [Nethttpd_types.empty_environment]

P
properties [Nethttpd_types.empty_environment]
protocol [Nethttpd_types.empty_environment]

T
tls_session_props [Nethttpd_types.empty_environment]
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.cache_t-c.html0000644000175000017500000004363312731530353022545 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.cache_t

Class type Uq_engines_compat.cache_t

class type ['a] cache_t = object .. end

method get_engine : unit -> 'a engine
method get_opt : unit -> 'a option
method put : 'a -> unit
method invalidate : unit -> unit
method abort : unit -> unit
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.watchdog.html0000644000175000017500000004120112731530353023565 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.watchdog float -> '#Uq_engines_compat.engine -> [unit] Uq_engines_compat.engineocamlnet-4.1.2/doc/html-main/Netmime.mime_header_ro-c.html0000644000175000017500000004423012731530353022046 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.mime_header_ro

Class type Netmime.mime_header_ro

class type mime_header_ro = object .. end
This is the read-only version of a MIME header. There are only methods to read the header fields.

method fields : (string * string) list
method field : string -> string
method multiple_field : string -> string list
The current fields of the header. fields returns the complete header. field name returns the value of the field, or raises Not_found. multiple_field name returns all fields with the same name.

Note that field names are case-insensitive; field "content-length", and field "CONTENT-LENGTH" will return the same field. However, the method fields returns the original field names, without adjustment of the case.

The order of the fields is preserved.

ocamlnet-4.1.2/doc/html-main/type_Netmech_plain_sasl.html0000644000175000017500000004112112731530353022117 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_plain_sasl sig module PLAIN : Netsys_sasl_types.SASL_MECHANISM endocamlnet-4.1.2/doc/html-main/Netshm_data.html0000644000175000017500000005711512731530353017527 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm_data

Module Netshm_data

module Netshm_data: sig .. end
Data representation for shared memory

type 'a data_manager = {
   to_int32_array : 'a -> Netshm.int32_array; (*
Represent the value as an int32_array
*)
   of_int32_array : Netshm.int32_array list -> 'a; (*
Read the value back from its int32_array representation. The array is given as list of array fragments in reverse order. The fragments must not be empty.
*)
   of_int32_array_prefix : (Netshm.int32_array list -> 'a option) option; (*
Read the value back from its int32_array representation. Unlike of_int32_array, it is allowed to pass a prefix of the whole array to this function. As of_int32_array, this prefix is given as list of array fragments in reverse order. The function may return None if it is not yet possible to reconstruct the value. Otherwise the value is returned as Some v.
*)
   hash_fn : 'a -> int32; (*
Hash function
*)
}
The data manager consists of several manager functions. of_int32_array_prefix is optional.
val int32_manager : int32 data_manager
Represents an int32 as one-element int32_array
val int64_manager : int64 data_manager
Represents an int64 as two-element int32_array
val nativeint_manager : nativeint data_manager
Uses either int32_manager or int64_manager to represent nativeint, depending on the size of nativeint.
val int_manager : int data_manager
Uses either int32_manager or int64_manager to represent int, depending on the size of int.
val int32_array_manager : Netshm.int32_array data_manager
The identity representation manager
val string_manager : string data_manager
Represents a string in the following way. The first element is the size of the string. The following elements store the bytes. The last word is filled up with zero bytes if necessary.
val pair_manager : 'a data_manager ->
'b data_manager -> ('a * 'b) data_manager
Creates a compound manager for pairs from two input managers
val left_pair_manager : 'a data_manager -> 'a data_manager
Uses the same representation as pair_manager, but the resulting data manager only reads the left value of the pair.

This data manager does not support to_int32_array.

val option_manager : 'a data_manager -> 'a option data_manager
Creates a data manager from an input data manager for optional values
ocamlnet-4.1.2/doc/html-main/Netsys_tls.Debug.html0000644000175000017500000004155512731530353020475 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_tls.Debug

Module Netsys_tls.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/Netulex.Ulexing.html0000644000175000017500000005057612731530353020342 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netulex.Ulexing

Module Netulex.Ulexing

module Ulexing: sig .. end


This is a lexing buffer for ulex.
type lexbuf 
exception Error
Lexical error
val from_ulb_lexbuf : Netulex.ULB.unicode_lexbuf -> lexbuf
Creates a new lexbuf from the unicode_lexbuf. After that, the unicode_lexbuf must no longer be modified.
val lexeme_start : lexbuf -> int
The character position of the start of the lexeme
val lexeme_end : lexbuf -> int
The character position of the end of the lexeme
val lexeme_length : lexbuf -> int
The length of the lexeme in characters
val lexeme : lexbuf -> int array
Returns the lexeme as array of Unicode code points
val lexeme_char : lexbuf -> int -> int
Returns the code point of a certain character of the lexeme
val sub_lexeme : lexbuf -> int -> int -> int array
Returns a substring of the lexeme as array of Unicode code points. The first int is the characater position where to start, the second int is the number of characters.
val utf8_lexeme : lexbuf -> string
Returns the lexeme as UTF-8 encoded string
val utf8_sub_lexeme : lexbuf -> int -> int -> string
Returns a substring of the lexeme as UTF-8 encoded string. The first int is the characater position where to start, the second int is the number of characters.
val utf8_sub_lexeme_length : lexbuf -> int -> int -> int
Same as String.length(utf8_sub_lexeme args), i.e. returns the number of bytes a certain sub lexeme will have when encoded as UTF-8 string.
ocamlnet-4.1.2/doc/html-main/Uq_engines.server_endpoint_listener-c.html0000644000175000017500000004340412731530353024723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.server_endpoint_listener

Class type Uq_engines.server_endpoint_listener

class type server_endpoint_listener = object .. end
Moved to Uq_server.server_endpoint_listener

method listen : listen_address ->
Unixqueue.event_system ->
server_endpoint_acceptor engine
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.client_socket_connector-c.html0000644000175000017500000004252312731530353026054 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.client_socket_connector

Class type Uq_engines_compat.client_socket_connector

class type client_socket_connector = client_endpoint_connector

ocamlnet-4.1.2/doc/html-main/type_Netcgi_dbi.DBI_DRIVER.html0000644000175000017500000004416712731530353022043 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_dbi.DBI_DRIVER sig
  type connection
  val connect :
    ?host:string ->
    ?port:string ->
    ?user:string ->
    ?password:string -> string -> Netcgi_dbi.DBI_DRIVER.connection
  val close : Netcgi_dbi.DBI_DRIVER.connection -> unit
  val closed : Netcgi_dbi.DBI_DRIVER.connection -> bool
  val commit : Netcgi_dbi.DBI_DRIVER.connection -> unit
  val ping : Netcgi_dbi.DBI_DRIVER.connection -> bool
  val rollback : Netcgi_dbi.DBI_DRIVER.connection -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.msync_engine.html0000644000175000017500000004206412731530353024453 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.msync_engine '#Uq_engines_compat.engine list ->
('-> '-> 'b) ->
'-> Unixqueue.event_system -> ['b] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.modify_http_reactor_config-c.html0000644000175000017500000004551312731530353026421 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.modify_http_reactor_config

Class Nethttpd_reactor.modify_http_reactor_config

class modify_http_reactor_config : ?modify_http_protocol_config:Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config -> ?modify_http_processor_config:http_processor_config ->
http_processor_config -> ?config_reactor_synch:[ `Close | `Connection | `Flush | `Write ] -> http_reactor_config ->
http_reactor_config
Modifies the passed config object as specified by the optional arguments.

modify_http_protocol_config and modify_http_processor_config: These functions can be used to modify the parts of the config object that are inherited from http_protocol_config and http_processor_config, respectively: For example:

        let new_cfg =
          new modify_http_reactor_config
            ~modify_http_protocol_config:
               (new Nethttpd_kernel.modify_http_protocol_config
                  ~config_suppress_broken_pipe:true)
            ~modify_http_processor_config:
               (new Nethttpd_reactor.modify_http_processor_config
                  ~config_timeout:15.0)
            old_cfg
      


ocamlnet-4.1.2/doc/html-main/Netchannels.lift_raw_out_channel-c.html0000644000175000017500000004301112731530353024135 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.lift_raw_out_channel

Class Netchannels.lift_raw_out_channel

class lift_raw_out_channel : raw_out_channel -> out_obj_channel
This class implements the methods from compl_out_channel by calling the methods of raw_out_channel. There is no additional buffering.

ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.receiver.html0000644000175000017500000004155312731530353022434 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.receiver src:Unix.file_descr ->
dst:#Uq_transfer.async_out_channel ->
?close_src:bool ->
?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.wrapped_datagram_socket.html0000644000175000017500000004415512731530353025307 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.wrapped_datagram_socket object
  method datagram_type : Uq_engines.datagram_type
  method descriptor : Unix.file_descr
  method recvfrom :
    Bytes.t -> int -> int -> Unix.msg_flag list -> int * Uq_engines.sockspec
  method sendto :
    Bytes.t -> int -> int -> Unix.msg_flag list -> Uq_engines.sockspec -> int
  method shut_down : unit -> unit
  method socket_domain : Unix.socket_domain
  method socket_protocol : int
  method socket_type : Unix.socket_type
end
ocamlnet-4.1.2/doc/html-main/type_Netasn1.html0000644000175000017500000013201012731530353017636 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netasn1 sig
  exception Out_of_range
  exception Parse_error of int
  exception Header_too_short
  module Type_name :
    sig
      type type_name =
          Bool
        | Integer
        | Enum
        | Real
        | Bitstring
        | Octetstring
        | Null
        | Seq
        | Set
        | OID
        | ROID
        | ObjectDescriptor
        | External
        | Embedded_PDV
        | NumericString
        | PrintableString
        | TeletexString
        | VideotexString
        | VisibleString
        | IA5String
        | GraphicString
        | GeneralString
        | UniversalString
        | BMPString
        | UTF8String
        | CharString
        | UTCTime
        | GeneralizedTime
    end
  module Value :
    sig
      type pc = Primitive | Constructed
      type value =
          Bool of bool
        | Integer of Netasn1.Value.int_value
        | Enum of Netasn1.Value.int_value
        | Real of Netasn1.Value.real_value
        | Bitstring of Netasn1.Value.bitstring_value
        | Octetstring of string
        | Null
        | Seq of Netasn1.Value.value list
        | Set of Netasn1.Value.value list
        | Tagptr of Netasn1.Value.tag_class * int * Netasn1.Value.pc *
            Netstring_tstring.tstring_polybox * int * int
        | Tag of Netasn1.Value.tag_class * int * Netasn1.Value.pc *
            Netasn1.Value.value
        | ITag of Netasn1.Value.tag_class * int * Netasn1.Value.value
        | OID of int array
        | ROID of int array
        | ObjectDescriptor of string
        | External of Netasn1.Value.value list
        | Embedded_PDV of Netasn1.Value.value list
        | NumericString of string
        | PrintableString of string
        | TeletexString of string
        | VideotexString of string
        | VisibleString of string
        | IA5String of string
        | GraphicString of string
        | GeneralString of string
        | UniversalString of string
        | BMPString of string
        | UTF8String of string
        | CharString of string
        | UTCTime of Netasn1.Value.time_value
        | GeneralizedTime of Netasn1.Value.time_value
      and tag_class = Universal | Application | Context | Private
      and int_value
      and real_value
      and bitstring_value
      and time_value
      type time_subtype = [ `G | `U ]
      val type_of_value :
        Netasn1.Value.value -> Netasn1.Type_name.type_name option
      val get_int_repr : Netasn1.Value.int_value -> string
      val get_int_b256 : Netasn1.Value.int_value -> int array
      val get_int : Netasn1.Value.int_value -> int
      val get_int32 : Netasn1.Value.int_value -> int32
      val get_int64 : Netasn1.Value.int_value -> int64
      val int : int -> Netasn1.Value.int_value
      val int32 : int32 -> Netasn1.Value.int_value
      val int64 : int64 -> Netasn1.Value.int_value
      val int_b256 : int array -> Netasn1.Value.int_value
      val get_real_repr : Netasn1.Value.real_value -> string
      val get_bitstring_size : Netasn1.Value.bitstring_value -> int
      val get_bitstring_data : Netasn1.Value.bitstring_value -> string
      val get_bitstring_bits :
        ?size:int -> Netasn1.Value.bitstring_value -> bool array
      val get_bitstring_repr : Netasn1.Value.bitstring_value -> string
      val bitstring_of_bits : bool array -> Netasn1.Value.bitstring_value
      val bitstring_of_string :
        string -> int -> Netasn1.Value.bitstring_value
      val truncate_trailing_zero_bits :
        Netasn1.Value.bitstring_value -> Netasn1.Value.bitstring_value
      val get_time_subtype :
        Netasn1.Value.time_value -> Netasn1.Value.time_subtype
      val get_time_repr : Netasn1.Value.time_value -> string
      val get_time : Netasn1.Value.time_value -> Netdate.t
      val utctime : Netdate.t -> Netasn1.Value.time_value
      val gentime : digits:int -> Netdate.t -> Netasn1.Value.time_value
      val equal : Netasn1.Value.value -> Netasn1.Value.value -> bool
    end
  val decode_ber :
    ?pos:int -> ?len:int -> string -> int * Netasn1.Value.value
  val decode_ber_tstring :
    ?pos:int -> ?len:int -> Netsys_types.tstring -> int * Netasn1.Value.value
  val decode_ber_poly :
    ?pos:int ->
    ?len:int ->
    'Netstring_tstring.tstring_ops -> '-> int * Netasn1.Value.value
  val decode_ber_contents :
    ?pos:int ->
    ?len:int ->
    ?indefinite:bool ->
    string ->
    Netasn1.Value.pc ->
    Netasn1.Type_name.type_name -> int * Netasn1.Value.value
  val decode_ber_contents_tstring :
    ?pos:int ->
    ?len:int ->
    ?indefinite:bool ->
    Netsys_types.tstring ->
    Netasn1.Value.pc ->
    Netasn1.Type_name.type_name -> int * Netasn1.Value.value
  val decode_ber_contents_poly :
    ?pos:int ->
    ?len:int ->
    ?indefinite:bool ->
    'Netstring_tstring.tstring_ops ->
    '->
    Netasn1.Value.pc ->
    Netasn1.Type_name.type_name -> int * Netasn1.Value.value
  val decode_ber_length : ?pos:int -> ?len:int -> string -> int
  val decode_ber_length_tstring :
    ?pos:int -> ?len:int -> Netsys_types.tstring -> int
  val decode_ber_length_poly :
    ?pos:int -> ?len:int -> 'Netstring_tstring.tstring_ops -> '-> int
  val decode_ber_header :
    ?pos:int ->
    ?len:int ->
    ?skip_length_check:bool ->
    string ->
    int * Netasn1.Value.tag_class * Netasn1.Value.pc * int * int option
  val decode_ber_header_tstring :
    ?pos:int ->
    ?len:int ->
    ?skip_length_check:bool ->
    Netsys_types.tstring ->
    int * Netasn1.Value.tag_class * Netasn1.Value.pc * int * int option
  val decode_ber_header_poly :
    ?pos:int ->
    ?len:int ->
    ?skip_length_check:bool ->
    'Netstring_tstring.tstring_ops ->
    '-> int * Netasn1.Value.tag_class * Netasn1.Value.pc * int * int option
  val streamline_seq :
    (Netasn1.Value.tag_class * int * Netasn1.Type_name.type_name) list ->
    Netasn1.Value.value list -> Netasn1.Value.value option list
  val streamline_set :
    (Netasn1.Value.tag_class * int * Netasn1.Type_name.type_name) list ->
    Netasn1.Value.value list -> Netasn1.Value.value list
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.put_call.html0000644000175000017500000004060512731530353023123 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.put_call Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.server_endpoint_acceptor.html0000644000175000017500000004226412731530353027065 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.server_endpoint_acceptor object
  method accept :
    unit ->
    (Unix.file_descr * Uq_engines_compat.inetspec option)
    Uq_engines_compat.engine
  method multiple_connections : bool
  method server_address : Uq_engines_compat.connect_address
  method shut_down : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netx509.html0000644000175000017500000012607512731530353017517 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509 sig
  type oid = Netoid.t
  class type directory_name =
    object
      method eq_name : (Netx509.oid * Netasn1.Value.value) list list
      method eq_string : string
      method name : (Netx509.oid * Netasn1.Value.value) list list
      method string : string
    end
  class type x509_certificate =
    object
      method extensions : (Netx509.oid * string * bool) list
      method issuer : Netx509.directory_name
      method issuer_unique_id : Netasn1.Value.bitstring_value option
      method public_key : Netasn1.Value.bitstring_value
      method public_key_algorithm : Netx509.oid * Netasn1.Value.value option
      method serial_number : string
      method signature : Netasn1.Value.bitstring_value
      method signature_algorithm : Netx509.oid * Netasn1.Value.value option
      method subject : Netx509.directory_name
      method subject_unique_id : Netasn1.Value.bitstring_value option
      method valid_not_after : float
      method valid_not_before : float
      method version : int
    end
  module DN_attributes :
    sig
      val at_name : Netx509.oid
      val at_surname : Netx509.oid
      val at_givenName : Netx509.oid
      val at_initials : Netx509.oid
      val at_generationQualifier : Netx509.oid
      val at_commonName : Netx509.oid
      val at_localityName : Netx509.oid
      val at_stateOrProvinceName : Netx509.oid
      val at_organizationName : Netx509.oid
      val at_organizationalUnitName : Netx509.oid
      val at_title : Netx509.oid
      val at_dnQualifier : Netx509.oid
      val at_countryName : Netx509.oid
      val at_serialNumber : Netx509.oid
      val at_pseudonym : Netx509.oid
      val at_domainComponent : Netx509.oid
      val at_emailAddress : Netx509.oid
      val at_uid : Netx509.oid
      val attribute_types : (Netx509.oid * string * string list) list
      val lookup_attribute_type_by_oid : Netx509.oid -> string * string list
      val lookup_attribute_type_by_name :
        string -> Netx509.oid * string * string list
    end
  module X509_DN_string : Netdn.DN_string
  val lookup_dn_ava :
    Netx509.directory_name -> Netx509.oid -> Netasn1.Value.value
  val lookup_dn_ava_utf8 : Netx509.directory_name -> Netx509.oid -> string
  class x509_dn_from_ASN1 : Netasn1.Value.value -> directory_name
  class x509_dn_from_string : string -> directory_name
  class x509_certificate_from_ASN1 : Netasn1.Value.value -> x509_certificate
  class x509_certificate_from_DER : string -> x509_certificate
  module CE :
    sig
      val ce_authority_key_identifier : Netx509.oid
      val ce_subject_key_identifier : Netx509.oid
      val ce_key_usage : Netx509.oid
      val ce_certificate_policies : Netx509.oid
      val ce_any_policy : Netx509.oid
      val ce_policy_mappings : Netx509.oid
      val ce_subject_alt_name : Netx509.oid
      val ce_issuer_alt_name : Netx509.oid
      val ce_subject_directory_attributes : Netx509.oid
      val ce_basic_constraints : Netx509.oid
      val ce_name_constraints : Netx509.oid
      val ce_policy_constraints : Netx509.oid
      val ce_ext_key_usage : Netx509.oid
      val ce_crl_distribution_points : Netx509.oid
      val ce_inhibit_any_policy : Netx509.oid
      val ce_freshest_crl : Netx509.oid
      val ce_authority_info_access : Netx509.oid
      val ce_subject_info_access : Netx509.oid
      val certificate_extensions : (Netx509.oid * string) list
    end
  exception Extension_not_found of Netx509.oid
  val find_extension :
    Netx509.oid -> (Netx509.oid * string * bool) list -> string * bool
  val check_critical_exts :
    Netx509.oid list -> (Netx509.oid * string * bool) list -> bool
  type general_name =
      [ `DNS_name of string
      | `Directory_name of Netx509.directory_name
      | `Edi_party_name of string option * string
      | `IP_address of Unix.socket_domain * Unix.inet_addr * Unix.inet_addr
      | `Other_name of Netx509.oid * Netasn1.Value.value
      | `Registered_ID of Netx509.oid
      | `Rfc822_name of string
      | `Uniform_resource_identifier of string
      | `X400_address of Netasn1.Value.value ]
  type authority_key_identifier = {
    aki_key_identifier : string option;
    aki_authority_cert_issuer : Netx509.general_name list;
    aki_authority_cert_serial_number : string option;
  }
  val parse_authority_key_identifier :
    string -> Netx509.authority_key_identifier
  val parse_subject_key_identifier : string -> string
  type key_usage_flag =
      [ `Crl_sign
      | `Data_encipherment
      | `Decipher_only
      | `Digital_signature
      | `Encipher_only
      | `Key_agreement
      | `Key_cert_sign
      | `Key_encipherment
      | `Non_repudiation ]
  val parse_key_usage : string -> Netx509.key_usage_flag list
  val parse_subject_alt_name : string -> Netx509.general_name list
  val parse_issuer_alt_name : string -> Netx509.general_name list
  val parse_subject_directory_attributes :
    string -> (Netx509.oid * Netasn1.Value.value list) list
  val parse_basic_constraints : string -> bool * int option
  type ext_key_usage_flag =
      [ `Client_auth
      | `Code_signing
      | `Email_protection
      | `OCSP_signing
      | `Server_auth
      | `Time_stamping
      | `Unknown ]
  val parse_ext_key_usage :
    string -> (Netx509.oid * Netx509.ext_key_usage_flag) list
  module KP :
    sig
      val kp_server_auth : Netx509.oid
      val kp_client_auth : Netx509.oid
      val kp_code_signing : Netx509.oid
      val kp_email_protection : Netx509.oid
      val kp_time_stamping : Netx509.oid
      val kp_ocsp_signing : Netx509.oid
      val ext_key_purposes :
        (Netx509.oid * Netx509.ext_key_usage_flag * string) list
    end
  type authority_access_description_flag = [ `CA_issuers | `OCSP | `Unknown ]
  type subject_access_description_flag =
      [ `CA_repository | `Time_stamping | `Unknown ]
  type access_description_flag =
      [ `CA_issuers | `CA_repository | `OCSP | `Time_stamping | `Unknown ]
  val parse_authority_info_access :
    string ->
    (Netx509.oid * Netx509.authority_access_description_flag *
     Netx509.general_name)
    list
  val parse_subject_info_access :
    string ->
    (Netx509.oid * Netx509.subject_access_description_flag *
     Netx509.general_name)
    list
  module AD :
    sig
      val ad_ca_issuers : Netx509.oid
      val ad_ocsp : Netx509.oid
      val ad_ca_repository : Netx509.oid
      val ad_time_stamping : Netx509.oid
      val access_descriptions :
        (Netx509.oid * Netx509.access_description_flag * string) list
    end
  val general_name_from_ASN1 : Netasn1.Value.value -> Netx509.general_name
  val general_names_from_ASN1 :
    Netasn1.Value.value -> Netx509.general_name list
  val directory_string_from_ASN1 : Netasn1.Value.value -> string
  val attribute_from_ASN1 :
    Netasn1.Value.value -> Netx509.oid * Netasn1.Value.value list
  val attributes_from_ASN1 :
    Netasn1.Value.value -> (Netx509.oid * Netasn1.Value.value list) list
end
ocamlnet-4.1.2/doc/html-main/type_Netmcore_condition.Debug.html0000644000175000017500000004101312731530353023176 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_condition.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Uq_transfer.pseudo_async_out_channel-c.html0000644000175000017500000004257412731530353025066 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.pseudo_async_out_channel

Class Uq_transfer.pseudo_async_out_channel

class pseudo_async_out_channel : #Netchannels.raw_out_channel -> async_out_channel
Takes a Netchannels.raw_out_channel as an asynchronous channel. It is always possible to output to this channel.

ocamlnet-4.1.2/doc/html-main/type_Netplex_mutex.html0000644000175000017500000004213712731530353021200 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mutex sig
  val plugin : Netplex_types.plugin
  type mutex
  val access : string -> Netplex_mutex.mutex
  val lock : Netplex_mutex.mutex -> unit
  val unlock : Netplex_mutex.mutex -> unit
end
ocamlnet-4.1.2/doc/html-main/Netsys_pmanage.html0000644000175000017500000004521512731530353020253 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pmanage

Module Netsys_pmanage

module Netsys_pmanage: sig .. end
Manage persistent objects


This module allows you to keep a list of all objects with kernel persistency in an external file.
type pm_obj = [ `File of string
| `Posix_sem of string
| `Posix_shm of string
| `Sem_cont of string ]
class type pmanage = object .. end
val pmanage : string -> pmanage
Create a new manager for persistent kernel objects. The data is stored in a text file whose path is passed to this function. If the file already exists, it is opened and used. If the file does not exist yet, an empty manager will be created.

This function can be safely used from several threads and several processes.

val fake_pmanage : unit -> pmanage
A pseudo manager that does not save anything to a text file
val unlink_this : pm_obj -> unit
Unlinks this object
ocamlnet-4.1.2/doc/html-main/Nethttpd_engine.http_engine_config-c.html0000644000175000017500000004646612731530353024476 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_engine_config

Class type Nethttpd_engine.http_engine_config

class type http_engine_config = object .. end
Inherits
method config_input_flow_control : bool
If true, the engine stops reading input tokens from the HTTP kernel when there is data in the input channel of the engine not yet read. If false, all available input tokens are fetched from the kernel and buffered up in the input channel.

In general, this should be set to true. However, this is only possible when the user of the engine is prepared for flow control. In particular, all data contained in the input channel must be immediately read, or else the engine blocks. By calling input_ch_async # request_notification, the user can be notified when there is data to read.

When set to false, the engine never blocks, but the price is that the input channel may become as large as needed to store the whole request.

The option config_limit_pipeline_size does not have any effect for engines.

method config_output_flow_control : bool
If true, the engine signals the user when there is already enough data to output, and no more output should be generated. The user can query this state by calling output_ch_async # can_output, and react accordingly. The user can also ignore this signal, and the output channel buffers all data.

If false, the mentioned method can_output returns always true. This turns off flow control in the case it is implemented by the user of the engine, but actually not wanted.

The internal processing of data is not affected by this configuration option. In doubt, set it to true.

ocamlnet-4.1.2/doc/html-main/Netmech_krb5_sasl.Krb5_gs2_profile.html0000644000175000017500000005552712731530353023732 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_krb5_sasl.Krb5_gs2_profile

Module Netmech_krb5_sasl.Krb5_gs2_profile

module Krb5_gs2_profile: Netmech_gs2_sasl.PROFILE 
This is the profile used for Netmech_krb5_sasl.Krb5_gs2

val mechanism_name : string
The GS2 version of the mechanism name (w/o "-PLUS" suffix)
val announce_channel_binding : bool
Whether to announce the availability of channel binding by adding "-PLUS" to the mechanism name, and by offering channel bindings in the initial token.
val mechanism_oid : Netsys_gssapi.oid
The OID of the mechanism to use
val client_additional_params : string list
Additional parameters understood by create_client_session
val server_additional_params : string list
Additional parameters understood by create_server_session
val client_map_user_name : params:(string * string) list -> string -> string * Netsys_gssapi.oid
For clients: maps user names to a pair (name_string,name_type) that can be used in the GSSAPI for acquiring a name. If the name_type is the empty array, no target name is passed to the GSSAPI.

The params are from the create_client_session call.

val server_map_user_name : params:(string * string) list -> string * Netsys_gssapi.oid -> string
For servers: maps a pair (name_string,name_type) coming from the GSSAPI to a user name. The params are from the create_server_session call.

The function may raise Not_found in which case the authentication will fail.

val client_get_target_name : params:(string * string) list -> string * Netsys_gssapi.oid
For clients: get the GSSAPI name of the target to contact as (name_string,name_type) pair. If the name_type is the empty array, no target name is passed to the GSSAPI.

The params are from the create_client_session call.

val server_bind_target_name : params:(string * string) list -> (string * Netsys_gssapi.oid) option
For servers: optionally bind the GSSAPI name of the server. The params are from the create_server_session call.
val server_check_target_name : params:(string * string) list -> string * Netsys_gssapi.oid -> bool
For servers: check whether the GSSAPI name the client sent is the right one. This is a more flexible alternative to server_bind_target_name: instead of binding to a single name, the client may send any target name, and we check now whether this name is acceptable. params are from the create_server_session call.
val client_flags : params:(string * string) list -> (Netsys_gssapi.req_flag * bool) list
Flags for init_sec_context. The bool says whether the flag is required (otherwise the feature is only offered). `Mutual_flag is always required.
val server_flags : params:(string * string) list -> Netsys_gssapi.req_flag list
Required flags for accept_sec_context. `Mutual_flag is always required.
val client_credential : exn option
If set, the client will use a certain credential (and not acquire one). This is intended for passing in delegated credentials (well, not really elegant). This needs to be set to the Credential exception of the GSSAPI provider.
ocamlnet-4.1.2/doc/html-main/type_Netplex_kit.protocol_switch_factory.html0000644000175000017500000004113712731530353025574 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.protocol_switch_factory string ->
(string * Netplex_types.processor_factory) list ->
Netplex_types.processor_factory
ocamlnet-4.1.2/doc/html-main/type_Netcgi_fcgi.html0000644000175000017500000006500612731530353020540 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_fcgi sig
  class type cgi =
    object
      method argument : string -> Netcgi.cgi_argument
      method argument_exists : string -> bool
      method argument_value : ?default:string -> string -> string
      method arguments : Netcgi.cgi_argument list
      method at_exit : (unit -> unit) -> unit
      method data : Netchannels.in_obj_channel
      method data_length : int
      method data_mtime : float
      method environment : Netcgi.cgi_environment
      method finalize : unit -> unit
      method multiple_argument : string -> Netcgi.cgi_argument list
      method out_channel : Netchannels.trans_out_obj_channel
      method output : Netchannels.trans_out_obj_channel
      method request_method :
        [ `DELETE | `GET | `HEAD | `POST | `PUT of Netcgi.cgi_argument ]
      method role : [ `Authorizer | `Filter | `Responder ]
      method set_header :
        ?status:Nethttp.http_status ->
        ?content_type:string ->
        ?content_length:int ->
        ?set_cookie:Nethttp.cookie list ->
        ?set_cookies:Netcgi.Cookie.t list ->
        ?cache:Netcgi.cache_control ->
        ?filename:string ->
        ?language:string ->
        ?script_type:string ->
        ?style_type:string ->
        ?fields:(string * string list) list -> unit -> unit
      method set_redirection_header :
        ?set_cookies:Netcgi.Cookie.t list ->
        ?fields:(string * string list) list -> string -> unit
      method url :
        ?protocol:Nethttp.protocol ->
        ?with_authority:Netcgi.other_url_spec ->
        ?with_script_name:Netcgi.other_url_spec ->
        ?with_path_info:Netcgi.other_url_spec ->
        ?with_query_string:Netcgi.query_string_spec -> unit -> string
    end
  val run :
    ?config:Netcgi.config ->
    ?allow:(Unix.sockaddr -> bool) ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?exn_handler:Netcgi.exn_handler ->
    ?socket:Unix.file_descr ->
    ?sockaddr:Unix.sockaddr -> ?port:int -> (Netcgi_fcgi.cgi -> unit) -> unit
  val handle_request :
    Netcgi.config ->
    Netcgi.output_type ->
    Netcgi.arg_store ->
    Netcgi.exn_handler ->
    (Netcgi_fcgi.cgi -> unit) ->
    max_conns:int ->
    log:(string -> unit) option ->
    Unix.file_descr -> Netcgi.connection_directive
  val handle_connection :
    Netcgi.config ->
    Netcgi.output_type ->
    Netcgi.arg_store ->
    Netcgi.exn_handler ->
    (Netcgi_fcgi.cgi -> unit) ->
    max_conns:int -> one_shot:bool -> Unix.file_descr -> unit
end
ocamlnet-4.1.2/doc/html-main/Netfs.html0000644000175000017500000013500012731530353016345 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netfs

Module Netfs

module Netfs: sig .. end
Class type stream_fs for filesystems with stream access to files


The class type Netfs.stream_fs is an abstraction for both kernel-level and user-level filesystems. It is used as parameter for algorithms (like globbing) that operate on filesystems but do not want to assume any particular filesystem. Only stream access is provided (no seek).

File paths:

The filesystem supports hierarchical file names. File paths use Unix conventions, i.e.

  • / is the root
  • Path components are separated by slashes. Several consecutive slashes are allowed but mean the same as a single slash.
  • . is the same directory
  • .. is the parent directory
All paths need to be absolute (i.e. start with /).

There can be additional constraints on paths:

  • Character encoding restriction: A certain ASCII-compatible character encoding is assumed (including UTF-8)
  • Character exclusion: Certain characters may be excluded
Implementations may impose more constraints that cannot be expressed here (case insensitivity, path length, exclusion of special names etc.).

Virtuality:

There is no assumption that / is the real root of the local filesystem. It can actually be anywhere - a local subdirectory, or a remote directory, or a fictive root. There needs not to be any protection against "running beyond root", e.g. with the path /...

This class type also supports remote filesystems, and thus there is no concept of file handle (because this would exclude a number of implementations).

Errors:

Errors should generally be indicated by raising Unix_error. For many error codes the interpretation is already given by POSIX. Here are some more special cases:

  • EINVAL: should also be used for invalid paths, or when a flag cannot be supported (and it is non-ignorable)
  • ENOSYS: should also be used if an operation is generally unavailable
In case of hard errors (like socket errors when communicating with the remote server) there is no need to stick to Unix_error, though.

Subtyping:

The class type Netfs.stream_fs is subtypable, and subtypes can add more features by:

  • adding more methods
  • adding more flags to existing methods
Omitted:

Real filesystems usually provide a lot more features than what is represented here, such as:

  • Access control and file permissions
  • Metadata like timestamps
  • Random access to files
This definition here is intentionally minimalistic. In the future this class type will be extended, and more more common filesystem features will be covered. See Netfs.empty_fs for a way how to ensure that your definition of a stream_fs can still be built after stream_fs has been extended.

The class type Netfs.stream_fs is an abstraction for both kernel-level and user-level filesystems. It is used as parameter for algorithms (like globbing) that operate on filesystems but do not want to assume any particular filesystem. Only stream access is provided (no seek).

File paths:

The filesystem supports hierarchical file names. File paths use Unix conventions, i.e.

  • / is the root
  • Path components are separated by slashes. Several consecutive slashes are allowed but mean the same as a single slash.
  • . is the same directory
  • .. is the parent directory
All paths need to be absolute (i.e. start with /).

There can be additional constraints on paths:

  • Character encoding restriction: A certain ASCII-compatible character encoding is assumed (including UTF-8)
  • Character exclusion: Certain characters may be excluded
Implementations may impose more constraints that cannot be expressed here (case insensitivity, path length, exclusion of special names etc.).

Virtuality:

There is no assumption that / is the real root of the local filesystem. It can actually be anywhere - a local subdirectory, or a remote directory, or a fictive root. There needs not to be any protection against "running beyond root", e.g. with the path /...

This class type also supports remote filesystems, and thus there is no concept of file handle (because this would exclude a number of implementations).

Errors:

Errors should generally be indicated by raising Unix_error. For many error codes the interpretation is already given by POSIX. Here are some more special cases:

  • EINVAL: should also be used for invalid paths, or when a flag cannot be supported (and it is non-ignorable)
  • ENOSYS: should also be used if an operation is generally unavailable
In case of hard errors (like socket errors when communicating with the remote server) there is no need to stick to Unix_error, though.

Subtyping:

The class type Netfs.stream_fs is subtypable, and subtypes can add more features by:

  • adding more methods
  • adding more flags to existing methods
Omitted:

Real filesystems usually provide a lot more features than what is represented here, such as:

  • Access control and file permissions
  • Metadata like timestamps
  • Random access to files
This definition here is intentionally minimalistic. In the future this class type will be extended, and more more common filesystem features will be covered. See Netfs.empty_fs for a way how to ensure that your definition of a stream_fs can still be built after stream_fs has been extended.

The class type stream_fs


type read_flag = [ `Binary | `Dummy | `Skip of int64 | `Streaming ] 
type read_file_flag = [ `Binary | `Dummy ] 
type write_flag = [ `Binary | `Create | `Dummy | `Exclusive | `Streaming | `Truncate ] 
type write_file_flag = [ `Binary | `Create | `Dummy | `Exclusive | `Link | `Truncate ] 
type write_common = [ `Binary | `Create | `Dummy | `Exclusive | `Truncate ] 
The intersection of write_flag and write_file_flag
type size_flag = [ `Dummy ] 
type test_flag = [ `Dummy | `Link ] 
type remove_flag = [ `Dummy | `Recursive ] 
type rename_flag = [ `Dummy ] 
type symlink_flag = [ `Dummy ] 
type readdir_flag = [ `Dummy ] 
type readlink_flag = [ `Dummy ] 
type mkdir_flag = [ `Dummy | `Nonexcl | `Path ] 
type rmdir_flag = [ `Dummy ] 
type copy_flag = [ `Dummy ] 

Note `Dummy: this flag is always ignored. There are two reasons for having it:
  • Ocaml does not allow empty variants
  • it is sometimes convenient to have it (e.g. in: if <condition> then `Create else `Dummy)

type test_type = [ `D | `E | `F | `H | `N | `R | `S | `W | `X ] 
Tests:
  • `N: the file name exists
  • `E: the file exists
  • `D: the file exists and is a directory
  • `F: the file exists and is regular
  • `H: the file exists and is a symlink (possibly to a non-existing target)
  • `R: the file exists and is readable
  • `W: the file exists and is writable
  • `X: the file exists and is executable
  • `S: the file exists and is non-empty

class type local_file = object .. end
class type stream_fs = object .. end
class empty_fs : string -> stream_fs
This is a class where all methods fail with ENOSYS.
val local_fs : ?encoding:Netconversion.encoding ->
?root:string -> ?enable_relative_paths:bool -> unit -> stream_fs
local_fs(): Returns a filesystem object for the local filesystem.

  • encoding: Specifies the character encoding of paths. The default is system-dependent.
  • root: the root of the returned object is the directory root of the local filesystem. If omitted, the root is the root of the local filesystem (i.e. / for Unix, and see comments for Windows below). Use root="." to make the current working directory the root. Note that "." like other relative paths are interpreted at the time when the access method is executed.
  • enable_relative_paths: Normally, only absolute paths can be passed to the access methods like read. By setting this option to true one can also enable relative paths. These are taken relative to the working directory, and not relative to root. Relative names are off by default because there is usually no counterpart in network filesystems.


OS Notes



OS Notes



Unix in general: There is no notion of character encoding of paths. Paths are just bytes. Because of this, the default encoding is None. If a different encoding is passed to local_fs, these bytes are just interpreted in this encoding. There is no conversion.

For desktop programs, though, usually the character encoding of the locale is taken for filenames. You can get this by passing

    let encoding = 
      Netconversion.user_encoding()
    

as encoding argument.

OS Notes



Unix in general: There is no notion of character encoding of paths. Paths are just bytes. Because of this, the default encoding is None. If a different encoding is passed to local_fs, these bytes are just interpreted in this encoding. There is no conversion.

For desktop programs, though, usually the character encoding of the locale is taken for filenames. You can get this by passing

    let encoding = 
      Netconversion.user_encoding()
    

as encoding argument.

Windows: If the root argument is not passed to local_fs it is possible to access the whole filesystem:

  • Paths starting with drive letters like c:/ are also considered as absolute
  • Additionally, paths starting with slashes like /c:/ mean the same
  • UNC paths starting with two slashes like //hostname are supported
However, when a root directory is passed, these additional notations are not possible anymore - paths must start with /, and there is neither support for drive letters nor for UNC paths.

The encoding arg defaults to current ANSI codepage, and it is not supported to request a different encoding. (The difficulty is that the Win32 bindings of the relevant OS functions always assume the ANSI encoding.)

There is no support for backslashes as path separators (such paths will be rejected), for better compatibility with other platforms.

OS Notes



Unix in general: There is no notion of character encoding of paths. Paths are just bytes. Because of this, the default encoding is None. If a different encoding is passed to local_fs, these bytes are just interpreted in this encoding. There is no conversion.

For desktop programs, though, usually the character encoding of the locale is taken for filenames. You can get this by passing

    let encoding = 
      Netconversion.user_encoding()
    

as encoding argument.

Windows: If the root argument is not passed to local_fs it is possible to access the whole filesystem:

  • Paths starting with drive letters like c:/ are also considered as absolute
  • Additionally, paths starting with slashes like /c:/ mean the same
  • UNC paths starting with two slashes like //hostname are supported
However, when a root directory is passed, these additional notations are not possible anymore - paths must start with /, and there is neither support for drive letters nor for UNC paths.

The encoding arg defaults to current ANSI codepage, and it is not supported to request a different encoding. (The difficulty is that the Win32 bindings of the relevant OS functions always assume the ANSI encoding.)

There is no support for backslashes as path separators (such paths will be rejected), for better compatibility with other platforms.



OS Notes



Unix in general: There is no notion of character encoding of paths. Paths are just bytes. Because of this, the default encoding is None. If a different encoding is passed to local_fs, these bytes are just interpreted in this encoding. There is no conversion.

For desktop programs, though, usually the character encoding of the locale is taken for filenames. You can get this by passing

    let encoding = 
      Netconversion.user_encoding()
    

as encoding argument.

Windows: If the root argument is not passed to local_fs it is possible to access the whole filesystem:

  • Paths starting with drive letters like c:/ are also considered as absolute
  • Additionally, paths starting with slashes like /c:/ mean the same
  • UNC paths starting with two slashes like //hostname are supported
However, when a root directory is passed, these additional notations are not possible anymore - paths must start with /, and there is neither support for drive letters nor for UNC paths.

The encoding arg defaults to current ANSI codepage, and it is not supported to request a different encoding. (The difficulty is that the Win32 bindings of the relevant OS functions always assume the ANSI encoding.)

There is no support for backslashes as path separators (such paths will be rejected), for better compatibility with other platforms.



List:

  • Nethttp_fs allows one to access HTTP-based filesystems
  • Netftp_fs allows on to access filesystems via FTP
  • Shell_fs allows one to access filesystems by executing shell commands. This works locally and via ssh.
There are even some implementations outside Ocamlnet:
  • Webdav provides an extension of Nethttp_fs for the full WebDAV set of filesystem operations


OS Notes



Unix in general: There is no notion of character encoding of paths. Paths are just bytes. Because of this, the default encoding is None. If a different encoding is passed to local_fs, these bytes are just interpreted in this encoding. There is no conversion.

For desktop programs, though, usually the character encoding of the locale is taken for filenames. You can get this by passing

    let encoding = 
      Netconversion.user_encoding()
    

as encoding argument.

Windows: If the root argument is not passed to local_fs it is possible to access the whole filesystem:

  • Paths starting with drive letters like c:/ are also considered as absolute
  • Additionally, paths starting with slashes like /c:/ mean the same
  • UNC paths starting with two slashes like //hostname are supported
However, when a root directory is passed, these additional notations are not possible anymore - paths must start with /, and there is neither support for drive letters nor for UNC paths.

The encoding arg defaults to current ANSI codepage, and it is not supported to request a different encoding. (The difficulty is that the Win32 bindings of the relevant OS functions always assume the ANSI encoding.)

There is no support for backslashes as path separators (such paths will be rejected), for better compatibility with other platforms.



List:

  • Nethttp_fs allows one to access HTTP-based filesystems
  • Netftp_fs allows on to access filesystems via FTP
  • Shell_fs allows one to access filesystems by executing shell commands. This works locally and via ssh.
There are even some implementations outside Ocamlnet:
  • Webdav provides an extension of Nethttp_fs for the full WebDAV set of filesystem operations


Algorithms


val copy : ?replace:bool ->
?streaming:bool ->
#stream_fs -> string -> #stream_fs -> string -> unit
copy orig_fs orig_name dest_fs dest_name: Copies the file orig_name from orig_fs to the file dest_name in dest_fs. By default, the destination file is truncated and overwritten if it already exists.

If orig_fs and dest_fs are the same object, the copy method is called to perform the operation. Otherwise, the data is read chunk by chunk from the file in orig_fs and then written to the destination file in dest_fs.

Symlinks are resolved, and the linked file is copied, not the link as such.

The copy does not preserve ownerships, file permissions, or timestamps. (The stream_fs object does not represent these.) There is no protection against copying an object to itself.

  • replace: If set, the destination file is removed and created again if it already exists
  • streaming: use streaming mode for reading and writing files

val copy_into : ?replace:bool ->
?subst:(int -> string) ->
?streaming:bool ->
#stream_fs -> string -> #stream_fs -> string -> unit
copy_into orig_fs orig_name dest_fs dest_name: Like copy, but this version also supports recursive copies. The dest_name must be an existing directory, and the file or tree at orig_name is copied into it.

Symlinks are copied as symlinks.

If replace and the destination file/directory already exists, it is deleted before doing the copy.

  • subst: See Netfs.convert_path
  • streaming: use streaming mode for reading and writing files

type file_kind = [ `Directory | `None | `Other | `Regular | `Symlink ] 
val iter : pre:(string -> file_kind -> file_kind -> unit) ->
?post:(string -> unit) -> #stream_fs -> string -> unit
iter pre fs start: Iterates over the file hierarchy at start. The function pre is called for every filename. The filenames passed to pre are relative to start. The start must be a directory.

For directories, the pre function is called for the directory before it is called for the members of the directories. The function post can additionally be passed. It is only called for directories, but after the members.

pre is called as pre rk lk where rk is the file kind after following symlinks and lk the file kind without following symlinks (the link itself).

Example: iter pre fs "/foo" would call

  • pre "dir" `Directory `Directory (meaning the directory "/foo/dir")
  • pre "dir/file1" `File `File
  • pre "dir/file2" `File `Symlink
  • post "dir"
Note: symlinks to non-existing files are reported as pre name `None `Symlink.
val convert_path : ?subst:(int -> string) ->
#stream_fs -> #stream_fs -> string -> string
convert_path oldfs newfs oldpath: The encoding of oldpath (which is assumed to reside in oldfs) is converted to the encoding of newfs and returned.

It is possible that the conversion is not possible, and the function subst is then called with the problematic code point as argument (in the encoding of oldfs). The default subst function just raises Netconversion.Cannot_represent.

If one of the filesystem objects does not specify an encoding, the file name is not converted, but simply returned as-is. This may result in errors when newfs has an encoding while oldfs does not have one because the file name might use byte representations that are illegal in newfs.

ocamlnet-4.1.2/doc/html-main/type_Rpc_client.USE_CLIENT.html0000644000175000017500000004451012731530353022107 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.USE_CLIENT sig
  type t
  val use : Rpc_client.USE_CLIENT.t -> Rpc_program.t -> unit
  val unbound_sync_call :
    Rpc_client.USE_CLIENT.t ->
    Rpc_program.t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
  val unbound_async_call :
    Rpc_client.USE_CLIENT.t ->
    Rpc_program.t ->
    string ->
    Netxdr.xdr_value -> ((unit -> Netxdr.xdr_value) -> unit) -> unit
  val xdr_ctx : Rpc_client.USE_CLIENT.t -> Netxdr.ctx
end
ocamlnet-4.1.2/doc/html-main/Netmime.wrap_mime_body-c.html0000644000175000017500000004232212731530353022104 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.wrap_mime_body

Class Netmime.wrap_mime_body

class wrap_mime_body : #mime_body -> mime_body
Wraps the inner body

ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi.mime_argument-c.html0000644000175000017500000004264412731530353024416 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi.mime_argument

Class Netcgi1_compat.Netcgi.mime_argument

class mime_argument : ?work_around_backslash_bug:bool -> string -> Netmime.mime_message -> Netcgi1_compat.Netcgi_types.cgi_argument

ocamlnet-4.1.2/doc/html-main/type_Netchannels_tut.html0000644000175000017500000004062012731530353021470 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_tut sig  endocamlnet-4.1.2/doc/html-main/type_Shell_sys.job_handler_engine_type.html0000644000175000017500000004312412731530353025135 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_sys.job_handler_engine_type object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method job : Shell_sys.job
  method job_instance : Shell_sys.job_instance
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : ('Uq_engines.engine -> bool) -> unit
  method state : 'Uq_engines.engine_state
end
ocamlnet-4.1.2/doc/html-main/Netnumber.BE.html0000644000175000017500000006425012731530353017522 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber.BE

Module Netnumber.BE

module BE: ENCDEC 
Encoders/decoders for big endian - network byte order


Encode/decode numbers as strings. These functions exist in two flavors:
val read_int4 : Bytes.t -> int -> Netnumber.int4
val read_int8 : Bytes.t -> int -> Netnumber.int8
val read_uint4 : Bytes.t -> int -> Netnumber.uint4
val read_uint8 : Bytes.t -> int -> Netnumber.uint8
read_<t> create integer values from the characters found at a certain position in the string. Raises Out_of_range if the position is bad
val read_int4_unsafe : Bytes.t -> int -> Netnumber.int4
val read_int8_unsafe : Bytes.t -> int -> Netnumber.int8
val read_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4
val read_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8
Same, but no index check
val read_string_int4 : string -> int -> Netnumber.int4
val read_string_int8 : string -> int -> Netnumber.int8
val read_string_uint4 : string -> int -> Netnumber.uint4
val read_string_uint8 : string -> int -> Netnumber.uint8
val read_string_int4_unsafe : string -> int -> Netnumber.int4
val read_string_int8_unsafe : string -> int -> Netnumber.int8
val read_string_uint4_unsafe : string -> int -> Netnumber.uint4
val read_string_uint8_unsafe : string -> int -> Netnumber.uint8
For immutable strings
val write_int4 : Bytes.t -> int -> Netnumber.int4 -> unit
val write_int8 : Bytes.t -> int -> Netnumber.int8 -> unit
val write_uint4 : Bytes.t -> int -> Netnumber.uint4 -> unit
val write_uint8 : Bytes.t -> int -> Netnumber.uint8 -> unit
write_<t> copies the characters corresponding to the integer values into the string at the given positions. Raises Out_of_range if the position is bad.
val write_int4_unsafe : Bytes.t -> int -> Netnumber.int4 -> unit
val write_int8_unsafe : Bytes.t -> int -> Netnumber.int8 -> unit
val write_uint4_unsafe : Bytes.t -> int -> Netnumber.uint4 -> unit
val write_uint8_unsafe : Bytes.t -> int -> Netnumber.uint8 -> unit
write_<t>_unsafe: Same, but no index check.
val int4_as_bytes : Netnumber.int4 -> Bytes.t
val int8_as_bytes : Netnumber.int8 -> Bytes.t
val uint4_as_bytes : Netnumber.uint4 -> Bytes.t
val uint8_as_bytes : Netnumber.uint8 -> Bytes.t
<t>_as_bytes: Returns the corresponding bytes for an integer value
val int4_as_string : Netnumber.int4 -> string
val int8_as_string : Netnumber.int8 -> string
val uint4_as_string : Netnumber.uint4 -> string
val uint8_as_string : Netnumber.uint8 -> string
<t>_as_string: Returns the corresponding string for an integer value
val write_fp4 : Bytes.t -> int -> Netnumber.fp4 -> unit
val write_fp8 : Bytes.t -> int -> Netnumber.fp8 -> unit
val fp4_as_string : Netnumber.fp4 -> string
val fp8_as_string : Netnumber.fp8 -> string
val fp4_as_bytes : Netnumber.fp4 -> Bytes.t
val fp8_as_bytes : Netnumber.fp8 -> Bytes.t
val read_fp4 : Bytes.t -> int -> Netnumber.fp4
val read_fp8 : Bytes.t -> int -> Netnumber.fp8
val read_string_fp4 : string -> int -> Netnumber.fp4
val read_string_fp8 : string -> int -> Netnumber.fp8
ocamlnet-4.1.2/doc/html-main/Netsys_crypto.html0000644000175000017500000004672212731530353020167 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto

Module Netsys_crypto

module Netsys_crypto: sig .. end
Cryptographic providers


Users should not call functions of the providers directly. Instead, use:
val current_tls : unit -> (module Netsys_crypto_types.TLS_PROVIDER)
Return the current TLS provider. Only available if such a provider is linked into the executable. Do this by calling the init function of the provider, e.g. Nettls_gnutls.init.
val current_tls_opt : unit -> (module Netsys_crypto_types.TLS_PROVIDER) option
Same as current_tls but it returns None if TLS is unavailable
val current_symmetric_crypto : unit -> (module Netsys_crypto_types.SYMMETRIC_CRYPTO)
Returns the current provider for symmetric cryptography. This provider is always available, but may be empty (not implementing any ciphers).
val current_pubkey_crypto : unit -> (module Netsys_crypto_types.PUBKEY_CRYPTO)
Returns the current provider for public key cryptography. This provider is always available, but may be empty (not implementing any ciphers).
val current_digests : unit -> (module Netsys_crypto_types.DIGESTS)
Returns the current provider for cryptographic digests. This provider is always available, but may be empty (not implementing any digest).
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_kernel.http_protocol.html0000644000175000017500000004701312731530353024366 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_protocol #Nethttpd_kernel.http_protocol_config ->
Unix.file_descr ->
object
  method abort : Nethttpd_kernel.fatal_error -> unit
  method config : Nethttpd_kernel.http_protocol_config
  method cycle : ?block:float -> unit -> unit
  method do_input : bool
  method do_output : bool
  method fd : Unix.file_descr
  method hooks : Nethttpd_kernel.http_protocol_hooks
  method input_timeout_class : [ `Next_message | `None | `Normal ]
  method need_linger : bool
  method peek_recv : unit -> Nethttpd_kernel.req_token
  method pipeline_len : int
  method receive : unit -> Nethttpd_kernel.req_token
  method recv_queue_byte_size : int
  method recv_queue_len : int
  method resp_queue_filled : bool
  method resp_queue_len : int
  method shutdown : unit -> unit
  method test_coverage : string list
  method timeout : unit -> unit
  method tls_session_props : Nettls_support.tls_session_props option
  method waiting_for_next_message : bool
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.enhanced_raw_in_channel.html0000644000175000017500000004273712731530353025402 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.enhanced_raw_in_channel object
  method close_in : unit -> unit
  method private enhanced_input :
    Bytes.t -> int -> int -> Netchannels.input_result
  method private enhanced_input_line : unit -> string
  method input : Bytes.t -> int -> int -> int
  method pos_in : int
end
ocamlnet-4.1.2/doc/html-main/Netplex_config.html0000644000175000017500000005010112731530353020230 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_config

Module Netplex_config

module Netplex_config: sig .. end
Read the configuration file

exception Config_error of string
val read_config_file : string -> Netplex_types.config_file
Reads a filename and returns the representation object
val repr_config_file : string -> Netplex_types.config_tree -> Netplex_types.config_file
repr_config_file name tree: converts the tree to a full config_file object. name is the filename reported by the object.
val read_netplex_config : Netplex_types.parallelization_type ->
Netplex_types.logger_factory list ->
Netplex_types.workload_manager_factory list ->
Netplex_types.processor_factory list ->
Netplex_types.config_file -> Netplex_types.netplex_config
Reads a Netplex configuration file:

 netplex {
      <settings>
    }
 

The configuration options are now documented in Netplex_admin.

More documentation: See Example - A Simple Web Server for a complete example of a config file. See Creating Sockets for explanations how to specify sockets in the config file.

val read_tls_config : ?verify:((module Netsys_crypto_types.TLS_ENDPOINT) -> bool -> bool -> bool) ->
Netplex_types.config_file ->
Netplex_types.address ->
(module Netsys_crypto_types.TLS_PROVIDER) option ->
(module Netsys_crypto_types.TLS_CONFIG) option
Reads the TLS section of a configuration file: At the passed location there must be tls section (or None is returned).

The TLS options are now documented in Configuring TLS.

ocamlnet-4.1.2/doc/html-main/Nethttpd_kernel.http_protocol_config-c.html0000644000175000017500000005072412731530353025075 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_protocol_config

Class type Nethttpd_kernel.http_protocol_config

class type http_protocol_config = object .. end
Configuration values for the HTTP kernel

method config_max_reqline_length : int
Maximum size of the request line. Longer lines are immediately replied with a "Request URI too long" response. Suggestion: 32768.
method config_max_header_length : int
Maximum size of the header, including the request line. Longer headers are treated as attack, and cause the fatal error `Message_too_long. Suggestion: 65536.
method config_max_trailer_length : int
Maximum size of the trailer
method config_limit_pipeline_length : int
Limits the length of the pipeline (= unreplied requests). A value of 0 disables pipelining. A value of n allows that another request is received although there are already n unreplied requests.
method config_limit_pipeline_size : int
Limits the size of the pipeline in bytes. If the buffered bytes in the input queue exceed this value, the receiver temporarily stops reading more data. The value 0 has the effect that even the read-ahead of data of the current request is disabled. The value (-1) disables the receiver completely (not recommended).
method config_announce_server : announcement
Whether to set the Server header:
  • `Ignore: The kernel does not touch the Server header.
  • `Ocamlnet: Announce this web server as "Ocamlnet/<version>"
  • `Ocamlnet_and s: Announce this web server as s and append the Ocamlnet string.
  • `As s: Announce this web server as s

method config_suppress_broken_pipe : bool
Whether to suppress `Broken_pipe errors. Instead `Broken_pipe_ignore is reported.
method config_tls : Netsys_crypto_types.tls_config option
If set, the server enables TLS with the arugment config
ocamlnet-4.1.2/doc/html-main/type_Authentication.html0000644000175000017500000004061712731530353021317 0ustar gerdgerd Ocamlnet 4 Reference Manual : Authentication sig  endocamlnet-4.1.2/doc/html-main/Netsys_oothr.mutex-c.html0000644000175000017500000004423512731530353021360 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr.mutex

Class type Netsys_oothr.mutex

class type mutex = object .. end

method lock : unit -> unit
In a multi-threaded program: Suspends the calling thread until the mutex is locked. In a single-threaded program: This is a no-op
method unlock : unit -> unit
In a multi-threaded program: Unlocks a mutex. In a single-threaded program: This is a no-op
method try_lock : unit -> bool
In a multi-threaded program: Tries to immediately lock the mutex, and returns whether the lock could be obtained. In a single-threaded program: returns true
method repr : exn
May be used internally be the implementation
ocamlnet-4.1.2/doc/html-main/type_Netsendmail_tut.html0000644000175000017500000004062012731530353021471 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsendmail_tut sig  endocamlnet-4.1.2/doc/html-main/Netsys_ciphers.cipher_ctx-c.html0000644000175000017500000005353712731530353022655 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_ciphers.cipher_ctx

Class type Netsys_ciphers.cipher_ctx

class type cipher_ctx = object .. end

method padding : padding
The padding scheme of the cipher
method block_constraint : int
The buffers used with encrypt/decrypt must have a length that is a multiple of this number. (In ECB mode this is the block size.)

This value doesn't take padding into account.

method supports_aead : bool
Whether this cipher integrates authentication
method set_iv : string -> unit
Sets the initialization vector (this must be done before starting the encryption or decryption).
method set_header : string -> unit
Sets the header to authenticate for AEAD (this must be done before starting the encryption or decryption).
method encrypt : last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int
let n_in, n_out = encrypt ~last inbuf outbuf: Encrypts the text in inbuf and writes the result to outbuf. The returned numbers indicate how much data was processed: the first n_in bytes of inbuf are encrypted, and the first n_out bytes of outbuf are filled with ciphertext.

This function can be called several times to encrypt a larger text. last should be set for the last call.

The sizes of inbuf and outbuf must be at least one block in order to produce non-zero (n_in,n_out). (For `CTS only: two blocks.)

method decrypt : last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int
let n_in, n_out = decrypt ~last inbuf outbuf: Decrypts the text in inbuf and writes the result to outbuf. The returned numbers indicate how much data was processed: the first n_in bytes of inbuf are decrypted, and the first n_out bytes of outbuf are filled with plaintext.

This function can be called several times to decrypt a larger text. last should be set for the last call.

The sizes of inbuf and outbuf must be at least one block in order to produce non-zero (n_in,n_out). (For `CTS only: two blocks.)

On error, the method fails.

method encrypt_bytes : Bytes.t -> Bytes.t
Encrypts this string as a whole
method encrypt_string : string -> string
Encrypts this string as a whole
method decrypt_bytes : Bytes.t -> Bytes.t
Decrypts this string as a whole
method decrypt_string : string -> string
Decrypts this string as a whole
method mac : unit -> string
Returns the MAC for AEAD ciphers. Can first be called after the encryption/decryption is complete. This function fails for non-AEAD ciphers.
ocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.SCRAM.html0000644000175000017500000011415012731530353021727 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM

Functor Netmech_scram_sasl.SCRAM

module SCRAM: 
Create a new SCRAM SASL mechanism for this profile.

SCRAM is the most recent challenge/response mechanism specified by IETF, and should be preferred over others. See Netmech_scram for details.

Notes about init_credentials:

When used in servers, the credentials can be specified in the special "authPassword-SCRAM-SHA-1" format, e.g.

      let h = SHA1.hash_function
      let salt = Netmech_scram.create_salt()
      let i = 4096
      let (st_key,srv_key) = Netmech_scram.stored_key h password salt i
      let value =
        Netencoding.Base64.encode st_key ^ ":" ^ 
          Netencoding.Base64.encode srv_key in
      let creds_l =
        [ "authpassword-SCRAM-SHA-1", value,
           [ "info", sprintf "%d:%s" i (Netencoding.Base64.encode salt) ]
        ]
      let creds = SCRAM.init_credentials creds_l
      

If existing, the "authPassword-*" entry takes precedence over a normal "password" entry. The parameter "info" is needed. This format is intended to be stored in authentication databases instead of the cleartext password (compare with RFC-5803; this is intentionally derived from the usual LDAP format for SCRAM credentials).

Notes about create_server_session:

The implementation understands the parameter "i", which can be set to the iteration count. If omitted, an implementation-defined default is used.

Parameters

  • The parameters mutual and secure are understood but ignored (there is mutual authentication anyway, and SCRAM is considered as secure method)

Parameters:
P : PROFILE

val mechanism_name : string
val client_first : [ `No | `Optional | `Required ]
Whether the client sends the first message:
  • `Required: always
  • `Optional: the client may choose to do so if the protocol permits this
  • `No: the server sends the first message

val server_sends_final_data : bool
Whether final data from the server must be interpreted by the mechanism
val supports_authz : bool
whether the authorization name can be transmitted
val available : unit -> bool
Whether the mechanism is available, in particular whether the required crypto support is linked in
type credentials 
val init_credentials : (string * string * (string * string) list) list ->
credentials
Supply the mechanism with credentials. These are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

            [ "password", "ThE sEcReT", [] ]
          

Another common type is derived from the LDAP authPassword scheme (RFC 3112):

             [ "authPassword-" ^ scheme, authValue, [ "info", authInfo ] ]
          

The "info" attribute is optional. For instance, if you want to provide MD5-hashed passwords:

             [ "authPassword-MD5", hashed_password, [ "info", salt ] ]

          

Another common type is derived from the (older) LDAP userPassword scheme (RFC 2307):

            [ "userPassword-" ^ scheme, value, [] ]
         

More information can be found here: Credentials for SASL

type server_session 
val server_state : server_session ->
Netsys_sasl_types.server_state
val create_server_session : lookup:(string ->
string -> credentials option) ->
params:(string * string * bool) list ->
unit -> server_session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val server_configure_channel_binding : server_session ->
(string * string) list -> server_session
Configures acceptable channel bindings wiht a list of pairs (type,data).
val server_process_response : server_session ->
string -> server_session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val server_process_response_restart : server_session ->
string -> bool -> server_session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after server_process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as server_process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the server_session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

  let update_cache() =
    match server_session_id session with
      | None -> ()
      | Some id ->
          replace_in_session_cache id (server_stash_session session) in

  let rec check_state_after_response() =
    match server_state session with
      | `Restart id ->
           let old_session_s, time = find_in_session_cache id in
           let old_session = server_resume_session ~lookup old_session_s in
           let set_stale = current_time - time > limit in
           let session, cont =
             server_process_response_restart session msg set_stale in
           if not cont then 
             delete_in_session_cache id;
           (* Now check server_state again, should be `Emit now *)
           check_state_after_response()
      | `Emit ->
           let session, out_msg = server_emit_challenge session in
           update_cache();
           ...
      | ... ->
  in
  server_process_response session msg;

          

val server_emit_challenge : server_session ->
server_session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val server_stash_session : server_session -> string
Serializes the session as string
val server_resume_session : lookup:(string ->
string -> credentials option) ->
string -> server_session
Unserializes the session, and connect with the lookup function.
val server_session_id : server_session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val server_prop : server_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val server_user_name : server_session -> string
The name the client has authenticated as (or Not_found)
val server_authz_name : server_session -> string
The name the client authorizes as (or Not_found)
val server_channel_binding : server_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val server_gssapi_props : server_session -> Netsys_gssapi.server_props
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
type client_session 
val client_state : client_session ->
Netsys_sasl_types.client_state
val create_client_session : user:string ->
authz:string ->
creds:credentials ->
params:(string * string * bool) list ->
unit -> client_session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val client_configure_channel_binding : client_session ->
Netsys_sasl_types.cb -> client_session
Configure GS2-style channel binding
val client_restart : client_session ->
client_session
Restart the session for another authentication round. The session must be in state `OK.
val client_process_challenge : client_session ->
string -> client_session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val client_emit_response : client_session ->
client_session * string
Emit a new response. The state must be `Emit.
val client_channel_binding : client_session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_stash_session : client_session -> string
Serializes the session as string
val client_resume_session : string -> client_session
Unserializes the session
val client_session_id : client_session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val client_prop : client_session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val client_gssapi_props : client_session -> Netsys_gssapi.client_props
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
ocamlnet-4.1.2/doc/html-main/Nettls_support.html0000644000175000017500000005114512731530353020342 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_support

Module Nettls_support

module Nettls_support: sig .. end
Support types and functions for TLS

type credentials = [ `Anonymous | `X509 of Netx509.x509_certificate ] 
The types of credentials
type raw_credentials = [ `Anonymous | `X509 of string ] 
The encoded credentials:
  • `X509 s: The X509 certificate in DER encoding
  • `Anonymous: no certificate or other key is available

type cred_type = [ `Anonymous | `X509 ] 
The type of credential types
class type tls_session_props = object .. end
Direct access to TLS properties of a session
val get_tls_session_props : Netsys_crypto_types.tls_endpoint -> tls_session_props
Get the session properties for an endpoint for which the handshake is already done
val get_tls_user_name : tls_session_props -> string
Get the "user name" of client certificates. It is determined as follows:

  • if there is a subjectAltName with an email address (i.e. rfc822 type), this address is returned
  • if there is a subjectAltName using the directory name format, it is checked whether there is a "uid", "email", or "cn" name component
  • otherwise, it is checked whether there is a "uid", "email", or "cn" name component in the subject
Raises Not_found if nothing approriate is found.
val squash_file_tls_endpoint : (module Netsys_crypto_types.FILE_TLS_ENDPOINT) ->
(module Netsys_crypto_types.TLS_ENDPOINT)
Coerce a file endpoint to a normal endpoint
val is_endpoint_host : string -> tls_session_props -> bool
is_endpoint_host name props: checks whether name matches the certificate of the endpoint in props.

In particular, this function checks the DNS alternate name, and the common name of the subject. The certificate name can use wildcards.

Returns true if name could be verified this way.

NB. This doesn't check SNI (addressed_server), because this is the peer's task.

ocamlnet-4.1.2/doc/html-main/Netsys_oothr.thread-c.html0000644000175000017500000004344412731530353021466 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr.thread

Class type Netsys_oothr.thread

class type thread = object .. end

method id : int
In a multi-threaded program: Returns the thread ID. In a single-threaded program: Returns 0.
method join : unit -> unit
In a multi-threaded program: Suspends the calling thread until this thread terminates. In a single-threaded program: fails
method repr : exn
May be used internally be the implementation
ocamlnet-4.1.2/doc/html-main/type_Netldap.ldap_server.html0000644000175000017500000004211412731530353022226 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netldap.ldap_server object
  method ldap_endpoint : Netsockaddr.socksymbol
  method ldap_peer_name : string option
  method ldap_timeout : float
  method ldap_tls_config : (module Netsys_crypto_types.TLS_CONFIG) option
  method ldap_tls_mode : Netldap.tls_mode
end
ocamlnet-4.1.2/doc/html-main/Netx509_pubkey.html0000644000175000017500000007124112731530353020027 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey

Module Netx509_pubkey

module Netx509_pubkey: sig .. end
X.509 public key cryptography - keys and naming


Support for reading in public keys and retrieving the type of the key. This module is mostly about naming key types and algorithms.

In the X.509 standard a public key is often part of a certificate and there stored in the subjectPublicKeyInfo field. However, "raw" public keys (i.e. outside certificates) are also known. In this case, the same representation as for subjectPublicKeyInfo field is chosen and just stored separately in a file.

Like certificates, public keys are described by an ASN.1 syntax and are normally stored by applying the DER encoding rules. If stored in files, PEM headers for the DER encoding are common. Such files have a PEM header of "BEGIN PUBLIC KEY". Note that the header - unlike for private keys - does not indicate the type of key. The type is already a member of the subjectPublicKeyInfo field.

A public key consists of three parts:

  • the OID of the type of the key
  • the parameters of the algorithm
  • the key data
A certain type of public key can only be used with certain algorithms. Often, the OID for the type of the key is simply set to the OID for the simplest algorithm that can be used with the key. For example, RSA keys have the OID of the PKCS-1 encryption algorithm. However, you can use the same keys also with the slightly more complicated PKCS-1 signing algorithms.

It depends on the algorithm whether the parameters can be changed while keeping the key data.

See Netx509_pubkey_crypto for functions that actually encrypt or sign data with the current crypto provider.

type oid = Netoid.t 
OIDs are just integer sequences
type alg_id = 
| Alg_id of oid * Netasn1.Value.value option (*
Algorithms are identified by an OID and OID-specific parameters.
*)
type pubkey = {
   pubkey_type : alg_id;
   pubkey_data : Netasn1.Value.bitstring_value;
}
Public key info: the key as such plus the algorithm. This combination is stored in PEM files tagged with "PUBLIC KEY", and also part of X.509 certificates.
type hash_function = [ `SHA_1 | `SHA_224 | `SHA_256 | `SHA_384 | `SHA_512 ] 
type maskgen_function = [ `MGF1 of hash_function ] 
type alg_param = 
| P_PSS of hash_function * maskgen_function * int
| P_OAEP of hash_function * maskgen_function * string
type encrypt_alg = 
| Encrypt of oid * alg_param option (*
An algorithm that can be used for encryption. Same format as Alg_id
*)
type sign_alg = 
| Sign of oid * alg_param option (*
An algorithm that can be used for signing. Same format as Alg_id
*)
type kex_alg = 
| Kex of oid * alg_param option (*
An algorithm that can be used for key agreement. Same format as Alg_id

Remember that you can use any key agreement protocol also as public key mechanism: if Alice sends Bob message A based on a secret a, and Bob replies with message B based on a secret b, and both agree on a key K=f(a,b), you can consider A as the public key and Alices's secret a as the private key. The message B is a parameter of the ciphertext (comparable to the IV in symmetric cryptography), and K is used as transport key (for a symmetric cipher). That's why the key agreement algorithms appear here.

*)
val decode_pubkey_from_der : string -> pubkey
Decodes a DER-encoded public key info structure. Note that this function performs only a partial check on the integrity of the data.
val encode_pubkey_to_der : pubkey -> string
Encodes a public key info structure as DER
val read_pubkey_from_pem : Netchannels.in_obj_channel -> pubkey
Reads a PEM file tagged as "PUBLIC KEY". Note that this function performs only a partial check on the integrity of the data.
type privkey = 
| Privkey of string * string (*
(format,data), using the formats: "RSA", "DSA", "DH", "EC". The data string is for the mentioned formats DER-encoded.
*)
val read_privkey_from_pem : Netchannels.in_obj_channel -> privkey
Reads a PEM file tagged as "... PRIVATE KEY". This function cannot handle encrypted private keys. Note that this function performs only a partial check on the integrity of the data.
module Key: sig .. end
module Encryption: sig .. end
module Keyagreement: sig .. end
module Signing: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netftp_data_endpoint.html0000644000175000017500000010451112731530353022463 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint sig
  type ftp_data_prot = [ `C | `E | `P | `S ]
  type ftp_protector = {
    ftp_wrap_limit : unit -> int;
    ftp_wrap_s : string -> string;
    ftp_wrap_m : Netsys_types.memory -> Netsys_types.memory -> int;
    ftp_unwrap_s : string -> string;
    ftp_unwrap_m : Netsys_types.memory -> Netsys_types.memory -> int;
    ftp_prot_level : Netftp_data_endpoint.ftp_data_prot;
    ftp_close : unit -> unit;
    mutable ftp_gssapi_props : Netsys_gssapi.client_props option;
    mutable ftp_auth_loop : bool;
  }
  class type out_record_channel =
    object
      method close_out : unit -> unit
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method output_buffer : Buffer.t -> unit
      method output_byte : int -> unit
      method output_bytes : Bytes.t -> unit
      method output_channel : ?len:int -> Netchannels.in_obj_channel -> unit
      method output_char : char -> unit
      method output_eor : unit -> unit
      method output_string : string -> unit
      method pos_out : int
      method really_output : Bytes.t -> int -> int -> unit
      method really_output_string : string -> int -> int -> unit
    end
  class type in_record_channel =
    object
      method close_in : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method input_byte : unit -> int
      method input_char : unit -> char
      method input_eor : unit -> unit
      method input_line : unit -> string
      method pos_in : int
      method really_input : Bytes.t -> int -> int -> unit
      method really_input_string : int -> string
    end
  type local_receiver =
      [ `File_structure of Netchannels.out_obj_channel
      | `Record_structure of Netftp_data_endpoint.out_record_channel ]
  type local_sender =
      [ `File_structure of Netchannels.in_obj_channel
      | `Record_structure of Netftp_data_endpoint.in_record_channel ]
  type transmission_mode = [ `Block_mode | `Stream_mode ]
  type descr_state = [ `Clean | `Down | `Transfer_in_progress ]
  type text_data_repr =
      [ `ASCII of Netconversion.encoding
      | `ASCII_unix of Netconversion.encoding
      | `EBCDIC of Netconversion.encoding ]
  class write_out_record_channel :
    repr:Netftp_data_endpoint.text_data_repr ->
    Netchannels.out_obj_channel -> out_record_channel
  class read_in_record_channel :
    repr:Netftp_data_endpoint.text_data_repr ->
    Netchannels.in_obj_channel -> in_record_channel
  class data_converter :
    fromrepr:Netftp_data_endpoint.text_data_repr ->
    torepr:Netftp_data_endpoint.text_data_repr -> Netchannels.io_obj_channel
  class type ftp_data_engine =
    object
      method abort : unit -> unit
      method descr : Unix.file_descr
      method descr_state : Netftp_data_endpoint.descr_state
      method event_system : Unixqueue.event_system
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        (unit Uq_engines.engine -> bool) -> unit
      method state : unit Uq_engines.engine_state
    end
  class ftp_data_receiver :
    ?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option *
         string option ->
    ?protector:Netftp_data_endpoint.ftp_protector ->
    esys:Unixqueue.event_system ->
    mode:Netftp_data_endpoint.transmission_mode ->
    local_receiver:Netftp_data_endpoint.local_receiver ->
    descr:Unix.file_descr ->
    timeout:float ->
    timeout_exn:exn ->
    unit ->
    object
      method abort : unit -> unit
      method descr : Unix.file_descr
      method descr_state : descr_state
      method event_system : Unixqueue.event_system
      method local_receiver : Netftp_data_endpoint.local_receiver
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        (unit Uq_engines.engine -> bool) -> unit
      method state : unit Uq_engines.engine_state
    end
  class ftp_data_sender :
    ?tls:(module Netsys_crypto_types.TLS_CONFIG) * string option *
         string option ->
    ?protector:Netftp_data_endpoint.ftp_protector ->
    esys:Unixqueue.event_system ->
    mode:Netftp_data_endpoint.transmission_mode ->
    local_sender:Netftp_data_endpoint.local_sender ->
    descr:Unix.file_descr ->
    timeout:float ->
    timeout_exn:exn ->
    unit ->
    object
      method abort : unit -> unit
      method descr : Unix.file_descr
      method descr_state : descr_state
      method event_system : Unixqueue.event_system
      method local_sender : Netftp_data_endpoint.local_sender
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        (unit Uq_engines.engine -> bool) -> unit
      method state : unit Uq_engines.engine_state
    end
end
ocamlnet-4.1.2/doc/html-main/type_Netldap.Debug.html0000644000175000017500000004100012731530353020737 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netldap.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netchannels.raw_in_channel-c.html0000644000175000017500000004410212731530353022720 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_in_channel

Class type Netchannels.raw_in_channel

class type raw_in_channel = object .. end
Basic Unix-level class type for input channels as used by ocamlnet. In addition to the recommended standard, ocamlnet always support a position counter
Inherits
method pos_in : int
Returns the current channel position. This position can be expected to be consistent with the returned number of bytes of input, i.e. when input returns n, the position is advanced by n.

As seek operations are outside the scope of Netchannels, implementations may or may not take seek operations into account.

ocamlnet-4.1.2/doc/html-main/Nettls_gnutls_bindings.html0000644000175000017500000032644712731530353022031 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls_bindings

Module Nettls_gnutls_bindings

module Nettls_gnutls_bindings: sig .. end
Bindings of a C library

type gnutls_cipher_algorithm_t 
type gnutls_kx_algorithm_t 
type gnutls_mac_algorithm_t 
type gnutls_compression_method_t 
type gnutls_pk_algorithm_t 
type gnutls_sign_algorithm_t 
type gnutls_certificate_type_t 
type gnutls_digest_algorithm_t = gnutls_mac_algorithm_t 
type gnutls_session_t 
type gnutls_dh_params_t 
type gnutls_priority_t 
type gnutls_cipher_hd_t 
type gnutls_x509_privkey_t 
type gnutls_x509_crl_t 
type gnutls_x509_crt_t 
type gnutls_openpgp_keyring_t 
type gnutls_certificate_credentials_t 
type gnutls_anon_server_credentials_t 
type gnutls_anon_client_credentials_t 
type gnutls_srp_server_credentials_t 
type gnutls_srp_client_credentials_t 
type gnutls_psk_server_credentials_t 
type gnutls_psk_client_credentials_t 
type gnutls_pubkey_t 
type gnutls_privkey_t 
type gnutls_params_type_t = [ `Dh | `Ecdh | `Rsa_export ] 
type gnutls_credentials_type_t = [ `Anon | `Certificate | `Ia | `Psk | `Srp ] 
type gnutls_alert_level_t = [ `Fatal | `Warning ] 
type gnutls_alert_description_t = [ `Access_denied
| `Bad_certificate
| `Bad_record_mac
| `Certificate_expired
| `Certificate_revoked
| `Certificate_unknown
| `Certificate_unobtainable
| `Close_notify
| `Decode_error
| `Decompression_failure
| `Decrypt_error
| `Decryption_failed
| `Export_restriction
| `Handshake_failure
| `Illegal_parameter
| `Inner_application_failure
| `Inner_application_verification
| `Insufficient_security
| `Internal_error
| `No_application_protocol
| `No_renegotiation
| `Protocol_version
| `Record_overflow
| `Ssl3_no_certificate
| `Unexpected_message
| `Unknown_ca
| `Unknown_psk_identity
| `Unrecognized_name
| `Unsupported_certificate
| `Unsupported_extension
| `User_canceled ]
type gnutls_handshake_description_t = [ `Certificate_pkt
| `Certificate_request
| `Certificate_verify
| `Change_cipher_spec
| `Client_hello
| `Client_hello_v2
| `Client_key_exchange
| `Finished
| `Hello_request
| `Hello_verify_request
| `New_session_ticket
| `Server_hello
| `Server_hello_done
| `Server_key_exchange
| `Supplemental ]
type gnutls_certificate_status_t_flag = [ `Expired
| `Insecure_algorithm
| `Invalid
| `Mismatch
| `Not_activated
| `Purpose_mismatch
| `Revocation_data_issued_in_future
| `Revocation_data_superseded
| `Revoked
| `Signature_failure
| `Signer_constraints_failure
| `Signer_not_ca
| `Signer_not_found
| `Unexpected_owner ]
type gnutls_certificate_status_t = gnutls_certificate_status_t_flag list 
type gnutls_certificate_request_t = [ `Ignore | `Request | `Require ] 
type gnutls_certificate_verify_flags_flag = [ `Allow_any_x509_v1_ca_crt
| `Allow_sign_rsa_md2
| `Allow_sign_rsa_md5
| `Allow_x509_v1_ca_crt
| `Disable_ca_sign
| `Disable_crl_checks
| `Disable_time_checks
| `Disable_trusted_time_checks
| `Do_not_allow_same
| `Do_not_allow_x509_v1_ca_crt ]
type gnutls_certificate_verify_flags = gnutls_certificate_verify_flags_flag list 
type gnutls_openpgp_crt_status_t = [ `Cert | `Cert_fingerprint ] 
type gnutls_close_request_t = [ `Rdwr | `Wr ] 
type gnutls_protocol_t = [ `Dtls0_9
| `Dtls1_0
| `Dtls1_2
| `Ssl3
| `Tls1_0
| `Tls1_1
| `Tls1_2
| `Version_unknown ]
type gnutls_x509_crt_fmt_t = [ `Der | `Pem ] 
type gnutls_certificate_print_formats_t = [ `Compact | `Full | `Full_numbers | `Oneline | `Unsigned_full ] 
type gnutls_ecc_curve_t = [ `Invalid | `Secp192r1 | `Secp224r1 | `Secp256r1 | `Secp384r1 | `Secp521r1 ] 
type gnutls_sec_param_t = [ `Export
| `High
| `Insecure
| `Legacy
| `Low
| `Normal
| `Ultra
| `Unknown
| `Very_weak
| `Weak ]
type gnutls_init_flags_flag = [ `Client
| `Datagram
| `No_extensions
| `No_replay_protection
| `Nonblock
| `Server ]
type gnutls_init_flags = gnutls_init_flags_flag list 
type gnutls_server_name_type_t = [ `Dns ] 
type gnutls_supplemental_data_format_type_t = [ `Unknown ] 
type gnutls_psk_key_flags = [ `Hex | `Raw ] 
type gnutls_x509_subject_alt_name_t = [ `Dn
| `Dnsname
| `Ipaddress
| `Othername
| `Othername_xmpp
| `Rfc822name
| `Uri ]
type gnutls_privkey_type_t = [ `Ext | `Openpgp | `Pkcs11 | `X509 ] 
type key_usage_flag = [ `Crl_sign
| `Data_encipherment
| `Decipher_only
| `Digital_signature
| `Encipher_only
| `Key_agreement
| `Key_cert_sign
| `Key_encipherment
| `Non_repudiation ]
type key_usage = key_usage_flag list 
type gnutls_channel_binding_t = [ `Tls_unique ] 
type gnutls_info_access_what_t = [ `Accesslocation_generalname_type
| `Accessmethod_oid
| `Caissuers_uri
| `Ocsp_uri
| `Unknown
| `Uri ]
type gnutls_certificate_import_flags_flag = [ `Fail_if_unsorted | `Import_fail_if_exceed | `Sort ] 
type gnutls_certificate_import_flags = gnutls_certificate_import_flags_flag list 
type error_code = [ `Again
| `Asn1_der_error
| `Asn1_der_overflow
| `Asn1_element_not_found
| `Asn1_generic_error
| `Asn1_identifier_not_found
| `Asn1_syntax_error
| `Asn1_tag_error
| `Asn1_tag_implicit
| `Asn1_type_any_error
| `Asn1_value_not_found
| `Asn1_value_not_valid
| `Auth_error
| `Bad_cookie
| `Base64_decoding_error
| `Base64_encoding_error
| `Base64_unexpected_header_error
| `Certificate_error
| `Certificate_key_mismatch
| `Certificate_list_unsorted
| `Channel_binding_not_available
| `Compression_failed
| `Constraint_error
| `Crypto_already_registered
| `Crypto_init_failed
| `Cryptodev_device_error
| `Cryptodev_ioctl_error
| `Db_error
| `Decompression_failed
| `Decryption_failed
| `Dh_prime_unacceptable
| `Ecc_no_supported_curves
| `Ecc_unsupported_curve
| `Encryption_failed
| `Error_in_finished_packet
| `Expired
| `Fatal_alert_received
| `File_error
| `Got_application_data
| `Handshake_too_large
| `Hash_failed
| `Heartbeat_ping_received
| `Heartbeat_pong_received
| `Ia_verify_failed
| `Idna_error
| `Illegal_parameter
| `Illegal_srp_username
| `Incompat_dsa_key_with_tls_protocol
| `Incompatible_crypto_library
| `Incompatible_libtasn1_library
| `Insufficient_credentials
| `Internal_error
| `Interrupted
| `Invalid_password
| `Invalid_request
| `Invalid_session
| `Key_import_failed
| `Key_usage_violation
| `Large_packet
| `Lib_in_error_state
| `Locking_error
| `Mac_verify_failed
| `Memory_error
| `Mpi_print_failed
| `Mpi_scan_failed
| `Need_fallback
| `No_application_protocol
| `No_certificate_found
| `No_certificate_status
| `No_cipher_suites
| `No_compression_algorithms
| `No_priorities_were_set
| `No_self_test
| `No_temporary_dh_params
| `No_temporary_rsa_params
| `Ocsp_response_error
| `Openpgp_fingerprint_unsupported
| `Openpgp_getkey_failed
| `Openpgp_keyring_error
| `Openpgp_preferred_key_error
| `Openpgp_subkey_error
| `Openpgp_uid_revoked
| `Parsing_error
| `Pk_decryption_failed
| `Pk_encryption_failed
| `Pk_generation_error
| `Pk_sig_verify_failed
| `Pk_sign_failed
| `Pkcs11_attribute_error
| `Pkcs11_data_error
| `Pkcs11_device_error
| `Pkcs11_error
| `Pkcs11_key_error
| `Pkcs11_load_error
| `Pkcs11_pin_error
| `Pkcs11_pin_expired
| `Pkcs11_pin_locked
| `Pkcs11_requested_object_not_availble
| `Pkcs11_session_error
| `Pkcs11_signature_error
| `Pkcs11_slot_error
| `Pkcs11_token_error
| `Pkcs11_unsupported_feature_error
| `Pkcs11_user_error
| `Pkcs1_wrong_pad
| `Premature_termination
| `Pull_error
| `Push_error
| `Random_device_error
| `Random_failed
| `Received_illegal_extension
| `Received_illegal_parameter
| `Record_limit_reached
| `Rehandshake
| `Requested_data_not_available
| `Safe_renegotiation_failed
| `Self_test_error
| `Session_eof
| `Short_memory_buffer
| `Sockets_init_error
| `Srp_pwd_error
| `Srp_pwd_parsing_error
| `Success
| `Timedout
| `Too_many_empty_packets
| `Too_many_handshake_packets
| `Tpm_error
| `Tpm_key_not_found
| `Tpm_key_password_error
| `Tpm_session_error
| `Tpm_srk_password_error
| `Tpm_uninitialized
| `Unexpected_handshake_packet
| `Unexpected_packet
| `Unexpected_packet_length
| `Unimplemented_feature
| `Unknown_algorithm
| `Unknown_cipher_suite
| `Unknown_cipher_type
| `Unknown_compression_algorithm
| `Unknown_hash_algorithm
| `Unknown_pk_algorithm
| `Unknown_pkcs_bag_type
| `Unknown_pkcs_content_type
| `Unknown_srp_username
| `Unsafe_renegotiation_denied
| `Unsupported_certificate_type
| `Unsupported_signature_algorithm
| `Unsupported_version_packet
| `Unwanted_algorithm
| `User_error
| `Warning_alert_received
| `Warning_ia_fphf_received
| `Warning_ia_iphf_received
| `X509_unknown_san
| `X509_unsupported_attribute
| `X509_unsupported_critical_extension
| `X509_unsupported_extension
| `X509_unsupported_oid ]
type gnutls_pkcs_encrypt_flags_t_flag = [ `Null_password
| `Plain
| `Use_pbes2_3des
| `Use_pbes2_aes_128
| `Use_pbes2_aes_192
| `Use_pbes2_aes_256
| `Use_pbes2_des
| `Use_pkcs12_3des
| `Use_pkcs12_arcfour
| `Use_pkcs12_rc2_40 ]
type gnutls_pkcs_encrypt_flags_t = gnutls_pkcs_encrypt_flags_t_flag list 
type empty_flags_flag = [ `Dummy ] 
type empty_flags = empty_flags_flag list 
type str_datum = string 
type str_datum_p = string 
type const_str_datum_p = string 
val nettls_init : unit -> unit
val nettls_deinit : unit -> unit
val gnutls_error_is_fatal : error_code -> bool
val gnutls_strerror : error_code -> string
val gnutls_strerror_name : error_code -> string
val gnutls_check_version : unit -> string
val gnutls_global_set_log_level : int -> unit
val gnutls_init : gnutls_init_flags ->
gnutls_session_t
val gnutls_certificate_server_set_request : gnutls_session_t ->
gnutls_certificate_request_t -> unit
val gnutls_certificate_send_x509_rdn_sequence : gnutls_session_t -> bool -> unit
val gnutls_certificate_verify_peers2 : gnutls_session_t ->
gnutls_certificate_status_t
val gnutls_certificate_get_peers : gnutls_session_t -> string array
val gnutls_record_get_direction : gnutls_session_t -> bool
val gnutls_handshake : gnutls_session_t -> unit
val gnutls_rehandshake : gnutls_session_t -> unit
val gnutls_record_send : gnutls_session_t -> Netsys_mem.memory -> int -> int
val gnutls_record_recv : gnutls_session_t -> Netsys_mem.memory -> int
val gnutls_record_check_pending : gnutls_session_t -> int
val gnutls_bye : gnutls_session_t ->
gnutls_close_request_t -> unit
val gnutls_alert_get : gnutls_session_t ->
gnutls_alert_description_t
val gnutls_alert_get_name : gnutls_alert_description_t -> string
val gnutls_alert_get_strname : gnutls_alert_description_t -> string
val gnutls_alert_send : gnutls_session_t ->
gnutls_alert_level_t ->
gnutls_alert_description_t -> unit
val gnutls_alert_send_appropriate : gnutls_session_t -> int -> unit
val gnutls_error_to_alert : error_code ->
gnutls_alert_description_t *
gnutls_alert_level_t
val gnutls_priority_init : string -> gnutls_priority_t
val gnutls_priority_get_cipher_suite_index : gnutls_priority_t -> int -> int
val gnutls_priority_set : gnutls_session_t ->
gnutls_priority_t -> unit
val gnutls_set_default_priority : gnutls_session_t -> unit
val gnutls_sec_param_to_pk_bits : gnutls_pk_algorithm_t ->
gnutls_sec_param_t -> int
val gnutls_pk_bits_to_sec_param : gnutls_pk_algorithm_t ->
int -> gnutls_sec_param_t
val gnutls_sec_param_get_name : gnutls_sec_param_t -> string
val gnutls_session_set_data : gnutls_session_t -> Bytes.t -> unit
val gnutls_session_get_data : gnutls_session_t -> Bytes.t
val gnutls_session_get_id : gnutls_session_t -> Bytes.t
val gnutls_session_is_resumed : gnutls_session_t -> bool
val gnutls_db_set_cache_expiration : gnutls_session_t -> int -> unit
val gnutls_db_remove_session : gnutls_session_t -> unit
val gnutls_db_check_entry : gnutls_session_t -> string -> int
val gnutls_session_ticket_key_generate : unit -> string
val gnutls_session_ticket_enable_client : gnutls_session_t -> unit
val gnutls_session_ticket_enable_server : gnutls_session_t ->
str_datum_p -> unit
val gnutls_prf : gnutls_session_t ->
Netsys_mem.memory -> bool -> Netsys_mem.memory -> Netsys_mem.memory -> unit
val gnutls_prf_raw : gnutls_session_t ->
Netsys_mem.memory -> Netsys_mem.memory -> Netsys_mem.memory -> unit
val gnutls_session_channel_binding : gnutls_session_t ->
gnutls_channel_binding_t -> string
val gnutls_ecc_curve_get_name : gnutls_ecc_curve_t -> string
val gnutls_ecc_curve_get_size : gnutls_ecc_curve_t -> int
val gnutls_ecc_curve_get : gnutls_session_t ->
gnutls_ecc_curve_t
val gnutls_cipher_get : gnutls_session_t ->
gnutls_cipher_algorithm_t
val gnutls_kx_get : gnutls_session_t ->
gnutls_kx_algorithm_t
val gnutls_mac_get : gnutls_session_t ->
gnutls_mac_algorithm_t
val gnutls_compression_get : gnutls_session_t ->
gnutls_compression_method_t
val gnutls_certificate_type_get : gnutls_session_t ->
gnutls_certificate_type_t
val gnutls_cipher_get_key_size : gnutls_cipher_algorithm_t -> int
val gnutls_mac_get_key_size : gnutls_mac_algorithm_t -> int
val gnutls_cipher_get_name : gnutls_cipher_algorithm_t -> string
val gnutls_mac_get_name : gnutls_mac_algorithm_t -> string
val gnutls_compression_get_name : gnutls_compression_method_t -> string
val gnutls_kx_get_name : gnutls_kx_algorithm_t -> string
val gnutls_certificate_type_get_name : gnutls_certificate_type_t -> string
val gnutls_pk_get_name : gnutls_pk_algorithm_t -> string
val gnutls_sign_get_name : gnutls_sign_algorithm_t -> string
val gnutls_mac_get_id : string -> gnutls_mac_algorithm_t
val gnutls_compression_get_id : string -> gnutls_compression_method_t
val gnutls_cipher_get_id : string -> gnutls_cipher_algorithm_t
val gnutls_kx_get_id : string -> gnutls_kx_algorithm_t
val gnutls_protocol_get_id : string -> gnutls_protocol_t
val gnutls_certificate_type_get_id : string -> gnutls_certificate_type_t
val gnutls_pk_get_id : string -> gnutls_pk_algorithm_t
val gnutls_sign_get_id : string -> gnutls_sign_algorithm_t
val gnutls_cipher_list : unit -> gnutls_cipher_algorithm_t list
val gnutls_mac_list : unit -> gnutls_mac_algorithm_t list
val gnutls_compression_list : unit -> gnutls_compression_method_t list
val gnutls_protocol_list : unit -> gnutls_protocol_t list
val gnutls_certificate_type_list : unit -> gnutls_certificate_type_t list
val gnutls_kx_list : unit -> gnutls_kx_algorithm_t list
val gnutls_pk_list : unit -> gnutls_pk_algorithm_t list
val gnutls_sign_list : unit -> gnutls_sign_algorithm_t list
val gnutls_protocol_get_version : gnutls_session_t ->
gnutls_protocol_t
val gnutls_protocol_get_name : gnutls_protocol_t -> string
val gnutls_cipher_suite_get_name : gnutls_kx_algorithm_t ->
gnutls_cipher_algorithm_t ->
gnutls_mac_algorithm_t -> string
val net_have_crypto : unit -> bool
val gnutls_cipher_init : gnutls_cipher_algorithm_t ->
str_datum_p ->
str_datum_p ->
gnutls_cipher_hd_t
val gnutls_cipher_encrypt2 : gnutls_cipher_hd_t ->
Netsys_mem.memory -> Netsys_mem.memory -> unit
val gnutls_cipher_decrypt2 : gnutls_cipher_hd_t ->
Netsys_mem.memory -> Netsys_mem.memory -> unit
val gnutls_cipher_add_auth : gnutls_cipher_hd_t -> Bytes.t -> unit
val gnutls_cipher_tag : gnutls_cipher_hd_t -> Bytes.t -> unit
val gnutls_handshake_set_private_extensions : gnutls_session_t -> bool -> unit
val gnutls_handshake_get_last_out : gnutls_session_t ->
gnutls_handshake_description_t
val gnutls_handshake_get_last_in : gnutls_session_t ->
gnutls_handshake_description_t
val gnutls_handshake_set_max_packet_length : gnutls_session_t -> int -> unit
val gnutls_sign_algorithm_get_requested : gnutls_session_t ->
int -> gnutls_sign_algorithm_t
val gnutls_session_enable_compatibility_mode : gnutls_session_t -> unit
val gnutls_record_disable_padding : gnutls_session_t -> unit
val gnutls_record_get_max_size : gnutls_session_t -> int
val gnutls_record_set_max_size : gnutls_session_t -> int -> unit
val gnutls_server_name_set : gnutls_session_t ->
gnutls_server_name_type_t -> Bytes.t -> unit
val gnutls_server_name_get : gnutls_session_t ->
int -> Bytes.t * gnutls_server_name_type_t
val gnutls_safe_renegotiation_status : gnutls_session_t -> bool
val gnutls_supplemental_get_name : gnutls_supplemental_data_format_type_t -> string
val gnutls_credentials_clear : gnutls_session_t -> unit
val gnutls_key_generate : int -> string
val gnutls_fingerprint : gnutls_digest_algorithm_t ->
str_datum_p -> Bytes.t
val gnutls_certificate_allocate_credentials : unit -> gnutls_certificate_credentials_t
val gnutls_certificate_set_x509_system_trust : gnutls_certificate_credentials_t -> unit
val gnutls_certificate_set_x509_trust_file : gnutls_certificate_credentials_t ->
string -> gnutls_x509_crt_fmt_t -> unit
val gnutls_certificate_set_x509_trust_mem : gnutls_certificate_credentials_t ->
str_datum_p ->
gnutls_x509_crt_fmt_t -> unit
val gnutls_certificate_set_x509_crl_file : gnutls_certificate_credentials_t ->
string -> gnutls_x509_crt_fmt_t -> unit
val gnutls_certificate_set_x509_crl_mem : gnutls_certificate_credentials_t ->
str_datum_p ->
gnutls_x509_crt_fmt_t -> unit
val gnutls_certificate_set_x509_key_file : gnutls_certificate_credentials_t ->
string -> string -> gnutls_x509_crt_fmt_t -> unit
val gnutls_certificate_set_x509_key_mem : gnutls_certificate_credentials_t ->
str_datum_p ->
str_datum_p ->
gnutls_x509_crt_fmt_t -> unit
val gnutls_certificate_set_x509_simple_pkcs12_file : gnutls_certificate_credentials_t ->
string -> gnutls_x509_crt_fmt_t -> string -> unit
val gnutls_certificate_set_x509_simple_pkcs12_mem : gnutls_certificate_credentials_t ->
str_datum_p ->
gnutls_x509_crt_fmt_t -> string -> unit
val gnutls_certificate_set_x509_key : gnutls_certificate_credentials_t ->
gnutls_x509_crt_t array ->
gnutls_x509_privkey_t -> unit
val gnutls_certificate_set_x509_trust : gnutls_certificate_credentials_t ->
gnutls_x509_crt_t array -> int
val gnutls_certificate_set_x509_crl : gnutls_certificate_credentials_t ->
gnutls_x509_crl_t array -> int
val gnutls_anon_allocate_server_credentials : unit -> gnutls_anon_server_credentials_t
val gnutls_anon_allocate_client_credentials : unit -> gnutls_anon_client_credentials_t
val gnutls_dh_params_init : unit -> gnutls_dh_params_t
val gnutls_dh_params_import_raw : gnutls_dh_params_t ->
str_datum_p ->
str_datum_p -> unit
val gnutls_dh_params_import_pkcs3 : gnutls_dh_params_t ->
str_datum_p ->
gnutls_x509_crt_fmt_t -> unit
val gnutls_dh_params_generate2 : gnutls_dh_params_t -> int -> unit
val gnutls_dh_params_cpy : gnutls_dh_params_t ->
gnutls_dh_params_t -> unit
val gnutls_certificate_set_dh_params : gnutls_certificate_credentials_t ->
gnutls_dh_params_t -> unit
val gnutls_anon_set_server_dh_params : gnutls_anon_server_credentials_t ->
gnutls_dh_params_t -> unit
val gnutls_psk_set_server_dh_params : gnutls_psk_server_credentials_t ->
gnutls_dh_params_t -> unit
val gnutls_dh_set_prime_bits : gnutls_session_t -> int -> unit
val gnutls_dh_get_secret_bits : gnutls_session_t -> int
val gnutls_dh_get_peers_public_bits : gnutls_session_t -> int
val gnutls_dh_get_prime_bits : gnutls_session_t -> int
val gnutls_dh_get_group : gnutls_session_t -> string * string
val gnutls_dh_get_pubkey : gnutls_session_t -> string
val gnutls_auth_get_type : gnutls_session_t ->
gnutls_credentials_type_t
val gnutls_auth_server_get_type : gnutls_session_t ->
gnutls_credentials_type_t
val gnutls_auth_client_get_type : gnutls_session_t ->
gnutls_credentials_type_t
val gnutls_certificate_get_ours : gnutls_session_t ->
const_str_datum_p
val gnutls_certificate_activation_time_peers : gnutls_session_t -> float
val gnutls_certificate_expiration_time_peers : gnutls_session_t -> float
val gnutls_certificate_client_get_request_status : gnutls_session_t -> bool
val gnutls_certificate_get_issuer : gnutls_certificate_credentials_t ->
gnutls_x509_crt_t ->
empty_flags ->
gnutls_x509_crt_t
val gnutls_certificate_set_verify_flags : gnutls_certificate_credentials_t ->
gnutls_certificate_verify_flags -> unit
val gnutls_certificate_set_verify_limits : gnutls_certificate_credentials_t -> int -> int -> unit
val gnutls_openpgp_send_cert : gnutls_session_t ->
gnutls_openpgp_crt_status_t -> unit
val gnutls_srp_allocate_client_credentials : unit -> gnutls_srp_client_credentials_t
val gnutls_srp_set_client_credentials : gnutls_srp_client_credentials_t ->
string -> string -> unit
val gnutls_srp_allocate_server_credentials : unit -> gnutls_srp_server_credentials_t
val gnutls_srp_set_server_credentials_file : gnutls_srp_server_credentials_t ->
string -> string -> unit
val gnutls_srp_server_get_username : gnutls_session_t -> string
val gnutls_srp_set_prime_bits : gnutls_session_t -> int -> unit
val gnutls_srp_verifier : string ->
string ->
str_datum_p ->
str_datum_p ->
str_datum_p -> string
val gnutls_psk_allocate_client_credentials : unit -> gnutls_psk_client_credentials_t
val gnutls_psk_set_client_credentials : gnutls_psk_client_credentials_t ->
string ->
str_datum_p ->
gnutls_psk_key_flags -> unit
val gnutls_psk_allocate_server_credentials : unit -> gnutls_psk_server_credentials_t
val gnutls_psk_set_server_credentials_file : gnutls_psk_server_credentials_t -> string -> unit
val gnutls_psk_set_server_credentials_hint : gnutls_psk_server_credentials_t -> string -> unit
val gnutls_psk_server_get_username : gnutls_session_t -> string
val gnutls_psk_client_get_hint : gnutls_session_t -> string
val gnutls_x509_crt_init : unit -> gnutls_x509_crt_t
val gnutls_x509_crt_import : gnutls_x509_crt_t ->
const_str_datum_p ->
gnutls_x509_crt_fmt_t -> unit
val gnutls_x509_crt_export : gnutls_x509_crt_t ->
gnutls_x509_crt_fmt_t -> Bytes.t
val gnutls_x509_crt_get_issuer_dn : gnutls_x509_crt_t -> Bytes.t
val gnutls_x509_crt_get_issuer_dn_oid : gnutls_x509_crt_t -> int -> Bytes.t
val gnutls_x509_crt_get_dn : gnutls_x509_crt_t -> Bytes.t
val gnutls_x509_crt_get_dn_oid : gnutls_x509_crt_t -> int -> Bytes.t
val gnutls_x509_crt_check_hostname : gnutls_x509_crt_t -> string -> bool
val gnutls_x509_crt_get_signature_algorithm : gnutls_x509_crt_t ->
gnutls_sign_algorithm_t
val gnutls_x509_crt_get_signature : gnutls_x509_crt_t -> Bytes.t
val gnutls_x509_crt_get_version : gnutls_x509_crt_t -> int
val gnutls_x509_crt_get_key_id : gnutls_x509_crt_t ->
empty_flags -> Bytes.t
val gnutls_x509_crt_get_authority_key_id : gnutls_x509_crt_t -> Bytes.t * bool
val gnutls_x509_crt_get_subject_key_id : gnutls_x509_crt_t -> Bytes.t * bool
val gnutls_x509_crt_get_subject_unique_id : gnutls_x509_crt_t -> Bytes.t
val gnutls_x509_crt_get_issuer_unique_id : gnutls_x509_crt_t -> Bytes.t
val gnutls_x509_crt_get_authority_info_access : gnutls_x509_crt_t ->
int -> gnutls_info_access_what_t -> string * bool
val gnutls_x509_crt_get_activation_time : gnutls_x509_crt_t -> float
val gnutls_x509_crt_get_expiration_time : gnutls_x509_crt_t -> float
val gnutls_x509_crt_get_serial : gnutls_x509_crt_t -> Bytes.t
val gnutls_x509_crt_get_pk_algorithm : gnutls_x509_crt_t ->
gnutls_pk_algorithm_t * int
val gnutls_x509_crt_get_pk_rsa_raw : gnutls_x509_crt_t -> string * string
val gnutls_x509_crt_get_pk_dsa_raw : gnutls_x509_crt_t -> string * string * string * string
val gnutls_x509_crt_get_subject_alt_name : gnutls_x509_crt_t ->
int -> gnutls_x509_subject_alt_name_t * Bytes.t * bool
val gnutls_x509_crt_get_subject_alt_othername_oid : gnutls_x509_crt_t ->
int -> gnutls_x509_subject_alt_name_t * Bytes.t
val gnutls_x509_crt_get_issuer_alt_name : gnutls_x509_crt_t ->
int -> gnutls_x509_subject_alt_name_t * Bytes.t * bool
val gnutls_x509_crt_get_issuer_alt_othername_oid : gnutls_x509_crt_t ->
int -> gnutls_x509_subject_alt_name_t * Bytes.t
val gnutls_x509_crt_get_ca_status : gnutls_x509_crt_t -> bool
val gnutls_x509_crt_get_basic_constraints : gnutls_x509_crt_t -> bool * bool * int
val gnutls_x509_crt_get_key_usage : gnutls_x509_crt_t ->
key_usage * bool
val gnutls_x509_crt_get_extension_oid : gnutls_x509_crt_t -> int -> Bytes.t
val gnutls_x509_crt_get_extension_info : gnutls_x509_crt_t -> int -> Bytes.t * bool
val gnutls_x509_crt_get_extension_data : gnutls_x509_crt_t -> int -> Bytes.t
val gnutls_x509_crt_check_issuer : gnutls_x509_crt_t ->
gnutls_x509_crt_t -> bool
val gnutls_x509_crt_list_verify : gnutls_x509_crt_t array ->
gnutls_x509_crt_t array ->
gnutls_x509_crl_t array ->
gnutls_certificate_verify_flags ->
gnutls_certificate_status_t
val gnutls_x509_crt_verify : gnutls_x509_crt_t ->
gnutls_x509_crt_t array ->
gnutls_certificate_verify_flags ->
gnutls_certificate_status_t
val gnutls_x509_crl_verify : gnutls_x509_crl_t ->
gnutls_x509_crt_t array ->
gnutls_certificate_verify_flags ->
gnutls_certificate_status_t
val gnutls_x509_crt_check_revocation : gnutls_x509_crt_t ->
gnutls_x509_crl_t array -> bool
val gnutls_x509_crt_get_fingerprint : gnutls_x509_crt_t ->
gnutls_digest_algorithm_t -> Bytes.t
val gnutls_x509_crt_get_key_purpose_oid : gnutls_x509_crt_t -> int -> Bytes.t * bool
val gnutls_x509_privkey_init : unit -> gnutls_x509_privkey_t
val gnutls_x509_privkey_import : gnutls_x509_privkey_t ->
const_str_datum_p ->
gnutls_x509_crt_fmt_t -> unit
val gnutls_x509_privkey_import_pkcs8 : gnutls_x509_privkey_t ->
const_str_datum_p ->
gnutls_x509_crt_fmt_t ->
string -> gnutls_pkcs_encrypt_flags_t -> unit
val gnutls_x509_crl_init : unit -> gnutls_x509_crl_t
val gnutls_x509_crl_import : gnutls_x509_crl_t ->
const_str_datum_p ->
gnutls_x509_crt_fmt_t -> unit
val net_have_pubkey : unit -> bool
val gnutls_pubkey_init : unit -> gnutls_pubkey_t
val gnutls_privkey_init : unit -> gnutls_privkey_t
val gnutls_pubkey_import : gnutls_pubkey_t ->
const_str_datum_p ->
gnutls_x509_crt_fmt_t -> unit
val gnutls_pubkey_import_url : gnutls_pubkey_t -> string -> int -> unit
val gnutls_pubkey_import_privkey : gnutls_pubkey_t ->
gnutls_privkey_t -> int -> int -> unit
val gnutls_privkey_import_x509 : gnutls_privkey_t ->
gnutls_x509_privkey_t -> int -> unit
val gnutls_pubkey_encrypt_data : gnutls_pubkey_t ->
int -> const_str_datum_p -> string
val gnutls_privkey_decrypt_data : gnutls_privkey_t ->
int -> const_str_datum_p -> string
val gnutls_privkey_sign_data : gnutls_privkey_t ->
gnutls_digest_algorithm_t ->
int -> const_str_datum_p -> string
val gnutls_pubkey_verify_data2 : gnutls_pubkey_t ->
gnutls_sign_algorithm_t ->
int ->
const_str_datum_p ->
const_str_datum_p -> unit
val b_error_of_name : string -> error_code
exception Null_pointer
exception Error of error_code
exception Short_memory_buffer of int
type memory = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t 
type gnutls_credentials = [ `Anon_client of gnutls_anon_client_credentials_t
| `Anon_server of gnutls_anon_server_credentials_t
| `Certificate of gnutls_certificate_credentials_t
| `Psk_client of gnutls_psk_client_credentials_t
| `Psk_server of gnutls_psk_server_credentials_t
| `Srp_client of gnutls_srp_client_credentials_t
| `Srp_server of gnutls_srp_server_credentials_t ]
val gnutls_credentials_set : gnutls_session_t ->
gnutls_credentials -> unit
val b_set_pull_callback : gnutls_session_t ->
(memory -> int) -> unit
Sets the function for reading data. The function must return the number of read bytes (like Unix.read). The function can raise Unix_error. Only the codes EINTR, EAGAIN, EWOULDBLOCK, and EMSGSIZE are interpreted.
val b_set_push_callback : gnutls_session_t ->
(memory -> int -> int) -> unit
Sets the function for writing data. The function must return the number of written bytes (like Unix.write). The function can raise Unix_error. Only the codes EINTR, EAGAIN, EWOULDBLOCK, and EMSGSIZE are interpreted.
val b_set_pull_timeout_callback : gnutls_session_t -> (int -> bool) -> unit
Sets the function for waiting for new data to arrive (only used for DTLS). The integer are the milliseconds to wait at most. The function shall return true if there is data, and false in case of a timeout. The function can raise Unix_error. Only the codes EINTR, EAGAIN, EWOULDBLOCK, and EMSGSIZE are interpreted.
val b_set_verify_callback : gnutls_session_t ->
(gnutls_session_t -> bool) -> unit
Sets the function for verifying the peer's certificate. The function can return true if the certificate is acceptable, and false otherwise. Note that this callback is set in this binding on the session, and not on gnutls_certificate_credentials_t.
val set_fd : gnutls_session_t -> Unix.file_descr -> unit
Sets that this file descriptor is used for I/O. NB. This function just invokes b_set_pull_callback, b_set_push_callback, and b_set_pull_timeout_callback with the right argument functions.
val b_set_db_callbacks : gnutls_session_t ->
(string -> string -> unit) -> (string -> unit) -> (string -> string) -> unit
b_set_db_callbacks session store remove retrieve: sets the three callbacks for server-side session caching
val string_of_verification_status_flag : gnutls_certificate_status_t_flag -> string
Returns a string for the status code
val gnutls_x509_crt_list_import : string ->
gnutls_x509_crt_fmt_t ->
gnutls_certificate_import_flags ->
gnutls_x509_crt_t array
val gnutls_x509_crl_list_import : string ->
gnutls_x509_crt_fmt_t ->
gnutls_certificate_import_flags ->
gnutls_x509_crl_t array
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.serializer.html0000644000175000017500000004104412731530353024143 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.serializer Unixqueue.event_system -> ['a] Uq_engines_compat.serializer_tocamlnet-4.1.2/doc/html-main/Uq_socks5.proxy_client-c.html0000644000175000017500000004560712731530353022115 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_socks5.proxy_client

Class Uq_socks5.proxy_client

class proxy_client : Uq_engines.connect_address -> object .. end
The object created by new proxy_client addr can be passed as proxy to the Uq_engines.connector, Uq_engines.listener, and Uq_engines.datagram_provider functions to use the SOCKS proxy for connections, servers, and datagram socket, respectively.

The SOCKS client supports the following methods:

  • connect: Only TCP connections are supported (UDP could be made working - TODO)
  • listen: This works (only) for TCP sockets, too
  • create_datagram_socket: Creates unconnected datagram sockets that can be sent and received with object methods
Note that socket addresses are resolved by the proxy host; this applies to both `Sock_inet and `Sock_inet_byname. For the latter this means that name resolution is done by the proxy.

The nature of SOCKS restricts the functionality:

  • `Sock_unix addresses are not supported (i.e. you cannot connect to a Unix domain socket on the proxy host)
  • Listening server sockets can only accept one connection; after that they are "dead" and must be shut down first. The method multiple_connections is false because of this.
  • Further restrictions can be enforced by the SOCKS proxy and its configuration.

Inherits
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.unified_auth_handler.html0000644000175000017500000004114312731530353025457 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.unified_auth_handler ?insecure:bool -> #Nethttp_client.key_handler -> Nethttp_client.auth_handlerocamlnet-4.1.2/doc/html-main/type_Netchannels.compl_out_channel.html0000644000175000017500000004370212731530353024270 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.compl_out_channel object
  method output_buffer : Buffer.t -> unit
  method output_byte : int -> unit
  method output_bytes : Bytes.t -> unit
  method output_channel : ?len:int -> Netchannels.in_obj_channel -> unit
  method output_char : char -> unit
  method output_string : string -> unit
  method really_output : Bytes.t -> int -> int -> unit
  method really_output_string : string -> int -> int -> unit
end
ocamlnet-4.1.2/doc/html-main/Netplex_container.html0000644000175000017500000004453712731530353020765 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_container

Module Netplex_container

module Netplex_container: sig .. end
Containers

The container is the management object for the concurrently running service processor.


val create_container : Netplex_types.parallelization_type ->
Netplex_types.socket_service -> Netplex_types.container
The container for normal services
val create_admin_container : Unixqueue.unix_event_system ->
Netplex_types.parallelization_type ->
Netplex_types.socket_service -> Netplex_types.container
Internally used. The container for the special admin service
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.copier.html0000644000175000017500000004115012731530353023251 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.copier Uq_engines_compat.copy_task ->
Unixqueue.event_system -> [unit] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/type_Netcgi.Argument.html0000644000175000017500000004404212731530353021326 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.Argument sig
  exception Oversized
  val simple : string -> string -> Netcgi.cgi_argument
  val mime :
    ?work_around_backslash_bug:bool ->
    ?name:string -> Netmime.mime_message -> Netcgi.cgi_argument
  val clone :
    ?name:string ->
    ?value:string ->
    ?msg:Netmime.mime_message -> Netcgi.cgi_argument -> Netcgi.cgi_argument
  val set :
    Netcgi.cgi_argument list ->
    Netcgi.cgi_argument list -> Netcgi.cgi_argument list
end
ocamlnet-4.1.2/doc/html-main/type_Netulex.html0000644000175000017500000007253612731530353017771 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netulex sig
  module ULB :
    sig
      type unicode_lexbuf = private {
        mutable ulb_encoding : Netconversion.encoding;
        mutable ulb_encoding_start : int;
        mutable ulb_rawbuf : Bytes.t;
        mutable ulb_rawbuf_len : int;
        mutable ulb_rawbuf_end : int;
        mutable ulb_rawbuf_const : bool;
        mutable ulb_chars : int array;
        mutable ulb_chars_pos : int array;
        mutable ulb_chars_len : int;
        mutable ulb_eof : bool;
        mutable ulb_refill : Bytes.t -> int -> int -> int;
        mutable ulb_enc_change_hook : Netulex.ULB.unicode_lexbuf -> unit;
        mutable ulb_cursor : Bytes.t Netconversion.poly_cursor;
      }
      val from_function :
        ?raw_size:int ->
        ?char_size:int ->
        ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
        refill:(Bytes.t -> int -> int -> int) ->
        Netconversion.encoding -> Netulex.ULB.unicode_lexbuf
      val from_in_obj_channel :
        ?raw_size:int ->
        ?char_size:int ->
        ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
        Netconversion.encoding ->
        Netchannels.in_obj_channel -> Netulex.ULB.unicode_lexbuf
      val from_string :
        ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
        Netconversion.encoding -> string -> Netulex.ULB.unicode_lexbuf
      val from_bytes :
        ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
        Netconversion.encoding -> Bytes.t -> Netulex.ULB.unicode_lexbuf
      val from_bytes_inplace :
        ?enc_change_hook:(Netulex.ULB.unicode_lexbuf -> unit) ->
        Netconversion.encoding -> Bytes.t -> Netulex.ULB.unicode_lexbuf
      val delete : int -> Netulex.ULB.unicode_lexbuf -> unit
      val refill : Netulex.ULB.unicode_lexbuf -> unit
      val set_encoding :
        Netconversion.encoding -> Netulex.ULB.unicode_lexbuf -> unit
      val close : Netulex.ULB.unicode_lexbuf -> unit
      val utf8_sub_string :
        int -> int -> Netulex.ULB.unicode_lexbuf -> string
      val utf8_sub_string_length :
        int -> int -> Netulex.ULB.unicode_lexbuf -> int
    end
  module Ulexing :
    sig
      type lexbuf
      exception Error
      val from_ulb_lexbuf :
        Netulex.ULB.unicode_lexbuf -> Netulex.Ulexing.lexbuf
      val lexeme_start : Netulex.Ulexing.lexbuf -> int
      val lexeme_end : Netulex.Ulexing.lexbuf -> int
      val lexeme_length : Netulex.Ulexing.lexbuf -> int
      val lexeme : Netulex.Ulexing.lexbuf -> int array
      val lexeme_char : Netulex.Ulexing.lexbuf -> int -> int
      val sub_lexeme : Netulex.Ulexing.lexbuf -> int -> int -> int array
      val utf8_lexeme : Netulex.Ulexing.lexbuf -> string
      val utf8_sub_lexeme : Netulex.Ulexing.lexbuf -> int -> int -> string
      val utf8_sub_lexeme_length :
        Netulex.Ulexing.lexbuf -> int -> int -> int
      val start : Netulex.Ulexing.lexbuf -> unit
      val next : Netulex.Ulexing.lexbuf -> int
      val mark : Netulex.Ulexing.lexbuf -> int -> unit
      val backtrack : Netulex.Ulexing.lexbuf -> int
    end
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client_conncache.restrictive_cache-c.html0000644000175000017500000004241312731530353026165 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client_conncache.restrictive_cache

Class Nethttp_client_conncache.restrictive_cache

class restrictive_cache : unit -> connection_cache
A restrictive cache closes connections as soon as there are no pending requests.

ocamlnet-4.1.2/doc/html-main/Shell_sys.html0000644000175000017500000022546012731530353017245 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_sys

Module Shell_sys

module Shell_sys: sig .. end
Calls external programs, creates pipelines, etc. (full interface)


This module is now thread-safe (as of May 2009), provided the threads do no share the same Shell or Shell_sys values. Problems reported earlier here have been resolved.

This module is now thread-safe (as of May 2009), provided the threads do no share the same Shell or Shell_sys values. Problems reported earlier here have been resolved.

If you get errors like "Netsys_posix.watch_subprocess: uninitialized" you should call Shell_sys.install_job_handlers.

Common exceptions


exception Fatal_error of exn
An error is fatal if it is not possible to recover from it in a predictable manner. In this case, many function wrap such exceptions x into Fatal_error x.

Environments


type environment 
The abstract type of a process environment
val create_env : unit -> environment
Creates an empty environment
val current_env : unit -> environment
Returns the environment of the current process as abstract environment value
val copy_env : environment -> environment
Copies an environment
val set_env : environment -> string array -> unit
Sets the contents of the environment to the passed string array
val get_env : environment -> string array
Gets the contents of the environment as string array
val iter_env : f:(string -> unit) -> environment -> unit
Iterates over the strings of the environment, and calls f s for every string s.
val set_env_var : environment -> string -> string -> unit
set_env_var env varname varval: Sets the value of the variable varname in the environment env to varval.
val get_env_var : environment -> string -> string
Returns the value of the variable in the environment
val iter_env_vars : f:(string -> string -> unit) -> environment -> unit
Iterates over the variables of the environment, and calls f name value for every variable with name and value.

Commands


type command 
A command describes how to start a new process
val command : ?cmdname:string ->
?arguments:string array ->
?chdir:string ->
?environment:environment ->
?descriptors:Unix.file_descr list ->
?assignments:(Unix.file_descr * Unix.file_descr) list ->
filename:string -> unit -> command
Creates a command from the passed arguments:


cmdname : The name of the command passed in argv[0]. By default, this argument is derived from filename.
arguments : The arguments of the command (starting with the first real argument, skipping cmdname). By default [] .
chdir : Before the command is executed it is changed to this directory.
environment : The environment of the command. By default, the current environment
descriptors : The list of file descriptors to share with the current process. In the subprocess only those descriptors remain open that are either mentioned in descriptors, or that are the final target of assignments. By default, [stdin; stdout; stderr] .

Note that only the final targets of assignments remain open in the subprocess (unless they are also listed in descriptors). If there are cascaded assignments like (fd1, fd2); (fd2, fd3) the intermediate descriptors like fd2 are not considered as final targets; only fd3 would be a final target in this example.

assignments : A list of descriptor pairs (fd_from,fd_to) . The descriptor fd_from in the current process will be assigned to fd_to in the subprocess started for the command. The list of assignments is executed sequentially, so later assignments must take the effect of previous assignments into account. For example, to make stderr of the subprocess write to stdout of the parent process, pass [(stdout; stderr)] .
  • By default, there are no assignments.
filename : The name of the executable to start. The executable file is not searched, use Shell_sys.lookup_executable for this purpose.
exception Executable_not_found of string
Raised when an executable file cannot be found; the argument is the search name
val lookup_executable : ?path:string list -> string -> string
Searches an executable file. If the passed search name contains a slash, it is expected that this name is already the path name of the executable. If the search name does not contain a slash character, it is searched in the directories enumerated by the search path.


path : The search path. By default, the contents of the variable PATH of the current environment, split by ':', are used (Win32: SearchPath is used)
val get_cmdname : command -> string
Returns the name of the command
val get_arguments : command -> string array
Returns the argument array of the command (skipping the command name)
val get_chdir : command -> string option
Returns the chdir parameter of the command
val get_environment : command -> environment
Returns the designated environment of the command
val get_descriptors : command -> Unix.file_descr list
Returns the list of active descriptors
val get_assignments : command -> (Unix.file_descr * Unix.file_descr) list
Returns the list of assignments (fd_from,fd_to)
val get_filename : command -> string
Returns the file name of the executable
val set_cmdname : command -> string -> unit
Sets the command name
val set_arguments : command -> string array -> unit
Sets the argument array
val set_chdir : command -> string option -> unit
Sets the chdir parameter of the command
val set_environment : command -> environment -> unit
Sets the environment
val set_descriptors : command -> Unix.file_descr list -> unit
Sets the list of active descriptors
val set_assignments : command -> (Unix.file_descr * Unix.file_descr) list -> unit
Sets the list of assignments (fd_from,fd_to)
val set_filename : command -> string -> unit
Sets the file name of the executable to start
val copy_command : command -> command
Returns a duplicate of the command description
val is_executable : command -> bool
Returns true if there is an executable file for the command, and it is permitted to run this file (as stated by the file permissions).

false means that the command can definitely not be executed. However, even if the function returns true there may be still reasons that execution will fail.


Processes


type process 
A process is the running instance of a command (a Unix process)
type group_action = 
| New_bg_group (*
Start process in new background process group
*)
| New_fg_group (*
Start process in new foreground process group
*)
| Join_group of int (*
Started process joins this existing process group
*)
| Current_group (*
Started process remains in the current group
*)
Determines in which process group the new process will run
type fwd_mode = 
| No_forward (*
No forwarding of keyboard signals
*)
| Forward_to_process (*
Forward signals directly to subprocess
*)
| Forward_to_group (*
Forward signals to the process group of the subprocess
*)
Determines whether and how keyboard signals (SIGINT, SIGQUIT) are forwarded from the caller to the new child. There is no forwarding in Win32 - all console applications get the keyboard signals anyway.
val run : ?group:group_action ->
?forward_mode:fwd_mode ->
?pipe_assignments:(Unix.file_descr * Unix.file_descr) list ->
command -> process
Executes the command concurrently with the current process. The function does not wait until the process terminates; it returns immediately after the exec system call has been successfully performed; errors that occur until exec are caught and reported as exception (even errors in the fresh subprocess).

On error, one can assume that the process state has been cleaned up: any forked child process has terminated; any modifications of the global process state has been restored.

File descriptor assignments: First, the assignments in pipe_assignments are performed, then the assignments contained in the command. The pipe_assignments are interpreted as parallel assignment, not as sequential assignment.

Note: For users without very special needs, it is recommended to run jobs instead of processes. See below for the job API.


group : Determines in which process group the new process will run. By default Current_group.
forward_mode : Whether and how to forward keyboard signals to the new child. By default No_forward. The Win32 implementation ignores this argument.
pipe_assignments : A list of descriptor pairs (fd_from,fd_to). The descriptor fd_from in the current process will be assigned to fd_to in the started subprocess. In order to take effect, fd_to must also be passed in the descriptors property of the started command. Furthermore, fd_from may or may not be member of descriptors; in the first case it will remain open, in the latter case it will be closed. The list of assignments is executed in parallel. For example, to swap the roles of stdout and stderr, pass the list [(stdout,stderr); (stderr,stdout)] .
val process_id : process -> int
Returns the process ID of the process
val status : process -> Unix.process_status
Reports the status so far known: If the process has terminated, the status of the process is returned. If the process is still running, Not_found will be raised.
val command_of_process : process -> command
Returns the command that is now running as the process
val call : command -> process
Executes the command and waits until the process terminates (synchronous execution a la system, but no intermediate shell). status is guaranteed to return WEXITED or WSIGNALED.
val kill : ?signal:int -> process -> unit
Sends a signal to the passed process.


signal : The signal to send, by default SIGTERM

Jobs



Jobs



A job is the description of how to run several commands which are linked by pipelines (or which are just a logical unit). A job_instance is the running instance of a job.

Jobs are implemented on a higher layer than commands; the following means of the operating system are used by job invocations:

  • Normally a job_instance corresponds to a Unix process group. In this case the last added command will result in the process group leader.
  • Controlling the execution of jobs requires that signal handlers are set in many cases (see install_job_handlers)
  • The processes of jobs are often interconnected by pipelines (see add_pipeline).
  • It is possible to handle pipelines between the current process and processes of the job (see add_producer and add_consumer)


Jobs



A job is the description of how to run several commands which are linked by pipelines (or which are just a logical unit). A job_instance is the running instance of a job.

Jobs are implemented on a higher layer than commands; the following means of the operating system are used by job invocations:

  • Normally a job_instance corresponds to a Unix process group. In this case the last added command will result in the process group leader.
  • Controlling the execution of jobs requires that signal handlers are set in many cases (see install_job_handlers)
  • The processes of jobs are often interconnected by pipelines (see add_pipeline).
  • It is possible to handle pipelines between the current process and processes of the job (see add_producer and add_consumer)


Important:

In order to run jobs efficiently (without busy waiting) and properly it is strongly recommended to install the signal handlers using install_job_handlers

type job 
type job_instance 
val new_job : unit -> job
Creates a new job descriptor. Initially the job is empty, but you can fill it with commands (add_command), pipelines (add_pipeline), consumers (add_consumer) and producers (add_producer). When the job is set up, you can start it (run_job/finish_job or call_job).
val add_command : command -> job -> unit
Adds a command to a job.

Note that you cannot add the same command twice; however you can add a copy of a command already belonging to the job.

val add_pipeline : ?bidirectional:bool ->
?src_descr:Unix.file_descr ->
?dest_descr:Unix.file_descr ->
src:command -> dest:command -> job -> unit
Adds a pipeline which redirects the output of the command src to the input of the command dest.


bidirectional : if false (default), a classical pipe is created to connect the file descriptors. This normally restricts the data flow to one direction. If true, a socketpair is created which is roughly a bidirectional pipe. In this case, data flow in both directions is possible.
src_descr : determines the file descriptor of the source command which is redirected. This is by default stdout.
dest_descr : determines the file descriptor of the destination command to which the data stream is sent. This is by default stdin.
val add_producer : ?descr:Unix.file_descr ->
producer:(Unix.file_descr -> bool) ->
command -> job -> unit
Adds a producer to the job. A producer transfers data to the subprocess realizing the passed command. To do so, a pipe is created between the file descriptor descr of the subprocess and another descriptor descr' which is open in the current process. The function producer is called when data can be written into the pipe. The argument of producer is the writing end of the pipe descr'. This file descriptor is in non-blocking mode. The function producer must close descr' when all data are transferred. The return value of producer indicates whether the descriptor is still open.


descr : The descriptor of the subprocess to which the reading end of the pipe is dup'ed. By default stdin.
val from_string : ?pos:int ->
?len:int -> ?epipe:(unit -> unit) -> string -> Unix.file_descr -> bool
from_string ?pos ?len ?epipe s returns a function which can be used as producer argument for add_producer. The data transferred to the subprocess is taken from the string s. After these data are sent, the pipeline is closed.


pos : The position in s where the data slice to transfer begins. By default 0.
len : The length of the data slice to transfer. By default, all bytes from the start position pos to the end of the string are taken.
epipe : This function is called when the pipeline breaks (EPIPE). Default: the empty function. EPIPE exceptions are always caught, and implicitly handled by closing the pipeline.
val from_tstring : ?pos:int ->
?len:int ->
?epipe:(unit -> unit) -> Netsys_types.tstring -> Unix.file_descr -> bool
Same for tagged strings
val from_stream : ?epipe:(unit -> unit) -> string Stream.t -> Unix.file_descr -> bool
from_stream ?epipe s returns a function which can be used as producer argument for add_producer. The data transferred to the subprocess is taken from the string stream s. After these data are sent, the pipeline is closed.


epipe : This function is called when the pipeline breaks (EPIPE). Default: the empty function. EPIPE exceptions are always caught, and implicitly handled by closing the pipeline.
val add_consumer : ?descr:Unix.file_descr ->
consumer:(Unix.file_descr -> bool) ->
command -> job -> unit
Adds a consumer to the job. A consumer transfers data from the subprocess realizing the passed command to the current process. To do so, a pipe is created between the file descriptor descr of the subprocess and another descriptor descr' which is open in the current process. The function consumer is called when data can be read from the pipe. The argument of consumer is reading end of the pipe descr'. This file descriptor is in non-blocking mode. The function consumer must close descr' after EOF is detected. The return value of consumer indicates whether the descriptor is still open.


descr : The descriptor of the subprocess to which the writing end of the pipe is dup'ed. By default stdout.
val to_buffer : Buffer.t -> Unix.file_descr -> bool
to_buffer b returns a function which can be used as consumer argument for add_consumer. The data received from the subprocess is added to the buffer b.
val to_netbuffer : Netbuffer.t -> Unix.file_descr -> bool
Same for a Netbuffer
type group_mode = 
| Same_as_caller (*
The job runs in the same process group as the current process
*)
| Foreground (*
The job runs in a new foreground process group
*)
| Background (*
The job runs in a new background process group
*)
Specifies how the job instance is related to process groups
val run_job : ?mode:group_mode ->
?forward_signals:bool -> job -> job_instance
Invokes the commands of the job such that they run concurrently with the main process.

The function returns a job_instance, i.e. a value recording which processes are started, and how they are related. Furthermore, the function has the side effect of adding the job to the global list of current jobs.

The mode argument specifies whether a new Unix process group is created for the job instance. A process group has the advantage that it is possible to send signals to all processes of the group at once. For example, one can terminate a group by sending SIGTERM to it: All member processes get the signal. Usually, these are not only the subprocesses initially created, but also further processes started by the initial members.

So if it is necessary to send signals to the processes of the job, it will be advantegous to run it in a new process group. However, this also means that signals sent to the current process group are not automatically forwarded to the created process group. For example, if the current process group is terminated, the job will continue running, because it is member of a different process group. One has to explicitly catch and forward signals to avoid wild-running jobs.

The moral of the story is that one should only create new process groups when it is necessary (e.g. the user must be able to stop an action at any time). Furthermore, signal forwarding must be configured.

The Unix shell also allows the programmer to specify process group handling to a certain extent. Normally, commands are executed in the same process group as the caller. The syntax "command &" forces that the command is run in a new background process group. There is another situation when new process groups are created: when a new interactive shell is started the commands are run in new foreground process groups (so the keyboard signals like CTRL-C work).


mode : Specifies the process group handling. By default, the job is executed in the same process group as the current process (Same_as_caller). The value Background causes that a new background process group is started. The value Foreground causes that a new foreground process group is started. For the latter, it is required that there is a controlling terminal (i.e. it does not work for daemons). Any existing foreground process group (there is at most one) is put into the background, but this is not restored when the job is over (the caller must do this). Foreground process groups should be avoided unless you are writing an interactive shell interpreter.
forward_signals : If true, the default, keyboard signals (SIGINT, SIGQUIT) delivered to the current process are forwarded to the job. This has only a meaning if the job is running as background process group. Furthermore, it is required that install_job_handlers has been called to enable signal forwarding.

The function returns normally if at least one process could be started. If no process was startable (i.e. the first command was not startable), an exception is raised. If one or more processes could be started but not all, job_status will return Job_partially_running. The caller should then discard the job and any intermediate result that might already have been produced by the partial job.

When all processes could be started and no other exceptional condition happened, the function sets job_status to Job_running.

class type ['t] job_handler_engine_type = object .. end
This type of engine also returns the job and the job_instance.
class job_engine : Unixqueue.event_system -> job_instance -> [unit] job_handler_engine_type
The job_engine watches the job, and looks whether the processes are finished, and if so, it records the process statuses.
val finish_job : job_instance -> unit
This creates a job_engine internally and runs until it is finished, i.e. until the job has been executed.

In previous version of Ocamlnet there was an optional sys argument. This is gone now. Also, the error handling is different. It is no longer possible to restart finish_job when an error happens.

val call_job : ?mode:group_mode ->
?forward_signals:bool ->
?onerror:(job_instance -> unit) ->
job -> job_instance
Starts the job (see run_job) and waits until it finishes (see finish_job); i.e. call_job = run_job + finish_job. The function returns normally if all processes can be started; you can examine job_status of the result to get the information whether all processes returned the exit code 0.


mode : See run_job
forward_signals : See run_job
onerror : If not all of the processes can be started, the function passed by onerror is invoked. By default, this function calls abandon_job to stop the already running processes. After the onerror function has returned, the original exception is raised again. Fatal error conditions are not caught.
val processes : job_instance -> process list
Returns the processes that have actually been started for this job by run_job; note that the corresponding Unix process group may have additional processes (e.g. indirectly started processes).
exception No_Unix_process_group
Raised by functions referring to Unix process groups when the job has not been started in its own process group.
val process_group_leader : job_instance -> process
Returns the process group leader process. This function is not available for jobs in the mode Same_as_caller.
val process_group_id : job_instance -> int
Returns the Unix ID of the process group as number > 1. This function is not available for jobs in the mode Same_as_caller.
type job_status = 
| Job_running (*
All commands could be started, and at least one process is still running
*)
| Job_partially_running (*
Not all commands could be started, and at least one process is still running
*)
| Job_ok (*
all processes terminated with exit code 0
*)
| Job_error (*
all processes terminated but some abnormally
*)
| Job_abandoned (*
the job has been abandoned (see abandon_job)
*)
Indicates the status of the job
val job_status : job_instance -> job_status
Returns the status. The status may only change after finish_job has been called:

  • after run_job: status is Job_running or Job_partially_running
  • after finish_job: if returning normally: status is Job_ok or Job_error. After an exception happened the other states are possible, too

val kill_process_group : ?signal:int -> job_instance -> unit
Kills the process group if it is still (at least partially) running. This operation is not available if the mode is Same_as_caller (exception No_Unix_process_group).

Note 1: In the Unix terminology, "killing a job" only means to send a signal to the job. So the job may continue running, or it may terminate; in general we do not know this. Because of this, the job will still have an entry in the job list.

Note 2: Because sub-sub-processes are also killed, this function may send the signal to more processes than kill_processes (below). On the other hand, it is possible that sub-processes change their group ID such that it is also possible that this function sends the signal to fewer processes than kill_processes.


signal : The signal number to send (O'Caml signal numbers as used by the Sys module). Default is Sys.sigterm.
val kill_processes : ?signal:int -> job_instance -> unit
Kills the individual processes of the job which are still running.


signal : The signal number to send (O'Caml signal numbers as used by the Sys module). Default is Sys.sigterm.
val cancel_job : ?signal:int -> job_instance -> unit
Tries to get rid of a running job. If the mode is Same_as_caller, the signal is sent to the processes individually. If the mode is Foreground or Background, the signal is sent to the process group corresponding to the job.

This function removes the job from the job list; i.e. it is no longer watched. Because of some magic spells it is guaranteed that the job dies immediately without becoming a zombie (provided you have a SIGCHLD handler).


signal : The signal number to send (O'Caml signal numbers as used by the Sys module). Default is Sys.sigterm.
val abandon_job : ?signal:int -> job_instance -> unit
Deprecated name for cancel_job
exception Already_installed
Raised when the job handlers are already installed
val configure_job_handlers : ?catch_sigint:bool ->
?catch_sigquit:bool ->
?catch_sigterm:bool -> ?catch_sighup:bool -> ?at_exit:bool -> unit -> unit
Configures signal and at_exit handlers for jobs:
  • The keyboard signals SIGINT and SIGQUIT are forwarded to all jobs which are running in the background (and thus are not automatically notified) and want to get such signals (forward_signals).
  • The signals SIGTERM and SIGHUP are (if the handler is installed) forwarded to all dependent processes (regardless whether they are running in their own Unix process group or not, and regardless of forward_signals).
  • The at_exit handler sends a SIGTERM to all dependent processes, too.
In previous versions of Ocamlnet it was also possible to configure catch_sigchld to set whether a SIGCHLD handler is installed. This is now always done.

In previous versions of Ocamlnet there was also a set_sigpipe flag. This flag is gone as a SIGPIPE handler is now always installed.

The handlers are now managed by Netsys_signal. The handlers of this module set the keep_default flag for SIGINT, SIGQUIT, SIGTERM, and SIGHUP, so that the default action for these signals is executed after the forwarding to the child processes is done. By setting another handler in Netsys_signal without that flag this behavior can be overridden.

Note that if an uncaught exception leads to program termination, this situation will not be detected; any running jobs will not be terminated (sorry, this cannot be fixed).

This function sets only which handlers will be installed when install_job_handlers (below) is invoked. The function fails if the handlers are already installed.

Win32: No handlers are installed. It would be desirable to some extent that at least at_exit is honoured, however, this is not yet done.


catch_sigint : whether to install a SIGINT handler (default: true)
catch_sigquit : whether to install a SIGQUIT handler (default: true)
catch_sigterm : whether to install a SIGTERM handler (default: true)
catch_sighup : whether to install a SIGHUP handler (default: true)
at_exit : whether to set the at_exit handler (default: true)
val install_job_handlers : unit -> unit
Installs handlers as configured before. Raises Already_installed if the handlers are already installed.

Removed functions



Removed functions



The functions add_rd_polling and add_wr_polling have been removed. They were added prior to the merge with the equeue library. Use a Unixqueue now, which is much more powerful.

Removed functions



The functions add_rd_polling and add_wr_polling have been removed. They were added prior to the merge with the equeue library. Use a Unixqueue now, which is much more powerful.

Also no longer supported because the type system_handler is gone:

type system_handler

 type process_event 

val wait : 
      ?wnohang:bool ->                     (* default: false *)
      ?wuntraced:bool ->                   (* default: false *)
      ?restart:bool ->                     (* default: false *)
      ?check_interval:float ->             (* default: 0.1 *)
      ?read:(Unix.file_descr list) ->      (* default: [] *)
      ?write:(Unix.file_descr list) ->     (* default: [] *)
      ?except:(Unix.file_descr list) ->    (* default: [] *)
      process list ->
        process_event list
    
val register_job : system_handler -> job_instance -> unit

val iter_job_instances : f:(job_instance -> unit) ->  unit

val watch_for_zombies : unit -> unit

val process_group_expects_signals : job_instance -> bool


Removed functions



The functions add_rd_polling and add_wr_polling have been removed. They were added prior to the merge with the equeue library. Use a Unixqueue now, which is much more powerful.

Also no longer supported because the type system_handler is gone:

type system_handler

 type process_event 

val wait : 
      ?wnohang:bool ->                     (* default: false *)
      ?wuntraced:bool ->                   (* default: false *)
      ?restart:bool ->                     (* default: false *)
      ?check_interval:float ->             (* default: 0.1 *)
      ?read:(Unix.file_descr list) ->      (* default: [] *)
      ?write:(Unix.file_descr list) ->     (* default: [] *)
      ?except:(Unix.file_descr list) ->    (* default: [] *)
      process list ->
        process_event list
    
val register_job : system_handler -> job_instance -> unit

val iter_job_instances : f:(job_instance -> unit) ->  unit

val watch_for_zombies : unit -> unit

val process_group_expects_signals : job_instance -> bool


Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netx509.x509_certificate_from_DER.html0000644000175000017500000004070712731530353024277 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_certificate_from_DER string -> Netx509.x509_certificateocamlnet-4.1.2/doc/html-main/type_Netmime.wrap_mime_header_ro.html0000644000175000017500000004101712731530353023720 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.wrap_mime_header_ro #Netmime.mime_header_ro -> Netmime.mime_headerocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi_types.cgi_argument.html0000644000175000017500000004414312731530353026272 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_types.cgi_argument object
  method charset : string
  method content_type : string
  method content_type_params : (string * Netmime_string.s_param) list
  method filename : string option
  method finalize : unit -> unit
  method name : string
  method open_value_rd : unit -> Netchannels.in_obj_channel
  method open_value_wr : unit -> Netchannels.out_obj_channel
  method representation : Netcgi1_compat.Netcgi_types.representation
  method ro : bool
  method set_value : string -> unit
  method store : Netcgi1_compat.Netcgi_types.store
  method value : string
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.Debug.html0000644000175000017500000004100312731530353021450 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Uq_engines.fmap_engine-c.html0000644000175000017500000004313212731530353022056 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.fmap_engine

Class Uq_engines.fmap_engine

class [['a, 'b]] fmap_engine : 'a #engine -> ('a final_state -> 'b final_state) -> ['b] engine
Similar to map_engine but different calling conventions: The mapping function is called when the argument engine reaches a final state, and this state can be mapped to another final state.

ocamlnet-4.1.2/doc/html-main/type_Netmcore_mutex.html0000644000175000017500000004366312731530353021342 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_mutex sig
  type mutex_type = [ `Errorcheck | `Normal | `Recursive ]
  type mutex
  val dummy : unit -> Netmcore_mutex.mutex
  val create :
    Netmcore_heap.mutator ->
    Netmcore_mutex.mutex_type -> Netmcore_mutex.mutex
  val lock : Netmcore_mutex.mutex -> unit
  val unlock : Netmcore_mutex.mutex -> unit
  val destroy : Netmcore_mutex.mutex -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.qseq_engine.html0000644000175000017500000004157012731530353024274 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.qseq_engine '#Uq_engines_compat.engine ->
('-> '#Uq_engines_compat.engine) -> ['b] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/type_Netsys_global.propagator.html0000644000175000017500000004147412731530353023324 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_global.propagator object
  method propagate : string -> string -> int64
  method update : string -> int64 -> (string * int64) option
end
ocamlnet-4.1.2/doc/html-main/Rpc_proxy.ManagedClient.html0000644000175000017500000011113112731530353021744 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_proxy.ManagedClient

Module Rpc_proxy.ManagedClient

module ManagedClient: sig .. end


Managed clients are Rpc_client clients with the ability to reconnect in the case of errors.

Additional features:

  • they can also be disabled, either based on a time criterion or a customizable hook. This encodes the assumption that failing servers need some time to recover
  • unused connections are closed (driven by a timeout)
  • support for the initial ping after establishing the connection
Initial pings are useful to test whether the connection is really working. Servers normally accept new TCP connections without knowing whether there are resources for processing the connections (i.e. whether there is a process or thread waiting for serving it). Because of this, the client cannot assume that the TCP connection is really up only because the connect system call said the connection is there. The initial ping fixes this problem: The null procedure is once called after the TCP connection has been established. Only when this works the client believes the connection is really up. It is required that mclient_programs is configured with at least one program, and this program must have a procedure number 0 of type void -> void.

In multi-threaded programs, threads must not share managed clients.

Managed clients can be used together with ocamlrpcgen-generated modules. Provided the generated module M_clnt contains the client code for program P and version V, one can do

         module MC = M_clnt.Make'P(Rpc_proxy.ManagedClient)
      

and call RPCs f as in

         let res = MC.V.f mc arg
      

(if mc is the managed client, and arg the argument).

type mclient 
A managed client
type mclient_config = {
   mclient_rcache : Rpc_proxy.ReliabilityCache.rcache; (*
The rcache
*)
   mclient_socket_config : Rpc_client.socket_config; (*
The socket configuration
*)
   mclient_idle_timeout : float; (*
After how many seconds unused connections are closed. A negative value means never. 0 means immediately. A positive value is a point in time in the future.
*)
   mclient_programs : Rpc_program.t list; (*
The programs to bind
*)
   mclient_msg_timeout : float; (*
After how many seconds the reply must have been arrived. A negative value means there is no timeout. 0 means immediately. A positive value is a point in time in the future.
*)
   mclient_msg_timeout_is_fatal : bool; (*
Whether a message timeout is to be considered as fatal error (the client is shut down, and the error counter for the endpoint is increased)
*)
   mclient_exception_handler : (exn -> unit) option; (* *)
   mclient_auth_methods : Rpc_client.auth_method list; (*
Set these authentication methods in the client
*)
   mclient_user_name : string option; (*
The user name for authentication, None = default user
*)
   mclient_initial_ping : bool; (*
Whether to call procedure 0 of the first program after connection establishment (see comments above)
*)
   mclient_max_response_length : int option; (*
The maximum response length. See Rpc_client.set_max_response_length.
*)
   mclient_mstring_factories : Netxdr_mstring.named_mstring_factories option; (*
The factories to use for decoding managed strings
*)
}
exception Service_unavailable
Procedure calls may end with this exception when the reliability cache disables the service
val create_mclient_config : ?rcache:Rpc_proxy.ReliabilityCache.rcache ->
?socket_config:Rpc_client.socket_config ->
?idle_timeout:float ->
?programs:Rpc_program.t list ->
?msg_timeout:float ->
?msg_timeout_is_fatal:bool ->
?exception_handler:(exn -> unit) ->
?auth_methods:Rpc_client.auth_method list ->
?user_name:string option ->
?initial_ping:bool ->
?max_response_length:int ->
?mstring_factories:Netxdr_mstring.named_mstring_factories ->
unit -> mclient_config

Create a config record. The optional arguments set the config components with the same name. The defaults are:
  • rcache: Use the global reliability cache
  • socket_config: Rpc_client.default_socket_config
  • programs: The empty list. It is very advisable to fill this!
  • msg_timeout: (-1), i.e. none
  • msg_timeout_is_fatal: false
  • exception_handler: None
  • auth_methods: empty list
  • user_name: None
  • initial_ping: false
  • max_response_length: None
  • mstring_factories: None

val create_mclient : mclient_config ->
Rpc_client.connector ->
Unixqueue.event_system -> mclient
Create a managed client for this config connecting to this connector. Only Internet and Unix connectors are supported.
type state = [ `Connecting | `Down | `Up of Unix.sockaddr option ] 
The state:
  • `Down: The initial state, and also reached after a socket error, or after one of the shutdown functions is called. Although `Down, there might still some cleanup to do. When RPC functions are called, the client is automatically revived.
  • `Connecting: This state is used while the initial ping is done. It does not reflect whether the client is really TCP-connected. Without initial ping, this state cannot occur.
  • `Up s: The client is (so far known) up and can be used. s is the socket address of the local socket

val mclient_state : mclient -> state
Get the state
val mclient_serial : mclient -> int
Get the serial number of the connection. The serial number is increased when the client is reconnected. If the client is down the serial number of the next connection attempt is returned.
val pending_calls : mclient -> int
Returns the number of pending calls
val event_system : mclient -> Unixqueue.event_system
Return the event system
val shut_down : mclient -> unit
val sync_shutdown : mclient -> unit
val trigger_shutdown : mclient -> (unit -> unit) -> unit
Shut down the managed client. See the corresponding functions Rpc_client.shut_down, Rpc_client.sync_shutdown, and Rpc_client.trigger_shutdown
val record_unavailability : mclient -> unit
Increases the error counter in the reliability cache for this connection. The only effect can be that the error counter exceeds the rcache_threshold so that the server endpoint is disabled for some time. However, this only affects new connections, not existing ones.

For a stricter interpretation of errors see enforce_unavailability.

The error counter is increased anyway when a socket error happens, or an RPC call times out and msg_timeout_is_fatal is set. This function can be used to also interpret other misbehaviors as fatal errors.

val enforce_unavailability : mclient -> unit
Enforces that all pending procedure calls get the Service_unavailable exception, and that the client is shut down. The background is this: When the reliability cache discovers an unavailable port or host, only the new call is stopped with this exception, but older calls remain unaffected. This function can be used to change the policy, and to stop even pending calls.

The difference to trigger_shutdown is that the pending RPC calls get the exception Service_unavailable instead of Rpc_client.Message_lost, and that it is enforced that the shutdown is recorded as fatal error in the reliability cache.

val set_batch_call : mclient -> unit
The next call is a batch call. See Rpc_client.set_batch_call
val rpc_engine : mclient ->
(mclient -> 'a -> ((unit -> 'b) -> unit) -> unit) ->
'a -> 'b Uq_engines.engine
Call an RPC function in engine style:

 let e = rpc_engine mc f_rpc 

where f_rpc is one of the generated client functions (async signature). The engine reaches `Done r when the result r has arrived.

The engine is not abortable (shut the client down instead).

val compare : mclient -> mclient -> int
ManagedClient can be used with Set.Make and Map.Make
include Rpc_client.USE_CLIENT

We implement the USE_CLIENT interface for calling procedures
ocamlnet-4.1.2/doc/html-main/Netstring_tstring.html0000644000175000017500000007456712731530353021041 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstring_tstring

Module Netstring_tstring

module Netstring_tstring: sig .. end
Support module for tagged strings

type '_ tstring_kind = 
| String_kind : string tstring_kind
| Bytes_kind : Bytes.t tstring_kind
| Memory_kind : Netsys_types.memory tstring_kind
GADT for encoding the string type (string/bytes/bigarray)
type 't tstring_ops = {
   kind : 't tstring_kind option;
   length : 't -> int;
   get : 't -> int -> char;
   unsafe_get : 't -> int -> char;
   unsafe_get3 : 't -> int -> int; (*
get 3 chars packed into one int (first char shifted by 16 bits, second char shifted by 8 bits, third char unshifted)
*)
   copy : 't -> 't;
   string : 't -> string; (*
if possible this function does not make a copy
*)
   bytes : 't -> Bytes.t; (*
if possible this function does not make a copy
*)
   sub : 't -> int -> int -> 't;
   substring : 't -> int -> int -> string;
   subbytes : 't -> int -> int -> Bytes.t;
   subpoly : 'u. 'u tstring_kind -> 't -> int -> int -> 'u;
   blit_to_bytes : 't -> int -> Bytes.t -> int -> int -> unit;
   blit_to_memory : 't -> int -> Netsys_types.memory -> int -> int -> unit;
   index_from : 't -> int -> char -> int;
   index_from3 : 't -> int -> int -> char -> char -> char -> int; (*
finds any of three chars. The second int is the search radius
*)
   rindex_from : 't -> int -> char -> int;
   rindex_from3 : 't -> int -> int -> char -> char -> char -> int; (*
finds any of three chars. The second int is the search radius
*)
}
Operations to call on strings
type tstring_ops_box = 
| Tstring_ops_box : 't tstring_kind * 't tstring_ops -> tstring_ops_box
GADT for hiding the type parameter
type tstring_box = 
| Tstring_box : 't tstring_kind * 't tstring_ops * 't -> tstring_box
GADT for hiding the type parameter
type tstring_polybox = 
| Tstring_polybox : 't tstring_ops * 't -> tstring_polybox
GADT for hiding the type parameter. Warning: This GADT does not permit you to recover the kind of string
val string_ops : string tstring_ops
Implementation of the operations for string
val bytes_ops : Bytes.t tstring_ops
Implementation of the operations for bytes
val memory_ops : Netsys_types.memory tstring_ops
Implementation of the operations for memory
val ops_of_tstring : Netsys_types.tstring -> tstring_ops_box
Create a Tstring_ops_box
type 'a with_fun = {
   with_fun : 's. 's tstring_ops -> 's -> 'a;
}
A polymorphic function for strings
val with_tstring : 'a with_fun -> Netsys_types.tstring -> 'a
with_tstring f ts: Calls f.with_fun with the right implementation of the tstring_ops argument
val length_tstring : Netsys_types.tstring -> int
Get the length of a tagged string
val tstring_of_tbuffer : Netsys_types.tbuffer -> Netsys_types.tstring
Get the tagged string of a tagged buffer
val polymorph_string_transformation : (string -> string) ->
's tstring_ops ->
't tstring_kind -> 's -> 't
polymorph_string_transformation f ops kind s: Converts s to a string, runs f on this string, and converts the result to the type demanded by kind
ocamlnet-4.1.2/doc/html-main/type_Netsys_pollset.pollset.html0000644000175000017500000004342712731530353023052 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset.pollset object
  method add : Unix.file_descr -> Netsys_posix.poll_req_events -> unit
  method cancel_wait : bool -> unit
  method dispose : unit -> unit
  method find : Unix.file_descr -> Netsys_posix.poll_req_events
  method remove : Unix.file_descr -> unit
  method wait :
    float ->
    (Unix.file_descr * Netsys_posix.poll_req_events *
     Netsys_posix.poll_act_events)
    list
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_program.html0000644000175000017500000004632112731530353020611 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_program sig
  type t
  val create :
    Netnumber.uint4 ->
    Netnumber.uint4 ->
    Netxdr.xdr_type_system ->
    (string * (Netnumber.uint4 * Netxdr.xdr_type_term * Netxdr.xdr_type_term))
    list -> Rpc_program.t
  val id : Rpc_program.t -> int
  val update :
    ?program_number:Netnumber.uint4 ->
    ?version_number:Netnumber.uint4 -> Rpc_program.t -> Rpc_program.t
  val program_number : Rpc_program.t -> Netnumber.uint4
  val version_number : Rpc_program.t -> Netnumber.uint4
  val null_proc_name : Rpc_program.t -> string option
  val signature :
    Rpc_program.t ->
    string -> Netnumber.uint4 * Netxdr.xdr_type * Netxdr.xdr_type
  val procedure_number : Rpc_program.t -> string -> Netnumber.uint4
end
ocamlnet-4.1.2/doc/html-main/type_Netx509.x509_dn_from_string.html0000644000175000017500000004067712731530353023320 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_dn_from_string string -> Netx509.directory_nameocamlnet-4.1.2/doc/html-main/type_Netsys_win32.html0000644000175000017500000012766312731530353020656 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_win32 sig
  val get_full_path_name : string -> string
  val get_long_path_name : string -> string
  type w32_event
  val create_event : unit -> Netsys_win32.w32_event
  val set_event : Netsys_win32.w32_event -> unit
  val reset_event : Netsys_win32.w32_event -> unit
  val test_event : Netsys_win32.w32_event -> bool
  val event_wait : Netsys_win32.w32_event -> float -> bool
  val event_descr : Netsys_win32.w32_event -> Unix.file_descr
  val wsa_event_select :
    Netsys_win32.w32_event ->
    Unix.file_descr -> Netsys_posix.poll_req_events -> unit
  val wsa_maximum_wait_events : unit -> int
  val wsa_wait_for_multiple_events :
    Netsys_win32.w32_event array -> int -> int option
  val wsa_enum_network_events :
    Unix.file_descr -> Netsys_win32.w32_event -> Netsys_posix.poll_act_events
  val real_select :
    Unix.file_descr list ->
    Unix.file_descr list ->
    Unix.file_descr list ->
    float ->
    Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
  type w32_pipe_server
  type w32_pipe
  type pipe_mode = Pipe_in | Pipe_out | Pipe_duplex
  val rev_mode : Netsys_win32.pipe_mode -> Netsys_win32.pipe_mode
  val create_local_pipe_server :
    string -> Netsys_win32.pipe_mode -> int -> Netsys_win32.w32_pipe_server
  val pipe_listen : Netsys_win32.w32_pipe_server -> int -> unit
  val pipe_accept : Netsys_win32.w32_pipe_server -> Netsys_win32.w32_pipe
  val pipe_connect :
    string -> Netsys_win32.pipe_mode -> Netsys_win32.w32_pipe
  val pipe_pair :
    Netsys_win32.pipe_mode -> Netsys_win32.w32_pipe * Netsys_win32.w32_pipe
  val pipe_read : Netsys_win32.w32_pipe -> Bytes.t -> int -> int -> int
  val pipe_write : Netsys_win32.w32_pipe -> Bytes.t -> int -> int -> int
  val pipe_write_string :
    Netsys_win32.w32_pipe -> string -> int -> int -> int
  val pipe_shutdown : Netsys_win32.w32_pipe -> unit
  val pipe_shutdown_server : Netsys_win32.w32_pipe_server -> unit
  val pipe_connect_event :
    Netsys_win32.w32_pipe_server -> Netsys_win32.w32_event
  val pipe_rd_event : Netsys_win32.w32_pipe -> Netsys_win32.w32_event
  val pipe_wr_event : Netsys_win32.w32_pipe -> Netsys_win32.w32_event
  val pipe_wait_connect : Netsys_win32.w32_pipe_server -> float -> bool
  val pipe_wait_rd : Netsys_win32.w32_pipe -> float -> bool
  val pipe_wait_wr : Netsys_win32.w32_pipe -> float -> bool
  val pipe_server_descr : Netsys_win32.w32_pipe_server -> Unix.file_descr
  val pipe_descr : Netsys_win32.w32_pipe -> Unix.file_descr
  val pipe_name : Netsys_win32.w32_pipe -> string
  val pipe_server_name : Netsys_win32.w32_pipe_server -> string
  val pipe_mode : Netsys_win32.w32_pipe -> Netsys_win32.pipe_mode
  val pipe_server_mode :
    Netsys_win32.w32_pipe_server -> Netsys_win32.pipe_mode
  val unpredictable_pipe_name : unit -> string
  type w32_input_thread
  val create_input_thread : Unix.file_descr -> Netsys_win32.w32_input_thread
  val input_thread_event :
    Netsys_win32.w32_input_thread -> Netsys_win32.w32_event
  val input_thread_read :
    Netsys_win32.w32_input_thread -> Bytes.t -> int -> int -> int
  val cancel_input_thread : Netsys_win32.w32_input_thread -> unit
  val input_thread_proxy_descr :
    Netsys_win32.w32_input_thread -> Unix.file_descr
  type w32_output_thread
  val create_output_thread :
    Unix.file_descr -> Netsys_win32.w32_output_thread
  val output_thread_event :
    Netsys_win32.w32_output_thread -> Netsys_win32.w32_event
  val output_thread_write :
    Netsys_win32.w32_output_thread -> Bytes.t -> int -> int -> int
  val output_thread_write_string :
    Netsys_win32.w32_output_thread -> string -> int -> int -> int
  val close_output_thread : Netsys_win32.w32_output_thread -> unit
  val cancel_output_thread : Netsys_win32.w32_output_thread -> unit
  val output_thread_proxy_descr :
    Netsys_win32.w32_output_thread -> Unix.file_descr
  type create_process_option =
      CP_change_directory of string
    | CP_set_env of string
    | CP_std_handles of Unix.file_descr * Unix.file_descr * Unix.file_descr
    | CP_create_console
    | CP_detach_from_console
    | CP_inherit_console
    | CP_inherit_or_create_console
    | CP_unicode_environment
    | CP_ansi_environment
    | CP_new_process_group
    | CP_inherit_process_group
  val cp_set_env : string array -> Netsys_win32.create_process_option
  val search_path : string option -> string -> string option -> string
  type w32_process
  val create_process :
    string ->
    string ->
    Netsys_win32.create_process_option list -> Netsys_win32.w32_process
  val close_process : Netsys_win32.w32_process -> unit
  val get_process_status :
    Netsys_win32.w32_process -> Unix.process_status option
  val as_process_event : Netsys_win32.w32_process -> Netsys_win32.w32_event
  val emulated_pid : Netsys_win32.w32_process -> int
  val win_pid : Netsys_win32.w32_process -> int
  val process_descr : Netsys_win32.w32_process -> Unix.file_descr
  val terminate_process : Netsys_win32.w32_process -> unit
  val has_console : unit -> bool
  val is_console : Unix.file_descr -> bool
  val get_console_input : unit -> Unix.file_descr
  val get_console_output : unit -> Unix.file_descr
  type w32_console_attr = {
    mutable cursor_x : int;
    mutable cursor_y : int;
    mutable cursor_size : int;
    mutable cursor_visible : bool;
    mutable text_attr : int;
  }
  type w32_console_info = { mutable width : int; mutable height : int; }
  val get_console_attr : unit -> Netsys_win32.w32_console_attr
  val set_console_attr : Netsys_win32.w32_console_attr -> unit
  val get_console_info : unit -> Netsys_win32.w32_console_info
  val fg_blue : int
  val fg_green : int
  val fg_red : int
  val fg_intensity : int
  val bg_blue : int
  val bg_green : int
  val bg_red : int
  val bg_intensity : int
  type w32_console_mode = {
    mutable enable_echo_input : bool;
    mutable enable_insert_mode : bool;
    mutable enable_line_input : bool;
    mutable enable_processed_input : bool;
    mutable enable_quick_edit_mode : bool;
    mutable enable_processed_output : bool;
    mutable enable_wrap_at_eol_output : bool;
  }
  val get_console_mode : unit -> Netsys_win32.w32_console_mode
  val set_console_mode : Netsys_win32.w32_console_mode -> unit
  val init_console_codepage : unit -> unit
  val clear_until_end_of_line : unit -> unit
  val clear_until_end_of_screen : unit -> unit
  val clear_console : unit -> unit
  val get_active_code_page : unit -> int
  type w32_object =
      W32_event of Netsys_win32.w32_event
    | W32_pipe of Netsys_win32.w32_pipe
    | W32_pipe_server of Netsys_win32.w32_pipe_server
    | W32_process of Netsys_win32.w32_process
    | W32_input_thread of Netsys_win32.w32_input_thread
    | W32_output_thread of Netsys_win32.w32_output_thread
  val lookup : Unix.file_descr -> Netsys_win32.w32_object
  val lookup_event : Unix.file_descr -> Netsys_win32.w32_event
  val lookup_pipe : Unix.file_descr -> Netsys_win32.w32_pipe
  val lookup_pipe_server : Unix.file_descr -> Netsys_win32.w32_pipe_server
  val lookup_process : Unix.file_descr -> Netsys_win32.w32_process
  val lookup_input_thread : Unix.file_descr -> Netsys_win32.w32_input_thread
  val lookup_output_thread :
    Unix.file_descr -> Netsys_win32.w32_output_thread
  val unregister : Unix.file_descr -> unit
  val test_close_on_exec : Unix.file_descr -> bool
  val modify_close_on_exec : Unix.file_descr -> bool -> unit
  val is_crt_fd : Unix.file_descr -> int -> bool
  val fill_random : Bytes.t -> unit
  module Debug :
    sig
      val enable : bool Pervasives.ref
      val debug_c_wrapper : bool -> unit
    end
  val input_thread_descr : Netsys_win32.w32_input_thread -> Unix.file_descr
  val output_thread_descr : Netsys_win32.w32_output_thread -> Unix.file_descr
  val gc_proxy : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/Netmech_digest_http.html0000644000175000017500000004504012731530353021253 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http

Module Netmech_digest_http

module Netmech_digest_http: sig .. end
Digest authentication for HTTP

module Digest: Nethttp.HTTP_CLIENT_MECHANISM 
This is the standard HTTP digest authentication mechanism (see RFCs 2069, 2617, 7616).
module Digest_mutual: Nethttp.HTTP_CLIENT_MECHANISM 
This is the standard HTTP digest authentication mechanism (see RFCs 2069, 2617, 7616).
module type PROFILE = sig .. end
module Make_digest: 
Create a custom version of the digest mechanism
ocamlnet-4.1.2/doc/html-main/type_Netmcore_heap.Debug.html0000644000175000017500000004100612731530353022127 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_heap.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netftp_data_endpoint.write_out_record_channel.html0000644000175000017500000004122212731530353027530 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.write_out_record_channel repr:Netftp_data_endpoint.text_data_repr ->
Netchannels.out_obj_channel -> Netftp_data_endpoint.out_record_channel
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.html0000644000175000017500000030111712731530353021773 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat sig
  exception Closed_channel
  exception Broken_communication
  exception Watchdog_timeout
  exception Timeout
  exception Addressing_method_not_supported
  exception Cancelled
  type 't engine_state =
      [ `Aborted | `Done of '| `Error of exn | `Working of int ]
  type 't final_state = [ `Aborted | `Done of '| `Error of exn ]
  val string_of_state : 'Uq_engines_compat.engine_state -> string
  class type ['t] engine =
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        ('Uq_engines_compat.engine -> bool) -> unit
      method state : 'Uq_engines_compat.engine_state
    end
  class ['t] delegate_engine : '#Uq_engines_compat.engine -> ['t] engine
  val when_state :
    ?is_done:('-> unit) ->
    ?is_error:(exn -> unit) ->
    ?is_aborted:(unit -> unit) ->
    ?is_progressing:(int -> unit) -> '#Uq_engines_compat.engine -> unit
  class ['a] signal_engine :
    Unixqueue.event_system ->
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification : ('a engine -> bool) -> unit
      method signal : 'Uq_engines_compat.final_state -> unit
      method state : 'a engine_state
    end
  val signal_engine :
    Unixqueue.event_system ->
    'Uq_engines_compat.engine * ('Uq_engines_compat.final_state -> unit)
  class ['a, 'b] map_engine :
    map_done:('-> 'Uq_engines_compat.engine_state) ->
    ?map_error:(exn -> 'Uq_engines_compat.engine_state) ->
    ?map_aborted:(unit -> 'Uq_engines_compat.engine_state) ->
    ?propagate_working:bool -> '#Uq_engines_compat.engine -> ['b] engine
  val map_engine :
    map_done:('-> 'Uq_engines_compat.engine_state) ->
    ?map_error:(exn -> 'Uq_engines_compat.engine_state) ->
    ?map_aborted:(unit -> 'Uq_engines_compat.engine_state) ->
    ?propagate_working:bool ->
    '#Uq_engines_compat.engine -> 'Uq_engines_compat.engine
  class ['a, 'b] fmap_engine :
    '#Uq_engines_compat.engine ->
    ('Uq_engines_compat.final_state -> 'Uq_engines_compat.final_state) ->
    ['b] engine
  val fmap_engine :
    '#Uq_engines_compat.engine ->
    ('Uq_engines_compat.final_state -> 'Uq_engines_compat.final_state) ->
    'Uq_engines_compat.engine
  class ['a] meta_engine :
    '#Uq_engines_compat.engine -> ['Uq_engines_compat.final_state] engine
  val meta_engine :
    '#Uq_engines_compat.engine ->
    'Uq_engines_compat.final_state Uq_engines_compat.engine
  class ['t] epsilon_engine :
    'Uq_engines_compat.engine_state ->
    Unixqueue.event_system -> ['t] engine
  val epsilon_engine :
    'Uq_engines_compat.engine_state ->
    Unixqueue.event_system -> 'Uq_engines_compat.engine
  class ['a, 'b] seq_engine :
    '#Uq_engines_compat.engine ->
    ('-> '#Uq_engines_compat.engine) -> ['b] engine
  val seq_engine :
    '#Uq_engines_compat.engine ->
    ('-> '#Uq_engines_compat.engine) -> 'Uq_engines_compat.engine
  class ['a, 'b] qseq_engine :
    '#Uq_engines_compat.engine ->
    ('-> '#Uq_engines_compat.engine) -> ['b] engine
  val qseq_engine :
    '#Uq_engines_compat.engine ->
    ('-> '#Uq_engines_compat.engine) -> 'Uq_engines_compat.engine
  class ['a] stream_seq_engine :
    '->
    ('-> '#Uq_engines_compat.engine) Stream.t ->
    Unixqueue.event_system -> ['a] engine
  val stream_seq_engine :
    '->
    ('-> '#Uq_engines_compat.engine) Stream.t ->
    Unixqueue.event_system -> 'Uq_engines_compat.engine
  class ['a, 'b] sync_engine :
    '#Uq_engines_compat.engine ->
    '#Uq_engines_compat.engine -> ['a * 'b] engine
  val sync_engine :
    '#Uq_engines_compat.engine ->
    '#Uq_engines_compat.engine -> ('a * 'b) Uq_engines_compat.engine
  class ['a, 'b] msync_engine :
    '#Uq_engines_compat.engine list ->
    ('-> '-> 'b) -> '-> Unixqueue.event_system -> ['b] engine
  val msync_engine :
    '#Uq_engines_compat.engine list ->
    ('-> '-> 'b) ->
    '-> Unixqueue.event_system -> 'Uq_engines_compat.engine
  class ['a] delay_engine :
    float ->
    (unit -> '#Uq_engines_compat.engine) ->
    Unixqueue.event_system -> ['a] engine
  val delay_engine :
    float ->
    (unit -> '#Uq_engines_compat.engine) ->
    Unixqueue.event_system -> 'Uq_engines_compat.engine
  class ['a] timeout_engine :
    float -> exn -> 'Uq_engines_compat.engine -> ['a] engine
  val timeout_engine :
    float ->
    exn -> 'Uq_engines_compat.engine -> 'Uq_engines_compat.engine
  class watchdog : float -> '#Uq_engines_compat.engine -> [unit] engine
  val watchdog :
    float -> '#Uq_engines_compat.engine -> unit Uq_engines_compat.engine
  class type ['a] serializer_t =
    object
      method serialized :
        (Unixqueue.event_system -> 'Uq_engines_compat.engine) ->
        'Uq_engines_compat.engine
    end
  class ['a] serializer : Unixqueue.event_system -> ['a] serializer_t
  val serializer :
    Unixqueue.event_system -> 'Uq_engines_compat.serializer_t
  class type ['a] prioritizer_t =
    object
      method prioritized :
        (Unixqueue.event_system -> 'Uq_engines_compat.engine) ->
        int -> 'Uq_engines_compat.engine
    end
  class ['a] prioritizer : Unixqueue.event_system -> ['a] prioritizer_t
  val prioritizer :
    Unixqueue.event_system -> 'Uq_engines_compat.prioritizer_t
  class type ['a] cache_t =
    object
      method abort : unit -> unit
      method get_engine : unit -> 'Uq_engines_compat.engine
      method get_opt : unit -> 'a option
      method invalidate : unit -> unit
      method put : '-> unit
    end
  class ['a] cache :
    (Unixqueue.event_system -> 'Uq_engines_compat.engine) ->
    Unixqueue.event_system -> ['a] cache_t
  val cache :
    (Unixqueue.event_system -> 'Uq_engines_compat.engine) ->
    Unixqueue.event_system -> 'Uq_engines_compat.cache_t
  class ['t] engine_mixin :
    'Uq_engines_compat.engine_state ->
    Unixqueue.event_system ->
    object
      method event_system : Unixqueue.event_system
      method private notify : unit -> unit
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        ('Uq_engines_compat.engine -> bool) -> unit
      method private set_state : 'Uq_engines_compat.engine_state -> unit
      method state : 'Uq_engines_compat.engine_state
    end
  module Operators :
    sig
      val ( ++ ) :
        '#Uq_engines_compat.engine ->
        ('-> '#Uq_engines_compat.engine) -> 'Uq_engines_compat.engine
      val ( >> ) :
        '#Uq_engines_compat.engine ->
        ('Uq_engines_compat.final_state -> 'Uq_engines_compat.final_state) ->
        'Uq_engines_compat.engine
      val eps_e :
        'Uq_engines_compat.engine_state ->
        Unixqueue.event_system -> 'Uq_engines_compat.engine
    end
  class poll_engine :
    ?extra_match:(exn -> bool) ->
    (Unixqueue.operation * float) list ->
    Unixqueue.event_system ->
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method group : Unixqueue.group
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        (Unixqueue.event engine -> bool) -> unit
      method restart : unit -> unit
      method state : Unixqueue.event engine_state
    end
  class ['a] input_engine :
    (Unix.file_descr -> 'a) ->
    Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
  class ['a] output_engine :
    (Unix.file_descr -> 'a) ->
    Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
  class poll_process_engine :
    ?period:float ->
    pid:int -> Unixqueue.event_system -> [Unix.process_status] engine
  class type async_out_channel =
    object
      method can_output : bool
      method close_out : unit -> unit
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method pos_out : int
      method request_notification : (unit -> bool) -> unit
    end
  class type async_in_channel =
    object
      method can_input : bool
      method close_in : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method pos_in : int
      method request_notification : (unit -> bool) -> unit
    end
  class pseudo_async_out_channel :
    #Netchannels.raw_out_channel -> async_out_channel
  class pseudo_async_in_channel :
    #Netchannels.raw_in_channel -> async_in_channel
  class receiver :
    src:Unix.file_descr ->
    dst:#Uq_engines_compat.async_out_channel ->
    ?close_src:bool ->
    ?close_dst:bool -> Unixqueue.event_system -> [unit] engine
  class sender :
    src:#Uq_engines_compat.async_in_channel ->
    dst:Unix.file_descr ->
    ?close_src:bool ->
    ?close_dst:bool -> Unixqueue.event_system -> [unit] engine
  class type async_out_channel_engine =
    object
      method abort : unit -> unit
      method can_output : bool
      method close_out : unit -> unit
      method event_system : Unixqueue.event_system
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method pos_out : int
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification : (unit engine -> bool) -> unit
      method state : unit engine_state
    end
  class type async_in_channel_engine =
    object
      method abort : unit -> unit
      method can_input : bool
      method close_in : unit -> unit
      method event_system : Unixqueue.event_system
      method input : Bytes.t -> int -> int -> int
      method pos_in : int
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification : (unit engine -> bool) -> unit
      method state : unit engine_state
    end
  class output_async_descr :
    dst:Unix.file_descr ->
    ?buffer_size:int ->
    ?close_dst:bool -> Unixqueue.event_system -> async_out_channel_engine
  class input_async_descr :
    src:Unix.file_descr ->
    ?buffer_size:int ->
    ?close_src:bool -> Unixqueue.event_system -> async_in_channel_engine
  type copy_task =
      [ `Bidirectional of Unix.file_descr * Unix.file_descr
      | `Tridirectional of
          Unix.file_descr * Unix.file_descr * Unix.file_descr
      | `Uni_socket of Unix.file_descr * Unix.file_descr
      | `Unidirectional of Unix.file_descr * Unix.file_descr ]
  class copier :
    Uq_engines_compat.copy_task -> Unixqueue.event_system -> [unit] engine
  type inetspec =
      [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
      | `Sock_inet_byname of Unix.socket_type * string * int ]
  type sockspec =
      [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
      | `Sock_inet_byname of Unix.socket_type * string * int
      | `Sock_unix of Unix.socket_type * string ]
  val sockspec_of_sockaddr :
    Unix.socket_type -> Unix.sockaddr -> Uq_engines_compat.sockspec
  val sockspec_of_socksymbol :
    Unix.socket_type -> Netsockaddr.socksymbol -> Uq_engines_compat.sockspec
  type connect_address =
      [ `Command of string * (int -> Unixqueue.event_system -> unit)
      | `Socket of
          Uq_engines_compat.sockspec * Uq_engines_compat.connect_options
      | `W32_pipe of Netsys_win32.pipe_mode * string ]
  and connect_options =
    Uq_engines.connect_options = {
    conn_bind : Uq_engines_compat.sockspec option;
  }
  val default_connect_options : Uq_engines_compat.connect_options
  type connect_status =
      [ `Command of Unix.file_descr * int
      | `Socket of Unix.file_descr * Uq_engines_compat.sockspec
      | `W32_pipe of Unix.file_descr ]
  val client_endpoint : Uq_engines_compat.connect_status -> Unix.file_descr
  val client_socket : Uq_engines_compat.connect_status -> Unix.file_descr
  class type client_endpoint_connector =
    object
      method connect :
        Uq_engines_compat.connect_address ->
        Unixqueue.event_system ->
        Uq_engines_compat.connect_status Uq_engines_compat.engine
    end
  class type client_socket_connector = client_endpoint_connector
  val connector :
    ?proxy:#Uq_engines_compat.client_socket_connector ->
    Uq_engines_compat.connect_address ->
    Unixqueue.event_system ->
    Uq_engines_compat.connect_status Uq_engines_compat.engine
  type listen_options =
    Uq_engines.listen_options = {
    lstn_backlog : int;
    lstn_reuseaddr : bool;
  }
  type listen_address =
      [ `Socket of
          Uq_engines_compat.sockspec * Uq_engines_compat.listen_options
      | `W32_pipe of
          Netsys_win32.pipe_mode * string * Uq_engines_compat.listen_options ]
  val default_listen_options : Uq_engines_compat.listen_options
  class type server_endpoint_acceptor =
    object
      method accept :
        unit ->
        (Unix.file_descr * Uq_engines_compat.inetspec option)
        Uq_engines_compat.engine
      method multiple_connections : bool
      method server_address : Uq_engines_compat.connect_address
      method shut_down : unit -> unit
    end
  class type server_socket_acceptor = server_endpoint_acceptor
  class direct_acceptor :
    ?close_on_shutdown:bool ->
    ?preclose:(unit -> unit) ->
    Unix.file_descr -> Unixqueue.event_system -> server_endpoint_acceptor
  class direct_socket_acceptor :
    Unix.file_descr -> Unixqueue.event_system -> server_endpoint_acceptor
  class type server_endpoint_listener =
    object
      method listen :
        Uq_engines_compat.listen_address ->
        Unixqueue.event_system ->
        Uq_engines_compat.server_endpoint_acceptor Uq_engines_compat.engine
    end
  class type server_socket_listener = server_endpoint_listener
  val listener :
    ?proxy:#Uq_engines_compat.server_socket_listener ->
    Uq_engines_compat.listen_address ->
    Unixqueue.event_system ->
    Uq_engines_compat.server_socket_acceptor Uq_engines_compat.engine
  type datagram_type = [ `Inet6_udp | `Inet_udp | `Unix_dgram ]
  class type wrapped_datagram_socket =
    object
      method datagram_type : Uq_engines_compat.datagram_type
      method descriptor : Unix.file_descr
      method recvfrom :
        Bytes.t ->
        int -> int -> Unix.msg_flag list -> int * Uq_engines_compat.sockspec
      method sendto :
        Bytes.t ->
        int -> int -> Unix.msg_flag list -> Uq_engines_compat.sockspec -> int
      method shut_down : unit -> unit
      method socket_domain : Unix.socket_domain
      method socket_protocol : int
      method socket_type : Unix.socket_type
    end
  class type datagram_socket_provider =
    object
      method create_datagram_socket :
        Uq_engines_compat.datagram_type ->
        Unixqueue.event_system ->
        Uq_engines_compat.wrapped_datagram_socket Uq_engines_compat.engine
    end
  val datagram_provider :
    ?proxy:#Uq_engines_compat.datagram_socket_provider ->
    Uq_engines_compat.datagram_type ->
    Unixqueue.event_system ->
    Uq_engines_compat.wrapped_datagram_socket Uq_engines_compat.engine
  class type multiplex_controller =
    object
      method alive : bool
      method cancel_reading : unit -> unit
      method cancel_shutting_down : unit -> unit
      method cancel_writing : unit -> unit
      method event_system : Unixqueue.event_system
      method inactivate : unit -> unit
      method mem_supported : bool
      method read_eof : bool
      method reading : bool
      method shutting_down : bool
      method start_mem_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_mem_writing :
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_shutting_down :
        ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
      method start_writing :
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_writing_eof :
        when_done:(exn option -> unit) -> unit -> unit
      method supports_half_open_connection : bool
      method tls_session : (string * string) option
      method tls_session_props : Nettls_support.tls_session_props option
      method tls_stashed_endpoint : unit -> exn
      method writing : bool
      method wrote_eof : bool
    end
  exception Mem_not_supported
  val create_multiplex_controller_for_connected_socket :
    ?close_inactive_descr:bool ->
    ?preclose:(unit -> unit) ->
    ?supports_half_open_connection:bool ->
    ?timeout:float * exn ->
    Unix.file_descr ->
    Unixqueue.unix_event_system -> Uq_engines_compat.multiplex_controller
  class type datagram_multiplex_controller =
    object
      method alive : bool
      method cancel_reading : unit -> unit
      method cancel_shutting_down : unit -> unit
      method cancel_writing : unit -> unit
      method event_system : Unixqueue.event_system
      method inactivate : unit -> unit
      method mem_supported : bool
      method read_eof : bool
      method reading : bool
      method received_from : Unix.sockaddr
      method send_to : Unix.sockaddr -> unit
      method shutting_down : bool
      method start_mem_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_mem_writing :
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_shutting_down :
        ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
      method start_writing :
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_writing_eof :
        when_done:(exn option -> unit) -> unit -> unit
      method supports_half_open_connection : bool
      method tls_session : (string * string) option
      method tls_session_props : Nettls_support.tls_session_props option
      method tls_stashed_endpoint : unit -> exn
      method writing : bool
      method wrote_eof : bool
    end
  val create_multiplex_controller_for_datagram_socket :
    ?close_inactive_descr:bool ->
    ?preclose:(unit -> unit) ->
    ?timeout:float * exn ->
    Unix.file_descr ->
    Unixqueue.unix_event_system ->
    Uq_engines_compat.datagram_multiplex_controller
  type onshutdown_out_spec =
      [ `Action of
          Uq_engines_compat.async_out_channel_engine ->
          Uq_engines_compat.multiplex_controller ->
          unit Uq_engines_compat.engine_state -> unit
      | `Ignore
      | `Initiate_shutdown ]
  type onshutdown_in_spec =
      [ `Action of
          Uq_engines_compat.async_in_channel_engine ->
          Uq_engines_compat.multiplex_controller ->
          unit Uq_engines_compat.engine_state -> unit
      | `Ignore
      | `Initiate_shutdown ]
  class output_async_mplex :
    ?onclose:[ `Ignore | `Write_eof ] ->
    ?onshutdown:Uq_engines_compat.onshutdown_out_spec ->
    ?buffer_size:int ->
    Uq_engines_compat.multiplex_controller -> async_out_channel_engine
  class input_async_mplex :
    ?onshutdown:Uq_engines_compat.onshutdown_in_spec ->
    ?buffer_size:int ->
    Uq_engines_compat.multiplex_controller -> async_in_channel_engine
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Uq_tcl.html0000644000175000017500000004420412731530353016522 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_tcl

Module Uq_tcl

module Uq_tcl: sig .. end
Integration with the labltk event system


Integration with the labltk event system

Integration with the labltk event system

This module provides integration of Unixqueue event systems with the TCL event queue (and, as a consequence, with the labltk event queue).

Integration with the labltk event system

This module provides integration of Unixqueue event systems with the TCL event queue (and, as a consequence, with the labltk event queue).

OPAM users: Note that this library is currently unavailable.
type runner = Unixqueue.event_system -> (unit -> unit) -> unit 
class tcl_event_system : ?run:runner -> unit -> Unixqueue.event_system
This class is an alternate implementation of the Unixqueue event systems for the TCL event loop.
ocamlnet-4.1.2/doc/html-main/Netchannels.lift_rec_in_channel-c.html0000644000175000017500000004406712731530353023730 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.lift_rec_in_channel

Class Netchannels.lift_rec_in_channel

class lift_rec_in_channel : ?start_pos_in:int -> rec_in_channel -> in_obj_channel
This class implements pos_in and the methods from compl_in_channel by calling the methods of rec_in_channel. There is no additional buffering.

The performance of the method input_line is very bad (consider to override it, e.g. by enhanced_input_line as defined below).

The method pos_in is implemented by counting the number of octets read by the input method.


start_pos_in : The initial value of the counter for pos_in. Defaults to 0.

ocamlnet-4.1.2/doc/html-main/type_Netcgi_common.Cookie.html0000644000175000017500000005536312731530353022335 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.Cookie sig
  type t = Nethttp.Cookie.t
  val make :
    ?max_age:int ->
    ?domain:string ->
    ?path:string ->
    ?secure:bool ->
    ?comment:string ->
    ?comment_url:string ->
    ?ports:int list -> string -> string -> Netcgi_common.Cookie.t
  val name : Netcgi_common.Cookie.t -> string
  val value : Netcgi_common.Cookie.t -> string
  val max_age : Netcgi_common.Cookie.t -> int option
  val domain : Netcgi_common.Cookie.t -> string option
  val path : Netcgi_common.Cookie.t -> string option
  val secure : Netcgi_common.Cookie.t -> bool
  val comment : Netcgi_common.Cookie.t -> string
  val comment_url : Netcgi_common.Cookie.t -> string
  val ports : Netcgi_common.Cookie.t -> int list option
  val set_value : Netcgi_common.Cookie.t -> string -> unit
  val set_max_age : Netcgi_common.Cookie.t -> int option -> unit
  val set_domain : Netcgi_common.Cookie.t -> string option -> unit
  val set_path : Netcgi_common.Cookie.t -> string option -> unit
  val set_secure : Netcgi_common.Cookie.t -> bool -> unit
  val set_comment : Netcgi_common.Cookie.t -> string -> unit
  val set_comment_url : Netcgi_common.Cookie.t -> string -> unit
  val set_ports : Netcgi_common.Cookie.t -> int list option -> unit
  val set : #Netmime.mime_header -> Netcgi_common.Cookie.t list -> unit
  val get : #Netmime.mime_header -> Netcgi_common.Cookie.t list
  val of_record : Nethttp.cookie -> Netcgi_common.Cookie.t
  val to_record : Netcgi_common.Cookie.t -> Nethttp.cookie
end
ocamlnet-4.1.2/doc/html-main/Netmech_scram.AES_CTS.html0000644000175000017500000004466112731530353021172 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram.AES_CTS

Module Netmech_scram.AES_CTS

module AES_CTS: sig .. end
This module implements AES in Ciphertext Stealing mode (see RFC 3962)

val c : int
val m : int
val encrypt : string -> string -> string
val encrypt_mstrings : string -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
val decrypt : string -> string -> string
val decrypt_mstrings : string -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
val tests : (string * string * string) list
val run_tests : unit -> bool
val run_mtests : unit -> bool
ocamlnet-4.1.2/doc/html-main/type_Netplex_cenv.Make_lever.html0000644000175000017500000004252712731530353023045 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.Make_lever functor (T : FUN_TYPE->
  sig
    type s = T.s
    type r = T.r
    type t = s -> r
    val register :
      Netplex_types.controller -> (Netplex_types.controller -> t) -> t
  end
ocamlnet-4.1.2/doc/html-main/type_Netmcore_matrix.html0000644000175000017500000005534112731530353021500 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_matrix sig
  type ('e, 'h) sarray2
  type ('e, 'h) sarray2_descr
  val create :
    Netmcore.res_id ->
    int -> 'e array array -> '-> ('e, 'h) Netmcore_matrix.sarray2
  val make :
    Netmcore.res_id ->
    int -> int -> '-> '-> ('e, 'h) Netmcore_matrix.sarray2
  val init :
    Netmcore.res_id ->
    int ->
    int -> (int -> int -> 'e) -> '-> ('e, 'h) Netmcore_matrix.sarray2
  val set : ('e, 'a) Netmcore_matrix.sarray2 -> int -> int -> '-> unit
  val get_ro : ('e, 'a) Netmcore_matrix.sarray2 -> int -> int -> 'e
  val get_p :
    ('e, 'b) Netmcore_matrix.sarray2 -> int -> int -> ('-> 'a) -> 'a
  val get_c : ('e, 'a) Netmcore_matrix.sarray2 -> int -> int -> 'e
  val dim : ('a, 'b) Netmcore_matrix.sarray2 -> int * int
  val header : ('a, 'h) Netmcore_matrix.sarray2 -> 'h
  val deref : ('e, 'a) Netmcore_matrix.sarray2 -> 'e array array
  val heap : ('a, 'b) Netmcore_matrix.sarray2 -> Obj.t Netmcore_heap.heap
  val descr_of_sarray2 :
    ('e, 'h) Netmcore_matrix.sarray2 ->
    ('e, 'h) Netmcore_matrix.sarray2_descr
  val sarray2_of_descr :
    Netmcore.res_id ->
    ('e, 'h) Netmcore_matrix.sarray2_descr ->
    ('e, 'h) Netmcore_matrix.sarray2
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.seq_engine.html0000644000175000017500000004153312731530353022547 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.seq_engine '#Uq_engines.engine ->
('-> '#Uq_engines.engine) -> ['b] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/Netsmtp.client-c.html0000644000175000017500000005602012731530353020421 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsmtp.client

Class Netsmtp.client

class client : Netchannels.in_obj_channel -> Netchannels.out_obj_channel -> object .. end

method helo : ?host:string -> unit -> string list
Sends an EHLO command to the server. The optional argument ?host defaults to the default hostname of the machine. This function returns the ESMTP lines returned by the server.

If EHLO is not supported, the method automatically falls back to HELO.

EHLO is specified in RFC 1869.

method helo_response : string list
The response from the last HELO or EHLO
method auth : Netsys_sasl.sasl_mechanism ->
string ->
string -> Netsys_sasl.credentials -> (string * string * bool) list -> unit
auth mech user authz creds params: Performs a SASL authentication using the AUTH command. See Netsys_sasl.Client.create_session for details.

Example:

client # auth
  (module Netmech_digest_sasl.DIGEST_MD5)
  "user"
  ""
  [ "password", "sEcReT", [] ]
  []
   

method authenticated : bool
Whether the auth command ran successfully
method mail : string -> unit
Performs a MAIL FROM command. The string argument is the mail address (without < >) of the sender.
method rcpt : string -> unit
Performs a RCPT TO command. the string argument is one of the mail address the mail has to be sent to. You have to use that function for each recipient of the mail.

If the server returns a 551 error (user relocated, see RFC 2821, section 3.4), the relocated adress is silently used, and the error is not raised

method data : Netchannels.in_obj_channel -> unit
This method really send the mail. Do not issue that command without having used mail once, and at least rcpt once too
method rset : unit -> unit
Reset the current transaction
method expn : string -> string list option
Expand command : expn list will try to expand the Mailing list list. If the list cannot be Expanded (reply 252) then None is returned.
method help : unit -> string list
Performs the Help command. Returns the server multiline answer.
method noop : unit -> unit
NOOP : does nothing, keeps the connection alive.
method quit : unit -> unit
Requests the server to end this session.
method close : unit -> unit
Closes the file descriptors
method starttls : peer_name:string option -> Netsys_crypto_types.tls_config -> unit
Sends STARTTLS, and negotiates a secure connection. This should only be done after EHLO, and only if "STARTTLS" is among the returned strings.

STARTTLS is specified in RFC 3207.

Note that it is meaningful to submit EHLO again after STARTTLS, as the server may now enable more options.

method command : string -> int * string list
Sends this command, and returns the status code and the status texts.
method tls_endpoint : Netsys_crypto_types.tls_endpoint option
Returns the TLS endpoint (after STARTTLS)
method tls_session_props : Nettls_support.tls_session_props option
Returns the TLS session properties (after STARTTLS)
method gssapi_props : Netsys_gssapi.client_props option
Returns GSSAPI properties, if available
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.SCRAM_SHA1.html0000644000175000017500000004066412731530353023554 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SCRAM_SHA1 Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.multiplex_controller.html0000644000175000017500000005213612731530353026264 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.multiplex_controller object
  method alive : bool
  method cancel_reading : unit -> unit
  method cancel_shutting_down : unit -> unit
  method cancel_writing : unit -> unit
  method event_system : Unixqueue.event_system
  method inactivate : unit -> unit
  method mem_supported : bool
  method read_eof : bool
  method reading : bool
  method shutting_down : bool
  method start_mem_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_mem_writing :
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_shutting_down :
    ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
  method start_writing :
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit
  method supports_half_open_connection : bool
  method tls_session : (string * string) option
  method tls_session_props : Nettls_support.tls_session_props option
  method tls_stashed_endpoint : unit -> exn
  method writing : bool
  method wrote_eof : bool
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_sharedvar.html0000644000175000017500000006427512731530353022024 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sharedvar sig
  exception Sharedvar_type_mismatch of string
  exception Sharedvar_no_permission of string
  exception Sharedvar_not_found of string
  exception Sharedvar_null
  val plugin : Netplex_types.plugin
  val create_var :
    ?own:bool ->
    ?ro:bool -> ?enc:bool -> ?timeout:float -> ?ssn:string -> string -> bool
  val delete_var : string -> bool
  val set_value : string -> string -> bool
  val set_enc_value : string -> Netplex_types.encap -> bool
  val get_value : string -> string option
  val get_enc_value : string -> Netplex_types.encap option
  val wait_for_value : string -> string option
  val wait_for_enc_value : string -> Netplex_types.encap option
  val get_lazily : string -> (unit -> string) -> string option
  val get_enc_lazily :
    string -> (unit -> Netplex_types.encap) -> Netplex_types.encap option
  val dump : string -> Netlog.level -> unit
  type 'a versioned_value
  val vv_access : string -> string Netplex_sharedvar.versioned_value
  val vv_access_enc :
    string -> Netplex_types.encap Netplex_sharedvar.versioned_value
  val vv_get : 'Netplex_sharedvar.versioned_value -> 'a option
  val vv_version : 'Netplex_sharedvar.versioned_value -> int64
  val vv_update : 'Netplex_sharedvar.versioned_value -> bool
  val vv_set : 'Netplex_sharedvar.versioned_value -> '-> bool
  module Make_var_type :
    functor (T : Netplex_cenv.TYPE->
      sig
        type t = T.t
        val get : string -> t
        val set : string -> t -> unit
      end
  module type VV_TYPE =
    sig
      type t
      type var
      val access : string -> Netplex_sharedvar.VV_TYPE.var
      val get : Netplex_sharedvar.VV_TYPE.var -> Netplex_sharedvar.VV_TYPE.t
      val set :
        Netplex_sharedvar.VV_TYPE.var -> Netplex_sharedvar.VV_TYPE.t -> unit
      val version : Netplex_sharedvar.VV_TYPE.var -> int64
      val update : Netplex_sharedvar.VV_TYPE.var -> bool
    end
  module Make_vv :
    functor (T : Netplex_cenv.TYPE->
      sig
        type t = T.t
        type var
        val access : string -> var
        val get : var -> t
        val set : var -> t -> unit
        val version : var -> int64
        val update : var -> bool
      end
  val global_propagator : unit -> Netsys_global.propagator
  val propagate_back : Netplex_types.controller -> unit
end
ocamlnet-4.1.2/doc/html-main/Netsys_gssapi.poly_gss_api-c.html0000644000175000017500000011056212731530353023036 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.poly_gss_api

Class type Netsys_gssapi.poly_gss_api

class type [['credential, 'name, 'context]] poly_gss_api = object .. end

method provider : string
A string name identifying the provider
method no_credential : 'credential
A substitute credential for GSS_C_NO_CREDENTIAL
method no_name : 'name
A substitute name for GSS_C_NO_NAME
method is_no_credential : 'credential -> bool
A test for GSS_C_NO_CREDENTIAL
method is_no_name : 'name -> bool
A test for GSS_C_NO_NAME
method accept_sec_context : 't.
context:'context option ->
acceptor_cred:'credential ->
input_token:token ->
chan_bindings:channel_bindings option ->
out:(src_name:'name ->
mech_type:oid ->
output_context:'context option ->
output_token:token ->
ret_flags:ret_flag list ->
time_rec:time ->
delegated_cred:'credential ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
On the first call, pass ~context:None. If successful, the function outputs a non-None ~output_context which should be passed as new ~context in follow-up calls.

If the output_token is non-empty, it must be transmitted to the peer - independent of the major_status.

method acquire_cred : 't.
desired_name:'name ->
time_req:time ->
desired_mechs:oid_set ->
cred_usage:cred_usage ->
out:(cred:'credential ->
actual_mechs:oid_set ->
time_rec:time ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method add_cred : 't.
input_cred:'credential ->
desired_name:'name ->
desired_mech:oid ->
cred_usage:cred_usage ->
initiator_time_req:time ->
acceptor_time_req:time ->
out:(output_cred:'credential ->
actual_mechs:oid_set ->
initiator_time_rec:time ->
acceptor_time_rec:time ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method canonicalize_name : 't.
input_name:'name ->
mech_type:oid ->
out:(output_name:'name ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method compare_name : 't.
name1:'name ->
name2:'name ->
out:(name_equal:bool ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method context_time : 't.
context:'context ->
out:(time_rec:time ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method delete_sec_context : 't.
context:'context ->
out:(minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
Output tokens are not supported (this is a deprecated feature of GSSAPI)
method display_name : 't.
input_name:'name ->
out:(output_name:string ->
output_name_type:oid ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method display_minor_status : 't.
status_value:minor_status ->
mech_type:oid ->
out:(status_strings:string list ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
Note that display_minor_status decodes all status value parts in one step and returns the result as string list. Also, this method is restricted to decoding minor statuses
method duplicate_name : 't.
name:'name ->
out:(dest_name:'name ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method export_name : 't.
name:'name ->
out:(exported_name:string ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method export_sec_context : 't.
context:'context ->
out:(interprocess_token:interprocess_token ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method get_mic : 't.
context:'context ->
qop_req:qop ->
message:message ->
out:(msg_token:token ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method import_name : 't.
input_name:string ->
input_name_type:oid ->
out:(output_name:'name ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method import_sec_context : 't.
interprocess_token:interprocess_token ->
out:(context:'context option ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method indicate_mechs : 't.
out:(mech_set:oid_set ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method init_sec_context : 't.
initiator_cred:'credential ->
context:'context option ->
target_name:'name ->
mech_type:oid ->
req_flags:req_flag list ->
time_req:float option ->
chan_bindings:channel_bindings option ->
input_token:token option ->
out:(actual_mech_type:oid ->
output_context:'context option ->
output_token:token ->
ret_flags:ret_flag list ->
time_rec:time ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
On the first call, pass ~context:None. If successful, the function outputs a non-None ~output_context which should be passed as new ~context in follow-up calls.

If the output_token is non-empty, it must be transmitted to the peer - independent of the major_status.

method inquire_context : 't.
context:'context ->
out:(src_name:'name ->
targ_name:'name ->
lifetime_req:time ->
mech_type:oid ->
ctx_flags:ret_flag list ->
locally_initiated:bool ->
is_open:bool ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method inquire_cred : 't.
cred:'credential ->
out:(name:'name ->
lifetime:time ->
cred_usage:cred_usage ->
mechanisms:oid_set ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method inquire_cred_by_mech : 't.
cred:'credential ->
mech_type:oid ->
out:(name:'name ->
initiator_lifetime:time ->
acceptor_lifetime:time ->
cred_usage:cred_usage ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method inquire_mechs_for_name : 't.
name:'name ->
out:(mech_types:oid_set ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method inquire_names_for_mech : 't.
mechanism:oid ->
out:(name_types:oid_set ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method process_context_token : 't.
context:'context ->
token:token ->
out:(minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method unwrap : 't.
context:'context ->
input_message:message ->
output_message_preferred_type:[ `Bytes | `Memory ] ->
out:(output_message:message ->
conf_state:bool ->
qop_state:qop ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
Note that the output_message can be a buffer of different type (string vs. bigarray) than input_message. In output_message_preferred_type the called may wish a certain representation. It is, however, not ensured that the wish is granted.
method verify_mic : 't.
context:'context ->
message:message ->
token:token ->
out:(qop_state:qop ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
method wrap : 't.
context:'context ->
conf_req:bool ->
qop_req:qop ->
input_message:message ->
output_message_preferred_type:[ `Bytes | `Memory ] ->
out:(conf_state:bool ->
output_message:message ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
output_message_preferred_type: see unwrap
method wrap_size_limit : 't.
context:'context ->
conf_req:bool ->
qop_req:qop ->
req_output_size:int ->
out:(max_input_size:int ->
minor_status:minor_status ->
major_status:major_status -> unit -> 't) ->
unit -> 't
ocamlnet-4.1.2/doc/html-main/type_Netsys_gssapi.client_props.html0000644000175000017500000004144412731530353023672 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.client_props object
  method flags : Netsys_gssapi.ret_flag list
  method mech_type : Netsys_gssapi.oid
  method time : Netsys_gssapi.time
end
ocamlnet-4.1.2/doc/html-main/Rpc_transport.Debug.html0000644000175000017500000004176412731530353021170 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_transport.Debug

Module Rpc_transport.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging
ocamlnet-4.1.2/doc/html-main/Netx509.DN_attributes.html0000644000175000017500000005327712731530353021227 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.DN_attributes

Module Netx509.DN_attributes

module DN_attributes: sig .. end


Object identifiers used in distinguished names

Object identifiers used in distinguished names

This module is an implementation of Netdn.AT_LOOKUP, and can be used with the parser/printer in Netdn.

Object identifiers used in distinguished names

This module is an implementation of Netdn.AT_LOOKUP, and can be used with the parser/printer in Netdn.

Attibute types
val at_name : Netx509.oid
val at_surname : Netx509.oid
val at_givenName : Netx509.oid
val at_initials : Netx509.oid
val at_generationQualifier : Netx509.oid
val at_commonName : Netx509.oid
val at_localityName : Netx509.oid
val at_stateOrProvinceName : Netx509.oid
val at_organizationName : Netx509.oid
val at_organizationalUnitName : Netx509.oid
val at_title : Netx509.oid
val at_dnQualifier : Netx509.oid
val at_countryName : Netx509.oid
val at_serialNumber : Netx509.oid
val at_pseudonym : Netx509.oid
val at_domainComponent : Netx509.oid
val at_emailAddress : Netx509.oid
val at_uid : Netx509.oid
val attribute_types : (Netx509.oid * string * string list) list
The above types in the format (oid, full_name, short_names)
val lookup_attribute_type_by_oid : Netx509.oid -> string * string list
Looks the OID up, and returns (full_name, short_names). May raise Not_found.
val lookup_attribute_type_by_name : string -> Netx509.oid * string * string list
Looks the name up, which can either be a full name or a short name. Returns the whole triple (oid, full_name, short_names), or raises Not_found.
ocamlnet-4.1.2/doc/html-main/type_Netplex_cenv.TYPE.html0000644000175000017500000004067212731530353021553 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_cenv.TYPE sig type t endocamlnet-4.1.2/doc/html-main/type_Netx509.KP.html0000644000175000017500000004257712731530353020034 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.KP sig
  val kp_server_auth : Netx509.oid
  val kp_client_auth : Netx509.oid
  val kp_code_signing : Netx509.oid
  val kp_email_protection : Netx509.oid
  val kp_time_stamping : Netx509.oid
  val kp_ocsp_signing : Netx509.oid
  val ext_key_purposes :
    (Netx509.oid * Netx509.ext_key_usage_flag * string) list
end
ocamlnet-4.1.2/doc/html-main/type_Netfs.html0000644000175000017500000010101612731530353017406 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netfs sig
  type read_flag = [ `Binary | `Dummy | `Skip of int64 | `Streaming ]
  type read_file_flag = [ `Binary | `Dummy ]
  type write_flag =
      [ `Binary | `Create | `Dummy | `Exclusive | `Streaming | `Truncate ]
  type write_file_flag =
      [ `Binary | `Create | `Dummy | `Exclusive | `Link | `Truncate ]
  type write_common = [ `Binary | `Create | `Dummy | `Exclusive | `Truncate ]
  type size_flag = [ `Dummy ]
  type test_flag = [ `Dummy | `Link ]
  type remove_flag = [ `Dummy | `Recursive ]
  type rename_flag = [ `Dummy ]
  type symlink_flag = [ `Dummy ]
  type readdir_flag = [ `Dummy ]
  type readlink_flag = [ `Dummy ]
  type mkdir_flag = [ `Dummy | `Nonexcl | `Path ]
  type rmdir_flag = [ `Dummy ]
  type copy_flag = [ `Dummy ]
  type test_type = [ `D | `E | `F | `H | `N | `R | `S | `W | `X ]
  class type local_file =
    object method close : unit -> unit method filename : string end
  class type stream_fs =
    object
      method cancel : unit -> unit
      method copy : Netfs.copy_flag list -> string -> string -> unit
      method mkdir : Netfs.mkdir_flag list -> string -> unit
      method nominal_dot_dot : bool
      method path_encoding : Netconversion.encoding option
      method path_exclusions : (int * int) list
      method read :
        Netfs.read_flag list -> string -> Netchannels.in_obj_channel
      method read_file :
        Netfs.read_file_flag list -> string -> Netfs.local_file
      method readdir : Netfs.readdir_flag list -> string -> string list
      method readlink : Netfs.readlink_flag list -> string -> string
      method remove : Netfs.remove_flag list -> string -> unit
      method rename : Netfs.rename_flag list -> string -> string -> unit
      method rmdir : Netfs.rmdir_flag list -> string -> unit
      method size : Netfs.size_flag list -> string -> int64
      method symlink : Netfs.symlink_flag list -> string -> string -> unit
      method test : Netfs.test_flag list -> string -> Netfs.test_type -> bool
      method test_list :
        Netfs.test_flag list -> string -> Netfs.test_type list -> bool list
      method write :
        Netfs.write_flag list -> string -> Netchannels.out_obj_channel
      method write_file :
        Netfs.write_file_flag list -> string -> Netfs.local_file -> unit
    end
  class empty_fs : string -> stream_fs
  val local_fs :
    ?encoding:Netconversion.encoding ->
    ?root:string -> ?enable_relative_paths:bool -> unit -> Netfs.stream_fs
  val copy :
    ?replace:bool ->
    ?streaming:bool ->
    #Netfs.stream_fs -> string -> #Netfs.stream_fs -> string -> unit
  val copy_into :
    ?replace:bool ->
    ?subst:(int -> string) ->
    ?streaming:bool ->
    #Netfs.stream_fs -> string -> #Netfs.stream_fs -> string -> unit
  type file_kind = [ `Directory | `None | `Other | `Regular | `Symlink ]
  val iter :
    pre:(string -> Netfs.file_kind -> Netfs.file_kind -> unit) ->
    ?post:(string -> unit) -> #Netfs.stream_fs -> string -> unit
  val convert_path :
    ?subst:(int -> string) ->
    #Netfs.stream_fs -> #Netfs.stream_fs -> string -> string
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.datagram_multiplex_controller-c.html0000644000175000017500000004313212731530353027277 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.datagram_multiplex_controller

Class type Uq_engines_compat.datagram_multiplex_controller

class type datagram_multiplex_controller = object .. end
Inherits
method received_from : Unix.sockaddr
method send_to : Unix.sockaddr -> unit
ocamlnet-4.1.2/doc/html-main/Netmech_scram_gssapi.server_key_verifier-c.html0000644000175000017500000004344212731530353025704 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_gssapi.server_key_verifier

Class type Netmech_scram_gssapi.server_key_verifier

class type server_key_verifier = object .. end
A server_key_verifier verifies on the server side that the users exist and have the right authentication credentials

method scram_credentials : string -> Netmech_scram.credentials
Returns the credentials for a user, or raises Not_found. See Netmech_scram.create_server_session for the meaning of this triple.
ocamlnet-4.1.2/doc/html-main/Netx509.x509_certificate-c.html0000644000175000017500000005103412731530353021734 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_certificate

Class type Netx509.x509_certificate

class type x509_certificate = object .. end
An X.509 certificate in decoded form. The is only the public part, i.e. it includes only the various descriptive fields, the public key, and the signature by the issuer.

method subject : directory_name
The DN of the subject
method subject_unique_id : Netasn1.Value.bitstring_value option
The unique ID of the subject
method issuer : directory_name
The DN of the issuer
method issuer_unique_id : Netasn1.Value.bitstring_value option
The unique ID of the issuer
method version : int
The "version" field, 1 to 3
method serial_number : string
The "serialNumber" field
method valid_not_before : float
Activation time as seconds since the epoch ("notBefore" field)
method valid_not_after : float
Expiration time as seconds since the epoch ("notAfter" field)
method signature : Netasn1.Value.bitstring_value
The signature
method signature_algorithm : oid * Netasn1.Value.value option
The algorithm of the signature (OID, and algorithm-specific parameters)
method public_key : Netasn1.Value.bitstring_value
The subject's public key
method public_key_algorithm : oid * Netasn1.Value.value option
The algorithm of the public key (OID, and algorithm-specific parameters)
method extensions : (oid * string * bool) list
Extensions (version 3 certificates) as triples (oid, data, critical). OIDs can occur several times.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.cache.html0000644000175000017500000004143012731530353023034 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.cache (Unixqueue.event_system -> 'Uq_engines_compat.engine) ->
Unixqueue.event_system -> ['a] Uq_engines_compat.cache_t
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.qseq_engine-c.html0000644000175000017500000004260512731530353023453 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.qseq_engine

Class Uq_engines_compat.qseq_engine

class [['a, 'b]] qseq_engine : 'a #engine -> ('a -> 'b #engine) -> ['b] engine

ocamlnet-4.1.2/doc/html-main/type_Netcgi_common.cgi.html0000644000175000017500000005242412731530353021661 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.cgi Netcgi_common.cgi_environment ->
Netcgi_common.output_type ->
Netcgi_common.request_method ->
Netcgi_common.cgi_argument list ->
object
  method argument : string -> Netcgi_common.cgi_argument
  method argument_exists : string -> bool
  method argument_value : ?default:string -> string -> string
  method arguments : Netcgi_common.cgi_argument list
  method at_exit : (unit -> unit) -> unit
  method environment : Netcgi_common.cgi_environment
  method finalize : unit -> unit
  method multiple_argument : string -> Netcgi_common.cgi_argument list
  method out_channel : Netchannels.trans_out_obj_channel
  method output : Netchannels.trans_out_obj_channel
  method request_method : Netcgi_common.request_method
  method set_header :
    ?status:Nethttp.http_status ->
    ?content_type:string ->
    ?content_length:int ->
    ?set_cookie:Nethttp.cookie list ->
    ?set_cookies:Netcgi_common.Cookie.t list ->
    ?cache:Netcgi_common.cache_control ->
    ?filename:string ->
    ?language:string ->
    ?script_type:string ->
    ?style_type:string -> ?fields:(string * string list) list -> unit -> unit
  method set_redirection_header :
    ?set_cookies:Netcgi_common.Cookie.t list ->
    ?fields:(string * string list) list -> string -> unit
  method url :
    ?protocol:Nethttp.protocol ->
    ?with_authority:Netcgi_common.other_url_spec ->
    ?with_script_name:Netcgi_common.other_url_spec ->
    ?with_path_info:Netcgi_common.other_url_spec ->
    ?with_query_string:Netcgi_common.query_string_spec -> unit -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.config_file.html0000644000175000017500000004564112731530353023450 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.config_file object
  method bool_param : Netplex_types.address -> bool
  method filename : string
  method float_param : Netplex_types.address -> float
  method int_param : Netplex_types.address -> int
  method print : Netplex_types.address -> string
  method resolve_parameter :
    Netplex_types.address -> string -> Netplex_types.address
  method resolve_section :
    Netplex_types.address -> string -> Netplex_types.address list
  method restrict_parameters : Netplex_types.address -> string list -> unit
  method restrict_subsections : Netplex_types.address -> string list -> unit
  method root_addr : Netplex_types.address
  method root_name : string
  method string_param : Netplex_types.address -> string
  method tree : Netplex_types.config_tree
end
ocamlnet-4.1.2/doc/html-main/type_Uq_libevent.LIBOEVENT.html0000644000175000017500000004607512731530353022147 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_libevent.LIBOEVENT sig
  type event
  type event_flags = TIMEOUT | READ | WRITE | SIGNAL
  type event_callback =
      Unix.file_descr -> Uq_libevent.LIBOEVENT.event_flags -> unit
  val create : unit -> Uq_libevent.LIBOEVENT.event
  val set :
    Uq_libevent.LIBOEVENT.event ->
    Unix.file_descr ->
    Uq_libevent.LIBOEVENT.event_flags list ->
    persist:bool -> Uq_libevent.LIBOEVENT.event_callback -> unit
  val add : Uq_libevent.LIBOEVENT.event -> float option -> unit
  val del : Uq_libevent.LIBOEVENT.event -> unit
  type loop_flags = ONCE | NONBLOCK
  val loop : Uq_libevent.LIBOEVENT.loop_flags -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Unixqueue.performance_event_system.html0000644000175000017500000004070412731530353025432 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.performance_event_system unit -> Unixqueue.event_systemocamlnet-4.1.2/doc/html-main/type_Nethttp_client.key.html0000644000175000017500000004166212731530353022114 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.key object
  method credentials : (string * string * (string * string) list) list
  method domain : Neturl.url list
  method password : string
  method realm : string
  method user : string
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.plugin.html0000644000175000017500000004414112731530353022474 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.plugin object
  method ctrl_added : Netplex_types.controller -> unit
  method ctrl_container_finished :
    Netplex_types.controller -> Netplex_types.container_id -> bool -> unit
  method ctrl_receive_call :
    Netplex_types.controller ->
    Netplex_types.container_id ->
    string -> Netxdr.xdr_value -> (Netxdr.xdr_value option -> unit) -> unit
  method ctrl_unplugged : Netplex_types.controller -> unit
  method program : Rpc_program.t
  method required : Netplex_types.plugin list
end
ocamlnet-4.1.2/doc/html-main/type_Netshm_array.html0000644000175000017500000004563512731530353021001 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm_array sig
  type 'a t
  val manage :
    ?pagesize:int ->
    ?init:int ->
    '->
    'Netshm_data.data_manager ->
    Netshm.locking_method -> Netshm.shm_descr -> 'Netshm_array.t
  val length : 'Netshm_array.t -> int
  val get : 'Netshm_array.t -> int -> 'a
  val set : 'Netshm_array.t -> int -> '-> unit
  val resize : 'Netshm_array.t -> int -> unit
  val default_value : 'Netshm_array.t -> 'a
  val shm_table : 'Netshm_array.t -> Netshm.shm_table
end
ocamlnet-4.1.2/doc/html-main/Netchannels.lift_rec_out_channel-c.html0000644000175000017500000004361112731530353024123 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.lift_rec_out_channel

Class Netchannels.lift_rec_out_channel

class lift_rec_out_channel : ?start_pos_out:int -> rec_out_channel -> out_obj_channel
This class implements pos_out and the methods from compl_out_channel by calling the methods of rec_out_channel. There is no additional buffering.

The method pos_out is implemented by counting the number of octets read by the output method.


start_pos_out : The initial value of the counter for pos_out. Defaults to 0.

ocamlnet-4.1.2/doc/html-main/type_Netmech_scram.AES_CTS.html0000644000175000017500000004373712731530353022236 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram.AES_CTS sig
  val c : int
  val m : int
  val encrypt : string -> string -> string
  val encrypt_mstrings :
    string -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
  val decrypt : string -> string -> string
  val decrypt_mstrings :
    string -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list
  val tests : (string * string * string) list
  val run_tests : unit -> bool
  val run_mtests : unit -> bool
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_sasl.Server.html0000644000175000017500000005335712731530353022121 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl.Server sig
  type session
  type 'credentials init_credentials =
      (string * string * (string * string) list) list -> 'credentials
  type lookup = {
    lookup :
      'c.
        Netsys_sasl.sasl_mechanism ->
        'Netsys_sasl.Server.init_credentials ->
        string -> string -> 'c option;
  }
  val create_session :
    mech:Netsys_sasl.sasl_mechanism ->
    lookup:Netsys_sasl.Server.lookup ->
    params:(string * string * bool) list ->
    unit -> Netsys_sasl.Server.session
  val process_response :
    Netsys_sasl.Server.session -> string -> Netsys_sasl.Server.session
  val process_response_restart :
    Netsys_sasl.Server.session ->
    string -> bool -> Netsys_sasl.Server.session * bool
  val emit_challenge :
    Netsys_sasl.Server.session -> Netsys_sasl.Server.session * string
  val stash_session : Netsys_sasl.Server.session -> string
  val resume_session :
    mech:Netsys_sasl.sasl_mechanism ->
    lookup:Netsys_sasl.Server.lookup -> string -> Netsys_sasl.Server.session
  val session_id : Netsys_sasl.Server.session -> string option
  val prop : Netsys_sasl.Server.session -> string -> string
  val gssapi_props : Netsys_sasl.Server.session -> Netsys_gssapi.server_props
  val user_name : Netsys_sasl.Server.session -> string
  val authz_name : Netsys_sasl.Server.session -> string
  val channel_binding : Netsys_sasl.Server.session -> Netsys_sasl_types.cb
end
ocamlnet-4.1.2/doc/html-main/Netsys_pollset.pollset-c.html0000644000175000017500000005044112731530353022223 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset.pollset

Class type Netsys_pollset.pollset

class type pollset = object .. end

method find : Unix.file_descr -> Netsys_posix.poll_req_events
Checks whether a descriptor is member of the set, and returns its event mask. Raises Not_found if the descriptor is not in the set.
method add : Unix.file_descr -> Netsys_posix.poll_req_events -> unit
Add a descriptor or modify an existing descriptor
method remove : Unix.file_descr -> unit
Remove a descriptor from the set (if it is member)
method wait : float ->
(Unix.file_descr * Netsys_posix.poll_req_events *
Netsys_posix.poll_act_events)
list
Wait for events, and return the output events matching the event mask. This is level-triggered polling, i.e. if a descriptor continues to match an event mask, it is again reported the next time wait is invoked.

There is no guarantee that the list is complete.

It is unspecified how the set reacts on descriptors that became invalid (i.e. are closed) while being member of the set. The set implementation is free to silently disregard such descriptors, or to report them as invalid. It is strongly recommended to remove descriptors before closing them.

method dispose : unit -> unit
Release any OS resources associated with the pollset. The pollset remains usable, however, and by invoking any method except cancel_wait the required OS resources are automatically allocated again. Only for cancel_wait it is ensured that the disposal remains in effect.
method cancel_wait : bool -> unit
There is a cancel bit in the pollset, and this method sets it to the argument value.

When the bit is true, any wait invocation will immediately time out. It is allowed to set the cancel bit from another thread, and when it becomes true, a parallel running wait will see that and timeout. Note that there is no protection against race conditions: It is possible that wait returns events that are found at the same time the cancellation is carried out, i.e. you cannot rely on that the list returned by wait is empty.

This is the only method of a pollset that is allowed to be called from a different thread. If not supported on a platform this method will fail.

ocamlnet-4.1.2/doc/html-main/type_Netmech_digest_sasl.html0000644000175000017500000004112712731530353022301 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_sasl sig module DIGEST_MD5 : Netsys_sasl_types.SASL_MECHANISM endocamlnet-4.1.2/doc/html-main/Netmime_string.html0000644000175000017500000027135212731530353020265 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime_string

Module Netmime_string

module Netmime_string: sig .. end
Low-level functions to parse and print mail and MIME messages

Netmime_string contains a lot of functions to scan and print strings formatted as MIME messages. For a higher-level view on this topic, see the Netmime module.

Contents




Splitting a string into lines



Splitting a string into lines



These functions are all CR/LF-aware, i.e. lines can be terminated by either LF or CR/LF.
val find_line_end : string -> int -> int -> int
find_line_end s pos len: Searches the next line end (CR/LF or only LF), and returns the position. The search starts at position pos, and covers the next len bytes. Raises Not_found if there is no line end.
val find_line_end_poly : 's Netstring_tstring.tstring_ops -> 's -> int -> int -> int
polymorphic version
val find_line_start : string -> int -> int -> int
find_line_start s pos len: Searches the next start, and returns its position. The line start is the position after the next line end (CR/LF or only LF). The search starts at position pos, and covers the next len bytes. Raises Not_found if there is no line end.
val find_line_start_poly : 's Netstring_tstring.tstring_ops -> 's -> int -> int -> int
polymorphic version
val find_double_line_start : string -> int -> int -> int
find_double_line_start s pos len: Searches two adjacent line ends (each may be a CR/LF combination or a single LF), and returns the position after the second line end. The search starts at position pos, and covers the next len bytes. Raises Not_found if the mentioned pattern is not found.
val find_double_line_start_poly : 's Netstring_tstring.tstring_ops -> 's -> int -> int -> int
polymorphic version
val skip_line_ends : string -> int -> int -> int
skip_line_ends s pos len: Skips over adjacent line ends (terminated by CR/LF or plain LF), and returns the position after the last line end. The search starts at position pos, and covers the next len bytes. Note that this function cannot raise Not_found.
val skip_line_ends_poly : 's Netstring_tstring.tstring_ops -> 's -> int -> int -> int
polymorphic version
val fold_lines_p : ('a -> int -> int -> int -> bool -> 'a) -> 'a -> string -> int -> int -> 'a
fold_lines_p f acc0 s pos len: Splits the substring of s from pos to pos+len into lines, and folds over these lines like List.fold_left. The function f is called as f acc p0 p1 p2 is_last where acc is the current accumulator (initialized with acc0), and
  • p0 is the start position of the line in s
  • p1 is the position of the line terminator in s
  • p2 is the position after the line terminator in s
  • is_last is true if this is the last line in the iteration
The lines can be terminated with CR/LF or LF. For the last line the terminator is optional (p1=p2 is possible).

The function is tail-recursive.

val fold_lines_p_poly : 's Netstring_tstring.tstring_ops ->
('a -> int -> int -> int -> bool -> 'a) -> 'a -> 's -> int -> int -> 'a
even more polymorphic
val fold_lines : ('a -> string -> 'a) -> 'a -> string -> int -> int -> 'a
fold_lines f acc0 s pos len: Splits the substring of s from pos to pos+len into lines, and folds over these lines like List.fold_left. The function f is called as f acc line where acc is the current accumulator (initialized with acc0), and line is the current line w/o terminator.

The lines can be terminated with CR/LF or LF.

The function is tail-recursive.

Example: Get the lines as list:

         List.rev(fold_lines (fun l acc -> acc::l) [] s pos len)
      

val fold_lines_poly : 's Netstring_tstring.tstring_ops ->
('a -> 's -> 'a) -> 'a -> 's -> int -> int -> 'a
even more polymorphic
val iter_lines : (string -> unit) -> string -> int -> int -> unit
iter_lines f s pos len: Splits the substring of s from pos to pos+len into lines, and calls f line for each line.

The lines can be terminated with CR/LF or LF.

val iter_lines_poly : 's Netstring_tstring.tstring_ops -> ('s -> unit) -> 's -> int -> int -> unit
even more polymorphic
val skip_whitespace_left : string -> int -> int -> int
skip_whitespace_left s pos len: Returns the smallest p with p >= pos && p < pos+len so that s.[p] is not a whitesapce character (space, TAB, CR, LF), and s.[q] is a whitespace character for all q<p. If this is not possible Not_found will be raised.
val skip_whitespace_right : string -> int -> int -> int
skip_whitespace_right s pos len: Returns the biggest p with p >= pos && p < pos+len so that s.[p] is not a whitesapce character (space, TAB, CR, LF), and s.[q] is a whitespace character for all q>p. If this is not possible Not_found will be raised.

Parsing and Printing Mail Headers



Parsing and Printing Mail Headers



The Format of Mail Messages

Messages consist of a header and a body; the first empty line separates both parts. The header contains lines "param-name: param-value" where the param-name must begin on column 0 of the line, and the ":" separates the name and the value. So the format is roughly:

   param1-name: param1-value
   ...
   paramN-name: paramN-value
   _
   body 

(Where "_" denotes an empty line.)

Details

Note that parameter values are restricted; you cannot represent arbitrary strings. The following problems can arise:

  • Values cannot begin with whitespace characters, because there may be an arbitrary number of whitespaces between the ":" and the value.
  • Values (and names of parameters, too) must only be formed of 7 bit ASCII characters. (If this is not enough, the MIME standard knows the extension RFC 2047 that allows that header values may be composed of arbitrary characters of arbitrary character sets. See below how to decode such characters in values returned by this function.)
  • Header values may be broken into several lines. Continuation lines must begin with whitespace characters. This means that values must not contain line breaks as semantic part of the value. And it may mean that one whitespace character is not distinguishable from several whitespace characters.
  • Header lines must not be longer than 78 characters (soft limit) or 998 characters (hard limit). Values that would result into longer lines must be broken into several lines. This means that you cannot represent strings that contain too few whitespace characters. (Note: The soft limit is to avoid that user agents have problems with long lines. The hard limit means that transfer agents sometimes do not transfer longer lines correctly.)
  • Some old gateways pad the lines with spaces at the end of the lines.
This implementation of a mail scanner tolerates a number of deviations from the standard: long lines are not rejected; 8 bit values are generally accepted; lines may be ended only with LF instead of CRLF.

Compatibility

These functions can parse all mail headers that conform to RFC 822 or RFC 2822.

But there may be still problems, as RFC 822 allows some crazy representations that are actually not used in practice. In particular, RFC 822 allows it to use backslashes to "indicate" that a CRLF sequence is semantically meant as line break. As this function normally deletes CRLFs, it is not possible to recognize such indicators in the result of the function.

val fold_header : ?downcase:bool ->
?unfold:bool ->
?strip:bool ->
('a -> string -> string -> 'a) -> 'a -> string -> int -> int -> 'a
fold_header f acc0 s pos len: Parses a MIME header in the string s from pos to exactly pos+len. The MIME header must be terminated by an empty line.

A folding operation is done over the header values while the lines are extracted from the string, very much like List.fold_left. For each header (n,v) where n is the name and v is the value, the function f is called as f acc n v.

If the header cannot be parsed, a Failure is raised.

Certain transformations may be applied (default: no transformations):

  • If downcase is set, the header names are converted to lowercase characters
  • If unfold is set, the line terminators are not included in the resulting values. This covers both the end of line characters at the very end of a header and the end of line characters introduced by continuation lines.
  • If strip is set, preceding and trailing white space is removed from the value (including line terminators at the very end of the value)

val list_header : ?downcase:bool ->
?unfold:bool -> ?strip:bool -> string -> int -> int -> (string * string) list
list_header s pos len: Returns the headers as list of pairs (name,value).

For the meaning of the arguments see fold_header above.

val scan_header : ?downcase:bool ->
?unfold:bool ->
?strip:bool ->
string -> start_pos:int -> end_pos:int -> (string * string) list * int
let params, header_end_pos = scan_header s start_pos end_pos:

Deprecated.

Scans the mail header that begins at position start_pos in the string s and that must end somewhere before position end_pos. It is intended that in end_pos the character position following the end of the body of the MIME message is passed.

Returns the parameters of the header as (name,value) pairs (in params), and in header_end_pos the position of the character following directly after the header (i.e. after the blank line separating the header from the body).

  • If downcase, header names are converted to lowercase characters
  • The arguments unfold and strip have a slightly different meaning as for the new function fold_header above. In particular, whitespace is already stripped off the returned values if any of unfold or strip are enabled. (This is for backward compatibility.)
Also, this function is different because downcase and unfold are enabled by default, and only strip is not enabled.
val scan_header_tstring : ?downcase:bool ->
?unfold:bool ->
?strip:bool ->
Netsys_types.tstring ->
start_pos:int -> end_pos:int -> (string * string) list * int
The same for tagged strings
val scan_header_poly : ?downcase:bool ->
?unfold:bool ->
?strip:bool ->
's Netstring_tstring.tstring_ops ->
's -> start_pos:int -> end_pos:int -> (string * string) list * int
Polymorphic version
val read_header : ?downcase:bool ->
?unfold:bool ->
?strip:bool -> Netstream.in_obj_stream -> (string * string) list
This function expects that the current position of the passed in_obj_stream is the first byte of the header. The function scans the header and returns it. After that, the stream position is after the header and the terminating empty line (i.e. at the beginning of the message body).

The options downcase, unfold, and strip have the same meaning as in scan_header.

Example

To read the mail message "file.txt":

 let ch = new Netchannels.input_channel (open_in "file.txt") in
 let stream = new Netstream.input_stream ch in
 let header = read_header stream in
 stream#close_in()  (* no need to close ch *)
 

val write_header : ?soft_eol:string ->
?eol:string -> Netchannels.out_obj_channel -> (string * string) list -> unit
This function writes the header to the passed out_obj_channel. The empty line following the header is also written.

Exact output format:

  • The header is not folded, i.e. no additional CRLF sequences are inserted into the header to avoid long header lines. In order to produce correct headers, the necessary CRLF bytes must already exist in the field values. (You can use the function write_value below for this.)
  • However, this function helps getting some details right. First, whitespace at the beginning of field values is suppressed.

    Example:

    write_header ch ["x","Field value"; "y"," Other value"] outputs:

     x: Field value\r\n
     y: Other value\r\n
     \r\n
  • The end-of-line sequences LF, and CRLF, followed by whitespace are replaced by the passed soft_eol string. If the necessary space or tab character following the eol is missing, an additional space character will be inserted.

    Example:

    write_header ch ["x","Field\nvalue"; "y","Other\r\n\tvalue"] outputs:

     x: Field\r\n
      value
     y: Other\r\n
     \tvalue
  • Empty lines (and lines only consisting of whitespace) are suppressed if they occur inside the header.

    Example:

    write_header ch ["x","Field\n\nvalue"] outputs:

     x: Field\r\n
      value
  • Whitespace at the end of a header field is suppressed. One field is separated from the next field by printing eol once.

These rules ensure that the printed header will be well-formed with two exceptions:

  • Long lines (> 72 characters) are neither folded nor rejected
  • True 8 bit characters are neither properly encoded nor rejected
These two problems cannot be addressed without taking the syntax of the header fields into account. See below how to create proper header fields from s_token lists.

Parsing Structured Values



Parsing Structured Values



The following types and functions allow it to build scanners for structured mail and MIME values in a highly configurable way.

Structured Values

RFC 822 (together with some other RFCs) defines lexical rules how formal mail header values should be divided up into tokens. Formal mail headers are those headers that are formed according to some grammar, e.g. mail addresses or MIME types.

Some of the characters separate phrases of the value; these are the "special" characters. For example, '@' is normally a special character for mail addresses, because it separates the user name from the domain name (as in user@domain). RFC 822 defines a fixed set of special characters, but other RFCs use different sets. Because of this, the following functions allow it to configure the set of special characters.

Every sequence of characters may be embraced by double quotes, which means that the sequence is meant as literal data item; special characters are not recognized inside a quoted string. You may use the backslash to insert any character (including double quotes) verbatim into the quoted string (e.g. "He said: \"Give it to me!\""). The sequence of a backslash character and another character is called a quoted pair.

Structured values may contain comments. The beginning of a comment is indicated by '(', and the end by ')'. Comments may be nested. Comments may contain quoted pairs. A comment counts as if a space character were written instead of it.

Control characters are the ASCII characters 0 to 31, and 127. RFC 822 demands that mail headers are 7 bit ASCII strings. Because of this, this module also counts the characters 128 to 255 as control characters.

Domain literals are strings embraced by '[' and ']'; such literals may contain quoted pairs. Today, domain literals are used to specify IP addresses (rare), e.g. user@[192.168.0.44].

Every character sequence not falling in one of the above categories is an atom (a sequence of non-special and non-control characters). When recognized, atoms may be encoded in a character set different than US-ASCII; such atoms are called encoded words (see RFC 2047).

Scanning Using the Extended Interface

In order to scan a string containing a structured value, you must first create a mime_scanner using the function create_mime_scanner. The scanner contains the reference to the scanned string, and a specification how the string is to be scanned. The specification consists of the lists specials and scan_options.

The character list specials specifies the set of special characters. These are the characters that are not regarded as part of atoms, because they work as delimiters that separate atoms (like @ in the above example). In addition to this, when '"', '(', and '[' are seen as regular characters not delimiting quoted string, comments, and domain literals, respectively, these characters must also be added to specials. In detail, these rules apply:

  • Spaces:
    • If ' ' in specials: A space character is returned as Special ' '. Note that there may also be an effect on how comments are returned (see below).
    • If ' ' not in specials: Spaces are not returned, although they still delimit atoms.
  • Tabs, CRs, LFs:
    • If '\t' in specials: A tab character is returned as Special '\t'.
    • If '\t' not in specials: Tabs are not returned, although they still delimit atoms.
    • If '\r' in specials: A CR character is returned as Special '\r'.
    • If '\r' not in specials: CRs are not returned, although they still delimit atoms.
    • If '\n' in specials: A LF character is returned as Special '\n'.
    • If '\n' not in specials: LFs are not returned, although they still delimit atoms.
  • Comments:
    • If '(' in specials: Comments are not recognized. The character '(' is returned as Special '('.
    • If '(' not in specials: Comments are recognized. How comments are returned, depends on the following:
      1. If Return_comments in scan_options: Outer comments are returned as Comment (note that inner comments are recognized but are not returned as tokens)
      2. If otherwise ' ' in specials: Outer comments are returned as Special ' '
      3. Otherwise: Comments are recognized but not returned at all.
  • Quoted strings:
    • If '"' in specials: Quoted strings are not recognized, and double quotes are returned as Special '"'.
    • If '"' not in specials: Quoted strings are returned as QString tokens.
  • Domain literals:
    • If '[' in specials: Domain literals are not recognized, and left brackets are returned as Special '['.
    • If '[' not in specials: Domain literals are returned as DomainLiteral tokens.

If recognized, quoted strings are returned as QString s, where s is the string without the embracing quotes, and with already decoded quoted pairs.

Control characters c are returned as Control c.

If recognized, comments may either be returned as spaces (in the case you are not interested in the contents of comments), or as Comment tokens. The contents of comments are not further scanned; you must start a subscanner to analyze comments as structured values.

If recognized, domain literals are returned as DomainLiteral s, where s is the literal without brackets, and with decoded quoted pairs.

Atoms are returned as Atom s where s is a longest sequence of atomic characters (all characters which are neither special nor control characters nor delimiters for substructures). If the option Recognize_encoded_words is on, atoms which look like encoded words are returned as EncodedWord tokens. (Important note: Neither '?' nor '=' must be special in order to enable this functionality.)

After the mime_scanner has been created, you can scan the tokens by invoking scan_token which returns one token at a time, or by invoking scan_token_list which returns all following tokens.

There are two token types: s_token is the base type and is intended to be used for pattern matching. s_extended_token is a wrapper that additionally contains information where the token occurs.

Scanning Using the Simple Interface

Instead of creating a mime_scanner and calling the scan functions, you may also invoke scan_structured_value. This function returns the list of tokens directly; however, it is restricted to s_token.

Examples

  • Simple address:
     scan_structured_value "user@domain.com" [ '@'; '.' ] []
       = [ Atom "user"; Special '@'; Atom "domain"; Special '.'; Atom "com" ]
     
  • Spaces are not returned:
     scan_structured_value "user @ domain . com" [ '@'; '.' ] []
       = [ Atom "user"; Special '@'; Atom "domain"; Special '.'; Atom "com" ]
     
  • Comments are not returned:
     scan_structured_value "user(Do you know him?)@domain.com" [ '@'; '.' ] []
       = [ Atom "user"; Special '@'; Atom "domain"; Special '.'; Atom "com" ]
     
  • Comments are indicated if requested:
     scan_structured_value "user(Do you know him?)@domain.com" [ '@'; '.' ] 
         [ Return_comments ]
       = [ Atom "user"; Comment; Special '@'; Atom "domain"; Special '.'; 
           Atom "com" ]
     
  • Spaces are returned if special:
     scan_structured_value "user (Do you know him?) @ domain . com" 
         [ '@'; '.'; ' ' ] []
       = [ Atom "user"; Special ' '; Special ' '; Special ' '; Special '@'; 
           Special ' '; Atom "domain";
           Special ' '; Special '.'; Special ' '; Atom "com" ]
     
  • Both spaces and comments are requested:
     scan_structured_value "user (Do you know him?) @ domain . com" 
         [ '@'; '.'; ' ' ] [ Return_comments ]
       = [ Atom "user"; Special ' '; Comment; Special ' '; Special '@'; 
           Special ' '; Atom "domain";
           Special ' '; Special '.'; Special ' '; Atom "com" ]
     
  • Another case:
     scan_structured_value "user @ domain . com" [ '@'; '.'; ' ' ] []
       = [ Atom "user"; Special ' '; Special '@'; Special ' '; Atom "domain";
           Special ' '; Special '.'; Special ' '; Atom "com" ]
     
  • '(' is special:
     scan_structured_value "user(Do you know him?)@domain.com" ['@'; '.'; '(']
         []
       = [ Atom "user"; Special '('; Atom "Do"; Atom "you"; Atom "know";
           Atom "him?)"; Special '@'; Atom "domain"; Special '.'; Atom "com" ]
     
  • Quoted strings:
     scan_structured_value "\"My.name\"@domain.com" [ '@'; '.' ] []
       = [ QString "My.name"; Special '@'; Atom "domain"; Special '.';
           Atom "com" ]
     
  • Encoded words are not returned:
     scan_structured_value "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=" 
         [ ] [ ] 
       = [ Atom "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=" ]
     
  • Encoded words are returned if requested:
     scan_structured_value "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=" 
         [ ] [ Recognize_encoded_words ] 
       = [ EncodedWord(("ISO-8859-1",""), "Q", "Keld_J=F8rn_Simonsen") ]
     

type s_token = 
| Atom of string
| EncodedWord of ((string * string) * string * string) (*
Args: ((charset,lang),encoding,encoded_word)
*)
| QString of string
| Control of char
| Special of char
| DomainLiteral of string
| Comment
| End (*
*)
A token may be one of:
  • QString s: The quoted string s, i.e a string between double quotes. Quoted pairs are already decoded in s.
  • Control c: The control character c (0-31, 127, 128-255)
  • Special c: The special character c, i.e. a character from the specials list
  • DomainLiteral s: The bracketed string s, i.e. a string between brackets. Quoted pairs are already decoded in s.
  • Comment: A string between parentheses. This kind of token is only generated when the option Return_comments is in effect.
  • EncodedWord((charset,lang),encoding,encoded_word): An RFC-2047 style encoded word: charset is the name of the character set; lang is the language specifier (from RFC 2231) or ""; encoding is either "Q" or "B"; and encoded_word is the word encoded in charset and encoding. This kind of token is only generated when the option Recognize_encoded_words is in effect (if not, Atom is generated instead).
  • Atom s: A string which is neither quoted not bracketed nor written in RFC 2047 notation, and which is not a control or special character, i.e. the "rest"
  • End: The end of the string

type s_option = 
| No_backslash_escaping (*
Do not handle backslashes in quoted string and comments as escape characters; backslashes are handled as normal characters. For example: The wrong qstring "C:\dir\file" will be returned as QString "C:\dir\file" when this option is in effect, and not as QString "C:dirfile" as by default. -- This is a common error in many MIME implementations.
*)
| Return_comments (*
Comments are returned as token Comment (unless '(' is included in the list of special characters, in which case comments are not recognized at all). You may get the exact location of the comment by applying get_pos and get_length to the extended token.
*)
| Recognize_encoded_words (*
Enables that encoded words are recognized and returned as EncodedWord instead of Atom.
*)
type s_extended_token 
An opaque type containing the information of s_token plus:
  • where the token occurs
  • RFC-2047 access functions

val get_token : s_extended_token -> s_token
Return the s_token within the s_extended_token
val get_decoded_word : s_extended_token -> string
val get_charset : s_extended_token -> string
Return the decoded word (the contents of the word after decoding the "Q" or "B" representation), and the character set of the decoded word (uppercase).

These functions not only work for EncodedWord. The function get_decoded_word returns for the other kinds of token:

  • Atom: Returns the atom without decoding it
  • QString: Returns the characters inside the double quotes, and ensures that any quoted pairs are decoded
  • Control: Returns the one-character string
  • Special: Returns the one-character string
  • DomainLiteral: Returns the characters inside the brackets, and ensures that any quoted pairs are decoded
  • Comment: Returns ""
The function get_charset returns "US-ASCII" for them.
val get_language : s_extended_token -> string
Returns the language if the token is an EncodedWord, and "" for all other tokens.
val get_pos : s_extended_token -> int
Return the byte position where the token starts in the string (the first byte has position 0)
val get_line : s_extended_token -> int
Return the line number where the token starts (numbering begins usually with 1)
val get_column : s_extended_token -> int
Return the column of the line where the token starts (first column is number 0)
val get_length : s_extended_token -> int
Return the length of the token in bytes
val separates_adjacent_encoded_words : s_extended_token -> bool
True iff the current token is white space (i.e. Special ' ', Special '\t', Special '\r' or Special '\n') and the last non-white space token was EncodedWord and the next non-white space token will be EncodedWord.

The background of this function is that white space between encoded words does not have a meaning, and must be ignored by any application interpreting encoded words.

type mime_scanner 
The opaque type of a scanner for structured values
val create_mime_scanner : specials:char list ->
scan_options:s_option list ->
?pos:int -> ?line:int -> ?column:int -> string -> mime_scanner
Creates a new mime_scanner scanning the passed string.


specials : The list of characters recognized as special characters.
scan_options : The list of global options modifying the behaviour of the scanner
pos : The position of the byte where the scanner starts in the passed string. Defaults to 0.
line : The line number of this first byte. Defaults to 1.
column : The column number of this first byte. Default to 0.

Note for create_mime_scanner:

The optional parameters pos, line, column are intentionally placed after scan_options and before the string argument, so you can specify scanners by partially applying arguments to create_mime_scanner which are not yet connected with a particular string:

 let my_scanner_spec = create_mime_scanner my_specials my_options in
 ...
 let my_scanner = my_scanner_spec my_string in 
 ...

val get_pos_of_scanner : mime_scanner -> int
val get_line_of_scanner : mime_scanner -> int
val get_column_of_scanner : mime_scanner -> int
Return the current position, line, and column of a mime_scanner. The primary purpose of these functions is to simplify switching from one mime_scanner to another within a string:

 let scanner1 = create_mime_scanner ... s in
 ... now scanning some tokens from s using scanner1 ...
 let scanner2 = create_mime_scanner ... 
                  ?pos:(get_pos_of_scanner scanner1)
                  ?line:(get_line_of_scanner scanner1)
                  ?column:(get_column_of_scanner scanner1)
                  s in
 ... scanning more tokens from s using scanner2 ... 

Restriction: These functions are not available if the option Recognize_encoded_words is on. The reason is that this option enables look-ahead scanning; please use the location of the last scanned token instead.

Note: To improve the performance of switching, it is recommended to create scanner specs in advance (see the example my_scanner_spec above).

val scan_token : mime_scanner ->
s_extended_token * s_token
Returns the next token, or End if there is no more token. The token is returned both as extended and as normal token.
val scan_token_list : mime_scanner ->
(s_extended_token * s_token) list
Returns all following tokens as a list (excluding End)
val scan_structured_value : string ->
char list -> s_option list -> s_token list
This function is included for backwards compatibility, and for all cases not requiring extended tokens.

It scans the passed string according to the list of special characters and the list of options, and returns the list of all tokens.

val specials_rfc822 : char list
val specials_rfc2045 : char list
The sets of special characters defined by the RFCs 822 and 2045.

Parsing Certain Forms of Structured Values


val scan_encoded_text_value : string -> s_extended_token list
Scans a "text" value. The returned token list contains only Special, Atom and EncodedWord tokens. Spaces, TABs, CRs, LFs are returned (as Special) unless they occur between adjacent encoded words in which case they are suppressed. The characters '(', '[', and '"' are also returned as Special tokens, and are not interpreted as delimiters.

For instance, this function can be used to scan the "Subject" field of mail messages.

val scan_value_with_parameters : string -> s_option list -> string * (string * string) list
let name, params = scan_value_with_parameters s options: Scans values with annotations like name ; p1=v1 ; p2=v2 ; ... For example, MIME types like "text/plain;charset=ISO-8859-1" can be parsed.

The values may or may not be quoted. The characters ";", "=", and even "," are only accepted as part of values when they are quoted. On sytax errors, the function fails.

RFC 2231: This function supports some features of this RFC: Continued parameter values are concatenated. For example:

 Content-Type: message/external-body; access-type=URL;
    URL*0="ftp://";
    URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" 

This is returned as:

"message/external-body", 
   [ ("access-type", "URL");
     ("URL", "ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar") ]
      ) 

However, encoded parameter values are not handled specially. The parameter title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A would be returned as ("title*", "us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A"). Use scan_values_with_parameters_ep instead (see below).

Raises Failure on syntax errors.

type s_param 
The type of encoded parameters (RFC 2231)
val param_value : s_param -> string
val param_charset : s_param -> string
val param_language : s_param -> string
Return the decoded value of the parameter, the charset (uppercase), and the language. If the charset is not available, "" will be returned. If the language is not available, "" will be returned.
val mk_param : ?charset:string -> ?language:string -> string -> s_param
Creates a parameter from a value (in decoded form). The parameter may have a charset and a language.
val print_s_param : Format.formatter -> s_param -> unit
Prints a parameter to the formatter (as toploop printer)
val scan_value_with_parameters_ep : string ->
s_option list ->
string * (string * s_param) list
let name, params = scan_value_with_parameters_ep s options: This version of the scanner copes with encoded parameters according to RFC 2231. Note: "ep" means "encoded parameters".

Example: doc.html;title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A

The parameter title would be returned as:

  • name is "title"
  • value is "This is ***fun***"
  • charset is "US-ASCII"
  • language is "en-us"
Raises Failure on syntax errors.
val scan_mime_type : string -> s_option list -> string * (string * string) list
let name, params = scan_mime_type s options: Scans MIME types like text/plain; charset=iso-8859-1 The name of the type and the names of the parameters are converted to lower case.

Raises Failure on syntax errors.

val scan_mime_type_ep : string ->
s_option list ->
string * (string * s_param) list
let name, params = scan_mime_type_ep s options: This version copes with RFC-2231-encoded parameters.

Raises Failure on syntax errors.

val split_mime_type : string -> string * string
let (main_type, sub_type) = split_mime_type content_type: Splits the MIME type into main and sub type, for example split_mime_type "text/plain" = ("text", "plain") . The returned strings are always lowercase.

Raises Failure on syntax errors.


Printing Structured Values


exception Line_too_long
Raised when the hard limit of the line length is exceeded
val write_value : ?maxlen1:int ->
?maxlen:int ->
?hardmaxlen1:int ->
?hardmaxlen:int ->
?fold_qstring:bool ->
?fold_literal:bool ->
?unused:int Pervasives.ref ->
?hardunused:int Pervasives.ref ->
Netchannels.out_obj_channel -> s_token list -> unit
Writes the list of s_token to the out_obj_channel. The value is optionally folded into several lines while writing, but this is off by default. To enable folding, pass both maxlen1 and maxlen: The maxlen1 parameter specifies the length of the first line to write, the maxlen parameter specifies the length of the other lines.

If enabled, folding tries to ensure that the value is written in several lines that are not longer as specified by maxlen1 and maxlen. The value is split into lines by inserting "folding space" at certain locations (which is usually a linefeed followed by a space character, see below). The following table specifies between which tokens folding may happen:

               +=========================================================+
 1st   \   2nd | Atom | QString | DLiteral | EncWord | Special | Spec ' '|
 ==============+======+=========+==========+=========+=========+=========+
          Atom | FS   |  FS     |   FS     |   FS    |    -    |    F    |
       QString | FS   |  FS     |   FS     |   FS    |    -    |    F    |
 DomainLiteral | FS   |  FS     |   FS     |   FS    |    -    |    F    |
   EncodedWord | FS   |  FS     |   FS     |   FS    |    -    |    F    |
       Special | -    |  -      |   -      |   -     |    -    |    F    |
   Special ' ' | -    |  -      |   -      |   -     |    -    |    -    |
 ==============+======+=========+==========+=========+=========+=========+

The table shows between which two types of tokens a space or a folding space is inserted:

  • FS: folding space
  • F: linefeed without extra space
  • -: nothing can be inserted here
Folding space is "\n ", i.e. only LF, not CRLF is used as end-of-line character. The function write_header will convert these LF to CRLF if needed.

Special '\t' is handled like Special ' '. Control characters are just printed, without folding. Comments, however, are substituted by either space or folding space. The token End is ignored.

Furthermore, folding may also happen within tokens:

  • Atom, Control, and Special are never split up into parts. They are simply printed.
  • EncodedWords, however, are reformatted. This especially means: adjacent encoded words are first concatenated if possible (same character set, same encoding, same language), and then split up into several pieces with optimally chosen lengths. Note: Because this function gets s_token as input and not s_extended_token, it is not known whether Special ' ' tokens (or other whitespace) between adjacent EncodedWords must be ignored. Because of this, write_value only reformats adjacent encoded words when there is not any whitespace between them.
  • QString may be split up in a special way unless fold_qstring is set to false. For example, "One Two Three" may be split up into three lines "One\n Two\n \ Three". Because some header fields explicitly forbid folding of quoted strings, it is possible to set ~fold_qstring:false (it is true by default). Note: Software should not rely on that the different types of whitespace (especially space and TAB) remain intact at the beginning of a line. Furthermore, it may also happen that additional whitespace is added at the end of a line by the transport layer.
  • DomainLiteral: These are handled like QString. The parameter ~fold_literal:false turns folding off if it must be prevented, it is true by default.
  • Comment: Comments are effectively omitted! Instead of Comment, a space or folding space is printed. However, you can output comments by passing sequences like Special "("; ...; Special ")" .
It is possible to get the actual number of characters back that can still be printed into the last line without making the line too long. Pass an int ref as unused to get this value (it may be negative!). Pass an int ref as hardunused to get the number of characters that may be printed until the hard limit is exceeded.

The function normally does not fail when a line becomes too long, i.e. it exceeds maxlen1 or maxlen. However, it is possible to specify a hard maximum length (hardmaxlen1 and hardmaxlen). If these are exceeded, the function will raise Line_too_long.

For electronic mail, a maxlen of 78 and a hardmaxlen of 998 is recommended.

Known Problems:

  • The reformatter for EncodedWords takes into account that multi-byte characters must not be split up. However, this works only when the multi-byte character set is known to Netconversion. You can assume that UTF-8 and UTF-16 always work. If the character set is not known the reformatter may split the string at wrong positions.
  • The reformatter for EncodedWords may parse the token, and if this fails, you will get the exception Malformed_code. This is only done in some special cases, however.
  • The function prints spaces between adjacent atoms. Although this is allowed in principal, other MIME implementations might fail when there are spaces at unexpected locations. Workaround: If no spaces are desired, concatenate adjacent atoms before passing them to this function.
Further Tips:
  • Pass ~maxlen1:0 and ~maxlen:0 to get shortest lines
  • Use the reformatter for encoded words! It works well. For example, to output a long sentence, just wrap it into one EncodedWord. The reformatter takes care to fold the word into several lines.

val param_tokens : ?maxlen:int ->
(string * s_param) list -> s_token list
Formats a parameter list. For example, [ "a", "b"; "c", "d" ] is transformed to the token sequence corresponding to ; a=b; c=d. If maxlen is specified, it is ensured that the individual parameter (e.g. "a=b;") is not longer than maxlen-1, such that it will fit into a line with maximum length maxlen. By default, no maximum length is guaranteed. If maxlen is passed, or if a parameter specifies a character set or language, the encoding of RFC 2231 will be applied. If these conditions are not met, the parameters will be encoded traditionally.
val split_uri : string -> s_token list
Splits a long URI according to the algorithm of RFC 2017. The input string must only contain 7 bit characters, and must be, if necessary, already be URL-encoded.

Scanning MIME Messages


val scan_multipart_body : string ->
start_pos:int ->
end_pos:int -> boundary:string -> ((string * string) list * string) list
let [params1, value1; params2, value2; ...] = scan_multipart_body s start_pos end_pos boundary:

Scans the string s that is the body of a multipart message. The multipart message begins at position start_pos in s, and end_pos is the position of the character following the message. In boundary the boundary string must be passed (this is the "boundary" parameter of the multipart MIME type, e.g. multipart/mixed;boundary="some string" ).

The return value is the list of the parts, where each part is returned as pair (params, value). The left component params is the list of name/value pairs of the header of the part. The right component is the raw content of the part, i.e. if the part is encoded ("content-transfer-encoding"), the content is returned in the encoded representation. The caller is responsible for decoding the content.

The material before the first boundary and after the last boundary is not returned.

Multipart Messages

The MIME standard defines a way to group several message parts to a larger message (for E-Mails this technique is known as "attaching" files to messages); these are the so-called multipart messages. Such messages are recognized by the major type string "multipart", e.g. multipart/mixed or multipart/form-data. Multipart types MUST have a boundary parameter because boundaries are essential for the representation.

Multipart messages have a format like (where "_" denotes empty lines):

 ...Header...
 Content-type: multipart/xyz; boundary="abc"
 ...Header...
 _
 Body begins here ("prologue")
 --abc
 ...Header part 1...
 _
 ...Body part 1...
 --abc
 ...Header part 2...
 _
 ...Body part 2
 --abc
 ...
 --abc--
 Epilogue 

The parts are separated by boundary lines which begin with "--" and the string passed as boundary parameter. (Note that there may follow arbitrary text on boundary lines after "--abc".) The boundary is chosen such that it does not occur as prefix of any line of the inner parts of the message.

The parts are again MIME messages, with header and body. Note that it is explicitely allowed that the parts are even multipart messages.

The texts before the first boundary and after the last boundary are ignored.

Note that multipart messages as a whole MUST NOT be encoded. Only the PARTS of the messages may be encoded (if they are not multipart messages themselves).

Please read RFC 2046 if want to know the gory details of this brain-dead format.

val scan_multipart_body_and_decode : string ->
start_pos:int ->
end_pos:int -> boundary:string -> ((string * string) list * string) list
Same as scan_multipart_body, but decodes the bodies of the parts if they are encoded using the methods "base64" or "quoted printable". Fails, if an unknown encoding is used.
val scan_multipart_body_from_netstream : Netstream.in_obj_stream ->
boundary:string ->
create:((string * string) list -> 'a) ->
add:('a -> Netstream.in_obj_stream -> int -> int -> unit) ->
stop:('a -> unit) -> unit
scan_multipart_body_from_netstream s boundary create add stop:

Reads the MIME message from the netstream s block by block. The parts are delimited by the boundary.

Once a new part is detected and begins, the function create is called with the MIME header as argument. The result p of this function may be of any type.

For every chunk of the part that is being read, the function add is invoked: add p s k n.

Here, p is the value returned by the create invocation for the current part. s is the netstream. The current window of s contains the read chunk completely; the chunk begins at position k of the window (relative to the beginning of the window) and has a length of n bytes.

When the part has been fully read, the function stop is called with p as argument.

That means, for every part the following is executed:

  • let p = create h
  • add p s k1 n1
  • add p s k2 n2
  • ...
  • add p s kN nN
  • stop p
Important Precondition:
  • The block size of the netstream s must be at least String.length boundary + 4
Exceptions:
  • Exceptions can happen because of ill-formed input, and within the callbacks of the functions create, add, stop.
  • If the exception happens while part p is being read, and the create function has already been called (successfully), the stop function is also called (you have the chance to close files). The exception is re-raised after stop returns.

val read_multipart_body : (Netstream.in_obj_stream -> 'a) ->
string -> Netstream.in_obj_stream -> 'a list
This is the "next generation" multipart message parser. It is called as follows:

let parts = read_multipart_body f boundary s

As precondition, the current position of the stream s must be at the beginning of the message body. The string boundary must be the message boundary (without "--"). The function f is called for every message part, and the resulting list parts is the concatentation of the values returned by f.

The stream passed to f is a substream of s that begins at the first byte of the header of the message part. The function f can read data from the substream as necessary. The substream terminates at the end of the message part. This means that f can simply read the data of the substream from the beginning to the end. It is not necessary that f reads the substream until EOF, however.

After all parts have been read, the trailing material of stream s is skipped until EOF of s is reached.


Helpers for MIME Messages


val create_boundary : ?random:string list -> ?nr:int -> unit -> string
Creates a boundary string that can be used to separate multipart messages. The string is 63 characters long and has the following "features":
  • Most of the string consists of the minus character yielding a clear optical effect
  • The string contains "=__". This sequence cannot be obtained by the quoted-printable encoding, so you need not to care whether strings encoded as quoted-printable contain the boundary.
  • The string contains "<&>;" which is illegal in HTML, XML, and SGML.
  • The string does not contain double quotes or backslashes, so you can safely put double quotes around it in the MIME header.
  • The string contains nr, so you can safely distinguish between several boundaries occurring in the same MIME body if you assign different nr.
  • The string contains a hash value composed of the first 256 bytes of all strings passed as random, and influenced by the current GC state.

ocamlnet-4.1.2/doc/html-main/Netchannels.output_command-c.html0000644000175000017500000004371012731530353023013 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_command

Class Netchannels.output_command

class output_command : ?onclose:unit -> unit -> string -> out_obj_channel
Runs the command with /bin/sh, and data written to the channel is piped to stdin of the command.

The method pos_out returns the number of written octets.

When close_out is invoked, the subprocess is waited for. If the process exits with code 0, the method returns normally. Otherwise, the exception Command_failure is raised. (The channel is closed even if this exception is raised.)


onclose : this function is called when the close_out method is invoked, just after the underlying descriptor has been closed.

ocamlnet-4.1.2/doc/html-main/Nethttp.http_header_ro-c.html0000644000175000017500000004224212731530353022127 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.http_header_ro

Class type Nethttp.http_header_ro

class type http_header_ro = Netmime.mime_header_ro
The HTTP header is represented as MIME header

ocamlnet-4.1.2/doc/html-main/Netmech_scram_gssapi.client_key_ring-c.html0000644000175000017500000004336712731530353025006 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_gssapi.client_key_ring

Class type Netmech_scram_gssapi.client_key_ring

class type client_key_ring = object .. end
A client_key_ring identifies the user on the client side

method password_of_user_name : string -> string
Returns the cleartext password for a user name, or raises Not_found if the user is unknown
method default_user_name : string option
This method may return a default user name
ocamlnet-4.1.2/doc/html-main/type_Shell_uq.call_engine.html0000644000175000017500000004220712731530353022350 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_uq.call_engine ?ignore_error_code:bool ->
?mode:Shell_sys.group_mode ->
?stdin:Shell.producer ->
?stdout:Shell.consumer ->
?stderr:Shell.consumer ->
Shell_sys.command list ->
Unixqueue.event_system ->
[Shell_sys.job_status] Shell_uq.job_handler_engine_type
ocamlnet-4.1.2/doc/html-main/type_Netlog.Debug.html0000644000175000017500000005215412731530353020614 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netlog.Debug sig
  type dlogger = string -> string -> unit
  val fwd_dlogger : Netlog.Debug.dlogger
  val null_dlogger : Netlog.Debug.dlogger
  val current_dlogger : Netlog.Debug.dlogger Pervasives.ref
  val log : string -> string -> unit
  val logf : string -> ('a, unit, string, unit) Pervasives.format4 -> 'a
  val enable_module : string -> unit
  val disable_module : string -> unit
  val enable_all : unit -> unit
  val disable_all : unit -> unit
  val names : unit -> string list
  val register_module : string -> bool Pervasives.ref -> unit
  val mk_dlog : string -> bool Pervasives.ref -> string -> unit
  val mk_dlogr : string -> bool Pervasives.ref -> (unit -> string) -> unit
  type serial
  val new_serial : unit -> Netlog.Debug.serial
  val track_fd :
    ?update:bool ->
    ?anchor:'->
    ?sn:Netlog.Debug.serial ->
    owner:string -> descr:string -> Unix.file_descr -> unit
  val release_fd :
    ?sn:Netlog.Debug.serial -> ?force:bool -> Unix.file_descr -> unit
  val fd_string : ?owner:bool -> ?descr:bool -> Unix.file_descr -> string
  val fd_table : unit -> string list
  val enable_fd_tracking : bool Pervasives.ref
end
ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi_env.cgi_environment-c.html0000644000175000017500000006301512731530353025616 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_env.cgi_environment

Class type Netcgi1_compat.Netcgi_env.cgi_environment

class type cgi_environment = object .. end

method config : cgi_config
method cgi_gateway_interface : string
method cgi_server_software : string
method cgi_server_name : string
method cgi_server_protocol : string
method cgi_server_port : int option
method cgi_request_method : string
method cgi_path_info : string
method cgi_path_translated : string
method cgi_script_name : string
method cgi_query_string : string
method cgi_remote_host : string
method cgi_remote_addr : string
method cgi_auth_type : string
method cgi_remote_user : string
method cgi_remote_ident : string
method cgi_property : ?default:string -> string -> string
method cgi_properties : (string * string) list
method cgi_https : bool
method cgi_request_uri : string
I rest to be convinced we need this. Is it provided by web servers different from Apache? Why is the #url method not enough?
method protocol : protocol
method input_header : Netmime.mime_header
method input_header_field : ?default:string -> string -> string
method multiple_input_header_field : string -> string list
method input_header_fields : (string * string) list
method user_agent : string
method cookies : (string * string) list
Cookies are returned in decoded form. An additional #cookie method has been added for convenience and coherence with e.g. Netcgi.cgi.arguments v.s. Netcgi.cgi.argument.
method input_content_length : int
method input_content_type_string : string
method input_content_type : string * (string * Netmime_string.s_param) list
Type now is unit -> string * (string * Netmime_string.s_param) list to be coherent with Netmime.mime_header_ro.
method input_ch : Netchannels.in_obj_channel
Not the user business.
method input_state : input_state
Not the user business.
method set_input_state : input_state -> unit
Not the user business.
method output_header : Netmime.mime_header
method output_header_field : ?default:string -> string -> string
method multiple_output_header_field : string -> string list
method output_header_fields : (string * string) list
method set_output_header_field : string -> string -> unit
method set_multiple_output_header_field : string -> string list -> unit
method set_output_header_fields : (string * string) list -> unit
method set_status : Nethttp.http_status -> unit
method send_output_header : unit -> unit
method output_ch : Netchannels.out_obj_channel
Deprecated.in favor of out_channel by analogy with the standard library -- even though it is a "channel object".
method output_state : output_state
Not the user business.
method set_output_state : output_state -> unit
Not the user business.
method log_error : string -> unit
ocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.SHA256_PLUS.html0000644000175000017500000004435512731530353022606 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SHA256_PLUS

Module Netmech_scram_sasl.SHA256_PLUS

module SHA256_PLUS: PROFILE 
Same as Netmech_scram_sasl.SHA256, only that the mechanism name is "SCRAM-SHA-256-PLUS"

val hash_function : Netsys_digests.iana_hash_fn
The hash function. We only allow functions where IANA registered an official name. Note that SCRAM is currently only specified for SHA1, although the hash function is easily exchangable.
val iteration_count_limit : int
The maximum iteration count supported
val announce_channel_binding : bool
Whether servers announce the availability of channel binding by adding "-PLUS" to the mechanism name.
ocamlnet-4.1.2/doc/html-main/Uq_engines.stream_seq_engine-c.html0000644000175000017500000004414212731530353023300 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.stream_seq_engine

Class Uq_engines.stream_seq_engine

class ['a] stream_seq_engine : 'a -> ('a -> 'a #engine) Stream.t -> Unixqueue.event_system -> ['a] engine
let se = new stream_seq_engine x0 s esys: The constructed engine se fetches functions f : 'a -> 'a #engine from the stream s, and runs the engines obtained by calling these functions e = f x one after the other. Each function call gets the result of the previous engine as argument. The first call gets x0 as argument.

If one of the engines e transitions into an error or aborted state, se will also do that. If se is aborted, this is passed down to the currently running engine e.


ocamlnet-4.1.2/doc/html-main/Shell_uq.html0000644000175000017500000005176312731530353017057 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_uq

Module Shell_uq

module Shell_uq: sig .. end
Run shell commands within Unixqueues


This module is not thread-safe. See the module Shell_sys for more information.

This module is not thread-safe. See the module Shell_sys for more information.

Signal handlers: It is important to have a number of signal handlers installed for proper function of the engines. It is recommended to call the pair of functions Shell_sys.configure_job_handlers and Shell_sys.install_job_handlers for this purpose. This is not done automatically.

Note that this has a global side effect on the whole process, because there is only one set of signal handlers.

This module is not thread-safe. See the module Shell_sys for more information.

Signal handlers: It is important to have a number of signal handlers installed for proper function of the engines. It is recommended to call the pair of functions Shell_sys.configure_job_handlers and Shell_sys.install_job_handlers for this purpose. This is not done automatically.

Note that this has a global side effect on the whole process, because there is only one set of signal handlers.

Engines


class type ['t] job_handler_engine_type = object .. end
This type of engine also returns the job and the job_instance.
class call_engine : ?ignore_error_code:bool -> ?mode:Shell_sys.group_mode -> ?stdin:Shell.producer -> ?stdout:Shell.consumer -> ?stderr:Shell.consumer -> Shell_sys.command list -> Unixqueue.event_system -> [Shell_sys.job_status] job_handler_engine_type
This engine corresponds to Shell.call.

Examples

All examples presented for the Shell module can be easily rewritten for Shell_uq. For example, to call "ls" and collect the result in a buffer, use this piece of code:

 let ues = Unixqueue.create_unix_event_system();;
 let b = Buffer.create 10;;
 let e = new call_engine ~stdout:(Shell.to_buffer b) [ Shell.command "ls" ];;
 Unixqueue.run ues;;
 let r = Buffer.contents b;;
 

This means, one simply creates a call_engine instead of invoking Shell.call, and then runs the queue. Note that you must look at e#state to find out whether the engine e produced an error, no exception is raised in this case.

It is allowed (and somehow the purpose of this module) to create several job engines, and let them run in parallel.
ocamlnet-4.1.2/doc/html-main/Nethttpd_reactor.http_reactive_request-c.html0000644000175000017500000004761312731530353025443 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_reactive_request

Class type Nethttpd_reactor.http_reactive_request

class type http_reactive_request = object .. end

method environment : Nethttpd_types.extended_environment
The Netcgi environment representing the request header, the response header, and the channels to receive the request body and to send the response body. The channels are locked until either accept_body or reject_body have been called - using the channels before raises exceptions.

This environment is not fully CGI-compatible. In particular, the following differences exist:

  • There is no cgi_path_info and no cgi_path_translated.
  • The user is always unauthenticated.
  • The Status response header works as in CGI. The Location header, however, must be a full URL when set (only browser redirects)
  • When the request body is transmitted by chunked encoding, the header Content-Length is not set. In CGI this is interpreted as missing body. It is unlikely that clients send requests with chunked encoding, as this may cause interoperability problems anyway.

method accept_body : unit -> unit
Call this method to unlock the body channels. In terms of HTTP, this sends the "100 Continue" response when necessary. One can reply with a positive or negative message.
method reject_body : unit -> unit
Call this method to unlock the body channels. In terms of HTTP, this prevents sending the "100 Continue" response. Any arriving request body is silently discarded. One should immediately reply with an error mesage.
method finish_request : unit -> unit
Reads the rest of the body (if any), and discards that data
method finish : unit -> unit
This method should be called after the request has been fully processed. It takes care that the HTTP protocol is fulfilled, and the next request can be properly detected and parsed. If the request body has not been fully read, this is now done, and its data are dropped. If the response is incomplete, it is completed. If the error is not recoverable, a "Server Error" is generated.
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.output_async_mplex-c.html0000644000175000017500000004303112731530353025111 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.output_async_mplex

Class Uq_engines_compat.output_async_mplex

class output_async_mplex : ?onclose:[ `Ignore | `Write_eof ] -> ?onshutdown:onshutdown_out_spec -> ?buffer_size:int -> multiplex_controller -> async_out_channel_engine

ocamlnet-4.1.2/doc/html-main/type_Netstream.html0000644000175000017500000005010012731530353020266 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstream sig
  class type in_obj_stream =
    object
      method block_size : int
      method close_in : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method input_byte : unit -> int
      method input_char : unit -> char
      method input_line : unit -> string
      method pos_in : int
      method really_input : Bytes.t -> int -> int -> unit
      method really_input_string : int -> string
      method skip : int -> unit
      method want : int -> unit
      method want_another_block : unit -> unit
      method window : Netbuffer.t
      method window_at_eof : bool
      method window_length : int
    end
  class input_stream :
    ?len:int ->
    ?block_size:int -> Netchannels.in_obj_channel -> in_obj_stream
  class sub_stream :
    ?len:int -> ?delimiter:string -> Netstream.in_obj_stream -> in_obj_stream
  val print_in_obj_stream :
    Format.formatter -> Netstream.in_obj_stream -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netx509.DN_attributes.html0000644000175000017500000004643112731530353022262 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.DN_attributes sig
  val at_name : Netx509.oid
  val at_surname : Netx509.oid
  val at_givenName : Netx509.oid
  val at_initials : Netx509.oid
  val at_generationQualifier : Netx509.oid
  val at_commonName : Netx509.oid
  val at_localityName : Netx509.oid
  val at_stateOrProvinceName : Netx509.oid
  val at_organizationName : Netx509.oid
  val at_organizationalUnitName : Netx509.oid
  val at_title : Netx509.oid
  val at_dnQualifier : Netx509.oid
  val at_countryName : Netx509.oid
  val at_serialNumber : Netx509.oid
  val at_pseudonym : Netx509.oid
  val at_domainComponent : Netx509.oid
  val at_emailAddress : Netx509.oid
  val at_uid : Netx509.oid
  val attribute_types : (Netx509.oid * string * string list) list
  val lookup_attribute_type_by_oid : Netx509.oid -> string * string list
  val lookup_attribute_type_by_name :
    string -> Netx509.oid * string * string list
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.ctrl_message_receiver.html0000644000175000017500000004224512731530353025535 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.ctrl_message_receiver object
  method name : string
  method receive_admin_message :
    Netplex_types.controller -> string -> string array -> unit
  method receive_message :
    Netplex_types.controller -> string -> string array -> unit
end
ocamlnet-4.1.2/doc/html-main/Netplex_sharedvar.html0000644000175000017500000011221512731530353020747 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sharedvar

Module Netplex_sharedvar

module Netplex_sharedvar: sig .. end
Netplex-wide variables


This plugin allows to have Netplex-global variables that can be read and written by all components. These variables are useful to communicate names and other small pieces of information across the whole Netplex. For instance, one component could allocate a shared memory object, and put its name into a variable to make it known to other components.

This implementation works in both multi-processing and multi-threading netplex environments. It is, however, not very fast, because the variables live in the controller, and the access operations are realized by RPC's. It is good enough when these operations are only infrequently called, e.g. in the post-start and pre-finish processor callbacks.

Furthermore, note that it is unwise to put large values into variables when using them in multi-processing contexts. The controller process is also the parent process of all forked children, and when a lot of memory is allocated in the controller, all this memory needs to be copied when the fork is done. As workaround, put such values into temporary files, and only pass the names of the files around via variables.

Variables come in two flavors:

A string variable cannot be accessed as encapsulated variable, and vice versa.

The latter kind is useful to safely store structured ocaml values in Netplex variables.

More documentation can also be found here: Storing global state

Thread safety: Full. The functions can be called from any thread.

exception Sharedvar_type_mismatch of string
The (dynamically typed) variable has the wrong type (string/exn)
exception Sharedvar_no_permission of string
It is not allowed to set the value
exception Sharedvar_not_found of string
The variable does not exist. Only used by Make_var_type
exception Sharedvar_null
The initial value of a shared exception variable
val plugin : Netplex_types.plugin
To enable shared variables, call the controller's add_plugin method with this object as argument. This can e.g. be done in the post_add_hook of the processor.

Classical API



Classical API



Most of the folloing functions can be invoked in both container and controller contexts, with the notable exception of wait_for_value.
val create_var : ?own:bool ->
?ro:bool -> ?enc:bool -> ?timeout:float -> ?ssn:string -> string -> bool
Create the variable with the passed name with an empty string (or the exception Sharedvar_null) as initial value. If the creation is possible (i.e. the variable did not exist already), the function returns true, otherwise the already existing variable is left unchanged, and false is passed back. By default, the variable can be modified and deleted by any other container. Two options allow you to change that:

  • own: If true, the created variable is owned by the calling socket service. Only the caller can delete it, and when the last component of the socket service terminates, the variable is automatically deleted. The deletion happens after the post_finish_hook is executed, so the variable is still accessible from this hook. Note that the controller has unlimited access anyway.
  • ro: if true, only the owner can set the value
  • enc: if true, the variable stores encapsulated values, otherwise strings (defaults to false)
  • timeout: if passed, the variable will be automatically deleted after this number of seconds. The timeout starts anew with every read or write of the variable.
  • ssn: If called from the controller and own, this must be set to the socket service name of the owner
Variable names are global to the whole netplex system. By convention, these names are formed like "service_name.local_name", i.e. they are prefixed by the socket service to which they refer.
val delete_var : string -> bool
delete_var name: Deletes the variable name. Returns true if the deletion could be carried out, and false when the variable does not exist, or the container does not have permission to delete the variable.
val set_value : string -> string -> bool
set_value name value: Sets the variable name to value. This is only possible when the variable exists, and is writable. Returns true if the function is successful, and false when the variable does not exist.

Raises Sharedvar_no_permission if the variable cannot be modified.

Raises Sharedvar_type_mismatch if the variable is not a string variable.

val set_enc_value : string -> Netplex_types.encap -> bool
set_enc_value name value: Sets the variable name to value. Return value as for set_value.

Raises Sharedvar_no_permission if the variable cannot be modified.

Raises Sharedvar_type_mismatch if the variable is not encapsulated

val get_value : string -> string option
get_value name: Gets the value of the variable name. If the variable does not exist, None is returned.

Raises Sharedvar_type_mismatch if the variable is not a string variable.

val get_enc_value : string -> Netplex_types.encap option
get_enc_value name: Gets the value of the variable name. If the variable does not exist, None is returned.

Raises Sharedvar_type_mismatch if the variable is not encapsulated

val wait_for_value : string -> string option
wait_for_value name: If the variable exists and set_value has already been called at least once, the current value is returned. If the variable exists, but set_value has not yet been called at all, the function waits until set_value is called, and returns the value set then. If the variable does not exist, the function immediately returns None.

An ongoing wait is interrupted when the variable is deleted. In this case None is returned.

This function can only be invoked from container context!

val wait_for_enc_value : string -> Netplex_types.encap option
Same for encapsulated variables
val get_lazily : string -> (unit -> string) -> string option
get_lazily name f: Uses the variable name to ensure that f is only invoked when get_lazily is called for the first time, and that the value stored in the variable is returned the next times. This works from whatever component get_lazily is called.

If f() raises an exception, the exception is suppressed, and None is returned as result of get_lazily. Exceptions are not stored in the variable, so the next time get_lazily is called it is again tried to compute the value of f(). If you want to catch the exception this must done in the body of f.

No provisions are taken to delete the variable. If delete_var is called by user code (which is allowed at any time), and get_lazily is called again, the lazy value will again be computed.

This function can only be invoked from container context!

val get_enc_lazily : string -> (unit -> Netplex_types.encap) -> Netplex_types.encap option
Same for encapsulated values
val dump : string -> Netlog.level -> unit
Dumps the access counter of this variable to Netlog. The string argument "*" dumps all variables.

API with versioned access



API with versioned access



The API with versioned values can very quickly check whether newer values are available (the check consists just of a memory read). If a newer version is avaiable, the value still needs to be retrieved with an RPC call, though.

The central function is vv_update. See also the limitations mentioned there.

type 'a versioned_value 
Cache for the current value
val vv_access : string -> string versioned_value
Get the current value of this variable. This succeeds even when the variable does not exist.
val vv_access_enc : string -> Netplex_types.encap versioned_value
Same for encapsulated variables
val vv_get : 'a versioned_value -> 'a option
Extract the current value, or None if the variable cannot be found.
val vv_version : 'a versioned_value -> int64
Get the current version number. The version number is increased by every "set" operation. Raised Not_found if the variable cannot be found.
val vv_update : 'a versioned_value -> bool
Check whether there is a new version of the value, and update the cache. Return whether the update occurred.

Note that there is a limitation on the number of variables that can use vv_update. For every versioned_value a slot in a shared memory segment is allocated. However, there is only a limited number of such slots (currently 1023). If more slots are needed, the performance will be degraded.

val vv_set : 'a versioned_value -> 'a -> bool
Set the current value. Return whether successful

Classical functor


module Make_var_type: 
functor (T : Netplex_cenv.TYPE) -> Netplex_cenv.VAR_TYPE with type t = T.t
Creates a module with get and set functions to access variables of type T.t.

Functor with versioned access


module type VV_TYPE = sig .. end
module Make_vv: 
functor (T : Netplex_cenv.TYPE) -> VV_TYPE with type t = T.t

Netsys_global



Netsys_global



This is a propagator for Netsys_global. It is automatically activated when the Netplex controller is started.
val global_propagator : unit -> Netsys_global.propagator
Create a new propagator, and initialize Netplex_sharedvar with the current variables from Netsys_global. Note that a global variable with name n appears in Netplex as variable "global." ^ n.

The version numbers appearing in both modules are unrelated.

This function must be called from controller context.

val propagate_back : Netplex_types.controller -> unit
Copy the global variables from Netplex_sharedvar (with prefix "global.") back to Netsys_global

Examples



Examples



Example code:

Here, one randomly chosen container computes precious_value, and makes it available to all others, so the other container can simply grab the value. This is similar to what get_lazily does internally:

      let get_precious_value() =
        let container = Netplex_cenv.self_cont() in
        let var_name = "my_service.precious" in
        if Netplex_sharedvar.create_var var_name then (
          let precious_value = 
            try ...    (* some costly computation *)
            with exn ->
              ignore(Netplex_sharedvar.delete_var var_name);
              raise exn in
          let b = Netplex_sharedvar.set_value var_name precious_value in
          assert b;
          precious_value
        )
        else (
          match Netplex_sharedvar.wait_for_value var_name with
           | Some v -> v
           | None -> failwith "get_precious_value"
                       (* or do plan B, e.g. compute the value *)
        )
    

We don't do anything here for deleting the value when it is no longer needed. Finding a criterion for that is very application-specific. If the variable can be thought as being another service endpoint of a socket service, it is a good idea to acquire the ownership (by passing ~own:true to create_var), so the variable is automatically deleted when the socket service stops.

Of course, the plugin must be enabled, e.g. by overriding the post_add_hook processor hook:

 
    method post_add_hook sockserv ctrl =
      ctrl # add_plugin Netplex_sharedvar.plugin
   

ocamlnet-4.1.2/doc/html-main/type_Netcgi.html0000644000175000017500000014672212731530353017555 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi sig
  class type cgi_argument =
    object
      method charset : string
      method content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method filename : string option
      method finalize : unit -> unit
      method name : string
      method open_value_rd : unit -> Netchannels.in_obj_channel
      method representation :
        [ `MIME of Netmime.mime_message | `Simple of Netmime.mime_body ]
      method store : [ `File of string | `Memory ]
      method value : string
    end
  module Argument :
    sig
      exception Oversized
      val simple : string -> string -> Netcgi.cgi_argument
      val mime :
        ?work_around_backslash_bug:bool ->
        ?name:string -> Netmime.mime_message -> Netcgi.cgi_argument
      val clone :
        ?name:string ->
        ?value:string ->
        ?msg:Netmime.mime_message ->
        Netcgi.cgi_argument -> Netcgi.cgi_argument
      val set :
        Netcgi.cgi_argument list ->
        Netcgi.cgi_argument list -> Netcgi.cgi_argument list
    end
  class type rw_cgi_argument =
    object
      method charset : string
      method content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method filename : string option
      method finalize : unit -> unit
      method name : string
      method open_value_rd : unit -> Netchannels.in_obj_channel
      method open_value_wr : unit -> Netchannels.out_obj_channel
      method representation :
        [ `MIME of Netmime.mime_message | `Simple of Netmime.mime_body ]
      method ro : bool
      method set_value : string -> unit
      method store : [ `File of string | `Memory ]
      method value : string
    end
  class simple_argument : ?ro:bool -> string -> string -> rw_cgi_argument
  class mime_argument :
    ?work_around_backslash_bug:bool ->
    string -> Netmime.mime_message -> rw_cgi_argument
  module Cookie :
    sig
      type t = Nethttp.Cookie.t
      val make :
        ?max_age:int ->
        ?domain:string ->
        ?path:string ->
        ?secure:bool ->
        ?comment:string ->
        ?comment_url:string ->
        ?ports:int list -> string -> string -> Netcgi.Cookie.t
      val name : Netcgi.Cookie.t -> string
      val value : Netcgi.Cookie.t -> string
      val domain : Netcgi.Cookie.t -> string option
      val path : Netcgi.Cookie.t -> string option
      val ports : Netcgi.Cookie.t -> int list option
      val max_age : Netcgi.Cookie.t -> int option
      val secure : Netcgi.Cookie.t -> bool
      val comment : Netcgi.Cookie.t -> string
      val comment_url : Netcgi.Cookie.t -> string
      val set_value : Netcgi.Cookie.t -> string -> unit
      val set_max_age : Netcgi.Cookie.t -> int option -> unit
      val set_domain : Netcgi.Cookie.t -> string option -> unit
      val set_path : Netcgi.Cookie.t -> string option -> unit
      val set_secure : Netcgi.Cookie.t -> bool -> unit
      val set_comment : Netcgi.Cookie.t -> string -> unit
      val set_comment_url : Netcgi.Cookie.t -> string -> unit
      val set_ports : Netcgi.Cookie.t -> int list option -> unit
      val of_netscape_cookie : Nethttp.netscape_cookie -> Netcgi.Cookie.t
      val to_netscape_cookie : Netcgi.Cookie.t -> Nethttp.netscape_cookie
    end
  type http_method = [ `DELETE | `GET | `HEAD | `POST | `PUT ]
  type config =
    Netcgi_common.config = {
    tmp_directory : string;
    tmp_prefix : string;
    permitted_http_methods : Netcgi.http_method list;
    permitted_input_content_types : string list;
    input_content_length_limit : int;
    max_arguments : int;
    workarounds :
      [ `Backslash_bug
      | `MSIE_Content_type_bug
      | `Work_around_MSIE_Content_type_bug
      | `Work_around_backslash_bug ] list;
    default_exn_handler : bool;
  }
  val default_config : Netcgi.config
  class type cgi_environment =
    object
      method cgi_auth_type : string
      method cgi_gateway_interface : string
      method cgi_https : bool
      method cgi_path_info : string
      method cgi_path_translated : string
      method cgi_properties : (string * string) list
      method cgi_property : ?default:string -> string -> string
      method cgi_query_string : string
      method cgi_remote_addr : string
      method cgi_remote_host : string
      method cgi_remote_ident : string
      method cgi_remote_user : string
      method cgi_request_method : string
      method cgi_script_name : string
      method cgi_server_name : string
      method cgi_server_port : int option
      method cgi_server_protocol : string
      method cgi_server_software : string
      method config : Netcgi.config
      method cookie : string -> Netcgi.Cookie.t
      method cookies : Netcgi.Cookie.t list
      method input_content_length : int
      method input_content_type :
        unit -> string * (string * Netmime_string.s_param) list
      method input_content_type_string : string
      method input_header : Netmime.mime_header
      method input_header_field : ?default:string -> string -> string
      method input_header_fields : (string * string) list
      method log_error : string -> unit
      method multiple_input_header_field : string -> string list
      method multiple_output_header_field : string -> string list
      method out_channel : Netchannels.out_obj_channel
      method output_ch : Netchannels.out_obj_channel
      method output_header : Netmime.mime_header
      method output_header_field : ?default:string -> string -> string
      method output_header_fields : (string * string) list
      method protocol : Nethttp.protocol
      method send_output_header : unit -> unit
      method set_multiple_output_header_field : string -> string list -> unit
      method set_output_header_field : string -> string -> unit
      method set_output_header_fields : (string * string) list -> unit
      method set_status : Nethttp.http_status -> unit
      method user_agent : string
    end
  type other_url_spec = [ `Env | `None | `This of string ]
  type query_string_spec =
      [ `Args of Netcgi.rw_cgi_argument list
      | `Env
      | `None
      | `This of Netcgi.cgi_argument list ]
  type cache_control = [ `Max_age of int | `No_cache | `Unspecified ]
  class type cgi =
    object
      method argument : string -> Netcgi.cgi_argument
      method argument_exists : string -> bool
      method argument_value : ?default:string -> string -> string
      method arguments : Netcgi.cgi_argument list
      method at_exit : (unit -> unit) -> unit
      method environment : Netcgi.cgi_environment
      method finalize : unit -> unit
      method multiple_argument : string -> Netcgi.cgi_argument list
      method out_channel : Netchannels.trans_out_obj_channel
      method output : Netchannels.trans_out_obj_channel
      method request_method :
        [ `DELETE | `GET | `HEAD | `POST | `PUT of Netcgi.cgi_argument ]
      method set_header :
        ?status:Nethttp.http_status ->
        ?content_type:string ->
        ?content_length:int ->
        ?set_cookie:Nethttp.cookie list ->
        ?set_cookies:Netcgi.Cookie.t list ->
        ?cache:Netcgi.cache_control ->
        ?filename:string ->
        ?language:string ->
        ?script_type:string ->
        ?style_type:string ->
        ?fields:(string * string list) list -> unit -> unit
      method set_redirection_header :
        ?set_cookies:Netcgi.Cookie.t list ->
        ?fields:(string * string list) list -> string -> unit
      method url :
        ?protocol:Nethttp.protocol ->
        ?with_authority:Netcgi.other_url_spec ->
        ?with_script_name:Netcgi.other_url_spec ->
        ?with_path_info:Netcgi.other_url_spec ->
        ?with_query_string:Netcgi.query_string_spec -> unit -> string
    end
  class type cgi_activation = cgi
  type output_type =
      [ `Direct of string
      | `Transactional of
          Netcgi.config ->
          Netchannels.out_obj_channel -> Netchannels.trans_out_obj_channel ]
  val buffered_transactional_outtype : Netcgi.output_type
  val buffered_transactional_optype : Netcgi.output_type
  val tempfile_transactional_outtype : Netcgi.output_type
  val tempfile_transactional_optype : Netcgi.output_type
  type arg_store =
      Netcgi.cgi_environment ->
      string ->
      Netmime.mime_header_ro ->
      [ `Automatic
      | `Automatic_max of float
      | `Discard
      | `File
      | `File_max of float
      | `Memory
      | `Memory_max of float ]
  type exn_handler = Netcgi.cgi_environment -> (unit -> unit) -> unit
  type connection_directive =
      [ `Conn_close
      | `Conn_close_linger
      | `Conn_error of exn
      | `Conn_keep_alive ]
end
ocamlnet-4.1.2/doc/html-main/Uq_multiplex.datagram_multiplex_controller-c.html0000644000175000017500000004363412731530353026336 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_multiplex.datagram_multiplex_controller

Class type Uq_multiplex.datagram_multiplex_controller

class type datagram_multiplex_controller = object .. end
Additional methods for unconnected datagram handling
Inherits
method received_from : Unix.sockaddr
Returns the socket address of the last received datagram. This value is updated just before the when_done callback of the reader is invoked.
method send_to : Unix.sockaddr -> unit
Sets the socket address of the next datagram to send.
ocamlnet-4.1.2/doc/html-main/type_Nethttp.http_trailer.html0000644000175000017500000004057512731530353022471 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp.http_trailer Netmime.mime_headerocamlnet-4.1.2/doc/html-main/index_module_types.html0000644000175000017500000005521012731530353021172 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of module types

Index of module types


A
AT_LOOKUP [Netdn]

C
CIPHERS [Netsys_crypto_modes]
CONFIG [Netgssapi_auth]

D
DBI_DRIVER [Netcgi_dbi]
DBI_POOL [Netcgi_dbi]
DIGESTS [Netsys_crypto_types]
DN_string [Netdn]

E
ENCAP [Netplex_encap]
ENCDEC [Netnumber]

F
FILE_TLS_ENDPOINT [Netsys_crypto_types]
FUN_TYPE [Netplex_cenv]
Abstraction for function types s->t

G
GNUTLS_ENDPOINT [Nettls_gnutls]
GNUTLS_PROVIDER [Nettls_gnutls]
GSSAPI [Netsys_gssapi]

H
HTTP_CLIENT_MECHANISM [Nethttp]

L
LEVER [Netplex_cenv]
LIBOEVENT [Uq_libevent]

M
MBOX [Netplex_mbox]
The type of mailboxes mbox with messages of type t

P
POLLSET [Uq_libevent]
PROFILE [Netmech_spnego_http]
PROFILE [Netmech_gs2_sasl]
PROFILE [Netmech_digest_http]
PROFILE [Netmech_scram_http]
PROFILE [Netmech_scram_sasl]
The profile sets some basic parameters.
PUBKEY_CRYPTO [Netsys_crypto_types]

S
SASL_MECHANISM [Netsys_sasl_types]
SYMMETRIC_CRYPTO [Netsys_crypto_types]

T
TLS_CONFIG [Netsys_crypto_types]
TLS_ENDPOINT [Netsys_crypto_types]
TLS_EXCEPTIONS [Netsys_crypto_types]
The exceptions the TLS provider may use (in addition to OCaml's built-in exception).
TLS_PROVIDER [Netsys_crypto_types]
TYPE [Netplex_encap]
Just a (monomorphic) type t
TYPE [Netplex_cenv]
Just a (monomorphic) type t

U
USE_CLIENT [Rpc_client]
This module type is what the generated "clnt" module assumes about the client interface

V
VAR_TYPE [Netplex_cenv]
A (monomorphic) type t with two functions get and set accessing the container variables
VV_TYPE [Netplex_sharedvar]
ocamlnet-4.1.2/doc/html-main/type_Netsys_gssapi.server_props.html0000644000175000017500000004231212731530353023715 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.server_props object
  method deleg_credential : (exn * Netsys_gssapi.time) option
  method flags : Netsys_gssapi.ret_flag list
  method initiator_name : string * Netsys_gssapi.oid
  method initiator_name_exported : string
  method mech_type : Netsys_gssapi.oid
  method time : Netsys_gssapi.time
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.delay_engine.html0000644000175000017500000004150312731530353024415 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.delay_engine float ->
(unit -> '#Uq_engines_compat.engine) ->
Unixqueue.event_system -> ['a] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/Rpc_client.default_socket_config-c.html0000644000175000017500000004214412731530353024116 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.default_socket_config

Class Rpc_client.default_socket_config

class default_socket_config : socket_config
Default configuration as class

ocamlnet-4.1.2/doc/html-main/Netshm_hashtbl.html0000644000175000017500000005777012731530353020252 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netshm_hashtbl

Module Netshm_hashtbl

module Netshm_hashtbl: sig .. end
Hash tables in shared memory

type ('a, 'b) t 
val manage : ?pagesize:int ->
?init:int ->
'a Netshm_data.data_manager ->
'b Netshm_data.data_manager ->
Netshm.locking_method -> Netshm.shm_descr -> ('a, 'b) t
Manages a shared memory object as a hash table like Netshm.manage, and additionally represent arbitrary O'Caml values.

It is essential that the same data managers are passed as at the time when the hash table was initialized.

For example, to get a hash table from int to string, use

 manage Netshm_data.int_manager Netshm_data.string_manager lm sd 

val add : ('a, 'b) t -> 'a -> 'b -> unit
add tbl key value: Adds the binding of key to value to the table. Previous bindings are not removed, but simply hidden.
val find : ('a, 'b) t -> 'a -> 'b
find tbl key: Finds the current binding of key in tbl or raises Not_found if no such binding exists.
val find_all : ('a, 'b) t -> 'a -> 'b list
find_all tbl key returns the list of all data associated with key in tbl. The current binding is returned first, then the previous bindings, in reverse order of introduction in the table.
val mem : ('a, 'b) t -> 'a -> bool
mem tbl key checks if key is bound in tbl.
val remove : ('a, 'b) t -> 'a -> unit
remove tbl key removes the current binding of key in tbl, restoring the previous binding if it exists. It does nothing if key is not bound in tbl.
val replace : ('a, 'b) t -> 'a -> 'b -> unit
replace tbl key value replaces the current binding of key in tbl by a binding of key to value. If key is unbound in tbl, a binding of key to value is added to tbl.
val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit
iter f tbl applies f to all bindings in table tbl. f receives the key as first argument, and the associated value as second argument. Each binding is presented exactly once to f. The order in which the bindings are passed to f is unspecified. However, if the table contains several bindings for the same key, they are passed to f in reverse order of introduction, that is, the most recent binding is passed first.

While the iteration is in progress, the table is locked. That means you cannot modify it during the iteration.

val iter_keys : ('a -> unit) -> ('a, 'b) t -> unit
iter_keys f tbl applies f to all keys in table tbl. If there are several bindings for a key, f is only called once.

While the iteration is in progress, the table is locked. That means you cannot modify it during the iteration.

val fold : ('a -> 'b -> 'c -> 'c) -> ('a, 'b) t -> 'c -> 'c
fold f tbl init computes (f kN dN ... (f k1 d1 init)...), where k1 ... kN are the keys of all bindings in tbl, and d1 ... dN are the associated values. Each binding is presented exactly once to f. The order in which the bindings are passed to f is unspecified. However, if the table contains several bindings for the same key, they are passed to f in reverse order of introduction, that is, the most recent binding is passed first.

While the iteration is in progress, the table is locked. That means you cannot modify it during the iteration.

val length : ('a, 'b) t -> int
length tbl returns the number of bindings in tbl. Multiple bindings are counted multiply, so length gives the number of times iter calls its first argument.
val shm_table : ('a, 'b) t -> Netshm.shm_table
Returns the underlying shared memory table used to implement hash tables.
ocamlnet-4.1.2/doc/html-main/Nethttp_client.get-c.html0000644000175000017500000004222712731530353021260 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.get

Class Nethttp_client.get

class get : string -> http_call
Argument: URI

ocamlnet-4.1.2/doc/html-main/Equeue.Debug.html0000644000175000017500000004312412731530353017551 0ustar gerdgerd Ocamlnet 4 Reference Manual : Equeue.Debug

Module Equeue.Debug

module Debug: sig .. end

type debug_target = [ `Any | `Process of int | `Thread of int ] 
val enable : bool Pervasives.ref
Enable Netlog debugging
val set_debug_mode : bool -> unit
Sets enable.
val set_debug_target : debug_target -> unit
Restricts debugging to this target.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.sync_engine.html0000644000175000017500000004146612731530353022740 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.sync_engine '#Uq_engines.engine -> '#Uq_engines.engine -> ['a * 'b] Uq_engines.engineocamlnet-4.1.2/doc/html-main/type_Netsaslprep.html0000644000175000017500000004142612731530353020637 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsaslprep sig
  exception SASLprepError
  val saslprep_a : int array -> int array
  val saslprep : string -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.out_obj_channel.html0000644000175000017500000004501012731530353023722 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.out_obj_channel object
  method close_out : unit -> unit
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method output_buffer : Buffer.t -> unit
  method output_byte : int -> unit
  method output_bytes : Bytes.t -> unit
  method output_channel : ?len:int -> in_obj_channel -> unit
  method output_char : char -> unit
  method output_string : string -> unit
  method pos_out : int
  method really_output : Bytes.t -> int -> int -> unit
  method really_output_string : string -> int -> int -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Unixqueue_select.select_based_event_system.html0000644000175000017500000004072612731530353027111 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_select.select_based_event_system unit -> Unixqueue_select.sb_event_systemocamlnet-4.1.2/doc/html-main/Netchannels.augment_raw_in_channel-c.html0000644000175000017500000004507312731530353024450 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.augment_raw_in_channel

Class virtual Netchannels.augment_raw_in_channel

class virtual augment_raw_in_channel : object .. end
This class implements the methods from compl_in_channel by calling the methods of raw_in_channel. There is no additional buffering. The performance of the method input_line is very bad (consider to override it, e.g. by enhanced_input_line as defined below).
Inherits
method virtual input : Bytes.t -> int -> int -> int
As in raw_in_channel
method virtual close_in : unit -> unit
As in raw_in_channel
method virtual pos_in : int
As in raw_in_channel
ocamlnet-4.1.2/doc/html-main/type_Netsys_gssapi.GSSAPI.gss_api.html0000644000175000017500000004130012731530353023572 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.GSSAPI.gss_api [Netsys_gssapi.GSSAPI.credential, Netsys_gssapi.GSSAPI.name,
 Netsys_gssapi.GSSAPI.context]
Netsys_gssapi.poly_gss_api
ocamlnet-4.1.2/doc/html-main/type_Netplex_kit.html0000644000175000017500000006470412731530353020631 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit sig
  class type virtual v_processor =
    object
      method config_internal :
        (string * Netplex_types.polysocket_kind_box) list
      method container_event_system : unit -> Unixqueue.event_system
      method container_run : Unixqueue.event_system -> unit
      method global_exception_handler : exn -> bool
      method post_add_hook :
        Netplex_types.socket_service -> Netplex_types.controller -> unit
      method post_finish_hook :
        Netplex_types.socket_service ->
        Netplex_types.controller -> Netplex_types.container_id -> unit
      method post_rm_hook :
        Netplex_types.socket_service -> Netplex_types.controller -> unit
      method post_start_hook : Netplex_types.container -> unit
      method pre_finish_hook : Netplex_types.container -> unit
      method pre_start_hook :
        Netplex_types.socket_service ->
        Netplex_types.controller -> Netplex_types.container_id -> unit
      method virtual process :
        when_done:(unit -> unit) ->
        Netplex_types.container -> Unix.file_descr -> string -> unit
      method process_internal :
        when_done:(unit -> unit) ->
        Netplex_types.container ->
        Netplex_types.polyserver_box -> string -> unit
      method receive_admin_message :
        Netplex_types.container -> string -> string array -> unit
      method receive_message :
        Netplex_types.container -> string -> string array -> unit
      method shutdown : unit -> unit
      method virtual supported_ptypes :
        Netplex_types.parallelization_type list
      method system_shutdown : unit -> unit
      method workload_hook : Netplex_types.container -> bool -> int -> unit
    end
  class empty_processor_hooks : unit -> Netplex_types.processor_hooks
  class processor_hooks_delegation :
    Netplex_types.processor_hooks -> Netplex_types.processor_hooks
  class virtual processor_base : Netplex_types.processor_hooks -> v_processor
  class protocol_switch_processor :
    (string * Netplex_types.processor) list -> Netplex_types.processor
  class protocol_switch_factory :
    string ->
    (string * Netplex_types.processor_factory) list ->
    Netplex_types.processor_factory
  val add_helper_service :
    Netplex_types.controller ->
    string -> Netplex_types.processor_hooks -> unit
  val create_protocol :
    ?lstn_backlog:int ->
    ?lstn_reuseaddr:bool ->
    ?so_keepalive:bool ->
    ?tcp_nodelay:bool ->
    ?local_chmod:int ->
    ?local_chown:int * int ->
    ?configure_slave_socket:(Unix.file_descr -> unit) ->
    string -> Netplex_types.extended_address array -> Netplex_types.protocol
  val create_socket_service_config :
    ?startup_timeout:float ->
    ?change_user_to:int * int ->
    ?gc_when_idle:bool ->
    ?conn_limit:int ->
    string ->
    Netplex_types.protocol list ->
    Netplex_types.controller_config -> Netplex_types.socket_service_config
end
ocamlnet-4.1.2/doc/html-main/Netclient_tut.html0000644000175000017500000011546612731530353020125 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netclient_tut

Netclient_tut


Netclient tutorial

Here we give some recipes how to submit HTTP and FTP requests to servers. There is a quite simple interface representing the hierarchy of remote files, which is recommended for all occasional uses. If performance is important, however, the protocol-specific interfaces will give you more options.

Accessing HTTP and FTP as filesystem

Let's start with an example: We want to get the public files

  • http://foo.org/bar
  • ftp://foo.org/baz
For HTTP we need a filesystem object accessing the foo.org server:

let fs1 = Nethttp_fs.http_fs "http://foo.org"

The same for FTP looks like:

let fs2 = Netftp_fs.ftp_fs "ftp://foo.org"

The objects fs1 and fs2 provide now a number of methods for accessing files. These do not only cover downloads, but also listing directories, writing files, renaming files, and a number of further operations. The commonly available methods are those of Netfs.stream_fs. The incarnations of this interface for concrete protocols usually define more methods. It is guaranteed that you can coerce the types to Netfs.stream_fs, though:

let my_filesystems =
  [ (fs1 :> Netfs.stream_fs); (fs2 :> Netfs.stream_fs) ]

The method we use here is read:

method read : read_flags -> string -> Netchannels.in_obj_channel

All access methods take a list of flags as first argument. For example, a possible flag here is `Binary switching to binary mode for the protcols where it makes a difference (like FTP).

The second argument is the file path, using slashes as separators, and always starting with a slash. The path is appended to the base URL given when creating the fs1 and fs2 objects. Note that the path must not contain any URL-specific encodings like "%xx".

We get a an Netchannels.in_obj_channel back we can read the data from:

let c1 = fs1 # read [] "/bar"
let s1 = Netchannels.string_of_in_obj_channel c1
let () = c1 # close_in()

let c2 = fs2 # read [`Binary] "/baz"
let s2 = Netchannels.string_of_in_obj_channel c2
let () = c2 # close_in()

It depends very much on the implementation what actually happens:

  • HTTP has built-in resilience against errors. Downloads are tried again if errors occur.
  • HTTP follows redirects automatically, perhaps pointing to a different server.
  • FTP does not retry after errors.
  • The possible error codes can be different. For example, FTP does not distinguish between "access denied" and "file not found".
You should keep in mind that the protocol differences do not go away, just because we are mapping the protocols to a common interface here.

By default, the downloaded data are cached in a temporary file. Some implementations support the streaming mode to avoid that (like HTTP), and you are directly connected with the reading socket when reading from the returned in_obj_channel. Pass `Streaming as flag to read to enable this. In streaming mode, however, neither retries nor redirects are possible.

Other access methods

An overview:

  • write works very much like read, only that you get a Netchannels.out_obj_channel back. The network write operation normally starts first when this channel is closed, and the so-far cached data are uploaded to the server. For HTTP there is also a streaming mode. The write operation takes also flags that look like normal open flags, i.e. whether you want to create a file, truncate a file, or ensure the unique creation. Not all protocols support every combination, though. For HTTP a write is translated to sending a PUT method to the server.
  • readdir reads the names of a directory. For FTP this is clearly an NLST command. For HTTP the implementation just extracts the names from the hyperlinks contained in the page - this works well for applying readdir to automatically generated file indexes.
  • remove translates to the DELETE method for HTTP. This method is defined in the HTTP standard, but usually not available on servers, though.
  • size gets the size of a file. This may work for HTTP or may not - depending on whether the server knows the size (which is often not the case for dynamically generated content). For FTP there is the SIZE command. However, this is a later addition to the protocol, and may not be available on ancient servers.
  • test and test_list allow it to test properties of files (existence, type, non-empty, accessibility). This is only partially implemented for HTTP and FTP.
The following operations are only applicable to FTP:

  • rename
  • mkdir
  • rmdir
There are also operations that do not make sense here:

  • symlink
  • readlink
  • copy

Other filesystem implementations

There is a full implementation of Netfs.stream_fs for accessing local files: Netfs.local_fs. There are more definitions inside and outside Ocamlnet, see Other impementations of stream_fs for a list. It also mentions a WebDAV implementation extending the HTTP definition explained here, and which covers a larger set of access operations.

Configuring HTTP and FTP file accesses

When creating the access object, one can set a callback that allows almost arbitrary configurations:

let fs1 = 
  Nethttp_fs.http_fs
     ~config_pipeline:(fun p -> ...)
     "http://foo.org"

let fs2 = 
  Netftp_fs.ftp_fs 
     ~config_client:(fun c -> ...)
     "ftp://foo.org"

Here, p and c are the underlying protocol implementations.

Simple authentication for HTTP

Do it like this in the config_pipeline callback:

  let user = "user" in
  let password = "secret" in
  let realm = "the realm string" in
  let domain = [ "http://foo.org " ] in
  let keys = new Nethttp_client.key_ring() in
  keys # add_key (Nethttp_client.key ~user ~password ~realm ~domain);
  let ah = new Nethttp_client.unified_auth_handler keys in
  p # add_auth_handler ah

The Nethttp_client.unified_auth_handler implements at the moment the "basic" and "digest" schemes (and will probably be extended in the future). On unencrypted transports the "basic" scheme is disabled by default. With

 new Nethttp_client.unified_auth_handler ~insecure:bool keys 

the "basic" scheme is always enabled. (Note that the "basic" scheme sends the password in clear text. See below how to activate TLS.)

Simple authentication for FTP

This is not done in the config_client callback, but directly when creating the filesystem object. The user string is always taken from the URL (as normally the accessed file space depends on the user). Passwords and account names (if needed) are supplied by callbacks:

let fs2 = 
   Netftp_fs.ftp_fs
      ~get_password:(fun () -> "secret")
      ~get_account:(fun () -> "account")
      "ftp://user@foo.org"

Configure a web proxy for HTTP

Do it like this in the config_pipeline callback:

  p # set_proxy "proxy.company.net" 8080;
  p # set_proxy_auth "user" "secret";
  p # avoid_proxy_for [ ".company.net"; "localhost" ]

Or you can just import this data from the environment variables "http_proxy" and "no_proxy":

  p # set_proxy_from_environment()

Configure a web proxy for FTP

Web proxies often also support FTP URLs, but only for a limited set of operations (often only read works).

Note that you have to use Nethttp_fs to use this feature, not Netftp_fs:

let fs1 = 
  Nethttp_fs.http_fs
     ~config_pipeline:(fun p ->
        p # set_proxy "proxy.company.net" 8080;
        p # set_proxy_auth "user" "secret";
     )
     ~enable_ftp:true
     "ftp://foo.org"

In this configuration, the web proxy is contacted via HTTP, and the proxy talks FTP with the content server.

If you do not configure the proxy, any accesses will fail (no transport error).

Configure a SOCKS proxy for HTTP

This is an alternative to a web proxy. Do it like this in the config_pipeline callback:

  p # set_socks5_proxy "proxy.company.net" 1080

Configure a SOCKS proxy for FTP

Do it like this in the config_client callback:

  c # set_socks5_proxy "proxy.company.net" 1080

The current implementation is limited to file transfers in passive mode, though. This is nowadays not a problem anymore, because almost all FTP servers support it.

Configure HTTPS

In order to use HTTPS the TLS provider must be initialized. This is normally GnuTLS:

Once this is done, the HTTP client can also process "https" URLs.

NB. In previous versions of OCamlnet there was a separate "Https_client" module. This module does not exist anymore, as its functionality is integrated into the main Nethttp_client module.

NB. The server is authenticated by default, using the system-wide list of CA certificates.

Configure FTPS

You can also enable TLS for FTP connections if the server supports it (of course, you also need to activate GnuTLS as described in the section above):

let fs2 = 
   Netftp_fs.ftp_fs
      ...
      ~tls_enabled:true
      ~tls_required:true   (* or false *)
      "ftp://user@foo.org"

NB. The server is authenticated by default, using the system-wide list of CA certificates.

Globbing

The Netglob module can be used to interpret wildcards in filenames. An example:

let files =
  Netglob.glob
    ~fsys:(Netglob.of_stream_fs (fs2 :> Netfs.stream_fs))
    (`String "/dir/*.gif")

This would return paths to all gif files in /dir on the FTP server fs2.

Caveat: Globbing works only well if the server provides the operations for recognizing directories. Most FTP servers don't - only the recently (1) added MLST command allows it to safely recognize directories.

(1) recently = many years ago, but existing FTP deployments seem only to be very slowly upgraded.

Test whether an FTP server supports MLST: There must be a line for MLST in the output for the FEAT command, like in

$ ftp localhost
Connected to localhost.
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
...
ftp> quote feat
211-Extensions supported:
 EPRT
 IDLE
 MDTM
 SIZE
 REST STREAM
 MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
 MLSD
 AUTH TLS
 PBSZ
 PROT
 UTF8
 TVFS
 ESTA
 PASV
 EPSV
 SPSV
 ESTP
211 End.

For HTTP servers, the recognition of directories is even worse. Don't rely on it.

Copying

There are the generic copy algorithms Netfs.copy and Netfs.copy_into, which can also be used for HTTP and FTP.

For example, let's copy the file "/xyz" from fs1 to fs2, i.e. from an HTTP server to an FTP server:

Netfs.copy (fs1 :> Netfs.stream_fs) "/xyz" (fs2 : Netfs.stream_fs) "/xyz"

Iterating files

There is the generic file iterator Netfs.iter, which walks through the directory hierarchy on the server:

Netfs.iter
  ~pre:(fun name kind symkind -> ...)
  (fs2 :> Netfs.stream_fs)
  "/"

Note that you may run into problems in conjunction with HTTP and FTP:

  • HTTP may redirect file accesses, and the iterator is not aware of this
  • FTP does not represent symlinks as such, and the iterator would follow symlink loops infinitely
  • Both HTTP and FTP have problems recognizing directories (see the remarks about globbing above).

Accessing HTTP via Nethttp_client

The Nethttp_client module is the real implementation of HTTP. It is asynchronous, which means it can do many tasks in parallel, but also needs special care when using it.

The tasks are organized as pipelines. This is actually an HTTP protocol feature - one can send the next request(s) to an HTTP server without having to wait for the response of the prior request. The pipeline is available as Ocaml class:

let p = new Nethttp_client.pipeline

By adding requests, the pipeline is told to send them to the right server. If the server allows pipelining on HTTP level, this feature is exploited to speed up the accesses. Here, we submit two different GET requests:

let x1 = new Nethttp_client.get "http://foo.org/bar"
let x2 = new Nethttp_client.get "http://foo.org/baz"

p # add x1;
p # add x2

The objects x1 and x2 are instances of Nethttp_client.http_call. They have lots of access methods for changing the request type and getting the returned response.

Now, after just adding the objects, nothing is done yet. You also have to start the pipeline:

p # run()

(Or, alternatively, do Unixqueue.run p#event_system, which is just the same.)

Now, you can get the fetched data with:

let d1 = x1 # response_body # value

Before looking at the value, you would normally check the status code of the response. There are a few possibilities:

How the pipeline works

The object p is actually several pipelines in one object. For each connected server, p keeps a small number of parallel connections (normally 2). Each connection is then driven in a pipelined way, if possible.

When running p, all the connections to the servers are created in parallel, and the communication is done in parallel.

Accessing FTP via Netftp_client

The Netftp_client is also an asynchronous implementation. It is a bit more difficult to exploit this, though, because Netftp_client is a bit simpler than Nethttp_client.

Generally, a client can only connect to a single server, not to several at once. Also, there is no queue of pending requests - all submitted requests are immediately executed, and the next request can first be started when the previous has finished.

In synchrounous code, a file download looks like:

let client = new ftp_client()
let () = client # exec (connect_method ~host:"foo.bar" ())
let () = client # exec 
	    (login_method
	       ~user:"anonymous" 
	       ~get_password:(fun () -> "")
	       ~get_account:(fun () -> "")
		())
let buffer = Buffer.create 1000 
let ch = new Netchannels.output_buffer buffer
let () = client # exec 
            (get_method
                ~file:(`NVFS "dir/baz")
                ~representation:`Image 
                ~store:(fun _ -> `File_structure ch) 
                ());
let s = Buffer.contents buffer

As you see, this is just a sequence of exec calls. There is also an exec_e method allowing to start these operations as Uq_engines.engine, allowing asynchronous execution.

FTP has a number of subtle protocol options - like file transfer in several modes. Please refer to Netftp_client where these details are extensively documented.

You close the connection using the QUIT command with

let () = client # exec (quit_method())

or just run client # reset() to just shut the TCP connection down.

Advanced topics for HTTP

The following things are possible, but would require some more in-depth discussion exceeding the scope of this list of recipes:

  • Tweak the TLS configuration: By modifying the tls configuration option you can change many aspects of the TLS layer. In particular, you can weaken the authentication by accepting any server certification, and you can make it stronger by requiring a certain certification, or by sending a client certificate. You need to change the option Nethttp_client.http_options.tls for doing so. See Tls for more links.

Advanced topics for FTP

  • Tweak the TLS configuration: Netftp_fs allows it to pass the tls_config argument. By setting this explicitly, you can also get any advanced effect.
  • Use GSSAPI authentication for FTP: The FTP client implements RFC 2228. Often it is only needed to set the gssapi_provider argument of Netftp_fs.ftp_fs to Netgss.System, and the ticket-based Kerberos login works.

ocamlnet-4.1.2/doc/html-main/Netx509.html0000644000175000017500000010521412731530353016446 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509

Module Netx509

module Netx509: sig .. end
X.509 certificates


This module defines a parser for X.509 certificates in Internet context (RFC 5280). The basic structure is implemented, and there are also parsers for the most needed extensions.

There are several involved formats:

  • ASN.1 is the language in which the certificate format is described. When we refer here to ASN.1 we mean tagged values as defined by Netasn1.Value.value.
  • DER is the common binary encoding for ASN.1 values in this context. DER is a subset of BER (which is implemented by Netasn1.decode_ber). The encoding of ASN.1 values in BER is ambiguous, and DER specifies the variant to use in order to get a "distinguished" encoding (that's what the "D" stands for), which is needed to get unique digital signatures.
  • PEM is a set of standards for "privacy enhanced mail". The "PEM encoding" of certificates is simply BASE-64 of DER.

type oid = Netoid.t 
OIDs are just integer sequences
class type directory_name = object .. end
Directory names are also known as distinguished names.
class type x509_certificate = object .. end
An X.509 certificate in decoded form.

OIDs for DN attribute types


module DN_attributes: sig .. end

Distinguished names


module X509_DN_string: Netdn.DN_string 
Parser/printer for distnguished names as they may occur in X.509 certificates
val lookup_dn_ava : directory_name -> oid -> Netasn1.Value.value
Find the first relative DN setting this OID (or Not_found)
val lookup_dn_ava_utf8 : directory_name -> oid -> string
Same as lookup_dn_ava, but additionally converts the value to UTF-8

Parsers


class x509_dn_from_ASN1 : Netasn1.Value.value -> directory_name
Returns the DN object for a Name entity
class x509_dn_from_string : string -> directory_name
Returns the DN object for an RFC 4514-encoded string
class x509_certificate_from_ASN1 : Netasn1.Value.value -> x509_certificate
Parses the passed ASN.1 value and returns the certificate object
class x509_certificate_from_DER : string -> x509_certificate
Parses the passed DER string and returns the certificate object

Extensions



Extensions



Extensions are identified by an OID (found in the following CE module), and the value is a DER-encoded ASN.1 value. The parse_* functions take this DER-encoded value and decode them. E.g. get the "authority key identifier":

  let _, aki_der, _ = 
    List.find
      (fun (oid,_,_) -> oid = CE.ce_authority_key_identifier) 
      cert#extensions in
  let aki =
    parse_authority_key_identifier aki_der
 

Or use find_extension, as defined below.

Note that we don't have parsers for all extensions.

module CE: sig .. end
exception Extension_not_found of oid
val find_extension : oid -> (oid * string * bool) list -> string * bool
find_extension is designed to be applied to the result of the extensions method of Netx509.x509_certificate:

  let (data, critical) =
    find_extension CE.ce:authority_key_identifier cert#extensions
      

It returns the undecoded data string, and the critical flag.

Raises Extension_not_found if there is no such extension.

val check_critical_exts : oid list -> (oid * string * bool) list -> bool
check_critical_exts list exts: When an extension is flagged as critical, it must be processed by the communication endpoint. If there is a critical extension that cannot be processed, this is an error. This function checks whether there are any critical extensions in exts beyond those in list, and returns true in this case.

Use this in software as:

  let unprocessed_critical =
    check_critical_exts
       [ CE.ce_basic_constraints ]
       cert#extensions
  

and pass the list of all extension OIDs you actually process. You should raise an error if unprocessed_critical is true.

type general_name = [ `DNS_name of string
| `Directory_name of directory_name
| `Edi_party_name of string option * string
| `IP_address of Unix.socket_domain * Unix.inet_addr * Unix.inet_addr
| `Other_name of oid * Netasn1.Value.value
| `Registered_ID of oid
| `Rfc822_name of string
| `Uniform_resource_identifier of string
| `X400_address of Netasn1.Value.value ]
General names:
  • `Other_name(oid, value): the oid determines the extension name format
  • `Rfc822_name n: an email address n (ASCII encoded)
  • `DNS_name n: an Internet domain n (ASCII encoded - no internationalization)
  • `X400_address v: an X.400 address, which is not decoded here and just given as unparsed ASN.1 value v
  • `Directory_name n: a directory name n (i.e. a name using the syntax of distinguished names)
  • `Edi_party_name(assigner,party), both names as UTF-8
  • `Uniform_resource_identifier uri: this uri (ASCII-encoded, no internationalization)
  • `IP_address(dom,addr,mask): the address with mask
  • `Registered oid: a symbolical pre-registered name known under oid

type authority_key_identifier = {
   aki_key_identifier : string option;
   aki_authority_cert_issuer : general_name list;
   aki_authority_cert_serial_number : string option;
}
val parse_authority_key_identifier : string -> authority_key_identifier
val parse_subject_key_identifier : string -> string
Returns the key identifier directly
type key_usage_flag = [ `Crl_sign
| `Data_encipherment
| `Decipher_only
| `Digital_signature
| `Encipher_only
| `Key_agreement
| `Key_cert_sign
| `Key_encipherment
| `Non_repudiation ]
val parse_key_usage : string -> key_usage_flag list
val parse_subject_alt_name : string -> general_name list
val parse_issuer_alt_name : string -> general_name list
val parse_subject_directory_attributes : string -> (oid * Netasn1.Value.value list) list
val parse_basic_constraints : string -> bool * int option
type ext_key_usage_flag = [ `Client_auth
| `Code_signing
| `Email_protection
| `OCSP_signing
| `Server_auth
| `Time_stamping
| `Unknown ]
val parse_ext_key_usage : string -> (oid * ext_key_usage_flag) list
Returns the OID as array, and as decoded flag
module KP: sig .. end
Key purpose IDs as returned by parse_ext_key_usage
type authority_access_description_flag = [ `CA_issuers | `OCSP | `Unknown ] 
type subject_access_description_flag = [ `CA_repository | `Time_stamping | `Unknown ] 
type access_description_flag = [ `CA_issuers | `CA_repository | `OCSP | `Time_stamping | `Unknown ] 
val parse_authority_info_access : string ->
(oid * authority_access_description_flag *
general_name)
list
val parse_subject_info_access : string ->
(oid * subject_access_description_flag * general_name)
list
module AD: sig .. end

Generic parsers
val general_name_from_ASN1 : Netasn1.Value.value -> general_name
Parses the general_name structure
val general_names_from_ASN1 : Netasn1.Value.value -> general_name list
Parse a sequence of general names
val directory_string_from_ASN1 : Netasn1.Value.value -> string
Returns the directory_string as UTF-8
val attribute_from_ASN1 : Netasn1.Value.value -> oid * Netasn1.Value.value list
Parses an attribute
val attributes_from_ASN1 : Netasn1.Value.value -> (oid * Netasn1.Value.value list) list
Parses a sequence of attributes
ocamlnet-4.1.2/doc/html-main/Nethttp.html0000644000175000017500000011366112731530353016725 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp

Module Nethttp

module Nethttp: sig .. end

Basic definitions for the HTTP protocol




These definitions can be used by both HTTP clients and servers, and by protocols in the middle, e.g. CGI.
type protocol_version = int * int 

A pair of a major and minor version number
type protocol_attribute = [ `Secure_https ] 
type protocol = [ `Http of protocol_version * protocol_attribute list
| `Other ]
The base protocol. RFC 2145 defines how to interpret major and minor numbers. In particular, we have:
  • `Http((0,9),_) is the ancient HTTP version 0.9
  • `Http((1,n),_) is the HTTP protocol 1.n. It is expected that all these versions are compatible to each other except negotiable features.
  • `Http((m,_),_) for m>1 is regarded as unknown protocol, incompatible to any `Http((1,n),_)
  • `Other is anything else (unrecognizes protocol)

val string_of_protocol : protocol -> string
Returns the string representation, e.g. "HTTP/1.0". Fails for `Other
val protocol_of_string : string -> protocol
Parses the protocol string, e.g. "HTTP/1.0". Returns `Other for unrecognized strings
type http_status = [ `Accepted
| `Bad_gateway
| `Bad_request
| `Conflict
| `Continue
| `Created
| `Expectation_failed
| `Forbidden
| `Found
| `Gateway_timeout
| `Gone
| `Http_version_not_supported
| `Internal_server_error
| `Length_required
| `Method_not_allowed
| `Moved_permanently
| `Multiple_choices
| `No_content
| `Non_authoritative
| `Not_acceptable
| `Not_found
| `Not_implemented
| `Not_modified
| `Ok
| `Partial_content
| `Payment_required
| `Precondition_failed
| `Proxy_auth_required
| `Request_entity_too_large
| `Request_timeout
| `Request_uri_too_long
| `Requested_range_not_satisfiable
| `Reset_content
| `See_other
| `Service_unavailable
| `Switching_protocols
| `Temporary_redirect
| `Unauthorized
| `Unsupported_media_type
| `Use_proxy ]
HTTP response status:

Informational (1xx):

  • `Continue
  • `Switching_protocols
Successful (2xx):
  • `Ok
  • `Created
  • `Accepted
  • `Non_authoritative
  • `No_content
  • `Reset_content
  • `Partial_content
Redirection (3xx):
  • `Multiple_choices
  • `Moved_permanently
  • `Found
  • `See_other
  • `Not_modified
  • `Use_proxy
  • `Temporary_redirect
Client error (4xx):
  • `Bad_request
  • `Unauthorized
  • `Payment_required
  • `Forbidden
  • `Not_found
  • `Method_not_allowed
  • `Not_acceptable
  • `Proxy_auth_required
  • `Request_timeout
  • `Conflict
  • `Gone
  • `Length_required
  • `Precondition_failed
  • `Request_entity_too_large
  • `Request_uri_too_long
  • `Unsupported_media_type
  • `Request_range_not_satisfiable
  • `Expectation_failed
Server Error (5xx):
  • `Internal_server_error
  • `Not_implemented
  • `Bad_gateway
  • `Service_unavailable
  • `Gateway_timeout
  • `Http_version_not_supported

val int_of_http_status : http_status -> int
Returns the integer code for a status value
val http_status_of_int : int -> http_status
Returns the status value for an integer code, or raises Not_found
val string_of_http_status : http_status -> string
Returns the informational text for a status value
val base_code : int -> int
Allows to handle unknown status codes that are untranslatable by http_status_of_int:
  • for a code 100 to 199 the value 100 is returned
  • for a code 200 to 299 the value 200 is returned
  • for a code 300 to 399 the value 300 is returned
  • for a code 400 to 499 the value 400 is returned
  • for all other codes 500 is returned
E.g.
  let st =
    try Nethttp.http_status_of_int code
    with Not_found ->
      Nethttp.http_status_of_int (Nethttp.base_code code)
      

type http_method = string * string 
Method name, URI
type cache_control_token = [ `Extension of string * string option
| `Max_age of int
| `Max_stale of int option
| `Min_fresh of int
| `Must_revalidate
| `No_cache of string list
| `No_store
| `No_transform
| `Only_if_cached
| `Private of string list
| `Proxy_revalidate
| `Public
| `S_maxage of int ]
The cache control token for the Cache-control header
type etag = [ `Strong of string | `Weak of string ] 
Entity tags can be weak or strong
val weak_validator_match : etag -> etag -> bool
Whether the tags match weakly (see RFC 2616 for definition)
val strong_validator_match : etag -> etag -> bool
Whether the tags match strongly (see RFC 2616 for definition)
exception Bad_header_field of string
Raised when a header field cannot be parsed. The string argument is the name of the failing function
class type http_header = Netmime.mime_header
class type http_header_ro = Netmime.mime_header_ro
The HTTP header is represented as MIME header
class type http_trailer = Netmime.mime_header
class type http_trailer_ro = Netmime.mime_header_ro
The HTTP trailer is represented as MIME header
val status_of_cgi_header : http_header -> int * string
Returns the status code and the status text corresponding to the Status header
type netscape_cookie = {
   cookie_name : string; (*
The name of the cookie
*)
   cookie_value : string; (*
The value of the cookie. There are no restrictions on the value of the cookie
*)
   cookie_expires : float option; (*
Expiration:
  • None: the cookie expires when the browser session ends.
  • Some t: the cookie expires at the time t (seconds since the epoch)

*)
   cookie_domain : string option; (*
Cookies are bound to a certain domain, i.e. the browser sends them only when web pages of the domain are requested:

  • None: the domain is the hostname of the server
  • Some domain: the domain is domain

*)
   cookie_path : string option; (*
Cookies are also bound to certain path prefixes, i.e. the browser sends them only when web pages at the path or below are requested.

  • None: the path is script name + path_info
  • Some p: the path is p. With Some "/" you can disable the path restriction completely.

*)
   cookie_secure : bool; (*
Cookies are also bound to the type of the web server: false means servers without SSL, true means servers with activated SSL ("https").
*)
}
These are old-style cookies, as introduced by Netscape. For a better representation of cookies see the Nethttp.Cookie module.

This type is kept for now (and is also not considered as deprecated), as the access functions in the Nethttp.Header module are more complete than those for Nethttp.Cookie.

type cookie = netscape_cookie 
Compatibility name. Deprecated
val decode_query : string -> string * string
Splits the URI into a "script name" and a "query string"
val split_host_port : string -> string * int option
Splits the Host header in hostname and optional port number. Fails on syntax error
val uripath_encode : string -> string
Encodes unsafe characters in URI paths. The slash character is not encoded. This function should only be applied to the part before '?'.
val uripath_decode : string -> string
Decodes %XX sequences in URI paths. %2F is forbidden (failure). This function should only be applied to the part before '?'.

Parsing and Printing of Headers


module Cookie: sig .. end
module Header: sig .. end

HTTP transport registry


type transport_layer_id = int 
val new_trans_id : unit -> transport_layer_id
Allocates and returns a new ID
val http_trans_id : transport_layer_id
Identifies the pure HTTP transport (without SSL), with or without web proxies
val https_trans_id : transport_layer_id
Identifies anonymous HTTPS transport (i.e. no client certificates), with or without web proxies.
val spnego_trans_id : transport_layer_id
Identifies an anonymous HTTPS transport that is additionally authenticated via SPNEGO (as described in RFC 4559)
val proxy_only_trans_id : transport_layer_id
Identifies web proxy connections. Use this to e.g. send an FTP URL to a web proxy via HTTP

Types for authentication



Types for authentication



See also Netsys_sasl_types.SASL_MECHANISM. This is very similar, only that
  • the messages are encapsulated as HTTP headers, and
  • the "realm" parameter is commonly supported by mechanisms
In SASL terms, HTTP authentication is normally "server first". There is only one exception: re-authentication, which is "client first".
type match_result = [ `Accept of string * string option
| `Accept_reroute of string * string option * transport_layer_id
| `Reject
| `Reroute of string * transport_layer_id ]
module type HTTP_CLIENT_MECHANISM = sig .. end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.server_endpoint_listener.html0000644000175000017500000004163712731530353027115 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.server_endpoint_listener object
  method listen :
    Uq_engines_compat.listen_address ->
    Unixqueue.event_system ->
    Uq_engines_compat.server_endpoint_acceptor Uq_engines_compat.engine
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.trace_call-c.html0000644000175000017500000004220612731530353022567 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.trace_call

Class Nethttp_client.trace_call

class trace_call : http_call

ocamlnet-4.1.2/doc/html-main/Uq_resolver.resolver-c.html0000644000175000017500000004415512731530353021666 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_resolver.resolver

Class type Uq_resolver.resolver

class type resolver = object .. end

method ipv6 : bool
Whether host_by_name may return IPv6 addresses
method host_by_name : string -> Unixqueue.event_system -> Unix.host_entry engine
Look up the passed host name up. The implementation can be synchronous or asynchronous. In the first case, an engine is returned that is already in one of the states `Done he or `Error e where he is the host entry, or e is an exception like Host_not_found. In this case the passed event system is ignored. If the implementation is asynchronous, the caller must run the event system until the state of the engine transitions to `Done he or `Error e.
ocamlnet-4.1.2/doc/html-main/Rpc_netplex.html0000644000175000017500000005372312731530353017564 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_netplex

Module Rpc_netplex

module Rpc_netplex: sig .. end
Netplex support for RPC servers (TCP only)

val rpc_factory : configure:(Netplex_types.config_file -> Netplex_types.address -> 'a) ->
?socket_config:('a -> Rpc_server.socket_config) ->
?hooks:('a -> Netplex_types.processor_hooks) ->
?supported_ptypes:Netplex_types.parallelization_type list ->
name:string ->
setup:(Rpc_server.t -> 'a -> unit) -> unit -> Netplex_types.processor_factory
A factory for TCP-based RPC servers. In name the name of the processor is defined. This name can be referenced from the config file like:

    processor {
        type = "the passed [name]";
        ...
    }
 

Parameters may be included in the processor section:

  • portmapper: This is a boolean parameter. If set to true, the Internet port is registered with the portmapper program. This will fail if there are several Internet bindings with distinct port numbers!
  • timeout: This is a float parameter. It sets the transport timeout of the RPC server (see Rpc_server.set_timeout). If a connection hangs for this number of seconds, it is shut down by the server.
Further parameters and subsections can be defined by the user. These parameters should be parsed and checked for correctness by the configure callback. The result of configure is also passed to setup and other optional functions. The configure function is called just before the service is added to Netplex (i.e. from the controller context).

The return value of configure can be of any type. This value exists once for every time the processor is instantiated (used) by a service. It is not only useful for passing configuration values down, but also for storing intermediate results while establishing the service.

The Rpc_server.t structure is created every time a new connection is accepted. Of course, this is done from the context of the container. The Rpc_server.t is created without any binding; the user must bind procedures in the setup function. This can be done by calling Rpc_server.bind or the ocamlrpcgen-generated function (by the -srv2 switch of ocamlrpcgen).

For example, a minimal factory for an RPC service may look like:

   let proc_ping () = ()     (* Trivial RPC procedure *)

   let my_factory() =
     Rpc_netplex.rpc_factory
       ~name:"my_rpc_service"
       ~factory:(fun _ _ -> ())
       ~setup:(fun rpc () ->
                 My_rpc_srv.bind ~proc_ping rpc
              )
       ()
 

The setup function is also called once before a new connection is accepted to get a list of programs and procedures. The Rpc_server.t is a special one in this case, and one can test for it with the Rpc_server.is_dummy function.


socket_config : An optional function computing the socket configuration. By default, Rpc_server.default_socket_config is used. Special socket configuration would, for example, allow SSL.
hooks : An optional function returning the hooks to call. See Netplex_types.processor_hooks for documentation.
supported_ptypes : Which parallelization types are supported by the service. By default, both multi-processing and multi-threading are included in this list.
val debug_rpc_internals : bool Pervasives.ref
val debug_rpc_service : bool Pervasives.ref
These variables control debugging of Rpc_server. If set, the debug messages are sent to the Netplex logger. These variables must be set before an RPC connection is accepted.
ocamlnet-4.1.2/doc/html-main/Rpc_proxy.ManagedSet.html0000644000175000017500000007114712731530353021275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_proxy.ManagedSet

Module Rpc_proxy.ManagedSet

module ManagedSet: sig .. end


Manages a set of clients
type mset 
a managed set
type mset_policy = [ `Balance_load | `Failover ] 
Sets in which order managed clients are picked from the services array passed to create_mset:
  • `Failover: Picks an element from the first service in services that is enabled and has free capacity. That means that the first service is preferred until it is maxed out or it fails, then the second service is preferred, and so on.
  • `Balance_load: Picks an element from the service in services that is enabled and has the lowest load.

type mset_config = {
   mset_mclient_config : Rpc_proxy.ManagedClient.mclient_config; (*
The mclient config
*)
   mset_policy : mset_policy; (*
The policy
*)
   mset_pending_calls_max : int; (*
When an mclient processes this number of calls at the same time, it is considered as fully busy. (Value must by > 0).
*)
   mset_pending_calls_norm : int; (*
When an mclient processes less than this number of calls, its load is considered as too light, and it is tried to put more load on this client before opening another one
*)
   mset_idempotent_max : int; (*
How often idempotent procedures may be tried to be called. A negative value means infinite.
*)
   mset_idempotent_wait : float; (*
Wait this number of seconds before trying again
*)
}
exception Cluster_service_unavailable
Raised by mset_pick when no available endpoint can be found, or all available endpoints have reached their maximum load.
val create_mset_config : ?mclient_config:Rpc_proxy.ManagedClient.mclient_config ->
?policy:mset_policy ->
?pending_calls_max:int ->
?pending_calls_norm:int ->
?idempotent_max:int ->
?idempotent_wait:float -> unit -> mset_config
Create a config record. The optional arguments set the config components with the same name. The defaults are:
  • mclient_config: The default mclient config
  • policy: `Balance_load
  • pending_calls_max: max_int
  • pending_calls_norm: 1
  • idempotent_max: 3
  • idempotent_wait: 5.0

val create_mset : mset_config ->
(Rpc_client.connector * int) array ->
Unixqueue.event_system -> mset
create_mset config services: The mset is created with config, and the services array describes which ports are available, and how often each port may be contacted (i.e. max number of connections).
val mset_pick : ?from:int list ->
mset -> Rpc_proxy.ManagedClient.mclient * int
Pick an mclient for another call, or raise Cluster_service_unavailable. The returned int is the index in the mset_services array.

If from is given, not all specified mclients qualify for this call. In from one can pass a list of indexes pointing into the mset_services array, and only from these mclients the mclient is picked. For `Failover policies, the order given in from is respected, and the mclients are checked from left to right.

val mset_services : mset -> (Rpc_client.connector * int) array
Returns the service array
val mset_load : mset -> int array
Returns the number of pending calls per service
val event_system : mset -> Unixqueue.event_system
Return the event system
val shut_down : mset -> unit
val sync_shutdown : mset -> unit
val trigger_shutdown : mset -> (unit -> unit) -> unit
Shut down the managed set. See the corresponding functions Rpc_client.shut_down, Rpc_client.sync_shutdown, and Rpc_client.trigger_shutdown
val idempotent_async_call : ?from:int list ->
mset ->
(Rpc_proxy.ManagedClient.mclient -> 'a -> ((unit -> 'b) -> unit) -> unit) ->
'a -> ((unit -> 'b) -> unit) -> unit
idempotent_async_call mset async_call arg emit: Picks a new mclient and calls async_call mclient arg emit. If the call leads to a fatal error, a new mclient is picked, and the call is repeated. In total, the call may be tried mset_idempotent_max times. It is recommended to set rcache_threshold to 1 when using this function because this enforces that a different mclient is picked when the first one fails.

Note that a timeout is not considered as a fatal error by default; one has to enable that by setting mclient_msg_timeout_is_fatal.

Note that this form of function is compatible with the generated foo'async functions of the language mapping.

from has the same meaning as in mset_pick.

val idempotent_sync_call : ?from:int list ->
mset ->
(Rpc_proxy.ManagedClient.mclient -> 'a -> ((unit -> 'b) -> unit) -> unit) ->
'a -> 'b
Synchronized version. Note that you have to pass an asynchronous function as second argument. The result is synchronous, however.
ocamlnet-4.1.2/doc/html-main/type_Netplex_advanced.html0000644000175000017500000004062112731530353021577 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_advanced sig  endocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.sender.html0000644000175000017500000004157312731530353023261 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.sender src:#Uq_engines_compat.async_in_channel ->
dst:Unix.file_descr ->
?close_src:bool ->
?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_modes.Symmetric_cipher.html0000644000175000017500000005005012731530353025711 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes.Symmetric_cipher sig
  type sc_ctx = {
    set_iv : string -> unit;
    set_header : string -> unit;
    encrypt : Netsys_types.memory -> Netsys_types.memory -> unit;
    decrypt : Netsys_types.memory -> Netsys_types.memory -> bool;
    mac : unit -> string;
  }
  type sc = {
    name : string;
    mode : string;
    key_lengths : (int * int) list;
    iv_lengths : (int * int) list;
    block_constraint : int;
    supports_aead : bool;
    create : string -> Netsys_crypto_modes.Symmetric_cipher.sc_ctx;
  }
  val extract :
    (module Netsys_crypto_types.SYMMETRIC_CRYPTO->
    string * string -> Netsys_crypto_modes.Symmetric_cipher.sc
  val extract_all :
    (module Netsys_crypto_types.SYMMETRIC_CRYPTO->
    Netsys_crypto_modes.Symmetric_cipher.sc list
  val cbc_of_ecb :
    Netsys_crypto_modes.Symmetric_cipher.sc ->
    Netsys_crypto_modes.Symmetric_cipher.sc
  val ofb_of_ecb :
    Netsys_crypto_modes.Symmetric_cipher.sc ->
    Netsys_crypto_modes.Symmetric_cipher.sc
  val ctr_of_ecb :
    Netsys_crypto_modes.Symmetric_cipher.sc ->
    Netsys_crypto_modes.Symmetric_cipher.sc
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_intro_gss.html0000644000175000017500000004061612731530353021152 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_intro_gss sig  endocamlnet-4.1.2/doc/html-main/type_Uq_engines.poll_process_engine.html0000644000175000017500000004124112731530353024457 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.poll_process_engine ?period:float ->
pid:int -> Unixqueue.event_system -> [Unix.process_status] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Netchannels.rec_in_channel.html0000644000175000017500000004146312731530353023530 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.rec_in_channel object
  method close_in : unit -> unit
  method input : Bytes.t -> int -> int -> int
end
ocamlnet-4.1.2/doc/html-main/Netftp_client.Debug.html0000644000175000017500000004200312731530353021111 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_client.Debug

Module Netftp_client.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module
ocamlnet-4.1.2/doc/html-main/type_Platform.html0000644000175000017500000004061112731530353020116 0ustar gerdgerd Ocamlnet 4 Reference Manual : Platform sig  endocamlnet-4.1.2/doc/html-main/Nethttp_client.html0000644000175000017500000022126512731530353020263 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client

Module Nethttp_client

module Nethttp_client: sig .. end
HTTP 1.1 client


Note for beginners: There is a simplified interface called Nethttp_client.Convenience.

Note for beginners: There is a simplified interface called Nethttp_client.Convenience.

Implements the following advanced features:
  • chunked message transport
  • persistent connections
  • connections in pipelining mode ("full duplex" connections)
  • modular authentication methods, currently Basic, Digest, and Negotiate
  • event-driven implementation; allows concurrent service for several network connections
  • HTTP proxy support, also with Basic and Digest authentication
  • SOCKS proxy support (1)
  • HTTPS support is now built-in, but requires that a TLS provider is initialized (see Tls for more information). HTTPS proxies are also supported (CONNECT method) (1)
  • Automatic and configurable retry of failed idempotent requests
  • Redirections can be followed automatically
  • Compressed message bodies can be automatically decoded (gzip only, method set_accept_encoding) (1)
Left out:
  • multipart messages, including multipart/byterange
  • content digests specified by RFC 2068 and 2069 (2)
  • content negotiation (2)
  • conditional and partial GET (2)
  • client-side caching (2)
  • HTTP/0.9 compatibility
(1) Since Ocamlnet-3.3

(2) These features can be implemented on top of this module if really needed, but there is no special support for them.

Related modules/software:

  • Nethttp_fs allows you to access HTTP servers in the style of filesystems
  • WebDAV: If you are looking for WebDAV there is an extension of this module: Webdav, which is separately available.


Note for beginners: There is a simplified interface called Nethttp_client.Convenience.

Implements the following advanced features:
  • chunked message transport
  • persistent connections
  • connections in pipelining mode ("full duplex" connections)
  • modular authentication methods, currently Basic, Digest, and Negotiate
  • event-driven implementation; allows concurrent service for several network connections
  • HTTP proxy support, also with Basic and Digest authentication
  • SOCKS proxy support (1)
  • HTTPS support is now built-in, but requires that a TLS provider is initialized (see Tls for more information). HTTPS proxies are also supported (CONNECT method) (1)
  • Automatic and configurable retry of failed idempotent requests
  • Redirections can be followed automatically
  • Compressed message bodies can be automatically decoded (gzip only, method set_accept_encoding) (1)
Left out:
  • multipart messages, including multipart/byterange
  • content digests specified by RFC 2068 and 2069 (2)
  • content negotiation (2)
  • conditional and partial GET (2)
  • client-side caching (2)
  • HTTP/0.9 compatibility
(1) Since Ocamlnet-3.3

(2) These features can be implemented on top of this module if really needed, but there is no special support for them.

Related modules/software:

  • Nethttp_fs allows you to access HTTP servers in the style of filesystems
  • WebDAV: If you are looking for WebDAV there is an extension of this module: Webdav, which is separately available.


Thread safety

The module can be compiled such that it is thread-safe. In particular, one has to link the http_client_mt.cmxo object, and thread-safety is restricted to the following kinds of usage:

  • The golden rule is that threads must not share pipeline objects. If every thread uses its own pipeline, every thread will have its own set of state variables. It is not detected if two threads errornously share a pipeline, neither by an error message nor by implicit serialization. Strange things may happen.
  • The same applies to the other objects, e.g. http_call objects
  • The Convenience module even serializes; see below.


Note for beginners: There is a simplified interface called Nethttp_client.Convenience.

Implements the following advanced features:
  • chunked message transport
  • persistent connections
  • connections in pipelining mode ("full duplex" connections)
  • modular authentication methods, currently Basic, Digest, and Negotiate
  • event-driven implementation; allows concurrent service for several network connections
  • HTTP proxy support, also with Basic and Digest authentication
  • SOCKS proxy support (1)
  • HTTPS support is now built-in, but requires that a TLS provider is initialized (see Tls for more information). HTTPS proxies are also supported (CONNECT method) (1)
  • Automatic and configurable retry of failed idempotent requests
  • Redirections can be followed automatically
  • Compressed message bodies can be automatically decoded (gzip only, method set_accept_encoding) (1)
Left out:
  • multipart messages, including multipart/byterange
  • content digests specified by RFC 2068 and 2069 (2)
  • content negotiation (2)
  • conditional and partial GET (2)
  • client-side caching (2)
  • HTTP/0.9 compatibility
(1) Since Ocamlnet-3.3

(2) These features can be implemented on top of this module if really needed, but there is no special support for them.

Related modules/software:

  • Nethttp_fs allows you to access HTTP servers in the style of filesystems
  • WebDAV: If you are looking for WebDAV there is an extension of this module: Webdav, which is separately available.


Thread safety

The module can be compiled such that it is thread-safe. In particular, one has to link the http_client_mt.cmxo object, and thread-safety is restricted to the following kinds of usage:

  • The golden rule is that threads must not share pipeline objects. If every thread uses its own pipeline, every thread will have its own set of state variables. It is not detected if two threads errornously share a pipeline, neither by an error message nor by implicit serialization. Strange things may happen.
  • The same applies to the other objects, e.g. http_call objects
  • The Convenience module even serializes; see below.


Types and Exceptions


exception Bad_message of string
The server sent a message which cannot be interpreted. The string indicates the reason.
exception No_reply
There was no response to the request because some other request failed earlier and it was not allowed to send the request again.
exception Too_many_redirections
While following redirections the limit has been reached
exception Name_resolution_error of string
Could not resolve this name - same as Uq_engines.Host_not_found
exception URL_syntax_error of string
This URL cannot be parsed after a redirection has been followed.
exception Timeout of string
A timeout. The string explains which connection is affected. New since Ocamlnet-3.3.
exception Proxy_error of int
An error status from a proxy. This is only used when extra proxy messages are used to configure the proxy (e.g. the CONNECT message).
exception Response_too_large
The length of the response exceeds the configured maximum
exception Http_protocol of exn
The request could not be processed because the exception condition was raised. The inner exception is one of the above defined.
exception Http_error of (int * string)
Deprecated in the scope of pipeline. The server sent an error message. The left component of the pair is the error code, the right component is the error text. This exception is only used by get_resp_body, and by the Nethttp_client.Convenience module. Note that for the latter usage the exception does not count as deprecated.
type status = [ `Client_error
| `Http_protocol_error of exn
| `Redirection
| `Server_error
| `Successful
| `Unserved ]
Condensed status information of a HTTP call:
  • `Unserved: The call has not yet been finished
  • `HTTP_protocol_error e: An error on HTTP level occurred. Corresponds to the exception Http_protocol.
  • `Successful: The call is successful, and the response code is between 200 and 299.
  • `Redirection: The call is successful, and the response code is between 300 and 399.
  • `Client_error: The call failed with a response code between 400 and 499.
  • `Server_error: The call failed for any other reason.

type 'a auth_status = [ `Auth_error
| `Continue of 'a
| `Continue_reroute of 'a * int
| `None
| `OK
| `Reroute of int ]
Status of HTTP-level authentication:
  • `None: Authentication wasn't tried.
  • `OK: The authentication protocol finished. What this means exactly depends on the protocol. For most protocols it just means that the server authenticated the client. For some protocols it may also mean that the client authenticated the server (mutual authentication).
  • `Auth_error: The authentication protocol did not succeed. Note that this state can also be reached for an otherwise successful HTTP response (i.e. code 200) when the client could not authenticate the server and the protocol demands this.
  • `Reroute trans_id: The request should be retried on a new connection for the transport identified by trans_id
  • `Continue: The authentication is still in progress. Normally the user should not see this state as the engine automatically continues the protocol. The argument of `Continue is private.
  • `Continue_reroute: the combination of continue and reroute: the auth protocol continues, but the next request must be sent on the indicated transport.

type 'message_class how_to_reconnect = 
| Send_again (*
Send the request automatically again
*)
| Request_fails (*
Drop the request
*)
| Inquire of ('message_class -> bool) (*
If the function return true send again, otherwise drop the request.
*)
| Send_again_if_idem (*
Default behaviour: Send_again for idempotent methods (GET, HEAD), Request_fails for the rest
*)
How to deal with automatic reconnections, especially when the connection crashes.
type 'message_class how_to_redirect = 
| Redirect (*
Perform the redirection
*)
| Do_not_redirect (*
No redirection
*)
| Redirect_inquire of ('message_class -> bool) (*
If the function return true redirect, otherwise do not redirect. It is legal to set the Location header as part of the action performed by the function. (Should be an absolute http URL.)
*)
| Redirect_if_idem (*
Default behaviour: Redirect for idempotent methods (GET, HEAD), Do_not_redirect for the rest
*)
type private_api 
The private part of the http_call class type
type response_body_storage = [ `Body of unit -> Netmime.mime_body
| `Device of unit -> Uq_io.out_device
| `File of unit -> string
| `Memory ]
How to create the response body:
  • `Memory: The response body is in-memory
  • `File f: The response body is stored into the file whose name is returned by f()
  • `Body f: The response body is stored into the object returned by f()
  • `Device f: The response is directly forwarded to the device obtained by f() (new since Ocamlnet-3.3)
When the function f is called in the latter cases the response header has already been received, and can be retrieved with the response_header method of the call object. Also, response_status_text, response_status_code, and response_status return meaningful values.
type synchronization = 
| Sync (*
The next request begins after the response of the last request has been received.
*)
| Pipeline of int (*
The client is allowed to send several requests without waiting for responses. The number is the maximum number of unreplied requests that are allowed. A typical value: 5. If you increase this value, the risk becomes higher that requests must be repeatedly sent to the server in the case the connection crashes. Increasing is recommended if you send a bigger number of GET or HEAD requests to the server. Decreasing is recommended if you send large POST or PUT requests to the server.

Values > 8 are interpreted as 8.

*)
This type determines whether to keep requests and responses synchronized or not.

The first request/response round is always done in Sync mode, because the protocol version of the other side is not known at that moment. Pipeline requires HTTP/1.1.

In previous versions of netclient there was a third option, Sync_with_handshake_before_request_body. This option is no longer necessary because the HTTP specification has been updated in the meantime, and there is a better mechanism now (the Expect header is set).

type resolver = Unixqueue.unix_event_system ->
string -> (Unix.inet_addr option -> unit) -> unit
A name resolver is a function r called as r esys name reply. As name the name to resolve is passed. The resolver must finally call reply with either the resolved address or with None, indicating an error in the latter case. The event system esys can be used to carry out the resolution process in an asynchronous way, but this is optional.

Only 1:1 resolution is supported, 1:n resolution not.

type transport_layer_id = int 
The ID identifies a requirement for the transport channel, especially whether plain HTTP is sufficient, or HTTPS needs to be used, and if so, whether there are further requirements for the TLS context. There are the predefined IDs:


type http_options = {
   synchronization : synchronization; (*
Default: Pipeline 5.
*)
   maximum_connection_failures : int; (*
This option limits the number of connection attempts. Default: 2
*)
   maximum_message_errors : int; (*
This option limits the number of protocol errors tolerated per request. If a request leads to a protocol error, the connection is shut down, the server is connected again, and the request is tried again (if the kind of the message allows retransmission). If a request repeatedly fails, this option limits the number of retransmissions. Default: 2
*)
   inhibit_persistency : bool; (*
This option turns persistent connections off. Default: false It is normally not necessary to change this option.
*)
   connection_timeout : float; (*
If there is no network transmission for this period of time, the connection is shut down, and tried again. Default: 300.0 (seconds) It may be necessary to increase this value if HTTP is used for batch applications that contact extremely slow services.
*)
   number_of_parallel_connections : int; (*
The client keeps up to this number of parallel connections to a single content server or proxy. Default: 2 You may increase this value if you are mainly connected with an HTTP/1.0 proxy.
*)
   maximum_redirections : int; (*
The maximum number of redirections per message
*)
   handshake_timeout : float; (*
The timeout when waiting for "100 Continue". Default: 1.0
*)
   resolver : resolver; (*
The function for name resolution
*)
   configure_socket : Unix.file_descr -> unit; (*
A function to configure socket options
*)
   tls : Netsys_crypto_types.tls_config option; (*
The TLS configuration to use by default for https URLs. (This can be overridden per request by using a different transport_layer_id.)
*)
   schemes : (string * Neturl.url_syntax * int option * transport_layer_id)
list
;
(*
The list of supported URL schemes. The tuples mean (scheme, syntax, default_port, cb). By default, the schemes "http", "https", and "ipp" are supported.
*)
   verbose_status : bool;
   verbose_request_header : bool;
   verbose_response_header : bool;
   verbose_request_contents : bool;
   verbose_response_contents : bool;
   verbose_connection : bool;
   verbose_events : bool; (*
Enable various debugging message types.
  • verbose_status: reports about status of received documents
  • verbose_request_header: prints the header sent to the server
  • verbose_request_contents: prints the document sent to the server
  • verbose_response_header: prints the header of the answer from the server
  • verbose_response_contents: prints the document received from the server
  • verbose_connection: reports many connection events; authentication, too.
  • verbose_events: everything about the interaction with Unixqueue
By default, verbose_status and verbose_connection are enabled. Note that you also have to set Debug.enable to true to see any log message at all!
*)
}
Options for the whole pipeline. It is recommended to change options the following way:
    let opts = pipeline # get_options in
    let new_opts = { opts with <field> = <value>; ... } in
    pipeline # set_options new_opts
 

New fields can be added anytime to this record, and this style of changing options is transparent to field additions.

type header_kind = [ `Base | `Effective ] 
The `Base header is set by the user of http_call and is never changed during processing the call. The `Effective header is a copy of the base header at the time the request is sent. The effective header contains additions like Content-length and authentication info.
class type http_call = object .. end
The container for HTTP calls
class type tls_cache = object .. end
A cache object for storing TLS session data
val null_tls_cache : unit -> tls_cache
This "cache" does not remember any session
val unlim_tls_cache : unit -> tls_cache
Returns a simple cache without limit for the number of cached sessions
class type transport_channel_type = object .. end

HTTP methods


class virtual generic_call : object .. end
This class is an implementation of http_call.

The following classes are implementations for the various HTTP methods. These classes do not initialize the call object.
class get_call : http_call
class trace_call : http_call
class options_call : http_call
class head_call : http_call
class post_call : http_call
class put_call : http_call
class delete_call : http_call

The following classes initialize the request message of the call (header and body). These classes are also backward compatible to the classes found in earlier versions of netclient.
class get : string -> http_call
Argument: URI
class trace : string -> int -> http_call
Arguments: URI, maximum number of hops
class options : string -> http_call
Argument: URI or "*"
class head : string -> http_call
Argument: URI
class post : string -> (string * string) list -> http_call
Arguments: URI, parameter list to be transferred as application/x-www-form-urlencoded body
class post_raw : string -> string -> http_call
Arguments: URI, body
class put : string -> string -> http_call
Arguments: URI, body
class delete : string -> http_call
Argument: URI

Authentication


class type key = object .. end
A key is a user/password combination for a certain realm
val key : user:string ->
password:string ->
realm:string -> domain:Neturl.url list -> key
Create a key object. user and password are encoded in UTF-8.
val key_creds : user:string ->
creds:(string * string * (string * string) list) list ->
http_options -> key
Create a key object from a list of credentials
class type key_handler = object .. end
class key_ring : ?uplink:#key_handler -> ?no_invalidation:bool -> unit -> object .. end
The key_ring is a cache for keys.
class type auth_session = object .. end
An auth_session represents an authenticated session
class type auth_handler = object .. end
An authentication handler has the capability of adding the necessary headers to messages.
class basic_auth_handler : ?enable_reauth:bool -> ?skip_challenge:bool -> #key_handler -> auth_handler
Basic authentication.
class digest_auth_handler : #key_handler -> auth_handler
Digest authentication.
class unified_auth_handler : ?insecure:bool -> #key_handler -> auth_handler
Support both digest and basic authentication, with preference to digest.
class generic_auth_handler : #key_handler -> (module Nethttp.HTTP_CLIENT_MECHANISM) list -> auth_handler
Authenticate with the passed generic HTTP mechanisms

For the Negotiate method (SPNEGO/GSSAPI), have a look at Netmech_spnego_http.

For the Negotiate method (SPNEGO/GSSAPI), have a look at Netmech_spnego_http.

Transport



For the Negotiate method (SPNEGO/GSSAPI), have a look at Netmech_spnego_http.

Transport



A connection cache is an object that keeps connections open that are currently unused. A connection cache can be shared by several pipelines.
type connection_cache = Nethttp_client_conncache.connection_cache 
val close_connection_cache : connection_cache -> unit
Closes all descriptors known to the cache
val create_restrictive_cache : unit -> connection_cache
A restrictive cache closes connections as soon as there are no pending requests.
val create_aggressive_cache : unit -> connection_cache
This type of cache tries to keep connections as long open as possible. The consequence is that users are responsible for closing the descriptors (by calling close_connection_cache) when the cache is no longer in use.
val http_trans_id : transport_layer_id
Identifies the pure HTTP transport (without SSL), with or without web proxies
val https_trans_id : transport_layer_id
Identifies anonymous HTTPS transport (i.e. no client certificates), with or without web proxies.
val spnego_trans_id : transport_layer_id
Identifies an anonymous HTTPS transport that is additionally authenticated via SPNEGO (as described in RFC 4559)
val proxy_only_trans_id : transport_layer_id
Identifies web proxy connections. Use this to e.g. send an FTP URL to a web proxy via HTTP
val new_trans_id : unit -> transport_layer_id
Allocates and returns a new ID
val http_transport_channel_type : transport_channel_type
Transport via HTTP
val https_transport_channel_type : Netsys_crypto_types.tls_config -> transport_channel_type
Create a new transport for HTTPS and this configuration. As of OCamlnet-4, https is automatically enabled if Netsys_crypto.current_tls returns something, i.e. if TLS is globally initialized, so there is often no reason to configure a special https transport with this function. You still need it if you want to enable special configurations per request:

        let my_trans_id = Nethttp_client.new_trans_id()
        let my_tct = Nethttp_client.https_transport_channel_type my_tls_config
        pipeline # configure_transport my_trans_id my_tct;
      

Now you can enable this special configuration for a request object call:

        call # set_transport_layer my_trans_id
      

If you want to change the TLS configuration for the whole pipeline, just set the tls field of Nethttp_client.http_options.

type proxy_type = [ `Http_proxy | `Socks5 ] 

Pipelines


class pipeline : object .. end
A pipeline is a queue of HTTP calls to perform

Example using the pipeline:

 let call = new get "http://server/path" in
 let pipeline = new pipeline in
 pipeline # add call;
 pipeline # run();    (* Now the HTTP client is working... *)
 match call # status with
 | `Successful -> ...
 | ...
 


Example using the pipeline:

 let call = new get "http://server/path" in
 let pipeline = new pipeline in
 pipeline # add call;
 pipeline # run();    (* Now the HTTP client is working... *)
 match call # status with
 | `Successful -> ...
 | ...
 


Auxiliary pipeline functions


val parse_proxy_setting : insecure:bool -> string -> string * int * (string * string * bool) option
Parses the value of an environment variable like http_proxy, i.e. an HTTP URL. The argument is the URL. Returns (host,port,auth) where auth may include user name, password, and the insecure flag.
val parse_no_proxy : string -> string list
Parses the value of an environment variable like no_proxy. Returns the list of domains.

Convenience module for simple applications



Convenience module for simple applications



Do open Nethttp_client.Convenience for simple applications.
module Convenience: sig .. end

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netx509.CE.html0000644000175000017500000005104712731530353016740 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.CE

Module Netx509.CE

module CE: sig .. end


The OIDs of the extensions in RFC 5280
val ce_authority_key_identifier : Netx509.oid
val ce_subject_key_identifier : Netx509.oid
val ce_key_usage : Netx509.oid
val ce_certificate_policies : Netx509.oid
val ce_any_policy : Netx509.oid
val ce_policy_mappings : Netx509.oid
val ce_subject_alt_name : Netx509.oid
val ce_issuer_alt_name : Netx509.oid
val ce_subject_directory_attributes : Netx509.oid
val ce_basic_constraints : Netx509.oid
val ce_name_constraints : Netx509.oid
val ce_policy_constraints : Netx509.oid
val ce_ext_key_usage : Netx509.oid
val ce_crl_distribution_points : Netx509.oid
val ce_inhibit_any_policy : Netx509.oid
val ce_freshest_crl : Netx509.oid
val ce_authority_info_access : Netx509.oid
val ce_subject_info_access : Netx509.oid
val certificate_extensions : (Netx509.oid * string) list
All the above listed OIDs with their string names (useful for displaying extension types)
ocamlnet-4.1.2/doc/html-main/type_Netchannels.input_command.html0000644000175000017500000004070112731530353023430 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_command string -> Netchannels.in_obj_channelocamlnet-4.1.2/doc/html-main/Netencoding.Base64.encoding_pipe-c.html0000644000175000017500000004246412731530353023603 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Base64.encoding_pipe

Class Netencoding.Base64.encoding_pipe

class encoding_pipe : ?linelength:int -> ?crlf:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipe
This pipe encodes the data written into the pipe. linelength and crlf work as in encode.

ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_http.Make_SCRAM.html0000644000175000017500000004114612731530353023746 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_http.Make_SCRAM functor (P : PROFILE-> Nethttp.HTTP_CLIENT_MECHANISMocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.TLS_CONFIG.html0000644000175000017500000004122012731530353024126 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_CONFIG sig module TLS : TLS_PROVIDER val config : TLS.config endocamlnet-4.1.2/doc/html-main/Uq_engines_compat.async_in_channel-c.html0000644000175000017500000004370012731530353024445 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.async_in_channel

Class type Uq_engines_compat.async_in_channel

class type async_in_channel = object .. end

method input : Bytes.t -> int -> int -> int
method close_in : unit -> unit
method pos_in : int
method can_input : bool
method request_notification : (unit -> bool) -> unit
ocamlnet-4.1.2/doc/html-main/Netstring_pcre.html0000644000175000017500000010006612731530353020260 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstring_pcre

Module Netstring_pcre

module Netstring_pcre: sig .. end
Wrapper for regexps with PCRE syntax

This module is a version of Str with a thread-safe interface, implemented using Pcre.

This modules processes PCRE-style regular expressions. If you like to write Str-like regexps, you can also use Netstring_str with almost the same signature.

The functions in this module are unavailable if Ocamlnet is built with Str as implementation of regular expressions! They will always raise Invalid_argument!

OPAM users: Note that the OPAM package for OCamlnet does not build with PCRE support by default. The trigger for this is the presence of the pcre OPAM package, i.e. do opam install pcre to include the netstring-pcre library in a rebuild.



Supported regexp syntax: See pcrepattern(3).
type regexp = Pcre.regexp 
The type of regular expressions; now based on Pcre
type split_result = Pcre.split_result = 
| Text of string
| Delim of string
| Group of int * string
| NoGroup (*
Here we keep compatiblity with Pcre
*)
type result 
The type of matching results
val regexp : string -> regexp
Parses a regexp
val regexp_case_fold : string -> regexp
Parses a case-insensitive regexp
val quote : string -> string
Quotes a string such that it can be included in a regexp
val regexp_string : string -> regexp
Returns a regexp that matches exactly the string
val regexp_string_case_fold : string -> regexp
Returns a case-insensitive regexp that matches exactly the string
val string_match : regexp -> string -> int -> result option
Matches the string at the position with the regexp. Returns None if no match is found. Returns Some r on success, and r describes the match.
val bytes_match : regexp -> Bytes.t -> int -> result option
Same for bytes
val search_forward : regexp -> string -> int -> int * result
Searches a match of the string with the regexp, starting at the position and in forward direction. Raises Not_found if no match could be found. Returns (p,r) when a match at position p is found, described by r.
val search_forward_bytes : regexp -> Bytes.t -> int -> int * result
Same for bytes
val search_backward : regexp -> string -> int -> int * result
Searches a match of the string with the regexp, starting at the position and in backward direction. Raises Not_found if no match could be found. Returns (p,r) when a match at position p is found, described by r.
val search_backward_bytes : regexp -> Bytes.t -> int -> int * result
Same for bytes
val matched_string : result -> string -> string
Extracts the matched part from the string. The string argument must be the same string passed to string_match or the search functions, and the result argument must be the corresponding result.
val matched_bytes : result -> Bytes.t -> Bytes.t
Same for bytes
val match_beginning : result -> int
Returns the position where the matched part begins
val match_end : result -> int
Returns the position where the matched part ends
val matched_group : result -> int -> string -> string
Extracts the substring the nth group matches from the whole string. The string argument must be the same string passed to string_match or the search functions, and the result argument must be the corresponding result.
val matched_group_bytes : result -> int -> Bytes.t -> Bytes.t
Same for bytes
val group_beginning : result -> int -> int
Returns the position where the substring matching the nth group begins
val group_end : result -> int -> int
Returns the position where the substring matching the nth group ends
val global_replace : regexp -> string -> string -> string
global_replace re templ s: Replaces all matchings of re in s by templ.

In templ one can refer to matched groups by the backslash notation: \1 refers to the first group, \2 to the second etc. \0 is the whole match. \\ is the backslash character.

val replace_first : regexp -> string -> string -> string
replace_first re templ s: Replaces the first match of re in s by templ.

In templ one can refer to matched groups by the backslash notation: \1 refers to the first group, \2 to the second etc. \0 is the whole match. \\ is the backslash character.

val global_substitute : regexp ->
(result -> string -> string) -> string -> string
global_substitute re subst s: Applies the substitution function subst to all matchings of re in s, and returns the transformed string. subst is called with the current result of the match and the whole string s.
val substitute_first : regexp ->
(result -> string -> string) -> string -> string
substitute_first re subst s: Applies the substitution function subst to the first matching of re in s, and returns the transformed string. subst is called with the current result of the match and the whole string s.
val split : regexp -> string -> string list
Splits the string according to the regexp in substrings. Occurrences of the delimiter at the beginning and the end are ignored.
val bounded_split : regexp -> string -> int -> string list
Splits into at most n substrings, based on split
val split_delim : regexp -> string -> string list
Same as split, but occurrences of the delimiter at the beginning and the end are returned as empty strings
val bounded_split_delim : regexp -> string -> int -> string list
Splits into at most n substrings, based on split_delim
val full_split : regexp -> string -> split_result list
Like split_delim, but returns the delimiters in the result
val bounded_full_split : regexp -> string -> int -> split_result list
Splits into at most n substrings, based on full_split
val string_before : string -> int -> string
The first n characters of a string
val string_after : string -> int -> string
The last n characters of a string
val first_chars : string -> int -> string
Same as string_before
val last_chars : string -> int -> string
Same as string_after
ocamlnet-4.1.2/doc/html-main/Nettelnet_client.telnet_session-c.html0000644000175000017500000007251412731530353024055 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettelnet_client.telnet_session

Class Nettelnet_client.telnet_session

class telnet_session : object .. end
A telnet session

Overwiew

The telnet_session object has two queues, one for arriving data, one for data to send. Once the session object is attached to an event system, it connects to the remote peer, and processes the queues. Input is appended to the input queue; output found on the output queue is sent to the other side. If input arrives, a callback function is invoked. You may close the output side of the socket by putting Telnet_eof onto the output queue. Once the EOF marker has been received, a Telnet_eof is appended to the input queue, and the connection is closed (completely). The session object detaches from the event system automatically in this case.

Hints

Set an input handler as callback function in the session object. The input handler is called when new input data have been arrived. It should inspect the input queue, process the queue as much as possible, and it should remove the processed items from the queue. While processing, it may add new items to the output queue.

If you are not within the callback function and add items to the output queue, the session object will not detect that there are new items to send - unless you invoke the update method.

If you want option negotiation, it is the simplest way to use the special option negotiation methods. Configure the options as you want (invoking enable, disable etc), but do not forget to modify the way input is processed. Every Telnet_will, _wont, _do, and _dont command must be passed to process_option_command.

method set_connection : telnet_connector -> unit
Sets the host name and the port of the remote server to contact.
method set_event_system : Unixqueue.event_system -> unit
Sets the event system to use. By default, a private event system is used.
method set_callback : (bool -> unit) -> unit
Sets the callback function. This function is called after new commands have been put onto the input queue. The argument passed to the callback function indicates whether a 'Synch' sequence was received from the remote side or not.

Note Synch: If the client sees a data mark command it will assume that it is actually a Synch sequence. The client automatically discards any Telnet_data commands from the input queue (but not Telnet_datas inside subnegotiations). The data mark command itself remains on the queue.

method set_exception_handler : (exn -> unit) -> unit
Sets the exception handler. Every known error condition is caught and passed to the exception handler. The exception handler can do whatever it wants to do. If it raises again an exception, the new exception is always propagated up to the caller (whoever this is). Often the caller is the event system scheduler (i.e. Unixqueue.run); see the documention there.

If you do not set the exception handler, a default handler is active. It first resets the session (see method reset), and then wraps the exception into the Telnet_protocol exception, and raises this exception again.

method output_queue : telnet_command Queue.t
The queue of commands to send to the remote side. If you add new commands to this queue, do not forget to invoke the update method which indicates to the event system that new data to send is available. After commands have been sent, they are removed from the queue.
method input_queue : telnet_command Queue.t
The queue of commands received from the remote side. This class only adds commands to the queue (and invokes the callback function). The user of this class is responsible for removing commands from the queue which have been processed.
method get_options : telnet_options
Get the configuration options.
method set_options : telnet_options -> unit
Set the configuration options.
method reset : unit -> unit
Closes the connection immediately and empties all queues. All negotiated options are reset, too.
method enable_local_option : telnet_negotiated_option -> unit
method enable_remote_option : telnet_negotiated_option -> unit
method disable_local_option : telnet_negotiated_option -> unit
method disable_remote_option : telnet_negotiated_option -> unit
method offer_local_option : telnet_negotiated_option -> unit
method request_remote_option : telnet_negotiated_option -> unit
method reset_local_option : telnet_negotiated_option -> unit
method reset_remote_option : telnet_negotiated_option -> unit
method get_local_option : telnet_negotiated_option ->
telnet_option_state
method get_remote_option : telnet_negotiated_option ->
telnet_option_state
method option_negotiation_is_over : bool
method process_option_command : telnet_command -> unit
method fetch_subnegotiation : string option
This method should be called as follows: If you find a Telnet_sb at the beginning of the input queue, remove this command Queue.take, and invoke fetch_subnegotiation. This method scans the queue and looks for the associated Telnet_se command. If it does not find it, None is returned. If Telnet_se is found, the parameter enclosed by the two commands is returned as Some s where s is the parameter string. Furthermore, in the latter case the data items and the closing Telnet_se are removed from the queue.
method attach : unit -> unit
Attach to the event system. After being attached, the client is ready to work.
method run : unit -> unit
Run the event system
method update : unit -> unit
If there are commands in the output queue, the event system is signaled that this client wants to do network I/O.
method send_synch : telnet_command list -> unit
At the next output oppurtunity, a Synch sequence is sent to the remote peer. This means that the passed commands, extended by an additional Data Mark command, are sent to the peer as urgent data.

Sending a Synch sequence has higher priority than the output queue; processing of the output queue is deferred until the Synch sequence has been completely sent.

method expect_input : bool -> unit
Set whether the timeout value is to be applied to the input side of the connection. This is true by default.
method start_tls : (module Netsys_crypto_types.TLS_CONFIG) -> peer_name:string option -> unit
Switch to TLS. Note that this is not covered by the TELNET protocol standard. However, some applications of TELNET use this nevertheless (e.g. FTP control connections).

Switching to TLS can be done at any time, but should be done at a moment when the other side of the connection expects it. If start_tls is invoked before attach, TLS is enabled at the very beginning of the TELNET connection.

The arguments are the TLS configuration, and the peer name for validation (pass the host name here).

method tls_session_props : Nettls_support.tls_session_props option
TLS session properties (if on)
method tls_session_data : string option
TLS session data (if on)
ocamlnet-4.1.2/doc/html-main/Netencoding.QuotedPrintable.encoding_pipe-c.html0000644000175000017500000004233612731530353025657 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.QuotedPrintable.encoding_pipe

Class Netencoding.QuotedPrintable.encoding_pipe

class encoding_pipe : ?crlf:bool -> unit -> Netchannels.pipe
This pipe encodes the data written into the pipe.

ocamlnet-4.1.2/doc/html-main/type_Netchannels.raw_out_channel_delegation.html0000644000175000017500000004110212731530353026132 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_out_channel_delegation ?close:bool -> Netchannels.raw_out_channel -> Netchannels.raw_out_channelocamlnet-4.1.2/doc/html-main/Netmech_scram_sasl.html0000644000175000017500000005162412731530353021071 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl

Module Netmech_scram_sasl

module Netmech_scram_sasl: sig .. end
SCRAM as SASL mechanism

This module needs the SHA-1 hash function. In order to use it, initialize crypto support, e.g. by including the nettls-gnutls packages and calling Nettls_gnutls.init.

As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of SCRAM should pass user names and passwords through Netsaslprep.saslprep.


module type PROFILE = sig .. end
The profile sets some basic parameters.
module SHA1: PROFILE 
Uses SHA-1 as hash function.
module SHA1_PLUS: PROFILE 
Same as Netmech_scram_sasl.SHA1, only that the mechanism name is "SCRAM-SHA-1-PLUS"
module SHA256: PROFILE 
Uses SHA-256 as hash function.
module SHA256_PLUS: PROFILE 
Same as Netmech_scram_sasl.SHA256, only that the mechanism name is "SCRAM-SHA-256-PLUS"
module SCRAM: 
Create a new SCRAM SASL mechanism for this profile.
module SCRAM_SHA1: Netsys_sasl_types.SASL_MECHANISM 
SCRAM with SHA1 profile
module SCRAM_SHA1_PLUS: Netsys_sasl_types.SASL_MECHANISM 
SCRAM with SHA1_PLUS profile
module SCRAM_SHA256: Netsys_sasl_types.SASL_MECHANISM 
SCRAM with SHA256 profile
module SCRAM_SHA256_PLUS: Netsys_sasl_types.SASL_MECHANISM 
SCRAM with SHA256_PLUS profile
ocamlnet-4.1.2/doc/html-main/Rpc_client.Debug.html0000644000175000017500000004375612731530353020415 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.Debug

Module Rpc_client.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Whether debug messages are enabled. See Netlog.Debug for more information.
val enable_ptrace : bool Pervasives.ref
Whether the procedure trace is enabled as debug messages. The procedure trace outputs for every RPC call and response a debug message. ptrace_verbosity says how verbose.
val ptrace_verbosity : Rpc_util.verbosity Pervasives.ref
How verbose the ptrace is. Defaults to `Name_abbrev_args
val disable_for_client : Rpc_client.t -> unit
Disables all log messages for this client (internally used)
ocamlnet-4.1.2/doc/html-main/type_Rpc_client.html0000644000175000017500000014025212731530353020416 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client sig
  exception Message_lost
  exception Message_timeout
  exception Response_dropped
  exception Communication_error of exn
  exception Client_is_down
  exception Keep_call
  exception Unbound_exception of exn
  type t
  type connector =
      Inet of (string * int)
    | Internet of (Unix.inet_addr * int)
    | Unix of string
    | W32_pipe of string
    | Descriptor of Unix.file_descr
    | Dynamic_descriptor of (unit -> Unix.file_descr)
    | Portmapped of string
  val connector_of_sockaddr : Unix.sockaddr -> Rpc_client.connector
  val connector_of_socksymbol :
    Netsockaddr.socksymbol -> Rpc_client.connector
  val shutdown_connector :
    Rpc_client.t ->
    Rpc_transport.rpc_multiplex_controller -> (unit -> unit) -> unit
  class type socket_config =
    object
      method multiplexing :
        dbg_name:string Pervasives.ref ->
        close_inactive_descr:bool ->
        peer_name:string option ->
        Rpc.protocol ->
        Unix.file_descr ->
        Unixqueue.event_system ->
        Rpc_transport.rpc_multiplex_controller Uq_engines.engine
      method non_blocking_connect : bool
    end
  val default_socket_config : Rpc_client.socket_config
  class default_socket_config : socket_config
  val blocking_socket_config : Rpc_client.socket_config
  class blocking_socket_config : socket_config
  val tls_socket_config :
    (module Netsys_crypto_types.TLS_CONFIG-> Rpc_client.socket_config
  class tls_socket_config :
    (module Netsys_crypto_types.TLS_CONFIG-> socket_config
  type internal_pipe = Netxdr.xdr_value Netsys_polypipe.polypipe
  type internal_socket = Netxdr.xdr_value Netsys_polysocket.polyclient
  type mode2 =
      [ `Internal_endpoint of
          Rpc_client.internal_pipe * Rpc_client.internal_pipe
      | `Internal_socket of Rpc_client.internal_socket
      | `Multiplexer_endpoint of Rpc_transport.rpc_multiplex_controller
      | `Socket of
          Rpc.protocol * Rpc_client.connector * Rpc_client.socket_config
      | `Socket_endpoint of Rpc.protocol * Unix.file_descr ]
  val create2 :
    ?program_number:Netnumber.uint4 ->
    ?version_number:Netnumber.uint4 ->
    ?initial_xid:int ->
    ?shutdown:(Rpc_client.t ->
               Rpc_transport.rpc_multiplex_controller ->
               (unit -> unit) -> unit) ->
    Rpc_client.mode2 ->
    Rpc_program.t -> Unixqueue.event_system -> Rpc_client.t
  val unbound_create :
    ?initial_xid:int ->
    ?shutdown:(Rpc_client.t ->
               Rpc_transport.rpc_multiplex_controller ->
               (unit -> unit) -> unit) ->
    Rpc_client.mode2 -> Unixqueue.event_system -> Rpc_client.t
  val bind : Rpc_client.t -> Rpc_program.t -> unit
  val use : Rpc_client.t -> Rpc_program.t -> unit
  val configure : Rpc_client.t -> int -> float -> unit
  val configure_next_call : Rpc_client.t -> int -> float -> unit
  val set_dgram_destination : Rpc_client.t -> Unix.sockaddr option -> unit
  val set_batch_call : Rpc_client.t -> unit
  val set_user_name : Rpc_client.t -> string option -> unit
  val set_max_response_length : Rpc_client.t -> int -> unit
  val set_exception_handler : Rpc_client.t -> (exn -> unit) -> unit
  val set_mstring_factories :
    Rpc_client.t -> Netxdr_mstring.named_mstring_factories -> unit
  val event_system : Rpc_client.t -> Unixqueue.event_system
  val programs : Rpc_client.t -> Rpc_program.t list
  val get_socket_name : Rpc_client.t -> Unix.sockaddr
  val get_peer_name : Rpc_client.t -> Unix.sockaddr
  val get_sender_of_last_response : Rpc_client.t -> Unix.sockaddr
  val get_xid_of_last_call : Rpc_client.t -> Netnumber.uint4
  val get_protocol : Rpc_client.t -> Rpc.protocol
  val get_tls_session_props :
    Rpc_client.t -> Nettls_support.tls_session_props option
  val get_gssapi_props : Rpc_client.t -> Netsys_gssapi.client_props option
  val abandon_call : Rpc_client.t -> Netnumber.uint4 -> unit
  val is_up : Rpc_client.t -> bool
  val get_stats : Rpc_client.t -> int * int * int
  val unbound_sync_call :
    Rpc_client.t ->
    Rpc_program.t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
  val unbound_async_call :
    Rpc_client.t ->
    Rpc_program.t ->
    string ->
    Netxdr.xdr_value -> ((unit -> Netxdr.xdr_value) -> unit) -> unit
  class unbound_async_call :
    Rpc_client.t ->
    Rpc_program.t ->
    string -> Netxdr.xdr_value -> [Netxdr.xdr_value] Uq_engines.engine
  val synchronize :
    Unixqueue.event_system ->
    ('-> ((unit -> 'b) -> unit) -> unit) -> '-> 'b
  val shut_down : Rpc_client.t -> unit
  val sync_shutdown : Rpc_client.t -> unit
  val trigger_shutdown : Rpc_client.t -> (unit -> unit) -> unit
  val set_debug_name : Rpc_client.t -> string -> unit
  val get_debug_name : Rpc_client.t -> string
  type reject_code = [ `Fail | `Next | `Renew | `Retry ]
  class type auth_session =
    object
      method auth_protocol : Rpc_client.auth_protocol
      method next_credentials :
        Rpc_client.t ->
        Rpc_program.t ->
        string ->
        Netnumber.uint4 ->
        string * string * string * string * Netxdr.encoder option *
        Netxdr.decoder option
      method server_accepts :
        Rpc_client.t -> Netnumber.uint4 -> string -> string -> unit
      method server_rejects :
        Rpc_client.t ->
        Netnumber.uint4 -> Rpc.server_error -> Rpc_client.reject_code
    end
  and auth_protocol =
    object
      method auth_method : Rpc_client.auth_method
      method destroy : unit -> unit
      method emit :
        Netnumber.uint4 ->
        Netnumber.uint4 -> Netnumber.uint4 -> Rpc_packer.packed_value
      method gssapi_props : Netsys_gssapi.client_props option
      method receive : Rpc_packer.packed_value -> unit
      method state :
        [ `Done of Rpc_client.auth_session
        | `Emit
        | `Error
        | `Receive of Netnumber.uint4 ]
    end
  and auth_method =
    object
      method name : string
      method new_session :
        Rpc_client.t -> string option -> Rpc_client.auth_protocol
    end
  val auth_none : Rpc_client.auth_method
  val set_auth_methods : Rpc_client.t -> Rpc_client.auth_method list -> unit
  module type USE_CLIENT =
    sig
      type t
      val use : Rpc_client.USE_CLIENT.t -> Rpc_program.t -> unit
      val unbound_sync_call :
        Rpc_client.USE_CLIENT.t ->
        Rpc_program.t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
      val unbound_async_call :
        Rpc_client.USE_CLIENT.t ->
        Rpc_program.t ->
        string ->
        Netxdr.xdr_value -> ((unit -> Netxdr.xdr_value) -> unit) -> unit
      val xdr_ctx : Rpc_client.USE_CLIENT.t -> Netxdr.ctx
    end
  val xdr_ctx : Rpc_client.t -> Netxdr.ctx
  val create :
    ?program_number:Netnumber.uint4 ->
    ?version_number:Netnumber.uint4 ->
    ?initial_xid:int ->
    ?shutdown:(Rpc_client.t ->
               Rpc_transport.rpc_multiplex_controller ->
               (unit -> unit) -> unit) ->
    Unixqueue.event_system ->
    Rpc_client.connector -> Rpc.protocol -> Rpc_program.t -> Rpc_client.t
  val program : Rpc_client.t -> Rpc_program.t
  val add_call :
    Rpc_client.t ->
    string ->
    Netxdr.xdr_value -> ((unit -> Netxdr.xdr_value) -> unit) -> unit
  val sync_call :
    Rpc_client.t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
  val verbose : bool -> unit
  module Debug :
    sig
      val enable : bool Pervasives.ref
      val enable_ptrace : bool Pervasives.ref
      val ptrace_verbosity : Rpc_util.verbosity Pervasives.ref
      val disable_for_client : Rpc_client.t -> unit
    end
end
ocamlnet-4.1.2/doc/html-main/Netexn.html0000644000175000017500000004645112731530353016542 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netexn

Module Netexn

module Netexn: sig .. end
Exception registry

This module allow the user to register exceptions, and to set a custom exception printing function. This results in nicer exception prints when Netexn.to_string is called instead of Printexc.to_string.

Generally, Printexc.to_string works well if:

  • the exception does not have arguments, or
  • all arguments are int's or string's.
In these cases it is not required to register a custom printer. Arguments that are neither int nor string are printed as "_", however, so defining a custom printer helps then.

The printers registered here are intended for helping debugging, so the goal is to print all of the exception in an unambiguous way. The syntax "Exception(arg1, arg2, ...)" is preferred.

Since OCaml 3.11.2 there is a similar feature in Printexc. If Ocamlnet recognizes that Printexc.register_printer is available, all functions registered in this module are also registered at the central Printexc registry. For users it does not make a difference then whether Netexn.to_string or Printexc.to_string is called to print the exception. We recommend, however, to use Netexn as primary registry for all code that uses Ocamlnet because this mechanism also works for older Ocaml versions, and is slightly more efficient.


val register_printer : exn -> (exn -> string) -> unit
register e f: Register that the exception type of the sample exception e is to be printed by f.

In multi-threaded programs, this function should no longer be called once threads have been spawned.

val to_string : exn -> string
Prints the exception as string, using the registered printer functions, or Printexc.to_string as fallback if there is no better printer
ocamlnet-4.1.2/doc/html-main/type_Netplex_sockserv.html0000644000175000017500000004364512731530353021702 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sockserv sig
  val create_socket_service :
    Netplex_types.processor ->
    Netplex_types.socket_service_config -> Netplex_types.socket_service
  val create_server_socket :
    string ->
    Netplex_types.protocol ->
    Netplex_types.extended_address -> Unix.file_descr
  val close_server_socket : Unix.file_descr -> unit
  val any_file_client_connector : string -> Rpc_client.connector
  val client_connector :
    Netplex_types.extended_address -> Rpc_client.connector
end
ocamlnet-4.1.2/doc/html-main/type_Netaux.html0000644000175000017500000004707012731530353017604 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaux sig
  module KMP :
    sig
      type pattern
      val make_pattern : string -> Netaux.KMP.pattern
      val find_pattern :
        Netaux.KMP.pattern -> ?pos:int -> ?len:int -> Bytes.t -> int
    end
  module ArrayAux :
    sig
      val int_blit : int array -> int -> int array -> int -> int -> unit
      val int_series :
        int array -> int -> int array -> int -> int -> int -> unit
      val int_blit_ref :
        (int array -> int -> int array -> int -> int -> unit) Pervasives.ref
      val int_series_ref :
        (int array -> int -> int array -> int -> int -> int -> unit)
        Pervasives.ref
    end
end
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.SHA1.html0000644000175000017500000004056412731530353022626 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SHA1 PROFILEocamlnet-4.1.2/doc/html-main/Netsys_types.mstring-c.html0000644000175000017500000004440612731530353021712 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_types.mstring

Class type Netsys_types.mstring

class type mstring = object .. end
See Netxdr_mstring.mstring for documentation

method length : int
method blit_to_bytes : int -> Bytes.t -> int -> int -> unit
method blit_to_string : int -> Bytes.t -> int -> int -> unit
Deprecated."Use blit_to_bytes instead."
method blit_to_memory : int -> memory -> int -> int -> unit
method as_bytes : Bytes.t * int
method as_string : string * int
method as_memory : memory * int
method preferred : [ `Bytes | `Memory ]
ocamlnet-4.1.2/doc/html-main/Netoid.html0000644000175000017500000004545112731530353016522 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netoid

Module Netoid

module Netoid: sig .. end
X.500 Object Identifiers

type t = int array 
val equal : t -> t -> bool
Whether two OIDs are equal
val compare : t -> t -> int
Lexicographic ordering of OIDs
val of_string : string -> t
Parses an OID in dot notation, e.g. of_string "2.3.4" = [| 2; 3; 4 |]
val to_string : t -> string
Returns the OID in dot notation, e.g. to_string [| 2; 3; 4 |] = "2.3.4"
val of_string_curly : string -> t
Parses an OID in curly brace notation, e.g. of_string "{2 3 4}" = [| 2; 3; 4 |]
val to_string_curly : t -> string
Returns the OID in curly brace notation, e.g. to_string [| 2; 3; 4 |] = "{2 3 4}"
ocamlnet-4.1.2/doc/html-main/Nethttp_client.Debug.html0000644000175000017500000004225512731530353021310 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.Debug

Module Nethttp_client.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module
ocamlnet-4.1.2/doc/html-main/Netmcore_basics.html0000644000175000017500000013445612731530353020404 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_basics

Netmcore_basics


Netmulticore Basics

Contents

The intention of this chapter is to give an overview over the basic mechanisms of Netmulticore. The focus is here on the safe mechanisms, i.e. those that cannot crash the program if used the wrong way. Generally, however, Netmulticore also provides unsafe programming elements, mostly to maximize performance. The unsafe elements are well explained in Netmcore_tut.

Processes

Netmulticore uses subprocesses as workers. This has the advantage that the workers are really independent from each other. Especially, every worker does its own memory management (e.g. a worker won't stop another worker when it does a garbage collection run). The downside is, of course, that it is harder to exchange data between the workers (especially compared with multithreading).

Remember that multithreading in OCaml is restricted so that at most only one CPU core can be utilized. Implementing the workers with full processes is so far the only way to run algorithms on more than one core.

There is a fixed process hierarchy. When Netmulticore starts up, the current process becomes the master process, and the workers will be children of this master:

master
  |
  +-- worker1
  |
  +-- worker2
  |
  +-- worker3

It is possible to create new workers at any time. A worker can create another worker, and Netmulticore creates then a new child as fork of the master (really, this works, and is implemented by forwarding the creation request from the worker to the master). Netmulticore never forks a worker from a worker directly - this would create deep process hierarchies, and these tend to become unmanageable.

In the same way, it is also possible to wait for the termination of a worker (join). Any worker can join any other worker.

All "payload work" must be really done by the workers, and not by the master. The master remains mostly idle for the time of the Netmulticore job, and only provides auxiliary services for things that must be done in the master (e.g. organizing a fork). Ideally, the master process is kept as lean as possible, i.e. nothing is stored there, because the new workers are copies of the master image, and copying is cheapest when the image is as small as possible.

Starting up, shutting down

At startup time, Netmulticore starts one special worker, the first process. This is the only worker that is not started by another worker, but directly by the process playing the role of the master.

When all workers have terminated, the Netmulticore job is done. At this point, the master process is alone again. It is now possible to query for the result of other worker processes, especially of the first process.

Let's look at a simple example (the "hello world" of Netmulticore):

let computation (x,y) =
  x +. y

let computation_fork, computation_join =
  Netmcore_process.def_process computation

let first_process() =
  Netmcore_process.start computation_fork (3.0,4.0)

let extract_result _ pid =
  Netmcore_process.join_nowait computation_join pid

let () =
  let sum_opt =
    Netmcore.run
      ~socket_directory:"/tmp/netmcore"
      ~first_process
      ~extract_result
      () in
  match sum_opt with
    | None -> printf "Error\n"
    | Some sum -> printf "Sum: %f\n" sum

The function to be run in a worker process is here computation. With Netmcore_process.def_process we define this function as designated process. Note that this needs to happen before the first worker is started, and because of this, it is normally done in global context (i.e. not from a function body, but directly at module level). The master needs to know all functions that can be used as worker processes in advance (remember that all forks are managed by the master). def_process returns a pair of "fork point" and "join point". These are abstract descriptors needed for forking and joining, respectively.

With Netmcore_process.start a new worker is started. The arguments are the "fork point" (which implicitly names the worker function), and the argument passed to the worker. The process identifier is returned. In this example, we have only one worker, and that takes over the role of the first process. (N.B. The pid is not directly the identifier used by the operating system, but an internally managed identifier.)

As mentioned, the Netmulticore job is done when all workers have finished their tasks. Normally, you call Netmcore_process.join to get the result of a worker. However, join also blocks the execution (i.e. it waits until the worker is done). In the master process, blocking is generally not allowed, and hence we have to use here the variant of join that does not wait, Netmcore_process.join_nowait. As we already know that the workers are finished, and we only want to get the result value, this is no problem here.

For joining, we pass the so-called "join point" to this function - basically, this tells join_nowait which result to retrieve.

The callback extract_result is invoked when the workers are already done, but before Netmulticore officially finishes its work. This is the last moment when workers can be joined. The result of extract_result is the result of Netmcore.run.

History: The function Netmcore.run is new in OCamlnet-3.6.3. In older versions there was only Netmcore.startup without providing any way to pass results back to the caller. Note that Netmcore.join_nowait was also added in this release. If you find code in the Internet, it often contains workarounds for these limitations present in older Ocamlnet versions.

A few more remarks:

  • The socket_directory is used for Unix domain sockets, and for temporary files Netmulticore may need. Typical locations are /tmp or /var/run. The path name of this directory must not be too iong (there is a limit of around 100 chars in total). The name can also be generated. You can delete the directory after use.
  • Worker parameters (here the float pair (3.0,4.0) and the sum) are passed by serializing the values with the Marshal module. So far, functional values, objects, lazy values, and exceptions cannot be marshalled.
  • Essentially, Netmulticore uses the functionality provided by Netplex to start and stop processes, and also for the communication between worker and master. Because of this, the Netplex infrastructure is fully available. For instance, you can use the functions of Netplex_cenv, e.g. for logging, or manipulating the Netplex container. The netplex-admin utility (see The netplex-admin command) can be used to query the process state from the command line. It is not only possible to use Netplex from Netmulticore, but also the other way round: A network server implemented with Netplex can start Netmulticore workers (just call Netmcore_process.start when you need one) - the only requirement and initialization for this is that Netmcore.add_plugins must have been called at Netplex startup time. We'll look at the possible interactions with Netplex closer below.

Primitive parallelization

In the most simple scenario, a few workers are started at the same time, and compute the result in parallel. When the workers are done, it is expected that every worker has computed some part result, and it is only required to retrieve it, and to combine it with the other part results. Note that Netmcore.run can only start one worker, so we need to start the real workers on our own from the single first process:

let n = <number of workers>

let computation (i,arg) =
  <compute something from arg and return it>

let computation_fork, computation_join =
  Netmcore_process.def_process computation

let manage arg =
  let pids =
    List.map
      (fun i -> Netmcore_process.start computation_fork (i,arg))
      (Array.to_list (Array.initialize n (fun i -> i))) in
  let results =
    List.map
      (fun pid ->
         match Netmcore_process.join computation_join pid with
           | None -> failwith "No result after error"
           | Some r -> r
      )
      pids in
  <reduce the results to a single one>

let manage_fork, manage_join =
  Netmcore_process.def_process manage

let first_process arg =
  Netmcore_process.start manage_fork arg

let extract_result _ pid =
  Netmcore_process.join_nowait manage_join pid

<call Netmcore.run as above>

Here, manage takes over the role of the first process that starts the real workers, and waits until the workers are done. Note that we use Netmcore_process.join here, and no longer join_nowait, because it is essential to wait for the termination of the workers.

Some remarks:

  • Starting and terminating processes are relatively expensive operations. This scheme is only well-suited if the parallelized computation takes really long (e.g. several seconds at least)
  • The workers do not communicate directly with each other in this scheme. The workers just get an argument to process, and deliver some part result. In between, there is no opportunity for data exchange.
  • The workers are created at the time they receive their arguments. There is no option for doing some per-worker initialization before the invocation. Of course, one can do some global initialization in the master, because the worker processes are created as copies of the master process, and inherit any global data prepared there.
  • Every worker gets an individual copy of the arguments. Copying is not a free operation, although quite cheap. For certain algorithms, copying per worker is already relatively expensive, and decreases the performance noticeably (e.g. this can be observed for sorting algorithms).

Using Netplex IPC mechanisms

As noted, the Netplex library is the basis on which Netmulticore provides more advanced features. Let's have a quick glance at the mechanisms Netplex defines:

Generally, the Netplex mechanisms are implemented on top of RPC messaging with Unix domain sockets. The master process serves as the controlling instance of the primitives, i.e. the worker sends a message to the master with a request like "lock the mutex", and the master implements the logic, eventually notifying the worker that the lock has been acquired. This type of IPC primitives is relatively slow, but also robust ("uncrashable"), and does not need special prerequisites like shared memory. (Note that there are also very fast IPC primitives in Netmulticore that use shared memory for communication, and which are described in Netmcore_tut. These are, however, a lot more complicated to use than the simple ones defined here, and not well suited as starting point for exploring parallelization options in OCaml.)

Initialization

The Netplex mechanisms need to be initialized at two times:

  • They need to be added as plugins to the Netplex controller. Such a plugin attaches some new behavior to the Netplex routines running in the master process. This type of initialization is done once per Netplex controller, and as Netmulticore creates a new controller per Netmcore.run call, this is required for every such call.

    The plugin is defined in the respective module (i.e. Netplex_mutex.plugin, Netplex_sharedvar.plugin, and Netplex_semaphore.plugin). You just need to add it to the controller with code like

      Netmcore.run
        ...
        ~init_ctrl:(fun ctrl -> ctrl # add_plugin Netplex_mutex.plugin)
        ...
        

    Adding a plugin several times is a no-op.

  • Of course, you can manage several objects per mechanism (i.e. several mutexes/variables/semaphores). Each object needs to be created. Note that you cannot do this in the scope of the master process! A good point in time to do this is at the beginning of the first worker process, before any further worker is launched. (Alternatively, it is also possible to create the objects when they are used first. This is a bit more complicated, and not covered by this tutorial.)

    The objects are normally identified by strings. For example, a semaphore could be created as

        ignore(Netplex_semaphore.create "my_sem" 5L)
        

    The initial value would be 5. The semaphore is now available for all workers in the same Netmcore.run session under this name. The return value of Netplex_semaphore.create says whether the semaphore was created (true). Otherwise, the semaphore existed already.

There is normally no need to delete the objects when you are done with them. The objects are bound to the lifetime of the Netplex controller, and this ends anyway when Netmcore.run returns.

Object initialization for semaphores

As mentioned, the function to call is Netplex_semaphore.create:

let success =
  Netplex_semaphore.create name initial_value

Remember that semaphores are counters with non-negative values, and hence initial_value is the initial counter value.

Object initialization for mutexes

There is no need to create mutexes - these are implicitly created (in unlocked state) when they are used for the first time, i.e. when doing

let mutex_handle =
  Netplex_mutex.access name

(Now call Netplex_mutex.lock or Netplex_mutex.unlock to work with the mutex.)

Object initialization for shared variables

For Netplex_sharedvar variables, the creation looks like

let success =
  Netplex_sharedvar.create_var ~enc:true "my_var"

We pass here enc:true which is required when we want to use the Netplex_sharedvar.Make_var_type functor for getting easy and safe access. This works like this: Define

module Var_foo =
  Netplex_sharedvar.Make_var_type(struct type t = foo end)

in global context to get the well-typed accessor functions

let value = Var_foo.get "my_var"

and

Var_foo.set "my_var" new_value

As noted, this works only when setting enc:true at creation time.

Operation

Generally, the access to the Netplex synchronization objects is restricted to the lifetime of the Netplex controller (i.e. the duration of Netmcore.run), and the objects can only be accessed from worker processes (or better, from any Netplex container, as workers are implemented by containers). It is not possible to interact with the objects from the master process (although there are a few exceptions from this rule, e.g. you can read (but not write) the value of a shared variable also from the master, and the last opportunity is even in the extract_result callback of Netmcore.run).

Every operation is isolated from concurrent operations of the same type. For example, when two workers set the same shared variable with Var_foo.set "my_var", there is no risk that the two calls interact in a bad way and cause a crash. Netplex implicitly serializes such calls, and one of the two calls is executed before the other.

For this reason, it is normally not necessary to proctect a single shared variable with a mutex. You need mutexes first when you need to synchronize several variables, or a variable and a semaphore.

Overview of the operations (see linked pages for details):

Message passing

Message passing means that a worker installs a message box, and waits for the arrival of messages from other workers. Messages can be arbitrary OCaml values provided these can be marshalled. The message boxes implemented by Netplex_mbox have only space for one message at a time, so the message senders will have to wait until the box is free.

There are other implementations of message boxes in OCamlnet: Netcamlbox provides very fast boxes that store the messages in shared memory. The caveat is that the size of the messages is limited. Another option is Netmcore_queue which is a shared value queue which can be easily extended to support full message box functionality. Both alternatives do not run on every operating system, though (but Linux and OS X are supported).

Preparations: First, the required plugin needs to be installed in the Netplex controller. Again, use code like

  Netmcore.run
    ...
    ~init_ctrl:(fun ctrl -> ctrl # add_plugin Netplex_mbox.plugin)
    ...

Second, create the mailbox module. This is very similar to Netplex_sharedvar, e.g.:

module Mbox_foo =
  Netplex_mbox.Make_mbox_type(struct type t = foo end)

Remember that this needs to happen in global context (i.e. don't do it in a local module).

Now create the mailbox (in a worker):

let mbox = Mbox_foo.create "mybox"

If the box already exists, it is just opened, so you can use create to get a handle for the message box in all workers accessing it. Sending a message msg of type foo is as easy as

Mbox_foo.send mbox msg

and receiving one is possible with

let msg = Mbox_foo.receive mbox

which also waits for the arrival of the message. Remember that all three functions, create, send, and receive can only be called from worker context.

Example: Task queue

In this example, we want to parallelize a list of tasks which can be independently run on any worker. The idea is that every worker provides a message box where a special process, the supervisor, sends the task descriptions to. If all tasks are done, the supervisor sends a termination request instead:

type worker_msg =
  | Task of task
  | Term_request

The supervisor has no idea by itself which worker is busy and which one would be free for another task. Because of this, the supervisor installs another message box, and the worker sends a message when it is idle and requests another task:

type supervisor_msg =
  | Task_request of int

The integer argument is the index of the requesting worker.

This arrangement will result in a "ping pong game": When a worker is free it sends Task_request to the supervisor, which in turn will send the next Task to the requesting worker, or Term_request if the list is already empty. The interesting property is that no process actively monitors another process - instead, all processes just wait for messages and react on these.

The definitions of the mailbox modules:

module Mbox_worker =
  Netplex_mbox.Make_mbox_type(struct type t = worker_msg end)

module Mbox_supervisor =
  Netplex_mbox.Make_mbox_type(struct type t = supervisor_msg end)

The implementation of the workers

The workers wait for the arrival of messages from the supervisor in a loop, and react on incoming tasks. The loop is left when the termination request arrives.

let worker_main w =
  (* where w is the index of the worker, 0..n-1 *)
  let wrk_mbox_name = sprintf "Worker_%d" w in
  let wrk_mbox = Mbox_worker.create wrk_mbox_name in
  let op_mbox = Mbox_supervisor.create "Supervisor" in
  let cont = ref true in
  while !cont do
    (* request a new task *)
    Mbox_supervisor.send op_mbox (Task_request w);
    (* wait for task *)
    match Mbox_worker.receive wrk_mbox with
      | Task t ->
           (* do here the task *)
           ...
      | Term_request ->
           cont := false
  done;
  ()

let worker_main_fork, worker_main_join =
  Netmcore_process.def_process worker_main

The implementation of the supervisor

The supervisor starts the worker processes, and also joins them at the end.

There is a queue of messages to send to the workers, q. When a worker requests another task, the next prepared message is sent. At the end of q there are as many Term_request messages as needed to ensure that all workers will terminate.

Note that this version does not collect any results from the workers. There could be extra Task_result messages for this purpose (emitted by the workers and interpreted by the supervisor).

let supervisor_main arg =
  let ((num_workers : int), (tasks : task list)) = arg in
  let op_mbox = Mbox_supervisor.create "Supervisor" in
  let q = Queue.create() in
  List.iter (fun t -> Queue.add q (Task t)) tasks;
  let workers =
    Array.init
      num_workers
      (fun i -> Netmcore_process.start worker_main_fork i) in
  Array.iteri
    (fun i _ -> Queue.add q Term_request)
    workers;
  let wrk_mbox_names = 
    Array.mapi
      (fun i _ -> sprintf "Worker_%d" i)
      workers in
  let wrk_mboxes =
    Array.map
      (fun name -> Mbox_worker.create name)
      wrk_mbox_names in
  while not(Queue.is_empty q) do
    (* wait for request *)
    match Mbox_supervisor.receive op_mbox with
      | Task_request r ->
          let msg = Queue.take q in
          let wrk_mbox = wrk_mboxes.(r) in
          Mbox_worker.send wrk_mbox msg;
  done;
  Array.iter
    (fun pid ->
       Netmcore_process.join worker_main_join pid
    )
    workers

let supervisor_main_fork, supervisor_main_join =
  Netmcore_process.def_process supervisor_main

A main program

The main program just starts the supervisor, and waits for its termination:

let main tasks =
  let sum_opt =
    Netmcore.run
      ~socket_directory:"/tmp/netmcore"
      ~first_process:(fun () ->
                        Netmcore_process.start supervisor_main_fork tasks
                     )
      ~extract_result:(fun _ pid ->
                        Netmcore_process.join_nowait supervisor_main_join pid
                      )
      () in
  match sum_opt with
    | None -> printf "Error\n"
    | Some () -> printf "Tasks completed\n"

Where to go on from here

If you want to write an Internet server, and you need Netmulticore for managing some workload processes, you should next try to understand Netplex in more detail. Netplex is a generic process manager with special support for server processes. As pointed out before, Netmulticore is just an extension of Netplex, so both libraries can be easily used together. Read more about Netplex in: Netplex_intro, Netplex_advanced, Netplex_admin.

If your focus is on the acceleration of your multicore program, the next page to read is Netmcore_tut. This page explains the parts of Netmulticore that use shared memory. In particular, the worker processes are enabled to access shared heaps containing OCaml values. The heaps are read/write, which is so far unique in the OCaml world. This allows you to represent shared data, e.g. as queues, hashtables, or arrays. The downside of these mechanisms is that unsafe and low-level OCaml features are used, comparable to writing a wrapper for a C function.
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.Debug.html0000644000175000017500000004101012731530353022470 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netcgi_common.mime_arg-c.html0000644000175000017500000004305712731530353022060 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.mime_arg

Class Netcgi_common.mime_arg

class mime_arg : ?work_around_backslash_bug:bool -> ?name:string -> Netmime.mime_message -> rw_cgi_argument
See Netcgi.Argument.mime. We reveal more of the object than Netcgi.Argument.mime for the backward compatibility layer.

ocamlnet-4.1.2/doc/html-main/type_Netclient_tut.html0000644000175000017500000004061612731530353021160 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netclient_tut sig  endocamlnet-4.1.2/doc/html-main/Netsys_polypipe.html0000644000175000017500000005640412731530353020506 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_polypipe

Module Netsys_polypipe

module Netsys_polypipe: sig .. end
Polymorphic message pipes


These pipes are restricted to a single process, and can be used to send messages of any types between threads.
exception Closed
type 'a polypipe 
val create : int -> 'a polypipe * 'a polypipe
Create a new polypipe with an internal buffer of n messages. The left descriptor is open for reading, and the right is open for writing.
val length : 'a polypipe -> int
return the number of messages in the buffer
val eof : 'a polypipe -> bool
whether the eof marker was sent. Note that there may still be messages in the buffer
val read : nonblock:bool -> 'a polypipe -> 'a option
read a message. None means EOF. Possible Unix.unix_error codes:
  • EAGAIN: the pipe is non-blocking, and there is no message in the buffer
  • EINTR: a signal arrived
Raises Closed if the polypipe has been closed.
val write : nonblock:bool -> 'a polypipe -> 'a option -> unit
write a message, or mark the end of the stream (None). Possible Unix.unix_error codes:
  • EAGAIN: the pipe is non-blocking, and there is no message in the buffer
  • EINTR: a signal arrived
  • EPIPE: it was tried to send a message after sending None.
Unlike OS pipes, polypipes become writable after signaling EOF.

Raises Closed if the polypipe has been closed.

val close : 'a polypipe -> unit
Close the pipe. Writing will be immediately impossible. Reading will return None.
val set_read_notify : 'a polypipe -> (unit -> unit) -> unit
set_read_notify pipe f: Sets that the function f is called when the pipe becomes readable (or reaches eof). Only one such function can be registered; any previous function is overwritten. The function will be called from a different thread.
val set_write_notify : 'a polypipe -> (unit -> unit) -> unit
set_write_notify pipe f: Sets that the function f is called when the pipe becomes writable (or reaches eof). Only one such function can be registered; any previous function is overwritten. The function will be called from a different thread.
val read_descr : 'a polypipe -> Unix.file_descr
Returns a descriptor that can be used for polling. When the descriptor is readable there is a message in the buffer. If called several times, always the same descriptor is returned.

The caller has to close the descriptor after use.

Raises Closed if the polypipe has been closed.

val write_descr : 'a polypipe -> Unix.file_descr
Returns a descriptor that can be used for polling. When the descriptor is readable (sic) there is space in the buffer for another message. If called several times, always the same descriptor is returned.

The caller has to close the descriptor after use.

Raises Closed if the polypipe has been closed.

val set_exception : 'a polypipe -> exn -> unit
Sets an exception that is returned by further calls of write. If an exception already exists, it is not overwritten.

read will return EOF. Readers need to test for the exceptionw with get_exception.

val get_exception : 'a polypipe -> exn option
Get the exception

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Neturl.html0000644000175000017500000010316412731530353017606 0ustar gerdgerd Ocamlnet 4 Reference Manual : Neturl sig
  exception Malformed_URL
  val extract_url_scheme : string -> string
  type url_syntax_option =
      Url_part_not_recognized
    | Url_part_allowed
    | Url_part_required
  type url_syntax = {
    url_enable_scheme : Neturl.url_syntax_option;
    url_enable_user : Neturl.url_syntax_option;
    url_enable_user_param : Neturl.url_syntax_option;
    url_enable_password : Neturl.url_syntax_option;
    url_enable_host : Neturl.url_syntax_option;
    url_enable_port : Neturl.url_syntax_option;
    url_enable_path : Neturl.url_syntax_option;
    url_enable_param : Neturl.url_syntax_option;
    url_enable_query : Neturl.url_syntax_option;
    url_enable_fragment : Neturl.url_syntax_option;
    url_enable_other : Neturl.url_syntax_option;
    url_accepts_8bits : bool;
    url_is_valid : Neturl.url -> bool;
    url_enable_relative : bool;
  }
  and url
  val url_syntax_is_valid : Neturl.url_syntax -> bool
  val partial_url_syntax : Neturl.url_syntax -> Neturl.url_syntax
  val null_url_syntax : Neturl.url_syntax
  val ip_url_syntax : Neturl.url_syntax
  val common_url_syntax : (string, Neturl.url_syntax) Hashtbl.t
  val null_url : Neturl.url
  val make_url :
    ?encoded:bool ->
    ?scheme:string ->
    ?user:string ->
    ?user_param:string list ->
    ?password:string ->
    ?host:string ->
    ?addr:Unix.inet_addr ->
    ?port:int ->
    ?socksymbol:Netsockaddr.socksymbol ->
    ?path:string list ->
    ?param:string list ->
    ?query:string ->
    ?fragment:string -> ?other:string -> Neturl.url_syntax -> Neturl.url
  val modify_url :
    ?syntax:Neturl.url_syntax ->
    ?encoded:bool ->
    ?scheme:string ->
    ?user:string ->
    ?user_param:string list ->
    ?password:string ->
    ?host:string ->
    ?addr:Unix.inet_addr ->
    ?port:int ->
    ?socksymbol:Netsockaddr.socksymbol ->
    ?path:string list ->
    ?param:string list ->
    ?query:string ->
    ?fragment:string -> ?other:string -> Neturl.url -> Neturl.url
  val remove_from_url :
    ?scheme:bool ->
    ?user:bool ->
    ?user_param:bool ->
    ?password:bool ->
    ?host:bool ->
    ?port:bool ->
    ?path:bool ->
    ?param:bool ->
    ?query:bool -> ?fragment:bool -> ?other:bool -> Neturl.url -> Neturl.url
  val default_url :
    ?encoded:bool ->
    ?scheme:string ->
    ?user:string ->
    ?user_param:string list ->
    ?password:string ->
    ?host:string ->
    ?port:int ->
    ?path:string list ->
    ?param:string list ->
    ?query:string ->
    ?fragment:string -> ?other:string -> Neturl.url -> Neturl.url
  val undefault_url :
    ?scheme:string ->
    ?user:string ->
    ?user_param:string list ->
    ?password:string ->
    ?host:string ->
    ?port:int ->
    ?path:string list ->
    ?param:string list ->
    ?query:string ->
    ?fragment:string -> ?other:string -> Neturl.url -> Neturl.url
  val url_syntax_of_url : Neturl.url -> Neturl.url_syntax
  val url_of_string : Neturl.url_syntax -> string -> Neturl.url
  val string_of_url : Neturl.url -> string
  val parse_url :
    ?schemes:(string, Neturl.url_syntax) Hashtbl.t ->
    ?base_syntax:Neturl.url_syntax ->
    ?accept_8bits:bool -> ?enable_fragment:bool -> string -> Neturl.url
  val fixup_url_string : ?escape_hash:bool -> string -> string
  val url_provides :
    ?scheme:bool ->
    ?user:bool ->
    ?user_param:bool ->
    ?password:bool ->
    ?host:bool ->
    ?port:bool ->
    ?path:bool ->
    ?param:bool ->
    ?query:bool -> ?fragment:bool -> ?other:bool -> Neturl.url -> bool
  val url_scheme : Neturl.url -> string
  val url_user : ?encoded:bool -> Neturl.url -> string
  val url_user_param : ?encoded:bool -> Neturl.url -> string list
  val url_password : ?encoded:bool -> Neturl.url -> string
  val url_host : Neturl.url -> string
  val url_port : Neturl.url -> int
  val url_path : ?encoded:bool -> Neturl.url -> string list
  val url_param : ?encoded:bool -> Neturl.url -> string list
  val url_query : ?encoded:bool -> Neturl.url -> string
  val url_fragment : ?encoded:bool -> Neturl.url -> string
  val url_other : ?encoded:bool -> Neturl.url -> string
  val url_addr : Neturl.url -> Unix.inet_addr
  val url_socksymbol : Neturl.url -> int -> Netsockaddr.socksymbol
  val split_path : string -> string list
  val join_path : string list -> string
  val norm_path : string list -> string list
  val apply_relative_url : Neturl.url -> Neturl.url -> Neturl.url
  val ensure_absolute_url : ?base:Neturl.url -> Neturl.url -> Neturl.url
  val file_url_of_local_path :
    ?getcwd:(unit -> string) -> string -> Neturl.url
  val local_path_of_file_url : Neturl.url -> string
  val print_url : Neturl.url -> unit
  val ldap_url_syntax : Neturl.url_syntax
end
ocamlnet-4.1.2/doc/html-main/Netascii_armor.html0000644000175000017500000005015512731530353020234 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netascii_armor

Module Netascii_armor

module Netascii_armor: sig .. end
Messages with ASCII armor


There are various forms of ASCII-armored messages:

  • PEM messages (privacy enhanced mail) - a historic message format
  • OpenPGP messages. This type of message has a header, a BASE-64-encoded body, and a checksum.
  • X.509 keys. These just use BASE-64.

type armor_type = [ `Base64 | `OpenPGP | `Plain ] 
type armored_message = [ `Base64 of Netmime.mime_body
| `OpenPGP of Netmime.mime_header * Netmime.mime_body * int
| `Plain of Netmime.mime_body ]
Messages:
  • `Plain m: The body m is written as-is
  • `Base64 m: The body m needs to be BASE-64-encoded in order to create the ASCII armor
  • `OpenPGP(h,m,chksum): There is a header h, a body m which will be BASE-64-encoded, and a checksum chksum

type armored_message_ro = [ `Base64 of Netmime.mime_body_ro
| `OpenPGP of Netmime.mime_header_ro * Netmime.mime_body_ro * int
| `Plain of Netmime.mime_body_ro ]
The read-only version of armored_message
type armor_spec = (string * armor_type) list 
Which types of armor to decode, and how. The strings are the identifiers in the boundaries, e.g. include "PRIVACY-ENHANCED MESSAGE" if the boundaries are "-----BEGIN PRIVACY-ENHANCED MESSAGE-----" and "-----END PRIVACY-ENHANCED MESSAGE-----". For every type you can define the armor_type.
val parse : armor_spec ->
Netchannels.in_obj_channel ->
(string * armored_message_ro) list
Parses the channel, and returns all messages that are enabled in the specification.

The channel is read line-by-line.

ocamlnet-4.1.2/doc/html-main/type_Netchannels.pipe.html0000644000175000017500000004144712731530353021540 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.pipe ?conv:(Netbuffer.t -> bool -> Netbuffer.t -> unit) ->
?buffer_size:int -> unit -> Netchannels.io_obj_channel
ocamlnet-4.1.2/doc/html-main/type_Nettls_gnutls.Symmetric_crypto.html0000644000175000017500000004067112731530353024560 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.Symmetric_crypto Netsys_crypto_types.SYMMETRIC_CRYPTOocamlnet-4.1.2/doc/html-main/type_Netchannels.augment_raw_out_channel.html0000644000175000017500000004527012731530353025471 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.augment_raw_out_channel object
  method virtual close_out : unit -> unit
  method virtual flush : unit -> unit
  method virtual output : Bytes.t -> int -> int -> int
  method output_buffer : Buffer.t -> unit
  method output_byte : int -> unit
  method output_bytes : Bytes.t -> unit
  method output_channel : ?len:int -> in_obj_channel -> unit
  method output_char : char -> unit
  method output_string : string -> unit
  method virtual pos_out : int
  method really_output : Bytes.t -> int -> int -> unit
  method really_output_string : string -> int -> int -> unit
end
ocamlnet-4.1.2/doc/html-main/Unixqueue_select.select_based_event_system-c.html0000644000175000017500000004264412731530353026271 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_select.select_based_event_system

Class Unixqueue_select.select_based_event_system

class select_based_event_system : unit -> sb_event_system
This the old Unix.select-based imeplementation of event systems which was the default one until Ocamlnet-2.2.

Please avoid in new code. This module merely exists to allow comparisons between the old implementation and the new one.

Note that this class definition also includes some private methods. These are required in some other Unixqueue implementations inheriting from this class.


ocamlnet-4.1.2/doc/html-main/Netsmtp.html0000644000175000017500000005657012731530353016736 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsmtp

Module Netsmtp

module Netsmtp: sig .. end
This is an interface for the Simple Mail Tranfer Protocol (SMTP) as specified by RFC 2821.

exception Protocol_error
exception Authentication_error
exception Transient_error of int * string
exception Permanent_error of int * string
val tcp_port : int
default TCP port for SMTP

The class client implements the SMTP protocol. Client objects are created by
 new client in_ch out_ch
where in_ch is an input channel representing the input direction of the TCP stream, and where out_ch is an output channel representing the output direction of the TCP stream.
class client : Netchannels.in_obj_channel -> Netchannels.out_obj_channel -> object .. end
class connect : ?proxy:#Uq_engines.client_endpoint_connector -> Uq_engines.connect_address -> float -> client
connect addr timeout: Connects with the server at addr, and configure that I/O operations time out after timeout seconds of waiting.
val auth_mechanisms : string list -> string list
If applied to helo_response, returns the list of AUTH mechanisms
val authenticate : ?host:string ->
?tls_config:Netsys_crypto_types.tls_config ->
?tls_required:bool ->
?tls_peer:string ->
?sasl_mechs:Netsys_sasl.sasl_mechanism list ->
?sasl_params:(string * string * bool) list ->
?user:string ->
?authz:string -> ?creds:Netsys_sasl.credentials -> client -> unit
Authenticates the session:

  • sends the EHLO string
  • if the server supports TLS, and tls_config is set, the TLS session is started, and EHLO is repeated
  • if AUTH support is announced by the server, one of the sasl_mechs is taken and used for authentication. If sasl_mechs is empty, this authentication step is skipped.
Options:

  • host: the host name of the client
  • tls_config: if set, TLS is tried on the connection
  • tls_required: if set, it is even required that TLS is supported. If not, a Netsys_types.TLS_error exception is raised.
  • tls_peer: the host name of the server (only needed for TLS, and only needed if the TLS configuration authenticates the server, or if the SNI extension is active)
  • sasl_mechs: available SASL mechanisms (in order of preference). If you pass mechanisms, you'll normally also need to pass user and creds.
  • sasl_params: parameters for SASL. A "digest-uri" parameter is always generated, and need not to be set
  • user: the user name to authenticate as
  • authz: the identity to act as (authorization name)
  • creds: credentials
Regarding TLS: note that it is uncommon to require the server to be authenticated (opportunistic encryption), because servers often do not have certficicates from a regular trust center. You can get such a TLS config with

let tls_config =
  Netsys_tls.create_x509_config
     ~peer_auth:`None
     (Netsys_crypto.current_tls())
      

SASL example:

Netsmtp.authenticate
  ~sasl_mechs:[ (module Netmech_scram_sasl.SCRAM_SHA1);
                (module Netmech_digest_sasl.DIGEST_MD5);
              ]
  ~user:"tom"
  ~creds:[ "password", "sEcReT", [] ]
  client

val sendmail : client -> Netmime.complex_mime_message -> unit
Sends the email to the receivers in the to, cc, and bcc headers. The SMTP server must support relaying of emails. See also Netsendmail.sendmail.

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Nettls_gnutls.GNUTLS.html0000644000175000017500000004363612731530353021163 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.GNUTLS

Module Nettls_gnutls.GNUTLS

module GNUTLS: GNUTLS_PROVIDER 
The implementation of TLS backed by GnuTLS, here using Netsys_types as TLS_EXCEPTIONS module

include Netsys_crypto_types.TLS_PROVIDER
val gnutls_session : endpoint -> Nettls_gnutls_bindings.gnutls_session_t
Get the gnutls_session of the endpoint
val gnutls_credentials : credentials -> Nettls_gnutls_bindings.gnutls_credentials
Get the gnutls_credentials of the generic credentials
ocamlnet-4.1.2/doc/html-main/Netmcore_hashtbl.html0000644000175000017500000006475612731530353020572 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_hashtbl

Module Netmcore_hashtbl

module Netmcore_hashtbl: sig .. end
Shared hashtables


This is a shared memory version of Hashtbl. Note that the degree of parallelization is quite restricted - practically all operations need to be serialized (with the exception of the "ro" variants).
type ('a, 'b, 'h) t 
The type of hash tables from type 'a to type 'b and a header of type 'h
type ('a, 'b, 'h) t_descr 
The marshallable descriptor of a shared hash table
val create : Netmcore.res_id -> 'h -> ('a, 'b, 'h) t
Hashtbl.create pool h creates a new, empty hash table in pool with a header h.
val clear : ('a, 'b, 'h) t -> unit
Empty a hash table.
val add : ('a, 'b, 'h) t -> 'a -> 'b -> unit
add tbl x y adds a binding of x to y in table tbl. Previous bindings for x are not removed, but simply hidden. That is, after performing Netmcore_hashtbl.remove tbl x, the previous binding for x, if any, is restored. (Same behavior as with association lists.)
val find_ro : ('a, 'b, 'h) t -> 'a -> 'b
find_ro tbl x returns the current binding of x in tbl, or raises Not_found if no such binding exists. If it is possible that the table is being modified at the same time, this function can crash. (Suffix "_ro" = for "read-only" hashtables.)
val find_p : ('a, 'b, 'h) t -> 'a -> ('b -> 'r) -> 'r
find_p tbl x f looks up the current binding of x in tbl, and calls f with this binding as argument. During the execution of f the binding is pinned and cannot be garbage-collected. Raises Not_found if there is no such binding.
val find_c : ('a, 'b, 'h) t -> 'a -> 'b
Like find but returns a copy of the binding in normal RAM
val find_all_ro : ('a, 'b, 'h) t -> 'a -> 'b list
Hashtbl.find_all tbl x returns the list of all data associated with x in tbl. The current binding is returned first, then the previous bindings, in reverse order of introduction in the table. If it is possible that the table is being modified at the same time, this function can crash. (Suffix "_ro" = for "read-only" hashtables.)
val find_all_p : ('a, 'b, 'h) t -> 'a -> ('b list -> 'r) -> 'r
Version of find_all with pinned result
val find_all_c : ('a, 'b, 'h) t -> 'a -> 'b list
Version of find_all with copied result
val mem_ro : ('a, 'b, 'h) t -> 'a -> bool
Hashtbl.mem tbl x checks if x is bound in tbl. If it is possible that the table is being modified at the same time, this function can crash. (Suffix "_ro" = for "read-only" hashtables.)
val mem : ('a, 'b, 'h) t -> 'a -> bool
Safe version of mem_ro in the presence of parallel modifications. It is a bit slower, though.
val remove : ('a, 'b, 'h) t -> 'a -> unit
Hashtbl.remove tbl x removes the current binding of x in tbl, restoring the previous binding if it exists. It does nothing if x is not bound in tbl.
val replace : ('a, 'b, 'h) t -> 'a -> 'b -> unit
Hashtbl.replace tbl x y replaces the current binding of x in tbl by a binding of x to y. If x is unbound in tbl, a binding of x to y is added to tbl. This is functionally equivalent to Hashtbl.remove tbl x followed by Hashtbl.add tbl x y.
val iter : ('a -> 'b -> unit) -> ('a, 'b, 'h) t -> unit
Hashtbl.iter f tbl applies f to all bindings in table tbl. f receives the key as first argument, and the associated value as second argument. Each binding is presented exactly once to f. The order in which the bindings are passed to f is unspecified. However, if the table contains several bindings for the same key, they are passed to f in reverse order of introduction, that is, the most recent binding is passed first.

The table cannot be modified while iter is running. Any attempt will result in a deadlock.

val length : ('a, 'b, 'h) t -> int
Hashtbl.length tbl returns the number of bindings in tbl. Multiple bindings are counted multiply, so Hashtbl.length gives the number of times Hashtbl.iter calls its first argument.
val header : ('a, 'b, 'h) t -> 'h
Returns the header
val heap : ('a, 'b, 'h) t -> Obj.t Netmcore_heap.heap
Returns the heap backing this data structure
val descr_of_hashtbl : ('a, 'b, 'h) t -> ('a, 'b, 'h) t_descr
Returns the descriptor
val hashtbl_of_descr : Netmcore.res_id ->
('a, 'b, 'h) t_descr -> ('a, 'b, 'h) t
Look up the hash table for this descriptor
ocamlnet-4.1.2/doc/html-main/type_Netmime.mime_header_ro.html0000644000175000017500000004145412731530353022674 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.mime_header_ro object
  method field : string -> string
  method fields : (string * string) list
  method multiple_field : string -> string list
end
ocamlnet-4.1.2/doc/html-main/type_Netlog.html0000644000175000017500000006357312731530353017576 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netlog sig
  type level =
      [ `Alert | `Crit | `Debug | `Emerg | `Err | `Info | `Notice | `Warning ]
  type logger = Netlog.level -> string -> unit
  val channel_logger :
    Pervasives.out_channel -> Netlog.level -> Netlog.logger
  val current_logger : Netlog.logger Pervasives.ref
  val log : Netlog.level -> string -> unit
  val logf :
    Netlog.level -> ('a, unit, string, unit) Pervasives.format4 -> 'a
  val level_weight : Netlog.level -> int
  val level_of_string : string -> Netlog.level
  val string_of_level : Netlog.level -> string
  val level_names : string array
  type format = [ `ISO | `Std ]
  val format_timestamp : Netlog.format -> int -> float * int -> string
  val current_formatter : (float * int -> string) Pervasives.ref
  module Debug :
    sig
      type dlogger = string -> string -> unit
      val fwd_dlogger : Netlog.Debug.dlogger
      val null_dlogger : Netlog.Debug.dlogger
      val current_dlogger : Netlog.Debug.dlogger Pervasives.ref
      val log : string -> string -> unit
      val logf : string -> ('a, unit, string, unit) Pervasives.format4 -> 'a
      val enable_module : string -> unit
      val disable_module : string -> unit
      val enable_all : unit -> unit
      val disable_all : unit -> unit
      val names : unit -> string list
      val register_module : string -> bool Pervasives.ref -> unit
      val mk_dlog : string -> bool Pervasives.ref -> string -> unit
      val mk_dlogr :
        string -> bool Pervasives.ref -> (unit -> string) -> unit
      type serial
      val new_serial : unit -> Netlog.Debug.serial
      val track_fd :
        ?update:bool ->
        ?anchor:'->
        ?sn:Netlog.Debug.serial ->
        owner:string -> descr:string -> Unix.file_descr -> unit
      val release_fd :
        ?sn:Netlog.Debug.serial -> ?force:bool -> Unix.file_descr -> unit
      val fd_string : ?owner:bool -> ?descr:bool -> Unix.file_descr -> string
      val fd_table : unit -> string list
      val enable_fd_tracking : bool Pervasives.ref
    end
  val ten_power : int -> int
end
ocamlnet-4.1.2/doc/html-main/Netsys_global.html0000644000175000017500000004770712731530353020113 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_global

Module Netsys_global

module Netsys_global: sig .. end
Global variables

This module provides a place to store global variables that work across subprocess boundaries. In order to push values to related processes it needs a propagator. The propagator is not included here. The Netplex library implements a propagator that is automatically activated.

Variables are limited to string type.


type variable 
val access : string -> variable
access name: Create or look up a variable with this name
val get : variable -> string
Get the value of the variable (after checking for an update)
val set : variable -> string -> unit
Set the value of the variable
val get_v : variable -> string * int64
Get the value and the version number of the variable
val set_v : variable -> string -> int64
Set the value and get the new version number
val iter : (string -> string -> int64 -> unit) -> unit
iter f: for every variable call f name value version
class type propagator = object .. end
val get_propagator : unit -> propagator option
Get the current propagator or return None
val set_propagator : propagator option -> unit
Set the current propagator to Some p, or remove the propagator with None
ocamlnet-4.1.2/doc/html-main/Netmime.mime_body-c.html0000644000175000017500000004534212731530353021060 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.mime_body

Class type Netmime.mime_body

class type mime_body = object .. end
A MIME body with both read and write method. It is still possible, however, to set the read-only flag to make this kind of body immutable, too.

The value of the body can be set either by a string, or by writing to an object channel. Both ways are possible independently of where the value is stored, in-memory, or as external file.

Inherits
method ro : bool
whether this body is read-only or not
method set_value : string -> unit
Sets the value. If the value is immutable, the exception Immutable will be raised.

The passed string must be in decoded form. When the body is stored in an external file, the file is overwritten.

method open_value_wr : unit -> Netchannels.out_obj_channel
Opens the value for writing. The current value is overwritten. If the value is immutable, the exception Immutable will be raised.

For example, to copy the file f into the value:

 
 let ch = body # open_value_wr() in
 let f_ch = new Netchannels.input_file f in
 ch # output_channel f_ch;
 f_ch # close_in();
 ch # close_out();
 

ocamlnet-4.1.2/doc/html-main/Uq_lwt.lwt_backend-c.html0000644000175000017500000004743012731530353021246 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_lwt.lwt_backend

Class Uq_lwt.lwt_backend

class lwt_backend : Unixqueue.event_system -> object .. end
Adapter for turning an Ocamlnet event_system into an Lwt Lwt_engine.t.

Use it like:

       class lwt_engine esys =
       object
         inherit Lwt_engine.abstract
         inherit Uq_lwt.lwt_backend esys
       end
    

(We've intentionally left out this definition to avoid any build dependency on Lwt. Also note that Lwt_engine is in the package lwt.unix.)

Now, activate this Lwt engine (event loop):

      Lwt_engine.set (new lwt_engine esys)
    

Note that Lwt can only deal with one event loop at a time, and the new event loop will be used for all Lwt code.

It is, unfortunately, necessary that you use the Lwt main loop (Lwt_main.run or Lwt_unix.run), because otherwise some hook functions are never executed (and execution will hang).

For an example, see tests/equeue/manual/relay.ml in the distribution tarball.

Netplex users: If you want to use lwt_engine for driving the event loop of the container, you can do so by overriding the processor hooks container_event_system and container_run, e.g.

    method container_event_system () =
      let esys = Unixqueue.create_unix_event_system() in
      Lwt_engine.set (new lwt_engine esys);
      esys

    method container_run esys =
      Lwt_main.run <something>
    

The Lwt thread <something> must at least run until the container is shut down. You can catch this moment by also defining the shutdown method.


method iter : bool -> unit
method private cleanup : unit
method private register_readable : Unix.file_descr -> (unit -> unit) -> unit Lazy.t
method private register_writable : Unix.file_descr -> (unit -> unit) -> unit Lazy.t
method private register_timer : float -> bool -> (unit -> unit) -> unit Lazy.t
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.async_out_channel.html0000644000175000017500000004246712731530353025500 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.async_out_channel object
  method can_output : bool
  method close_out : unit -> unit
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method pos_out : int
  method request_notification : (unit -> bool) -> unit
end
ocamlnet-4.1.2/doc/html-main/Netpagebuffer.html0000644000175000017500000006776212731530353020066 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netpagebuffer

Module Netpagebuffer

module Netpagebuffer: sig .. end
Buffer for page-aligned I/O


This kind of buffer uses page-aligned bigarrays. Data can only be added to the end, or deleted at the beginning of the buffer.

The idea of this buffer is that input data is added to the last page of the buffer only (with add_inplace). If then all previous input was already a multiple of the page size, it is ensured that the new input is added at a page boundary. This kind of input operation can often be accelerated by the OS ("zero copy network I/O").

type t 
val create : int -> t
create blocksize: creates new buffer with this blocksize, which must be a whole multiple of the page size of the OS

The blocksize is normally either

These cases are optimized, and the buffer is allocated in a shared pool.
val contents : t -> string
Returns the contents as string
val to_bytes : t -> Bytes.t
Returns the contents of the buffer as fresh string.
val to_tstring_poly : t -> 's Netstring_tstring.tstring_kind -> 's
Return the buffer in the format as selected by the arg
val to_tstring : t -> 'a Netstring_tstring.tstring_kind -> Netsys_types.tstring
Returns the buffer as tagged string, selecting the chosen representation
val length : t -> int
The length
val sub : t -> int -> int -> string
Returns a substring
val sub_bytes : t -> int -> int -> Bytes.t
Same for bytes
val blit_to_bytes : t -> int -> Bytes.t -> int -> int -> unit
Blits contents to a string
val blit_to_string : t -> int -> Bytes.t -> int -> int -> unit
Deprecated."Use blit_to_bytes instead."
val blit_to_memory : t -> int -> Netsys_mem.memory -> int -> int -> unit
Blits contents to another memory buffer
val blit_to_tbuffer : t -> int -> Netsys_types.tbuffer -> int -> int -> unit
Blits contents to a tagged buffer
val blit : t -> int -> Bytes.t -> int -> int -> unit
Compatibility name for blit_to_bytes
val add_string : t -> string -> unit
Adds a string to the end of the buffer
val add_bytes : t -> Bytes.t -> unit
Same for bytes
val add_tstring : t -> Netsys_types.tstring -> unit
Same for tagged string
val add_substring : t -> string -> int -> int -> unit
Adds a sub string to the end of the buffer
val add_sub_string : t -> string -> int -> int -> unit
Deprecated."Use add_substring instead."
val add_subbytes : t -> Bytes.t -> int -> int -> unit
Adds a sub string to the end of the buffer
val add_submemory : t -> Netsys_mem.memory -> int -> int -> unit
Adds a sub memory buffer to the end of the buffer
val add_sub_memory : t -> Netsys_mem.memory -> int -> int -> unit
Deprecated."Use add_submemory instead."
val add_subtstring : t -> Netsys_types.tstring -> int -> int -> unit
Adds a sub tstring to the end of the buffer
val add_inplace : t -> (Netsys_mem.memory -> int -> int -> int) -> int
add_inplace b f: Calls f m pos len where m is the last page of the buffer, and pos is the first free byte on the page, and len is the number of free bytes on the page. The function f is expected to store new data in m from pos to pos+n-1 and to return n. The number n is also returned as final result.

It is ensured that f is called with a value of len>=1.

val page_for_additions : t -> Netsys_mem.memory * int * int
let (m,pos,len) = page_for_additions b: Returns the last page in m, the first free byte on the page in pos, and the number of free bytes on the page in len. (The same values the function f would have got as arguments in add_inplace.)
val advance : t -> int -> unit
advance b n: Marks further n bytes in the last page of the buffer as used. These bytes are not modified in any way - it is expected that the user calls page_for_additions first, and sets these n bytes to new values directly.
val page_for_consumption : t -> Netsys_mem.memory * int * int
let (m,pos,len) = page_for_consumption b: Returns the first page in m, the first used byte on the page in pos, and the number of used bytes on the page in len.
val delete_hd : t -> int -> unit
delete_hd b n: Deletes n bytes from the beginning of the buffer
val clear : t -> unit
Deletes all contents of the buffer

Searching


val index_from : t -> int -> char -> int
index_from nb k c: Searches the character c in the buffer beginning at position k. If found, the position of the left-most occurence is returned. Otherwise, Not_found is raised.
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.http_service-c.html0000644000175000017500000004700312731530353023227 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.http_service

Class type Nethttpd_types.http_service

class type ['a] http_service = object .. end

method name : string
The name of the type of the service provider
method def_term : 'a
The definition term
method print : Format.formatter -> unit
Outputs the definition term to a formatter
method process_header : extended_environment -> http_service_reaction
First stage of HTTP processing: This method is called when the HTTP header has been received. This method must return quickly without blocking the thread how to go on. For example, this could look as follows:
  • Check whether the client is allowed to access this resource. If this can be done immediately, it should be done now. (If an external service must be queried, the check must not be done now, but deferred to the second or third stage.) If the access is denied, an error response can be sent back using `Static, `File, or, if computed, using `Reject_body.
  • Check whether the request is delegated to another service provider (e.g. lookup by hostname, by port number, or by URI). In this case, the result of this process_header call is simply the result of the process_header call of the other service provider.
  • If this service provider generates the contents, there are mainly two types of reaction. If the contents are stored in a file, one can simply return `File. Otherwise, return `Accept_body to continue with the second stage. Note that even if no body is expected to arrive, one must go through the second stage, and drop any unexpected body.
The argument of this function is the Netcgi environment. The header is complete, including the request method. One cannot access the input and output channels at this stage of processing.
ocamlnet-4.1.2/doc/html-main/type_Netmech_digest_http.PROFILE.html0000644000175000017500000004117312731530353023416 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http.PROFILE sig
  val mutual : bool
  val hash_functions : Netsys_digests.iana_hash_fn list
end
ocamlnet-4.1.2/doc/html-main/Equeue_howto.html0000644000175000017500000015011412731530353017742 0ustar gerdgerd Ocamlnet 4 Reference Manual : Equeue_howto

Equeue_howto


The Equeue, Unixqueue, and Engines HOWTO

This document tries to explain briefly what you can do with the Equeue library. It is more superficial than Equeue_intro, and gives some recipes how to do things.

Contents:

What is this about?

We talk here about a form of concurrent programming, sometimes called lightweight threading or cooperative threading. As for all concurrency mechanisms, the ultimate goal is to do several things in parallel. This type, however, focuses especially on I/O, because the points where the execution threads can be switched are usually the points where a thread needs to stop for waiting on an I/O resource.

There is no preemption: When normal OCaml code is executed, there is no possibility to switch the thread. First when the control is returned to the Equeue library, a different thread can be selected for execution.

There is also no parallelism: All execution happens in the context of the process or kernel thread running the code. It is only possible to use one CPU core.

Note that LWT is another popular (and younger) implementation of the same idea for OCaml. It is possible to use LWT together with Ocamlnet, but there are restrictions. We'll explain this later in this article.

What are event systems?

You will often see the type

 Unixqueue.event_system 

in signatures of functions. An event system bundles all resources that are needed to run cooperative threads, like watched file descriptors, handlers for file events, and timers. It is the common anchor point for all activities that will happen concurrently:

  • If you define several cooperative threads for the same event_system, it is possible to run them concurrently.
  • You can have any number of event_system objects in your program. However, once you attach cooperative threads to different event systems, they cannot run together anymore.
  • Having several event systems makes nevertheless sense in a number of scenarios. For example, you could write a library function that will do a number of I/O actions concurrently, but when all I/O is finished, the function returns normally (and stops any concurrent execution). In this case you would use a local event system that exists for the lifetime of this function only.
  • A more extreme model is to use only one event system for the whole program. This, however, means that the whole program must follow a programming style that is compatible with events.
The event_system object is usually passed on from one function call to the next. There is no global event system. (NB. If you develop for Netplex, there is a pseudo-global event system for every Netplex container. But this just means that you can define your own global event system if you need it for your application.)

How to create an event system:

let esys = Unixqueue.standard_event_system()

An older name of the same is Unixqueue.create_unix_event_system.

There is also a second implementation which uses accelerated poll interfaces if provided by the operating system (e.g. epoll on Linux):

let esys = Unixqueue.performance_event_system()

This, however, is only an advantage if you have hundreds of file descriptors to observe.

How to attach actions to event systems:

The abstraction of event systems defines an API allowing one to interact with it. This is available in the Unixqueue module. Normally, however, you don't use this module directly, because it is very low-level.

So, let's look directly at high-level interfaces. For example, the Nethttp_client uses event systems internally, and one can also control this aspect of it. When creating an Nethttp_client.pipeline object, just set the event system to the one you want to use. This attaches the whole HTTP protocol interpreter implemented by this object to the event system:

let pipeline = new Nethttp_client.pipeline
let () = pipeline # set_event_system esys

Note that you can attach other pipelines and even unrelated, other I/O actions to the same event system. This just means, as mentioned above, that these actions are done concurrently.

The HTTP pipeline is initially empty, i.e. it does nothing. Before something can happen, you need to program it, i.e. add tasks to do. For example:

pipeline # add_with_callback
  (new Nethttp_client.get "http://caml.inria.fr/")
  (fun get -> ...)

The add_with_callback method adds the HTTP task to run to the internal queue. Also, there is a callback function which gets invoked when the task is done.

If you enter the shown OCaml code into a toploop, you will notice that no I/O occurs so far. Adding something to the internal task queue does not yet trigger that it is executed. This is meant as a feature of all Equeue-based concurrency: You have the chance to set the machinery up before it starts running.

This example showed how to deal with HTTP clients. What about other network protocols? The scheme is always the same: The event system object needs to be passed down to the protocol interpreter, either directly at creation time, or directly after that.

How to run event systems

The remaining question is now how to start the execution after everything is set up. This is normally done with

Unixqueue.run esys

This single statement starts whatever action was previously configured, and returns first when the action is completely finished. In our example this means it covers the whole HTTP GET protocol.

It is allowed to modify the scene while something is already happening. For example, you could download a second HTTP file when the first is done:

pipeline # add_with_callback
  (new Nethttp_client.get "http://caml.inria.fr/")
  (fun get1 -> 
    pipeline # add_with_callback
      (new Nethttp_client.get "http://www.camlcity.org/")
      (fun get2 -> ...)
  )

These "in-place" modifications of what to do are not only allowed at points like the shown where a part of the action is already complete, but at any point in time. For example, you can define a timer that starts the other action, no matter at which point of execution the running action currently is:

pipeline # add_with_callback
  (new Nethttp_client.get "http://caml.inria.fr/")
  (fun get1 -> ...);

let g = Unixqueue.new_group esys
Unixqueue.once esys g time
  (fun () ->
    pipeline # add_with_callback
      (new Nethttp_client.get "http://www.camlcity.org/")
      (fun get2 -> ...)
  )

After time seconds the second download is started. (NB. What is the purpose of g? A Unixqueue group can be used for cancelling all actions associated to the group. In this case for cancelling the timer.)

The HTTP client provides an API style where the completion of an action is indicated to the user via a callback. This style is easy to use for beginners, but it has a drawback: There is no uniform way how to compose more elementary actions to more complex actions. Such composition is possible as shown in the example, but it is always an ad-hoc solution.

Recursion is your friend

Let's have a look at such an ad-hoc composition: Assumed we have a list of URLs we want to download them with high concurrency.

Idea 1: We just add all URLs to the same pipeline, as in

let count = ref 0
List.iter
  (fun url ->
    pipeline # add_with_callback
      (new Nethttp_client.get url)
      (fun get ->
        decr count;
        if !count = 0 then ... (* do some followup action here *)
      );
    incr count
  )
  list

and then run the esys. This works, but the "intelligence" of the HTTP pipeline object is only limited. If there are several files to download from the same server, the pipeline is able to manage to use only a limited number of connections to do this, and to serialize the requests over these connections. There is, however, no built-in mechanism that would limit the number of servers to contact at once. If you had one million different servers in this list, the pipeline would try to download from all servers concurrently. Of course, this will fail (lacking system resources).

Idea 2: We only add a limited number of URLs at a time.

let count = ref 0
let count_max = 10
let list = ref list

let rec maybe_next() =
  if !count < count_max then (
    match !list with
    | [] -> ()
    | url :: list' ->
        pipeline # add_with_callback
          (new Nethttp_client.get url)
          (fun get ->
             decr count;
             maybe_next();
             if !count = 0 then ...  (* followup action *)
          );
        incr count;
        list := list';
        maybe_next()
  )

We use here recursion to encode the repetitive algorithm. This is the mechanism of choice, because we need to continue the loop from the callback function (an imperative construct could not do so).

Note that recursive calls from callback functions do not fill up the stack, so you could do this endlessly without risking a stack overflow.

Trap: do not mix synchronous and event-based APIs

Many protocol interpreters provide both styles of APIs: Conventional synchronous APIs, and event-based APIs. The question is whether one can mix them.

This is not possible, because the synchronous API is normally derived from the event-based API by setting up a one-time action in the event system and then running the event system. If you mixed the APIs, it would occur that a running event system is again tried to be run. This is forbidden, though, and will cause that an exception is thrown.

So: Use the same instance of the protocol interpreter either in a synchronous way, or in an event-based way, but do not do both.

What are engines?

As we have seen, callbacks are a common way to notify the caller about state changes. However, callbacks are too primitive to allow systematic composition of actions. The abstraction of engines has been developed to fill this gap. As a first approximation, imagine an engine as a wrapped callback interface: a machinery which is executing something concurrently until the result is available, with the possibility of notifying users of the result.

Continuing the HTTP example, there is also an engine-based version of adding a request to the pipeline:

let e = pipeline # add_e (new Nethttp_client.get url)

This is the same as add_with_callback only that the delivery mechanism is different.

It is possible to attach a callback to an engine:

Uq_engines.when_state
  ~is_done:(fun () -> ...)
  ~is_error:(fun ex -> ...)
  e

The first function is called when the HTTP request could be processed successfully, and the second one when a fatal error occurs (with ex being the exception). Using Uq_engines.when_state, every engine-style interface can be turned into a callback-style interface. Of course, this is not the primary idea of this abstraction, but this possibility means that we can go to the lower level of callbacks whenever needed.

The three most important composition operators are available in Uq_engines.Operators. It is suggested that you open this module, and use the operators directly:

  • Sequence: With
     e1 ++ (fun r1 -> e2) 
    the engine e1 is executed first, and when it has computed the result r1, the engine e2 is started. The result of ++ is again an engine, so it is possible to concatenate several expressions:
     e1 ++ (fun r1 -> e2) ++ (fun r2 -> e3) ++ ... 
    One can also set the parentheses differently if the previous results are needed later:
     e1 ++ (fun r1 -> e2 ++ (fun r2 -> e3 ++ ... )) 
    The ++ operator is also available as normal function: Uq_engines.seq_engine
  • Mapping: With
     e1 >> (fun st1 -> st2) 
    one can map the final state of e1 to a different state. The state of the engine is either the computed value, the resulting exception, or the tag that the engine was aborted:
         e1 >>
           (function
             | `Done v -> ...
             | `Error ex -> ...
             | `Aborted -> ...
           )
       
    As you can also have access to exceptions, this construction can be used to catch exceptions, and to transform them into normal values:
         e1 >>
           (function
             | `Done s          -> `Done(Some s)
             | `Error Not_found -> `Done None
             | `Error ex        -> `Error ex
             | `Aborted         -> `Aborted
           )
       
  • Values as engines: If you just want to encapsulate an already existing value v into an engine, use
     eps_e (`Done v) esys 
    or more generally
     eps_e st esys 
    to encapsulate any state. The eps_e makes an engine out of a value by pretending that the value is computed in a single step (the epsilon step).
Using this, the above example of downloading two files, one after the other, looks like:

let e =
  pipeline # add_e
    (new Nethttp_client.get "http://caml.inria.fr/")
  ++ (fun get1 -> 
        pipeline # add_e
          (new Nethttp_client.get "http://www.camlcity.org/")
        ++ (fun get2 ->
              ...;
              eps_e (`Done()) pipeline#event_system
           )
     )

Note that the final result is here just (), and it is transformed with eps_e into an engine-compatible shape.

Getting results out of an engine-based algorithm

As engines use event systems internally, the constructed complex engine (like e in the previous example) is not immediately started, but first when the event system runs (unless the event system is already running). So you still finally need

Unixqueue.run esys

to fire up the prepared engines, and to wait for the result.

You may wonder how to access the result. In the previous example, the result was just (), so there is no interest in knowing it. But you could also just return what you have got, as in

let e =
  pipeline # add_e
    (new Nethttp_client.get "http://caml.inria.fr/")
  ++ (fun get1 -> 
        pipeline # add_e
          (new Nethttp_client.get "http://www.camlcity.org/")
        ++ (fun get2 ->
              eps_e (`Done(get1, get2)) pipeline#event_system
           )
     )

and the question is how to get the pair (get1,get2) with the downloaded files after e is finished. This is in deed very simple - after Unixqueue.run returns, you can check for result values:

let st = e # state

Here, st can again have the values

  • `Done x if the engine has a final value x (here our pair)
  • `Error e if the engine execution ended in an exception e
  • `Aborted if the engine was articially stopped
but also

  • `Working n if the engine is not yet done, and n is an integer indicating the number of computation steps
The `Working state is only visible if you query the state directly with state but not in the >> operator.

Forking and joining concurrent threads built with engines

By concatenating elementary engines with ++ you basically create an execution thread. As we are talking here about concurrent programming, the question is how to fork a new thread off of an existing one, and how to join again with the created thread once it is finished.

Forking is very simple: Just have several expressions, e.g.

let e1 = <expression using ++>
let e2 = <expression using ++>

Now e1 and e2 run concurrently.

For joining, use the function Uq_engines.sync_engine:

let e_joined =
  Uq_engines.sync_engine e1 e2

The engine e_joined is first finished when both e1 and e2 are finished. The result value of e_joined is the pair of the results of e1 and e2, e.g.

e_joined ++ (fun (r1,r2) -> ...)

There is also a version of sync_engine which can join any number of engines: Uq_engines.msync_engine. We use it in the engine-based version of the download example:

let count_max = 10

let download_e list =
  let list = ref list in

  let rec download_thread_e() =
    match !list with
    | [] -> eps_e (`Done ()) esys
    | url :: list' ->
        list := list';
        pipeline # add_e (new Nethttp_client.get url)
        ++ (fun get ->
              download_thread_e()
           ) in

  let rec fork_e k =
    if k < count_max then
      let e = download_thread_e() in
      e :: fork_e (k+1)
    else
      [] in

  let e_list = fork_e 0 in

  Uq_engines.msync_engine
    e_list
    (fun _ () -> ())
    ()
    esys

The function download_thread_e downloads documents sequentially from the HTTP servers. The URLs are fetched from the variable list. In order to get concurrency, count_max of these threads are started by the fork_e recursion. The result is e_list, a list of all concurrently running engines. Finally, msync_engine is used to wait until all of these threads are finished. msync_engine works like a fold operator, and aggregates the result values via the argument function. Here, the threads only return () as results, so aggregation is pointless.

Overview of library functions for engines

In Uq_engines:

This module contains the basic definition of engines, Uq_engines.engine, plus a number of combinators for engines:

Also, the module defines basic I/O engines:

In Uq_client:

In Uq_server:

  • Define a server: Uq_server.listener creates a server socket and allows it to process the accepted connections with engines.
In Uq_io:

This module contains functions for buffered I/O:

A "device" is a file descriptor, a multiplex controller (see Uq_engines.multiplex_controller), or an asynchronous channel. The definition of devices is extensible.

In Uq_transfer:

  • Copying data: Uq_transfer.copier copies data between file descriptors without looking at the data
Other basics:

Protocol interpreters:

Definition hierarchy

We have, top-to-bottom:

  • Engines are the top-level abstraction. Essentially, they "only" provide a notification mechanism for operations over event systems, but exactly this make them the easily composable units that are most useful for constructing algorithms.
  • Event systems are simply a uniform interface for event loops, and events can be queued up in user space (Equeue).
  • Pollsets (Netsys_pollset) are event loops, i.e. it is waited for file descriptor conditions.
  • Kernel interface (select, poll, epoll etc.)

Various tricks

Aborting engines: Unlike other types of threads, cooperative threads can be aborted at any time. Use the abort method:

 e # abort() 

The engine e will then enter the `Aborted state as soon as possible. Often this will happen immediately, but there are also engines where this takes some time.

Exceptions: There are several ways to signal exceptions. First, the orderly way:

 eps_e (`Error x) esys 

This creates an engine that represents an exception as final state. Because exceptions cannot always handled that cleanly, the basic combinators like ++ always catch exceptions, and represent these exceptions in their final state. For example:

e1 ++ (fun r1 -> raise x)

The ++ operator catches the exception, and the state transitions to `Error x (just as the eps_e example would do).

Note that this behavior relates to engines only. If you program event systems directly, there will be no automatic exception handling. For example

Unixqueue.once esys g 1.0 (fun () -> raise x)

does not catch x in any way. The effect is that the exception falls through to the caller, which is always Unixqueue.run.

How to jump out of event processing: The just mentioned way of raising an exception can be used to leave event processing. Just define

 exception Esys_exit 

and throw it like

Unixqueue.once esys g 0.0 (fun () -> raise Esys_exit)

and catch it like

try
  Unixqueue.run esys
with
  | Esys_exit -> ...

This works always, even if the call of Unixqueue.once is inside an engine expression.

Engines and LWT

Users who are familiar with LWT will certainly recognize many operations - although they often have another name. (You may wonder why both implementations exist - well, a longer story, but essentially Ocamlnet has older roots, and at a certain state of the development it only knew event systems but not yet engines. The LWT developers saw this, and found this insufficient, and developed LWT. Unfortunately, they did not base their new library on Ocamlnet, but chose to reimplement the event loop core. In the meantime, the Ocamlnet development fixed the deficiencies in their library. Now we have two good libraries for the same range of problems.)

Compare:

You should, however, be aware that there are some differences between the libraries:

  • Delayed vs immediate execution: The LWT threads are immediately started, and run until they sleep. First at this point, you need to call Lwt_main.run. In contrast, Equeue prefers to first start at Unixqueue.run time.
  • LWT allows it to create Lwt threads which are already terminated (Lwt.return). In Equeue we don't do - eps_e creates an engine which will terminate as soon as possible and which results in a constant value. Effectively, this means that eps_e is seen as point where threads can be switched, whereas this is not the case for Lwt.return. This gives more opportunities for switching, but there are also more subtle consequences, like who is the caller of suspended functions. In Equeue it is always the core of the event loop, whereas this is not uniform in LWT.
  • In Equeue all engines can be aborted, whereas in LWT a special abstraction needs to be used.
  • In LWT there can be only one active event loop at a time, whereas in Equeue there can be as many event_system objects as needed. This is mainly a restriction for programs using kernel threads: In Equeue, every thread can have its own event_system, but doing the same in LWT is impossible (incompatibility with kernel threads on this level).
The remaining question is how to use both facilities in the same program (provided it is not multi-threaded, which rules LWT out). There is now the library Uq_lwt helping here.

The idea is to replace the event loop built into LWT by the Ocamlnet event loop. This is done for a given esys by

class lwt_engine esys =
object
  inherit Lwt_engine.abstract
  inherit Uq_lwt.lwt_backend esys
end

Lwt_engine.set (new lwt_engine esys)

Additionally, it is required that you now always call Lwt_main.run for starting event-based programs, and not Unixqueue.run esys. The latter would not work for technical reasons. Of course, this means that the main program will be LWT.

How to call engines from LWT threads: Assumed you are in some LWT code, and want to call an engine-based function f : 'a -> 'b engine. This can be achieved by first simply calling the function, and then using an LWT primitive to LWT-wait until the engine is done:

let call_thread f x =
  let e = f x in
  let waiter, condition = Lwt.wait() in
  Uq_engines.when_state
    ~is_done:(fun r -> Lwt.wakeup condition r)
    ~is_error:(fun x -> Lwt.wakeup_exn condition x)
    e;
  waiter

How to call LWT threads from engines: The reverse for a function f : 'a -> 'b Lwt.thread:

let call_e f x =
  let thr = f x in
  let waiter, signal = Uq_engines.signal_engine() in
  Lwt.on_success thr (fun r -> signal (`Done r));
  Lwt.on_failure thr (fun x -> signal (`Error x));
  waiter

ocamlnet-4.1.2/doc/html-main/type_Rpc_intro.html0000644000175000017500000004061212731530353020272 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_intro sig  endocamlnet-4.1.2/doc/html-main/Netaux.KMP.html0000644000175000017500000004247112731530353017171 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaux.KMP

Module Netaux.KMP

module KMP: sig .. end

type pattern 
val make_pattern : string -> pattern
val find_pattern : pattern -> ?pos:int -> ?len:int -> Bytes.t -> int
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.fmap_engine-c.html0000644000175000017500000004267712731530353023436 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.fmap_engine

Class Uq_engines_compat.fmap_engine

class [['a, 'b]] fmap_engine : 'a #engine -> ('a final_state -> 'b final_state) -> ['b] engine

ocamlnet-4.1.2/doc/html-main/Get.html0000644000175000017500000004535412731530353016021 0ustar gerdgerd Ocamlnet 4 Reference Manual : Get

Get


How to get OCamlnet

From OPAM

OCamlnet is included in the main OPAM repository. Just do:

opam install ocamlnet

Some parts of OCamlnet are only installed when optional dependencies are installed:

  • netzip: is only installed when the camlzip OPAM package is available (i.e. do opam install camlzip to get it)
  • nettls-gnutls (i.e. TLS supprt): is only installed when the conf-gnutls OPAM package is installed
  • netgss-system (i.e. GSSAPI support): is only installed when the conf-gssapi package is installed
  • equeue-gtk2 (i.e. Gtk event loop support): is only installed when the lablgtk package is installed
  • netstring-pcre (i.e. using PCRE as regexp engine): is only installed when the pcre package is installed
For instance, if you want OCamlnet with TLS support, just do:

opam install ocamlnet conf-gnutls

Most recent version

There is a separate repository with the most recent version:

camlcity repository

See the README there how to use it.

From source

See the project page for downloading the tarball. See the inluded INSTALL file for installation instructions.

GIT version

See the GIT repository.


ocamlnet-4.1.2/doc/html-main/type_Netcgi_apache.Handler.html0000644000175000017500000004262212731530353022424 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Handler sig
  type result = OK | DECLINED | DONE | HTTP of int
  type t = Netcgi_apache.Apache.Request.t -> Netcgi_apache.Handler.result
  val register : Netcgi_apache.Handler.t -> string -> unit
end
ocamlnet-4.1.2/doc/html-main/Netsys_oothr.html0000644000175000017500000005003112731530353017766 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr

Module Netsys_oothr

module Netsys_oothr: sig .. end
Object-oriented thread API


Makes the most important multi-threading primitives available using object types. For single-threaded apps, the operations are substituted by no-ops.
class type mtprovider = object .. end
class type thread = object .. end
class type mutex = object .. end
class type condition = object .. end
val provider : mtprovider Pervasives.ref
Return the multi-threading provider
val serialize : mutex -> ('a -> 'b) -> 'a -> 'b
serialize m f arg: Locks m, runs f arg, unlocks m, and returns the result.
val atomic_init : 'a option Pervasives.ref -> 'a -> 'a
atomic_init var new_value: If the variable var is None, it is set to Some new_value, and new_value is returned. If it is Some old_value, then old_value is returned. The operation is atomic.

This function works independently of the provider.

val compare_and_swap : 'a Pervasives.ref -> 'a -> 'a -> bool
compare_and_swap var old_value new_value: If the variable var is physically identical to old_value it is atomically set to new_value, and true is returned. Otherwise, var is not assigned, and false is returned.

This function works independently of the provider.

ocamlnet-4.1.2/doc/html-main/Neturl.html0000644000175000017500000016021712731530353016547 0ustar gerdgerd Ocamlnet 4 Reference Manual : Neturl

Module Neturl

module Neturl: sig .. end
Uniform Resource Locators (URLs)

Contents

The tutorial has been moved to Neturl_tut.


Interface

This module provides functions to parse URLs, to print URLs, to store URLs, to modify URLs, and to apply relative URLs.

URLs are strings formed according to pattern (1) or (2):

  1. scheme://user;userparams:password@host:port/path;params?query#fragment
  2. scheme:other;params?query#fragment
The word at the beginning of the URL identifies the URL scheme (such as "http" or "file"). Depending on the scheme, not all of the parts are allowed, or parts may be omitted. This module defines the type url_syntax whose values describe which parts are allowed/required/ not allowed for a concrete URL scheme (see below).

Not all characters are allowed in a URL. Some characters are allowed, but have the special task to separate the various parts of the URL (reserved characters). However, it is possible to include even invalid or reserved characters as normal content by applying the %-encoding on these characters: A '%' indicates that an encoded character follows, and the character is denoted by a two-digit hexadecimal number (e.g. %2f for '/'). In the following descriptions, the term "encoded string" means a string containing such %-encoded characters, and the "decoded string" means a string not containing such characters. See the module Netencoding.Url for functions encoding or decoding strings.

The type url describes values storing the components of a URL, and the url_syntax for the URL. In general, the components are stored as encoded strings; however, not for all components the %-encoding is applicable.

For convenience, the functions creating, modifying, and accessing URLs can handle both encoded and decoded strings. In order to avoid errors, the functions pass strings even in their decoded form.

Note that there is currently no function to compare URLs. The canoncical comparison ( = ) is not applicable because the same URL may be written in different ways.

Note that nothing is said about the character set/encoding of URLs. Some protocols and standards prefer UTF-8 as fundamental encoding and apply the %-encoding on top of it; i.e. the byte sequence representing a character in UTF-8 is %-encoded.

Standards Compliance

This module implements RFC 1738 and RFC 1808. There is also a newer RFC, 2396, updating the former RFCs, but this module is not fully compatible with RFC 2396. The following (minor) problems may occur:

  • The module escapes more characters than needed. All characters that are "unsafe" or "reserved" in either RFC document are escaped.
  • URL parameters (appended with a ";") are handled as in RFCs 1738/1808. In RFC 2396, every path component may have parameters, and the algorithm to resolve relative URLs is different in this point. If it is required to apply RFC 2396, one can disable URL parameters in the syntax, and extract them from the path by a self-written postprocessor. Usually, this is only required for imap URLs.
In one point, RFC 2396 is preferred:

  • Authorities may be terminated by a question mark, as in "http://host?query". This is illegal in RFC 1738. The consequence is, however, that question marks in user strings must be escaped.
RFC 3986 introduces IPv6 addresses. These are now supported (but see the comments below).
exception Malformed_URL
Raised by a number of functions when encountering a badly formed URL.
val extract_url_scheme : string -> string
Returns the URL scheme from the string representation of an URL. E.g. extract_url_scheme "http://host/path" = "http". The scheme name is always converted to lowercase characters. Raises Malformed_URL if the scheme name is not found.
type url_syntax_option = 
| Url_part_not_recognized (*
The part, even if there, is not even recognized
*)
| Url_part_allowed (*
The part can be present
*)
| Url_part_required (*
The part must be present
*)
type url_syntax = {
   url_enable_scheme : url_syntax_option;
   url_enable_user : url_syntax_option;
   url_enable_user_param : url_syntax_option;
   url_enable_password : url_syntax_option;
   url_enable_host : url_syntax_option;
   url_enable_port : url_syntax_option;
   url_enable_path : url_syntax_option;
   url_enable_param : url_syntax_option;
   url_enable_query : url_syntax_option;
   url_enable_fragment : url_syntax_option;
   url_enable_other : url_syntax_option;
   url_accepts_8bits : bool;
   url_is_valid : url -> bool;
   url_enable_relative : bool;
}
Values of type url_syntax describe which components of an URL are recognized, which are allowed (and optional), and which are required. Not all combinations are valid; the predicate expressed by the function url_syntax_is_valid must hold.

The function url_is_valid is applied when a fresh URL is created and must return true. This function allows it to add an arbitrary validity criterion to url_syntax. (Note that the URL passed to this function is not fully working; you can safely assume that the accessor functions url_scheme etc. can be applied to it.)

Switch url_accepts_8bit: If true, the bytes with code 128 to 255 are treated like alphanumeric characters; if false these bytes are illegal (but it is still possible to include such byte in their encoded form: %80 to %FF).

Switch url_enable_relative: If true, the syntax allows relative URLs in principle. Actually, parsing of relative URLs is possible when the optional parts are flagged as Url_part_allowed and not as Url_part_required. However, it is useful to specify URL syntaxes always as absolute URLs, and to weaken them on demand when a relative URL is found by the parser. This switch enables that. In particular, the function partial_url_syntax checks this flag.

type url 
Values of type url describe concrete URLs. Every URL must have a fundamental url_syntax, and it is only possible to create URLs conforming to the syntax. See make_url for further information.
val url_syntax_is_valid : url_syntax -> bool
Checks whether the passed url_syntax is valid. This means:
  • If passwords are recognized, users (and hosts) must be recognized, too
  • If ports are recognized, hosts must be recognized, too
  • If users are recognized, hosts must be recognized, too
  • Either the syntax recognizes one of the phrases { user, password, host, port, path }, or the syntax recognized the phrase 'other'.

val partial_url_syntax : url_syntax -> url_syntax
Transforms the syntax into another syntax where all required parts are changed into optional parts.
val null_url_syntax : url_syntax
An URL syntax that recognizes nothing. Use this as base for your own definitions, e.g.
 let my_syntax = { null_url_syntax with
                     url_enable_host = Url_part_required; ... }
 

val ip_url_syntax : url_syntax
Syntax for IP based protocols. This syntax allows scheme, user, password, host, port, path, param, query, fragment, but not "other". It does not accept 8 bit bytes.
val common_url_syntax : (string, url_syntax) Hashtbl.t
Syntax descriptions for common URL schemes. The key of the hashtable is the scheme name, and the value is the corresponding syntax.

  • "file": scheme, host?, path
  • "ftp": scheme, user?, password?, host, port?, path?, param? Note: param is not checked.
  • "http", "https": scheme, user?, password?, host, port?, path?, query?
  • "mailto": scheme, other, query? (RFC 2368)
  • "pop", "pops": scheme, user?, user_param?, password?, host, port? Note: user_param is not checked. (RFC 2384)
  • "imap", "imaps": scheme, user?, user_param?, password?, host, port?, path?, query? (RFC 2192) Note: "param" is intentionally not recognized to get the resolution of relative URLs as described in the RFC. When analysing this kind of URL, it is recommended to re-parse it with "param" enabled.
  • "news": scheme, other (RFC 1738)
  • "nntp", "nntps": scheme, host, port?, path (with two components) (RFC 1738)
  • "data": scheme, other (RFC 2397). "other" is not further decomposed.
  • "ipp", "ipps": scheme, host, port? , path?, query? (RFC 3510)
  • "cid", "mid": Content/message identifiers: scheme, other
  • "ldap": scheme, host?, port?, path?, query? (RFC 4516)
Notes:
  • These syntax descriptions can be weakened for partial/relative URLs by changing the required parts to optional parts: See the function partial_url_syntax.
  • None of the descriptions allows fragments. These can be enabled by setting url_enable_fragment to Url_part_allowed. E.g.
     { file_url_syntax with url_enable_fragment = Url_part_allowed } 
  • 8 bit bytes are not accepted
  • A large number of standardised scheme syntaxes are not available, e.g. gopher, prospero, wais. The selection is a bit subjective, but I have tried to omit protocols that are no longer in common use, or that are very special.
  • The LDAP URL syntax (RFC 1959) does not fit into our scheme, it is omitted for now because of this.

val null_url : url
A URL without any component and null_url_syntax
val make_url : ?encoded:bool ->
?scheme:string ->
?user:string ->
?user_param:string list ->
?password:string ->
?host:string ->
?addr:Unix.inet_addr ->
?port:int ->
?socksymbol:Netsockaddr.socksymbol ->
?path:string list ->
?param:string list ->
?query:string ->
?fragment:string -> ?other:string -> url_syntax -> url
Creates a URL from components:

  • The components scheme and host are simple strings to which the %-encoding is not applicable. host may be a (DNS) name, an IPv4 address as "dotted quad", or an IPv6 address enclosed in brackets.
  • addr also sets host, but directly from an inet_addr.
  • The component port is a simple number. Of course, the %-encoding is not applicable, too.
  • socksymbol sets both host and port from the socksymbol of type `Inet or `Inet_byname.
  • The components user, password, query, fragment, and other are strings which may contain %-encoded characters. By default, you can pass any string for these components, and problematic characters are automatically encoded. If you set encoded:true, the passed strings must already be encoded, but the function checks whether the encoding is syntactically correct. Note that for query even the characters '?' and '=' are encoded by default, so you need to set encoded:true to pass a reasonable query string.
  • The components user_param, path and param are lists of strings which may contain %-encoded characters. Again, the default is to pass decoded strings to the function, and the function encodes them automatically, and by setting encoded:true the caller is responsible for encoding the strings. Passing empty lists for these components means that they are not part of the constructed URL. See below for the respresentation of these components.
socksymbol has precedence over addr, which has precedence over host. socksymbol also has precedence over port.

The strings representing the components do not contain the characters separating the components from each other.

The created URL must conform to the url_syntax, i.e.:

  • The URL must only contain components which are recognized by the syntax
  • The URL must contain components which are required by the syntax
  • The URL must fulfill the predicate expressed by the url_is_valid function of the syntax.
The path of a URL is represented as a list of '/'-separated path components. i.e.

[ s1; s2; ...; sN ] represents the path s1 ^ "/" ^ s2 ^ "/" ^ ... ^ "/" ^ sN

As special cases:

  • [] is the non-existing path
  • [ "" ] is "/"
  • [ "";"" ] is illegal
Except of s1 and sN, the path components must not be empty strings.

To avoid ambiguities, it is illegal to create URLs with both relative paths (s1 <> "") and host components.

Parameters of URLs (param and user_param) are components beginning with ';'. The list of parameters is represented as list of strings where the strings contain the value following ';'.

val modify_url : ?syntax:url_syntax ->
?encoded:bool ->
?scheme:string ->
?user:string ->
?user_param:string list ->
?password:string ->
?host:string ->
?addr:Unix.inet_addr ->
?port:int ->
?socksymbol:Netsockaddr.socksymbol ->
?path:string list ->
?param:string list ->
?query:string ->
?fragment:string -> ?other:string -> url -> url
Modifies the passed components and returns the modified URL. The modfied URL shares unmodified components with the original URL.
val remove_from_url : ?scheme:bool ->
?user:bool ->
?user_param:bool ->
?password:bool ->
?host:bool ->
?port:bool ->
?path:bool ->
?param:bool ->
?query:bool -> ?fragment:bool -> ?other:bool -> url -> url
Removes the true components from the URL, and returns the modified URL. The modfied URL shares unmodified components with the original URL.
val default_url : ?encoded:bool ->
?scheme:string ->
?user:string ->
?user_param:string list ->
?password:string ->
?host:string ->
?port:int ->
?path:string list ->
?param:string list ->
?query:string ->
?fragment:string -> ?other:string -> url -> url
Adds missing components and returns the modified URL. The modfied URL shares unmodified components with the original URL.
val undefault_url : ?scheme:string ->
?user:string ->
?user_param:string list ->
?password:string ->
?host:string ->
?port:int ->
?path:string list ->
?param:string list ->
?query:string ->
?fragment:string -> ?other:string -> url -> url
Removes components from the URL if they have the passed value, and returns the modified URL. Note: The values must always be passed in encoded form! The modfied URL shares unmodified components with the original URL.
val url_syntax_of_url : url -> url_syntax
Returns the url_syntax record of a URL.
val url_of_string : url_syntax -> string -> url
Parses the passed string according to the passed url_syntax.
val string_of_url : url -> string
Returns the URL as string
val parse_url : ?schemes:(string, url_syntax) Hashtbl.t ->
?base_syntax:url_syntax ->
?accept_8bits:bool -> ?enable_fragment:bool -> string -> url
Parses the string and returns the URL the string represents. If the URL is absolute (i.e. begins with a scheme like "http:..."), the syntax will be looked up in schemes. If the URL is relative, the base_syntax will be taken if passed. Without base_syntax, relative URLs cannot be parsed.


schemes : This hashtable maps scheme names to syntax descriptions. The default is common_url_syntax.
base_syntax : If passed, the function can parse relative URLs according to this syntax. If not passed, the function will raise Malformed_URL on a relative URL.
accept_8bits : If false, the default, it depends on the syntax descriptions in schemes whether 8 bit characters are accepted in the input or not. If true, 8 bit characters are always accepted.
enable_fragment : If false, the default, it depends on the syntax descriptions in schemes whether fragment identifiers (e.g. "#fragment") are recognized or not. If true, fragments are always recognized.
val fixup_url_string : ?escape_hash:bool -> string -> string
Escapes some unsafe or "unwise" characters that are commonly used in URL strings: space, < > { } ^ \\ | and double quotes. Call this function before parsing the URL to support these characters.

If escape_hash is set, '#' is also escaped.

Change: Since Ocamlnet-3.4, square brackets are no longer fixed up, because they have now a legal use to denote IPv6 addresses.

val url_provides : ?scheme:bool ->
?user:bool ->
?user_param:bool ->
?password:bool ->
?host:bool ->
?port:bool ->
?path:bool ->
?param:bool ->
?query:bool -> ?fragment:bool -> ?other:bool -> url -> bool
Returns true iff the URL has all of the components passed with true value.
val url_scheme : url -> string
val url_user : ?encoded:bool -> url -> string
val url_user_param : ?encoded:bool -> url -> string list
val url_password : ?encoded:bool -> url -> string
val url_host : url -> string
val url_port : url -> int
val url_path : ?encoded:bool -> url -> string list
val url_param : ?encoded:bool -> url -> string list
val url_query : ?encoded:bool -> url -> string
val url_fragment : ?encoded:bool -> url -> string
val url_other : ?encoded:bool -> url -> string
Return components of the URL. The functions return decoded strings unless encoded:true is set. If the component does not exist, the exception Not_found is raised.

Note that IPv6 addresses, when returned by url_host, are enclosed in square brackets. Modules calling url_host may require porting to support this syntax variant.

val url_addr : url -> Unix.inet_addr
If the host part of the URL is an IP address, the address is returned. Works for IPv4 and IPv6 addresses. Otherwise Not_found is raised.
val url_socksymbol : url -> int -> Netsockaddr.socksymbol
url_socksymbol url default_port: Returns the host and port parts of the URL as socksymbol. If the port is missing in the URL, default_port is substituted. If the host is missing in the URL the exception Not_found is raised.
val split_path : string -> string list
Splits a '/'-separated path into components (e.g. to set up the path argument of make_url). E.g.
 split_path "a/b/c" = [ "a"; "b"; "c" ],
 split_path "/a/b"  = [ ""; "a"; "b" ],
 split_path "a/b/"  = [ "a"; "b"; "" ] 
Beware that split_path ".." returns [".."] while split_path "../" returns [".."; ""]. The two will behave differently, for example when used with Neturl.apply_relative_url.
val join_path : string list -> string
Concatenates the path components (reverse function of split_path).
val norm_path : string list -> string list
Removes "." and ".." from the path if possible. Deletes double slashes.

Examples

  • norm_path ["."] = []

    means: "." = ""

  • norm_path ["."; ""] = []

    means: "./" = ""

  • norm_path ["a"; "."] = ["a"; ""]

    means: "a/." = "a/"

  • norm_path ["a"; "b"; "."] = ["a"; "b"; ""]

    means: "a/b/." = "a/b/"

  • norm_path ["a"; "."; "b"; "."] = ["a"; "b"; ""]

    means: "a/./b/." = "a/b/"

  • norm_path [".."] = [".."; ""]

    means: ".." = "../"

  • norm_path [".."; ""] = [".."; ""]

    means: "../" = "../"

  • norm_path ["a"; "b"; ".."; "c" ] = ["a"; "c"]

    means: "a/b/../c" = "a/c"

  • norm_path ["a"; "b"; ".."; "c"; ""] = ["a"; "c"; ""]

    means: "a/b/../c/" = "a/c/"

  • norm_path ["";"";"a";"";"b"] = [""; "a"; "b"]

    means: "//a//b" = "/a/b"

  • norm_path ["a"; "b"; ""; ".."; "c"; ""] = ["a"; "c"; ""]

    means: "a/b//../c/" = "a/c/"

  • norm_path ["a"; ".."] = []

    means: "a/.." = ""


val apply_relative_url : url -> url -> url
apply_relative_url base rel: Interprets rel relative to base and returns the new URL. This function implements RFC 1808.

It is not necessary that rel has the same syntax as base. Note, however, that it is checked whether the resulting URL is syntactically correct with the syntax of base. If not, the exception Malformed_URL will be raised.

Examples (the URLs are represented as strings, see Neturl.split_path to split them for Neturl.make_url):

base="x/y", url="a/b" => result="x/a/b" base="x/y/", url="a/b" => result="x/y/a/b" base="x/y/..", url="a/b" => result="x/y/a/b" (beware!) base="x/y/../", url="a/b" => result="x/a/b"

val ensure_absolute_url : ?base:url -> url -> url
If the anonymous URL is absolute, it is just returned as result of this function. If the URL is relative, it is tried to make it absolute by resolving it relative to base. If there is no base or if the the base URL does not allow the parts that would be added (e.g. if the anonymous URL possesses a fragment and base does not allow that), this will fail, and the function raises Malformed_URL.
val file_url_of_local_path : ?getcwd:(unit -> string) -> string -> url
Generates a URL with "file" scheme from the passed path name. The URL is always absolute, i.e. the current directory is prepended if the path is not absolute.

Note that no character set conversions are performed.

Win32: The input path name may use forward or backward slashes. Absolute paths with drive letters and UNC paths are recognised. Relative paths with drive letters, however, are not recognised (e.g. "c:file"), as it is not possible to access the drive-specific working directory from the O'Caml runtime.

Cygwin: The input path name may use forward or backward slashes. Absolute paths with drive letters and UNC paths are recognised. The former are translated to "/cygdrive" names.


getcwd : The function returns the path taken as current working directory. Note that for Win32 this must be either an absolute name with drive letter, or an UNC path. Default: Sys.getcwd
val local_path_of_file_url : url -> string
Extracts the path from an absolute file URL, and returns a correct path name.

If the URL is not a file URL, or is not absolute, the function will fail.

Win32: The URL must either contain a drive letter, or must refer to another host.

Cygwin: Drive letters and remote URLs are recognised.

val print_url : url -> unit
Printer for the toploop.
ocamlnet-4.1.2/doc/html-main/type_Netcgi.cgi_argument.html0000644000175000017500000004417512731530353022217 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.cgi_argument object
  method charset : string
  method content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method filename : string option
  method finalize : unit -> unit
  method name : string
  method open_value_rd : unit -> Netchannels.in_obj_channel
  method representation :
    [ `MIME of Netmime.mime_message | `Simple of Netmime.mime_body ]
  method store : [ `File of string | `Memory ]
  method value : string
end
ocamlnet-4.1.2/doc/html-main/Rpc_portmapper.html0000644000175000017500000007352212731530353020275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper

Module Rpc_portmapper

module Rpc_portmapper: sig .. end
Portmapper/RPCBIND interface


RPC programs are usually registered with a daemon that is known under two names: Portmapper or RPCBIND. The name Portmapper normally refers to version 2 of the registry, whereas RPCBIND refers to versions 3 and 4. Version 2 is limited to IPv4 whereas the newer versions also support IPv6 and Unix Domain sockets.

Recent Linux and BSD distributions deploy a version of RPCBIND that is a port of Sun's original RPCBIND software. Older distributions only support Portmapper.

Most of the following calls invoke Portmapper procedures only. The calls with the suffix _rpcbind first invoked RPCBIND procedures, and if there is no support for RPCBIND, these calls fall back to Portmapper (and limited functionality).

type t 
represents a client for the Portmapper/RPCBIND daemon
val create : ?esys:Unixqueue.event_system -> Rpc_client.connector -> t
Connects to the Portmapper/RPCBIND service listening on the given connector.
val create_inet : ?esys:Unixqueue.event_system -> string -> Rpc.protocol -> t
Connects to a Portmapper/RPCBIND listening on an Internet port. The argument is the hostname where the portmapper is running or its internet address. This function connects always to the port 111 on the given host; this is the standard for portmapper daemons.
val create_local : ?esys:Unixqueue.event_system -> unit -> t
Connects to the local Portmapper/RPCBIND daemon. Such a client must only be used for setting and unsetting entries.
val shut_down : t -> unit
Shuts down the connection
val null : t -> unit
Calls the 'NULL' procedure of the portmapper. This procedure has no effect. You can use 'null' to determine whether a procedure call is possible or not.
val null'async : t -> ((unit -> unit) -> unit) -> unit
val set : t ->
Netnumber.uint4 -> Netnumber.uint4 -> Rpc.protocol -> int -> bool
set pm_client program_nr version_nr protocol port_nr: Extends the mapping managed by the Portmapper: The triple (program_nr, version_nr, protocol) is mapped to the given port_nr. It is not allowed to overwrite an existing mapping. The procedure returns true if the mapping has been extended and false otherwise. Note that it usually only possible to set a mapping on the local host.
val set'async : t ->
Netnumber.uint4 ->
Netnumber.uint4 -> Rpc.protocol -> int -> ((unit -> bool) -> unit) -> unit
val set_rpcbind : t ->
Netnumber.uint4 -> Netnumber.uint4 -> string -> string -> string -> bool
set_rpcbind pm_client program_nr version_nr netid uaddr owner:

Sets an RPCBIND mapping, and if RPCBIND is not supported, the corresponding Portmapper mapping so far possible (when netid is "tcp" or "udp").

The triple (program_nr, version_nr, netid) is mapped to (uaddr,owner). Netids can be:

  • "tcp" (only IPv4)
  • "tcp6"
  • "udp" (only IPv4)
  • "udp6"
  • "local"
For uaddr see RFC 5665 and Rpc.create_inet_uaddr, Rpc.parse_inet_uaddr.
val set_rpcbind'async : t ->
Netnumber.uint4 ->
Netnumber.uint4 ->
string -> string -> string -> ((unit -> bool) -> unit) -> unit
val unset : t ->
Netnumber.uint4 -> Netnumber.uint4 -> Rpc.protocol -> int -> bool
unset pm_client program_nr version_nr protocol port_nr: removes the mapping. The procedure returns true if the mapping has been removed and false otherwise. Note that it usually only possible to unset a mapping on the local host.
val unset'async : t ->
Netnumber.uint4 ->
Netnumber.uint4 -> Rpc.protocol -> int -> ((unit -> bool) -> unit) -> unit
val unset_rpcbind : t ->
Netnumber.uint4 -> Netnumber.uint4 -> string -> string -> string -> bool
set_rpcbind pm_client program_nr version_nr netid uaddr owner.

Unsets an RPCBIND mapping, and if RPCBIND is not supported, the corresponding Portmapper mapping so far possible (when netid is "tcp" or "udp").

Note that it is unspecified what to do with uaddr and owner. These arguments appear in the formal specification but are not described in the RFC. It is probably best to pass empty strings.

You can call this function with netid="" to remove all entries for the pair (program_nr,version_nr).

val unset_rpcbind'async : t ->
Netnumber.uint4 ->
Netnumber.uint4 ->
string -> string -> string -> ((unit -> bool) -> unit) -> unit
val getport : t -> Netnumber.uint4 -> Netnumber.uint4 -> Rpc.protocol -> int
getport pm_client program_nr version_nr protocol: finds out the port where the given service runs. Returns 0 if the service is not registered.
val getport'async : t ->
Netnumber.uint4 ->
Netnumber.uint4 -> Rpc.protocol -> ((unit -> int) -> unit) -> unit
val getaddr_rpcbind : t ->
Netnumber.uint4 -> Netnumber.uint4 -> string -> string -> string option
getaddr_rpcbind pm_client program_nr version_nr netid caller_uaddr:

Gets the uaddr for the triple (program_nr,version_nr,netid) (or "" if not found). You can pass netid="" to get the uaddr for the netid of the transport on which RPCBIND is invoked (e.g. if you call RPCBIND on TCP/IPv6 you get the uaddr for netid="tcp6").

Experimentation shows that the RPCBIND daemon on Linux does not correctly respond when netid is not the empty string. Because of this it is recommended to set netid always to the empty string.

You can pass the uaddr of the caller as caller_uaddr to get a more precise response. Normally set caller_uaddr="", though.

Falls back to Portmapper version 2 if RPCBIND isn't available. In this case you cannot retrieve IPv6 entries even if you contact Portmapper via IPv6.

val getaddr_rpcbind'async : t ->
Netnumber.uint4 ->
Netnumber.uint4 ->
string -> string -> ((unit -> string option) -> unit) -> unit
val dump : t ->
(Netnumber.uint4 * Netnumber.uint4 * Rpc.protocol * int) list
returns the list of known mappings. The quadrupels have the meaning (program_nr, version_nr, protocol, port)
val dump'async : t ->
((unit -> (Netnumber.uint4 * Netnumber.uint4 * Rpc.protocol * int) list) ->
unit) ->
unit
val port_of_program : Rpc_program.t -> string -> Rpc.protocol -> int
port_of_program program host protocol: queries the portmapper running on host for the program registered for protocol. Returns the port number or fails if the number is not known.
val sockaddr_of_program_rpcbind : Rpc_program.t -> string -> string -> Unix.sockaddr * Rpc.protocol
sockaddr_of_program program host netid: gets the sockaddr for this program.

Falls back to portmapper version 2 if rpcbind isn't available.

ocamlnet-4.1.2/doc/html-main/Nethttp_client.head_call-c.html0000644000175000017500000004220412731530353022370 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.head_call

Class Nethttp_client.head_call

class head_call : http_call

ocamlnet-4.1.2/doc/html-main/Nethttp_client.options-c.html0000644000175000017500000004223512731530353022173 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.options

Class Nethttp_client.options

class options : string -> http_call
Argument: URI or "*"

ocamlnet-4.1.2/doc/html-main/Netchannels.io_obj_channel-c.html0000644000175000017500000004307112731530353022706 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.io_obj_channel

Class type Netchannels.io_obj_channel

class type io_obj_channel = object .. end
A channel supporting both input and output. The input and output aspects are strictly separated
Inherits
ocamlnet-4.1.2/doc/html-main/Netulex.ULB.html0000644000175000017500000010457012731530353017343 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netulex.ULB

Module Netulex.ULB

module ULB: sig .. end


This module provides the unicode_lexbuf record with access functions. In this record, the data is available in two forms: As an array of Unicode code points ulb_chars, and as string of encoded chars ulb_rawbuf. Both buffers are synchronised by ulb_chars_pos. This array stores where every character of ulb_chars can be found in ulb_rawbuf.
type unicode_lexbuf = private {
   mutable ulb_encoding : Netconversion.encoding; (*
The character encoding of ulb_rawbuf
*)
   mutable ulb_encoding_start : int; (*
The first character position to which ulb_encoding applies (the encoding of earlier positions is lost)
*)
   mutable ulb_rawbuf : Bytes.t; (*
The encoded string to analyse
*)
   mutable ulb_rawbuf_len : int; (*
The filled part of ulb_rawbuf
*)
   mutable ulb_rawbuf_end : int; (*
The analysed part of ulb_rawbuf. We have always ulb_rawbuf_end <= ulb_rawbuf_len. The analysed part may be shorter than the filled part because there is not enough space in ulb_chars, or because the filled part ends with an incomplete multi-byte character
*)
   mutable ulb_rawbuf_const : bool; (*
Whether ulb_rawbuf is considered as a constant. If true, it is never blitted.
*)
   mutable ulb_chars : int array; (*
The analysed part of ulb_rawbuf as array of Unicode code points. Only the positions 0 to ulb_chars_len-1 of the array are filled.
*)
   mutable ulb_chars_pos : int array; (*
For every analysed character this array stores the byte position where the character begins in ulb_rawbuf. In addition, the array contains at ulb_chars_len the value of ulb_rawbuf_end.

This array is one element longer than ulb_chars.

*)
   mutable ulb_chars_len : int; (*
The filled part of ulb_chars
*)
   mutable ulb_eof : bool; (*
Whether EOF has been seen
*)
   mutable ulb_refill : Bytes.t -> int -> int -> int; (*
The refill function
*)
   mutable ulb_enc_change_hook : unicode_lexbuf -> unit; (*
This function is called when the encoding changes
*)
   mutable ulb_cursor : Bytes.t Netconversion.poly_cursor; (*
Internally used by the implementation
*)
}
val from_function : ?raw_size:int ->
?char_size:int ->
?enc_change_hook:(unicode_lexbuf -> unit) ->
refill:(Bytes.t -> int -> int -> int) ->
Netconversion.encoding -> unicode_lexbuf
Creates a unicode_lexbuf to analyse strings of the passed encoding coming from the refill function.


raw_size : The initial size for ulb_rawbuf. Defaults to 512
char_size : The initial size for ulb_chars. Defaults to 256
enc_change_hook : This function is called when the encoding is changed, either by this module, or by the user calling set_encoding.
refill : This function is called with arguments ulb_rawbuf, ulb_rawbuf_len, and l, where l = String.length ulb_rawbuf - ulb_rawbuf_len is the free space in the buffer. The function should fill new bytes into this substring, and return the number of added bytes. The return value 0 signals EOF.
val from_in_obj_channel : ?raw_size:int ->
?char_size:int ->
?enc_change_hook:(unicode_lexbuf -> unit) ->
Netconversion.encoding ->
Netchannels.in_obj_channel -> unicode_lexbuf
Creates a unicode_lexbuf to analyse strings of the passed encoding coming from the object channel.


raw_size : The initial size for ulb_rawbuf. Defaults to 512
char_size : The initial size for ulb_chars. Defaults to 256
enc_change_hook : This function is called when the encoding is changed, either by this module, or by the user calling set_encoding.
val from_string : ?enc_change_hook:(unicode_lexbuf -> unit) ->
Netconversion.encoding -> string -> unicode_lexbuf
Creates a unicode_lexbuf analysing the passed string encoded in the passed encoding. This function copies the input string.


enc_change_hook : This function is called when the encoding is changed, either by this module, or by the user calling set_encoding
val from_bytes : ?enc_change_hook:(unicode_lexbuf -> unit) ->
Netconversion.encoding -> Bytes.t -> unicode_lexbuf
Same for bytes
val from_bytes_inplace : ?enc_change_hook:(unicode_lexbuf -> unit) ->
Netconversion.encoding -> Bytes.t -> unicode_lexbuf
Creates a unicode_lexbuf analysing the passed string encoded in the passed encoding. This function does not copy the input string, but uses it directly as ulb_rawbuf. The string is not modified by ULB, but the caller must ensure that other program parts do not modify it either.


enc_change_hook : This function is called when the encoding is changed, either by this module, or by the user calling set_encoding

Regarding from_string_inplace, this function has been removed as strings are now considered immutable.
val delete : int -> unicode_lexbuf -> unit
Deletes the number of characters from unicode_lexbuf. These characters are removed from the beginning of the buffer, i.e. ulb_chars.(n) becomes the new first character of the buffer. All three buffers ulb_rawbuf, ulb_chars, and ulb_chars_pos are blitted as necessary.

When the buffer is already at EOF, the function fails.

For efficiency, it should be tried to call delete as seldom as possible. Its speed is linear to the number of characters to move.

val refill : unicode_lexbuf -> unit
Tries to add characters to the unicode_lexbuf by calling the ulb_refill function. When the buffer is already at EOF, the exception End_of_file is raised, and the buffer is not modified. Otherwise, the ulb_refill function is called to add new characters. If necessary, ulb_rawbuf, ulb_chars, and ulb_chars_pos are enlarged such that it is ensured that either at least one new character is added, or that EOF is found for the first time In the latter case, ulb_eof is set to true (and the next call of refill_unicode_lexbuf will raise End_of_file).
val set_encoding : Netconversion.encoding -> unicode_lexbuf -> unit
Sets the encoding to the passed value. This only affects future refill calls. The hook enc_change_hook is invoked when defined.
val close : unicode_lexbuf -> unit
Sets ulb_eof of the unicode_lexbuf. The rest of the buffer is not modified
val utf8_sub_string : int -> int -> unicode_lexbuf -> string
The two int arguments are the position and length of a sub string of the lexbuf that is returned as UTF8 string. Position and length are given as character multiples, not byte multiples.
val utf8_sub_string_length : int -> int -> unicode_lexbuf -> int
Returns String.length(utf8_sub_string args). Tries not to allocate the UTF-8 string.
ocamlnet-4.1.2/doc/html-main/type_Netgssapi_support.html0000644000175000017500000005423612731530353022073 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_support sig
  val oid_to_der : Netsys_gssapi.oid -> string
  val der_to_oid : string -> int Pervasives.ref -> Netsys_gssapi.oid
  val oid_to_der_value : Netsys_gssapi.oid -> string
  val der_value_to_oid :
    string -> int Pervasives.ref -> int -> Netsys_gssapi.oid
  val wire_encode_token : Netsys_gssapi.oid -> Netsys_gssapi.token -> string
  val wire_decode_token :
    string -> int Pervasives.ref -> Netsys_gssapi.oid * Netsys_gssapi.token
  val encode_exported_name : Netsys_gssapi.oid -> string -> string
  val decode_exported_name :
    string -> int Pervasives.ref -> Netsys_gssapi.oid * string
  val gs2_encode_saslname : string -> string
  val gs2_decode_saslname : string -> string
  val parse_kerberos_name : string -> string list * string option
  val create_mic_token :
    sent_by_acceptor:bool ->
    acceptor_subkey:bool ->
    sequence_number:int64 ->
    get_mic:(Netsys_gssapi.message -> string) ->
    message:Netsys_gssapi.message -> string
  val parse_mic_token_header : string -> bool * bool * int64
  val verify_mic_token :
    get_mic:(Netsys_gssapi.message -> string) ->
    message:Netsys_gssapi.message -> token:string -> bool
  val create_wrap_token_conf :
    sent_by_acceptor:bool ->
    acceptor_subkey:bool ->
    sequence_number:int64 ->
    get_ec:(int -> int) ->
    encrypt_and_sign:(Netsys_gssapi.message -> Netsys_gssapi.message) ->
    message:Netsys_gssapi.message -> Netsys_gssapi.message
  val parse_wrap_token_header :
    Netsys_gssapi.message -> bool * bool * bool * int64
  val unwrap_wrap_token_conf :
    decrypt_and_verify:(Netsys_gssapi.message -> Netsys_gssapi.message) ->
    token:Netsys_gssapi.message -> Netsys_gssapi.message
end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.key_ring.html0000644000175000017500000004311712731530353023130 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.key_ring ?uplink:#Nethttp_client.key_handler ->
?no_invalidation:bool ->
unit ->
object
  method add_key : Nethttp_client.key -> unit
  method clear : unit -> unit
  method inquire_key :
    domain:Neturl.url option -> realm:string -> auth:string -> key
  method invalidate_key : key -> unit
  method keys : Nethttp_client.key list
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_test.html0000644000175000017500000004217712731530353020613 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_test sig
  val run :
    ?config:Netcgi.config ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?args:Netcgi.cgi_argument list -> (Netcgi.cgi -> unit) -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi.cgi_environment.html0000644000175000017500000005372012731530353022735 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.cgi_environment object
  method cgi_auth_type : string
  method cgi_gateway_interface : string
  method cgi_https : bool
  method cgi_path_info : string
  method cgi_path_translated : string
  method cgi_properties : (string * string) list
  method cgi_property : ?default:string -> string -> string
  method cgi_query_string : string
  method cgi_remote_addr : string
  method cgi_remote_host : string
  method cgi_remote_ident : string
  method cgi_remote_user : string
  method cgi_request_method : string
  method cgi_script_name : string
  method cgi_server_name : string
  method cgi_server_port : int option
  method cgi_server_protocol : string
  method cgi_server_software : string
  method config : Netcgi.config
  method cookie : string -> Netcgi.Cookie.t
  method cookies : Netcgi.Cookie.t list
  method input_content_length : int
  method input_content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method input_content_type_string : string
  method input_header : Netmime.mime_header
  method input_header_field : ?default:string -> string -> string
  method input_header_fields : (string * string) list
  method log_error : string -> unit
  method multiple_input_header_field : string -> string list
  method multiple_output_header_field : string -> string list
  method out_channel : Netchannels.out_obj_channel
  method output_ch : Netchannels.out_obj_channel
  method output_header : Netmime.mime_header
  method output_header_field : ?default:string -> string -> string
  method output_header_fields : (string * string) list
  method protocol : Nethttp.protocol
  method send_output_header : unit -> unit
  method set_multiple_output_header_field : string -> string list -> unit
  method set_output_header_field : string -> string -> unit
  method set_output_header_fields : (string * string) list -> unit
  method set_status : Nethttp.http_status -> unit
  method user_agent : string
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.extended_environment-c.html0000644000175000017500000004401612731530353024755 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.extended_environment

Class type Nethttpd_types.extended_environment

class type extended_environment = object .. end
Same as v_extended_environment, but no virtual methods
Inherits
method server_socket_addr : Unix.sockaddr
method remote_socket_addr : Unix.sockaddr
method output_state : output_state Pervasives.ref
ocamlnet-4.1.2/doc/html-main/Shell_uq.call_engine-c.html0000644000175000017500000004444512731530353021535 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_uq.call_engine

Class Shell_uq.call_engine

class call_engine : ?ignore_error_code:bool -> ?mode:Shell_sys.group_mode -> ?stdin:Shell.producer -> ?stdout:Shell.consumer -> ?stderr:Shell.consumer -> Shell_sys.command list -> Unixqueue.event_system -> [Shell_sys.job_status] job_handler_engine_type
This engine corresponds to Shell.call. The command list is executed until the job is done. In this case, the status of the engine changes to `Done or `Error. If not ignore_error_code, failed jobs are reported by the error status `Error Subprocess_failure. If ignore_error_code, failed jobs are ignored, and result in the status `Done (however, jobs terminated by signals are still reported as errors).

For the other arguments see Shell.call.

When the engine goes to `Error or `Aborted, the job is terminated ( Shell_sys.abandon_job ).


ocamlnet-4.1.2/doc/html-main/type_Nettelnet_client.Debug.html0000644000175000017500000004101112731530353022652 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettelnet_client.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netstream.in_obj_stream.html0000644000175000017500000004475112731530353023117 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstream.in_obj_stream object
  method block_size : int
  method close_in : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method input_byte : unit -> int
  method input_char : unit -> char
  method input_line : unit -> string
  method pos_in : int
  method really_input : Bytes.t -> int -> int -> unit
  method really_input_string : int -> string
  method skip : int -> unit
  method want : int -> unit
  method want_another_block : unit -> unit
  method window : Netbuffer.t
  method window_at_eof : bool
  method window_length : int
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_modes.Add_modes.html0000644000175000017500000004126712731530353024274 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes.Add_modes functor (SC : Netsys_crypto_types.SYMMETRIC_CRYPTO->
  Netsys_crypto_types.SYMMETRIC_CRYPTO
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.FILE_TLS_ENDPOINT.html0000644000175000017500000004164612731530353025214 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.FILE_TLS_ENDPOINT sig
  module TLS : TLS_PROVIDER
  val endpoint : TLS.endpoint
  val rd_file : Unix.file_descr
  val wr_file : Unix.file_descr
end
ocamlnet-4.1.2/doc/html-main/Netmappings.html0000644000175000017500000004563312731530353017567 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmappings

Module Netmappings

module Netmappings: sig .. end
Internal access to the character conversion database

This is an internal module.


type from_uni_list = 
| U_nil
| U_single of (int * int)
| U_double of (int * int * int * int)
| U_array of int array
val get_to_unicode : string -> int array
val get_from_unicode : string -> from_uni_list array
val lock : unit -> unit
val unlock : unit -> unit
ocamlnet-4.1.2/doc/html-main/type_Rpc_client.unbound_async_call.html0000644000175000017500000004142512731530353024261 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.unbound_async_call Rpc_client.t ->
Rpc_program.t ->
string -> Netxdr.xdr_value -> [Netxdr.xdr_value] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.output_async_mplex.html0000644000175000017500000004172312731530353024571 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.output_async_mplex ?onclose:[ `Ignore | `Write_eof ] ->
?onshutdown:Uq_transfer.onshutdown_out_spec ->
?buffer_size:int ->
Uq_engines.multiplex_controller -> Uq_transfer.async_out_channel_engine
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.datagram_socket_provider.html0000644000175000017500000004162112731530353025472 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.datagram_socket_provider object
  method create_datagram_socket :
    Uq_engines.datagram_type ->
    Unixqueue.event_system ->
    Uq_engines.wrapped_datagram_socket Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.auth_session-c.html0000644000175000017500000004766412731530353023217 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.auth_session

Class type Nethttp_client.auth_session

class type auth_session = object .. end
An auth_session represents an authenticated session

method auth_scheme : string
The authentication scheme, e.g. "basic"
method auth_domain : Neturl.url list * int
The list of domain URIs defines the protection space. For requests of the same protection space the mechanism may perform re-authentication. Setting this to [] disables re-authentication.

The integer is the transport layer ID.

method auth_realm : string
The realm
method auth_user : string
The user identifier (UTF-8)
method authenticate : http_call ->
bool -> (string * string) list auth_status
Returns a list of additional headers that will authenticate the passed call for this session. (This is usually only one header, authorization.)

If a re-authentication needs to be done, the call does not contain any authentication information. If the call is authenticated in reaction to a 401 status, the response header contains the www-authenticate field(s).

The bool says whether this is the re-authentication path.

method auth_session_id : string option
An optional ID which is only needed for multi-step authentication protocols (i.e. which require more than one challenge/response step). This is ID is first retrieved after a successful authenticate. After a re-authentication the ID may change.
method invalidate : http_call -> unit
The session is notified that authentication failed. (This method is not called for failed re-authentications, but only if an authentication attempt after a 401 status failed.)
ocamlnet-4.1.2/doc/html-main/Nethtml.html0000644000175000017500000012235112731530353016706 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethtml

Module Nethtml

module Nethtml: sig .. end
Parsing of HTML

type document = 
| Element of (string * (string * string) list * document list)
| Data of string
The type document represents parsed HTML documents:

  • Element (name, args, subnodes) is an element node for an element of type name (i.e. written <name ...>...</name>) with arguments args and subnodes subnodes (the material within the element). The arguments are simply name/value pairs. Entity references (something like &xy;) occuring in the values are not resolved.

    Arguments without values (e.g. <select name="x" multiple>: here, multiple is such an argument) are represented as (name,name), i.e. the name is also returned as value.

    As argument names are case-insensitive, the names are all lowercase.

  • Data s is a character data node. Again, entity references are contained as such and not as what they mean.

Character encodings: The parser is restricted to ASCII-compatible encodings (see the function Netconversion.is_ascii_compatible for a definition). In order to read other encodings, the text must be first recoded to an ASCII-compatible encoding (example below). Names of elements and attributes must additionally be ASCII-only.


We also need a type that declares how to handle the various tags. This is called a "simplified DTD", as it is derived from SGML DTDs, but simplified to the extent used in the HTML definition.

The HTML specification (http://www.w3.org/TR/1999/REC-html401-19991224) is the reference for the HTML DTD. You can see there that most HTML elements are either an inline element, a block element, or both ("flow" element). The grammar of HTML is described in terms of these classes. For instance, a P tag (paragraph) is a block element and contains block elements whereas B (bold) is an inline element and contains inline elements. From this follows that you cannot put a P inside a B: <B><P>something</P></B> is illegal.

The parser needs this information to resolve such input, i.e. do something with bad HTML. As HTML allows tag minimization (many end tags can be omitted), the parser can read this as: <B></B><P>something</P> (and the </B> in the input is ignored).

If all start and all end tags are written out, changing the simplified_dtd does not make any difference.

There is no normative text that says how to read bad HTML. Because of this, it is - to a large degree - an interpretation of HTML what you put into simplified_dtd. We provide two versions:

  • html40_dtd: tries to be close to the official spec
  • relaxed_html40_dtd: tries to be close to what common web browsers implement

type element_class = [ `Block | `Essential_block | `Everywhere | `Inline | `None ] 
Element classes are a property used in the HTML DTD. For our purposes, we define element classes simply as an enumeration:
  • `Inline is the class of inline HTML elements
  • `Block is the class of block HTML elements
  • `Essential_block is a sub-class of `Block with the additional property that every start tag must be explicitly ended
  • `None means that the members of the class are neither block nor inline elements, but have to be handled specially
  • `Everywhere means that the members of the class can occur everywhere, regardless of whether a constraint allows it or not.

type model_constraint = [ `Any
| `Block
| `Elements of string list
| `Empty
| `Except of model_constraint * model_constraint
| `Flow
| `Inline
| `Or of model_constraint * model_constraint
| `Special
| `Sub_exclusions of string list * model_constraint ]
Model constraints define the possible sub elements of an element:
  • `Inline: The sub elements must belong to the class `Inline
  • `Block: The sub elements must be members of the classes `Block or `Essential_block
  • `Flow: The sub elements must belong to the classes `Inline, `Block, or `Essential_block
  • `Empty: There are no sub elements
  • `Any: Any sub element is allowed
  • `Special: The element has special content (e.g. <script>). Functionally equivalent to `Empty
  • `Elements l: Only these enumerated elements may occur as sub elements
  • `Or(m1,m2): One of the constraints m1 or m2 must hold
  • `Except(m1,m2): The constraint m1 must hold, and m2 must not hold
  • `Sub_exclusions(l,m): The constraint m must hold; furthermore, the elements enumerated in list l are not allowed as direct or indirect subelements, even if m or the model of a subelement would allow them. The difference to `Except(m, `Elements l) is that the exclusion is inherited to the subelements. The `Sub_exclusions expression must be toplevel, i.e. it must not occur within an `Or, `Except, or another 'Sub_exclusions expression.
Note that the members of the class `Everywhere are allowed everywhere, regardless of whether the model constraint allows them or not.

Note that certain aspects are not modeled:

  • #PCDATA: We do not specify where PCDATA is allowed and where not.
  • Order, Number: We do neither specify in which order the sub elements must occur nor how often they can occur
  • Inclusions: DTDs may describe that an element extraordinarily allows a list of elements in all sub elements.
  • Optional tags: Whether start or end tags can be omitted (to some extent, this can be expressed with `Essential_block, however)

type simplified_dtd = (string * (element_class * model_constraint)) list 
A simplified_dtd is an associative list of tuples (element_name, (element_class, constraint)): For every element_name it is declared that it is a member of element_class, and that the sub elements must satisfy constraint.

It is not allowed to have several entries for the same element.

val html40_dtd : simplified_dtd
The (transitional) HTML 4.0 DTD, expressed as simplified_dtd
val relaxed_html40_dtd : simplified_dtd
A relaxed version of the HTML 4.0 DTD that matches better common practice. In particular, this DTD additionally allows that inline elements may span blocks. For example,
 <B>text1 <P>text2 
is parsed as
 <B>text1 <P>text2</P></B> 
and not as
 <B>text1 </B><P>text2</P> 
\- the latter is more correct (and parsed by html40_dtd), but is not what users expect.

Note that this is still not what many browsers implement. For example, Netscape treats most inline tags specially: <B> switches bold on, </B> switches bold off. For example,

 <A href='a'>text1<B>text2<A href='b'>text3 
is parsed as
 <A href='a'>text1<B>text2</B></A><B><A href='b'>text3</A></B> 
\- there is an extra B element around the second anchor! (You can see what Netscape parses by loading a page into the "Composer".) IMHO it is questionable to consider inline tags as switches because this is totally outside of the HTML specification, and browsers may differ in that point.

Furthermore, several elements are turned into essential blocks: TABLE, UL, OL, and DL. David Fox reported a problem with structures like:

 <TABLE><TR><TD><TABLE><TR><TD>x</TD></TD></TR></TABLE>y</TD></TR></TABLE> 
i.e. the TD of the inner table has two end tags. Without additional help, the second </TD> would close the outer table cell. Because of this problem, tables are now essential meaning that it is not allowed to implicitly add a missing </TABLE>; every table element has to be explicitly ended. This rule seems to be what many browsers implement.
val parse_document : ?dtd:simplified_dtd ->
?return_declarations:bool ->
?return_pis:bool ->
?return_comments:bool ->
?case_sensitive:bool -> Lexing.lexbuf -> document list
Parses the HTML document from a lexbuf and returns it.


dtd : specifies the DTD to use. By default, html40_dtd is used which bases on the transitional HTML 4.0 DTD
return_declarations : if set, the parser returns <!...> declarations as Element("!",["contents",c],[]) nodes, where c is the string inside <! and >. - By default, declarations are skipped.
return_pis : if set, the parser returns <?...> (or <?...?>) processing instructions as Element("?",["contents",c],[]) nodes, where c is the string inside <? and > (or ?>). - By default, processing instructions are skipped.
return_comments : if set, the parser returns <!-- .... --> comments as Element("--",["contents",c],[]) nodes, where c is the string inside <!-- and -->. - By default, comments are skipped.
case_sensitive : if set, the case of attributes and elements is preserved, and when comparing these entities case matters. By default, the case does not matter, and attributes and elements are returned with lowercased names.
val parse : ?dtd:simplified_dtd ->
?return_declarations:bool ->
?return_pis:bool ->
?return_comments:bool ->
?case_sensitive:bool -> Netchannels.in_obj_channel -> document list
Parses the HTML document from an object channel and returns it. For example, to parse the HTML string s:
 let ch = new Netchannels.input_string s in
 let doc = parse ch
 

Arguments are the same as in parse_document.


Note on XHTML

The parser can read XHTML, as long as the following XML features are not used:

  • Internal DTD subset, i.e. <!DOCTYPE html ... [ ... ]>
  • External entities
  • <![CDATA[
  • <![INCLUDE[
  • <![IGNORE[
The following XML features are ok:
  • Processing instructions
  • Empty elements (e.g. <br/>) as long as the element is declared as `Empty.


Note on XHTML

The parser can read XHTML, as long as the following XML features are not used:

  • Internal DTD subset, i.e. <!DOCTYPE html ... [ ... ]>
  • External entities
  • <![CDATA[
  • <![INCLUDE[
  • <![IGNORE[
The following XML features are ok:
  • Processing instructions
  • Empty elements (e.g. <br/>) as long as the element is declared as `Empty.


Note on Character Encodings

The parser can only read character streams that are encoded in an ASCII- compatible way. For example, it is possible to read a UTF-8-encoded stream, but not a UTF-16-encoded stream. All bytes between 1 and 127 are taken as ASCII, and other bytes are ignored (copied from input to output).

Non-ASCII-compatible streams must be recoded first. For example, to read a UTF-16-encoded netchannel ch, use:

 let p = 
   new Netconversion.recoding_pipe ~in_enc:`Enc_utf16 ~out_enc:`Enc_utf8 () in
 let ch' =
   new Netchannels.input_filter ch p in
 let doc =
   Nethtml.parse ch' in
 ch' # close_in();
 ch # close_in();
 

val decode : ?enc:Netconversion.encoding ->
?subst:(int -> string) ->
?entity_base:[ `Empty | `Html | `Xml ] ->
?lookup:(string -> string) ->
?dtd:simplified_dtd -> document list -> document list
Converts entities &name; and &#num; into the corresponding characters. The argument enc must indicate the character set of the document (by default ISO-8859-1 for backwards compatibility). If a character cannot be represented in this encoding, the function subst is called (input is the Unicode code point, output is the substituted string). By default, the function fails if such a character is found.

The arg entity_base selects which entities can be converted (see Netencoding.Html.decode). The function lookup is called for all unknown &name; entities. By default, this function fails.

Declarations, processing instructions, and comments are not decoded. The same also applies to elements declared as `Special in the DTD. The dtd argument determines the DTD, by default html40_dtd is assumed.

val encode : ?enc:Netconversion.encoding ->
?prefer_name:bool ->
?dtd:simplified_dtd -> document list -> document list
Converts problematic characters to their corresponding entities. The argument enc must indicate the character set of the document (by default ISO-8859-1 for backwards compatibility). If prefer_name, the algorithm tries to find the named entities (&name;); otherwise only numeric entities (&#num;) are generated. Names are preferred by default.

Declarations, processing instructions, and comments are not encoded. The same also applies to elements declared as `Special in the DTD. The dtd argument determines the DTD, by default html40_dtd is assumed.

val map_list : (string -> string) -> document list -> document list
map_list f doclst: Applies f to all attribute values and data strings (except the attributes of "?", "!", or "--" nodes).

This can be used to change the text encoding of a parsed document:

 let doc' = map_list String.lowercase doc
 
converts all text data to lowercase characters.
type xmap_value = 
| Xmap_attribute of string * string * string
| Xmap_data of string option * string
val xmap_list : (xmap_value -> string) ->
string option -> document list -> document list
xmap_list f surrounding_element_opt doclst: Similar to map_list, the function f is applied to all attribute values and data strings. Unlike map_list, more information is passed to the callback function f. This function is called with an xmap_value argument:
  • Xmap_attribute(ename,aname,aval): The function is called for an attribute value of element ename. The attribute is aname and has the value aval. The function must return the new value of the attribute (i.e. aval').
  • Xmap_data(ename_opt,data): The function is called for a data node surrounded by an element ename_opt (which is None if the data node is the outermost node). The string data is the value of the data node. The function must return the new value of the data node (i.e. data').
xmap_list is invoked with surrounding_element_opt which is the name of the surrounding element, or None if such an element does not exist, or is unknown.
val write : ?dtd:simplified_dtd ->
?xhtml:bool -> Netchannels.out_obj_channel -> document list -> unit
Writes the document to the output channel. No additional encoding or decoding happens.

Empty elements are written without end tag (see also optional argument xhtml); the rest is written unabbreviated.

Example: To write the document to a file:

 let f = open_out "filename" in
 let ch = new Netchannels.output_channel f in
 write ch doc;
 ch # close_out()
 


dtd : The assumed simplified DTD, by default html40_dtd
xhtml : makes the output compatible with XHTML 1.0 Strict by closing `Empty tags with "/>" (true by default).
ocamlnet-4.1.2/doc/html-main/type_Uq_libevent.html0000644000175000017500000005122712731530353020614 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_libevent sig
  module type LIBOEVENT =
    sig
      type event
      type event_flags = TIMEOUT | READ | WRITE | SIGNAL
      type event_callback =
          Unix.file_descr -> Uq_libevent.LIBOEVENT.event_flags -> unit
      val create : unit -> Uq_libevent.LIBOEVENT.event
      val set :
        Uq_libevent.LIBOEVENT.event ->
        Unix.file_descr ->
        Uq_libevent.LIBOEVENT.event_flags list ->
        persist:bool -> Uq_libevent.LIBOEVENT.event_callback -> unit
      val add : Uq_libevent.LIBOEVENT.event -> float option -> unit
      val del : Uq_libevent.LIBOEVENT.event -> unit
      type loop_flags = ONCE | NONBLOCK
      val loop : Uq_libevent.LIBOEVENT.loop_flags -> unit
    end
  module type POLLSET =
    sig
      val create_pollset : unit -> Netsys_pollset.pollset
      val create_event_system : unit -> Unixqueue.event_system
    end
  module Make : functor (L : LIBOEVENT-> POLLSET
end
ocamlnet-4.1.2/doc/html-main/type_Netstream.input_stream.html0000644000175000017500000004115212731530353023006 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstream.input_stream ?len:int ->
?block_size:int -> Netchannels.in_obj_channel -> Netstream.in_obj_stream
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.TLS_ENDPOINT.html0000644000175000017500000004307112731530353023346 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_ENDPOINT

Module type Netsys_crypto_types.TLS_ENDPOINT

module type TLS_ENDPOINT = sig .. end

module TLS: Netsys_crypto_types.TLS_PROVIDER 
val endpoint : TLS.endpoint
ocamlnet-4.1.2/doc/html-main/Netplex_types.socket_controller-c.html0000644000175000017500000004563612731530353024122 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.socket_controller

Class type Netplex_types.socket_controller

class type socket_controller = object .. end

method state : socket_state
The current state
method enable : unit -> unit
Enables a disabled socket service again
method disable : unit -> unit
Disable a socket service temporarily
method restart : unit -> unit
Restarts the containers for this socket service only
method shutdown : unit -> unit
Closes the socket service forever, and initiates a shutdown of all containers serving this type of service.
method container_state : (container_id * string * container_state * bool)
list
method start_containers : int -> int
method stop_containers : container_id list -> unit
ocamlnet-4.1.2/doc/html-main/Netplex_controller.html0000644000175000017500000004751212731530353021162 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_controller

Module Netplex_controller

module Netplex_controller: sig .. end
Controller


The controller is the main part of the Netplex system that starts and stop the individual service containers.
val create_controller : Netplex_types.parallelizer ->
Netplex_types.controller_config -> Netplex_types.controller
Create a controller with the default event system
val create_controller_for_esys : Unixqueue.event_system ->
Netplex_types.parallelizer ->
Netplex_types.controller_config -> Netplex_types.controller
Create a controller for the passed event system
val extract_config : Netplex_types.logger_factory list ->
Netplex_types.config_file -> Netplex_types.controller_config
Extracts the controller config

Configuring the controller

There is a controller section that may configure the controller:

 netplex {
         ...
         controller {
           socket_directory = "/var/run/myapp_sockets";
           max_level = "debug";
           logging { ... };
         }
         ...
       }
    

The socket_directory overrides the location where the special directory with Unix Domain sockets and other runtime files is created.

The max_level parameter defines the global maximum log level. It defaults to "info". By setting it to "debug" (as shown) debug logging is enabled. This parameter can be modified at runtime.

The logging section is explained in Netplex_log.

module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netplex_kit.empty_processor_hooks-c.html0000644000175000017500000004227312731530353024444 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.empty_processor_hooks

Class Netplex_kit.empty_processor_hooks

class empty_processor_hooks : unit -> Netplex_types.processor_hooks
This is an empty set of processor hooks, i.e. all methods are empty

ocamlnet-4.1.2/doc/html-main/type_Unixqueue.event_system.html0000644000175000017500000005017512731530353023054 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.event_system object
  method add_abort_action :
    Unixqueue.group -> (Unixqueue.group -> exn -> unit) -> unit
  method add_close_action :
    Unixqueue.group -> Unix.file_descr * (Unix.file_descr -> unit) -> unit
  method add_event : Unixqueue.event -> unit
  method add_handler :
    Unixqueue.group ->
    (Unixqueue.event_system ->
     Unixqueue.event Equeue.t -> Unixqueue.event -> unit) ->
    unit
  method add_resource :
    Unixqueue.group -> Unixqueue.operation * float -> unit
  method add_weak_resource :
    Unixqueue.group -> Unixqueue.operation * float -> unit
  method clear : Unixqueue.group -> unit
  method exists_resource : Unixqueue.operation -> bool
  method is_running : bool
  method new_group : unit -> Unixqueue.group
  method new_wait_id : unit -> Unixqueue.wait_id
  method remove_resource : Unixqueue.group -> Unixqueue.operation -> unit
  method run : unit -> unit
  method when_blocking : (unit -> unit) -> unit
end
ocamlnet-4.1.2/doc/html-main/Netmime.wrap_mime_body_ro-c.html0000644000175000017500000004225212731530353022606 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.wrap_mime_body_ro

Class Netmime.wrap_mime_body_ro

class wrap_mime_body_ro : #mime_body_ro -> mime_body
Wraps the inner body but disallows modifications. In this case, Immutable is raised.

ocamlnet-4.1.2/doc/html-main/Uq_transfer.copier-c.html0000644000175000017500000004357212731530353021273 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.copier

Class Uq_transfer.copier

class copier : copy_task -> Unixqueue.event_system -> [unit] Uq_engines.engine
This engine copies data between file descriptors as specified by the copy_task argument.

The task is done when all input descriptors are at EOF. See the description of copy_task for details, especially whether the descriptors are closed or not.

On error or abort, the descriptors are only closed if they had been closed on regular EOF.

The semantics of the engine is undefined if one of the descriptors is not stream-oriented.

TODO: This class cannot yet cope with Win32 named piped.


ocamlnet-4.1.2/doc/html-main/Rpc_auth_sys.html0000644000175000017500000005224212731530353017737 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_auth_sys

Module Rpc_auth_sys

module Rpc_auth_sys: sig .. end
Authentication module AUTH_SYS


This module implements system authentication (AUTH_SYS, also known as AUTH_UNIX).

*********************************************************************** WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!

This authentication method is insecure because it does not use any verifier. I strongly dissuade everybody from using this authentication method for newly written RPC systems. I include it here only for compatibility with older systems.

WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! ***********************************************************************

type identity = [ `Effective_user | `Real_user | `This_user of int * int * int array * string ] 
Specifies the user:
  • `Effective_user: Take the effective user of the process
  • `Real_user: Take the real user of the process
  • `This_user(uid,gid,sup_groups,hostname): Pretend to be this user

val client_auth_method : ?identity:identity -> unit -> Rpc_client.auth_method
Pass the result of this function to Rpc_client.set_auth_methods to configure client authentication.

identity: As whom the clients authenticates.

type user_name_format = [ `Custom of int32 -> int32 -> int32 array -> string -> string | `Full | `UID ] 
How Rpc_server.get_user returns the user as string:
  • `Full: The format includes all transmitted details: "<uid>.<gid>.<gid1>.<gid2>...@<hostname>". All user and group IDs are numeric. The first two numbers, <uid> and <gid> are always present. The other numbers are the supplementary group IDs and can be omitted. The <hostname> is the name passed in the credentials.
  • `UID: The string is the numeric user ID
  • `Custom f: The string is returned by the function f. The arguments are uid, gid, the array of the supplementary group IDs and the hostname.

val server_auth_method : ?lookup_hostname:bool ->
?require_privileged_port:bool ->
?user_name_as:user_name_format -> unit -> Rpc_server.auth_method
Pass the result of this function to Rpc_server.set_auth_methods to configure authentication.

lookup_hostname: if true, the hostname contained in the credentials is checked (by gethostbyname)

require_privileged_port: if true, the client must use a privileged port. Note that Unix domain sockets are rejected in this mode.

User name strings as formatted as specified by user_name_as. This defaults to `Full.

val parse_user_name : string -> int * int * int array * string
Parses a user name as returned by Rpc_server.get_user in conjunction with the AUTH_SYS authentication and `Full formatting. Returns (uid,gid,sup_groups,hostname).1
ocamlnet-4.1.2/doc/html-main/type_Netplex_log.syslog_config.html0000644000175000017500000004202512731530353023457 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_log.syslog_config object
  method log_component : string
  method log_facility : Netsys_posix.syslog_facility
  method log_format : string
  method log_identifier : string
  method log_max_level : Netplex_types.level
  method log_subchannel : string
end
ocamlnet-4.1.2/doc/html-main/Rpc_proxy.ReliabilityCache.html0000644000175000017500000007132412731530353022457 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_proxy.ReliabilityCache

Module Rpc_proxy.ReliabilityCache

module ReliabilityCache: sig .. end


The reliability cache stores information about the availability of remote servers. The managed clients put information about recent failures into the cache.

It is advantegeous to have only one cache per process, because this maximizes the usefulness. The cache is thread-safe.

A server endpoint is disabled when too many errors occur in sequence. For a disabled endpoint the functions host_is_enabled and/or sockaddr_is_enabled return false. The endpoint is automatically enabled again after some timeout; this is initially disable_timeout_min, but is increased exponentially until disable_timeout_max when further errors occur.

Independently of this machinery the functions host_is_enabled and sockaddr_is_enabled may also return false when an external availability checker says that the endpoint is down. This information is not entered into the cache, and will also not trigger the disable timeout. Instead, the hook function getting the availability will be simply called again.

type rcache 
The cache
type rcache_policy = [ `Any_failing_port_disables_host
| `Failing_port_disables_host of int
| `Independent
| `None ]
How failures of individual ports are interpreted:
  • `Independent: When a connection to a remote port repeatedly fails, only this port is disabled
  • `Failing_port_disables_host p: When a connection to the TCP port p repeatedly fails, the whole remote host is disabled. Other ports do not disable the host, but are treated as in `Independent.
  • `Any_failing_port_disables_host: When a connection to any TCP port repeatedly fails, the whole remote host is disabled
  • `None: Nothing is disabled
Note that the rcache_availability hook is not affected by the policy; this hook is called anyway. The policy only determines how the internal error counter is interpreted.
type rcache_config = {
   rcache_policy : rcache_policy; (*
The policy, see above
*)
   rcache_disable_timeout_min : float; (*
For how long ports and hosts are disabled
*)
   rcache_disable_timeout_max : float; (*
For how long ports and hosts are disabled at most
*)
   rcache_threshold : int; (*
How many errors are required for disabling a port
*)
   rcache_availability : rcache -> Unix.sockaddr -> bool; (*
External availability checker. Called by sockaddr_is_enabled before the result is calculated
*)
}
val create_rcache_config : ?policy:rcache_policy ->
?disable_timeout_min:float ->
?disable_timeout_max:float ->
?threshold:int ->
?availability:(rcache -> Unix.sockaddr -> bool) ->
unit -> rcache_config
Create a config record. The optional arguments set the config components with the same name. The arguments default to:
  • policy = `None
  • disable_timeout_min = 1.0
  • disable_timeout_max = 64.0
  • threshold = 1
  • availability = fun _ _ -> true

val create_rcache : rcache_config -> rcache
Creates a new cache object. The same cache can be used by several managed clients, even by totally unrelated ones
val rcache_config : rcache -> rcache_config
Return the config
val global_rcache_config : unit -> rcache_config
Returns the global config:
  • policy = `None
  • disable_timeout_min = 1.0
  • disable_timeout_max = 64.0
  • threshold = 1
  • availability = fun _ _ -> true

val set_global_rcache_config : rcache_config -> unit
Sets the new global config. This is only possible as long as neither default_global_config nor global_rcache have been called.
val global_rcache : unit -> rcache
The global cache. Initially, this cache has the default config. It is possible to change the default config before using the global cache for the first time.
val derive_rcache : rcache ->
rcache_config -> rcache
derive_cache parent config: Returns a new cache that shares the error counters with parent. The interpretation of the counters, however, may be differently configured in config.

Because it is advantageous to share the error information as much as possible, the recommended way to create a new cache object is to derive it from the global cache.

What derive_rcache actually does (and this is not yet optimal): Any incr and reset of an error counter is also forwarded to the parent cache. The tests whether hosts and ports are enabled do an AND of the results for the cache and its parent (i.e. both must be ok to enable). This allows some information sharing, but only in vertical direction.

val incr_rcache_error_counter : rcache -> Unix.sockaddr -> unit
Increase the error counter for this sockaddr. If the threshold is reached and there is a disable policy, the sockaddr will be disabled.

This function is to be called after an RPC call times out, or runs into a socket error.

val reset_rcache_error_counter : rcache -> Unix.sockaddr -> unit
Reset the error counter for this sockaddr. If disabled, the sockaddr is set to enabled again.

This function is to be called when an RPC call is successful.

val sockaddr_is_enabled : rcache -> Unix.sockaddr -> bool
Returns whether the sockaddr is enabled. This also calls the rcache_availability hook.
val host_is_enabled : rcache -> Unix.inet_addr -> bool
Returns whether the host is enabled
ocamlnet-4.1.2/doc/html-main/type_Netchannels.output_descr.html0000644000175000017500000004133112731530353023313 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_descr ?blocking:bool ->
?start_pos_out:int ->
?fd_style:Netsys.fd_style -> Unix.file_descr -> Netchannels.raw_out_channel
ocamlnet-4.1.2/doc/html-main/type_Netsys_tls.Debug.html0000644000175000017500000004100312731530353021522 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_tls.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Netx509.x509_certificate_from_ASN1.html0000644000175000017500000004102712731530353024363 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.x509_certificate_from_ASN1 Netasn1.Value.value -> Netx509.x509_certificateocamlnet-4.1.2/doc/html-main/Uq_libevent.LIBOEVENT.html0000644000175000017500000004773112731530353021106 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_libevent.LIBOEVENT

Module type Uq_libevent.LIBOEVENT

module type LIBOEVENT = sig .. end

type event 
type event_flags = 
| TIMEOUT
| READ
| WRITE
| SIGNAL
type event_callback = Unix.file_descr -> event_flags -> unit 
val create : unit -> event
val set : event ->
Unix.file_descr ->
event_flags list ->
persist:bool -> event_callback -> unit
val add : event -> float option -> unit
val del : event -> unit
type loop_flags = 
| ONCE
| NONBLOCK
val loop : loop_flags -> unit
ocamlnet-4.1.2/doc/html-main/type_Uq_tcl.html0000644000175000017500000004174512731530353017572 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_tcl sig
  type runner = Unixqueue.event_system -> (unit -> unit) -> unit
  class tcl_event_system :
    ?run:Uq_tcl.runner -> unit -> Unixqueue.event_system
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_intro.html0000644000175000017500000004061712731530353021345 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_intro sig  endocamlnet-4.1.2/doc/html-main/type_Netmappings.html0000644000175000017500000004326112731530353020623 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmappings sig
  type from_uni_list =
      U_nil
    | U_single of (int * int)
    | U_double of (int * int * int * int)
    | U_array of int array
  val get_to_unicode : string -> int array
  val get_from_unicode : string -> Netmappings.from_uni_list array
  val lock : unit -> unit
  val unlock : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netencoding.Base64.html0000644000175000017500000005235512731530353021622 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Base64 sig
  val encode :
    ?pos:int ->
    ?len:int ->
    ?linelength:int ->
    ?crlf:bool -> ?plus:char -> ?slash:char -> string -> string
  val encode_tstring :
    ?pos:int ->
    ?len:int ->
    ?linelength:int ->
    ?crlf:bool ->
    ?plus:char -> ?slash:char -> Netsys_types.tstring -> Bytes.t
  val encode_poly :
    ?pos:int ->
    ?len:int ->
    ?linelength:int ->
    ?crlf:bool ->
    ?plus:char ->
    ?slash:char -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
  val decode :
    ?pos:int ->
    ?len:int ->
    ?accept_spaces:bool -> ?plus:char -> ?slash:char -> string -> string
  val decode_tstring :
    ?pos:int ->
    ?len:int ->
    ?accept_spaces:bool ->
    ?plus:char -> ?slash:char -> Netsys_types.tstring -> Bytes.t
  val decode_poly :
    ?pos:int ->
    ?len:int ->
    ?accept_spaces:bool ->
    ?plus:char ->
    ?slash:char -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
  class encoding_pipe :
    ?linelength:int ->
    ?crlf:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipe
  class decoding_pipe :
    ?accept_spaces:bool ->
    ?plus:char -> ?slash:char -> unit -> Netchannels.pipe
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.internal_environment.html0000644000175000017500000005761412731530353026115 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.internal_environment object
  method cgi_auth_type : string
  method cgi_gateway_interface : string
  method cgi_https : bool
  method cgi_path_info : string
  method cgi_path_translated : string
  method cgi_properties : (string * string) list
  method cgi_property : ?default:string -> string -> string
  method cgi_query_string : string
  method cgi_remote_addr : string
  method cgi_remote_host : string
  method cgi_remote_ident : string
  method cgi_remote_user : string
  method cgi_request_method : string
  method cgi_request_uri : string
  method cgi_script_name : string
  method cgi_server_name : string
  method cgi_server_port : int option
  method cgi_server_protocol : string
  method cgi_server_software : string
  method config : Netcgi.config
  method cookie : string -> Netcgi.Cookie.t
  method cookies : Netcgi.Cookie.t list
  method input_body_size : int64
  method input_channel : Netchannels.in_obj_channel
  method input_content_length : int
  method input_content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method input_content_type_string : string
  method input_header : Netmime.mime_header
  method input_header_field : ?default:string -> string -> string
  method input_header_fields : (string * string) list
  method log_access : unit -> unit
  method log_error : string -> unit
  method log_props : (string * string) list -> unit
  method multiple_input_header_field : string -> string list
  method multiple_output_header_field : string -> string list
  method out_channel : Netchannels.out_obj_channel
  method output_ch : Netchannels.out_obj_channel
  method output_header : Netmime.mime_header
  method output_header_field : ?default:string -> string -> string
  method output_header_fields : (string * string) list
  method output_state : Nethttpd_types.output_state ref
  method protocol : Nethttp.protocol
  method remote_socket_addr : Unix.sockaddr
  method req_method : Nethttp.http_method
  method request_body_rejected : bool
  method response : Nethttpd_kernel.http_response
  method send_file : Unix.file_descr -> int64 -> unit
  method send_output_header : unit -> unit
  method server_socket_addr : Unix.sockaddr
  method set_multiple_output_header_field : string -> string list -> unit
  method set_output_header_field : string -> string -> unit
  method set_output_header_fields : (string * string) list -> unit
  method set_status : Nethttp.http_status -> unit
  method tls_session_props : Nettls_support.tls_session_props option
  method unlock : unit -> unit
  method user_agent : string
end
ocamlnet-4.1.2/doc/html-main/Shell_sys.Debug.html0000644000175000017500000004174712731530353020276 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_sys.Debug

Module Shell_sys.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module
ocamlnet-4.1.2/doc/html-main/Netmcore.compute_resource-c.html0000644000175000017500000004351512731530353022655 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore.compute_resource

Class type Netmcore.compute_resource

class type compute_resource = object .. end

method id : res_id
an ID of the resource that is valid in the whole Netplex system
method typ : compute_resource_type
which type of resource
method repr : compute_resource_repr
the resource detail
method release : unit -> unit
Notify the manager that the resource is not used any longer by this process. If all processes release the resource it will be finally destroyed.
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.Operators.html0000644000175000017500000004412012731530353022705 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.Operators

Module Uq_engines_compat.Operators

module Operators: sig .. end

val (++) : 'a #Uq_engines_compat.engine ->
('a -> 'b #Uq_engines_compat.engine) -> 'b Uq_engines_compat.engine
val (>>) : 'a #Uq_engines_compat.engine ->
('a Uq_engines_compat.final_state -> 'b Uq_engines_compat.final_state) ->
'b Uq_engines_compat.engine
val eps_e : 't Uq_engines_compat.engine_state ->
Unixqueue.event_system -> 't Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/type_Netdate.html0000644000175000017500000006033712731530353017725 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdate sig
  type t = {
    year : int;
    month : int;
    day : int;
    hour : int;
    minute : int;
    second : int;
    nanos : int;
    zone : int;
    week_day : int;
  }
  val localzone : int
  val localzone_nodst : int
  val get_localzone : unit -> int
  val create :
    ?localzone:bool -> ?zone:int -> ?nanos:int -> float -> Netdate.t
  type localization = {
    full_day_names : string array;
    abbr_day_names : string array;
    parsed_day_names : string list array;
    full_month_names : string array;
    abbr_month_names : string array;
    parsed_month_names : string list array;
    timezone_names : (string * int * bool) list;
    am_particle : string;
    pm_particle : string;
    d_format : string;
    t_format : string;
    d_t_format : string;
    t_format_ampm : string;
    char_encoding : string;
  }
  type compiled_localization
  val posix_l9n : Netdate.localization
  val l9n_from_locale : string -> Netdate.localization
  val compile_l9n : Netdate.localization -> Netdate.compiled_localization
  val parse :
    ?localzone:bool ->
    ?zone:int -> ?l9n:Netdate.compiled_localization -> string -> Netdate.t
  val since_epoch : Netdate.t -> float
  val since_epoch_timespec : Netdate.t -> float * int
  val since_epoch_approx : Netdate.t -> float
  val week_day : Netdate.t -> int
  val year_day : Netdate.t -> int
  val iso8601_week_pair : Netdate.t -> int * int
  val parse_epoch :
    ?l9n:Netdate.compiled_localization ->
    ?localzone:bool -> ?zone:int -> string -> float
  val parse_epoch_timespec :
    ?l9n:Netdate.compiled_localization ->
    ?localzone:bool -> ?zone:int -> string -> float * int
  val parse_epoch_approx :
    ?l9n:Netdate.compiled_localization ->
    ?localzone:bool -> ?zone:int -> string -> float
  val format_to :
    ?l9n:Netdate.compiled_localization ->
    Netchannels.out_obj_channel -> fmt:string -> Netdate.t -> unit
  val format :
    ?l9n:Netdate.compiled_localization -> fmt:string -> Netdate.t -> string
  val mk_date :
    ?localzone:bool ->
    ?zone:int -> ?nanos:int -> fmt:string -> float -> string
  val mk_mail_date : ?localzone:bool -> ?zone:int -> float -> string
  val mk_usenet_date : ?localzone:bool -> ?zone:int -> float -> string
  val mk_internet_date :
    ?localzone:bool -> ?zone:int -> ?digits:int -> float -> string
end
ocamlnet-4.1.2/doc/html-main/Shell_intro.html0000644000175000017500000005235012731530353017556 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_intro

Shell_intro


The shell library: Pipelines and redirections

The shell library provides some of the functionality of a Unix shell; in particular the library supports starting simple commands, executing pipelined commands, and arranging redirections.

Module Shell: The comfortable layer

This module is designed for the average user who does not know very much about the Unix process model, and just wants to start external commands. A simple command can be executed by a statement like

 call [ cmd "ls" [ "/dir1"; "/dir2" ]] 

This statement searches "ls" in the current search PATH, launches the new process, and passes the arguments "/dir1" and /dir2" to the process. Nothing special is done with the file descriptors; the new process shares stdin, stdout and stderr with the current process (all other descriptors are automatically closed).

A pipeline can be constructed by call as well. For example:

 call [ cmd "find" [ "/dir" ]; cmd "grep" [ "something" ] ] 

The output of "find" is redirected to the input of "grep".

You can redirect stdin, stdout, stderr (and every other descriptor) by assigning them to other descriptors, or by opening and reading from or writing to them. In the latter case, multiple descriptors can be served parallely. For example:

let s = "d\na\nc\nb\n" in
let b = Buffer.create 20 in
call ~stdin:(from_string s) ~stdout:(to_buffer b) [ cmd "sort" [] ]

Here, "sort" reads the contents of s and writes the result to b.

Unlike the Unix shell, this module reports errors from all components of a pipeline. For example:

call [ cmd "cat" [ "/notfound" ]; cmd "ls" [ "/notfound.too" ] ]

This will raise an exception

Subprocess_error [ "/bin/cat", Unix.WEXITED 1; "/bin/ls", Unix.WEXITED 1 ]

There is another subtle difference to many Unix shells (and normally also the system function in libc). This module reports errors occuring between fork and exec; for instance if the file "fail" refers to a non-existing interpreter

#! /not/found

but is executable, this special error can only be detected by the "exec" call. Unix shells print an error message to stderr, and return an exit code of 127 (which is reserved for this case):

Sys.command "fail";;
sh: ./fail: No such file or directory
~ : int = 127

However, the true reason isn't reported. In contrast to this, the Shell module is able to pass the real error condition back to the calling program:

call [ command "fail" ];;
Uncaught exception: Unix.Unix_error(20, "execve", "./fail").

Module Shell_sys: The fundamental layer

The module Shell is a simple application of the functions defined in Shell_sys, the more fundamental module. Shell_sys allows a more fine-grained control of the execution of external commands; however, it is more difficult to use.

Shell_sys allows it to run processes both synchronously and asynchronously, to form pipelines with arbitrary topology, to create user-defined handlers serving file descriptors, and to control signal handling.

Module Unix_exts: The missing system calls

This module contains some system calls missing in the Unix library distributed with O'Caml.
ocamlnet-4.1.2/doc/html-main/Credentials.html0000644000175000017500000006243712731530353017540 0ustar gerdgerd Ocamlnet 4 Reference Manual : Credentials

Credentials


Credentials

Credentials for SASL

For SASL credentials are specified as a list

 (string * string * (string * string) list) list 

which looks complicated and needs some explanations. Basically, this list presents the authentication mechanism a number of encodings for the same secret. The mechanism can then pick the encoding it can process best. Every encoding of the secret is a tuple

 (type, data, params) 

where type and data are strings, and params is a (string * string) list) list with (name,value) pairs.

Why supporting several encodings? First, there may be huge differences in the speed of the authentication mechanism, in particular when you compare a cleartext password pw with the version of pw that is really used in the mechanism, which is often a function of the password kdf(pw) (kdf = key derivation function). These functions are designed to be slow. Second, there may be a security benefit when a password database needs not to store pw, but can store kdf(pw), in particular on the server side.

All mechanisms support:

  • type = "password": The data string is the raw, unprocessed password. Note that many mechanisms require that the password is a UTF-8 string, and some even request a certain UTF-8 form (the so-called string preparation of the password). The password type does not take any parameters.
The other types are mechanism-specific, and are usually only supported on the server side:

  • type = "authPassword-SCRAM-SHA-1": The data string is the "stored password" for the mechanism SCRAM-SHA-1. There is one parameter "info" containing the iteration count and the salt. These two strings are defined in RFC-5803. OCamlnet uses here intentionally the same format as is commonly used in LDAP servers for storing SCRAM credentials. See Netmech_scram_sasl.SCRAM for sample code how to generate this encoding.
(This list will probably be extended.)

OCamlnet tries to support types conforming either to the pattern defined in RFC 3112 or RFC 2307. See Netsys_sasl_types.SASL_MECHANISM.init_credentials for details.

UTF-8

All user names and passwords for SASL mechanisms must be given in UTF-8.

SASLprep

Moreover, there is a special algorithm normalizing characters where Unicode permits several ways of encoding them: SASLprep. In OCamlnet, SASLprep is implemented by Netsaslprep.

Newer SASL mechanisms require that user names and passwords go through SASLprep. Although older mechansims do not strictly require this yet, it is often also a good idea to apply SASLprep nevertheless, as all mechanisms access the same password database.

OCamlnet does not automatically call SASLprep. Callers of the SASL mechanisms should do that before the user names and passwords reach the mechanism implementations, e.g.

  let creds =
    [ "password", Netsaslprep.saslprep pw, [] ]

The reason is that SASLprep is fairly expensive, and should best only called once when several mechanisms have been enabled.

Credentials for TLS

The (X.509) credentials exist here in two "flavors", namely certificates and private keys.

  • A certificate is a public key that is signed by a trust center. In order to be exact, we should also take the revocations into account, present in form of CRLs (certificate revocation lists).
  • A private key is a large random number.
What makes the handling of these data structures a bit problematic are the various encodings and container formats. Usually certificates and keys are stored on disk, where key files are often password-protected. But one step after the other:

Representations in RAM

  • DER encoding of certificates: This is the primary way certificates are represented as binary BLOB. The DER encoding is not directly used for storing certificates in files. In OCamlnet, the DER encoding is a string (or string list) tagged with `DER.
  • Certificates as parsed objects: The DER encoding can be parsed, and their contents are made accessible as Netx509.x509_certificate objects. The parser function is Netx509.x509_certificate_from_DER.
  • DER encoding of CRLs: Like for certificates there is a DER encoding for revocation lists. The tag `DER is also used for these lists. There is, however, no parser callable from OCaml. (Inside GnuTLS there is a parser.)
  • Private keys can exist in various encodings: RSA, DSA, EC, and PKCS-8. These are also binary encodings based on ASN.1, but with a different internal format. The formats for RSA, DSA, and EC are for the respective public key mechanisms. PKCS-8 is a container format that can contain any of these formats internally, and that optionally also supports encryption. In OCamlnet, the tags `RSA, `DSA, `EC, `PKCS8 and `PKCS8_encrypted are attached to strings with the respective formats. As of now, no parsers for any of these formats are callable from OCaml. Important note: Encrypted keys are only supported via PKCS-8. If you have a PEM file with a "DEK-Info" header, this file cannot be read in. Convert it to PKCS-8 first with an external tool.
Representations on disk

As mentioned, there is always a container format:

  • PEM files: These text files are made up of sections, and every section consists of a header like "-----BEGIN CERTIFICATE-----", the base64 encoded data, and a trailer like "-----END CERTIFICATE-----". Various types of objects are supported. There is a generic parser for the PEM format in Netascii_armor. These are the objects (per header string):
    • "X509 CERTIFICATE" or "CERTIFICATE": The data is the DER encoding of the certificate
    • "X509 CRL": The data is the DER encoding of the CRL
    • "RSA PRIVATE KEY": The data is the RSA key
    • "DSA PRIVATE KEY": The data is the DSA key
    • "EC PRIVATE KEY": The data is the EC key
    • "PRIVATE KEY": The data is in PKCS-8 format
    • "ENCRYPTED PRIVATE KEY": The data is in the encrypted PKCS-8 format
  • PKCS-12 files: so far unsupported in OCamlnet

Note that OCamlnet does not contain any utility for generating these files. You can use the GnuTLS utility certtool or the openssl command.

Besides X.509 credentials, there are also other types (e.g. SRP or OpenPGP credentials) that be used with TLS. This is quite uncommon, though, and should only be used in special situations. At present, such alternate authentication methods are not supported in these TLS bindings.

Credentials for the GSSAPI

The system-level GSSAPI

You can usually pass credentials as pairs string * oid where the string contain the data formatted according to the rules for the OID.

At present, there are no helper functions to support any type of OID better that is possible here.

GSSAPI modules defined in OCaml

To be written


ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.FILE_TLS_ENDPOINT.html0000644000175000017500000004352412731530353024150 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.FILE_TLS_ENDPOINT

Module type Netsys_crypto_types.FILE_TLS_ENDPOINT

module type FILE_TLS_ENDPOINT = sig .. end

module TLS: Netsys_crypto_types.TLS_PROVIDER 
val endpoint : TLS.endpoint
val rd_file : Unix.file_descr
val wr_file : Unix.file_descr
ocamlnet-4.1.2/doc/html-main/index_values.html0000644000175000017500000324331312731530353017766 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of values

Index of values


(++) [Uq_engines_compat.Operators]
(++) [Uq_engines.Operators]
Another name for qseq_engine.
(<&) [Shell]
Same as assign, but infix notation.
(>&) [Shell]
Same as assign, but infix notation.
(>>) [Uq_engines_compat.Operators]
(>>) [Uq_engines.Operators]
Another name for fmap_engine.
_exit [Netsys]
Exit the program immediately without running the atexit handlers.
_of_PMAP'V2'pmapproc_callit'arg [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_callit'res [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_dump'arg [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_dump'res [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_getport'arg [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_getport'res [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_null'arg [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_null'res [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_set'arg [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_set'res [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_unset'arg [Rpc_portmapper_aux]
_of_PMAP'V2'pmapproc_unset'res [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_callit'arg [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_callit'res [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_dump'arg [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_dump'res [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_getaddr'res [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_gettime'arg [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_gettime'res [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_null'arg [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_null'res [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_set'arg [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_set'res [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_unset'arg [Rpc_portmapper_aux]
_of_PMAP'V3'rpcbproc_unset'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_bcast'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_bcast'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_dump'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_dump'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_getaddr'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_getaddrlist'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_getaddrlist'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_getstat'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_getstat'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_gettime'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_gettime'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_getversaddr'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_getversaddr'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_indirect'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_indirect'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_null'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_null'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_set'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_set'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_unset'arg [Rpc_portmapper_aux]
_of_PMAP'V4'rpcbproc_unset'res [Rpc_portmapper_aux]
_of_call_args [Rpc_portmapper_aux]
_of_call_result [Rpc_portmapper_aux]
_of_mapping [Rpc_portmapper_aux]
_of_netbuf [Rpc_portmapper_aux]
_of_pmaplist [Rpc_portmapper_aux]
_of_pmaplist_p [Rpc_portmapper_aux]
_of_rp__list [Rpc_portmapper_aux]
_of_rpcb [Rpc_portmapper_aux]
_of_rpcb_entry [Rpc_portmapper_aux]
_of_rpcb_entry_list [Rpc_portmapper_aux]
_of_rpcb_entry_list_ptr [Rpc_portmapper_aux]
_of_rpcb_rmtcallargs [Rpc_portmapper_aux]
_of_rpcb_rmtcallres [Rpc_portmapper_aux]
_of_rpcb_stat [Rpc_portmapper_aux]
_of_rpcb_stat_byvers [Rpc_portmapper_aux]
_of_rpcblist_ptr [Rpc_portmapper_aux]
_of_rpcbs_addrlist [Rpc_portmapper_aux]
_of_rpcbs_addrlist_ptr [Rpc_portmapper_aux]
_of_rpcbs_proc [Rpc_portmapper_aux]
_of_rpcbs_rmtcalllist [Rpc_portmapper_aux]
_of_rpcbs_rmtcalllist_ptr [Rpc_portmapper_aux]
_of_uaddr [Rpc_portmapper_aux]
_program [Rpc_portmapper_clnt.Make'PMAP.V4]
_program [Rpc_portmapper_clnt.Make'PMAP.V3]
_program [Rpc_portmapper_clnt.Make'PMAP.V2]
_to_PMAP'V2'pmapproc_callit'arg [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_callit'res [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_dump'arg [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_dump'res [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_getport'arg [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_getport'res [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_null'arg [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_null'res [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_set'arg [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_set'res [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_unset'arg [Rpc_portmapper_aux]
_to_PMAP'V2'pmapproc_unset'res [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_callit'arg [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_callit'res [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_dump'arg [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_dump'res [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_getaddr'res [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_gettime'arg [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_gettime'res [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_null'arg [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_null'res [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_set'arg [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_set'res [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_unset'arg [Rpc_portmapper_aux]
_to_PMAP'V3'rpcbproc_unset'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_bcast'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_bcast'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_dump'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_dump'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_getaddr'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_getaddrlist'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_getaddrlist'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_getstat'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_getstat'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_gettime'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_gettime'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_getversaddr'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_getversaddr'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_indirect'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_indirect'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_null'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_null'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_set'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_set'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_unset'arg [Rpc_portmapper_aux]
_to_PMAP'V4'rpcbproc_unset'res [Rpc_portmapper_aux]
_to_call_args [Rpc_portmapper_aux]
_to_call_result [Rpc_portmapper_aux]
_to_mapping [Rpc_portmapper_aux]
_to_netbuf [Rpc_portmapper_aux]
_to_pmaplist [Rpc_portmapper_aux]
_to_pmaplist_p [Rpc_portmapper_aux]
_to_rp__list [Rpc_portmapper_aux]
_to_rpcb [Rpc_portmapper_aux]
_to_rpcb_entry [Rpc_portmapper_aux]
_to_rpcb_entry_list [Rpc_portmapper_aux]
_to_rpcb_entry_list_ptr [Rpc_portmapper_aux]
_to_rpcb_rmtcallargs [Rpc_portmapper_aux]
_to_rpcb_rmtcallres [Rpc_portmapper_aux]
_to_rpcb_stat [Rpc_portmapper_aux]
_to_rpcb_stat_byvers [Rpc_portmapper_aux]
_to_rpcblist_ptr [Rpc_portmapper_aux]
_to_rpcbs_addrlist [Rpc_portmapper_aux]
_to_rpcbs_addrlist_ptr [Rpc_portmapper_aux]
_to_rpcbs_proc [Rpc_portmapper_aux]
_to_rpcbs_rmtcalllist [Rpc_portmapper_aux]
_to_rpcbs_rmtcalllist_ptr [Rpc_portmapper_aux]
_to_uaddr [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_callit'arg [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_callit'res [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_dump'arg [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_dump'res [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_getport'arg [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_getport'res [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_null'arg [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_null'res [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_set'arg [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_set'res [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_unset'arg [Rpc_portmapper_aux]
_xof_PMAP'V2'pmapproc_unset'res [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_callit'arg [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_callit'res [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_dump'arg [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_dump'res [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_getaddr'res [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_gettime'arg [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_gettime'res [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_null'arg [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_null'res [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_set'arg [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_set'res [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_unset'arg [Rpc_portmapper_aux]
_xof_PMAP'V3'rpcbproc_unset'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_bcast'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_bcast'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_dump'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_dump'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_getaddr'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_getaddrlist'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_getaddrlist'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_getstat'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_getstat'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_gettime'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_gettime'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_getversaddr'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_getversaddr'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_indirect'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_indirect'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_null'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_null'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_set'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_set'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_unset'arg [Rpc_portmapper_aux]
_xof_PMAP'V4'rpcbproc_unset'res [Rpc_portmapper_aux]
_xof_call_args [Rpc_portmapper_aux]
_xof_call_result [Rpc_portmapper_aux]
_xof_mapping [Rpc_portmapper_aux]
_xof_netbuf [Rpc_portmapper_aux]
_xof_pmaplist [Rpc_portmapper_aux]
_xof_pmaplist_p [Rpc_portmapper_aux]
_xof_rp__list [Rpc_portmapper_aux]
_xof_rpcb [Rpc_portmapper_aux]
_xof_rpcb_entry [Rpc_portmapper_aux]
_xof_rpcb_entry_list [Rpc_portmapper_aux]
_xof_rpcb_entry_list_ptr [Rpc_portmapper_aux]
_xof_rpcb_rmtcallargs [Rpc_portmapper_aux]
_xof_rpcb_rmtcallres [Rpc_portmapper_aux]
_xof_rpcb_stat [Rpc_portmapper_aux]
_xof_rpcb_stat_byvers [Rpc_portmapper_aux]
_xof_rpcblist_ptr [Rpc_portmapper_aux]
_xof_rpcbs_addrlist [Rpc_portmapper_aux]
_xof_rpcbs_addrlist_ptr [Rpc_portmapper_aux]
_xof_rpcbs_proc [Rpc_portmapper_aux]
_xof_rpcbs_rmtcalllist [Rpc_portmapper_aux]
_xof_rpcbs_rmtcalllist_ptr [Rpc_portmapper_aux]
_xof_uaddr [Rpc_portmapper_aux]

A
abandon_call [Rpc_client]
To be used in conjunction with Rpc_client.Keep_call: The call with this session identifier is no longer expected, and removed from the internal data structures.
abandon_job [Shell_sys]
Deprecated name for cancel_job
abort [Netldap]
Close the connection immediately
abspath [Netsys]
Return an absolute path for this file.
ac_by_host [Nethttpd_services]
Configures host-based access control
accelerated_pollset [Netsys_pollset_posix]
Returns a pollset using a "fast" poll mechanism, if available.
accept [Netsys_polysocket]
Accepts the next connection (or returns the next connection from the backlog queue).
accept_descr [Netsys_polysocket]
Returns a descriptor that can be used for polling.
accept_sec_context [Netgssapi_auth.Auth]
Calls G.accept_sec_context, and returns (out_context,out_token,flags,props_opt).
accept_switch [Netsys_crypto_types.TLS_PROVIDER]
On the client: Enter another handshake round with new configuration data.
acceptable_transports_http [Netmech_spnego_http.PROFILE]
Which transport IDs are acceptable for authenticated requests on unencrypted connections.
acceptable_transports_https [Netmech_spnego_http.PROFILE]
Which transport IDs are acceptable for authenticated requests on HTTPS-secured connections.
access [Netsys_global]
access name: Create or look up a variable with this name
access [Netplex_mutex]
Access the named mutex.
access [Netplex_sharedvar.VV_TYPE]
access [Netmcore_buffer]
access b pos f: Gets access to the internal string backing the byte at position pos.
access_descriptions [Netx509.AD]
acquire_initiator_cred [Netgssapi_auth.Auth]
act_events_of_event_source [Netsys_posix]
Return the actual events of the source.
act_events_of_int [Netsys_posix]
ad_ca_issuers [Netx509.AD]
ad_ca_repository [Netx509.AD]
ad_ocsp [Netx509.AD]
ad_time_stamping [Netx509.AD]
add [Netsys_crypto_types.DIGESTS]
Adds data
add [Netshm_hashtbl]
add tbl key value: Adds the binding of key to value to the table.
add [Netshm]
add tbl key value: Adds the binding of key to value to the table.
add [Netmcore_hashtbl]
add tbl x y adds a binding of x to y in table tbl.
add [Netmcore_heap]
Pushes a new value onto the heap.
add [Netldap]
Same as synchronous function
add [Netcgi_apache.Apache.Table]
Table.add tbl key value adds the (key, value) pair in the table tbl.
add [Uq_libevent.LIBOEVENT]
add_1_complement [Netauth]
The addition algorithm for 1's-complement numbers.
add_abort_action [Unixqueue]
An abort action is added to the group.
add_buffer [Netbuffer]
add_buffer nb1 nb2: Adds the contents of nb2 to the end of nb1
add_bytes [Netpagebuffer]
Same for bytes
add_bytes [Netbuffer]
Same for bytes
add_call [Rpc_client]
add_call client proc_name arg f: add the call to the procedure name with argument arg to the queue of unprocessed calls.
add_char [Netbuffer]
add_char nb c: Adds a single char at the end of the buffer
add_char_2 [Netbuffer]
add_char_2 nb c1 c2: Adds two chars at the end of the buffer
add_char_4 [Netbuffer]
add_char_4 nb c1 c2 c3 c4: Adds four chars at the end of the buffer
add_close_action [Unixqueue]
A close action is added for the file descriptor.
add_command [Shell_sys]
Adds a command to a job.
add_consumer [Shell_sys]
Adds a consumer to the job.
add_e [Netldap]
add_e conn ~dn ~attributes: Adds a new entry under dn with the attributes, given as list (attr_descr, values).
add_event [Unixqueue]
Add an additional event.
add_event [Equeue]
Puts an event into the event queue of the system.
add_event_source [Netsys_posix]
Adds the event source to the aggregator
add_handler [Unixqueue]
Add an event handler that is associated to the given group.
add_handler [Equeue]
Adds a handler to the list of handlers of the system.
add_helper_service [Netplex_kit]
add_helper_service ctrl name hooks: Adds a helper service name to the controller ctrl.
add_immutable [Netmcore_heap]
Pushes a new value onto the heap.
add_init_array [Netmcore_heap]
add_init_array m n f: Pushes a new value with n elements onto the heap.
add_inplace [Netpagebuffer]
add_inplace b f: Calls f m pos len where m is the last page of the buffer, and pos is the first free byte on the page, and len is the number of free bytes on the page.
add_inplace [Netbuffer]
add_inplace nb f: Calls the function f to add bytes to the netbuffer nb.
add_pipeline [Shell_sys]
Adds a pipeline which redirects the output of the command src to the input of the command dest.
add_plugins [Netmcore]
To enable compute processes for any Netplex program, call this function with the controller object as argument.
add_producer [Shell_sys]
Adds a producer to the job.
add_resource [Unixqueue]
Add a resource such that it is watched for conditions described by the operation for the period given by the float number.
add_some [Netmcore_heap]
add_some mut x: Returns Some x where the O'Caml value representing Some is allocated in the heap using mut.
add_string [Netpagebuffer]
Adds a string to the end of the buffer
add_string [Netbuffer]
add_string nb s: Adds a copy of the string s to the logical end of the netbuffer nb.
add_string [Netmcore_buffer]
Adds a string to the end of the buffer
add_string [Netmcore_heap]
let s = add_string mut len: Adds an uninitialized string of length len to the heap using mut, and returns the string
add_sub_memory [Netpagebuffer]
add_sub_memory [Netbuffer]
add_sub_memory [Netmcore_buffer]
add_sub_string [Netpagebuffer]
add_sub_string [Netbuffer]
add_sub_string [Netmcore_buffer]
add_subbytes [Netpagebuffer]
Adds a sub string to the end of the buffer
add_subbytes [Netbuffer]
Same for bytes
add_submemory [Netpagebuffer]
Adds a sub memory buffer to the end of the buffer
add_submemory [Netbuffer]
Same as add_substring, but gets data from a memory buffer
add_submemory [Netmcore_buffer]
Adds a sub memory buffer to the end of the buffer
add_substring [Netpagebuffer]
Adds a sub string to the end of the buffer
add_substring [Netbuffer]
add_substring nb s k n: Adds the substring of s starting at position k with length n to the logical end of the netbuffer nb.
add_substring [Netmcore_buffer]
Adds a sub string to the end of the buffer
add_subtstring [Netpagebuffer]
Adds a sub tstring to the end of the buffer
add_subtstring [Netbuffer]
Same for tagged string
add_subtstring_poly [Netbuffer]
Polymorphic version
add_tstring [Netpagebuffer]
Same for tagged string
add_tstring [Netbuffer]
Same for tagged string
add_tstring_poly [Netbuffer]
Polymorphic version
add_uniform_array [Netmcore_heap]
add_uniform_array m n x: Pushes a new value with n elements onto the heap.
add_weak_resource [Unixqueue]
Similar to add_resource, but the resource is weak.
admin [Netcgi_apache.Apache.Server]
server_admin field.
admin_connector [Netplex_cenv]
Determines the admin socket of the controller, and returns an RPC client connector suitable for connecting with the admin interface of the controller.
advance [Netpagebuffer]
advance b n: Marks further n bytes in the last page of the buffer as used.
advance [Netbuffer]
These two functions work together, so that the effect of add_inplace can be obtained in two steps.
ajp_processor [Netcgi_plex]
alg_id_of_encrypt_alg [Netx509_pubkey.Encryption]
Get the alg_id of an encryption alg
alg_id_of_kex_alg [Netx509_pubkey.Keyagreement]
Get the alg_id of a key agreement alg
alg_id_of_sign_alg [Netx509_pubkey.Signing]
Get the alg_id of a sign alg
algorithm_x509 [Netsys_crypto_types.PUBKEY_CRYPTO]
The algorithm is specified by OID.
all_decoders [Netcompression]
The iana names of all encoders and decoders, resp.
all_encoders [Netcompression]
alloc_aligned_memory [Netsys_mem]
alloc_aligned_memory alignment size: Allocates a buffer of size whose start address is a multiple of alignment.
alloc_mem [Netmcore_mempool]
Allocate memory in this pool.
alloc_memory_pages [Netsys_mem]
Allocates memory in units of pages.
alloc_wait_entry [Netmcore_condition]
Allocates a wait_entry
alloc_wait_entry_e [Netmcore_condition]
alloc_wait_entry_e mut set filename: Allocates a new wait entry with notification via named pipe.
announce_channel_binding [Netmech_gs2_sasl.PROFILE]
Whether to announce the availability of channel binding by adding "-PLUS" to the mechanism name, and by offering channel bindings in the initial token.
announce_channel_binding [Netmech_scram_sasl.PROFILE]
Whether servers announce the availability of channel binding by adding "-PLUS" to the mechanism name.
anon_bind_creds [Netldap]
any_file_client_connector [Netplex_sockserv]
Interprets a file name as connector for a local RPC service.
apply_relative_url [Neturl]
apply_relative_url base rel: Interprets rel relative to base and returns the new URL.
are_compatible [Netxdr]
are_compatible: currently not implemented
area_for_additions [Netbuffer]
arg_parse [Netcgi_ajp]
arg_parse speclist anon_fun usage_msg parses the command line and return an associative list describing the content of the property file (see Netcgi_ajp.props_of_file).
args [Netplex_main]
let (opt_list, cmdline_cfg) = args(): Returns opt_list for inclusion in the Arg.parse option list.
args [Netcgi_apache.Apache.Request]
request_rec args field.
array_of_oid_set [Netgss_bindings]
as_obj [Netsys_mem]
Same as as_value but returns the value as Obj.t
as_process_event [Netsys_win32]
Casts the process handle to an event handle.
as_sem [Netsys_sem]
as_sem mem pos: Interprets the memory at position pos to pos + sem_size() - 1 as anonymous semaphore.
as_sem [Netsys_posix]
as_sem mem pos: Interprets the memory at position pos to pos + sem_size() - 1 as anonymous semaphore.
as_value [Netsys_mem]
as_value mem offset: Returns a pointer to mem+offset.
assbackwards [Netcgi_apache.Apache.Request]
request_rec assbackwards field; true if HTTP/0.9, "simple" request.
assign [Shell]
Arranges a redirection such that writing to src or reading from src will actually write to target or read from target (i.e., the target descriptor is duplicated and replaces the src descriptor just before the process is launched.)
assign [Netmcore_ref]
assign sr x: Sets the contents of sr to a deep copy of x.
assigned_pair [Shell]
Returns the target and the source of the assignment as pair of descriptors (target,src).
at_commonName [Netx509.DN_attributes]
at_countryName [Netx509.DN_attributes]
at_dnQualifier [Netx509.DN_attributes]
at_domainComponent [Netx509.DN_attributes]
at_emailAddress [Netx509.DN_attributes]
at_fdcwd [Netsys_posix]
Pseudo descriptor value to be used as first argument of *at functions
at_generationQualifier [Netx509.DN_attributes]
at_givenName [Netx509.DN_attributes]
at_initials [Netx509.DN_attributes]
at_localityName [Netx509.DN_attributes]
at_name [Netx509.DN_attributes]
at_organizationName [Netx509.DN_attributes]
at_organizationalUnitName [Netx509.DN_attributes]
at_pseudonym [Netx509.DN_attributes]
at_serialNumber [Netx509.DN_attributes]
at_stateOrProvinceName [Netx509.DN_attributes]
at_surname [Netx509.DN_attributes]
at_title [Netx509.DN_attributes]
at_transport_eof [Netsys_tls]
Whether the underlying transport channel has seen the end of input.
at_transport_eof [Netsys_crypto_types.TLS_PROVIDER]
Whether the underlying transport channel has seen the end of input.
at_uid [Netx509.DN_attributes]
atomic_init [Netsys_oothr]
atomic_init var new_value: If the variable var is None, it is set to Some new_value, and new_value is returned.
attribute_from_ASN1 [Netx509]
Parses an attribute
attribute_types [Netx509.DN_attributes]
The above types in the format (oid, full_name, short_names)
attribute_types [Netdn.AT_LOOKUP]
The above types in the format (oid, full_name, short_names)
attributes_from_ASN1 [Netx509]
Parses a sequence of attributes
auth_mechanisms [Netsmtp]
If applied to helo_response, returns the list of AUTH mechanisms
auth_none [Rpc_server]
The authentication method "AUTH_NONE", i.e.
auth_none [Rpc_client]
The authentication method that does not perform authentication.
auth_too_weak [Rpc_server]
The method that always rejects.
auth_transport [Rpc_server]
Authenticate by trusting the transport layer.
auth_type [Netcgi_apache.Apache.Request]
authenticate [Netpop]
Authenticates the session:
authenticate [Netsmtp]
Authenticates the session:
authz_name [Netsys_sasl.Server]
The name the client authorizes as (or Not_found)
authz_name [Netsys_sasl.Client]
The authorization name
available [Netsys_sasl_types.SASL_MECHANISM]
Whether the mechanism is available, in particular whether the required crypto support is linked in
available [Nethttp.HTTP_CLIENT_MECHANISM]
Whether the mechanism is available, in particular whether the required crypto support is linked in
available_input_encodings [Netconversion]
Returns the list of all available encodings that can be used for input strings.
available_output_encodings [Netconversion]
Returns the list of all available encodings that can be used for output strings.

B
b_error_of_name [Nettls_gnutls_bindings]
b_set_db_callbacks [Nettls_gnutls_bindings]
b_set_db_callbacks session store remove retrieve: sets the three callbacks for server-side session caching
b_set_pull_callback [Nettls_gnutls_bindings]
Sets the function for reading data.
b_set_pull_timeout_callback [Nettls_gnutls_bindings]
Sets the function for waiting for new data to arrive (only used for DTLS).
b_set_push_callback [Nettls_gnutls_bindings]
Sets the function for writing data.
b_set_verify_callback [Nettls_gnutls_bindings]
Sets the function for verifying the peer's certificate.
base_code [Nethttp]
Allows to handle unknown status codes that are untranslatable by http_status_of_int: for a code 100 to 199 the value 100 is returned, for a code 200 to 299 the value 200 is returned, for a code 300 to 399 the value 300 is returned, for a code 400 to 499 the value 400 is returned, for all other codes 500 is returned E.g.
basic_mime_header [Netmime]
Same as function
best_charset [Nethttp.Header]
Returns the best charset for a header and a list of supported charsets.
best_encoding [Nethttp.Header]
Returns the best encoding for a header and a list of supported encodings.
best_locking_method [Netshm]
Return the best locking method other than No_locking
best_media_type [Nethttp.Header]
Returns the best media type for a header and a list of supported types.
bg_blue [Netsys_win32]
bg_green [Netsys_win32]
bg_intensity [Netsys_win32]
Bits of text_attr
bg_red [Netsys_win32]
bigarray [Netshm]
bind [Rpc_server]
Binds the program as specified by the binding list.
bind [Rpc_client]
Binds this program additionally
bitstring_of_bits [Netasn1.Value]
Get the bitstring from a bool array
bitstring_of_string [Netasn1.Value]
Get the bitstring from a string and the total number of bits.
blit [Netpagebuffer]
Compatibility name for blit_to_bytes
blit [Netbuffer]
Compatibility name for blit_to_bytes
blit_bytes_to_memory [Netsys_mem]
blit_bytes_to_memory src srcoff dst dstoff len copies len characters from string src, starting at character number srcoff, to buffer dst, starting at character number dstoff
blit_bytes_to_memory_unsafe [Netsys_mem]
Unsafe version
blit_from_bytes [Netbuffer]
Same for bytes
blit_from_memory [Netbuffer]
Same for memory
blit_from_string [Netbuffer]
blit_from_string src srcpos dest destpos len: Copies the len bytes at position srcpos from the string src to the netbuffer dest at position destpos.
blit_from_tstring [Netbuffer]
Same for tagged string
blit_memory_to_bytes [Netsys_mem]
blit_memory_to_bytes src srcoff dst dstoff len copies len characters from buffer src, starting at character number srcoff, to string dst, starting at character number dstoff
blit_memory_to_bytes_unsafe [Netsys_mem]
Unsafe version
blit_memory_to_string [Netsys_mem]
blit_memory_to_string_unsafe [Netsys_mem]
blit_mstrings_to_memory [Netxdr_mstring]
blits the mstrings one after the other to the memory, so that they appear there concatenated
blit_poll_array [Netsys_posix]
blit_poll_array a1 p1 a2 p2 len: Copies the len cells at index p1 from a1 to a2 at index p2.
blit_string_to_memory [Netsys_mem]
blit_string_to_memory src srcoff dst dstoff len: A version for immutable strings
blit_string_to_memory_unsafe [Netsys_mem]
Unsafe version
blit_to_bytes [Netpagebuffer]
Blits contents to a string
blit_to_bytes [Netbuffer]
blit_to_bytes nb srcpos dest destpos len: Copies the len bytes at position srcpos from nb to the string dest at position destpos.
blit_to_bytes [Netmcore_buffer]
Blits contents to a string
blit_to_memory [Netpagebuffer]
Blits contents to another memory buffer
blit_to_memory [Netbuffer]
blit_to_memory nb srcpos dest destpos len: Copies the len bytes at position srcpos from nb to the membuffer dest at position destpos.
blit_to_memory [Netmcore_buffer]
Blits contents to a memory buffer
blit_to_string [Netpagebuffer]
blit_to_string [Netbuffer]
blit_to_string [Netmcore_buffer]
blit_to_tbuffer [Netpagebuffer]
Blits contents to a tagged buffer
blit_to_tbuffer [Netbuffer]
Blits to a tagged buffer
block_constraint [Netsys_crypto_types.SYMMETRIC_CRYPTO]
The buffers used with encrypt/decrypt must have a length that is a multiple of this number.
block_length [Netsys_crypto_types.DIGESTS]
the block length (in bytes)
blocking_gread [Netsys]
let p = blocking_gread fd_style fd s pos len: Like gread up to len bytes are read from fd and stored in s.
blocking_gread_tbuf [Netsys]
Same for a tagged buffer
blocking_socket_config [Rpc_client]
Configuration with non_blocking_connect = false
bool_var [Netplex_cenv]
Access a variable with simple type.
bound_programs [Rpc_server]
Returns the bound programs
bounded_full_split [Netstring_str]
Splits into at most n substrings, based on full_split
bounded_full_split [Netstring_pcre]
Splits into at most n substrings, based on full_split
bounded_split [Netstring_str]
Splits into at most n substrings, based on split
bounded_split [Netstring_pcre]
Splits into at most n substrings, based on split
bounded_split_delim [Netstring_str]
Splits into at most n substrings, based on split_delim
bounded_split_delim [Netstring_pcre]
Splits into at most n substrings, based on split_delim
broadcast [Netmcore_condition]
broadcast c restarts all processes waiting on the condition variable c.
buffer_of_bytes [Netgss_bindings]
buffer_of_descr [Netmcore_buffer]
Look up the buffer for this descriptor
buffer_of_memory [Netgss_bindings]
buffer_of_string [Netgss_bindings]
buffered_transactional_optype [Netcgi1_compat.Netcgi]
buffered_transactional_optype [Netcgi]
Deprecated name for buffered_transactional_outtype
buffered_transactional_outtype [Netcgi]
The output_type implementing transactions with a RAM-based buffer
bye [Netsys_crypto_types.TLS_PROVIDER]
Performs the final handshake (exchanges close requests).
byte_order_mark [Netconversion]
Returns the byte order mark that must occur at the beginning of files to indicate whether "little endian" or "big endian" is used.
bytes_based_mstrings [Netxdr_mstring]
Uses bytes to represent mstrings
bytes_match [Netstring_str]
Same for bytes
bytes_match [Netstring_pcre]
Same for bytes
bytes_of_buffer [Netgss_bindings]
bytes_of_in_obj_channel [Netchannels]
Same for bytes
bytes_of_memory [Netsys_mem]
Return a new string as a copy of the bigarray
bytes_of_packed_value [Rpc_packer]
bytes_ops [Netstring_tstring]
Implementation of the operations for bytes
bytes_to_mstring [Netxdr_mstring]
Represent bytes as mstring (no copy)

C
c [Netmech_scram.AES_CTS]
cache [Uq_engines_compat]
cache [Uq_engines]
Same as function
call [Shell]
Starts the pipeline represented by the list of commands; i.e.
call [Shell_sys]
Executes the command and waits until the process terminates (synchronous execution a la system, but no intermediate shell).
call [Rpc_simple_client]
call simple_client procedure_name procedure_arg: Call the procedure with the given name and the given argument.
call_job [Shell_sys]
Starts the job (see run_job) and waits until it finishes (see finish_job); i.e.
camlbox_addr [Netcamlbox]
returns the address
camlbox_bcapacity [Netcamlbox]
same for an already opened box
camlbox_bmessages [Netcamlbox]
same for an already opened box
camlbox_bmsg_size [Netcamlbox]
same for an already opened box
camlbox_cancel_wait [Netcamlbox]
Cancels a camlbox_wait operation called by a different thread
camlbox_capacity [Netcamlbox]
Returns the maximum number of messages n
camlbox_delete [Netcamlbox]
camlbox_delete box k: Deletes the message number k from box.
camlbox_fd [Netcamlbox]
Opens a new file descriptor to this address
camlbox_get [Netcamlbox]
camlbox_get box k: Returns message number k from box.
camlbox_get_copy [Netcamlbox]
camlbox_get box k: Returns a deep copy of message number k from box.
camlbox_messages [Netcamlbox]
Returns the number of messages at the moment
camlbox_msg_size [Netcamlbox]
Returns the max size of a message in bytes
camlbox_saddr [Netcamlbox]
returns the address
camlbox_scapacity [Netcamlbox]
same for a box already opened for sending
camlbox_send [Netcamlbox]
Sends a message to a camlbox.
camlbox_sender [Netcamlbox]
Prepares for sending.
camlbox_sender_of_fd [Netcamlbox]
Gets a sender for a file descriptor from camlbox_fd.
camlbox_smessages [Netcamlbox]
same for a box already opened for sending
camlbox_smsg_size [Netcamlbox]
same for a box already opened for sending
camlbox_wait [Netcamlbox]
Waits until new messages arrive, and return the message numbers.
camlbox_wake [Netcamlbox]
Sends an "empty message" - this only means that if the receiving thread is waiting for new messages it is interrupted and camlbox_wait will return the empty list.
cancel_all_timers [Netplex_cenv]
Cancels all active timers
cancel_input_thread [Netsys_win32]
Stops the input thread.
cancel_job [Shell_sys]
Tries to get rid of a running job.
cancel_output_thread [Netsys_win32]
Stops the output thread.
cancel_timer [Netplex_cenv]
Cancels the timer: The callback function is not called any longer
catalog [Netx509_pubkey.Signing]
(name, aliases, oid, container_oid)
catalog [Netx509_pubkey.Keyagreement]
(name, aliases, oid, pubkey_oid)
catalog [Netx509_pubkey.Encryption]
(name, aliases, oid, pubkey_oid)
catalog [Netx509_pubkey.Key]
(name, aliases, privkey_name, oid)
cbc_of_ecb [Netsys_crypto_modes.Symmetric_cipher]
For a given cipher in ECB mode, a new cipher in CBC mode is returned.
ce_any_policy [Netx509.CE]
ce_authority_info_access [Netx509.CE]
ce_authority_key_identifier [Netx509.CE]
ce_basic_constraints [Netx509.CE]
ce_certificate_policies [Netx509.CE]
ce_crl_distribution_points [Netx509.CE]
ce_ext_key_usage [Netx509.CE]
ce_freshest_crl [Netx509.CE]
ce_inhibit_any_policy [Netx509.CE]
ce_issuer_alt_name [Netx509.CE]
ce_key_usage [Netx509.CE]
ce_name_constraints [Netx509.CE]
ce_policy_constraints [Netx509.CE]
ce_policy_mappings [Netx509.CE]
ce_subject_alt_name [Netx509.CE]
ce_subject_directory_attributes [Netx509.CE]
ce_subject_info_access [Netx509.CE]
ce_subject_key_identifier [Netx509.CE]
certificate_extensions [Netx509.CE]
All the above listed OIDs with their string names (useful for displaying extension types)
cgi_with_args [Netcgi_common]
cgi_with_args (new cgi) env out op ?put_arg in_chan constructs a Netcgi.cgi object.
channel_binding [Netsys_sasl.Server]
Whether the client suggests or demands channel binding
channel_binding [Netsys_sasl.Client]
Whether the client suggests or demands channel binding
channel_logger [Netlog]
channel_logger ch lev: Prints all messages with a level of lev and higher to the channel ch.
channel_logger [Netplex_log]
Outputs messages to the channel
channel_logger_from_obj [Netplex_log]
Outputs messages to the channel
char_of_option [Nettelnet_client]
Converts the option name to the character representing it on the octet-stream level.
check_client_flags [Netgssapi_auth.Auth]
check_critical_exts [Netx509]
check_critical_exts list exts: When an extension is flagged as critical, it must be processed by the communication endpoint.
check_directory_glob_expr [Netglob]
If the last component of the glob expression matches only directories because it ends with a literal / character, the value Some expr' is returned where expr' matches the same path without the trailing /.
check_rooted_glob_expr [Netglob]
If the glob expression matches the root directory (i.e.
check_server_flags [Netgssapi_auth.Auth]
check_status [Netgssapi_auth.Auth]
If the major_status indicates an error, an error string is formed, optionally including the function name fn and the detailed information derived from minor_status.
chmod_shm [Netshm]
chown_shm [Netshm]
Set file permission bits, user and group ownership of the object
ci_code_cmp [Netconversion]
A compare function for ustring_compare: Case-insensitive comparison: This function compares by the lowercase code point if it exists, and the untransformed code point otherwise.
ciphers [Netsys_crypto_modes.CIPHERS]
ciphers [Netsys_ciphers]
List of supported ciphers
ciphers [Netsys_crypto_types.SYMMETRIC_CRYPTO]
List of supported ciphers.
clear [Netpagebuffer]
Deletes all contents of the buffer
clear [Netbuffer]
Deletes all contents from the buffer.
clear [Netmcore_hashtbl]
Empty a hash table.
clear [Netmcore_buffer]
Deletes all contents of the buffer
clear [Netmcore_queue]
Removes all elements from the queue
clear [Netcgi_apache.Apache.Table]
Table.clear tbl removes all key/value pairs from the table tbl.
clear [Unixqueue]
Terminate the whole group.
clear_close_on_exec [Netsys]
Working versions of the functions with the same name in Unix
clear_console [Netsys_win32]
Clears the screen and the buffer, and sets the cursor to (0,0).
clear_until_end_of_line [Netsys_win32]
Writes a space character from the current cursor position to the end of the line
clear_until_end_of_screen [Netsys_win32]
Writes a space character from the current cursor position to the end of the screen
client_additional_params [Netmech_gs2_sasl.PROFILE]
Additional parameters understood by create_client_session
client_auth_method [Rpc_auth_gssapi]
Creates an authentication method from a GSS-API interface.
client_auth_method [Rpc_auth_sys]
Pass the result of this function to Rpc_client.set_auth_methods to configure client authentication.
client_authz_name [Netsys_sasl_types.SASL_MECHANISM]
The authorization name
client_authz_name [Netmech_scram]
The authorization name
client_channel [Uq_client]
client_channel st timeout: returns a bidirectional channel for st that times out after timeout seconds of waiting.
client_channel_binding [Netsys_sasl_types.SASL_MECHANISM]
Whether the client suggests or demands channel binding
client_channel_binding [Netmech_scram]
Returns the channel binding
client_channel_binding [Nethttp.HTTP_CLIENT_MECHANISM]
Whether the client suggests or demands channel binding
client_configure_channel_binding [Netsys_sasl_types.SASL_MECHANISM]
Configure GS2-style channel binding
client_configure_channel_binding [Netmech_scram]
Sets whether to request channel binding.
client_configure_channel_binding [Nethttp.HTTP_CLIENT_MECHANISM]
Configure GS2-style channel binding
client_connector [Netplex_sockserv]
Returns the RPC client connector for this Netplex address
client_credential [Netmech_gs2_sasl.PROFILE]
If set, the client will use a certain credential (and not acquire one).
client_domain [Nethttp.HTTP_CLIENT_MECHANISM]
After successful authentication, this function may return the URIs defining the authentication space.
client_emit_flag [Netmech_scram]
Whether client_emit_message can now be called
client_emit_message [Netmech_scram]
Emits the next message to be sent to the server
client_emit_message_kv [Netmech_scram]
Emits the next message to be sent to the server.
client_emit_response [Netsys_sasl_types.SASL_MECHANISM]
Emit a new response.
client_emit_response [Nethttp.HTTP_CLIENT_MECHANISM]
let (creds,new_headers) = client_emit_response cs method uri header:
client_endpoint [Uq_engines_compat]
client_endpoint [Uq_client]
Returns the client endpoint contained in the connect_status
client_error_flag [Netmech_scram]
Whether an error occurred, and the protocol cannot advance anymore
client_export [Netmech_scram]
client_finish_flag [Netmech_scram]
Whether the client is authenticated and the server verified
client_first [Netsys_sasl.Info]
Whether the client sends the first message: `Required: always, `Optional: the client may choose to do so if the protocol permits this, `No: the server sends the first message
client_first [Netsys_sasl_types.SASL_MECHANISM]
Whether the client sends the first message: `Required: always, `Optional: the client may choose to do so if the protocol permits this, `No: the server sends the first message
client_flags [Netmech_gs2_sasl.PROFILE]
Flags for init_sec_context.
client_get_target_name [Netmech_gs2_sasl.PROFILE]
For clients: get the GSSAPI name of the target to contact as (name_string,name_type) pair.
client_gssapi_props [Netsys_sasl_types.SASL_MECHANISM]
Return the GSSAPI properties of the client, after the authentication is successful (and raises Not_found up to then).
client_gssapi_props [Nethttp.HTTP_CLIENT_MECHANISM]
Returns the GSSAPI props if available, or raise Not_found
client_import [Netmech_scram]
Exports a client session as string, and imports the string again.
client_map_user_name [Netmech_gs2_sasl.PROFILE]
For clients: maps user names to a pair (name_string,name_type) that can be used in the GSSAPI for acquiring a name.
client_match [Nethttp.HTTP_CLIENT_MECHANISM]
Checks whether this mechanism can accept the initial authentication challenge (i.e.
client_password [Netmech_scram]
The password
client_process_challenge [Netsys_sasl_types.SASL_MECHANISM]
Process the challenge from the server.
client_process_challenge [Nethttp.HTTP_CLIENT_MECHANISM]
client_process_challenge cs method uri header challenge:
client_prop [Netsys_sasl_types.SASL_MECHANISM]
Get a mechanism-specific property of the session.
client_prop [Netmech_scram]
Returns a property of the client (or Not_found): "snonce": server nonce, "cnonce": client nonce, "salt": password salt, "i": iteration count, "client_key": this key is derived from the salted password but cannot be derived from the stored key. Its presence proves that the password was entered. It is ideal for encrypting data with a per-user key. The client key is known both to the client and to the server (after running the protocol)., "protocol_key": another key defined in RFC-5801 known by both sides. The protocol key is additionally also dependent on the nonces., "error"
client_prop [Nethttp.HTTP_CLIENT_MECHANISM]
Get a mechanism-specific property of the session.
client_protocol_key [Netmech_scram]
The 128-bit protocol key for encrypting messages.
client_recv_flag [Netmech_scram]
Whether client_recv_message can now be called
client_recv_message [Netmech_scram]
Receives the next message from the server
client_restart [Netsys_sasl_types.SASL_MECHANISM]
Restart the session for another authentication round.
client_restart [Netmech_scram]
Restart a client session (draft-ietf-httpauth-scram-auth-15).
client_restart [Nethttp.HTTP_CLIENT_MECHANISM]
Restart the session for another authentication round.
client_restart_stale [Netmech_scram]
Restart a client session after the server indicated that the session is stale.
client_resume_session [Netsys_sasl_types.SASL_MECHANISM]
Unserializes the session
client_resume_session [Nethttp.HTTP_CLIENT_MECHANISM]
Unserializes the session
client_semifinish_flag [Netmech_scram]
Whether the client is authentication
client_session_id [Netsys_sasl_types.SASL_MECHANISM]
Optionally return a string that can be used to identify the client session.
client_session_id [Nethttp.HTTP_CLIENT_MECHANISM]
Optionally return a string that can be used to identify the client session.
client_socket [Uq_engines_compat]
client_stash_session [Netsys_sasl_types.SASL_MECHANISM]
Serializes the session as string
client_stash_session [Nethttp.HTTP_CLIENT_MECHANISM]
Serializes the session as string
client_state [Netsys_sasl_types.SASL_MECHANISM]
client_state [Nethttp.HTTP_CLIENT_MECHANISM]
client_user_name [Netsys_sasl_types.SASL_MECHANISM]
The user name
client_user_name [Netmech_scram]
The user name
client_user_name [Nethttp.HTTP_CLIENT_MECHANISM]
The user name
clock_getcpuclockid [Netsys_posix]
Return the ID of a clock that counts the CPU seconds of the given process.
clock_getres [Netsys_posix]
Get the resolution of this clock
clock_gettime [Netsys_posix]
Get the time of this clock
clock_settime [Netsys_posix]
Set the time of this clock
clone [Netcgi.Argument]
close [Netsys_polypipe]
Close the pipe.
close [Netulex.ULB]
Sets ulb_eof of the unicode_lexbuf.
close [Netldap]
Same as synchronous function
close [Netcgi_dbi.DBI_DRIVER]
close_client [Netsys_polysocket]
Closes the client and the endpoint.
close_connection_cache [Nethttp_client]
Closes all descriptors known to the cache
close_e [Netldap]
Close the connection using the close protocol
close_output_thread [Netsys_win32]
Adds the EOF condition to the buffer.
close_process [Netsys_win32]
Closes the handle in the w32_process value, if it is still open
close_server [Netsys_polysocket]
Closes the server.
close_server_socket [Netplex_sockserv]
Closes a socket as opened with create_server_socket
close_shm [Netshm]
Closes the object.
closed [Netcgi_dbi.DBI_DRIVER]
closelog [Netsys_posix]
Closes the log stream
cmd [Shell]
The same as command but with a slightly different interface: Use
 cmd "ls" [ "/dir/file" ] 
instead of
 command ~arguments:[|"/dir/file"|] "ls" 
cmd_interpreter [Shell_fs]
Creates a command interpreter from a function that creates the real command (as pipeline) to execute
cmp_bytes [Netsys_mem]
Compares two strings like String.compare.
cmp_string [Netsys_mem]
A version for immutable strings
code_cmp [Netconversion]
A compare function for ustring_compare: Normal string comparison: This function compares by code point
color [Netsys_mem]
Return the GC color
command [Shell]
Creates a command descriptor, to be used in call.
command [Shell_sys]
Creates a command from the passed arguments:
command_of_process [Shell_sys]
Returns the command that is now running as the process
comment [Nethttp.Cookie]
Returns the comment associated to the cookie or "" if it does not exists.
comment [Netcgi.Cookie]
Returns the comment associated to the cookie or "" if it does not exists.
comment [Netcgi_common.Cookie]
Returns the comment associated to the cookie or "" if it does not exists.
comment_url [Nethttp.Cookie]
Returns the comment URL associated to the cookie or "" if it does not exists.
comment_url [Netcgi.Cookie]
Returns the comment URL associated to the cookie or "" if it does not exists.
comment_url [Netcgi_common.Cookie]
Returns the comment URL associated to the cookie or "" if it does not exists.
commit [Netcgi_dbi.DBI_DRIVER]
common_url_syntax [Neturl]
Syntax descriptions for common URL schemes.
compare [Rpc_proxy.ManagedClient]
ManagedClient can be used with Set.Make and Map.Make
compare [Netoid]
Lexicographic ordering of OIDs
compare [Netldap]
Same as synchronous function
compare_and_swap [Netsys_oothr]
compare_and_swap var old_value new_value: If the variable var is physically identical to old_value it is atomically set to new_value, and true is returned.
compare_e [Netldap]
compare_e conn ~dn ~attr ~value (): returns true if the attribute attr of entry dn has value (according to equality matching)
compile_l9n [Netdate]
Preprocess the localization data for faster parsing and printing
compose [Netsendmail]
Composes a mail message with a main text, and optionally a number of attachments.
concat_mstrings [Netxdr_mstring]
concatenates the mstrings and return them as single string.
concat_mstrings_bytes [Netxdr_mstring]
Same, returning bytes
config [Netsys_crypto_types.TLS_CONFIG]
config_filename [Netplex_main]
Returns the filename of the configuration file, or the default if it has not been set on the command-line
config_filename_opt [Netplex_main]
Returns the filename of the configuration file, or None if it has not been set on the command-line
config_tree_opt [Netplex_main]
Returns the tree of the configuration file, or None if it has not been set by create or modify.
configure [Rpc_client]
configure client retransmissions timeout: sets the number of retransmissions and the timeout for the next calls.
configure [Nethttp_client.Convenience]
Configurations: insecure: whether basic authentication over non-TLS connections is enabled You can only configure before the first user.
configure_channel_binding [Netsys_sasl.Client]
Configure GS2-style channel binding
configure_job_handlers [Shell_sys]
Configures signal and at_exit handlers for jobs: The keyboard signals SIGINT and SIGQUIT are forwarded to all jobs which are running in the background (and thus are not automatically notified) and want to get such signals (forward_signals)., The signals SIGTERM and SIGHUP are (if the handler is installed) forwarded to all dependent processes (regardless whether they are running in their own Unix process group or not, and regardless of forward_signals)., The at_exit handler sends a SIGTERM to all dependent processes, too. In previous versions of Ocamlnet it was also possible to configure catch_sigchld to set whether a SIGCHLD handler is installed.
configure_next_call [Rpc_client]
Same as configure, but it only affects the next call
configure_pipeline [Nethttp_client.Convenience]
This function will be called before the pipeline is used.
conn_bind [Netldap]
Same as synchronous function
conn_bind_e [Netldap]
Bind the connection to credentials
connect [Netsys_polysocket]
Requests the connection with this server.
connect [Netldap]
connect [Netcgi_dbi.DBI_DRIVER]
connect [Uq_client]
connect addr tmo: Runs connect_e for this addr, and returns the result.
connect_check [Netsys]
Tests whether the socket is connected with the peer after calling Unix.connect.
connect_client [Netplex_internal]
connect_client is_kind n name: Creates a new polyclient that is connected to the registered service name.
connect_descr [Netsys_polysocket]
Returns a descriptor that can be used for polling.
connect_e [Netldap]
connect_e [Uq_client]
This engine connects to a socket as specified by the connect_address, optionally using the proxy, and changes to the state `Done(status) when the connection is established.
connect_method [Netftp_client]
This method connects to the host
connection [Netcgi_apache.Apache.Request]
request_rec connection field.
connector [Uq_engines_compat]
connector_of_sockaddr [Rpc_server]
Converts the socket address into a connector
connector_of_sockaddr [Rpc_client]
Converts the socket address into a connector
connector_of_socksymbol [Rpc_server]
Converts the Netsockaddr.socksymbol into a connector
connector_of_socksymbol [Rpc_client]
Converts the Netsockaddr.socksymbol into a connector
const_err_event [Netsys_posix]
const_hup_event [Netsys_posix]
const_nval_event [Netsys_posix]
const_pri_event [Netsys_posix]
const_rd_event [Netsys_posix]
const_wr_event [Netsys_posix]
constant_workload_manager_factory [Netplex_workload]
Reads a workload_manager section like
consume_event [Netsys_posix]
Consumes the event, and switches the event fd to off again.
container [Netsys_sem]
container prefix: The prefix shall identify the container uniquely.
content_type [Netcgi_apache.Apache.Request]
request_rec content_type field.
contents [Netpagebuffer]
Returns the contents as string
contents [Netbuffer]
Returns the contents of the buffer as fresh string.
contents [Netmcore_buffer]
Returns the full contents
convert [Netconversion]
Converts the string from in_enc to out_enc, and returns it.
convert_path [Netfs]
convert_path oldfs newfs oldpath: The encoding of oldpath (which is assumed to reside in oldfs) is converted to the encoding of newfs and returned.
convert_poly [Netconversion]
Polymorphic version
convert_tstring [Netconversion]
Same for tagged strings
copy [Netfs]
copy orig_fs orig_name dest_fs dest_name: Copies the file orig_name from orig_fs to the file dest_name in dest_fs.
copy [Netmcore_heap]
Creates a deep copy of the input value, and stores the duplicate in normal process memory.
copy_command [Shell_sys]
Returns a duplicate of the command description
copy_cursor [Netconversion]
Copies the cursor.
copy_e [Uq_io]
let e = copy_e d_in d_out: Copies data from d_in to d_out, and transitions to `Done n when all data is copied (where n are the number of copied bytes).
copy_env [Shell_sys]
Copies an environment
copy_into [Netfs]
copy_into orig_fs orig_name dest_fs dest_name: Like copy, but this version also supports recursive copies.
copy_mstring [Netxdr_mstring]
Create a copy
copy_mstrings [Netxdr_mstring]
Create a copy
copy_value [Netsys_mem]
copy_value flags v: Creates a deep copy of v and returns it.
cots_connect [Rpc_xti_client]
The first parameter is the name of the TLI/XTI device.
cp_set_env [Netsys_win32]
Returns the CP_set_env option for this array of environment variables (in the Unix.environment format)
create [Rpc_server]
Deprecated creation of an RPC server.
create [Rpc_portmapper]
Connects to the Portmapper/RPCBIND service listening on the given connector.
create [Rpc_simple_client]
Create a simple client that connects with the given server using the given protocol type.
create [Rpc_client]
Opens a connection to the server specified by the connector.
create [Rpc_program]
create program_nr version_nr type_system procedures
create [Netsys_polypipe]
Create a new polypipe with an internal buffer of n messages.
create [Netsys_crypto_types.DIGESTS]
Creates a fresh context
create [Netsys_crypto_types.SYMMETRIC_CRYPTO]
create c key: create a new cipher context for key.
create [Netpagebuffer]
create blocksize: creates new buffer with this blocksize, which must be a whole multiple of the page size of the OS
create [Netdate]
Convert the time (seconds since the epoch) to a date/time record
create [Netbuffer]
Creates a netbuffer which allocates initially this number of bytes.
create [Netplex_mbox.MBOX]
Creates a new mailbox with the passed name, or opens an existing mailbox.
create [Netplex_semaphore]
Create the semaphore with this initial value.
create [Netplex_main]
Creates the command-line configuration object.
create [Netmcore_hashtbl]
Hashtbl.create pool h creates a new, empty hash table in pool with a header h.
create [Netmcore_matrix]
create pool_id n2 a h: Creates a matrix by deeply copying a normal array a and using the copy of h as header.
create [Netmcore_buffer]
create pool bsize h: Creates a buffer in pool with a block size of bsize.
create [Netmcore_queue]
create pool h: Creates an empty queue in the pool, with header h
create [Netmcore_mutex]
create m t: Creates a mutex of type t, and pushes it to the heap, using the mutator m.
create [Netmcore_sem]
create m value: Creates a semaphore with initial value, and pushes it to the heap, using the mutator m.
create [Netmcore_array]
create pool_id a h: Creates a shared array by deeply copying a normal array a and using the copy of h as header
create [Uq_libevent.LIBOEVENT]
create [Equeue]
Creates a new event system that has an event source, but is otherwise empty.
create2 [Rpc_server]
Creates a server according to the mode2 argument.
create2 [Rpc_client]
New style clients: Opens a connection to the server specified by mode2.
create_address_list_tokens [Netsendmail]
Returns the list of s_tokens representing email addresses as structured value.
create_admin_container [Netplex_container]
Internally used.
create_aggressive_cache [Nethttp_client]
This type of cache tries to keep connections as long open as possible.
create_boundary [Netmime_string]
Creates a boundary string that can be used to separate multipart messages.
create_camlbox [Netmcore_camlbox]
create_camlbox prefix n size: Creates a new camlbox with a unique name derived from prefix.
create_camlbox [Netcamlbox]
create_camlbox addr n size: Creates a new camlbox for up to n messages of size bytes.
create_client [Netsys_polysocket]
Create a new socket client.
create_client_config [Netsys_gssapi]
mech_type is the GSSAPI mechanism to use.
create_client_session [Netsys_sasl_types.SASL_MECHANISM]
The new client session authenticate as user and authorizes as authz (empty string if not applicable).
create_client_session [Netmech_scram]
create_client_session p username password: Creates a new client session for profile p so that the client authenticates as user username, and proves its identity with the given password.
create_client_session [Nethttp.HTTP_CLIENT_MECHANISM]
The new client session authenticate as user.
create_client_session2 [Netmech_scram]
create_client_session p username authzname password: Like create_client_session, but also sets the authorization name (only processed for the SASL profile).
create_condition [Netmcore_condition]
create m: Creates a condition variable, and pushes it to the heap, using the mutator m.
create_config [Netsys_crypto_types.TLS_PROVIDER]
The configuration includes:
create_constant_workload_manager [Netplex_workload]
A constant number of threads is created (the int argument).
create_container [Netsys_sem]
create_container prefix: Like container, but the container is always created.
create_container [Netplex_container]
The container for normal services
create_controller [Netplex_controller]
Create a controller with the default event system
create_controller_for_esys [Netplex_controller]
Create a controller for the passed event system
create_cursor [Netconversion]
Creates a new cursor for the passed string and the passed encoding.
create_dynamic_workload_manager [Netplex_workload]
create_endpoint [Netsys_crypto_types.TLS_PROVIDER]
Creates a new endpoint for this configuration.
create_env [Shell_sys]
Creates an empty environment
create_event [Netsys_win32]
Create an event object
create_event [Netsys_posix]
Creates a new event file descriptor.
create_event_aggregator [Netsys_posix]
create_event_aggregator is_interruptible: Creates a new aggregator, and allocates the required OS resources.
create_event_system [Uq_libevent.POLLSET]
create_file_endpoint [Netsys_tls]
create_file_endpoint ~role ~rd ~wr ~peer_name tls_config: Creates a new TLS endpoint (encapsulated as module, together with the provider) for the case that the data flows over file descriptors.
create_heap [Netmcore_heap]
create_heap pool_id size root: Creates a new heap with size bytes in the pool identified by pool_id.
create_in_buffer [Uq_io]
Provides a buffered version of the in_device.
create_inet [Rpc_portmapper]
Connects to a Portmapper/RPCBIND listening on an Internet port.
create_inet_uaddr [Rpc]
Create an universal address from an internet addr and a port
create_input_netbuffer [Netchannels]
Creates an input channel and a shutdown function for a netbuffer.
create_input_thread [Netsys_win32]
Creates the input thread for this file descriptor.
create_local [Rpc_portmapper]
Connects to the local Portmapper/RPCBIND daemon.
create_local_pipe_server [Netsys_win32]
create_mclient [Rpc_proxy.ManagedClient]
Create a managed client for this config connecting to this connector.
create_mclient_config [Rpc_proxy.ManagedClient]
create_mempool [Netmcore_mempool]
Creates the memory pool as shared memory object of the passed size (rounded up to the next multiple of pages) and returns the resource ID.
create_mic_token [Netgssapi_support]
Create a MIC token:
create_mime_scanner [Netmime_string]
Creates a new mime_scanner scanning the passed string.
create_monitor [Uq_mt]
Creates a new monitor.
create_mset [Rpc_proxy.ManagedSet]
create_mset config services: The mset is created with config, and the services array describes which ports are available, and how often each port may be contacted (i.e.
create_mset_config [Rpc_proxy.ManagedSet]
Create a config record.
create_multiplex_controller_for_connected_socket [Uq_engines_compat]
create_multiplex_controller_for_connected_socket [Uq_multiplex]
Creates a multiplex controller for a bidirectional socket (e.g.
create_multiplex_controller_for_datagram_socket [Uq_engines_compat]
create_multiplex_controller_for_datagram_socket [Uq_multiplex]
Creates a multiplex controller for datagram sockets (e.g.
create_out_buffer [Uq_io]
Provides a buffered version of the out_device.
create_output_thread [Netsys_win32]
Creates the output thread for this file descriptor.
create_poll_array [Netsys_posix]
Create a poll array with the given size.
create_pollset [Uq_libevent.POLLSET]
create_poly_cursor [Netconversion]
Polymorphic version
create_pool [Netsys_mem]
Create a new pool.
create_preallocated_shm [Netmcore]
create_preallocated_shm prefix size: Creates a new preallocated shm object with a unique name based on prefix, and a length of size bytes.
create_preallocated_shm_sc [Netmcore]
Same as create_preallocated_shm with the extension that a semaphore container is also allocated and returned
create_process [Netsys_win32]
create_process cmd cmdline options: Spawns a new process that runs concurrently with the calling process.
create_protocol [Netplex_kit]
create_protocol name addresses: Creates a protocol object from the passed arguments
create_rcache [Rpc_proxy.ReliabilityCache]
Creates a new cache object.
create_rcache_config [Rpc_proxy.ReliabilityCache]
Create a config record.
create_restrictive_cache [Nethttp_client]
A restrictive cache closes connections as soon as there are no pending requests.
create_rsaes_oaep_alg_id [Netx509_pubkey.Key]
create_rsaep_oaep_alg_id ... : Creates an algorithm identifier for RSAES-OAEP.
create_rsaes_oaep_key [Netx509_pubkey.Key]
Derives a public key that is specific for RSAES-OAEP from an RSA public key.
create_rsassa_pss_alg_id [Netx509_pubkey.Key]
create_rsassa_pss_alg_id ... : Creates an algorithm identifier for RSASSA-PSS.
create_rsassa_pss_key [Netx509_pubkey.Key]
Derives a public key that is specific for RSASSA-PSS from an RSA public key.
create_salt [Netmech_scram]
Creates a random string suited as salt
create_server [Netsys_polysocket]
Create a new socket server.
create_server_config [Netsys_gssapi]
mech_types is the list of GSSAPI mechanism that are acceptable.
create_server_session [Netsys_sasl_types.SASL_MECHANISM]
Create a new server session.
create_server_session [Netmech_scram]
create_server_session p auth: Creates a new server session with profile p and authenticator function auth.
create_server_session2 [Netmech_scram]
Same as create_server_session, but the authentication callback gets two arguments:
create_server_socket [Netplex_sockserv]
create_server_socket service_name proto addr: Creates a server socket as specified in proto for the address addr and returns it.
create_session [Netsys_sasl.Server]
Create a new server session.
create_session [Netsys_sasl.Client]
The new client session authenticate as user and authorizes as authz (empty string if not applicable).
create_socket_service [Netplex_sockserv]
Create the socket service (usually only internally used)
create_socket_service_config [Netplex_kit]
create_socket_service_config name protos ctrl_conf: Creates a socket_service_config object from the passed arguments
create_text_tokens [Netsendmail]
Returns the list of s_tokens representing an informal text as structured value.
create_timer [Netplex_cenv]
create_timer f tmo: Creates a timer with timeout value tmo: In tmo seconds f is called, and if this function returns true, the timer remains active, and another round of timing is arranged.
create_unique_shm [Netshm]
Create a shared memory object under a name that is derived from the passed shm_name.
create_unix_event_system [Unixqueue]
An alternate name for standard_event_system, provided for backward compatibility.
create_var [Netplex_sharedvar]
Create the variable with the passed name with an empty string (or the exception Sharedvar_null) as initial value.
create_wait_set [Netmcore_condition]
Creates a wait_set in the heap designated by the mutator
create_wrap_token_conf [Netgssapi_support]
Wraps a message so that it is encrypted and signed (confidential).
create_x509_config [Netsys_tls]
The configuration includes:
create_x509_credentials [Netsys_crypto_types.TLS_PROVIDER]
Create X.509 credentials from individual objects: system_trust: if set, the system certificates are trusted, trust specifies the CAs of peers to trust (default: empty), revoke specifies CRLs for revocation of peer certificates (default: empty), keys are our own certificates, as triples (cert_path, private_key, password) (default: empty) A client should set trust to the list of CAs it can accept on the server side.
ctermid [Netsys_posix]
Returns the name of the controlling tty of the current process as pathname to a device file
ctr_of_ecb [Netsys_crypto_modes.Symmetric_cipher]
For a given cipher in ECB mode, a new cipher in CTR mode is returned.
ctrl_increment [Netplex_semaphore]
Increment the named semaphore from controller context, substituting an increment from a container (e.g.
current_digests [Netsys_crypto]
Returns the current provider for cryptographic digests.
current_dlogger [Netlog.Debug]
The current debug logger.
current_env [Shell_sys]
Returns the environment of the current process as abstract environment value
current_formatter [Netlog]
The current timestamp formatter
current_logger [Netlog]
The variable containing the current logger function.
current_pubkey_crypto [Netsys_crypto]
Returns the current provider for public key cryptography.
current_resolver [Uq_resolver]
Returns the pluggable resolver.
current_symmetric_crypto [Netsys_crypto]
Returns the current provider for symmetric cryptography.
current_sys_id [Netplex_cenv]
Returns the system-dependent thread identifier of the caller (which must be in container or controller context)
current_tls [Netsys_crypto]
Return the current TLS provider.
current_tls_opt [Netsys_crypto]
Same as current_tls but it returns None if TLS is unavailable
cursor_at_end [Netconversion]
Returns whether the cursor is positioned past the last character.
cursor_blit [Netconversion]
cursor_blit cs ua pos len: Copies at most len characters as code points from the cursor position and the following positions to the array ua at index pos.
cursor_blit_maxlen [Netconversion]
Returns the maximum number of characters cursor_blit can copy at the current cursor position.
cursor_blit_positions [Netconversion]
Works like cursor_blit, but copies the byte positions of the characters into ua instead of the code points.
cursor_byte_length [Netconversion]
Returns the byte length of the representation of the character at the cursor.
cursor_char_count [Netconversion]
Returns the character count of the cursor.
cursor_encoding [Netconversion]
Returns the encoding of the cursor.
cursor_initial_rel_pos [Netconversion]
Returns the initial relative byte position of the cursor
cursor_pos [Netconversion]
Returns the byte position of the cursor, i.e.
cursor_range [Netconversion]
Returns the valid range of the cursor as pair (range_pos, range_len)
cursor_target [Netconversion]
Returns the string of the cursor

D
datagram_provider [Uq_engines_compat]
datagram_provider [Uq_datagram]
This engine creates a datagram socket as demanded by the datagram_type, optionally using proxy for sending and receiving datagrams.
datagram_rpc_multiplex_controller [Rpc_transport]
The multiplex controller for datagrams ((D)TLS not yet supported)
debug_c_wrapper [Netsys_win32.Debug]
Sets whether to debug the C wrapper part.
debug_info [Netmcore_heap]
Returns a multi-line debug string
debug_info [Netmcore_mempool]
Returns a string describing the allocations etc.
debug_rpc_internals [Rpc_netplex]
debug_rpc_service [Rpc_netplex]
These variables control debugging of Rpc_server.
decode [Nethtml]
Converts entities &name; and &#num; into the corresponding characters.
decode [Netencoding.Html]
The input string is recoded from in_enc to out_enc, and HTML entities (&name; or &#num;) are resolved.
decode [Netencoding.Url]
Option plus: Whether '+' is converted to space.
decode [Netencoding.Q]
Q-decode a string
decode [Netencoding.QuotedPrintable]
Decodes the string and returns it.
decode [Netencoding.Base64]
Decodes the given string argument.
decode_ber [Netasn1]
Decodes a BER-encoded ASN.1 value.
decode_ber_contents [Netasn1]
Decodes the BER-encoded contents of a data field.
decode_ber_contents_poly [Netasn1]
Polymorphic version
decode_ber_contents_tstring [Netasn1]
Same for tagged strings
decode_ber_header [Netasn1]
let (hdr_len, tc, pc, tag, len_opt) = decode_ber_header s: Decodes only the header: hdr_len will be the length of the header in bytes, tc is the tag class, pc whether primitive or constructed, tag is the numeric tag value, len_opt is the length field, or None if the header selects indefinite length If skip_length_check is set, the function does not check whether the string is long enough to hold the whole data part.
decode_ber_header_poly [Netasn1]
Polymorphic version
decode_ber_header_tstring [Netasn1]
Same for tagged strings
decode_ber_length [Netasn1]
Like decode_ber, but returns only the length.
decode_ber_length_poly [Netasn1]
Polymorphic version
decode_ber_length_tstring [Netasn1]
Same for tagged strings
decode_ber_poly [Netasn1]
polymorphic version
decode_ber_tstring [Netasn1]
Same for tagged strings
decode_exported_name [Netgssapi_support]
Encode names as described in section 3.2 of RFC 2078
decode_mime_body [Netmime_channels]
let ch' = decode_mime_body hdr ch: According to the value of the Content-transfer-encoding header field in hdr the encoded MIME body written to ch' is decoded and transferred to ch.
decode_poly [Netencoding.Html]
Fully polymorphic version
decode_poly [Netencoding.Q]
Polymorphic version
decode_poly [Netencoding.QuotedPrintable]
Polymorphic version
decode_poly [Netencoding.Base64]
Polymorphic version
decode_pubkey_from_der [Netx509_pubkey]
Decodes a DER-encoded public key info structure.
decode_query [Nethttp]
Splits the URI into a "script name" and a "query string"
decode_to_latin1 [Netencoding.Html]
decode_tstring [Netencoding.Html]
This version takes a tstring argument, and returns the string type chosen by the out_kind arg.
decode_tstring [Netencoding.Q]
Same for tagged string inputs.
decode_tstring [Netencoding.QuotedPrintable]
Same for tagged string inputs.
decode_tstring [Netencoding.Base64]
Same for tagged string inputs.
decrement [Netplex_semaphore]
Decrement the named semaphore by 1, and return the new value.
decrypt [Netsys_crypto_types.PUBKEY_CRYPTO]
decrypt [Netsys_crypto_types.SYMMETRIC_CRYPTO]
decrypt cctx inbuf outbuf: Decrypts the data in inbuf and writes the result into outbuf.
decrypt [Netx509_pubkey_crypto]
Decrypt the string
decrypt [Netmech_scram.AES_CTS]
decrypt_and_verify [Netmech_scram.Cryptosystem]
Decrypts the ciphertext and verifies the attached signature.
decrypt_and_verify_mstrings [Netmech_scram.Cryptosystem]
Same, but with data representation as mstring list
decrypt_in [Netchannels_crypto]
let ch2 = decrypt_in ctx ch1: Reading from ch2 decrypts the data from ch1.
decrypt_mstrings [Netmech_scram.AES_CTS]
decrypt_out [Netchannels_crypto]
let ch2 = decrypt_out ctx ch1: Writing to ch2 decrypts the data and writes the plaintext to ch1.
def_process [Netmcore_process]
let (fp,jp) = def_process proc: Defines a process (which must happen in the master process), so that:
def_process [Netmcore]
let fork_point, join_point = def_process f: Defines process types, i.e.
default_block_size [Netsys_mem]
The default block size, normally 64 K (or better, 16 times the page size)
default_config [Netcgi1_compat.Netcgi_env]
default_config [Netcgi]
The default configuration is: tmp_directory: Netsys_tmp.tmp_directory(), tmp_prefix: "netcgi", permitted_http_methods: `GET, `HEAD, `POST., permitted_input_content_types: "multipart/form-data", "application/x-www-form-urlencoded"., input_content_length_limit: maxint (i.e., no limit)., max_arguments = 10000 (for security reasons), workarounds: all of them., default_exn_handler: set to true. To create a custom configuration, it is recommended to use this syntax:
      let custom_config = { default_config with tmp_prefix = "my_prefix" }
      
(This syntax is also robust w.r.t.
default_connect_options [Uq_engines_compat]
default_connect_options [Uq_client]
Returns the default options
default_host [Nethttpd_services]
Creates a host record that matches any request.
default_http_engine_config [Nethttpd_engine]
The default config: config_input_flow_control=false, config_output_flow_control=true
default_http_processor_config [Nethttpd_reactor]
Default configuration: Extends Nethttpd_kernel.default_http_protocol_config with config_timeout_next_request = 15.0, config_timeout = 300.0, config_cgi = Netcgi.default_config, config_error_response = Nethttpd_util.std_error_response, config_log_error: Uses Nethttpd_util.std_error_log_string to write a log message via Netlog., config_log_access: is a no-op, config_tls_cert_props: is true, config_tls_remote_user: is true
default_http_protocol_config [Nethttpd_kernel]
Default config: config_max_reqline_length = 32768, config_max_header_length = 65536, config_max_trailer_length = 32768, config_limit_pipeline_length = 5, config_limit_pipeline_size = 65536, config_announce_server = `Ocamlnet, config_suppress_broken_pipe = false, config_tls = None
default_http_reactor_config [Nethttpd_reactor]
Default configuration: Extends Nethttpd_reactor.default_http_processor_config with config_reactor_synch = `Write
default_listen_options [Uq_engines_compat]
default_listen_options [Uq_server]
Returns the default options
default_pool [Netsys_mem]
The default pool with the default block size.
default_resolver [Uq_resolver]
The default resolver uses Unix.gethostbyname to look up names.
default_services [Nethttpd_plex]
The default services
default_socket_config [Rpc_server]
default_socket_config [Rpc_client]
Default configuration with non_blocking_connect = true
default_url [Neturl]
Adds missing components and returns the modified URL.
default_value [Netshm_array]
Returns the default value
del [Uq_libevent.LIBOEVENT]
del_event_source [Netsys_posix]
Removes the source from the aggregator
delay_engine [Uq_engines_compat]
delay_engine [Uq_engines]
Same as function
deleg_credential [Netmech_spnego_http.PROFILE]
If you already have a credential, you can set this value to the exception Credential c (from the GSSAPI provider).
delete [Netulex.ULB]
Deletes the number of characters from unicode_lexbuf.
delete [Netbuffer]
delete nb k n: Deletes the n bytes at position k of netbuffer nb in-place.
delete [Netldap]
Same as synchronous function
delete_context [Netgssapi_auth.Manage]
Deletes the context, ignoring any error
delete_e [Netldap]
delete_e conn ~dn: Deletes the entry dn
delete_hd [Netpagebuffer]
delete_hd b n: Deletes n bytes from the beginning of the buffer
delete_hd [Netmcore_buffer]
delete_hd b n: Deletes n bytes from the beginning of the buffer.
delete_method [Netftp_client]
Deletes the named file
delete_var [Netplex_sharedvar]
delete_var name: Deletes the variable name.
der_of_oid [Netgss_bindings]
der_to_oid [Netgssapi_support]
Convert OID's to/from DER.
der_value_to_oid [Netgssapi_support]
Convert OID's to/from DER.
deref [Netmcore_matrix]
Returns the raw array in shared memory for unprotected access
deref [Netmcore_array]
Returns the raw array in shared memory for unprotected access
deref_c [Netmcore_ref]
deref_c sr: Returns a copy of the contents of sr.
deref_p [Netmcore_ref]
deref_p sr f: Runs f with the contents of sr, and returns the result of f.
deref_ro [Netmcore_ref]
Dereferences the variable and returns the contents, comparable to !.
derive_key_rfc3961_simplified [Netauth]
Derives a special key from a base key, as described in RFC 3961.
derive_keys [Netmech_scram.Cryptosystem]
derive_keys protocol_key usage: Returns the specific keys for this protocol_key and this usage numbers.
derive_rcache [Rpc_proxy.ReliabilityCache]
derive_cache parent config: Returns a new cache that shares the error counters with parent.
descr_of_buffer [Netmcore_buffer]
Returns the descriptor
descr_of_hashtbl [Netmcore_hashtbl]
Returns the descriptor
descr_of_heap [Netmcore_heap]
Get the descriptor of a heap
descr_of_sarray [Netmcore_array]
Returns the descriptor
descr_of_sarray2 [Netmcore_matrix]
Returns the descriptor
descr_of_squeue [Netmcore_queue]
Returns the descriptor
descr_of_sref [Netmcore_ref]
Returns the descriptor
dest_fp4 [Netnumber]
dest_fp8 [Netnumber]
dest_int4 [Netnumber]
dest_int8 [Netnumber]
dest_uint4 [Netnumber]
dest_uint8 [Netnumber]
dest_<t> destroy integer values and returns the corresponding char tuples.
dest_url_encoded_parameters [Netencoding.Url]
The argument is the URL-encoded parameter string.
dest_xv_array [Netxdr]
dest_xv_array_of_string_fast [Netxdr]
dest_xv_double [Netxdr]
dest_xv_enum [Netxdr]
dest_xv_enum_fast [Netxdr]
dest_xv_float [Netxdr]
dest_xv_hyper [Netxdr]
dest_xv_int [Netxdr]
dest_xv_mstring [Netxdr]
dest_xv_opaque [Netxdr]
dest_xv_string [Netxdr]
dest_xv_struct [Netxdr]
dest_xv_struct_fast [Netxdr]
dest_xv_uhyper [Netxdr]
dest_xv_uint [Netxdr]
dest_xv_union_over_enum [Netxdr]
dest_xv_union_over_enum_fast [Netxdr]
dest_xv_union_over_int [Netxdr]
dest_xv_union_over_uint [Netxdr]
dest_xv_void [Netxdr]
destroy [Netplex_semaphore]
Destroy this semaphore.
destroy [Netmcore_buffer]
Destroys the buffer
destroy [Netmcore_mutex]
Destroys the mutex
destroy [Netmcore_sem]
Destroys the semaphore
destroy [Netmcore_heap]
Destroys the heap and gives the memory back to the pool
destroy_condition [Netmcore_condition]
destroy_event [Netsys_posix]
Releases the OS resources.
destroy_event_aggregator [Netsys_posix]
Frees all OS resources
destroy_resources [Netmcore]
Destroys all resources that may be left
destroy_wait_set [Netmcore_condition]
Destroys these objects
detach [Rpc_server]
Internal function.
device_supports_memory [Uq_io]
Returns whether `Memory buffers are supported
dh [Netx509_pubkey.Keyagreement]
DH
dh_key [Netx509_pubkey.Key]
DH.
digest_bytes [Netsys_digests]
Digest a string
digest_mstrings [Netsys_digests]
Digest a sequence of mstrings
digest_string [Netsys_digests]
Digest a string
digest_tstring [Netsys_digests]
Digest a string
digests [Netsys_digests]
List of supported digests
digests [Netsys_crypto_types.DIGESTS]
returns digests
dim [Netmcore_matrix]
Returns the dimenstions
directory_string_from_ASN1 [Netx509]
Returns the directory_string as UTF-8
disable [Netunidata]
Disables the dynamic loader
disable_all [Netlog.Debug]
Disable all modules (the default)
disable_for_client [Rpc_client.Debug]
Disables all log messages for this client (internally used)
disable_for_server [Rpc_server.Debug]
Disables logging for this server
disable_module [Netlog.Debug]
Enable or disable the passed module M (e.g.
discard_request_body [Netcgi_apache.Apache.Request]
Discard client request body.
domain [Nethttp.Cookie]
The domain of the cookie, if set.
domain [Netcgi.Cookie]
The domain of the cookie, if set.
domain [Netcgi_common.Cookie]
domain_of_inet_addr [Netsys]
Returns the socket domain of Internet addresses, i.e.
downcast [Nettls_gnutls]
Attempts a downcast, or raises Not_found
downcast_endpoint [Nettls_gnutls]
Attempts a downcast, or raises Not_found
drop [Netsys_sem]
Drop the semaphores in this container, and delete the container.
dsa_key [Netx509_pubkey.Key]
DSA.
dsa_with_sha1 [Netx509_pubkey.Signing]
DSA
dsa_with_sha224 [Netx509_pubkey.Signing]
dsa_with_sha256 [Netx509_pubkey.Signing]
dummy [Netmcore_mutex]
A dummy mutex is non-functional, but can be used to put something into mutex-typed variables
dummy [Netmcore_sem]
A dummy semaphore is non-functional, but can be used to put something into semaphore-typed variables
dummy_condition [Netmcore_condition]
A dummy condition is non-functional, but can be used to put something into condition-typed variables
dummy_wait_set [Netmcore_condition]
A dummy wait_set is non-functional, but can be used to put something into wait_set-typed variables
dump [Rpc_portmapper]
returns the list of known mappings.
dump [Netshm]
dump [Netplex_sharedvar]
Dumps the access counter of this variable to Netlog.
dump'async [Rpc_portmapper]
dynamic_service [Nethttpd_services]
Configures the dynamic service.
dynamic_workload_manager_factory [Netplex_workload]
Reads a workload_manager section like

E
ec [Netx509_pubkey.Keyagreement]
ECDH using unrestricted keys
ec_key [Netx509_pubkey.Key]
All EC variants (ECDSA, ECDH, ECMQV).
ecdh [Netx509_pubkey.Keyagreement]
ECDH
ecdh_key [Netx509_pubkey.Key]
EC restricted to ECDH (RFC-5480)
ecdsa_with_sha1 [Netx509_pubkey.Signing]
ECDSA
ecdsa_with_sha224 [Netx509_pubkey.Signing]
ecdsa_with_sha256 [Netx509_pubkey.Signing]
ecdsa_with_sha384 [Netx509_pubkey.Signing]
ecdsa_with_sha512 [Netx509_pubkey.Signing]
ecmqv [Netx509_pubkey.Keyagreement]
ECMQV
ecmqv_key [Netx509_pubkey.Key]
EC restricted to ECMQV (RFC-5480)
eddsa [Netx509_pubkey.Signing]
EDDSA.
eddsa_key [Netx509_pubkey.Key]
EDDSA.
emit_challenge [Netsys_sasl.Server]
Emit a server challenge.
emit_response [Netsys_sasl.Client]
Emit a new response.
emulated_pid [Netsys_win32]
Returns the MSVCRT.DLL notion of the process identifier (pid).
enable [Shell_sys.Debug]
Enables Netlog-style debugging of this module
enable [Rpc_auth_gssapi.Debug]
enable [Rpc_server.Debug]
Whether debug messages of general kind are enabled.
enable [Rpc_client.Debug]
Whether debug messages are enabled.
enable [Rpc_transport.Debug]
Enables Netlog-style debugging
enable [Netunidata]
Enables the dynamic loader.
enable [Netsys_polypipe.Debug]
Enables Netlog-style debugging
enable [Netsys_tls.Debug]
enable [Netsys_sem.Debug]
enable [Netsys_signal.Debug]
Enables Netlog-style debugging of this module
enable [Netsys_pollset_win32.Debug]
Enables Netlog-style debugging of this module
enable [Netsys_win32.Debug]
Enables Netlog-style debugging of the Ocaml wrapper
enable [Netsys_posix.Debug]
Enables Netlog-style debugging
enable [Netsys.Debug]
Enables Netlog-style debugging
enable [Netmech_scram.Debug]
Enable debugging of this module
enable [Netstring_str.Debug]
enable [Netplex_cenv.Debug]
Enables Netlog-style debugging
enable [Netplex_container.Debug]
Enables debug logging of containers
enable [Netplex_controller.Debug]
enable [Netmcore_condition.Debug]
enable [Netmcore_heap.Debug]
enable [Netmcore_mempool.Debug]
Enable debugging
enable [Netmcore.Debug]
enable [Nethttpd_services.Debug]
enable [Nethttpd_engine.Debug]
Enables Netlog-style debugging of this module
enable [Nethttpd_reactor.Debug]
Enables Netlog-style debugging of this module
enable [Nethttpd_kernel.Debug]
Enables Netlog-style debugging of this module
enable [Netldap.Debug]
Enables Netlog-style debugging of this module
enable [Netpop.Debug]
Enables Netlog-style debugging of this module By default, the exchanged Telnet commands are logged.
enable [Netsmtp.Debug]
Enables Netlog-style debugging of this module By default, the exchanged Telnet commands are logged.
enable [Netftp_client.Debug]
Enables Netlog-style debugging of this module
enable [Nettelnet_client.Debug]
Enables Netlog-style debugging of this module By default, the exchanged Telnet commands are logged.
enable [Nethttp_client.Debug]
Enables Netlog-style debugging of this module
enable [Netcamlbox.Debug]
enable [Uq_engines_compat.Debug]
enable [Uq_engines.Debug]
Enables Netlog-style debugging
enable [Unixqueue.Debug]
Enable Netlog debugging
enable [Equeue.Debug]
Enable Netlog debugging
enable_all [Netlog.Debug]
Enable all modules
enable_alloc [Netmcore_mempool.Debug]
Trace allocation and deallocation
enable_ctrace [Rpc_server.Debug]
Whether debug messages are enabled that trace connection events.
enable_delegation [Netmech_spnego_http.PROFILE]
Whether to allow delegation of the credentials to the server.
enable_fd_tracking [Netlog.Debug]
By setting to true, each track_fd and release_fd is logged.
enable_module [Netlog.Debug]
enable_ptrace [Rpc_server.Debug]
Whether the procedure trace is enabled.
enable_ptrace [Rpc_client.Debug]
Whether the procedure trace is enabled as debug messages.
encode [Nethtml]
Converts problematic characters to their corresponding entities.
encode [Netencoding.Html]
The input string that is encoded as in_enc is recoded to out_enc, and the following characters are encoded as HTML entity (&name; or &#num;): The ASCII characters contained in unsafe_chars, The characters that cannot be represented in out_enc. By default (out_enc=`Enc_usascii), only ASCII characters can be represented, and thus all code points >= 128 are encoded as HTML entities. If you pass out_enc=`Enc_utf8, all characters can be represented. For example, the string "(a<b) & (c>d)" is encoded as "(a&lt;b) &amp; (c&gt;d)".
encode [Netencoding.Url]
Option plus: Whether spaces are converted to '+'.
encode [Netencoding.Q]
Note: All characters except alphanumeric characters are protected by hex tokens.
encode [Netencoding.QuotedPrintable]
Encodes the string and returns it.
encode [Netencoding.Base64]
Compute the "base 64" encoding of the given string argument.
encode_ber [Netasn1_encode]
Appends a BER encoding of the value to the buffer (including the header).
encode_ber_contents [Netasn1_encode]
Appends a BER encoding of the value to the buffer (excluding the header).
encode_exported_name [Netgssapi_support]
encode_from_latin1 [Netencoding.Html]
encode_mime_body [Netmime_channels]
let ch' = encode_mime_body hdr ch: According to the value of the Content-transfer-encoding header field in hdr the unencoded MIME body written to ch' is encoded and transferred to ch.
encode_poly [Netencoding.Html]
Fully polymorphic version
encode_poly [Netencoding.Q]
Polymorphic version
encode_poly [Netencoding.QuotedPrintable]
Polymorphic version
encode_poly [Netencoding.Base64]
Polymorphic version
encode_pubkey_to_der [Netx509_pubkey]
Encodes a public key info structure as DER
encode_tstring [Netencoding.Html]
This version takes a tstring argument, and returns the string type chosen by the out_kind arg.
encode_tstring [Netencoding.Q]
Same for tagged string inputs.
encode_tstring [Netencoding.QuotedPrintable]
Same for tagged string inputs.
encode_tstring [Netencoding.Base64]
Same for tagged string inputs.
encoding_of_glob_expr [Netglob]
Returns the encoding
encoding_of_string [Netconversion]
Returns the encoding of the name of the encoding.
encrypt [Netsys_crypto_types.PUBKEY_CRYPTO]
encrypt [Netsys_crypto_types.SYMMETRIC_CRYPTO]
encrypt cctx inbuf outbuf: Encrypts the data in inbuf and writes the result into outbuf.
encrypt [Netx509_pubkey_crypto]
Encrypt the string.
encrypt [Netmech_scram.AES_CTS]
encrypt_alg_of_pubkey [Netx509_pubkey.Encryption]
Normally use the algorithm that is present in the public key
encrypt_and_sign [Netmech_scram.Cryptosystem]
Encrypts the plaintext message and adds a signature to the ciphertext.
encrypt_and_sign_mstrings [Netmech_scram.Cryptosystem]
Same, but with data representation as mstring list
encrypt_in [Netchannels_crypto]
let ch2 = encrypt_in ctx ch1: Reading from ch2 encrypts the data from ch1.
encrypt_mstrings [Netmech_scram.AES_CTS]
encrypt_out [Netchannels_crypto]
let ch2 = encrypt_out ctx ch1: Writing to ch2 encrypts the data and writes the ciphertext to ch1.
endpoint [Nettls_gnutls.GNUTLS_ENDPOINT]
endpoint [Nettls_gnutls]
Wraps an endpoint
endpoint [Netsys_polysocket]
Returns the endpoint once connected.
endpoint [Netsys_tls]
Coercion
endpoint [Netsys_crypto_types.FILE_TLS_ENDPOINT]
endpoint [Netsys_crypto_types.TLS_ENDPOINT]
enforce_unavailability [Rpc_proxy.ManagedClient]
Enforces that all pending procedure calls get the Service_unavailable exception, and that the client is shut down.
ensure_absolute_url [Neturl]
If the anonymous URL is absolute, it is just returned as result of this function.
eof [Netsys_polypipe]
whether the eof marker was sent.
eof_as_none [Uq_io]
Represents EOF as None.
eps_e [Uq_engines_compat.Operators]
eps_e [Uq_engines.Operators]
Same as epsilon_engine
epsilon [Unixqueue]
The execution of the function is pushed onto the event queue (minimal delay)
epsilon_engine [Uq_engines_compat]
epsilon_engine [Uq_engines]
Same as function
equal [Netoid]
Whether two OIDs are equal
equal [Netasn1.Value]
Checks for equality.
err_headers_out [Netcgi_apache.Apache.Request]
request_rec err_headers_out field.
error_message [Netsys_tls]
Returns the message for humans (display, log files etc.) when called with an error or warning symbol.
error_message [Netsys_crypto_types.TLS_PROVIDER]
Returns the message for humans (display, log files etc.) when called with an error or warning symbol.
error_of_exn [Netmech_scram]
Converts one of the above exceptions to a human-readable string
error_page [Netcgi_common]
error_page env status fields msg detail: Logs an error message and outputs an error page via env.
event_aggregator_fd [Netsys_posix]
Returns the underlying file descriptor.
event_descr [Netsys_win32]
Returns the proxy descriptor for the event.
event_system [Rpc_proxy.ManagedSet]
Return the event system
event_system [Rpc_proxy.ManagedClient]
Return the event system
event_system [Rpc_client]
Returns the unixqueue to which the client is attached
event_wait [Netsys_win32]
Wait until the event is set to signaled state.
execute [Shell_fs]
Starts this command.
exists_resource [Unixqueue]
Find out if a specific resource already exists (or better: is already watched by an operation).
exn_handler_default [Netcgi_common]
exn_handler_default env ~exn_handler ~finally run_cgi will basically execute exn_handler env run_cgi.
expand_glob_expr [Netglob]
Resolve generative sub expressions by expanding them.
expanded_xdr_type [Netxdr]
expanded_xdr_type_term [Netxdr]
ext_key_purposes [Netx509.KP]
extract [Netsys_crypto_modes.Symmetric_cipher]
extract scrypto (name,mode): returns the cipher called name in mode as scipher, or raises Not_found
extract_all [Netsys_crypto_modes.Symmetric_cipher]
Extracts all ciphers
extract_call_gssapi_header [Rpc_packer]
returns the length of the prefix of the message so that the prefix includes the header until (and including) the credentials.
extract_config [Netplex_controller]
Extracts the controller config
extract_url_scheme [Neturl]
Returns the URL scheme from the string representation of an URL.

F
faccessat [Netsys_posix]
Same as Unix.access but the file is taken relative to the directory given by first argument
factory [Netcgi_plex]
Reads a Netplex configuration section like
    processor {
      type = "netcgi";          (* or the overridden [name] *)
      timeout = 15;             (* optional *)
      mount_dir = "/url/path";  (* optional *)
      mount_at = "/url/path";   (* optional alternative to mount_dir *)
    }
 
fadvise [Netsys_posix]
Advises to load pages into the page table from the file, or to remove such pages.
fake_pmanage [Netsys_pmanage]
A pseudo manager that does not save anything to a text file
fallocate [Netsys_posix]
Allocate space for the file and the specified file region
fcgi_processor [Netcgi_plex]
fchdir [Netsys_posix]
Set the current directory to the directory referenced by the file descriptor
fd_event_source [Netsys_posix]
Wraps a file descriptor as event_source, and monitors the events in poll_req_events.
fd_string [Netlog.Debug]
Return a string for generating debug messages.
fd_table [Netlog.Debug]
Returns the table of descriptors as list of lines.
fdatasync [Netsys_posix]
Syncs only data to disk.
fdopendir [Netsys_posix]
Make a directory handle from a file descriptor.
feat_method [Netftp_client]
Get the list of feature tokens (see also Netftp_client.ftp_state.ftp_features)
fg_blue [Netsys_win32]
fg_green [Netsys_win32]
fg_intensity [Netsys_win32]
fg_red [Netsys_win32]
fields [Netcgi_apache.Apache.Table]
Table.fields tbl returns a list of (key, value) pairs consisting of all entries of the table tbl.
file_descr_of_int [Netsys_posix]
Make a file descriptor from an integer
file_logger [Netplex_log]
Writes messages to this file
file_logger_factory [Netplex_log]
Reads a logging section like
file_logger_from_obj [Netplex_log]
Writes messages to this file
file_mime_body [Netmime]
Same as function
file_service [Nethttpd_services]
Configures a file service
file_translator [Nethttpd_services]
Translates an URI path to a file name.
file_url_of_local_path [Neturl]
Generates a URL with "file" scheme from the passed path name.
filename [Netcgi_apache.Apache.Request]
request_rec filename field.
fill_random [Netsys_rng]
Fills this string with random bytes
fill_random [Netsys_win32]
Fills the string with random bytes.
filter_out_buffer [Uq_io]
filter_out_buffer ~max p d: The data written to this device is redirected via pipe p and finally written to d.
find [Netsys_digests]
find name: get the digest name.
find [Netsys_ciphers]
find (name,mode): get the cipher name in the passed mode.
find [Netsys_crypto_types.DIGESTS]
Returns the digest of this name, or raises Not_found
find [Netsys_crypto_types.SYMMETRIC_CRYPTO]
find (name,mode): Looks up a cipher by name and mode, or raises Not_found
find [Netshm_hashtbl]
find tbl key: Finds the current binding of key in tbl or raises Not_found if no such binding exists.
find [Netshm]
find tbl key: Finds the current binding of key in tbl or raises Not_found if no such binding exists.
find_all [Netshm_hashtbl]
find_all tbl key returns the list of all data associated with key in tbl.
find_all [Netshm]
find_all tbl key returns the list of all data associated with key in tbl.
find_all_c [Netmcore_hashtbl]
Version of find_all with copied result
find_all_p [Netmcore_hashtbl]
Version of find_all with pinned result
find_all_ro [Netmcore_hashtbl]
Hashtbl.find_all tbl x returns the list of all data associated with x in tbl.
find_c [Netmcore_hashtbl]
Like find but returns a copy of the binding in normal RAM
find_double_line_start [Netmime_string]
find_double_line_start s pos len: Searches two adjacent line ends (each may be a CR/LF combination or a single LF), and returns the position after the second line end.
find_double_line_start_poly [Netmime_string]
polymorphic version
find_extension [Netx509]
find_extension is designed to be applied to the result of the extensions method of Netx509.x509_certificate:
find_line_end [Netmime_string]
find_line_end s pos len: Searches the next line end (CR/LF or only LF), and returns the position.
find_line_end_poly [Netmime_string]
polymorphic version
find_line_start [Netmime_string]
find_line_start s pos len: Searches the next start, and returns its position.
find_line_start_poly [Netmime_string]
polymorphic version
find_p [Netmcore_hashtbl]
find_p tbl x f looks up the current binding of x in tbl, and calls f with this binding as argument.
find_pattern [Netaux.KMP]
find_ro [Netmcore_hashtbl]
find_ro tbl x returns the current binding of x in tbl, or raises Not_found if no such binding exists.
finfo [Netcgi_apache.Apache.Request]
request_rec finfo field.
finish [Netsys_crypto_types.DIGESTS]
Returns the digest
finish_job [Shell_sys]
This creates a job_engine internally and runs until it is finished, i.e.
first_chars [Netstring_str]
Same as string_before
first_chars [Netstring_pcre]
Same as string_before
fix_MSIE_Content_type_bug [Netcgi_common]
fix_MSIE_Content_type_bug ct transforms the content-type string ct to fix the MSIE Content-Type bug.
fixup_url_string [Neturl]
Escapes some unsafe or "unwise" characters that are commonly used in URL strings: space, < > { } ^ \\ | and double quotes.
float_of_fp4 [Netnumber]
float_of_fp8 [Netnumber]
float_var [Netplex_cenv]
flush_e [Uq_io]
let e = flush_e d: If d has an internal buffer, all data is written out to d.
fmap_engine [Uq_engines_compat]
fmap_engine [Uq_engines]
Same as function
fold [Netshm_hashtbl]
fold f tbl init computes (f kN dN ... (f k1 d1 init)...), where k1 ... kN are the keys of all bindings in tbl, and d1 ... dN are the associated values.
fold [Netshm]
fold f tbl init computes (f kN dN ... (f k1 d1 init)...), where k1 ... kN are the keys of all bindings in tbl, and d1 ... dN are the associated values.
fold [Netmcore_queue]
fold f accu q
fold_header [Netmime_string]
fold_header f acc0 s pos len: Parses a MIME header in the string s from pos to exactly pos+len.
fold_lines [Netmime_string]
fold_lines f acc0 s pos len: Splits the substring of s from pos to pos+len into lines, and folds over these lines like List.fold_left.
fold_lines_p [Netmime_string]
fold_lines_p f acc0 s pos len: Splits the substring of s from pos to pos+len into lines, and folds over these lines like List.fold_left.
fold_lines_p_poly [Netmime_string]
even more polymorphic
fold_lines_poly [Netmime_string]
even more polymorphic
foreground [Netplex_main]
Returns whether the daemon runs in the foreground
forget_subprocess [Netsys_posix]
Frees OS resources.
format [Netdate]
Format a date/time record as a string
format_camlbox [Netcamlbox]
format_camlbox addr fd n size: The file fd is mapped into memory, and formatted as camlbox.
format_field_value [Netsendmail]
To put sval, an s_token list, into the header field name, call
format_status [Netgssapi_auth.Manage]
format_timestamp [Netlog]
format_timestamp fmt digits (seconds,nanos): Formats the timestamp (seconds,nanos) and returns the string.
format_to [Netdate]
Format a date/time record according to the format string and outputs the resulting string to the channel.
fp4_as_bytes [Netnumber.ENCDEC]
fp4_as_string [Netnumber.ENCDEC]
fp4_of_float [Netnumber]
fp4_of_fp8 [Netnumber]
Note fp4_of_fp8: This conversion is not exact.
fp8_as_bytes [Netnumber.ENCDEC]
fp8_as_string [Netnumber.ENCDEC]
fp8_of_float [Netnumber]
Note fp4_of_float: The same problems as in fp4_of_fp8 may arise
fp8_of_fp4 [Netnumber]
free_mem [Netmcore_mempool]
Frees this allocated block
free_wait_entry [Netmcore_condition]
Frees a wait_entry
free_wait_entry_e [Netmcore_condition]
Frees a wait_entry_e.
from_bytes [Netulex.ULB]
Same for bytes
from_bytes_inplace [Netulex.ULB]
Creates a unicode_lexbuf analysing the passed string encoded in the passed encoding.
from_dev_null [Shell]
A producer taking the data from /dev/null.
from_fd [Shell]
Creates a producer taking the data from the file descriptor passed to this function.
from_file [Shell]
Creates a producer taking the data from the file whose name is passed to this function.
from_function [Shell]
Creates a producer taking the data from a function.
from_function [Netulex.ULB]
Creates a unicode_lexbuf to analyse strings of the passed encoding coming from the refill function.
from_in_obj_channel [Netulex.ULB]
Creates a unicode_lexbuf to analyse strings of the passed encoding coming from the object channel.
from_stream [Shell]
Creates a producer taking the data from a stream of strings.
from_stream [Shell_sys]
from_stream ?epipe s returns a function which can be used as producer argument for add_producer.
from_string [Shell]
Creates a producer taking the data from a string s.
from_string [Shell_sys]
from_string ?pos ?len ?epipe s returns a function which can be used as producer argument for add_producer.
from_string [Netulex.ULB]
Creates a unicode_lexbuf analysing the passed string encoded in the passed encoding.
from_tstring [Shell_sys]
Same for tagged strings
from_ulb_lexbuf [Netulex.Ulexing]
Creates a new lexbuf from the unicode_lexbuf.
from_unicode [Netconversion]
Maps the Unicode code point to the corresponding code point of the charset, or raises Cannot_represent when there is no such corresponding code point.
fsync [Netsys_posix]
Sync data and metadata to disk
ftp_fs [Netftp_fs]
Same as function
full_split [Netstring_str]
Like split_delim, but returns the delimiters in the result
full_split [Netstring_pcre]
Like split_delim, but returns the delimiters in the result
fwd_dlogger [Netlog.Debug]
The standard debug logger simply prepends the module name to the message (separated by ": "), and calls the current logger to print it

G
gai_resolver [Uq_resolver]
This resolver uses Unix.getaddrinfo.
gc [Netmcore_heap]
Lock the heap and do a GC pass
gclose [Netsys]
Shuts down the system object referenced by the descriptor so far possible, and closes the descriptor.
ge_uint4 [Netnumber]
Other comparisons
ge_uint8 [Netnumber]
Other comparisons
general_name_from_ASN1 [Netx509]
Parses the general_name structure
general_names_from_ASN1 [Netx509]
Parse a sequence of general names
gentime [Netasn1.Value]
Create a time value for GeneralizedTime.
get [Netsys_global]
Get the value of the variable (after checking for an update)
get [Netbuffer]
get nb pos: Get the character at pos
get [Netshm_array]
get a k: Returns the contents of the array element number k where 0 <= k < length a.
get [Netplex_sharedvar.VV_TYPE]
get [Netplex_semaphore]
Get the value of the named semaphore.
get [Netplex_cenv.VAR_TYPE]
get [Netcgi_dbi.DBI_POOL]
Example: module MyPool = DbiPool(Dbi_postgres)
get [Netcgi_common.Cookie]
Decode the cookie header, may they be version 0 or 1.
get [Netcgi_apache.Apache.Table]
Table.get tbl key returns the corresponding entry in the table.
get_accept [Nethttp.Header]
Returns the Accept header as list of triples (media_range, media_range_params, accept_params).
get_accept_charset [Nethttp.Header]
Returns the Accept-charset header as list of pairs (charset,params).
get_accept_encoding [Nethttp.Header]
Returns the Accept-encoding header as list of pairs (coding,params).
get_accept_language [Nethttp.Header]
Returns the Accept-language header as list of pairs (lang_range,params).
get_accept_ranges [Nethttp.Header]
Returns the Accept-ranges header as list of tokens.
get_acceptor_cred [Netgssapi_auth.Auth]
get_acceptor_name [Netgssapi_auth.Auth]
get_active_code_page [Netsys_win32]
Get the active code page.
get_addressed_servers [Netsys_crypto_types.TLS_PROVIDER]
To be used in servers: The client can address one of several virtual servers with the SNI extension, and this function returns which was requested.
get_age [Nethttp.Header]
Returns the Age header as number
get_all [Netcgi_apache.Apache.Table]
Table.get_all tbl key same as Table.get tbl key except it returns all values corresponding to the key.
get_allow [Nethttp.Header]
Returns the Allow header as list of tokens.
get_arguments [Shell_sys]
Returns the argument array of the command (skipping the command name)
get_assignments [Shell_sys]
Returns the list of assignments (fd_from,fd_to)
get_auth_method [Rpc_server]
Returns the method that was used to authenticate the user.
get_authorization [Nethttp.Header]
Returns the Authorization header as pair (auth_scheme,auth_params), or raises Not_found if not present.
get_basic_auth_pw [Netcgi_apache.Apache.Request]
Get the password sent in basic authentication.
get_bitstring_bits [Netasn1.Value]
Get the bitstring as bool array.
get_bitstring_data [Netasn1.Value]
Get the data.
get_bitstring_repr [Netasn1.Value]
Get the representation
get_bitstring_size [Netasn1.Value]
Get the number of bits
get_c [Netmcore_matrix]
get_c sa k1 k2: Gets a copy of the (k1,k2)-th element of the matrix sæ
get_c [Netmcore_array]
get_c sa k: Gets a copy of the k-th element of the shared array sæ
get_cache_control [Nethttp.Header]
Returns the Cache-control header as list of tokens.
get_cert_type [Netsys_crypto_types.TLS_PROVIDER]
Get the type of the certificate
get_charset [Netmime_string]
Return the decoded word (the contents of the word after decoding the "Q" or "B" representation), and the character set of the decoded word (uppercase).
get_charset [Netftp_client]
get_chdir [Shell_sys]
Returns the chdir parameter of the command
get_cipher_algo [Netsys_crypto_types.TLS_PROVIDER]
Get the name of the cipher
get_cipher_suite_type [Netsys_crypto_types.TLS_PROVIDER]
The type of the cipher suite: "X509": X509 certificates are used, "OPENPGP": OpenPGP certificates are used, "ANON": anonymous credentials, "SRP": SRP credentials, "PSK": PSK credentials
get_client_block [Netcgi_apache.Apache.Request]
Get client request data.
get_client_block_buf [Netcgi_apache.Apache.Request]
get_client_block_buf r buf ofs len read a chunk of data and puts it in buf.[ofs .. ofs+len-1].
get_client_flags [Netgssapi_auth.Auth]
get_cmdname [Shell_sys]
Returns the name of the command
get_column [Netmime_string]
Return the column of the line where the token starts (first column is number 0)
get_column_of_scanner [Netmime_string]
Return the current position, line, and column of a mime_scanner.
get_compression_algo [Netsys_crypto_types.TLS_PROVIDER]
Get the name of the record-level compression method
get_config [Netsys_crypto_types.TLS_PROVIDER]
Get the current config (possibly modified because of a rehandshake)
get_conn_peer_name [Rpc_server]
Return the address of the socket serving the connection, and the client socket, resp.
get_conn_socket_name [Rpc_server]
get_connection [Nethttp.Header]
Returns the Connection header as list of tokens.
get_connection_id [Rpc_server]
Get the connection_id
get_console_attr [Netsys_win32]
get_console_info [Netsys_win32]
Get r/o console info.
get_console_input [Netsys_win32]
Get the input stream of the console.
get_console_mode [Netsys_win32]
get_console_output [Netsys_win32]
Get the output stream of the console.
get_content_disposition [Netmime_header]
Returns the Content-disposition field as parsed value.
get_content_encoding [Nethttp.Header]
Returns the Content-encoding header as list of tokens.
get_content_language [Nethttp.Header]
Returns the Content-language header as list of tokens.
get_content_length [Nethttp.Header]
Returns the Content-length header as number.
get_content_length [Netmime_header]
Returns the Content-length field as integer
get_content_location [Nethttp.Header]
Returns the Content-location header as string.
get_content_md5 [Nethttp.Header]
Returns the Content-MD5 header as string.
get_content_range [Nethttp.Header]
Returns the Content-range header as `Bytes(byte_range_resp_spec, instance_length).
get_content_transfer_encoding [Netmime_header]
Returns the Content-transfer-encoding as string
get_content_type [Nethttp.Header]
Returns the Content-type header as pair (media_type, params).
get_content_type [Netmime_header]
Returns the Content-type as parsed value.
get_cookie [Nethttp.Header]
Get the (Netscape) cookies as (name,value) pairs (or Not_found).
get_cookie_ct [Nethttp.Header]
Get the cookies in the Nethttp.Cookie.t representation (the suffix "_ct" reminds of Cookie.t).
get_create [Netftp_client]
get_custom_ops [Netsys_mem]
Returns custom ops for a sample value (or Invalid_argument)
get_date [Nethttp.Header]
Returns the Date header as number (seconds since the Epoch).
get_debug_name [Rpc_server]
Get the debug name
get_debug_name [Rpc_client]
Get the debug name
get_decoded_word [Netmime_string]
get_descriptors [Shell_sys]
Returns the list of active descriptors
get_display_name [Netgssapi_auth.Auth]
get_ec [Netmech_scram.Cryptosystem]
let ec = get_ec e_keys n: Returns the required value for the "extra count" field of RFC 4121 if the plaintext message has size n.
get_enc_lazily [Netplex_sharedvar]
Same for encapsulated values
get_enc_value [Netplex_sharedvar]
get_enc_value name: Gets the value of the variable name.
get_endpoint_creds [Netsys_crypto_types.TLS_PROVIDER]
Get the credentials that was actually used in the handshake, in raw format.
get_env [Shell_sys]
Gets the contents of the environment as string array
get_env_var [Shell_sys]
Returns the value of the variable in the environment
get_environment [Shell_sys]
Returns the designated environment of the command
get_etag [Nethttp.Header]
Returns the Etag header.
get_event_fd [Netsys_posix]
Returns a duplicate of the underlying file descriptor.
get_event_system [Rpc_server]
Find out the event system that contains the 'session'
get_exception [Netsys_polypipe]
Get the exception
get_expect [Nethttp.Header]
Returns the Expect header as list of triples (token,value,params).
get_expires [Nethttp.Header]
Returns the Expires header as number (seconds since the Epoch).
get_exported_name [Netgssapi_auth.Auth]
get_fd_of_event_source [Netsys_posix]
Get the file descriptor wrapped by this event source
get_fd_style [Netsys]
Get the file descriptor style.
get_file [Netmcore]
Gets the file with this ID (or raises No_resource).
get_filename [Shell_sys]
Returns the file name of the executable
get_from [Nethttp.Header]
Returns the From header as string.
get_from_unicode [Netmappings]
get_full_path_name [Netsys_win32]
Calls GetFullPathName
get_gssapi_props [Rpc_server]
Get the GSSAPI properties if available
get_gssapi_props [Rpc_client]
Get the GSSAPI properties of the last call (so far available)
get_host [Nethttp.Header]
Returns the Host header as pair (host,port).
get_host_by_name [Uq_resolver]
Look up the host, and return the host entry or raise the exception Host_not_found.
get_if_match [Nethttp.Header]
Returns the If-match header.
get_if_modified_since [Nethttp.Header]
Returns the If-modified-since header as number (seconds since the Epoch).
get_if_none_match [Nethttp.Header]
Returns the If-none-match header.
get_if_range [Nethttp.Header]
Returns the If-range header.
get_if_unmodified_since [Nethttp.Header]
Returns the If-unmodified-since header as number (seconds since the Epoch).
get_initiator_cred [Netgssapi_auth.Auth]
get_initiator_name [Netgssapi_auth.Auth]
get_int [Netasn1.Value]
Get an integer as int if representable, or raise Out_of_range
get_int32 [Netasn1.Value]
Get an integer as int32 if representable, or raise Out_of_range
get_int64 [Netasn1.Value]
Get an integer as int64 if representable, or raise Out_of_range
get_int_b256 [Netasn1.Value]
Get an integer in base 256 notation, big endian.
get_int_repr [Netasn1.Value]
Get an integer as bytes
get_kx_algo [Netsys_crypto_types.TLS_PROVIDER]
Get the name of the key exchange method
get_lang [Netftp_client]
get_language [Netmime_string]
Returns the language if the token is an EncodedWord, and "" for all other tokens.
get_last_modified [Nethttp.Header]
Returns the Last-modified header as number (seconds since the Epoch).
get_last_proc_info [Rpc_server]
Get a debug string describing the last invoked procedure
get_lazily [Netplex_sharedvar]
get_lazily name f: Uses the variable name to ensure that f is only invoked when get_lazily is called for the first time, and that the value stored in the variable is returned the next times.
get_length [Netmime_string]
Return the length of the token in bytes
get_line [Netmime_string]
Return the line number where the token starts (numbering begins usually with 1)
get_line_of_scanner [Netmime_string]
get_localzone [Netdate]
Retrieves the current offset for the local time zone, taking daylight savings into account.
get_location [Nethttp.Header]
Returns the Location header as string.
get_long_path_name [Netsys_win32]
Calls GetLongPathName
get_mac_algo [Netsys_crypto_types.TLS_PROVIDER]
Get the name of the message authentication code
get_main_socket_name [Rpc_server]
Returns the address of the server socket, or the address of the bidirectional pipe.
get_max_forwards [Nethttp.Header]
Returns the Max-forwards header as number.
get_media_type [Netftp_client]
get_method [Netftp_client]
This FTP method walks to the right directory and gets file from the server.
get_mic [Netmech_scram.Cryptosystem]
Returns a message integrity code
get_mic_mstrings [Netmech_scram.Cryptosystem]
Same, but with data representation as mstring list
get_modify [Netftp_client]
get_name [Netftp_client]
get_nonblock [Netsys_posix]
Returns whether the nonblock flag is set
get_p [Netmcore_matrix]
get_p sa k1 k2 f: Gets the (k1,k2)-th element of the matrix sa and call f with this element, and returns the result of f.
get_p [Netmcore_array]
get_p sa k f: Gets the k-th element of the shared array sa and call f with this element, and returns the result of f.
get_peer_credentials [Rpc_auth_local]
Return the pair (euid,egid) for a Unix domain socket.
get_peer_creds [Netsys_crypto_types.TLS_PROVIDER]
Get the credentials of the peer, in raw format.
get_peer_creds_list [Netsys_crypto_types.TLS_PROVIDER]
Get the chain that was actually used in the handshake.
get_peer_name [Rpc_server]
Return the address of the socket serving the session, and the client socket, resp.
get_peer_name [Rpc_client]
Return the addresses of the client socket and the server socket, resp.
get_perm [Netftp_client]
get_poll_cell [Netsys_posix]
get_poll_cell a k: Returns the poll cell k.
get_pos [Netmime_string]
Return the byte position where the token starts in the string (the first byte has position 0)
get_pos_of_scanner [Netmime_string]
get_pragma [Nethttp.Header]
Returns the Pragma header as list of pairs (token,value).
get_process_status [Netsys_win32]
Returns the process result if the process is finished, and None otherwise
get_propagator [Netsys_global]
Get the current propagator or return None
get_protocol [Rpc_server]
Return whether Tcp or Udp
get_protocol [Rpc_client]
Get the protocol flavour
get_protocol [Netsys_crypto_types.TLS_PROVIDER]
Get the name of the tunnel protocol
get_proxy_authenticate [Nethttp.Header]
Returns the Proxy-authenticate header as list of challenges (auth_scheme,auth_params).
get_proxy_authorization [Nethttp.Header]
Returns the Proxy-authorization header as pair (auth_scheme,auth_params).
get_range [Nethttp.Header]
Returns the Range header as `Bytes ranges, where the list ranges has elements of the form (Some first_pos, Some last_pos), (Some first_pos, None) (prefix range), or (None, Some last_pos) (suffix range).
get_real_repr [Netasn1.Value]
Get the byte representation of the real
get_referer [Nethttp.Header]
Returns the Referer header as string.
get_referrer [Nethttp.Header]
Same, for addicts of correct orthography
get_resource [Netmcore]
Retrieves the resource by ID.
get_retry_after [Nethttp.Header]
Returns the Retry-after header.
get_ro [Netmcore_matrix]
get_ro sa k1 k2: Gets the (k1,k2)-th element of the matrix sa.
get_ro [Netmcore_array]
get_ro sa k: Gets the k-th element of the shared array sa.
get_sem [Netmcore]
gets the semaphore with this ID (or raises No_resource).
get_sem_container [Netmcore]
Get the semaphore container
get_sender_of_last_response [Rpc_client]
Return the address of the sender of the last received response.
get_server [Rpc_server]
Returns the server instance of the session
get_server [Nethttp.Header]
Returns the Server header as uninterpreted string (including comments).
get_server_flags [Netgssapi_auth.Auth]
get_session_data [Netsys_crypto_types.TLS_PROVIDER]
Get the (non-printable) marshalled session data, for later resumption with resume_client
get_session_id [Netsys_crypto_types.TLS_PROVIDER]
The (non-printable) session ID
get_set_cookie [Nethttp.Header]
Get the Set-Cookie header
get_shm [Netmcore]
Gets the shm object with this ID (or raises No_resource).
get_size [Netftp_client]
get_socket_name [Rpc_server]
get_socket_name [Rpc_client]
get_srv_event_system [Rpc_server]
Returns the event system
get_state [Netsys_crypto_types.TLS_PROVIDER]
Return the recorded state
get_stats [Rpc_client]
Get stats (n_delayed, n_waiting, n_pending): n_delayed: Calls that wait for authentication, n_waiting: Calls that wait for being sent, n_pending: Calls that wait for the response
get_subprocess_status [Netsys_posix]
If the subprocess is terminated, this function returns the status.
get_target_name [Netgssapi_auth.Auth]
get_te [Nethttp.Header]
Returns the TE header as list of triples (te_token, te_params, accept_params).
get_time [Netasn1.Value]
Get the time.
get_time_repr [Netasn1.Value]
Get the raw time string
get_time_subtype [Netasn1.Value]
Whether this is for UTCTime (`U) or GeneralizedTime (`G)
get_tls_session_props [Rpc_server]
Get the TLS properties so far TLS is enabled
get_tls_session_props [Rpc_client]
Get the TLS properties so far TLS is enabled
get_tls_session_props [Nettls_support]
Get the session properties for an endpoint for which the handshake is already done
get_tls_user_name [Nettls_support]
Get the "user name" of client certificates.
get_to_unicode [Netmappings]
get_token [Netmime_string]
Return the s_token within the s_extended_token
get_trailer [Nethttp.Header]
Returns the Trailer header as list of field names.
get_transfer_encoding [Nethttp.Header]
Returns the Transfer-encoding header as list of pairs (token, params).
get_type [Netftp_client]
get_unique [Netftp_client]
get_unix_gid [Netftp_client]
get_unix_mode [Netftp_client]
get_unix_uid [Netftp_client]
get_upgrade [Nethttp.Header]
Returns the Upgrade header as list of products.
get_user [Rpc_server]
Returns the user name as returned by the authentication method.
get_user_agent [Nethttp.Header]
Returns the User-agent header as uninterpreted string (including comments).
get_v [Netsys_global]
Get the value and the version number of the variable
get_value [Netplex_sharedvar]
get_value name: Gets the value of the variable name.
get_vary [Nethttp.Header]
Returns the Vary header.
get_www_authenticate [Nethttp.Header]
Returns the WWW-Authenticate header as list of challenges (auth_scheme,auth_params).
get_xid [Rpc_server]
Returns the session ID.
get_xid_of_last_call [Rpc_client]
Returns the session identifier used in the just made call
getaddr_rpcbind [Rpc_portmapper]
getaddr_rpcbind pm_client program_nr version_nr netid caller_uaddr:
getaddr_rpcbind'async [Rpc_portmapper]
getpagesize [Netsys_mem]
Returns the size of a page as reported by sysconf.
getpeername [Netsys]
like Unix.getpeername, but errors are fixed up.
getpgid [Netsys_posix]
Return the process group ID of the process with the passed PID.
getpgrp [Netsys_posix]
Same as getpgid 0, i.e.
getport [Rpc_portmapper]
getport pm_client program_nr version_nr protocol: finds out the port where the given service runs.
getport'async [Rpc_portmapper]
getsid [Netsys_posix]
Returns the session ID of the process with the passed PID.
getvalue [Netmcore_sem]
Returns the value of the semaphore
glob [Netglob]
Forms a set of filenames as described below, and matches this set against the pattern.
global_propagator [Netplex_sharedvar]
Create a new propagator, and initialize Netplex_sharedvar with the current variables from Netsys_global.
global_rcache [Rpc_proxy.ReliabilityCache]
The global cache.
global_rcache_config [Rpc_proxy.ReliabilityCache]
Returns the global config: policy = `None, disable_timeout_min = 1.0, disable_timeout_max = 64.0, threshold = 1, availability = fun _ _ -> true
global_replace [Netstring_str]
global_replace re templ s: Replaces all matchings of re in s by templ.
global_replace [Netstring_pcre]
global_replace re templ s: Replaces all matchings of re in s by templ.
global_substitute [Netstring_str]
global_substitute re subst s: Applies the substitution function subst to all matchings of re in s, and returns the transformed string.
global_substitute [Netstring_pcre]
global_substitute re subst s: Applies the substitution function subst to all matchings of re in s, and returns the transformed string.
gnutls [Nettls_gnutls]
The implementation of TLS backed by GnuTLS, as value
gnutls_alert_get [Nettls_gnutls_bindings]
gnutls_alert_get_name [Nettls_gnutls_bindings]
gnutls_alert_get_strname [Nettls_gnutls_bindings]
gnutls_alert_send [Nettls_gnutls_bindings]
gnutls_alert_send_appropriate [Nettls_gnutls_bindings]
gnutls_anon_allocate_client_credentials [Nettls_gnutls_bindings]
gnutls_anon_allocate_server_credentials [Nettls_gnutls_bindings]
gnutls_anon_set_server_dh_params [Nettls_gnutls_bindings]
gnutls_auth_client_get_type [Nettls_gnutls_bindings]
gnutls_auth_get_type [Nettls_gnutls_bindings]
gnutls_auth_server_get_type [Nettls_gnutls_bindings]
gnutls_bye [Nettls_gnutls_bindings]
gnutls_certificate_activation_time_peers [Nettls_gnutls_bindings]
gnutls_certificate_allocate_credentials [Nettls_gnutls_bindings]
gnutls_certificate_client_get_request_status [Nettls_gnutls_bindings]
gnutls_certificate_expiration_time_peers [Nettls_gnutls_bindings]
gnutls_certificate_get_issuer [Nettls_gnutls_bindings]
gnutls_certificate_get_ours [Nettls_gnutls_bindings]
gnutls_certificate_get_peers [Nettls_gnutls_bindings]
gnutls_certificate_send_x509_rdn_sequence [Nettls_gnutls_bindings]
gnutls_certificate_server_set_request [Nettls_gnutls_bindings]
gnutls_certificate_set_dh_params [Nettls_gnutls_bindings]
gnutls_certificate_set_verify_flags [Nettls_gnutls_bindings]
gnutls_certificate_set_verify_limits [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_crl [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_crl_file [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_crl_mem [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_key [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_key_file [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_key_mem [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_simple_pkcs12_file [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_simple_pkcs12_mem [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_system_trust [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_trust [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_trust_file [Nettls_gnutls_bindings]
gnutls_certificate_set_x509_trust_mem [Nettls_gnutls_bindings]
gnutls_certificate_type_get [Nettls_gnutls_bindings]
gnutls_certificate_type_get_id [Nettls_gnutls_bindings]
gnutls_certificate_type_get_name [Nettls_gnutls_bindings]
gnutls_certificate_type_list [Nettls_gnutls_bindings]
gnutls_certificate_verify_peers2 [Nettls_gnutls_bindings]
gnutls_check_version [Nettls_gnutls_bindings]
gnutls_cipher_add_auth [Nettls_gnutls_bindings]
gnutls_cipher_decrypt2 [Nettls_gnutls_bindings]
gnutls_cipher_encrypt2 [Nettls_gnutls_bindings]
gnutls_cipher_get [Nettls_gnutls_bindings]
gnutls_cipher_get_id [Nettls_gnutls_bindings]
gnutls_cipher_get_key_size [Nettls_gnutls_bindings]
gnutls_cipher_get_name [Nettls_gnutls_bindings]
gnutls_cipher_init [Nettls_gnutls_bindings]
gnutls_cipher_list [Nettls_gnutls_bindings]
gnutls_cipher_suite_get_name [Nettls_gnutls_bindings]
gnutls_cipher_tag [Nettls_gnutls_bindings]
gnutls_compression_get [Nettls_gnutls_bindings]
gnutls_compression_get_id [Nettls_gnutls_bindings]
gnutls_compression_get_name [Nettls_gnutls_bindings]
gnutls_compression_list [Nettls_gnutls_bindings]
gnutls_credentials [Nettls_gnutls.GNUTLS_PROVIDER]
Get the gnutls_credentials of the generic credentials
gnutls_credentials_clear [Nettls_gnutls_bindings]
gnutls_credentials_set [Nettls_gnutls_bindings]
gnutls_db_check_entry [Nettls_gnutls_bindings]
gnutls_db_remove_session [Nettls_gnutls_bindings]
gnutls_db_set_cache_expiration [Nettls_gnutls_bindings]
gnutls_dh_get_group [Nettls_gnutls_bindings]
gnutls_dh_get_peers_public_bits [Nettls_gnutls_bindings]
gnutls_dh_get_prime_bits [Nettls_gnutls_bindings]
gnutls_dh_get_pubkey [Nettls_gnutls_bindings]
gnutls_dh_get_secret_bits [Nettls_gnutls_bindings]
gnutls_dh_params_cpy [Nettls_gnutls_bindings]
gnutls_dh_params_generate2 [Nettls_gnutls_bindings]
gnutls_dh_params_import_pkcs3 [Nettls_gnutls_bindings]
gnutls_dh_params_import_raw [Nettls_gnutls_bindings]
gnutls_dh_params_init [Nettls_gnutls_bindings]
gnutls_dh_set_prime_bits [Nettls_gnutls_bindings]
gnutls_ecc_curve_get [Nettls_gnutls_bindings]
gnutls_ecc_curve_get_name [Nettls_gnutls_bindings]
gnutls_ecc_curve_get_size [Nettls_gnutls_bindings]
gnutls_error_is_fatal [Nettls_gnutls_bindings]
gnutls_error_to_alert [Nettls_gnutls_bindings]
gnutls_fingerprint [Nettls_gnutls_bindings]
gnutls_global_set_log_level [Nettls_gnutls_bindings]
gnutls_handshake [Nettls_gnutls_bindings]
gnutls_handshake_get_last_in [Nettls_gnutls_bindings]
gnutls_handshake_get_last_out [Nettls_gnutls_bindings]
gnutls_handshake_set_max_packet_length [Nettls_gnutls_bindings]
gnutls_handshake_set_private_extensions [Nettls_gnutls_bindings]
gnutls_init [Nettls_gnutls_bindings]
gnutls_key_generate [Nettls_gnutls_bindings]
gnutls_kx_get [Nettls_gnutls_bindings]
gnutls_kx_get_id [Nettls_gnutls_bindings]
gnutls_kx_get_name [Nettls_gnutls_bindings]
gnutls_kx_list [Nettls_gnutls_bindings]
gnutls_mac_get [Nettls_gnutls_bindings]
gnutls_mac_get_id [Nettls_gnutls_bindings]
gnutls_mac_get_key_size [Nettls_gnutls_bindings]
gnutls_mac_get_name [Nettls_gnutls_bindings]
gnutls_mac_list [Nettls_gnutls_bindings]
gnutls_openpgp_send_cert [Nettls_gnutls_bindings]
gnutls_pk_bits_to_sec_param [Nettls_gnutls_bindings]
gnutls_pk_get_id [Nettls_gnutls_bindings]
gnutls_pk_get_name [Nettls_gnutls_bindings]
gnutls_pk_list [Nettls_gnutls_bindings]
gnutls_prf [Nettls_gnutls_bindings]
gnutls_prf_raw [Nettls_gnutls_bindings]
gnutls_priority_get_cipher_suite_index [Nettls_gnutls_bindings]
gnutls_priority_init [Nettls_gnutls_bindings]
gnutls_priority_set [Nettls_gnutls_bindings]
gnutls_privkey_decrypt_data [Nettls_gnutls_bindings]
gnutls_privkey_import_x509 [Nettls_gnutls_bindings]
gnutls_privkey_init [Nettls_gnutls_bindings]
gnutls_privkey_sign_data [Nettls_gnutls_bindings]
gnutls_protocol_get_id [Nettls_gnutls_bindings]
gnutls_protocol_get_name [Nettls_gnutls_bindings]
gnutls_protocol_get_version [Nettls_gnutls_bindings]
gnutls_protocol_list [Nettls_gnutls_bindings]
gnutls_psk_allocate_client_credentials [Nettls_gnutls_bindings]
gnutls_psk_allocate_server_credentials [Nettls_gnutls_bindings]
gnutls_psk_client_get_hint [Nettls_gnutls_bindings]
gnutls_psk_server_get_username [Nettls_gnutls_bindings]
gnutls_psk_set_client_credentials [Nettls_gnutls_bindings]
gnutls_psk_set_server_credentials_file [Nettls_gnutls_bindings]
gnutls_psk_set_server_credentials_hint [Nettls_gnutls_bindings]
gnutls_psk_set_server_dh_params [Nettls_gnutls_bindings]
gnutls_pubkey_encrypt_data [Nettls_gnutls_bindings]
gnutls_pubkey_import [Nettls_gnutls_bindings]
gnutls_pubkey_import_privkey [Nettls_gnutls_bindings]
gnutls_pubkey_import_url [Nettls_gnutls_bindings]
gnutls_pubkey_init [Nettls_gnutls_bindings]
gnutls_pubkey_verify_data2 [Nettls_gnutls_bindings]
gnutls_record_check_pending [Nettls_gnutls_bindings]
gnutls_record_disable_padding [Nettls_gnutls_bindings]
gnutls_record_get_direction [Nettls_gnutls_bindings]
gnutls_record_get_max_size [Nettls_gnutls_bindings]
gnutls_record_recv [Nettls_gnutls_bindings]
gnutls_record_send [Nettls_gnutls_bindings]
gnutls_record_set_max_size [Nettls_gnutls_bindings]
gnutls_rehandshake [Nettls_gnutls_bindings]
gnutls_safe_renegotiation_status [Nettls_gnutls_bindings]
gnutls_sec_param_get_name [Nettls_gnutls_bindings]
gnutls_sec_param_to_pk_bits [Nettls_gnutls_bindings]
gnutls_server_name_get [Nettls_gnutls_bindings]
gnutls_server_name_set [Nettls_gnutls_bindings]
gnutls_session [Nettls_gnutls.GNUTLS_PROVIDER]
Get the gnutls_session of the endpoint
gnutls_session_channel_binding [Nettls_gnutls_bindings]
gnutls_session_enable_compatibility_mode [Nettls_gnutls_bindings]
gnutls_session_get_data [Nettls_gnutls_bindings]
gnutls_session_get_id [Nettls_gnutls_bindings]
gnutls_session_is_resumed [Nettls_gnutls_bindings]
gnutls_session_set_data [Nettls_gnutls_bindings]
gnutls_session_ticket_enable_client [Nettls_gnutls_bindings]
gnutls_session_ticket_enable_server [Nettls_gnutls_bindings]
gnutls_session_ticket_key_generate [Nettls_gnutls_bindings]
gnutls_set_default_priority [Nettls_gnutls_bindings]
gnutls_sign_algorithm_get_requested [Nettls_gnutls_bindings]
gnutls_sign_get_id [Nettls_gnutls_bindings]
gnutls_sign_get_name [Nettls_gnutls_bindings]
gnutls_sign_list [Nettls_gnutls_bindings]
gnutls_srp_allocate_client_credentials [Nettls_gnutls_bindings]
gnutls_srp_allocate_server_credentials [Nettls_gnutls_bindings]
gnutls_srp_server_get_username [Nettls_gnutls_bindings]
gnutls_srp_set_client_credentials [Nettls_gnutls_bindings]
gnutls_srp_set_prime_bits [Nettls_gnutls_bindings]
gnutls_srp_set_server_credentials_file [Nettls_gnutls_bindings]
gnutls_srp_verifier [Nettls_gnutls_bindings]
gnutls_strerror [Nettls_gnutls_bindings]
gnutls_strerror_name [Nettls_gnutls_bindings]
gnutls_supplemental_get_name [Nettls_gnutls_bindings]
gnutls_x509_crl_import [Nettls_gnutls_bindings]
gnutls_x509_crl_init [Nettls_gnutls_bindings]
gnutls_x509_crl_list_import [Nettls_gnutls_bindings]
gnutls_x509_crl_verify [Nettls_gnutls_bindings]
gnutls_x509_crt_check_hostname [Nettls_gnutls_bindings]
gnutls_x509_crt_check_issuer [Nettls_gnutls_bindings]
gnutls_x509_crt_check_revocation [Nettls_gnutls_bindings]
gnutls_x509_crt_export [Nettls_gnutls_bindings]
gnutls_x509_crt_get_activation_time [Nettls_gnutls_bindings]
gnutls_x509_crt_get_authority_info_access [Nettls_gnutls_bindings]
gnutls_x509_crt_get_authority_key_id [Nettls_gnutls_bindings]
gnutls_x509_crt_get_basic_constraints [Nettls_gnutls_bindings]
gnutls_x509_crt_get_ca_status [Nettls_gnutls_bindings]
gnutls_x509_crt_get_dn [Nettls_gnutls_bindings]
gnutls_x509_crt_get_dn_oid [Nettls_gnutls_bindings]
gnutls_x509_crt_get_expiration_time [Nettls_gnutls_bindings]
gnutls_x509_crt_get_extension_data [Nettls_gnutls_bindings]
gnutls_x509_crt_get_extension_info [Nettls_gnutls_bindings]
gnutls_x509_crt_get_extension_oid [Nettls_gnutls_bindings]
gnutls_x509_crt_get_fingerprint [Nettls_gnutls_bindings]
gnutls_x509_crt_get_issuer_alt_name [Nettls_gnutls_bindings]
gnutls_x509_crt_get_issuer_alt_othername_oid [Nettls_gnutls_bindings]
gnutls_x509_crt_get_issuer_dn [Nettls_gnutls_bindings]
gnutls_x509_crt_get_issuer_dn_oid [Nettls_gnutls_bindings]
gnutls_x509_crt_get_issuer_unique_id [Nettls_gnutls_bindings]
gnutls_x509_crt_get_key_id [Nettls_gnutls_bindings]
gnutls_x509_crt_get_key_purpose_oid [Nettls_gnutls_bindings]
gnutls_x509_crt_get_key_usage [Nettls_gnutls_bindings]
gnutls_x509_crt_get_pk_algorithm [Nettls_gnutls_bindings]
gnutls_x509_crt_get_pk_dsa_raw [Nettls_gnutls_bindings]
gnutls_x509_crt_get_pk_rsa_raw [Nettls_gnutls_bindings]
gnutls_x509_crt_get_serial [Nettls_gnutls_bindings]
gnutls_x509_crt_get_signature [Nettls_gnutls_bindings]
gnutls_x509_crt_get_signature_algorithm [Nettls_gnutls_bindings]
gnutls_x509_crt_get_subject_alt_name [Nettls_gnutls_bindings]
gnutls_x509_crt_get_subject_alt_othername_oid [Nettls_gnutls_bindings]
gnutls_x509_crt_get_subject_key_id [Nettls_gnutls_bindings]
gnutls_x509_crt_get_subject_unique_id [Nettls_gnutls_bindings]
gnutls_x509_crt_get_version [Nettls_gnutls_bindings]
gnutls_x509_crt_import [Nettls_gnutls_bindings]
gnutls_x509_crt_init [Nettls_gnutls_bindings]
gnutls_x509_crt_list_import [Nettls_gnutls_bindings]
gnutls_x509_crt_list_verify [Nettls_gnutls_bindings]
gnutls_x509_crt_verify [Nettls_gnutls_bindings]
gnutls_x509_privkey_import [Nettls_gnutls_bindings]
gnutls_x509_privkey_import_pkcs8 [Nettls_gnutls_bindings]
gnutls_x509_privkey_init [Nettls_gnutls_bindings]
grab [Netsys_mem]
grab addr len: Interprets the address range from addr to addr+len-1 as memory bigarray.
grantpt [Netsys_posix]
Grant access to this PTY
gread [Netsys]
gread fd_style fd s pos len: Reads up to len bytes from descriptor fd which is supposed to support the I/O style fd_style, i.e.
gread_tbuf [Netsys]
Same for a tagged buffer
group [Netshm]
Execute a sequence of operations in a group:
group_beginning [Netstring_str]
Returns the position where the substring matching the nth group begins
group_beginning [Netstring_pcre]
Returns the position where the substring matching the nth group begins
group_end [Netstring_str]
Returns the position where the substring matching the nth group ends
group_end [Netstring_pcre]
Returns the position where the substring matching the nth group ends
grow [Netmcore_array]
grow sa n x: Grows the array to n elements.
gs2_decode_saslname [Netgssapi_support]
Encodes "," and "=" characters, and forbids null bytes, and checks whether the names are UTF-8-encoded (as required for the "saslname" production in section 4 of RFC 5801).
gs2_encode_saslname [Netgssapi_support]
gshutdown [Netsys]
gshutdown fd_style fd cmd: If there is the possibility to shut down the connection for this kind of descriptor, the shutdown is tried.
gss_accept_sec_context [Netgss_bindings]
gss_acquire_cred [Netgss_bindings]
gss_add_cred [Netgss_bindings]
gss_canonicalize_name [Netgss_bindings]
gss_compare_name [Netgss_bindings]
gss_context_time [Netgss_bindings]
gss_delete_sec_context [Netgss_bindings]
gss_display_name [Netgss_bindings]
gss_display_status [Netgss_bindings]
gss_duplicate_name [Netgss_bindings]
gss_export_name [Netgss_bindings]
gss_export_sec_context [Netgss_bindings]
gss_get_mic [Netgss_bindings]
gss_import_name [Netgss_bindings]
gss_import_sec_context [Netgss_bindings]
gss_indefinite [Netgss_bindings]
gss_indicate_mechs [Netgss_bindings]
gss_init_sec_context [Netgss_bindings]
gss_inquire_context [Netgss_bindings]
gss_inquire_cred [Netgss_bindings]
gss_inquire_cred_by_mech [Netgss_bindings]
gss_inquire_mechs_for_name [Netgss_bindings]
gss_inquire_names_for_mech [Netgss_bindings]
gss_process_context_token [Netgss_bindings]
gss_unwrap [Netgss_bindings]
gss_verify_mic [Netgss_bindings]
gss_wrap [Netgss_bindings]
gss_wrap_size_limit [Netgss_bindings]
gssapi_method [Netftp_client]
This method negotiates the use of GSSAPI authentication and security.
gssapi_props [Netsys_sasl.Server]
Get the GSSAPI props, or raise Not_found
gssapi_props [Netsys_sasl.Client]
Get the GSSAPI props, or raise Not_found
gt_uint4 [Netnumber]
gt_uint8 [Netnumber]
gwrite [Netsys]
gwrite fd_style fd s pos len: Writes up to len bytes to descriptor fd which is supposed to support the I/O style fd_style, i.e.
gwrite_tbuf [Netsys]
Same for a tagged buffer
gwrite_tstr [Netsys]
Same for a tagged string

H
handle_connection [Netcgi_fcgi]
handle_connection config output_type arg_store eh f ~max_conns ~one_shot fd: This is a lower-level interface that processes exactly one connection fd.
handle_connection [Netcgi_scgi]
handle_connection config output_type arg_store eh f ?script_name fd: This is a lower-level interface that processes exactly one connection fd.
handle_connection [Netcgi_ajp]
handle_connection config output_type arg_store eh f ?script_name fd: This is a lower-level interface that processes exactly one connection fd.
handle_request [Netcgi_fcgi]
handle_request config output_type arg_store eh f ~max_conns ~log fd: This is a lower-level interface that processes exactly one request arriving on the existing connection fd.
handle_request [Netcgi_scgi]
handle_request config output_type arg_store eh f ~log fd: This is a lower-level interface that processes exactly one request arriving on the existing connection fd.
handle_request [Netcgi_ajp]
handle_request config output_type arg_store eh f ~log fd: This is a lower-level interface that processes exactly one request arriving on the existing connection fd.
handshake [Netsys_tls]
Procedes the TLS protocol until payload data can be exchanged.
has_console [Netsys_win32]
True if there is a console
hash_function [Netmech_scram_http.PROFILE]
hash_function [Netmech_scram_sasl.PROFILE]
The hash function.
hash_functions [Netmech_digest_http.PROFILE]
List of enabled hash functions.
hashtbl_of_descr [Netmcore_hashtbl]
Look up the hash table for this descriptor
have_anon_posix_semaphores [Netsys_posix]
Returns true if anonymous POSIX semaphores are supported on this system
have_anon_semaphores [Netsys_sem]
Returns true if anonymous semaphores are supported on this system, either natively or emulated via named semaphores.
have_at [Netsys_posix]
Whether the *at functions are available (they were only recently standardized and cannot be expected on all OS yet)
have_event_aggregation [Netsys_posix]
Whether there is an implementation for this OS
have_fadvise [Netsys_posix]
Returns whether the OS supports the fadvise POSIX option
have_fallocate [Netsys_posix]
Returns whether the OS supports the fallocate POSIX option
have_ioprio [Netsys_posix]
Returns true if the system call ioprio_get is supported
have_named_posix_semaphores [Netsys_posix]
Returns true if named POSIX semaphores are supported on this system
have_poll [Netsys_posix]
Whether there is a native poll implementation on this OS
have_posix_semaphores [Netsys_posix]
Returns true if both kinds of semaphores are supported on this system
have_posix_shm [Netsys_posix]
Returns whether the OS supports POSIX shared memory
have_posix_timer [Netsys_posix]
hdr_address [Netsys_mem]
These two functions return the address of the Obj.t and the address of the header of the Obj.t, respectively.
header [Netmcore_hashtbl]
Returns the header
header [Netmcore_matrix]
Returns the header
header [Netmcore_buffer]
Returns the header
header [Netmcore_queue]
Returns the header
header [Netmcore_array]
Returns the header
header_only [Netcgi_apache.Apache.Request]
request_rec header_only field.
headers_in [Netcgi_apache.Apache.Request]
request_rec headers_in field.
headers_out [Netcgi_apache.Apache.Request]
request_rec headers_out field.
heap [Netmcore_hashtbl]
Returns the heap backing this data structure
heap [Netmcore_matrix]
Return the backing heap structure
heap [Netmcore_buffer]
Returns the underlying heap
heap [Netmcore_queue]
Returns the underlying heap
heap [Netmcore_array]
Return the backing heap structure
heap [Netmcore_ref]
Returns the backing heap structure
heap_of_descr [Netmcore_heap]
heap_of_descr pool d: Get the heap for a descriptor.
hello [Netsys_crypto_types.TLS_PROVIDER]
Performs the initial handshake (exchanges credentials and establishes a session).
hex_dump_b [Rpc_util]
Format the contents as hex sequence
hex_dump_m [Rpc_util]
hmac [Netsys_digests]
hmac dg key: returns the digest context computing the HMAC construction (RFC-2104).
hmac [Netauth]
The HMAC algorithm of RFC 2104.
host_distributor [Nethttpd_services]
Configures virtual hosting
host_is_enabled [Rpc_proxy.ReliabilityCache]
Returns whether the host is enabled
hostname [Netcgi_apache.Apache.Request]
request_rec hostname field -- hostname to which the request was made.
hostname [Netcgi_apache.Apache.Server]
server_hostname field (as declared in Apache configuration file).
html40_dtd [Nethtml]
The (transitional) HTML 4.0 DTD, expressed as simplified_dtd
http_delete [Nethttp_client.Convenience]
Does a "DELETE" request with the given URL and returns the response body.
http_delete_message [Nethttp_client.Convenience]
Does a "DELETE" request with the given URL and returns the reply.
http_fs [Nethttp_fs]
Same as normal function
http_get [Nethttp_client.Convenience]
Does a "GET" request with the given URL and returns the message body
http_get_message [Nethttp_client.Convenience]
Does a "GET" request with the given URL and returns the message
http_head_message [Nethttp_client.Convenience]
Does a "HEAD" request with the given URL and returns the reply.
http_password [Nethttp_client.Convenience]
The default password if authentication is required
http_post [Nethttp_client.Convenience]
Does a "POST" request with the given URL and returns the response body.
http_post_message [Nethttp_client.Convenience]
Does a "POST" request with the given URL and returns the reply.
http_put [Nethttp_client.Convenience]
Does a "PUT" request with the given URL and returns the response body.
http_put_message [Nethttp_client.Convenience]
Does a "PUT" request with the given URL and returns the reply.
http_status_of_int [Nethttp]
Returns the status value for an integer code, or raises Not_found
http_trans_id [Nethttp]
Identifies the pure HTTP transport (without SSL), with or without web proxies
http_trans_id [Nethttp_client]
Identifies the pure HTTP transport (without SSL), with or without web proxies
http_transport_channel_type [Nethttp_client]
Transport via HTTP
http_trials [Nethttp_client.Convenience]
number of times every request is tried.
http_user [Nethttp_client.Convenience]
The default user if authentication is required
http_verbose [Nethttp_client.Convenience]
Turns on debug messages on stderr.
https_trans_id [Nethttp]
Identifies anonymous HTTPS transport (i.e.
https_trans_id [Nethttp_client]
Identifies anonymous HTTPS transport (i.e.
https_transport_channel_type [Nethttp_client]
Create a new transport for HTTPS and this configuration.

I
iana_alist [Netsys_digests]
maps the IANA name to the hash function id
iana_find [Netsys_digests]
iana_find name: get the digest name
iana_rev_alist [Netsys_digests]
the reverse
id [Rpc_program]
The ID identifies the program (used in Rpc_client)
idempotent_async_call [Rpc_proxy.ManagedSet]
idempotent_async_call mset async_call arg emit: Picks a new mclient and calls async_call mclient arg emit.
idempotent_sync_call [Rpc_proxy.ManagedSet]
Synchronized version.
ignore_subprocess [Netsys_posix]
Changes the arrangement so that the termination of the subprocess is no longer reported by the file descriptor.
implementation [Netsys_crypto_types.TLS_PROVIDER]
Implementation-defined additional functionality
implementation_name [Netsys_crypto_types.TLS_PROVIDER]
String name of the implementation.
import_private_key_uri [Netsys_crypto_types.PUBKEY_CRYPTO]
indirect reference e.g.
import_private_key_uri_with_pin [Netsys_crypto_types.PUBKEY_CRYPTO]
import_private_key_x509 [Netsys_crypto_types.PUBKEY_CRYPTO]
import a private key from DER
import_public_key_from_private [Netsys_crypto_types.PUBKEY_CRYPTO]
import_public_key_uri [Netsys_crypto_types.PUBKEY_CRYPTO]
indirect reference e.g.
import_public_key_uri_with_pin [Netsys_crypto_types.PUBKEY_CRYPTO]
import_public_key_x509 [Netsys_crypto_types.PUBKEY_CRYPTO]
The DER-encoded subjectPublicKeyInfo
in_buffer_blit [Uq_io]
Blit to a string or memory buffer
in_buffer_fill_e [Uq_io]
Requests that the buffer is filled more than currently, and transitions to `Done eof when there is more data, or the EOF is reached (eof=true).
in_buffer_length [Uq_io]
The length
in_channel_of_mstrings [Netxdr_mstring]
Returns a channel reading from the sequence of mstrings
in_obj_channel [Uq_io]
in_obj_channel d timeout: Creates a synchronous channel from the input device.
inactivate [Uq_io]
Releases the OS resources immediately.
incr_rcache_error_counter [Rpc_proxy.ReliabilityCache]
Increase the error counter for this sockaddr.
increment [Netplex_semaphore]
Increment the named semaphore by 1, and return the new value.
index_from [Netpagebuffer]
index_from nb k c: Searches the character c in the buffer beginning at position k.
index_from [Netbuffer]
index_from nb k c: Searches the character c in the netbuffer beginning at position k.
inet_addr_of_protostring [Netsys]
Converts an IP address to the 4 bytes (IPv4) or 16 bytes (IPv6) representation in network byte order, and vice-versa
init [Netgzip]
By calling this function it is enforced that the (de)-compression algorithms are registered at Netcompression.
init [Nettls_gnutls]
Ensure that GnuTLS is initialized
init [Netsys_signal]
Call this function to ensure that this module is initialized.
init [Netmcore_matrix]
init pool_id n1 n2 f h: Creates a matrix of the passed number of elements (n1 * n2), and for getting the element at position k the function f k is run, and the copy of the result is written to the position.
init [Netmcore_array]
init pool_id n f h: Creates a shared array of the passed number of elements, and for getting the element at position k the function f k is run, and the copy of the result is written to the position.
init_array [Netsys_mem]
let voffset, bytelen = init_array mem offset size: Initializes the memory at offset and following bytes as Ocaml array with size elements.
init_array_bytelen [Netsys_mem]
Returns bytelen if init_array was called with the passed size.
init_console_codepage [Netsys_win32]
Sets the code page of the console to the ANSI code page of the system.
init_credentials [Netsys_sasl_types.SASL_MECHANISM]
Supply the mechanism with credentials.
init_credentials [Nethttp.HTTP_CLIENT_MECHANISM]
Supply the mechanism with credentials.
init_float_array [Netsys_mem]
Same for arrays of floats
init_float_array_bytelen [Netsys_mem]
Same for arrays of floats
init_header [Netsys_mem]
init_header mem offset tag size: Initializes the word at mem+offset as an Ocaml value header with the given tag and the given size (in words).
init_sec_context [Netgssapi_auth.Auth]
Calls G.init_sec_context, and returns (out_context,out_token,flags,props_opt).
init_string [Netsys_mem]
let voffset, bytelen = init_string mem offset len: Initializes the memory at offset and following bytes as Ocaml string with length len.
init_string_bytelen [Netsys_mem]
Returns bytelen if init_string was called with the passed len.
init_value [Netsys_mem]
let voffset, bytelen = init_value mem offset v flags: Initializes the memory at offset and following bytes as copy of the boxed value v.
initgroups [Netsys_posix]
See initgroups(3).
input_bytes [Netchannels]
Same as function
input_channel [Netchannels]
Same as function
input_command [Netchannels]
Same as function
input_e [Uq_io]
let e = input_e d s pos len: Reads data from d and puts it into the string s starting at pos and with maximum length len.
input_line_e [Uq_io]
let e = input_line_e d: Reads the next line from d and transitions to `Done line when done.
input_lines_e [Uq_io]
let e = input_lines_e d: Reads as many lines from d as can be found in the buffer of d, and transitions to `Done lines.
input_memory [Netchannels]
Same as function
input_stream_adapter [Shell_fs]
Arranges that the input of a shell command is made available as an out_obj_channel:
input_string [Netchannels]
Same as function
input_thread_event [Netsys_win32]
This event is signaled when there is data to read, or the EOF is reached, or there is an error condition
input_thread_proxy_descr [Netsys_win32]
Returns the proxy descriptor
input_thread_read [Netsys_win32]
input_thread_read t s pos len: Tries to read data from the buffer.
input_tstring [Netchannels]
Same for tagged strings (only as function)
insert_char [Netbuffer]
insert_char nb p c: Inserts character c at position p into the netbuffer nb
insert_string [Netbuffer]
insert_string nb p s: Inserts the value of string s at position p into the netbuffer nb
insert_sub_string [Netbuffer]
insert_subbytes [Netbuffer]
Same for bytes
insert_submemory [Netbuffer]
Same for memory
insert_substring [Netbuffer]
insert_string nb p s k n: Inserts a substring of string s at position p into the netbuffer nb.
insert_subtstring [Netbuffer]
Same for tagged string
install_job_handlers [Shell_sys]
Installs handlers as configured before.
install_subprocess_handler [Netsys_posix]
Installs a SIGCHLD handler for watching subprocesses.
int [Netasn1.Value]
Create an int
int32 [Netasn1.Value]
Create an int
int32_array_manager [Netshm_data]
The identity representation manager
int32_manager [Netshm_data]
Represents an int32 as one-element int32_array
int32_of_int4 [Netnumber]
int32_of_int8 [Netnumber]
int32_of_uint4 [Netnumber]
int32_of_uint8 [Netnumber]
int4_as_bytes [Netnumber.ENCDEC]
int4_as_string [Netnumber.ENCDEC]
int4_of_int [Netnumber]
int4_of_int32 [Netnumber]
int4_of_int64 [Netnumber]
int64 [Netasn1.Value]
Create an int
int64_manager [Netshm_data]
Represents an int64 as two-element int32_array
int64_of_file_descr [Netsys]
Returns the file descriptor as int64 number.
int64_of_int4 [Netnumber]
int64_of_int8 [Netnumber]
int64_of_uint4 [Netnumber]
int64_of_uint8 [Netnumber]
int8_as_bytes [Netnumber.ENCDEC]
int8_as_string [Netnumber.ENCDEC]
int8_of_int [Netnumber]
int8_of_int32 [Netnumber]
int8_of_int64 [Netnumber]
int_b256 [Netasn1.Value]
Create an int from a base 256 number, big endian, signed
int_blit [Netaux.ArrayAux]
A specialisation of Array.blit for int arrays.
int_manager [Netshm_data]
Uses either int32_manager or int64_manager to represent int, depending on the size of int.
int_of_act_events [Netsys_posix]
int_of_file_descr [Netsys_posix]
Return the file descriptor as integer.
int_of_http_status [Nethttp]
Returns the integer code for a status value
int_of_int4 [Netnumber]
int_of_int8 [Netnumber]
int_of_req_events [Netsys_posix]
int_of_uint4 [Netnumber]
int_of_uint8 [Netnumber]
int_series [Netaux.ArrayAux]
int_series src srcpos dst dstpos len n: Computes for every i, 0 <= i < len: dst.(dstpos+i) = n + SUM(j=0..(i-1): src.(srcpos+j))
int_var [Netplex_cenv]
interface [Netsys_gssapi.GSSAPI]
internal_redirect [Netcgi_apache.Apache.Request]
Internally redirects immediately to uri.
internal_redirect_handler [Netcgi_apache.Apache.Request]
Internally redirects immediately to uri using handler specified by r.
internal_rpc_multiplex_controller [Rpc_transport]
The multiplex controller for internal connections
interrupt_event_aggregator [Netsys_posix]
If create_event_aggregator was called with true as argument, the aggregator is interruptible, and this function interrupts it.
invoke_method [Netftp_client]
This FTP method simply invokes command.
io_obj_channel [Uq_io]
io_obj_channel d timeout: Creates a bidirectional synch channel from d.
ioprio_get [Netsys_posix]
Retrieve the priority of the target.
ioprio_set [Netsys_posix]
Sets the priority of the target processes.
ip_url_syntax [Neturl]
Syntax for IP based protocols.
ipproto_tcp [Rpc_portmapper_aux]
ipproto_udp [Rpc_portmapper_aux]
ipv6_inet_addr [Netsys]
IPv6-ification: If the input address is for IPv4, it is mapped to the IPv6 address space (so an IPv6 socket can be bound)
ipv6_socksymbol [Netsockaddr]
IPv6-ification of numeric IP addresses: IPv4 addresses are mapped to the IPv6 address space.
is_MSIE [Netcgi_common]
is_MSIE user_agent tells whether the user_agent is Microsoft Internet Explorer.
is_absolute [Netsys]
Whether this file path is absolute.
is_ascii_compatible [Netconversion]
"ASCII compatible" means: The bytes 1 to 127 represent the ASCII codes 1 to 127, and no other representation of a character contains the bytes 1 to 127.
is_bigarray [Netsys_mem]
Checks whether the objects ia actually a bigarray
is_cgi [Netcgi_cgi]
is_cgi says whether the script is run in a CGI environment.
is_console [Netsys_win32]
Tests whether the descriptor is the input or the output stream of the console.
is_crt_fd [Netsys_win32]
Tests whether the descriptor has a certain CRT counterpart.
is_dummy [Rpc_server]
Whether this is a server in `Dummy mode.
is_empty [Netmcore_queue]
Tests whether the queue is empty
is_encryption_supported [Netx509_pubkey_crypto]
Whether this algorithm is supported
is_endpoint_host [Nettls_support]
is_endpoint_host name props: checks whether name matches the certificate of the endpoint in props.
is_executable [Shell_sys]
Returns true if there is an executable file for the command, and it is permitted to run this file (as stated by the file permissions).
is_ipv4_inet_addr [Netsys]
Whether the address is an IPv4 address (including IPv4 addresses mapped into the IPv6 adress space)
is_ipv6_inet_addr [Netsys]
Whether the address is an IPv6 address (excluding IPv4 addresses mapped into the IPv6 adress space)
is_ipv6_system [Netsys]
Whether IPv6 is available and usable.
is_multicast_inet_addr [Netsys]
Whether the address is a multicast address (either IPv4 or IPv6)
is_no_context [Netgss_bindings]
is_no_credential [Netgss_bindings]
is_no_name [Netgss_bindings]
is_prefix [Netcgi_common]
is_prefix pre s checks whether pre is a prefix of s.
is_prird [Netsys]
Test whether the descriptor would not block if one of the input, output, or priority input operations were done.
is_readable [Netsys]
is_running [Unixqueue]
Whether the event loop is running
is_running [Equeue]
Returns whether the event loop is active
is_signing_supported [Netx509_pubkey_crypto]
Whether this algorithm is supported
is_single_byte [Netconversion]
Returns whether the encoding is a single-byte encoding
is_stderr [Netsys]
Returns whether the descriptors are stdin/stdout/stderr
is_stdin [Netsys]
is_stdout [Netsys]
is_up [Rpc_client]
Return whether the client is up
is_virtual [Netcgi_apache.Apache.Server]
is_virtual field.
is_writable [Netsys]
iso8601_week_pair [Netdate]
Returns (week_number, year) for the ISO-8601 definition of weeks.
iter [Netsys_global]
iter f: for every variable call f name value version
iter [Netfs]
iter pre fs start: Iterates over the file hierarchy at start.
iter [Netshm_hashtbl]
iter f tbl applies f to all bindings in table tbl.
iter [Netshm]
iter f tbl applies f to all bindings in table tbl.
iter [Netmcore_hashtbl]
Hashtbl.iter f tbl applies f to all bindings in table tbl.
iter [Netmcore_queue]
iter f q: Iterates over the elements of the queue and calls f x for each element x.
iter_env [Shell_sys]
Iterates over the strings of the environment, and calls f s for every string s.
iter_env_vars [Shell_sys]
Iterates over the variables of the environment, and calls f name value for every variable with name and value.
iter_keys [Netshm_hashtbl]
iter_keys f tbl applies f to all keys in table tbl.
iter_keys [Netshm]
iter_keys f tbl applies f to all keys in table tbl.
iter_lines [Netmime_string]
iter_lines f s pos len: Splits the substring of s from pos to pos+len into lines, and calls f line for each line.
iter_lines_poly [Netmime_string]
even more polymorphic
iteration_count_limit [Netmech_scram_sasl.PROFILE]
The maximum iteration count supported
iv_lengths [Netsys_crypto_types.SYMMETRIC_CRYPTO]
Supported iv lengths as pairs min,max.

J
job_status [Shell_sys]
Returns the status.
join [Netmcore_process]
let r_opt = join jp pid: Waits until the process pid finishes, and uses the join point jp to extract the result.
join [Netmcore]
let res_opt = join join_point pid: Waits until the process pid is done, and returns the result value if any.
join_nowait [Netmcore_process]
Like join, but it is not waited for the termination of the process.
join_nowait [Netmcore]
let res_opt = join_nowait join_point pid: Checks if the process pid is done, and returns the result value if so.
join_path [Neturl]
Concatenates the path components (reverse function of split_path).

K
kea [Netx509_pubkey.Keyagreement]
KEA
kea_key [Netx509_pubkey.Key]
KEA.
keep_away_from [Netsys_signal]
keep_away_from signo: This signal signo is added to the "keep away list".
keep_away_list [Netsys_signal]
Returns the "keep away list".
key [Nethttp_client]
Create a key object.
key_creds [Nethttp_client]
Create a key object from a list of credentials
key_lengths [Netsys_crypto_types.SYMMETRIC_CRYPTO]
Supported key lengths as pairs min,max.
key_oid_of_encrypt_alg [Netx509_pubkey.Encryption]
The OID public keys need to have
key_oid_of_kex_alg [Netx509_pubkey.Keyagreement]
The OID public keys need to have
key_oid_of_sign_alg [Netx509_pubkey.Signing]
The OID public keys need to have
kill [Shell_sys]
Sends a signal to the passed process.
kill_all_subprocesses [Netsys_posix]
kill_all_subprocess signal override nogroup: Sends a signal to potentially all subprocesses.
kill_process_group [Shell_sys]
Kills the process group if it is still (at least partially) running.
kill_processes [Shell_sys]
Kills the individual processes of the job which are still running.
kill_subprocess [Netsys_posix]
Sends this signal to the subprocess if this process still exists.
killpg_all_subprocesses [Netsys_posix]
killpg_all_subprocess signal override: Sends a signal to potentially all subprocesses belonging to a process group (i.e.
killpg_subprocess [Netsys_posix]
Sends this signal to the process group of the subprocess if there is still a watched subprocess belonging to this group.
kp_client_auth [Netx509.KP]
kp_code_signing [Netx509.KP]
kp_email_protection [Netx509.KP]
kp_ocsp_signing [Netx509.KP]
kp_server_auth [Netx509.KP]
kp_time_stamping [Netx509.KP]

L
l9n_from_locale [Netdate]
Retrieves the localization from the passed locale (use "" for the standard locale).
last_chars [Netstring_str]
Same as string_after
last_chars [Netstring_pcre]
Same as string_after
ldap_server [Netldap]
Specifies how to reach the server: e.g.
ldap_server_of_url [Netldap]
Gets the host and port from an LDAP URL.
ldap_url_attributes [Neturl_ldap]
ldap_url_dn [Neturl_ldap]
ldap_url_extensions [Neturl_ldap]
Return components of the URL.
ldap_url_filter [Neturl_ldap]
ldap_url_provides [Neturl_ldap]
Whether all the selected URL components are present and the accessor can return them (even if empty)
ldap_url_scope [Neturl_ldap]
le_uint4 [Netnumber]
le_uint8 [Netnumber]
left_pair_manager [Netshm_data]
Uses the same representation as pair_manager, but the resulting data manager only reads the left value of the pair.
length [Netsys_polypipe]
return the number of messages in the buffer
length [Netpagebuffer]
The length
length [Netbuffer]
Returns the logical length of the buffer
length [Netshm_array]
Returns the length of the array
length [Netshm_hashtbl]
length tbl returns the number of bindings in tbl.
length [Netshm]
length tbl returns the number of bindings in tbl.
length [Netmcore_hashtbl]
Hashtbl.length tbl returns the number of bindings in tbl.
length [Netmcore_buffer]
Returns the length
length [Netmcore_queue]
Returns the number of elements in the queue (O(1))
length [Netmcore_array]
Returns the length
length_mstrings [Netxdr_mstring]
returns the sum of the lengths of the mstrings
length_of_packed_value [Rpc_packer]
length_tstring [Netstring_tstring]
Get the length of a tagged string
level_names [Netlog]
The level names indexed by weight
level_of_string [Netlog]
level_of_string [Netplex_log]
Convert a string to a level
level_weight [Netlog]
A number correspondig to the level
level_weight [Netplex_log]
An integer corresponding to the level
lexbuf_of_in_obj_channel [Netchannels]
Creates a lexical buffer from an input channel.
lexeme [Netulex.Ulexing]
Returns the lexeme as array of Unicode code points
lexeme_char [Netulex.Ulexing]
Returns the code point of a certain character of the lexeme
lexeme_end [Netulex.Ulexing]
The character position of the end of the lexeme
lexeme_length [Netulex.Ulexing]
The length of the lexeme in characters
lexeme_start [Netulex.Ulexing]
The character position of the start of the lexeme
lift_in [Netchannels]
Turns a rec_in_channel or raw_in_channel, depending on the passed variant, into a full in_obj_channel object.
lift_out [Netchannels]
Turns a rec_out_channel or raw_out_channel, depending on the passed variant, into a full out_obj_channel object.
linear_distributor [Nethttpd_services]
Configures linear distribution
lines_of_in_obj_channel [Netchannels]
Reads from the input channel until EOF and returns the lines as string list.
linkat [Netsys_posix]
linkat olddirfd oldpath newdirfd newpath flags
list [Netsys_signal]
Returns the list of signal handlers
list_header [Netmime_string]
list_header s pos len: Returns the headers as list of pairs (name,value).
list_method [Netftp_client]
Lists the contents of the directory dir using the LIST command.
listen_on [Uq_server]
listen_on addr: Creates a server endpoint for addr
listen_on_inet_socket [Uq_server]
listen_on_inet_socket addr port stype opts: Creates a TCP or UDP server socket for IPv4 or IPv6, depending on the type of address.
listen_on_unix_socket [Uq_server]
listen_on_unix_socket path stype opts: Creates a Unix Domain server socket for the given path.
listen_on_w32_pipe [Uq_server]
listen_on_w32_pipe mode path opts: Creates a Win32 pipe server and returns the proxy descriptor.
listener [Uq_engines_compat]
listener [Uq_server]
This engine creates a server socket listening on the listen_address.
literal_glob_expr [Netglob]
Returns an expression that matches literally the passed string
load [Netunidata]
load key: Loads the table for this key, if not already loaded or statically linked in.
load_charset [Netunidata]
load_charset enc: Loads the forward and backward mapping tables for this charset.
local_fs [Netfs]
local_fs(): Returns a filesystem object for the local filesystem.
local_fsys [Netglob]
Accesses the local filesystem
local_interpreter [Shell_fs]
Executes commands on the local machine
local_path_of_file_url [Neturl]
Extracts the path from an absolute file URL, and returns a correct path name.
local_user_info [Netglob]
Get the home directory of a user from the local user database.
localzone [Netdate]
The offset in minutes for the local time zone from the UTC.
localzone_nodst [Netdate]
Returns the offset for the local time zone for the case that daylight savings are not effective.
lock [Netmappings]
lock [Netplex_mutex]
Wait until the mutex is free, and locks it
lock [Netmcore_mutex]
Locks the mutex
log [Netlog.Debug]
Writes a log message
log [Netlog]
Writes a log message
log [Netplex_cenv]
Writes a log message
logand_inet_addr [Netsys]
Returns the bitwise AND of the two argument addresses
logf [Netlog.Debug]
Writes a log message like printf
logf [Netlog]
Writes a log message like printf
logf [Netplex_cenv]
Writes a log message like printf
logger_factories [Netplex_log]
All built-in logger factories
logical_int32_of_uint4 [Netnumber]
logical_int64_of_uint8 [Netnumber]
logical_uint4_of_int32 [Netnumber]
logical_uint8_of_int64 [Netnumber]
login_method [Netftp_client]
This FTP method logs the user in.
lognot_inet_addr [Netsys]
Returns the bitwise NOT of the argument address
logor_inet_addr [Netsys]
Returns the bitwise OR of the two argument addresses
logxor_inet_addr [Netsys]
Returns the bitwise XOR of the two argument addresses
lookup [Netsys_win32]
Returns the real object behind a proxy descriptor, or raises Not_found.
lookup [Netplex_cenv]
lookup service_name protocol_name tries to find a Unix domain socket for the service and returns it.
lookup_attribute_type_by_name [Netx509.DN_attributes]
Looks the name up, which can either be a full name or a short name.
lookup_attribute_type_by_name [Netdn.AT_LOOKUP]
Looks the name up, which can either be a full name or a short name.
lookup_attribute_type_by_oid [Netx509.DN_attributes]
Looks the OID up, and returns (full_name, short_names).
lookup_attribute_type_by_oid [Netdn.AT_LOOKUP]
Looks the OID up, and returns (full_name, short_names).
lookup_camlbox_address [Netmcore_camlbox]
Returns the address of the camlbox identified by this resource ID
lookup_camlbox_sender [Netmcore_camlbox]
lookup_camlbox_sender res_id: Returns the sender object of the camlbox identified by this resource ID
lookup_container_sockets [Netplex_cenv]
lookup_container_sockets service_name protocol_name: returns the Unix Domain paths of all container sockets for this service and protocol.
lookup_decoder [Netcompression]
Returns the decoder, or raises Not_found
lookup_dn_ava [Netx509]
Find the first relative DN setting this OID (or Not_found)
lookup_dn_ava_utf8 [Netx509]
Same as lookup_dn_ava, but additionally converts the value to UTF-8
lookup_encoder [Netcompression]
Returns the encoder, or raises Not_found
lookup_event [Netsys_win32]
lookup_executable [Shell_sys]
Searches an executable file.
lookup_input_thread [Netsys_win32]
lookup_output_thread [Netsys_win32]
Returns the real object.
lookup_pipe [Netsys_win32]
lookup_pipe_server [Netsys_win32]
lookup_process [Netsys_win32]
loop [Uq_libevent.LIBOEVENT]
lt_uint4 [Netnumber]
lt_uint4 is true iff the first value is less than the second value as unsigned int
lt_uint8 [Netnumber]
lt_uint8 is true iff the first value is less than the second value as unsigned int

M
m [Netmech_scram.AES_CTS]
mac [Netsys_crypto_types.SYMMETRIC_CRYPTO]
Returns the MAC for AEAD ciphers.
main [Netcgi_apache.Apache.Request]
request_rec main field.
make [Nethttp.Cookie]
make ?expires ?domain ?path ?secure name value creates a new cookie with name name holding value.
make [Netmcore_matrix]
make pool_id n1 n2 x h: Creates a matrix of the passed number of elements (n1 * n2), copies the element x, and initializes each element of the new array with the single copy of x.
make [Netmcore_array]
make pool_id n x h: Creates a shared array of the passed number of elements, copies the element x, and initializes each element of the new array with the single copy of x.
make [Netcgi.Cookie]
make ?expires ?domain ?path ?secure name value creates a new cookie with name name holding value.
make [Netcgi_common.Cookie]
make_ldap_url [Neturl_ldap]
Create an LDAP URL
make_pattern [Netaux.KMP]
make_temporary_file [Netchannels]
Creates a temporary file in the directory tmp_directory with a name prefix tmp_prefix and a unique suffix.
make_tls [Nettls_gnutls]
The implementation of TLS backed by GnuTLS, here for an arbitrary TLS_EXCEPTIONS module
make_url [Neturl]
Creates a URL from components:
make_var_type [Netplex_cenv]
Create get and set functions for any (monomorphic) type.
makechar [Netconversion]
makechar enc i: Creates the string representing the Unicode code point i in encoding enc.
manage [Netshm_array]
Manages a shared memory object as an array, including the representation of arbitrary O'Caml values.
manage [Netshm_hashtbl]
Manages a shared memory object as a hash table like Netshm.manage, and additionally represent arbitrary O'Caml values.
manage [Netshm]
Starts managing an open shared memory object as shm_table.
manage_file [Netmcore]
hands over a file to the manager
manage_sem [Netmcore]
hands over a named semaphore to the manager
manage_shm [Netmcore]
hands over a named shm object to the manager
manage_shm_sc [Netmcore]
hands over a named shm object plus semaphore container to the manager
map_cb [Netgss_bindings]
map_engine [Uq_engines_compat]
map_engine [Uq_engines]
Same as function
map_list [Nethtml]
map_list f doclst: Applies f to all attribute values and data strings (except the attributes of "?", "!", or "--" nodes).
map_xv_enum_fast [Netxdr]
Works for both XV_enum and XV_enum_fast
map_xv_struct_fast [Netxdr]
Works for both XV_struct and XV_struct_fast
map_xv_union_over_enum_fast [Netxdr]
Works for both XV_union_over_enum and XV_union_over_enum_fast.
marshal_client_props [Netsys_gssapi]
marshal_server_props [Netsys_gssapi]
match_beginning [Netstring_str]
Returns the position where the matched part begins
match_beginning [Netstring_pcre]
Returns the position where the matched part begins
match_end [Netstring_str]
Returns the position where the matched part ends
match_end [Netstring_pcre]
Returns the position where the matched part ends
match_glob_expr [Netglob]
Matches the glob_expr against a string.
matched_bytes [Netstring_str]
Same for bytes
matched_bytes [Netstring_pcre]
Same for bytes
matched_group [Netstring_str]
Extracts the substring the nth group matches from the whole string.
matched_group [Netstring_pcre]
Extracts the substring the nth group matches from the whole string.
matched_group_bytes [Netstring_str]
Same for bytes
matched_group_bytes [Netstring_pcre]
Same for bytes
matched_string [Netstring_str]
Extracts the matched part from the string.
matched_string [Netstring_pcre]
Extracts the matched part from the string.
max_age [Nethttp.Cookie]
The expiration time of the cookie, in seconds.
max_age [Netcgi.Cookie]
The expiration time of the cookie, in seconds.
max_age [Netcgi_common.Cookie]
The expiration time of the cookie, in seconds.
max_int4 [Netnumber]
max_int8 [Netnumber]
max_uint4 [Netnumber]
max_uint8 [Netnumber]
mcast_add_membership [Netsys]
Join a multicast group.
mcast_drop_membership [Netsys]
Leave a multicast group.
mcast_set_loop [Netsys]
Whether sent multicast messages are received by the sending host
mcast_set_ttl [Netsys]
Set TTL/hops value
mclient_serial [Rpc_proxy.ManagedClient]
Get the serial number of the connection.
mclient_state [Rpc_proxy.ManagedClient]
Get the state
mdtm_method [Netftp_client]
Determines the date and time of the last modification of file.
mechanism_name [Netsys_sasl.Info]
mechanism_name [Netmech_gs2_sasl.PROFILE]
The GS2 version of the mechanism name (w/o "-PLUS" suffix)
mechanism_name [Netsys_sasl_types.SASL_MECHANISM]
mechanism_name [Netmech_scram]
The official name of the mechanism
mechanism_name [Nethttp.HTTP_CLIENT_MECHANISM]
mechanism_oid [Netmech_gs2_sasl.PROFILE]
The OID of the mechanism to use
mem [Netshm_hashtbl]
mem tbl key checks if key is bound in tbl.
mem [Netshm]
mem tbl key checks if key is bound in tbl.
mem [Netmcore_hashtbl]
Safe version of mem_ro in the presence of parallel modifications.
mem_read [Netsys_mem]
A version of Unix.read that uses a memory buffer.
mem_recv [Netsys_tls]
Same for a memory-backed buffer
mem_recv [Netsys_mem]
mem_ro [Netmcore_hashtbl]
Hashtbl.mem tbl x checks if x is bound in tbl.
mem_send [Netsys_tls]
Same for a memory-backed buffer
mem_send [Netsys_mem]
Versions of Unix.recv, and Unix.send using memory buffers.
mem_write [Netsys_mem]
A version of Unix.single_write that uses a memory buffer.
memory [Netshm]
memory_address [Netsys_mem]
Returns the start address of the buffer
memory_based_mstrings [Netxdr_mstring]
Uses memory to represent mstrings.
memory_map_file [Netsys_mem]
memory_map_file fd shared size: Maps size bytes of the file fd into memory, and returns the memory buffer like Bigarray.Array1.map_file.
memory_mime_body [Netmime]
Same as function
memory_of_bigarray [Netsys_mem]
memory_of_bigarray_1 [Netsys_mem]
memory_of_bigarray_2 [Netsys_mem]
memory_of_bigarray_3 [Netsys_mem]
These functions return an arbitrary bigarray as memory.
memory_of_buffer [Netgss_bindings]
memory_of_bytes [Netsys_mem]
Return a new bigarray as a copy of the string
memory_of_string [Netsys_mem]
Return a new bigarray as a copy of the string
memory_ops [Netstring_tstring]
Implementation of the operations for memory
memory_pool_based_mstrings [Netxdr_mstring]
Uses memory to represent mstrings.
memory_to_mstring [Netxdr_mstring]
Represent memory as mstring (no copy)
memory_unmap_file [Netsys_mem]
Unmaps the file.
meta_engine [Uq_engines_compat]
meta_engine [Uq_engines]
Same as function
method_distributor [Nethttpd_services]
Configures method distribution
method_name [Netcgi_apache.Apache.Request]
request_rec method field.
method_number [Netcgi_apache.Apache.Request]
request_rec method_number field (given symbolically instead of a number).
mime [Netcgi.Argument]
mime_arg ?name msg creates a MIME-structured CGI argument called name with contents msg.
min_int4 [Netnumber]
min_int8 [Netnumber]
min_uint4 [Netnumber]
min_uint8 [Netnumber]
minimum_size [Netmcore_heap]
Returns the size value one must pass to create_heap at minimum to put this root element onto the heap.
mk_date [Netdate]
Format the seconds (plus nanos if present) as a string
mk_dlog [Netlog.Debug]
let dlog = mk_dlog "M" enable: The conditional debug function
mk_dlogr [Netlog.Debug]
let dlogr = mk_dlog "M" enable: The conditional debug function
mk_fp4 [Netnumber]
mk_fp8 [Netnumber]
mk_int4 [Netnumber]
mk_int8 [Netnumber]
mk_internet_date [Netdate]
Convert the time (seconds since the epoch) to a date string that conforms to RFC 3339.
mk_mail_date [Netdate]
Convert the time (seconds since the epoch) to a date string that conforms to RFC 1123 (which updates RFC 822).
mk_param [Netmime_string]
Creates a parameter from a value (in decoded form).
mk_uint4 [Netnumber]
mk_uint8 [Netnumber]
mk_<t> create integer values from character tuples.
mk_url_encoded_parameters [Netencoding.Url]
The argument is a list of (name,value) pairs.
mk_usenet_date [Netdate]
Convert the time (seconds since the epoch) to a date string that conforms to RFC 1036 (which obsoletes RFC 850).
mkdir_method [Netftp_client]
Creates the named directory
mkdirat [Netsys_posix]
Same as Unix.mkdir but the file is taken relative to the directory given by first argument
mkfifoat [Netsys_posix]
mkfifoat dirfd path mode
mknod [Netsys_posix]
Creates the node with the given permissions and the given type
mlsd_method [Netftp_client]
Gets the entries for this directory.
mlst_method [Netftp_client]
Get the file entry for file.
mode [Netsys_crypto_types.SYMMETRIC_CRYPTO]
Returns the mode.
modify [Netplex_main]
Modifies the command-line configuration object
modify [Netmcore_heap]
modify h mutate: This function locks the heap so that this process has exclusive write access to it for the duration of the mutate function.
modify [Netldap]
Same as synchronous function
modify_close_on_exec [Netsys_win32]
Sets the close-on-exec flag, i.e.
modify_dn [Netldap]
Same as synchronous function
modify_dn_e [Netldap]
modify_dn_e conn ~dn ~new_rdn ~delete_old_rdn ~new_superior: renames and/or moves the entry in the tree.
modify_e [Netldap]
modify_e conn ~dn ~changes (): Modifies attributes of the entry for dn.
modify_fd_event_source [Netsys_posix]
Modifies the set of events monitored at this event source
modify_password [Netldap]
Same as synchronous function
modify_password_e [Netldap]
This is the LDAP extension for modifying passwords (potentially outside the tree; RFC 3062).
modify_url [Neturl]
Modifies the passed components and returns the modified URL.
moncontrol [Netsys]
Interface to the moncontrol routine of the GPROF profiler.
monitor_async [Uq_mt]
let result = monitor_async f arg: For calling RPC-style asynchronous clients.
monitor_do [Uq_mt]
let result = monitor_do mon f arg: Just runs f arg in the scope of the monitor, and returns the result.
monitor_run [Uq_mt]
let result = monitor_run mon f outer_esys arg: Runs another engine within the monitor.
move [Netconversion]
Moves the cursor one character to the right, or if num is passed, this number of characters to the right.
mp [Netplex_mp]
Uses Unix.fork to create new threads.
mset_load [Rpc_proxy.ManagedSet]
Returns the number of pending calls per service
mset_pick [Rpc_proxy.ManagedSet]
Pick an mclient for another call, or raise Cluster_service_unavailable.
mset_services [Rpc_proxy.ManagedSet]
Returns the service array
mstrings_of_in_channel [Netxdr_mstring]
Returns the data of a channel as a sequence of mstrings
mstrings_of_packed_value [Rpc_packer]
Get the packed string.
msync_engine [Uq_engines_compat]
msync_engine [Uq_engines]
Same as function
mt [Netplex_mt]
Uses Thread.create to create new threads
multi_file_logger [Netplex_log]
multi_file_logger_factory [Netplex_log]
Reads a logging section like
mut_pool [Netmcore_heap]
Return the pool ID
mut_sem_container [Netmcore_heap]
Return the semaphore container
mutual [Netmech_digest_http.PROFILE]
If true, the Authentication-Info header is checked.
mutual [Netmech_scram_http.PROFILE]

N
n_fold [Netauth]
Blumenthal's n-fold algorithm for an n that is divisible by 8.
name [Netsys_crypto_types.DIGESTS]
returns the name of the digest.
name [Netsys_crypto_types.SYMMETRIC_CRYPTO]
Returns the name.
name [Nethttp.Cookie]
The name of the cookie.
name [Netcgi.Cookie]
The name of the cookie.
name [Netcgi_common.Cookie]
name_alist [Netsys_digests]
maps the OCamlnet name to the hash function id
name_of_shm [Netshm]
Returns the name of an object
name_rev_alist [Netsys_digests]
the reverse
names [Netlog.Debug]
Return the possible module names for enable_module and disable_module
nanosleep [Netsys_posix]
nanosleep t t_rem: Sleeps for t seconds.
nativeint_manager [Netshm_data]
Uses either int32_manager or int64_manager to represent nativeint, depending on the size of nativeint.
net_db_dir [Netunidata]
Returns the directory where the dynamic tables can be found
net_ext_ciphers [Nettls_nettle_bindings]
net_have_crypto [Nettls_gnutls_bindings]
net_have_gcm_aes [Nettls_nettle_bindings]
net_have_pubkey [Nettls_gnutls_bindings]
net_nettle_cipher_name [Nettls_nettle_bindings]
net_nettle_ciphers [Nettls_nettle_bindings]
net_nettle_create_cipher_ctx [Nettls_nettle_bindings]
net_nettle_create_hash_ctx [Nettls_nettle_bindings]
net_nettle_decrypt [Nettls_nettle_bindings]
net_nettle_encrypt [Nettls_nettle_bindings]
net_nettle_gcm_aes_init [Nettls_nettle_bindings]
net_nettle_hash_digest [Nettls_nettle_bindings]
net_nettle_hash_init [Nettls_nettle_bindings]
net_nettle_hash_name [Nettls_nettle_bindings]
net_nettle_hash_update [Nettls_nettle_bindings]
net_nettle_hashes [Nettls_nettle_bindings]
net_nettle_set_decrypt_key [Nettls_nettle_bindings]
net_nettle_set_encrypt_key [Nettls_nettle_bindings]
nethttpd_factory [Nethttpd_plex]
Factory for a web server component.
nethttpd_processor [Nethttpd_plex]
netplex_processor mk_config http_service: Creates a Netplex processor for Nethttpd.
netid_of_inet_addr [Rpc]
Get the netid for an Internet address
nettle_gcm_aes_decrypt [Nettls_nettle_bindings]
nettle_gcm_aes_digest [Nettls_nettle_bindings]
nettle_gcm_aes_encrypt [Nettls_nettle_bindings]
nettle_gcm_aes_set_iv [Nettls_nettle_bindings]
nettle_gcm_aes_set_key [Nettls_nettle_bindings]
nettle_gcm_aes_update [Nettls_nettle_bindings]
nettls_deinit [Nettls_gnutls_bindings]
nettls_init [Nettls_gnutls_bindings]
new_group [Unixqueue]
Create a new, empty group for the event system
new_job [Shell_sys]
Creates a new job descriptor.
new_serial [Netlog.Debug]
Create new serial number
new_trans_id [Nethttp]
Allocates and returns a new ID
new_trans_id [Nethttp_client]
Allocates and returns a new ID
new_wait_id [Unixqueue]
Create a new unique wait identifier
next [Netcgi_apache.Apache.Request]
request_rec next field.
nlst_method [Netftp_client]
Lists the contents of the directory dir using the NLST command The representation must not be `Image.
no_channel_bindings [Netgss_bindings]
no_context [Netgss_bindings]
no_credential [Netgss_bindings]
no_name [Netgss_bindings]
no_oid [Netgss_bindings]
no_oid_set [Netgss_bindings]
norm_inet_addr [Netsys]
Normalization: If the input address is an IPv4 address mapped into the IPv6 address space, the IPv4 address is extracted.
norm_path [Neturl]
Removes "." and ".." from the path if possible.
norm_socksymbol [Netsockaddr]
Normalizes numeric IP addresses: if the address is an IPv4 address mapped to the IPv6 address space, the real IPv4 address is returned.
note_auth_failure [Netcgi_apache.Apache.Request]
Set headers to tell browser that authentication failed.
note_basic_auth_failure [Netcgi_apache.Apache.Request]
Set headers to tell browser that basic authentication failed.
note_digest_auth_failure [Netcgi_apache.Apache.Request]
Set headers to tell browser that digest authentication failed.
notes [Netcgi_apache.Apache.Request]
request_rec notes field.
nt_anonymous [Netsys_gssapi]
anonymous name
nt_export_name [Netsys_gssapi]
an export name
nt_hostbased_service [Netsys_gssapi]
names like "service@hostname"
nt_hostbased_service_alt [Netsys_gssapi]
another OID for the same (RFC 1964 mentions it)
nt_krb5_principal_name [Netsys_gssapi]
a Kerberos 5 principal name (see Netgssapi_support for parsers
nt_machine_uid_name [Netsys_gssapi]
user ID in host byte order
nt_string_uid_name [Netsys_gssapi]
user ID as string of digits
nt_user_name [Netsys_gssapi]
names like "username"
nth [Netbuffer]
Alias for get
null [Rpc_portmapper]
Calls the 'NULL' procedure of the portmapper.
null'async [Rpc_portmapper]
null_dlogger [Netlog.Debug]
The "logger" not printing anything
null_proc_name [Rpc_program]
Returns the name of procedure 0 (or None if not found)
null_tls_cache [Nethttp_client]
This "cache" does not remember any session
null_url [Neturl]
A URL without any component and null_url_syntax
null_url_syntax [Neturl]
An URL syntax that recognizes nothing.

O
obj_address [Netsys_mem]
of_compat_activation [Netcgi1_compat.Netcgi_types]
Portage: of_compat_activation converts an old style cgi_activation to a new CGI-like object.
of_compat_argument [Netcgi1_compat.Netcgi_types]
Portage: of_compat_argument a converts an old style argument a to a new style one.
of_compat_config [Netcgi1_compat.Netcgi_env]
Portage: of_compat_config c transform the old configuration c into one suitable for the new interface.
of_compat_environment [Netcgi1_compat.Netcgi_env]
Portage: of_compat_environment e converts the old environment e to the new interface.
of_netscape_cookie [Nethttp.Cookie]
Convert a Netscape cookie to the new representation
of_netscape_cookie [Netcgi.Cookie]
Convert a Netscape cookie to the new representation
of_record [Netcgi_common.Cookie]
Conversion from the deprecated style of cookie.
of_stream_fs [Netglob]
Use an arbitrary network filesystem for globbing
of_string [Netoid]
Parses an OID in dot notation, e.g.
of_string_curly [Netoid]
Parses an OID in curly brace notation, e.g.
ofb_of_ecb [Netsys_crypto_modes.Symmetric_cipher]
For a given cipher in ECB mode, a new cipher in OFB mode is returned.
oid_alist [Netsys_digests]
maps the OID to the hash function id
oid_of_der [Netgss_bindings]
oid_rev_alist [Netsys_digests]
the reverse
oid_set_of_array [Netgss_bindings]
oid_to_der [Netgssapi_support]
Encodings
oid_to_der_value [Netgssapi_support]
once [Unixqueue]
Arranges that the callback function is called once after the passed period of time (the float argument) has elapsed.
open_shm [Netshm]
Opens the shared memory object.
openat [Netsys_posix]
Same as Unix.openfile but open relative to the directory given by first argument
openlog [Netsys_posix]
openlog ident options facility: Opens a log stream.
ops_of_tstring [Netstring_tstring]
Create a Tstring_ops_box
option_manager [Netshm_data]
Creates a data manager from an input data manager for optional values
option_of_char [Nettelnet_client]
Converts a character representing an option to the internal option name.
options_service [Nethttpd_services]
This service responds to "OPTIONS *" requests, and nothing else
out_obj_channel [Uq_io]
out_obj_channel d timeout: Creates a synchronous channel from the output device.
output [Netcgi_apache.Apache.Request]
output r s ofs len send s[ofs .. len-1] back to the client.
output_bytes_e [Uq_io]
let e = output_bytes_e d s: Outputs the bytes s to d, and transitions to `Done() when done.
output_e [Uq_io]
let e = output_e d s pos len: Outputs data to d and takes it from the string s starting at pos and with maximum length len.
output_file_response [Nethttpd_types]
Outputs the contents of a file as response body, together with the given status and the header (optional).
output_memory_e [Uq_io]
let e = output_string_e d m: Outputs the bigarray m to d, and transitions to `Done() when done.
output_netbuffer_e [Uq_io]
let e = output_string_e d b: Outputs the contents of b to d, and transitions to `Done() when done.
output_static_response [Nethttpd_types]
Outputs the string argument as response body, together with the given status and the header (optional).
output_std_response [Nethttpd_types]
Outputs a "standard response" for the http_status.
output_stream_adapter [Shell_fs]
Arranges that the output of a shell command is made available as an in_obj_channel:
output_string_e [Uq_io]
let e = output_string_e d s: Outputs the string s to d, and transitions to `Done() when done.
output_thread_event [Netsys_win32]
This event is signaled when there is space in the buffer, or when there is an error condition
output_thread_proxy_descr [Netsys_win32]
Returns the proxy descriptor
output_thread_write [Netsys_win32]
output_thread_write t s pos len: Tries to write data to the buffer.
output_thread_write_string [Netsys_win32]
Same for immutable strings

P
pack_accepting_reply [Rpc_packer]
pack_accepting_reply_pseudo [Rpc_packer]
pack_call [Rpc_packer]
pack_call_gssapi_header [Rpc_packer]
for GSS-API - packs the call header up to the credentials
pack_call_pseudo [Rpc_packer]
pack_rejecting_reply [Rpc_packer]
pack_rejecting_reply_pseudo [Rpc_packer]
pack_successful_reply [Rpc_packer]
pack_successful_reply_pseudo [Rpc_packer]
pack_successful_reply_raw [Rpc_packer]
pack_xdr_value [Netxdr]
pack_xdr_value_as_bytes [Netxdr]
pack_xdr_value_as_mstrings [Netxdr]
The concatanated mstrings are the packed representation
pack_xdr_value_as_string [Netxdr]
rm: If true, four null bytes are prepended to the string for the record mark
packed_value_of_bytes [Rpc_packer]
packed_value_of_mstrings [Rpc_packer]
packed_value_of_string [Rpc_packer]
page_for_additions [Netpagebuffer]
let (m,pos,len) = page_for_additions b: Returns the last page in m, the first free byte on the page in pos, and the number of free bytes on the page in len.
page_for_consumption [Netpagebuffer]
let (m,pos,len) = page_for_consumption b: Returns the first page in m, the first used byte on the page in pos, and the number of used bytes on the page in len.
pagesize [Netsys_mem]
The best guess at the page size
pair_manager [Netshm_data]
Creates a compound manager for pairs from two input managers
paligned_memory_based_mstrings [Netxdr_mstring]
Uses memory to represent mstrings.
param_charset [Netmime_string]
param_language [Netmime_string]
Return the decoded value of the parameter, the charset (uppercase), and the language.
param_tokens [Netmime_string]
Formats a parameter list.
param_value [Netmime_string]
params [Netxdr]
return the X_param parameters contained in the type
parse [Netascii_armor]
Parses the channel, and returns all messages that are enabled in the specification.
parse [Netdn.DN_string]
Parses the string (or fails).
parse [Nethtml]
Parses the HTML document from an object channel and returns it.
parse [Netdate]
Parse a string and return a date/time record.
parse [Netaddress]
Parse a list of addresses in string representation, and return them as list of mailboxes or groups.
parse_authority_info_access [Netx509]
parse_authority_key_identifier [Netx509]
parse_basic_constraints [Netx509]
parse_document [Nethtml]
Parses the HTML document from a lexbuf and returns it.
parse_epoch [Netdate]
Parse a string and return the time (integral seconds since the epoch)
parse_epoch_approx [Netdate]
Parse a string and return the time (approximate seconds since the epoch)
parse_epoch_timespec [Netdate]
Parse a string and return the time (seconds and nanos since the epoch)
parse_ext_key_usage [Netx509]
Returns the OID as array, and as decoded flag
parse_glob_expr [Netglob]
Parses the glob expression.
parse_hostbased_service [Netsys_gssapi]
Returns (service,host) for "service@host".
parse_inet_uaddr [Rpc]
Parses an universal address and returns internet addr and port.
parse_issuer_alt_name [Netx509]
parse_kerberos_name [Netgssapi_support]
let (name_components, realm_opt) = parse_kerberos_name s: Returns the slash-separated name components as name_components, and the realm following "@" as realm_opt.
parse_key_usage [Netx509]
parse_mic_token_header [Netgssapi_support]
Returns the triple (sent_by_acceptor, acceptor_subkey, sequence_number) from the header of a MIC token that is passed to this function as string.
parse_mlsd_document [Netftp_client]
Returns the entries contained in the output of `MLSD
parse_nlst_document [Netftp_client]
Returns the filenames contained in the output of `NLST
parse_no_proxy [Nethttp_client]
Parses the value of an environment variable like no_proxy.
parse_proxy_setting [Nethttp_client]
Parses the value of an environment variable like http_proxy, i.e.
parse_quoted_parameters [Nethttp.Header]
A generic parser for comma-separated parameters in the form key=value or key="value".
parse_subject_alt_name [Netx509]
parse_subject_directory_attributes [Netx509]
parse_subject_info_access [Netx509]
parse_subject_key_identifier [Netx509]
Returns the key identifier directly
parse_url [Neturl]
Parses the string and returns the URL the string represents.
parse_user_name [Rpc_auth_sys]
Parses a user name as returned by Rpc_server.get_user in conjunction with the AUTH_SYS authentication and `Full formatting.
parse_wrap_token_header [Netgssapi_support]
let (sent_by_acceptor, sealed, acceptor_subkey, sequence_number) = parse_wrap_token_header token
partial_url_syntax [Neturl]
Transforms the syntax into another syntax where all required parts are changed into optional parts.
path [Nethttp.Cookie]
The path of the cookie, if set.
path [Netcgi.Cookie]
The path of the cookie, if set.
path [Netcgi_common.Cookie]
path_info [Netcgi_apache.Apache.Request]
request_rec path_info field.
peek_auth_error [Rpc_packer]
If an authentication error occurs, this function extracts it from the packed message.
peek_xid [Rpc_packer]
Extracts the session ID without analyzing the rest of the message.
pending_calls [Rpc_proxy.ManagedClient]
Returns the number of pending calls
pending_connection [Netsys_polysocket]
Whether there is a client waiting for being accepted
performance_event_system [Unixqueue]
Same as function
performance_pollset [Netsys_pollset_generic]
Returns the best available pollset on this platform for high performance servers that have to deal with many different file descriptors.
pidfile [Netplex_main]
Returns the location of the PID file (if any)
pin [Netmcore_heap]
pin m x: Pins a shared value x so it cannot be deleted by the garbage collector.
ping [Netcgi_dbi.DBI_DRIVER]
pipe_accept [Netsys_win32]
Waits until the connect event is signaled (usually meaning that a new client connection is available), and returns the new pipe.
pipe_connect [Netsys_win32]
pipe_connect name mode: Creates a client pipe handle, and tries to connect to the pipe server name.
pipe_connect_event [Netsys_win32]
The event object signals when a new client connection is available
pipe_descr [Netsys_win32]
Returns the proxy descriptor for the pipe.
pipe_listen [Netsys_win32]
Creates the backlog queue with n prepared server endpoints.
pipe_mode [Netsys_win32]
pipe_name [Netsys_win32]
pipe_name [Netmcore_condition]
Returns the name of the pipe
pipe_pair [Netsys_win32]
Returns a pair of connected pipes (using automatically generated names).
pipe_rd_event [Netsys_win32]
pipe_read [Netsys_win32]
pipe_read p s pos len: Tries to read data from the pipe.
pipe_server_descr [Netsys_win32]
Returns the proxy descriptor for the pipe server.
pipe_server_mode [Netsys_win32]
Returns the pipe/server mode
pipe_server_name [Netsys_win32]
Returns the name of the pipe
pipe_shutdown [Netsys_win32]
Cancels all pending I/O operations and closes the pipe handle.
pipe_shutdown_server [Netsys_win32]
Closes the pipe server: All endpoints in the backlog queue are shutdown.
pipe_wait_connect [Netsys_win32]
Wait until a client connects to this server.
pipe_wait_rd [Netsys_win32]
pipe_wait_wr [Netsys_win32]
Wait until the pipe becomes readable or writable.
pipe_wr_event [Netsys_win32]
The event objects signaling that read and write operations are possible.
pipe_write [Netsys_win32]
pipe_write p s pos len: Tries to write data to the pipe.
pipe_write_string [Netsys_win32]
Same for immutable string
plugin [Netplex_mbox]
To enable message boxes, call the controller's add_plugin method with this object as argument.
plugin [Netplex_mutex]
To enable mutexes, call the controller's add_plugin method with this object as argument.
plugin [Netplex_sharedvar]
To enable shared variables, call the controller's add_plugin method with this object as argument.
plugin [Netplex_semaphore]
To enable semaphores, call the controller's add_plugin method with this object as argument.
pmanage [Netsys_pmanage]
Create a new manager for persistent kernel objects.
pmanage [Netplex_cenv]
Access the manager for persistent kernel objects with limited lifetime.
pmap_port [Rpc_portmapper_aux]
pmapproc_callit [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_callit'async [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_dump [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_dump'async [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_getport [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_getport'async [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_null [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_null'async [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_set [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_set'async [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_unset [Rpc_portmapper_clnt.Make'PMAP.V2]
pmapproc_unset'async [Rpc_portmapper_clnt.Make'PMAP.V2]
poll [Netsys_posix]
poll a n tmo: Poll for the events of the cells 0 to n-1 of poll array a, and set the poll_act_events member of all cells.
poll_array_length [Netsys_posix]
Return the number of cells in the poll array
poll_based_pollset [Netsys_pollset_posix]
Returns a poll set whose implementation is based on the poll system call.
poll_err_result [Netsys_posix]
poll_event_sources [Netsys_posix]
poll_event_sources ea tmo: First, all modifications are pushed to the kernel, and polling is set up to get events.
poll_hup_result [Netsys_posix]
poll_null_events [Netsys_posix]
Create an empty set of poll_act_events, for initilization of poll cells.
poll_nval_result [Netsys_posix]
Look for the bit in poll_act_events and return the status
poll_pri_result [Netsys_posix]
poll_rd_result [Netsys_posix]
poll_req_events [Netsys_posix]
poll_req_events rd wr pri: Create a set of in events consisting of the bits rd, wr, and pri.
poll_req_triple [Netsys_posix]
Looks into a poll_req_events value, and returns the triple (rd,wr,pri).
poll_result [Netsys_posix]
Look whether there is any event in poll_out_events
poll_single [Netsys_posix]
poll_single fd rd wr pri tmo: Polls a single descriptor for the events given by rd, wr, and pri.
poll_wr_result [Netsys_posix]
pollset [Netsys_pollset_win32]
This is a pollset implementation that works for sockets, and, named pipes as provided by Netsys_win32 (add the descriptors returned by pipe_descr or pipe_server_descr to the pollset) The number of descriptors that can be added to the pollset has a quite low limit (usually 63 sockets or 31 pipes).
pollset_event_system [Unixqueue_pollset]
Implements a unixqueue on top of a pollset.
polymorph_string_transformation [Netstring_tstring]
polymorph_string_transformation f ops kind s: Converts s to a string, runs f on this string, and converts the result to the type demanded by kind
pool [Netmcore_heap]
Return the pool ID
pool_alloc_memory [Netsys_mem]
let m = pool_alloc_memory p: Gets a memory block m from the pool p.
pool_alloc_memory2 [Netsys_mem]
let m, free = pool_alloc_memory2 p: Gets a memory block m from the pool p like pool_alloc_memory.
pool_block_size [Netsys_mem]
Returns the size of the memory blocks in bytes
pool_reclaim [Netsys_mem]
Reclaim as much memory as possible
pool_report [Netsys_mem]
Returns a report describing the memory allocation in the pool
pop_c [Netmcore_queue]
pop_c q: Takes the first element x from the queue, removes it there, and returns a copy of x in normal memory.
pop_p [Netmcore_queue]
pop_p q f: Takes the first element x from the queue, removes it there, and calls f x.
port [Netcgi_apache.Apache.Request]
Server port.
port_of_program [Rpc_portmapper]
port_of_program program host protocol: queries the portmapper running on host for the program registered for protocol.
ports [Nethttp.Cookie]
port c the ports to which the cookie may be returned or [] if not set.
ports [Netcgi.Cookie]
port c the ports to which the cookie may be returned or [] if not set.
ports [Netcgi_common.Cookie]
posix_l9n [Netdate]
The standard POSIX localization (English names)
posix_openpt [Netsys_posix]
posix_openpt noctty: Opens an unused PTY master.
post [Netmcore_sem]
Increments the semaphore by one, and notifies one of the waiting processes.
postprocess_job [Shell]
Looks at the error codes of the job, and raises Subprocess_error when there is an error that cannot be ignored.
prefix [Netsys_sem]
Return the prefix
prefix_mstrings [Netxdr_mstring]
prefix_mstrings l n: returns the first n chars of the concatenated mstrings l as single string
prefix_mstrings_bytes [Netxdr_mstring]
Same, returning bytes
prefix_of_packed_value [Rpc_packer]
The first n bytes of the packed value
prev [Netcgi_apache.Apache.Request]
request_rec prev field.
print [Netdn.DN_string]
Prints the DN (cannot fail), using UTF-8 encoding
print_buffer [Netbuffer]
For the toploop
print_char [Netcgi_apache.Apache.Request]
Send a character back to the client.
print_endline [Netcgi_apache.Apache.Request]
Send a string followed by CR LF back to the client.
print_float [Netcgi_apache.Apache.Request]
Send a floating-point number back to the client.
print_glob_expr [Netglob]
Prints the glob expression as string.
print_in_obj_stream [Netstream]
A top-loop printer for streams
print_int [Netcgi_apache.Apache.Request]
Send a decimal number back to the client.
print_newline [Netcgi_apache.Apache.Request]
Send a CR LF back to the client.
print_s_param [Netmime_string]
Prints a parameter to the formatter (as toploop printer)
print_string [Netcgi_apache.Apache.Request]
Send a string back to the client.
print_url [Neturl]
Printer for the toploop.
prioritizer [Uq_engines_compat]
prioritizer [Uq_engines]
Same as function
private_key_format_of_key [Netx509_pubkey.Key]
Get the type of private key for a public key OID
procedure_number [Rpc_program]
procedure_number p name returns only the procedure number of the procedure called name.
process_bytes [Netsys_ciphers]
process_bytes p s: If p is encrypt or decrypt from a cipher_ctx, p will be called to submit the data from string s.
process_challenge [Netsys_sasl.Client]
Process the challenge from the server.
process_connection [Nethttpd_engine]
Sets up an engine that processes all requests using the service description.
process_connection [Nethttpd_reactor]
Processes all HTTP requests in turn arriving at the file descriptor, and calls the service provider for every request.
process_descr [Netsys_win32]
Returns the proxy descriptor of the process
process_group_id [Shell_sys]
Returns the Unix ID of the process group as number > 1.
process_group_leader [Shell_sys]
Returns the process group leader process.
process_id [Shell_sys]
Returns the process ID of the process
process_response [Netsys_sasl.Server]
Process the response from the client.
process_response_restart [Netsys_sasl.Server]
Process the response from the client when another session can be continued.
process_string [Netsys_ciphers]
process_string p s: same for immutable strings.
process_subbytes [Netsys_ciphers]
process_subbytes p s pos len: If p is encrypt or decrypt from a cipher_ctx, p will be called to submit the data from string s, starting at position pos and length len.
process_substring [Netsys_ciphers]
process_substring p s pos len: Same for immutable strings.
processes [Shell_sys]
Returns the processes that have actually been started for this job by run_job; note that the corresponding Unix process group may have additional processes (e.g.
profile [Netmech_scram]
Creates a profile
program [Rpc_client]
Returns the program the client represents.
program_PMAP'V2 [Rpc_portmapper_aux]
program_PMAP'V3 [Rpc_portmapper_aux]
program_PMAP'V4 [Rpc_portmapper_aux]
program_number [Rpc_program]
Return the program number
programs [Rpc_client]
Returns the list of all bound programs
prop [Netsys_sasl.Server]
Get a mechanism-specific property of the session.
prop [Netsys_sasl.Client]
Get a mechanism-specific property of the session.
propagate_back [Netplex_sharedvar]
Copy the global variables from Netplex_sharedvar (with prefix "global.") back to Netsys_global
props_of_file [Netcgi_ajp]
props_of_file fname parses the property file fname and returns it as an associative list.
proto_num [Netcgi_apache.Apache.Request]
request_rec proto_num field.
protocol [Netcgi_apache.Apache.Request]
request_rec protocol field.
protocol_of_string [Nethttp]
Parses the protocol string, e.g.
protostring_of_inet_addr [Netsys]
provider [Netsys_oothr]
Return the multi-threading provider
proxy_only_trans_id [Nethttp]
Identifies web proxy connections.
proxy_only_trans_id [Nethttp_client]
Identifies web proxy connections.
pseudo_value_of_xdr [Rpc_packer]
ptrace_verbosity [Rpc_server.Debug]
How verbose the ptrace is.
ptrace_verbosity [Rpc_client.Debug]
How verbose the ptrace is.
ptsname [Netsys_posix]
Get the name of the slave PTY
push [Netmcore_queue]
push x q: Pushes a copy of x to the end of the queue q
push_event_updates [Netsys_posix]
Pushes all modifications of the sources to the kernel
put_method [Netftp_client]
This FTP method walks to the right directory and puts file to the server.
put_string [Netbuffer]
put_string nb pos s: Copies the string s to the position pos of netbuffer nb

Q
qseq_engine [Uq_engines_compat]
qseq_engine [Uq_engines]
Almost the same as seq_engine, but this version does not propagate working state (i.e.
query_langinfo [Netsys_posix]
query_langinfo locale: Temporarily sets the passed locale and determines the language attributes.
quit_method [Netftp_client]
Quits and disconnects
quote [Netstring_str]
Quotes a string such that it can be included in a regexp
quote [Netstring_pcre]
Quotes a string such that it can be included in a regexp
quote_set [Netstring_str]
Returns a regexp (as string) that matches any of the characters in the argument.

R
raise_error [Netgssapi_auth.CONFIG]
rcache_config [Rpc_proxy.ReliabilityCache]
Return the config
rd_file [Netsys_crypto_types.FILE_TLS_ENDPOINT]
read [Netsys_polypipe]
read a message.
read_blocks [Netshm]
find_blocks tbl key f: The values may be stored in several disk blocks.
read_config_file [Netplex_config]
Reads a filename and returns the representation object
read_descr [Netsys_polypipe]
Returns a descriptor that can be used for polling.
read_dynamic_service_config [Nethttpd_plex]
read_dynamic_service_config handlers cfg addr uri_path: Reads the service configuration section of type "dynamic" from config file cfg at address addr.
read_file_service_config [Nethttpd_plex]
read_file_service_config cfg addr uri_path: Reads the service configuration section of type "file" from config file cfg at address addr.
read_fp4 [Netnumber.ENCDEC]
read_fp8 [Netnumber.ENCDEC]
read_header [Netmime_string]
This function expects that the current position of the passed in_obj_stream is the first byte of the header.
read_int4 [Netnumber.ENCDEC]
read_int4_unsafe [Netnumber.ENCDEC]
read_int8 [Netnumber.ENCDEC]
read_int8_unsafe [Netnumber.ENCDEC]
read_media_types_file [Nethttpd_services]
Reads a text file with two columns where the left column is the media type and the right column the corresponding suffix.
read_mime_header [Netmime_channels]
Decodes the MIME header that begins at the current position of the netstream, and returns the header as class basic_mime_header.
read_mime_message [Netmime_channels]
Decodes the MIME message that begins at the current position of the passed netstream.
read_multipart_body [Netmime_string]
This is the "next generation" multipart message parser.
read_netplex_config [Netplex_config]
Reads a Netplex configuration file:
read_privkey_from_pem [Netx509_pubkey]
Reads a PEM file tagged as "...
read_pubkey_from_pem [Netx509_pubkey]
Reads a PEM file tagged as "PUBLIC KEY".
read_string_fp4 [Netnumber.ENCDEC]
read_string_fp8 [Netnumber.ENCDEC]
read_string_int4 [Netnumber.ENCDEC]
read_string_int4_unsafe [Netnumber.ENCDEC]
read_string_int8 [Netnumber.ENCDEC]
read_string_int8_unsafe [Netnumber.ENCDEC]
read_string_uint4 [Netnumber.ENCDEC]
read_string_uint4_unsafe [Netnumber.ENCDEC]
read_string_uint8 [Netnumber.ENCDEC]
read_string_uint8_unsafe [Netnumber.ENCDEC]
For immutable strings
read_tls_config [Netplex_config]
Reads the TLS section of a configuration file: At the passed location there must be tls section (or None is returned).
read_uint4 [Netnumber.ENCDEC]
read_uint4_unsafe [Netnumber.ENCDEC]
read_uint8 [Netnumber.ENCDEC]
read_<t> create integer values from the characters found at a certain position in the string.
read_uint8_unsafe [Netnumber.ENCDEC]
Same, but no index check
readlinkat [Netsys_posix]
readlinkat dirfd path
real_select [Netsys_win32]
Up to Ocaml 3.10, this function is identical to Unix.select.
really_gread [Netsys]
really_read fd_style fd s pos len: Reads exactly len bytes from fd and stores them in s starting at pos.
really_gread_tbuf [Netsys]
Same for a tagged buffer
really_gwrite [Netsys]
really_write fd_style fd s pos len: Writes exactly the len bytes from s to fd starting at pos.
really_gwrite_tbuf [Netsys]
Same for a tagged buffer
really_gwrite_tstr [Netsys]
Same for a tagged string
really_input_e [Uq_io]
let e = input_e d s pos len: Reads data from d and puts it into the string s starting at pos and with length len.
really_output_e [Uq_io]
let e = really_output_e d s pos len: Outputs data to d and takes it from the string s starting at pos and with length len.
realpath [Netsys_posix]
Returns a pathname pointing to the same filesystem object so that the pathname does not include "." or ".." or symbolic links.
receive [Netplex_mbox.MBOX]
Receive a message: It is waited until a sender puts a message into the box.
recode [Netconversion]
Converts the character sequence contained in the at most in_len bytes of in_buf starting at byte position in_pos, and writes the result into at most out_len bytes of out_buf starting at byte position out_pos.
recode_poly [Netconversion]
A polymorphic version of recode
recode_tstring [Netconversion]
A version of recode for tagged strings
record_unavailability [Rpc_proxy.ManagedClient]
Increases the error counter in the reliability cache for this connection.
recover_glob_expr [Netglob]
Returns the explicit representation
recv [Netsys_tls]
recv endpoint buffer pos len: Receives data from endpoint, and puts the received bytes into buffer at byte position pos.
recv [Netsys_crypto_types.TLS_PROVIDER]
recv ep buffer n: Receives data, and puts them into the memory buffer, and returns the actual number of received bytes.
recv_will_not_block [Netsys_crypto_types.TLS_PROVIDER]
If there is still unprocessed data in the endpoint buffer, recv is guaranteed not to block or raise EAGAIN.
refill [Netulex.ULB]
Tries to add characters to the unicode_lexbuf by calling the ulb_refill function.
refuse [Netsys_polysocket]
All pending connection attempts will be refused.
refuse_switch [Netsys_crypto_types.TLS_PROVIDER]
On the client: Refuse a handshake
regexp [Netstring_str]
Parses a regexp
regexp [Netstring_pcre]
Parses a regexp
regexp_case_fold [Netstring_str]
Parses a case-insensitive regexp
regexp_case_fold [Netstring_pcre]
Parses a case-insensitive regexp
regexp_string [Netstring_str]
Returns a regexp that matches exactly the string
regexp_string [Netstring_pcre]
Returns a regexp that matches exactly the string
regexp_string_case_fold [Netstring_str]
Returns a case-insensitive regexp that matches exactly the string
regexp_string_case_fold [Netstring_pcre]
Returns a case-insensitive regexp that matches exactly the string
register [Netcompression]
Registers a compression algorithm.
register [Netplex_cenv.LEVER]
let reg_lever = register ctrl raw_lever: Registers raw_lever in the controller ctrl, so one can call reg_lever to activate it.
register [Netcgi_apache.Handler]
Modules may call register fn name to register one or more handler functions.
register_cleanup [Netcgi_apache.Apache.Request]
Register a cleanup function which is called when the current request cycle ends.
register_exclusive_handler [Netsys_signal]
An exclusive handler for a signal is the only handler for the signal.
register_handler [Netsys_signal]
This function registers a handler called name for signal number signal.
register_module [Netlog.Debug]
Registers the enable variable of the named module
register_post_fork_handler [Netsys_posix]
Registers a new post fork handler (MT-Safe)
register_printer [Netexn]
register e f: Register that the exception type of the sample exception e is to be printed by f.
register_server [Netplex_internal]
register_server name server: registers a server under the given name.
register_subprocess_handler [Netsys_posix]
Uses the Netsys_signal framework to manage the installation of the SIGCHLD handler.
reinit_cursor [Netconversion]
Reuses an existing cursor for a new purpose.
relaxed_html40_dtd [Nethtml]
A relaxed version of the HTML 4.0 DTD that matches better common practice.
release [Netmcore]
Release the resource with this ID.
release_buffer [Netgss_bindings]
release_fd [Netlog.Debug]
Removes this descriptor from the descriptor table.
release_fork_point [Netmcore_process]
Releases a fork point so it is deleted from the internal resource table.
release_join_point [Netmcore_process]
Releases a join point so it is deleted from the internal resource table.
remote_host [Netcgi_apache.Apache.Connection]
conn_rec remote_host field.
remote_ip [Netcgi_apache.Apache.Connection]
conn_rec remote_ip field.
remove [Netshm_hashtbl]
remove tbl key removes the current binding of key in tbl, restoring the previous binding if it exists.
remove [Netshm]
remove tbl key removes the current binding of key in tbl, restoring the previous binding if it exists.
remove [Netmcore_hashtbl]
Hashtbl.remove tbl x removes the current binding of x in tbl, restoring the previous binding if it exists.
remove_from_url [Neturl]
Removes the true components from the URL, and returns the modified URL.
remove_post_fork_handler [Netsys_posix]
Removes a post fork handler from the registry (MT-Safe)
remove_resource [Unixqueue]
Removes the operation from the watch list of the group.
rename_method [Netftp_client]
Renames the file_from into file_to.
renameat [Netsys_posix]
renameat olddirfd oldpath newdirfd newpath
replace [Netshm_hashtbl]
replace tbl key value replaces the current binding of key in tbl by a binding of key to value.
replace [Netshm]
replace tbl key value replaces the current binding of key in tbl by a binding of key to value.
replace [Netmcore_hashtbl]
Hashtbl.replace tbl x y replaces the current binding of x in tbl by a binding of x to y.
replace_first [Netstring_str]
replace_first re templ s: Replaces the first match of re in s by templ.
replace_first [Netstring_pcre]
replace_first re templ s: Replaces the first match of re in s by templ.
reply [Rpc_server]
Asynchronous procedures can reply their results with this function.
reply_error [Rpc_server]
Like reply, but an error condition is sent back to the caller.
report_connection_string [Netplex_cenv]
Output a log line for the netplex.connections admin message.
report_signal_as_event [Netsys_posix]
report_signal_as_event ev sig Installs a new signal handler for signal sig so that ev is signalled when a signal arrives.
repr_config_file [Netplex_config]
repr_config_file name tree: converts the tree to a full config_file object.
req_events_of_int [Netsys_posix]
request_time [Netcgi_apache.Apache.Request]
request_rec request_time field.
reset [Netsys_pollset_posix]
This module may keep some global state.
reset [Netbuffer]
Empty the buffer, deallocate the internal string, and replace it with a new string of length n that was allocated by Netbuffer.create n.
reset_event [Netsys_win32]
Set the object to "non-signaled" state
reset_rcache_error_counter [Rpc_proxy.ReliabilityCache]
Reset the error counter for this sockaddr.
resize [Netshm_array]
resize a n: Resizes the array to length n.
resp_100_continue [Nethttpd_kernel]
The predefined token for the "100 Continue" response
restart [Netsys_sasl.Client]
Restart the session for another authentication round.
restart [Netsys]
restart f arg calls f arg, and restarts this call if the exception Unix_error(EINTR,_,_) is caught.
restart_supported [Nethttp.HTTP_CLIENT_MECHANISM]
Whether the mechanism supports quick restarts (re-authentication)
restart_tmo [Netsys]
restart_tmo f tmo calls f with a timeout argument tmo, and restarted the call if the exception Unix_error(EINTR,_,_) is caught.
restart_wait [Netsys]
restart_wait mode fd_style fd f arg: Calls f arg, and handles the following exceptions: Unix_error(EINTR,_,_): Just calls f again, Unix_error(EAGAIN,_,_): waits until fd is readable or writable as designated by mode, and calls f again, Unix_error(EWOUDLBLOCK,_,_): same, Netsys_types.EAGAIN_RD: waits until fd is readable, and calls f again, Netsys_types.EAGAIN_WR: waits until fd is writable, and calls f again
restarting_poll [Netsys_posix]
A wrapper around poll that handles the EINTR condition
restarting_select [Netsys]
A wrapper around Unix.select that handles the EINTR condition.
restarting_sleep [Netsys]
Sleep for the passed time.
restore_endpoint [Netsys_crypto_types.TLS_PROVIDER]
Reconnect the stashed endpoint with recv and send functions
restore_management [Netsys_signal]
restore_management signo: Restores signal handling management for signo as defined by the handler list for this signal.
restore_tls_multiplex_controller [Uq_multiplex]
Like tls_multiplex_controller, but this function does not create a new TLS endpoint.
restrict_dynamic_service_config [Nethttpd_plex]
Restricts the subsections and paremeters in the service configuration section of type "dynamic" to the allowed ones.
restrict_file_service_config [Nethttpd_plex]
Restricts the subsections and paremeters in the service configuration section of type "file" to the allowed ones.
resume_client [Netsys_crypto_types.TLS_PROVIDER]
Creates a new endpoint that will resume an old session.
resume_session [Netsys_sasl.Server]
Unserializes the session, and connect with the lookup function.
resume_session [Netsys_sasl.Client]
Unserializes the session
retr_password [Netldap]
Same as synchronous function
retr_password_e [Netldap]
Connects and binds to the server, and retrieves the userPassword and authPassword attributes of the entry referenced by dn.
rev_mode [Netsys_win32]
Reverses the direction
rev_split [Netcgi_common]
split_rev is_delim s split s at each character is_delim and returns the list of substrings in reverse order.
rflush [Netcgi_apache.Apache.Request]
Flush any buffered data waiting to be written to the client.
rm_htspace [Netcgi_common]
rm_htspace is_space s low up returns the substring s.[low .. up - 1] stripped of possible heading and trailing spaces identified by the function is_space.
rmdir_method [Netftp_client]
Deletes the named directory
rollback [Netcgi_dbi.DBI_DRIVER]
root [Netmcore_heap]
Returns the root element
rotate_right [Netauth]
Rotate the (big-endian) bitstring to the right by n bits.
rpc_engine [Rpc_proxy.ManagedClient]
Call an RPC function in engine style:
rpc_factory [Rpc_netplex]
A factory for TCP-based RPC servers.
rpcb_port [Rpc_portmapper_aux]
rpcbproc_bcast [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_bcast'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_callit [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_callit'async [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_dump [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_dump [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_dump'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_dump'async [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_getaddr [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_getaddr [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_getaddr'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_getaddr'async [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_getaddrlist [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_getaddrlist'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_getstat [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_getstat'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_gettime [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_gettime [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_gettime'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_gettime'async [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_getversaddr [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_getversaddr'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_indirect [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_indirect'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_null [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_null [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_null'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_null'async [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_set [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_set [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_set'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_set'async [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_taddr2uaddr [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_taddr2uaddr [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_taddr2uaddr'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_taddr2uaddr'async [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_uaddr2taddr [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_uaddr2taddr [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_uaddr2taddr'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_uaddr2taddr'async [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_unset [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_unset [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbproc_unset'async [Rpc_portmapper_clnt.Make'PMAP.V4]
rpcbproc_unset'async [Rpc_portmapper_clnt.Make'PMAP.V3]
rpcbstat_highproc [Rpc_portmapper_aux]
rpcbvers_2_stat [Rpc_portmapper_aux]
rpcbvers_3_stat [Rpc_portmapper_aux]
rpcbvers_4_stat [Rpc_portmapper_aux]
rpcbvers_stat [Rpc_portmapper_aux]
rsa [Netx509_pubkey.Encryption]
alias RSAES-PKCS1-v1_5
rsa_key [Netx509_pubkey.Key]
alias PKCS-1.
rsa_with_sha1 [Netx509_pubkey.Signing]
These algorithms are used for signing
rsa_with_sha224 [Netx509_pubkey.Signing]
rsa_with_sha256 [Netx509_pubkey.Signing]
rsa_with_sha384 [Netx509_pubkey.Signing]
rsa_with_sha512 [Netx509_pubkey.Signing]
rsaes_oaep [Netx509_pubkey.Encryption]
RSAES-OAEP
rsaes_oaep_key [Netx509_pubkey.Key]
RSAES-OAEP.
rsassa_pss [Netx509_pubkey.Signing]
RSASSA-PSS
rsassa_pss_key [Netx509_pubkey.Key]
RSASSA-PSS.
run [Shell_sys]
Executes the command concurrently with the current process.
run [Netplex_main]
Similar to startup, but this function is tailored for Netplex systems that compute results (e.g.
run [Netmcore]
This function fixes a design error in startup, namely that it was difficult to get the result of the process(es) back.
run [Netcgi_test]
run [Netcgi_fcgi]
run f register the function f as a main function of the script.
run [Netcgi_cgi]
run f executes f cgi for each cgi request.
run [Netcgi_scgi]
run f executes f cgi for each SCGI request.
run [Netcgi_ajp]
run f executes f cgi for each AJP request.
run [Netcgi_apache]
run f register the function f as a main function of the script.
run [Unixqueue]
Starts the event loop.
run [Equeue]
Running a system means that, unless the queue is empty, the events at the time of the run invocation and all later added events are gone through.
run_in_container_context [Netplex_cenv]
run_in_container_context cont f: Arranges that f() is executed in the context of the container cont.
run_in_controller_context [Netplex_cenv]
run_in_controller_context ctrl f: Arranges that f() is executed in the context of the controller.
run_job [Shell_sys]
Invokes the commands of the job such that they run concurrently with the main process.
run_mtests [Netmech_scram.AES_CTS]
run_post_fork_handlers [Netsys_posix]
Runs all post fork handlers.
run_tests [Netmech_scram.AES_CTS]

S
s_read_int4_64_unsafe [Netsys_xdr]
For 64 bit platforms only: Decodes 4 bytes at this string position as a signed 32 bit int in network byte order
s_read_string_array_unsafe [Netsys_xdr]
let pos' = s_read_string_array s pos len max a: Decodes the XDR repr of an array of strings without length field.
s_write_int4_64_unsafe [Netsys_xdr]
For 64 bit platforms only: Encodes 4 bytes at this string position as a signed 32 bit int in network byte order
salt_password [Netmech_scram]
let salted_password = salt_password h password salt iteration_count
same_encoding [Netconversion]
Whether both encodings are the same.
sarray2_of_descr [Netmcore_matrix]
Look up the matrix for this descriptor
sarray_of_descr [Netmcore_array]
Look up the buffer for this descriptor
sasl_bind_creds [Netldap]
saslprep [Netsaslprep]
Transform a string given as UTF-8 string
saslprep_a [Netsaslprep]
Transform a string given as array of Unicode code points
scan_encoded_text_value [Netmime_string]
Scans a "text" value.
scan_header [Netmime_string]
let params, header_end_pos = scan_header s start_pos end_pos:
scan_header_poly [Netmime_string]
Polymorphic version
scan_header_tstring [Netmime_string]
The same for tagged strings
scan_mime_type [Netmime_string]
let name, params = scan_mime_type s options: Scans MIME types like text/plain; charset=iso-8859-1 The name of the type and the names of the parameters are converted to lower case.
scan_mime_type_ep [Netmime_string]
let name, params = scan_mime_type_ep s options: This version copes with RFC-2231-encoded parameters.
scan_multipart_body [Netmime_string]
let [params1, value1; params2, value2; ...] = scan_multipart_body s start_pos end_pos boundary:
scan_multipart_body_and_decode [Netmime_string]
Same as scan_multipart_body, but decodes the bodies of the parts if they are encoded using the methods "base64" or "quoted printable".
scan_multipart_body_from_netstream [Netmime_string]
scan_multipart_body_from_netstream s boundary create add stop:
scan_structured_value [Netmime_string]
This function is included for backwards compatibility, and for all cases not requiring extended tokens.
scan_token [Netmime_string]
Returns the next token, or End if there is no more token.
scan_token_list [Netmime_string]
Returns all following tokens as a list (excluding End)
scan_value_with_parameters [Netmime_string]
let name, params = scan_value_with_parameters s options: Scans values with annotations like name ; p1=v1 ; p2=v2 ; ... For example, MIME types like "text/plain;charset=ISO-8859-1" can be parsed.
scan_value_with_parameters_ep [Netmime_string]
let name, params = scan_value_with_parameters_ep s options: This version of the scanner copes with encoded parameters according to RFC 2231.
scgi_processor [Netcgi_plex]
scram_gss_api [Netmech_scram_gssapi]
Returns a standard-compliant GSS-API object for the passed SCRAM profile.
scram_mech [Netmech_scram_gssapi]
The OID of SCRAM
search [Netldap]
Same as synchronous function
search_backward [Netstring_str]
Searches a match of the string with the regexp, starting at the position and in backward direction.
search_backward [Netstring_pcre]
Searches a match of the string with the regexp, starting at the position and in backward direction.
search_backward_bytes [Netstring_str]
Same for bytes
search_backward_bytes [Netstring_pcre]
Same for bytes
search_e [Netldap]
Run the specified search: Search at base according to scope for entries matching the filter and return their attributes.
search_forward [Netstring_str]
Searches a match of the string with the regexp, starting at the position and in forward direction.
search_forward [Netstring_pcre]
Searches a match of the string with the regexp, starting at the position and in forward direction.
search_forward_bytes [Netstring_str]
Same for bytes
search_forward_bytes [Netstring_pcre]
Same for bytes
search_path [Netsys_win32]
search_path path_opt name ext_opt: Uses the SearchPath function to locate a file.
secure [Nethttp.Cookie]
Tells whether the cookie is secure.
secure [Netcgi.Cookie]
Tells whether the cookie is secure.
secure [Netcgi_common.Cookie]
Tells whether the cookie is secure.
select_based_event_system [Unixqueue_select]
Create a new Unix.select-based event system
select_emulation [Netsys_pollset_generic]
let select = select_emulation pset: Returns a function with the same meaning as Unix.select.
self_cont [Netplex_cenv]
Returns the container running the code of the caller, or raise Not_in_container_thread if called from outside a container context.
self_obj [Netplex_cenv]
Returns the container or the controller running the code of the caller, or raise Not_found if called from neither a container not a controller thread.
self_process_id [Netmcore]
Returns the process ID of a worker
sem_close [Netsys_posix]
Closes a named semaphore.
sem_container [Netmcore_heap]
Return the semaphore container
sem_container [Netmcore_mempool]
Returns the semaphore container
sem_create [Netsys_posix]
let (sem,name) = sem_create prefix init_value: Creates a new semaphore with a unique name.
sem_destroy [Netsys_sem]
Destroys the anonymous semaphore
sem_destroy [Netsys_posix]
Destroys the anonymous semaphore
sem_getvalue [Netsys_sem]
Returns the value of the semaphore.
sem_getvalue [Netsys_posix]
Returns the value of the semaphore.
sem_init [Netsys_sem]
sem_init cont mem pos pshared init_value: Initializes the memory at position pos to pos + sem_size() - 1 as anonymous semaphore.
sem_init [Netsys_posix]
sem_init mem pos pshared init_value: Initializes the memory at position pos to pos + sem_size() - 1 as anonymous semaphore.
sem_open [Netsys_posix]
sem_open name flags mode init_value: Opens a named semaphore which is optionally created.
sem_post [Netsys_sem]
Unlocks the semaphore (increases the value by 1)
sem_post [Netsys_posix]
Unlocks the semaphore (increases the value by 1)
sem_size [Netsys_sem]
The size of an anonymous semaphore in bytes (sizeof(sem_t))
sem_size [Netsys_posix]
The size of an anonymous semaphore in bytes (sizeof(sem_t))
sem_unlink [Netsys_posix]
Unlinks the semaphore name
sem_value_max [Netsys_sem]
The maximum value of a semaphore, but at most max_int
sem_value_max [Netsys_posix]
The maximum value of a semaphore, but at most max_int
sem_wait [Netsys_sem]
Locks the semaphore (decreases the value by 1).
sem_wait [Netsys_posix]
Locks the semaphore (decreases the value by 1).
send [Netsys_tls]
send endpoint buffer pos len: Sends data via endpoint, and takes the emitted bytes from buffer at byte position pos.
send [Netsys_crypto_types.TLS_PROVIDER]
send ep buffer n: Sends the first n bytes in the buffer over the endpoint, and returns the actual number of processed bytes.
send [Netplex_mbox.MBOX]
Send a message to this box.
send_file_response [Nethttpd_kernel]
Sends the contents of a file as response body, together with the given status and the header (optional).
send_http_header [Netcgi_apache.Apache.Request]
Send the HTTP headers.
send_message [Netplex_cenv]
send_message service_pattern msg_name msg_arguments: Sends a message to all services and message receivers matching service_pattern.
send_static_response [Nethttpd_kernel]
Sends the string argument as response body, together with the given status and the header (optional).
sendmail [Netsendmail]
Sends the passed message.
sendmail [Netsmtp]
Sends the email to the receivers in the to, cc, and bcc headers.
separates_adjacent_encoded_words [Netmime_string]
True iff the current token is white space (i.e.
seq_engine [Uq_engines_compat]
seq_engine [Uq_engines]
Same as function.
serialize [Netsys_oothr]
serialize m f arg: Locks m, runs f arg, unlocks m, and returns the result.
serializer [Uq_engines_compat]
serializer [Uq_engines]
Same as function
server [Netcgi_apache.Apache.Request]
request_rec server field.
server_additional_params [Netmech_gs2_sasl.PROFILE]
Additional parameters understood by create_server_session
server_auth_method [Rpc_auth_gssapi]
Creates an authentication method from a GSS-API interface.
server_auth_method [Rpc_auth_sys]
Pass the result of this function to Rpc_server.set_auth_methods to configure authentication.
server_auth_method [Rpc_auth_local]
Return the authentication method AUTH_LOCAL.
server_authz_name [Netsys_sasl_types.SASL_MECHANISM]
The name the client authorizes as (or Not_found)
server_authz_name [Netmech_scram]
The authorization name as transmitted from the client.
server_bind_target_name [Netmech_gs2_sasl.PROFILE]
For servers: optionally bind the GSSAPI name of the server.
server_channel_binding [Netsys_sasl_types.SASL_MECHANISM]
Whether the client suggests or demands channel binding
server_channel_binding [Netmech_scram]
Returns the channel binding requirement.
server_check_target_name [Netmech_gs2_sasl.PROFILE]
For servers: check whether the GSSAPI name the client sent is the right one.
server_configure_channel_binding [Netsys_sasl_types.SASL_MECHANISM]
Configures acceptable channel bindings wiht a list of pairs (type,data).
server_emit_challenge [Netsys_sasl_types.SASL_MECHANISM]
Emit a server challenge.
server_emit_flag [Netmech_scram]
Whether server_emit_message can now be called
server_emit_message [Netmech_scram]
Emits the next message to be sent to the client
server_emit_message_kv [Netmech_scram]
Emits the next message to be sent to the client.
server_error_flag [Netmech_scram]
Whether an error occurred, and the protocol cannot advance anymore
server_error_of_string [Netmech_scram]
Conversion
server_export [Netmech_scram]
server_finish_flag [Netmech_scram]
Whether the client is authenticated
server_flags [Netmech_gs2_sasl.PROFILE]
Required flags for accept_sec_context.
server_gssapi_props [Netsys_sasl_types.SASL_MECHANISM]
Return the GSSAPI properties of the server, after the authentication is successful (and raises Not_found up to then).
server_import [Netmech_scram]
server_import_any [Netmech_scram]
server_import_any2 [Netmech_scram]
Exports a server session as string, and imports the string again.
server_map_user_name [Netmech_gs2_sasl.PROFILE]
For servers: maps a pair (name_string,name_type) coming from the GSSAPI to a user name.
server_process_response [Netsys_sasl_types.SASL_MECHANISM]
Process the response from the client.
server_process_response_restart [Netsys_sasl_types.SASL_MECHANISM]
Process the response from the client when another session can be continued.
server_prop [Netsys_sasl_types.SASL_MECHANISM]
Get a mechanism-specific property of the session.
server_prop [Netmech_scram]
Returns a property of the server (or Not_found) - see also client_prop above: "snonce", "cnonce", "salt", "i" (iteration_count), "client_key", "protocol_key"
server_protocol_key [Netmech_scram]
The 128-bit protocol key for encrypting messages.
server_recv_flag [Netmech_scram]
Whether server_recv_message can now be called
server_recv_message [Netmech_scram]
Receives the next message from the client
server_resume_session [Netsys_sasl_types.SASL_MECHANISM]
Unserializes the session, and connect with the lookup function.
server_sends_final_data [Netsys_sasl.Info]
Whether final data from the server must be interpreted by the mechanism
server_sends_final_data [Netsys_sasl_types.SASL_MECHANISM]
Whether final data from the server must be interpreted by the mechanism
server_session_id [Netsys_sasl_types.SASL_MECHANISM]
Optionally return a string that can be used to identify the server session.
server_stash_session [Netsys_sasl_types.SASL_MECHANISM]
Serializes the session as string
server_state [Netsys_sasl_types.SASL_MECHANISM]
server_user_name [Netsys_sasl_types.SASL_MECHANISM]
The name the client has authenticated as (or Not_found)
server_user_name [Netmech_scram]
The user name as transmitted from the client.
session_id [Netsys_sasl.Server]
Optionally return a string that can be used to identify the server session.
session_id [Netsys_sasl.Client]
Optionally return a string that can be used to identify the client session.
set [Rpc_portmapper]
set pm_client program_nr version_nr protocol port_nr: Extends the mapping managed by the Portmapper: The triple (program_nr, version_nr, protocol) is mapped to the given port_nr.
set [Netsys_global]
Set the value of the variable
set [Netbuffer]
set nb pos c: Sets the character at pos to c
set [Netshm_array]
set a k x: Sets the contents of the array element number k to x where 0 <= k < length a.
set [Netplex_sharedvar.VV_TYPE]
set [Netplex_cenv.VAR_TYPE]
set [Netmcore_matrix]
set sa k1 k2 x: Sets the (k1,k2)-th element of the matrix sa to a deep copy of x.
set [Netmcore_array]
set sa k x: Sets the k-th element of the array sa to a deep copy of x.
set [Netcgi.Argument]
set new_args args creates a list of argument from args deleting the arguments whose name appears in new_args and adding the new_args arguments.
set [Netcgi_common.Cookie]
set http_header cookies sets the cookies in http_header using version 0 or version 1 depending on whether version 1 fields are used.
set [Netcgi_apache.Apache.Table]
Table.set tbl key value sets the (key, value) pair in the table tbl.
set [Uq_libevent.LIBOEVENT]
set'async [Rpc_portmapper]
set_accept [Nethttp.Header]
Sets the Accept header
set_accept_charset [Nethttp.Header]
Sets the Accept-charset header
set_accept_encoding [Nethttp.Header]
Sets the Accept-encoding header
set_accept_language [Nethttp.Header]
Sets the Accept-language header
set_accept_notify [Netsys_polysocket]
set_accept_notify srv f: Sets that the function f is called when a new connection arrives.
set_accept_ranges [Nethttp.Header]
Sets the Accept-ranges header
set_age [Nethttp.Header]
Sets the Age header
set_allow [Nethttp.Header]
Sets the Allow header
set_args [Netcgi_apache.Apache.Request]
Set request_rec args field.
set_arguments [Shell_sys]
Sets the argument array
set_assignments [Shell_sys]
Sets the list of assignments (fd_from,fd_to)
set_auth_methods [Rpc_server]
Sets the available authentication methods.
set_auth_methods [Rpc_client]
Set the authentication methods for this client.
set_authorization [Nethttp.Header]
Sets the Authorization header.
set_batch_call [Rpc_proxy.ManagedClient]
The next call is a batch call.
set_batch_call [Rpc_client]
The next call will be a batch call.
set_bool_var [Netplex_cenv]
Set a variable with simple type
set_cache_control [Nethttp.Header]
Sets the Cache-control header
set_chdir [Shell_sys]
Sets the chdir parameter of the command
set_close_on_exec [Netsys]
set_cmdname [Shell_sys]
Sets the command name
set_color [Netsys_mem]
Set the GC color
set_comment [Nethttp.Cookie]
set_comment c s sets the comment of the cookie c to s which must be UTF-8 encoded (RFC 2279).
set_comment [Netcgi.Cookie]
set_comment c s sets the comment of the cookie c to s which must be UTF-8 encoded (RFC 2279).
set_comment [Netcgi_common.Cookie]
set_comment_url [Nethttp.Cookie]
set_comment_url c url same as Netcgi.Cookie.set_comment except that the cookie comment is available on the page pointed by url.
set_comment_url [Netcgi.Cookie]
set_comment_url c url same as Netcgi.Cookie.set_comment except that the cookie comment is available on the page pointed by url.
set_comment_url [Netcgi_common.Cookie]
set_connect_notify [Netsys_polysocket]
set_connect_notify cl f: Sets that the function f is called when the connection is accepted.
set_connection [Nethttp.Header]
Sets the Connection header
set_console_attr [Netsys_win32]
Get/set console attributes.
set_console_mode [Netsys_win32]
Get/set the console mode.
set_content_encoding [Nethttp.Header]
Sets the Content-encoding header
set_content_language [Nethttp.Header]
Sets the Content-language header
set_content_length [Nethttp.Header]
Sets the Content-length header
set_content_location [Nethttp.Header]
Sets the Content-location header
set_content_md5 [Nethttp.Header]
Sets the Content-MD5 header
set_content_range [Nethttp.Header]
Sets the Content-range header
set_content_type [Nethttp.Header]
Sets the Content-type header
set_content_type [Netcgi_apache.Apache.Request]
Set request_rec content_type field.
set_cookie [Nethttp.Header]
Set the Cookie header.
set_current_resolver [Uq_resolver]
Set the pluggable resolver
set_date [Nethttp.Header]
Sets the Date header
set_debug_mode [Unixqueue.Debug]
Sets enable.
set_debug_mode [Equeue.Debug]
Sets enable.
set_debug_name [Rpc_server]
Set a name printed with debug messages
set_debug_name [Rpc_client]
Set a name printed with debug messages
set_debug_target [Unixqueue.Debug]
Restricts debugging to this target.
set_debug_target [Equeue.Debug]
Restricts debugging to this target.
set_descriptors [Shell_sys]
Sets the list of active descriptors
set_dgram_destination [Rpc_client]
set_dgram_destination client addr_opt: This function is required for using the client in conjunction with unconnected UDP sockets.
set_domain [Nethttp.Cookie]
Cookies are bound to a certain domain, i.e.
set_domain [Netcgi.Cookie]
Cookies are bound to a certain domain, i.e.
set_domain [Netcgi_common.Cookie]
set_enc_value [Netplex_sharedvar]
set_enc_value name value: Sets the variable name to value.
set_encoding [Netulex.ULB]
Sets the encoding to the passed value.
set_env [Shell_sys]
Sets the contents of the environment to the passed string array
set_env_var [Shell_sys]
set_env_var env varname varval: Sets the value of the variable varname in the environment env to varval.
set_environment [Shell_sys]
Sets the environment
set_etag [Nethttp.Header]
Sets the Etag header
set_event [Netsys_win32]
Set the object to "signaled" state
set_event [Netsys_posix]
Signals the event
set_exception [Netsys_polypipe]
Sets an exception that is returned by further calls of write.
set_exception_handler [Rpc_server]
Sets the exception handler for the server.
set_exception_handler [Rpc_client]
sets an exception handler (the default prints the exception with `Crit level to the logger set in Netlog).
set_expect [Nethttp.Header]
Sets the Expect header
set_expires [Nethttp.Header]
Sets the Expires header
set_fd [Nettls_gnutls_bindings]
Sets that this file descriptor is used for I/O.
set_filename [Shell_sys]
Sets the file name of the executable to start
set_filename [Netcgi_apache.Apache.Request]
Set request_rec filename field.
set_float_var [Netplex_cenv]
set_from [Nethttp.Header]
Sets the From header
set_global_rcache_config [Rpc_proxy.ReliabilityCache]
Sets the new global config.
set_header [Netsys_crypto_types.SYMMETRIC_CRYPTO]
set_header cctx data: Sets the additional header that is authenticated for AEAD schemes.
set_host [Nethttp.Header]
Sets the Host header
set_if_match [Nethttp.Header]
Sets the If-match header
set_if_modified_since [Nethttp.Header]
Sets the If-modified-since header
set_if_none_match [Nethttp.Header]
Sets the If-none-match header
set_if_range [Nethttp.Header]
Sets the If-range header
set_if_unmodified_since [Nethttp.Header]
Sets the If-unmodified-since header
set_int_var [Netplex_cenv]
set_ipv6_system [Netsys]
Sets whether IPv6 is usable
set_iv [Netsys_crypto_types.SYMMETRIC_CRYPTO]
set_iv cctx iv: Sets the initialization vector.
set_last_modified [Nethttp.Header]
Sets the Last-modified header
set_location [Nethttp.Header]
Sets the Location header
set_max_age [Nethttp.Cookie]
set_max_age c (Some t) sets the lifetime of the cookie c to t seconds.
set_max_age [Netcgi.Cookie]
set_max_age c (Some t) sets the lifetime of the cookie c to t seconds.
set_max_age [Netcgi_common.Cookie]
set_max_forwards [Nethttp.Header]
Sets the Max-forwards header
set_max_response_length [Rpc_client]
Sets the maximum length of responses.
set_mode_method [Netftp_client]
Requests a certain mode for future file transfers
set_mstring_factories [Rpc_server]
Sets the mstring factories to use for decoding requests containing managed strings
set_mstring_factories [Rpc_client]
Sets the mstring factory configuration that is used for decoding responses containing managed strings.
set_net_db_dir [Netunidata]
Change the directory where the dynamic tables can be found
set_nonblock_event [Netsys_posix]
Sets the event fd to non-blocking mode
set_onclose_action [Rpc_server]
Every time a connection is closed, the onclose function is called with the closed connection.
set_path [Nethttp.Cookie]
Cookies are also bound to certain path prefixes, i.e.
set_path [Netcgi.Cookie]
Cookies are also bound to certain path prefixes, i.e.
set_path [Netcgi_common.Cookie]
set_path_info [Netcgi_apache.Apache.Request]
Set request_rec path_info field.
set_poll_cell [Netsys_posix]
set_poll_cell a k c: Sets the poll cell k to c.
set_ports [Nethttp.Cookie]
set ports c (Some p) says that the cookie c must only be returned if the server request comes from one of the listed ports.
set_ports [Netcgi.Cookie]
set ports c (Some p) says that the cookie c must only be returned if the server request comes from one of the listed ports.
set_ports [Netcgi_common.Cookie]
set_pragma [Nethttp.Header]
Sets the Pragma header
set_propagator [Netsys_global]
Set the current propagator to Some p, or remove the propagator with None
set_proxy_authenticate [Nethttp.Header]
Sets the Proxy-authenticate header
set_proxy_authorization [Nethttp.Header]
Sets the Proxy-authorization header The "Basic" authentication scheme is represented as explained for get_proxy_authorization.
set_range [Nethttp.Header]
Sets the Range header
set_read_notify [Netsys_polypipe]
set_read_notify pipe f: Sets that the function f is called when the pipe becomes readable (or reaches eof).
set_referer [Nethttp.Header]
Sets the Referer header
set_referrer [Nethttp.Header]
Same, for addicts of correct orthography
set_retry_after [Nethttp.Header]
Sets the Retry-after header
set_rng [Netsys_rng]
Sets the globally used RNG
set_rpcbind [Rpc_portmapper]
set_rpcbind pm_client program_nr version_nr netid uaddr owner:
set_rpcbind'async [Rpc_portmapper]
set_secure [Nethttp.Cookie]
Cookies are also bound to the type of the web server: set_secure false means servers without SSL, set_secure true means servers with activated SSL ("https").
set_secure [Netcgi.Cookie]
Cookies are also bound to the type of the web server: set_secure false means servers without SSL, set_secure true means servers with activated SSL ("https").
set_secure [Netcgi_common.Cookie]
set_server [Nethttp.Header]
Sets the Server header
set_session_cache [Netsys_crypto_types.TLS_PROVIDER]
Sets the three callbacks for storing, removing and retrieving sessions (on the server side)
set_session_filter [Rpc_server]
If set, the filter function is invoked every time the beginning of a new RPC call is received, and the result of the filter function determines what to do with the call:
set_session_filter_2 [Rpc_server]
Same as set_session_filter, but the filter gets as second argument the connection ID.
set_set_cookie [Nethttp.Header]
Set the Set-Cookie header
set_set_cookie_ct [Nethttp.Header]
Set the Set-Cookie and Set-Cookie2 headers:
set_status [Netcgi_apache.Apache.Request]
Set request_rec status field.
set_status_line [Netcgi_apache.Apache.Request]
Set request_rec status_line field.
set_string_var [Netplex_cenv]
set_structure_method [Netftp_client]
Requests a certain structure for future file transfers
set_te [Nethttp.Header]
Sets the TE header
set_timeout [Rpc_server]
Sets the timeout for the transport.
set_tmp_directory [Netsys_tmp]
Set the directory for temporary files
set_trailer [Nethttp.Header]
Sets the Trailer header
set_transfer_encoding [Nethttp.Header]
Sets the Transfer-encoding header
set_upgrade [Nethttp.Header]
Sets the Upgrade header
set_uri [Netcgi_apache.Apache.Request]
Set request_rec uri field.
set_user_agent [Nethttp.Header]
Sets the User-agent header
set_user_name [Rpc_client]
Sets the user name, or None (the default user name).
set_v [Netsys_global]
Set the value and get the new version number
set_value [Nethttp.Cookie]
set_value c v sets the value of the cookie c to v.
set_value [Netplex_sharedvar]
set_value name value: Sets the variable name to value.
set_value [Netcgi.Cookie]
set_value c v sets the value of the cookie c to v.
set_value [Netcgi_common.Cookie]
set_vary [Nethttp.Header]
Sets the Vary header
set_write_notify [Netsys_polypipe]
set_write_notify pipe f: Sets that the function f is called when the pipe becomes writable (or reaches eof).
set_www_authenticate [Nethttp.Header]
Sets the WWW-Authenticate header
setpgid [Netsys_posix]
setpgid pid pgid: Set the process group ID of the process pid to pgid.
setpgrp [Netsys_posix]
Same as setpgid 0 0: A new process group ID is created, and the current process becomes its sole member.
setregid [Netsys_posix]
Changes both the real and the effective group ID of the current process.
setreuid [Netsys_posix]
Changes both the real and the effective user ID of the current process.
setup_client_block [Netcgi_apache.Apache.Request]
Setup for reading client request.
setup_job [Shell]
Creates a job like call, but does not execute it.
shared_sub_mstring [Netxdr_mstring]
shared_sub_mstring ms pos len: returns an mstring that includes a substring of ms, starting at pos, and with len bytes.
shared_sub_mstrings [Netxdr_mstring]
Same for a list of mstrings
shell_fs [Shell_fs]
The shell filesystem.
shm_create [Netsys_posix]
let (fd,name) = shm_create prefix size: Creates an shm object with a unique name.
shm_name [Netmcore_mempool]
Returns the name of the shared memory object
shm_open [Netsys_posix]
Opens a shared memory object.
shm_table [Netshm_array]
Returns the underlying shared memory table used to implement hash tables
shm_table [Netshm_hashtbl]
Returns the underlying shared memory table used to implement hash tables.
shm_type_of_name [Netshm]
shm_unlink [Netsys_posix]
Unlinks the name for a shared memory object
should_client_block [Netcgi_apache.Apache.Request]
Returns true if there is any client request data.
shut_down [Rpc_proxy.ManagedSet]
shut_down [Rpc_proxy.ManagedClient]
shut_down [Rpc_portmapper]
Shuts down the connection
shut_down [Rpc_simple_client]
Shut the connection down.
shut_down [Rpc_client]
Shuts down the connection.
shutdown [Netsys_tls]
Ends the TLS encapsulation of data:
shutdown_connector [Rpc_client]
The default implementation to shut down the connector.
shutdown_e [Uq_io]
Performs a regular shutdown of the device.
sign [Netsys_crypto_types.PUBKEY_CRYPTO]
sign [Netx509_pubkey_crypto]
let signature = sign alg key plaintext: Creates a signature.
signal [Netmcore_condition]
signal c restarts one of the processes waiting on the condition variable c.
signal_engine [Uq_engines_compat]
signal_engine [Uq_engines]
let (se, signal) = signal_engine esys: Same as function
signature [Rpc_program]
simple [Netcgi.Argument]
simple_arg name value creates an unstructured CGI argument called name with contents value.
simple_bind_creds [Netldap]
simple_listing [Nethttpd_services]
Simple listing generator for `Enable_listings
simple_pin_callback [Netsys_crypto_types.PUBKEY_CRYPTO]
since_epoch [Netdate]
Convert a date/time record into the time (seconds since the epoch), rounded down to the next integral number.
since_epoch_approx [Netdate]
Same, but the nanos are added to the seconds.
since_epoch_timespec [Netdate]
Returns the seconds since the epoch as pair (seconds,nanos)
size [Netsys_crypto_types.DIGESTS]
returns the size of the hash output (in bytes)
size_mem [Netmcore_mempool]
Returns the size of this block, or raises Not_found
size_mem_at_addr [Netmcore_mempool]
Returns the size of the block at this address, or raises Not_found
size_method [Netftp_client]
Determines the size of file.
skip_line_ends [Netmime_string]
skip_line_ends s pos len: Skips over adjacent line ends (terminated by CR/LF or plain LF), and returns the position after the last line end.
skip_line_ends_poly [Netmime_string]
polymorphic version
skip_whitespace_left [Netmime_string]
skip_whitespace_left s pos len: Returns the smallest p with p >= pos && p < pos+len so that s.[p] is not a whitesapce character (space, TAB, CR, LF), and s.[q] is a whitespace character for all q<p.
skip_whitespace_right [Netmime_string]
skip_whitespace_right s pos len: Returns the biggest p with p >= pos && p < pos+len so that s.[p] is not a whitesapce character (space, TAB, CR, LF), and s.[q] is a whitespace character for all q>p.
sleep [Netsys]
small_block_size [Netsys_mem]
The block size of small_pool, normally 4K (or better, the page size)
small_pool [Netsys_mem]
Another standard pool where the blocks are smaller than in default_pool.
sockaddr_is_enabled [Rpc_proxy.ReliabilityCache]
Returns whether the sockaddr is enabled.
sockaddr_of_program_rpcbind [Rpc_portmapper]
sockaddr_of_program program host netid: gets the sockaddr for this program.
sockaddr_of_socksymbol [Uq_resolver]
Use the resolver to look up names in Netsockaddr.socksymbol, and convert the symbol to a Unix.sockaddr only containing IP addresses.
sockaddr_of_uaddr [Rpc]
sockaddr_of_uaddr netid uaddr.
sockspec_of_sockaddr [Uq_engines_compat]
sockspec_of_sockaddr [Uq_client]
Converts a normal socket address to the extended form
sockspec_of_socksymbol [Uq_engines_compat]
sockspec_of_socksymbol [Uq_client]
Converts a Netsockaddr.socksymbol to this form
socksymbol_of_string [Netsockaddr]
Parses designations of the forms: <IPv4>:port, [<IPv4_or_IPv6]:port, <name>:port, /path, ./path Raises Failure on parse error.
spawn [Netsys_posix]
spawn cmd args: Fork the process and exec cmd which gets the arguments args.
specials_rfc2045 [Netmime_string]
The sets of special characters defined by the RFCs 822 and 2045.
specials_rfc822 [Netmime_string]
split [Netstring_str]
Splits the string according to the regexp in substrings.
split [Netstring_pcre]
Splits the string according to the regexp in substrings.
split_delim [Netstring_str]
Same as split, but occurrences of the delimiter at the beginning and the end are returned as empty strings
split_delim [Netstring_pcre]
Same as split, but occurrences of the delimiter at the beginning and the end are returned as empty strings
split_glob_expr [Netglob]
Splits the glob expression into filename components separated by literal / characters.
split_host_port [Nethttp]
Splits the Host header in hostname and optional port number.
split_mime_type [Netmime_string]
let (main_type, sub_type) = split_mime_type content_type: Splits the MIME type into main and sub type, for example split_mime_type "text/plain" = ("text", "plain") .
split_path [Neturl]
Splits a '/'-separated path into components (e.g.
split_uri [Netmime_string]
Splits a long URI according to the algorithm of RFC 2017.
spnego_trans_id [Nethttp]
Identifies an anonymous HTTPS transport that is additionally authenticated via SPNEGO (as described in RFC 4559)
spnego_trans_id [Nethttp_client]
Identifies an anonymous HTTPS transport that is additionally authenticated via SPNEGO (as described in RFC 4559)
squash_file_tls_endpoint [Nettls_support]
Coerce a file endpoint to a normal endpoint
squeue_of_descr [Netmcore_queue]
Look up the queue for this descriptor
sref [Netmcore_ref]
The shared version of ref: Creates a mutable shared variable in the given memory pool
sref_of_descr [Netmcore_ref]
Look up the reference for this descriptor
ssh_interpreter [Shell_fs]
Executes commands via ssh on the machine host as user (defaults to current user).
standard_event_system [Unixqueue]
Create a new, empty, standard event system
standard_pollset [Netsys_pollset_generic]
Returns a good standard implementation of pollset for this platform.
start [Netmcore_process]
let pid = start fp arg: Starts a new process at the fork point fp with argument arg.
start [Netmcore_buffer]
Returns the start index
start [Netmcore]
let pid = start fork_point arg: Starts the process with the given fork_point and the argument arg.
startup [Netplex_main]
Establishes a configuration and starts the Netplex daemon.
startup [Netmcore]
This function makes the current process the master process.
stash_endpoint [Netsys_crypto_types.TLS_PROVIDER]
The endpoint in "stashed" form, encapsulated as an exception.
stash_session [Netsys_sasl.Server]
Serializes the session as string
stash_session [Netsys_sasl.Client]
Serializes the session as string
state [Netsys_sasl.Client]
report the state (whether expecting challenges or responding)
stats [Netmcore_mempool]
Returns (total, free, contiguous) where total is the total size of the pool, free is the number of free bytes, contiguous is the size of the largest contiguous free block
status [Shell_sys]
Reports the status so far known: If the process has terminated, the status of the process is returned.
status [Netcgi_apache.Apache.Request]
request_rec status field.
status_line [Netcgi_apache.Apache.Request]
request_rec status_line field.
status_of_bad_request_error [Nethttpd_kernel]
Returns the best response code for the error
status_of_cgi_header [Nethttp]
Returns the status code and the status text corresponding to the Status header
std_access_log_string [Nethttpd_util]
Returns a log line for access logging
std_activation [Nethttpd_services]
Create the function for dyn_activation from a std_activation tag.
std_debug_access_log_string [Nethttpd_util]
Returns a log string for extended access logging (multi-line)
std_error_log_string [Nethttpd_util]
Returns a log line for error logging
std_error_response [Nethttpd_util]
Returns the HTML text of the standard error response
std_error_response [Nethttpd_plex]
A sample error response function
std_log_access [Nethttpd_plex]
Returns a function that logs accesses using the log_subch method of the passed container
std_log_error [Nethttpd_plex]
Returns a function that logs errors using the log_subch method of the passed container
stderr [Shell]
The standard descriptors; defined here for convenience.
stderr_logger_factory [Netplex_log]
Reads a logging section like
stdin [Shell]
stdout [Shell]
stop_connection [Rpc_server]
Schedules a special event that causes the connection to be stopped in the very near future.
stop_server [Rpc_server]
Stops the server: If a TCP server socket is listening, it is immediately closed.
storage [Netmime_channels]
Creates a new storage facility for a mime body according to store.
stored_key [Netmech_scram]
str_send [Netsys_tls]
Same for immutable string
stream_rpc_multiplex_controller [Rpc_transport]
The multiplex controller for stream encapsulation
stream_seq_engine [Uq_engines_compat]
stream_seq_engine [Uq_engines]
Same as function
streamline_seq [Netasn1]
streamline_seq expected seq: This function can be called for a list of values Value.Seq seq, and will compare the list seq with the expected list, and will mark missing elements in the sequence, and will recursively decode the occurring elements with the type information from expected.
streamline_set [Netasn1]
streamline_set typeinfo set: This function can be called for a list of values Value.Set seq, and decodes the list with the type information from typeinfo.
string_after [Netstring_str]
The last n characters of a string
string_after [Netstring_pcre]
The last n characters of a string
string_based_mstrings [Netxdr_mstring]
string_before [Netstring_str]
The first n characters of a string
string_before [Netstring_pcre]
The first n characters of a string
string_manager [Netshm_data]
Represents a string in the following way.
string_match [Netstring_str]
Matches the string at the position with the regexp.
string_match [Netstring_pcre]
Matches the string at the position with the regexp.
string_of_bad_request_error [Nethttpd_kernel]
Convert error to a string, for logging
string_of_buffer [Netgss_bindings]
string_of_calling_error [Netsys_gssapi]
string_of_encoding [Netconversion]
Returns the name of the encoding.
string_of_fatal_error [Nethttpd_kernel]
Convert error to a string, for logging
string_of_fd [Netsys]
Return a string describing the descriptor (for debugging)
string_of_fd_style [Netsys]
Returns a string describing the fd style (debugging)
string_of_flag [Netsys_gssapi]
string_of_http_method [Netcgi_common]
Returns the string value of the method
string_of_http_status [Nethttp]
Returns the informational text for a status value
string_of_in_obj_channel [Netchannels]
Reads from the input channel until EOF and returns the characters as string.
string_of_level [Netlog]
Convert level names to strings and vice versa
string_of_major_status [Netsys_gssapi]
string_of_memory [Netsys_mem]
Return a new string as a copy of the bigarray
string_of_output_state [Nethttpd_types]
Debugging
string_of_packed_value [Rpc_packer]
string_of_protocol [Nethttp]
Returns the string representation, e.g.
string_of_req_token [Nethttpd_kernel]
For debugging
string_of_request [Rpc_util]
Return the string representation of this call request
string_of_request_method [Netcgi_common]
string_of_response [Rpc_util]
Return the string representation of this call response
string_of_routine_error [Netsys_gssapi]
string_of_server_error [Rpc]
returns a string for debug purposes
string_of_server_error [Netmech_scram]
string_of_sockaddr [Rpc_transport]
Convert to string, for debugging purposes
string_of_sockaddr [Netsys]
Returns a human-readable string describing the address (for debug messages).
string_of_socksymbol [Netsockaddr]
The reverse function
string_of_state [Uq_engines_compat]
string_of_state [Uq_engines]
For debug purposes: Returns a string describing the state
string_of_suppl_status [Netsys_gssapi]
string_of_url [Neturl]
Returns the URL as string
string_of_value [Rpc_util]
Return a string representation of the value which must have the passed type
string_of_verification_status_flag [Nettls_gnutls_bindings]
Returns a string for the status code
string_ops [Netstring_tstring]
Implementation of the operations for string
string_to_mstring [Netxdr_mstring]
Represent a string as mstring (no copy)
string_var [Netplex_cenv]
strong_validator_match [Nethttp]
Whether the tags match strongly (see RFC 2616 for definition)
sub [Netpagebuffer]
Returns a substring
sub [Netbuffer]
sub nb k n: returns the n characters starting at position n from netbuffer nb as fresh string
sub [Netmcore_buffer]
Returns a substring
sub_bytes [Netpagebuffer]
Same for bytes
sub_bytes [Netbuffer]
Same for bytes
sub_lexeme [Netulex.Ulexing]
Returns a substring of the lexeme as array of Unicode code points.
subprocess_env [Netcgi_apache.Apache.Request]
request_rec subprocess_env field.
substitute_first [Netstring_str]
substitute_first re subst s: Applies the substitution function subst to the first matching of re in s, and returns the transformed string.
substitute_first [Netstring_pcre]
substitute_first re subst s: Applies the substitution function subst to the first matching of re in s, and returns the transformed string.
supported_types [Netshm]
The types supported for this OS
supported_x509 [Netsys_crypto_types.PUBKEY_CRYPTO]
The supported X509 algorithm types as list of OIDs
supports_aead [Netsys_crypto_types.SYMMETRIC_CRYPTO]
Whether this cipher integrates authentication
supports_authz [Netsys_sasl.Info]
whether the authorization name can be transmitted
supports_authz [Netsys_sasl_types.SASL_MECHANISM]
whether the authorization name can be transmitted
switch [Netsys_crypto_types.TLS_PROVIDER]
The server can use this to request a rehandshake and to use the new configuration for cert verification.
symlinkat [Netsys_posix]
symlinkat oldpath newdirfd newpath flags
sync_call [Rpc_client]
sync_engine [Uq_engines_compat]
sync_engine [Uq_engines]
Same as function
sync_shutdown [Rpc_proxy.ManagedSet]
sync_shutdown [Rpc_proxy.ManagedClient]
sync_shutdown [Rpc_client]
Enforces a synchronous shutdown of the connection.
synchronize [Rpc_client]
Turns an async call into a synchronous call
sysconf_open_max [Netsys_posix]
Return the maximum number of open file descriptor per process.
syslog [Netsys_posix]
syslog facility level message: Logs message at level for facility
syslog_logger [Netplex_log]
Creates a logger writing to syslog
syslog_logger_factory [Netplex_log]
Reads a logging section like
system_restart [Netplex_cenv]
Initiates a system restart (like the restart method of the controller)
system_shutdown [Netplex_cenv]
Initiates a system shutdown (like the shutdown method of the controller)

T
tcgetpgrp [Netsys_posix]
Return the process group ID of the foreground process group of the session associated with the file descriptor, which must be a tty.
tcp_port [Netpop]
Default TCP port for POP version 3
tcp_port [Netsmtp]
default TCP port for SMTP
tcsetpgrp [Netsys_posix]
Sets the foreground process group ID of the session associated with the file descriptor, which must be a tty.
tempfile_transactional_optype [Netcgi1_compat.Netcgi]
tempfile_transactional_optype [Netcgi]
Deprecated name for tempfile_transactional_outtype
tempfile_transactional_outtype [Netcgi]
The output_type implementing transactions with a tempfile-based buffer
template [Netcgi_modtpl]
Compile the template from a named file.
template_from_channel [Netcgi_modtpl]
Compile the template from a channel.
template_from_string [Netcgi_modtpl]
Compile the template from a literal string.
terminate_process [Netsys_win32]
Terminates the process
test_bind [Netldap]
Same as synchronous function
test_bind_e [Netldap]
Tries to bind to the server with the given credentials.
test_close_on_exec [Netsys_win32]
Tests whether the handle is not inheritable
test_event [Netsys_win32]
Test whether the object is in signaled state
test_nonce [Netmech_scram_http.PROFILE]
tests [Netmech_scram.AES_CTS]
the_request [Netcgi_apache.Apache.Request]
request_rec the_request field.
threaded_pollset [Netsys_pollset_win32]
This implementation overcomes the limit on the number of descriptors one can add to the set.
timeout_engine [Uq_engines_compat]
timeout_engine [Uq_engines]
Same as function
timer_create [Netsys_posix]
Create a new timer that will report expiration as given by the arg: TEXP_NONE: no notification, TEXP_EVENT e: the not_event e is signalled, TEXP_EVENT_CREATE: a special not_event is created for the timer. (Get the event via timer_event, see below.), TEXP_SIGNAL n: the signal n is sent to the process Note that TEXP_EVENT_CREATE is much faster on Linux than TEXP_EVENT, because it can be avoided to start a new thread whenever the timer expires.
timer_delete [Netsys_posix]
Deletes the timer
timer_event [Netsys_posix]
Returns the notification event for the timer styles TEXP_EVENT and TEXP_EVENT_CREATE.
timer_gettime [Netsys_posix]
Returns the number of seconds until the expiration, or (0.0,0) if the timer is off
timer_id [Netplex_cenv]
Returns an ID, e.g.
timer_settime [Netsys_posix]
timer_settime tm abstime interval value:
tls [Nettls_gnutls]
The implementation of TLS backed by GnuTLS, as value
tls_method [Netftp_client]
This FTP method negotiates the use of TLS.
tls_multiplex_controller [Uq_multiplex]
Creates a new multiplex controller on top of an existing controller, and configures the new controller for running the TLS protocol.
tls_session_props [Netldap]
Returns the TLS session properties
tls_socket_config [Rpc_server]
This configuration establishes TLS when accepting new connections.
tls_socket_config [Rpc_client]
This configuration establishes TLS when connecting with the server.
tmp_directory [Netsys_tmp]
Return the directory for temporary files.
tmp_prefix [Netsys_tmp]
tmp_prefix p: Enhance the prefix for temporary files by appending some digits to p.
to_buffer [Shell]
Creates a consumer writing the data into the passed buffer.
to_buffer [Shell_sys]
to_buffer b returns a function which can be used as consumer argument for add_consumer.
to_bytes [Netpagebuffer]
Returns the contents of the buffer as fresh string.
to_bytes [Netbuffer]
Returns the contents of the buffer as fresh string.
to_compat_activation [Netcgi1_compat.Netcgi_types]
Portage: to_compat_activation converts a new style cgi object to an old cgi_activation object.
to_compat_argument [Netcgi1_compat.Netcgi_types]
Portage: to_compat_argument a converts a new style argument a to an old style one.
to_compat_config [Netcgi1_compat.Netcgi_env]
Portage: to_compat_config c transform the new configuration c into one suitable for the old interface.
to_compat_environment [Netcgi1_compat.Netcgi_env]
Portage: to_compat_environment e converts the new environment e to the old interface.
to_dev_null [Shell]
A consumer redirecting the data to /dev/null.
to_fd [Shell]
Creates a consumer redirecting the data to the file descriptor
to_file [Shell]
Creates a consumer writing the data into the file whose name is passed to this function.
to_function [Shell]
Creates a consumer writing the data by calling a function.
to_hex [Netencoding]
to_lower [Netunichar]
Converts the input letter to lowercase.
to_netbuffer [Shell_sys]
Same for a Netbuffer
to_netscape_cookie [Nethttp.Cookie]
Convert to Netscape cookie (with information loss)
to_netscape_cookie [Netcgi.Cookie]
Convert to Netscape cookie (with information loss)
to_record [Netcgi_common.Cookie]
Conversion to the deprecated style of cookie (some parameters are dropped).
to_string [Netexn]
Prints the exception as string, using the registered printer functions, or Printexc.to_string as fallback if there is no better printer
to_string [Netoid]
Returns the OID in dot notation, e.g.
to_string_curly [Netoid]
Returns the OID in curly brace notation, e.g.
to_title [Netunichar]
Same for titlecase conversion
to_tstring [Netpagebuffer]
Returns the buffer as tagged string, selecting the chosen representation
to_tstring [Netbuffer]
Returns the buffer as tagged string, selecting the chosen representation
to_tstring_poly [Netpagebuffer]
Return the buffer in the format as selected by the arg
to_tstring_poly [Netbuffer]
Return the buffer in the format as selected by the arg
to_unicode [Netconversion]
Maps the code point of the charset to the corresponding Unicode code point, or raises Malformed_code, when the input number does not correspond to a code point.
to_upper [Netunichar]
Same for uppercase conversion
top_c [Netmcore_queue]
pop_p q f: Takes the first element x of the queue, and calls f x, without removing x from the queue.
top_p [Netmcore_queue]
pop_p q f: Takes the first element x of the queue, and calls f x, without removing x from the queue.
track_fd [Netlog.Debug]
track_fd ~owner ~descr fd: Enters the descriptor fd into the descriptor table.
trigger_shutdown [Rpc_proxy.ManagedSet]
Shut down the managed set.
trigger_shutdown [Rpc_proxy.ManagedClient]
Shut down the managed client.
trigger_shutdown [Rpc_client]
Triggers the shutdown, and calls the passed function back when it is done.
truncate_trailing_zero_bits [Netasn1.Value]
Truncates the biggest trailing part that only consist of 0 bits
try_shrinking [Netbuffer]
try_shrinking nb: If the length of the buffer is less than half of the allocated space, the netbuffer is reallocated in order to save memory.
tstring_of_tbuffer [Netstring_tstring]
Get the tagged string of a tagged buffer
tty_read_password [Netsys_posix]
tty_read_password prompt: If tty is a terminal, the prompt is printed, and a password is read from the terminal (echo off).
ttyname [Netsys_posix]
Returns the name of the controlling tty referred to by the file descriptor.
type_of_value [Netasn1.Value]
Returns the type, or None for Tag, ITag and Tagptr

U
uarray_of_ustring [Netconversion]
Returns the characters of the string as array of Unicode code points.
uarray_of_ustring_poly [Netconversion]
Polymorphic version
uarray_of_ustring_ts [Netconversion]
Same for tagged strings
uchar_at [Netconversion]
Returns the Unicode code point of the character at the cursor.
uint4_as_bytes [Netnumber.ENCDEC]
uint4_as_string [Netnumber.ENCDEC]
uint4_of_int [Netnumber]
uint4_of_int32 [Netnumber]
uint4_of_int64 [Netnumber]
uint8_as_bytes [Netnumber.ENCDEC]
<t>_as_bytes: Returns the corresponding bytes for an integer value
uint8_as_string [Netnumber.ENCDEC]
<t>_as_string: Returns the corresponding string for an integer value
uint8_of_int [Netnumber]
uint8_of_int32 [Netnumber]
uint8_of_int64 [Netnumber]
unbind [Rpc_server]
Unbinds the program if it is bound by the server
unbound_async_call [Rpc_client.USE_CLIENT]
unbound_ssync_call client pgm proc arg emit: Invoke the remote procedure proc of the program pgm via client.
unbound_async_call [Rpc_client]
unbound_ssync_call client pgm proc arg emit: Invoke the remote procedure proc of the program pgm via client.
unbound_create [Rpc_client]
Creates an unbound client.
unbound_sync_call [Rpc_client.USE_CLIENT]
unbound_sync_call client pgm proc arg: Invoke the remote procedure proc of the program pgm via client.
unbound_sync_call [Rpc_client]
unbound_sync_call client pgm proc arg: Invoke the remote procedure proc of the program pgm via client.
undefault_url [Neturl]
Removes components from the URL if they have the passed value, and returns the modified URL.
unix_error_of_code [Netsys]
Converts an integer error into the corresponding variant
unlim_tls_cache [Nethttp_client]
Returns a simple cache without limit for the number of cached sessions
unlink [Netsys_sem]
Unlinks the identified container if it exists, and unlinks all possible named semaphores.
unlink_camlbox [Netcamlbox]
Removes the global name of the camlbox.
unlink_mempool [Netmcore_mempool]
Deletes the persistent objects of this pool
unlink_shm [Netshm]
Removes the name permanently from the system
unlink_this [Netsys_pmanage]
Unlinks this object
unlinkat [Netsys_posix]
Same as Unix.unlink but unlink the file relative to the directory given by first argument
unlock [Netmappings]
unlock [Netplex_mutex]
Unlocks the mutex.
unlock [Netmcore_mutex]
Unlocks the mutex
unlockpt [Netsys_posix]
Unlock a PTY master/slave pair
unmarshal_client_props [Netsys_gssapi]
unmarshal_server_props [Netsys_gssapi]
This doesn't restore deleg_credential which is unmarshallable!
unpack_call [Rpc_packer]
unpack_call_body [Rpc_packer]
unpack_call_body_raw [Rpc_packer]
unpack_call_body_raw_bytes [Rpc_packer]
unpack_call_frame [Rpc_packer]
unpack_call_frame_l [Rpc_packer]
unpack_reply [Rpc_packer]
unpack_reply_verifier [Rpc_packer]
unpack_xdr_value [Netxdr]
unpack_xdr_value_l [Netxdr]
prefix: whether it is ok that the string is longer than the message (default: false)
unpack_xdr_value_str [Netxdr]
Same for strings
unpredictable_pipe_name [Netsys_win32]
Returns a valid pipe name that can practically not be predicted
unregister [Netsys_win32]
Removes this descriptor from the lookup table.
unsafe_buffer [Netbuffer]
Warning! This is a low-level function! Returns the current string that internally holds the buffer.
unsafe_chars_html4 [Netencoding.Html]
The string contains '<', '>', '"', '&' and the control characters 0-8, 11-12, 14-31, 127.
unset [Rpc_portmapper]
unset pm_client program_nr version_nr protocol port_nr: removes the mapping.
unset [Netcgi_apache.Apache.Table]
Table.unset tbl key delete every key/value pair associated with the key from the table tbl.
unset'async [Rpc_portmapper]
unset_rpcbind [Rpc_portmapper]
set_rpcbind pm_client program_nr version_nr netid uaddr owner.
unset_rpcbind'async [Rpc_portmapper]
unwrap [Netplex_encap.ENCAP]
Raises Netplex_encap.Type_mismatch if the value does not fit
unwrap_wrap_token_conf [Netgssapi_support]
Unwraps the token using the decryption function decrypt_and_verify from the cryptosystem.
update [Rpc_program]
Modifies program and/or version number.
update [Netplex_sharedvar.VV_TYPE]
update_alist [Nethttpd_types]
update_alist updl l: Returns the alist with all elements of updl and all elements of l that are not member of updl.
update_props_inheader [Netcgi_common]
update_props_inheader (name, value) (props, inheader) returns (props, inheader) to which the new parameter name-value has been added -- to props or inheader, depending on name.
uri [Netcgi_apache.Apache.Request]
request_rec uri field.
uri_distributor [Nethttpd_services]
Configures URI distribution.
uripath_decode [Nethttp]
Decodes %XX sequences in URI paths.
uripath_encode [Nethttp]
Encodes unsafe characters in URI paths.
url_addr [Neturl]
If the host part of the URL is an IP address, the address is returned.
url_fragment [Neturl]
url_host [Neturl]
url_of_string [Neturl]
Parses the passed string according to the passed url_syntax.
url_other [Neturl]
Return components of the URL.
url_param [Neturl]
url_password [Neturl]
url_path [Neturl]
url_port [Neturl]
url_provides [Neturl]
Returns true iff the URL has all of the components passed with true value.
url_query [Neturl]
url_scheme [Neturl]
url_socksymbol [Neturl]
url_socksymbol url default_port: Returns the host and port parts of the URL as socksymbol.
url_syntax_is_valid [Neturl]
Checks whether the passed url_syntax is valid.
url_syntax_of_url [Neturl]
Returns the url_syntax record of a URL.
url_user [Neturl]
url_user_param [Neturl]
use [Rpc_client.USE_CLIENT]
Announcement that this program will be used.
use [Rpc_client]
If there are no bound programs, this is a no-op.
user [Netcgi_apache.Apache.Request]
The authenticated user.
user_encoding [Netconversion]
Determines the preferred user encoding:
user_name [Netsys_sasl.Server]
The name the client has authenticated as (or Not_found)
user_name [Netsys_sasl.Client]
The user name
ustring_compare [Netconversion]
Compares two strings lexicographically.
ustring_compare_poly [Netconversion]
Polymorphic version
ustring_compare_ts [Netconversion]
Same for tagged strings
ustring_iter [Netconversion]
Iterates over the characters of a string, and calls the passed function for every code point.
ustring_iter_poly [Netconversion]
Polymorphic version
ustring_iter_ts [Netconversion]
Same for tagged strings
ustring_length [Netconversion]
Returns the length of the string in characters.
ustring_length_poly [Netconversion]
Polymorphic version
ustring_length_ts [Netconversion]
Same for tagged strings
ustring_map [Netconversion]
Maps every character of a string to a list of characters, and returns the concatenated string.
ustring_map_poly [Netconversion]
Polymorphic version
ustring_map_ts [Netconversion]
Same for tagged strings.
ustring_of_uarray [Netconversion]
Returns the array of Unicode code points as encoded string.
ustring_of_uchar [Netconversion]
ustring_of_uchar enc i: Creates the string representing the Unicode code point i in encoding enc.
ustring_sub [Netconversion]
ustring_sub enc start length s: Returns the substring of s starting at character count start and consisting of length characters.
ustring_sub_poly [Netconversion]
Polymorphic version
ustring_sub_ts [Netconversion]
Same for tagged strings.
ustring_to_lower [Netconversion]
Converts the input string to lowercase.
ustring_to_lower_poly [Netconversion]
Polymorphic version
ustring_to_lower_ts [Netconversion]
Same for tagged strings.
ustring_to_title [Netconversion]
Converts the input string to titlecase.
ustring_to_title_poly [Netconversion]
Polymorphic version
ustring_to_title_ts [Netconversion]
Same for tagged strings.
ustring_to_upper [Netconversion]
Converts the input string to uppercase.
ustring_to_upper_poly [Netconversion]
Polymorphic version
ustring_to_upper_ts [Netconversion]
Same for tagged strings.
utctime [Netasn1.Value]
Create a time value for UTCTime.
utf8_lexeme [Netulex.Ulexing]
Returns the lexeme as UTF-8 encoded string
utf8_sub_lexeme [Netulex.Ulexing]
Returns a substring of the lexeme as UTF-8 encoded string.
utf8_sub_lexeme_length [Netulex.Ulexing]
Same as String.length(utf8_sub_lexeme args), i.e.
utf8_sub_string [Netulex.ULB]
The two int arguments are the position and length of a sub string of the lexbuf that is returned as UTF8 string.
utf8_sub_string_length [Netulex.ULB]
Returns String.length(utf8_sub_string args).

V
validate_glob_expr [Netglob]
Checks whether the passed expression is syntactically valid.
validate_xdr_type [Netxdr]
validate_xdr_type_system [Netxdr]
value [Nethttp.Cookie]
The value of the cookie.
value [Netcgi.Cookie]
The value of the cookie.
value [Netcgi_common.Cookie]
value_area [Netsys_mem]
Marks the memory block as value area.
value_matches_type [Netxdr]
Is the value properly formed with respect to this type? The third argument of this function is a list of parameter instances.
verbose [Rpc_server]
Deprecated.
verbose [Rpc_client]
set whether you want debug messages or not (same as setting Rpc_client.Debug.enable)
verify [Netsys_crypto_types.PUBKEY_CRYPTO]
verify [Netsys_crypto_types.TLS_PROVIDER]
verify ep peer_name: Checks that: there is a trust chain for the peer's certificate, that peer_name is the common name of the certificate subject, or an alternate name These checks are not performed if peer_auth=`None is set in the configuration!
verify [Netx509_pubkey_crypto]
verify alg key plaintext signature: Checks the signature, and returns true on success.
verify [Netconversion]
Checks whether the string is properly encoded.
verify_mic_token [Netgssapi_support]
Verifies the MIC token with get_mic, and returns true if the verification is successful
verify_poly [Netconversion]
Polymorphic version
verify_ts [Netconversion]
Same for tagged strings
version [Netplex_sharedvar.VV_TYPE]
version_number [Rpc_program]
Return the version number
vv_access [Netplex_sharedvar]
Get the current value of this variable.
vv_access_enc [Netplex_sharedvar]
Same for encapsulated variables
vv_get [Netplex_sharedvar]
Extract the current value, or None if the variable cannot be found.
vv_set [Netplex_sharedvar]
Set the current value.
vv_update [Netplex_sharedvar]
Check whether there is a new version of the value, and update the cache.
vv_version [Netplex_sharedvar]
Get the current version number.

W
wait [Shell_fs]
Waits until the running command is finished
wait [Netmcore_condition]
wait we c m atomically unlocks the mutex m and suspends the calling process on the condition variable c.
wait [Netmcore_sem]
Decrements the semaphore by one.
wait_e [Netmcore_condition]
Like wait, but the suspension is done by waiting on a named pipe event (i.e.
wait_event [Netsys_posix]
If the event fd is not signalled, the function blocks until it gets signalled, even in non-blocking mode.
wait_for_enc_value [Netplex_sharedvar]
Same for encapsulated variables
wait_for_value [Netplex_sharedvar]
wait_for_value name: If the variable exists and set_value has already been called at least once, the current value is returned.
wait_until_connected [Netsys]
After a non-blocking connect has been initiated, this function can be used to wait until (1) the connect is successful, or (2) the connect fails, or (3) the operation times out.
wait_until_prird [Netsys]
Wait until an operation for a single descriptor becomes possible.
wait_until_readable [Netsys]
wait_until_writable [Netsys]
walk_method [Netftp_client]
This FTP method walks to the target directory:
watch_subprocess [Netsys_posix]
let fd, ws = watch_subprocess pid pgid kill_flag: Enters the subprocess pid into the watch list.
watchdog [Uq_engines_compat]
watchdog [Uq_engines]
Same as function
weak_once [Unixqueue]
Same as once, but the timer does not keep the event system running if it is the only remaining resource.
weak_validator_match [Nethttp]
Whether the tags match weakly (see RFC 2616 for definition)
week_day [Netdate]
Returns the week day.
when_state [Uq_engines_compat]
when_state [Uq_engines]
Watches the state of the argument engine, and arranges that one of the functions is called when the corresponding state change is done.
win32_code_pages [Netconversion]
Mapping between Win32 code page numbers and Ocamlnet encodings.
win_pid [Netsys_win32]
Returns the Windows notion of the process identifier (pid)
wire_decode_token [Netgssapi_support]
Encode tokens as described in section 3.1 of RFC 2078.
wire_encode_token [Netgssapi_support]
with_in_obj_channel [Netchannels]
with_in_obj_channel ch f: Computes f ch and closes ch.
with_out_obj_channel [Netchannels]
with_out_obj_channel ch f: Computes f ch and closes ch.
with_tstring [Netstring_tstring]
with_tstring f ts: Calls f.with_fun with the right implementation of the tstring_ops argument
with_tstring_cursor [Netconversion]
Creates a cursor like create_cursor and calls with_cursor_fun with the cursor, returning any result unchanged.
with_tty [Netsys_posix]
with_tty f: Runs f fd where fd is the terminal of the process.
with_value [Netmcore_heap]
with_value h find process: Logically, this runs process (find ()) and returns the result.
with_value_2 [Netmcore_heap]
with_value_3 [Netmcore_heap]
with_value_4 [Netmcore_heap]
with_value_5 [Netmcore_heap]
Same as with_value, but a tuple of values can be passed down
with_value_n [Netmcore_heap]
Same as with_value, but a list of values can be passed down
workload_manager_factories [Netplex_workload]
All built-in workload manager factories
wr_file [Netsys_crypto_types.FILE_TLS_ENDPOINT]
wrap [Netplex_encap.ENCAP]
wrap_attachment [Netsendmail]
Generates a header for the mime_body.
wrap_complex_mime_message_ro [Netmime]
wrap_mail [Netsendmail]
Sets the mail-related header fields in the input message, and returns a message ready for delivery.
wrap_mime_body_ro [Netmime]
Same as function
wrap_mime_header_ro [Netmime]
Same as function
wrap_parts [Netsendmail]
Generates an intermediate container for multipart attachments.
write [Netsys_polypipe]
write a message, or mark the end of the stream (None).
write [Nethtml]
Writes the document to the output channel.
write_blocks [Netshm]
write_blocks tbl ops key f: Like read_blocks this function iterates over the blocks of all bindings for key.
write_descr [Netsys_polypipe]
Returns a descriptor that can be used for polling.
write_eof_e [Uq_io]
let e = write_eof_e d: For devices supporting half-open connections, this engine writes the EOF marker and transitions to `Done true.
write_fp4 [Netnumber.ENCDEC]
write_fp8 [Netnumber.ENCDEC]
write_header [Netmime_string]
This function writes the header to the passed out_obj_channel.
write_int4 [Netnumber.ENCDEC]
write_int4_unsafe [Netnumber.ENCDEC]
write_int8 [Netnumber.ENCDEC]
write_int8_unsafe [Netnumber.ENCDEC]
write_mime_message [Netmime_channels]
Writes the MIME message to the output channel.
write_uint4 [Netnumber.ENCDEC]
write_uint4_unsafe [Netnumber.ENCDEC]
write_uint8 [Netnumber.ENCDEC]
write_<t> copies the characters corresponding to the integer values into the string at the given positions.
write_uint8_unsafe [Netnumber.ENCDEC]
write_<t>_unsafe: Same, but no index check.
write_value [Netmime_string]
Writes the list of s_token to the out_obj_channel.
wsa_enum_network_events [Netsys_win32]
Checks whether an event has been recorded
wsa_event_select [Netsys_win32]
associate event objects with socket conditions
wsa_maximum_wait_events [Netsys_win32]
max size of the array passed to wsa_wait_for_multiple_events
wsa_wait_for_multiple_events [Netsys_win32]
Waits until one of the events in the array is in signaled state, or until a timeout happens.

X
x_array_max [Netxdr]
Common abbreviation for arrays of arbitrary length
x_bool [Netxdr]
Common abbreviation for boolean types.
x_mstring_max [Netxdr]
Common abbreviation for mstrings of arbitrary length
x_opaque_max [Netxdr]
Common abbreviation for opaque data of arbitrary length
x_optional [Netxdr]
Common abbreviation for optional types.
x_string_max [Netxdr]
Common abbreviation for strings of arbitrary length
xdr_ctx [Rpc_server]
Get the recommended XDR context
xdr_ctx [Rpc_client.USE_CLIENT]
Returns the recommended XDR context
xdr_ctx [Rpc_client]
Returns the recommended XDR context
xdr_of_pseudo_value [Rpc_packer]
xdr_type_term [Netxdr]
xdr_type_term_system [Netxdr]
xdrt_PMAP'V2'pmapproc_callit'arg [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_callit'res [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_dump'arg [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_dump'res [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_getport'arg [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_getport'res [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_null'arg [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_null'res [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_set'arg [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_set'res [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_unset'arg [Rpc_portmapper_aux]
xdrt_PMAP'V2'pmapproc_unset'res [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_callit'arg [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_callit'res [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_dump'arg [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_dump'res [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_getaddr'res [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_gettime'arg [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_gettime'res [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_null'arg [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_null'res [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_set'arg [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_set'res [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_unset'arg [Rpc_portmapper_aux]
xdrt_PMAP'V3'rpcbproc_unset'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_bcast'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_bcast'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_dump'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_dump'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_getaddr'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_getaddrlist'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_getaddrlist'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_getstat'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_getstat'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_gettime'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_gettime'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_getversaddr'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_getversaddr'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_indirect'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_indirect'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_null'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_null'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_set'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_set'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_unset'arg [Rpc_portmapper_aux]
xdrt_PMAP'V4'rpcbproc_unset'res [Rpc_portmapper_aux]
xdrt_call_args [Rpc_portmapper_aux]
xdrt_call_result [Rpc_portmapper_aux]
xdrt_mapping [Rpc_portmapper_aux]
xdrt_netbuf [Rpc_portmapper_aux]
xdrt_pmaplist [Rpc_portmapper_aux]
xdrt_pmaplist_p [Rpc_portmapper_aux]
xdrt_rp__list [Rpc_portmapper_aux]
xdrt_rpcb [Rpc_portmapper_aux]
xdrt_rpcb_entry [Rpc_portmapper_aux]
xdrt_rpcb_entry_list [Rpc_portmapper_aux]
xdrt_rpcb_entry_list_ptr [Rpc_portmapper_aux]
xdrt_rpcb_rmtcallargs [Rpc_portmapper_aux]
xdrt_rpcb_rmtcallres [Rpc_portmapper_aux]
xdrt_rpcb_stat [Rpc_portmapper_aux]
xdrt_rpcb_stat_byvers [Rpc_portmapper_aux]
xdrt_rpcblist_ptr [Rpc_portmapper_aux]
xdrt_rpcbs_addrlist [Rpc_portmapper_aux]
xdrt_rpcbs_addrlist_ptr [Rpc_portmapper_aux]
xdrt_rpcbs_proc [Rpc_portmapper_aux]
xdrt_rpcbs_rmtcalllist [Rpc_portmapper_aux]
xdrt_rpcbs_rmtcalllist_ptr [Rpc_portmapper_aux]
xdrt_uaddr [Rpc_portmapper_aux]
xmap_list [Nethtml]
xmap_list f surrounding_element_opt doclst: Similar to map_list, the function f is applied to all attribute values and data strings.
xor_s [Netauth]
Performs the bitwise XOR of these strings (which must have the same length)
xv_false [Netxdr]
See x_bool
xv_none [Netxdr]
xv_some [Netxdr]
See x_optional
xv_true [Netxdr]

Y
year_day [Netdate]
Returns the year day (range 0 to 365)

Z
zero_pages [Netsys_mem]
zero_pages m pos len: If possible, the memory pages in the range pos to pos+len-1 of m are allocated again, so that they replace the previous pages.
ocamlnet-4.1.2/doc/html-main/Netasn1_encode.html0000644000175000017500000004407612731530353020130 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netasn1_encode

Module Netasn1_encode

module Netasn1_encode: sig .. end
ASN.1 encoder


Note that the encoder does not check whether the value is well-formed, in particular whether the constrained string values are correct.
val encode_ber : Netbuffer.t -> Netasn1.Value.value -> Netasn1.Value.pc
Appends a BER encoding of the value to the buffer (including the header). Returns whether a primitive or constructed encoding was generated.
val encode_ber_contents : Netbuffer.t -> Netasn1.Value.value -> Netasn1.Value.pc
Appends a BER encoding of the value to the buffer (excluding the header). Returns whether a primitive or constructed encoding was generated.
ocamlnet-4.1.2/doc/html-main/Uq_engines.epsilon_engine-c.html0000644000175000017500000004376712731530353022622 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.epsilon_engine

Class Uq_engines.epsilon_engine

class ['t] epsilon_engine : 't engine_state -> Unixqueue.event_system -> ['t] engine
This engine transitions from its initial state `Working 0 in one step ("epsilon time") to the passed constant state. During this time event processing will continue, so concurrently running engines can make progress. For performance reasons, however, external resources like file descriptors are not watched for new events.

In previous versions of this library the class was called const_engine. However, this is not a constant thing. In particular, it is possible that this engine is aborted, so the passed state is not reached. To avoid programming errors because of the misnomer, this class has been renamed.


ocamlnet-4.1.2/doc/html-main/Netcamlbox.Debug.html0000644000175000017500000004155512731530353020422 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcamlbox.Debug

Module Netcamlbox.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.full_info.html0000644000175000017500000004337112731530353023332 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.full_info object
  method cgi_properties : (string * string) list
  method input_body_size : int64
  method input_header : Nethttp.http_header
  method output_body_size : int64
  method output_header : Nethttp.http_header
  method remote_socket_addr : Unix.sockaddr
  method request_body_rejected : bool
  method request_method : string
  method request_uri : string
  method response_status_code : int
  method server_socket_addr : Unix.sockaddr
  method tls_session_props : Nettls_support.tls_session_props option
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_plex.html0000644000175000017500000007043412731530353021162 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_plex sig
  type config_log_error = Nethttpd_types.request_info -> string -> unit
  type config_log_access = Nethttpd_types.full_info -> unit
  type config_error_response = Nethttpd_types.error_response_params -> string
  val std_log_error :
    Netplex_types.container -> Nethttpd_plex.config_log_error
  val std_log_access :
    ?debug:bool -> Netplex_types.container -> Nethttpd_plex.config_log_access
  val std_error_response : Nethttpd_plex.config_error_response
  val restrict_file_service_config :
    Netplex_types.config_file -> Netplex_types.address -> unit
  val read_file_service_config :
    Netplex_types.config_file ->
    Netplex_types.address -> string -> Nethttpd_services.file_service
  val restrict_dynamic_service_config :
    Netplex_types.config_file -> Netplex_types.address -> unit
  val read_dynamic_service_config :
    (string *
     (Netplex_types.config_file ->
      Netplex_types.address ->
      string ->
      (#Netcgi.cgi_activation as 'a) Nethttpd_services.dynamic_service))
    list ->
    Netplex_types.config_file ->
    Netplex_types.address -> string -> 'Nethttpd_services.dynamic_service
  type encap = [ `Engine | `Reactor ]
  val nethttpd_processor :
    ?hooks:Netplex_types.processor_hooks ->
    ?encap:Nethttpd_plex.encap ->
    (Netplex_types.container -> #Nethttpd_reactor.http_reactor_config) ->
    'Nethttpd_types.http_service -> Netplex_types.processor
  type ('a, 'b) service_factory =
      (string * 'Nethttpd_services.dynamic_service) list ->
      Netplex_types.config_file ->
      Netplex_types.address -> string -> 'Nethttpd_types.http_service
    constraint 'a = #Netcgi.cgi_activation
    constraint 'b =
      [ `Dynamic_service of 'Nethttpd_services.dynamic_service
      | `File_service of Nethttpd_services.file_service ]
  val default_services :
    (string *
     (#Netcgi.cgi_activation as 'a,
      [ `Dynamic_service of 'Nethttpd_services.dynamic_service
      | `File_service of Nethttpd_services.file_service ])
     Nethttpd_plex.service_factory)
    list
  type httpd_factory = {
    httpd_factory :
      'a.
        (Netplex_types.container -> Nethttpd_reactor.http_reactor_config) ->
        'Nethttpd_types.http_service -> Netplex_types.processor;
  }
  val nethttpd_factory :
    ?name:string ->
    ?hooks:Netplex_types.processor_hooks ->
    ?encap:Nethttpd_plex.encap ->
    ?config_cgi:Netcgi.config ->
    ?handlers:(string *
               (#Netcgi.cgi_activation as 'a)
               Nethttpd_services.dynamic_service)
              list ->
    ?services:(string *
               ('a,
                [ `Dynamic_service of 'Nethttpd_services.dynamic_service
                | `File_service of Nethttpd_services.file_service ])
               Nethttpd_plex.service_factory)
              list ->
    ?log_error:(Netplex_types.container -> Nethttpd_plex.config_log_error) ->
    ?log_access:(?debug:bool ->
                 Netplex_types.container -> Nethttpd_plex.config_log_access) ->
    ?error_response:Nethttpd_plex.config_error_response ->
    ?processor_factory:Nethttpd_plex.httpd_factory ->
    ?tls:(module Netsys_crypto_types.TLS_PROVIDER->
    unit -> Netplex_types.processor_factory
end
ocamlnet-4.1.2/doc/html-main/Netsys_sasl.Server.html0000644000175000017500000006507612731530353021061 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl.Server

Module Netsys_sasl.Server

module Server: sig .. end

type session 
type 'credentials init_credentials = (string * string * (string * string) list) list -> 'credentials 
A function for preparing credentials, provided by the mechanism. The credentials are given as list (type,value,params). The mechanism may pick any element of this list which are considered as equivalent.

Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g.

          [ "password", "ThE sEcReT", [] ]
        

type lookup = {
   lookup : 'c.
Netsys_sasl.sasl_mechanism ->
'c init_credentials -> string -> string -> 'c option
;
}
see create_session
val create_session : mech:Netsys_sasl.sasl_mechanism ->
lookup:lookup ->
params:(string * string * bool) list -> unit -> session
Create a new server session. The lookup function is used to get the credentials for a given user name and a given authorization name (which is the empty string if not applicable). If the lookup function returns None, the user can either not be found, or the user does not have the privileges for the authorization name.

lookup is called as lookup.lookup mech init_creds user authz. You need to call init_creds back in order to prepare the credentials, e.g.

  let f_lookup : 'c . sasl_mechanism -> 'c init_credentials -> string ->
                string -> 'c option =
    fun mech init_creds user authz =
      try
        let password = ... in
        let creds = init_creds [ ("password", password, []) ] in
        Some creds
      with Not_found -> None

  let lookup = {lookup = f_lookup }
          

User name and authorization name are passed in UTF-8 encoding.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val process_response : session -> string -> session
Process the response from the client. This function must generally only be called when the session state is `Wait. As an exception, however, this function may also be invoked with the initial client response, even if the session state is `Emit, so far the mechanism permits at least optionally that the client starts the protocol.
val process_response_restart : session ->
string -> bool -> session * bool
Process the response from the client when another session can be continued. The string argument is the initial client response. This function must only be called when the state reaches `Restart id after process_response, and in this case the old session with id can be restarted. This function should be called with the same message string as process_repsonse was just called with.

If the bool arg is true, a stale response is created. This is a special restart which forces the client to run through the authentication process again, although everything else was successful. (If the protocol does not support the stale flag, it is silently ignored.)

Returns true if the restart is successful. If not, false is returned. In this case, the session object can (and should) still be used, but the caller must treat it as new session. In particular, the session ID may change.

All in all, the idea of this function is best illustrated by this authentication snippet how to process responses (the session cache functions need to be written by the user of this module):

let update_cache() =
  match session_id session with
    | None -> ()
    | Some id ->
        replace_in_session_cache id (stash_session session) in

let rec check_state_after_response() =
  match state session with
    | `Restart id ->
         let old_session_s, time = find_in_session_cache id in
         let old_session = resume_session ~lookup old_session_s in
         let set_stale = current_time - time > limit in
         let cont = process_response_restart session msg set_stale in
         if not cont then 
           delete_in_session_cache id;
         (* Now check state again, should be `Emit now *)
         check_state_after_response()
    | `Emit ->
         let out_msg = emit_challenge session in
         update_cache();
         ...
    | ... ->
in
process_response session msg;

        

val emit_challenge : session -> session * string
Emit a server challenge. This function must only be called when the session state is `Emit.
val stash_session : session -> string
Serializes the session as string
val resume_session : mech:Netsys_sasl.sasl_mechanism ->
lookup:lookup -> string -> session
Unserializes the session, and connect with the lookup function.
val session_id : session -> string option
Optionally return a string that can be used to identify the server session. Not all mechanisms support this.
val prop : session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "digest-uri" sent by the client.
val gssapi_props : session -> Netsys_gssapi.server_props
Get the GSSAPI props, or raise Not_found
val user_name : session -> string
The name the client has authenticated as (or Not_found)
val authz_name : session -> string
The name the client authorizes as (or Not_found)
val channel_binding : session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
ocamlnet-4.1.2/doc/html-main/Netplex_types.workload_manager-c.html0000644000175000017500000004633112731530353023674 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.workload_manager

Class type Netplex_types.workload_manager

class type workload_manager = object .. end
See Netplex_workload for definitions of workload managers

method hello : controller -> unit
Called by the controller when the service is added
method shutdown : unit -> unit
Called by the controller to notify the manager about a shutdown
method adjust : socket_service -> socket_controller -> unit
This function is called by the controller at certain events to adjust the number of available containers. The manager can call start_containers and stop_containers to change the system.

The function is called right after the startup to ensure that there are containers to serve requests. It is also called:

  • just after a connection has been accepted and before it is decided which container will have the chance to accept in the round
  • after the shutdown of a container
Of course, the workload manager is free to adjust the load at any other time, too, not only when adjust is called.
method capacity : container_id ->
container_state -> capacity
Computes the capacity, i.e. the number of jobs a certain container can accept in addition to the existing load.
ocamlnet-4.1.2/doc/html-main/Netplex_mbox.Make_mbox_type.html0000644000175000017500000004567112731530353022712 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mbox.Make_mbox_type

Functor Netplex_mbox.Make_mbox_type

module Make_mbox_type: 
functor (T : Netplex_cenv.TYPE) -> MBOX with type t = T.t
Create a new mailbox access module for message type T.t
Parameters:
T : Netplex_cenv.TYPE

type t 
The type of messages
type mbox 
The type of the mailboxes
val create : string -> mbox
Creates a new mailbox with the passed name, or opens an existing mailbox. Names are global to the whole Netplex process system.
val send : mbox -> t -> unit
Send a message to this box. If the box is full, it is waited until the box is free again. If several senders wait for the box, one sender is selected.
val receive : mbox -> t
Receive a message: It is waited until a sender puts a message into the box. If several receivers wait for the box, one receiver is selected.
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.http_service_receiver.html0000644000175000017500000004133612731530353025737 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.http_service_receiver object
  method process_body :
    Nethttpd_types.extended_environment ->
    Nethttpd_types.http_service_generator
end
ocamlnet-4.1.2/doc/html-main/type_Netgss_bindings.html0000644000175000017500000011540412731530353021455 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgss_bindings sig
  type gss_buffer_t
  type gss_OID
  type gss_OID_set
  type gss_cred_id_t
  type gss_ctx_id_t
  type gss_name_t
  type gss_channel_bindings_t
  type gss_cred_usage_t = [ `Accept | `Both | `Initiate ]
  type flags_flag =
      [ `Anon_flag
      | `Conf_flag
      | `Deleg_flag
      | `Integ_flag
      | `Mutual_flag
      | `Prot_ready_flag
      | `Replay_flag
      | `Sequence_flag
      | `Trans_flag ]
  type flags = Netgss_bindings.flags_flag list
  type gss_qop_t = [ `Qop_default ]
  type status_type_t = [ `Gss_code | `Mech_code ]
  val gss_accept_sec_context :
    Netgss_bindings.gss_ctx_id_t ->
    Netgss_bindings.gss_cred_id_t ->
    Netgss_bindings.gss_buffer_t ->
    Netgss_bindings.gss_channel_bindings_t ->
    int32 * int32 * Netgss_bindings.gss_ctx_id_t *
    Netgss_bindings.gss_name_t * Netgss_bindings.gss_OID *
    Netgss_bindings.gss_buffer_t * Netgss_bindings.flags * int32 *
    Netgss_bindings.gss_cred_id_t
  val gss_acquire_cred :
    Netgss_bindings.gss_name_t ->
    int32 ->
    Netgss_bindings.gss_OID_set ->
    Netgss_bindings.gss_cred_usage_t ->
    int32 * int32 * Netgss_bindings.gss_cred_id_t *
    Netgss_bindings.gss_OID_set * int32
  val gss_init_sec_context :
    Netgss_bindings.gss_cred_id_t ->
    Netgss_bindings.gss_ctx_id_t ->
    Netgss_bindings.gss_name_t ->
    Netgss_bindings.gss_OID ->
    Netgss_bindings.flags ->
    int32 ->
    Netgss_bindings.gss_channel_bindings_t ->
    Netgss_bindings.gss_buffer_t ->
    int32 * int32 * Netgss_bindings.gss_ctx_id_t * Netgss_bindings.gss_OID *
    Netgss_bindings.gss_buffer_t * Netgss_bindings.flags * int32
  val gss_process_context_token :
    Netgss_bindings.gss_ctx_id_t ->
    Netgss_bindings.gss_buffer_t -> int32 * int32
  val gss_context_time :
    Netgss_bindings.gss_ctx_id_t -> int32 * int32 * int32
  val gss_get_mic :
    Netgss_bindings.gss_ctx_id_t ->
    int32 ->
    Netgss_bindings.gss_buffer_t ->
    int32 * int32 * Netgss_bindings.gss_buffer_t
  val gss_verify_mic :
    Netgss_bindings.gss_ctx_id_t ->
    Netgss_bindings.gss_buffer_t ->
    Netgss_bindings.gss_buffer_t -> int32 * int32 * int32
  val gss_wrap :
    Netgss_bindings.gss_ctx_id_t ->
    bool ->
    int32 ->
    Netgss_bindings.gss_buffer_t ->
    int32 * int32 * bool * Netgss_bindings.gss_buffer_t
  val gss_unwrap :
    Netgss_bindings.gss_ctx_id_t ->
    Netgss_bindings.gss_buffer_t ->
    int32 * int32 * Netgss_bindings.gss_buffer_t * bool * int32
  val gss_display_status :
    int32 ->
    Netgss_bindings.status_type_t ->
    Netgss_bindings.gss_OID ->
    int32 -> int32 * int32 * int32 * Netgss_bindings.gss_buffer_t
  val gss_indicate_mechs :
    unit -> int32 * int32 * Netgss_bindings.gss_OID_set
  val gss_compare_name :
    Netgss_bindings.gss_name_t ->
    Netgss_bindings.gss_name_t -> int32 * int32 * bool
  val gss_display_name :
    Netgss_bindings.gss_name_t ->
    int32 * int32 * Netgss_bindings.gss_buffer_t * Netgss_bindings.gss_OID
  val gss_import_name :
    Netgss_bindings.gss_buffer_t ->
    Netgss_bindings.gss_OID -> int32 * int32 * Netgss_bindings.gss_name_t
  val gss_inquire_cred :
    Netgss_bindings.gss_cred_id_t ->
    int32 * int32 * Netgss_bindings.gss_name_t * int32 *
    Netgss_bindings.gss_cred_usage_t * Netgss_bindings.gss_OID_set
  val gss_inquire_context :
    Netgss_bindings.gss_ctx_id_t ->
    int32 * int32 * Netgss_bindings.gss_name_t * Netgss_bindings.gss_name_t *
    int32 * Netgss_bindings.gss_OID * Netgss_bindings.flags * bool * 
    bool
  val gss_wrap_size_limit :
    Netgss_bindings.gss_ctx_id_t ->
    bool -> int32 -> int32 -> int32 * int32 * int32
  val gss_add_cred :
    Netgss_bindings.gss_cred_id_t ->
    Netgss_bindings.gss_name_t ->
    Netgss_bindings.gss_OID ->
    Netgss_bindings.gss_cred_usage_t ->
    int32 ->
    int32 ->
    int32 * int32 * Netgss_bindings.gss_cred_id_t *
    Netgss_bindings.gss_OID_set * int32 * int32
  val gss_inquire_cred_by_mech :
    Netgss_bindings.gss_cred_id_t ->
    Netgss_bindings.gss_OID ->
    int32 * int32 * Netgss_bindings.gss_name_t * int32 * int32 *
    Netgss_bindings.gss_cred_usage_t
  val gss_export_sec_context :
    Netgss_bindings.gss_ctx_id_t ->
    int32 * int32 * Netgss_bindings.gss_buffer_t
  val gss_import_sec_context :
    Netgss_bindings.gss_buffer_t ->
    int32 * int32 * Netgss_bindings.gss_ctx_id_t
  val gss_inquire_names_for_mech :
    Netgss_bindings.gss_OID -> int32 * int32 * Netgss_bindings.gss_OID_set
  val gss_inquire_mechs_for_name :
    Netgss_bindings.gss_name_t -> int32 * int32 * Netgss_bindings.gss_OID_set
  val gss_export_name :
    Netgss_bindings.gss_name_t ->
    int32 * int32 * Netgss_bindings.gss_buffer_t
  val gss_duplicate_name :
    Netgss_bindings.gss_name_t -> int32 * int32 * Netgss_bindings.gss_name_t
  val gss_canonicalize_name :
    Netgss_bindings.gss_name_t ->
    Netgss_bindings.gss_OID -> int32 * int32 * Netgss_bindings.gss_name_t
  val gss_delete_sec_context : Netgss_bindings.gss_ctx_id_t -> int32 * int32
  exception Null_pointer
  type memory =
      (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
  val buffer_of_string : string -> int -> int -> Netgss_bindings.gss_buffer_t
  val buffer_of_bytes : Bytes.t -> int -> int -> Netgss_bindings.gss_buffer_t
  val buffer_of_memory :
    Netgss_bindings.memory -> Netgss_bindings.gss_buffer_t
  val string_of_buffer : Netgss_bindings.gss_buffer_t -> string
  val bytes_of_buffer : Netgss_bindings.gss_buffer_t -> Bytes.t
  val memory_of_buffer :
    Netgss_bindings.gss_buffer_t -> Netgss_bindings.memory
  val release_buffer : Netgss_bindings.gss_buffer_t -> unit
  val oid_of_der : string -> Netgss_bindings.gss_OID
  val der_of_oid : Netgss_bindings.gss_OID -> string
  val array_of_oid_set :
    Netgss_bindings.gss_OID_set -> Netgss_bindings.gss_OID array
  val oid_set_of_array :
    Netgss_bindings.gss_OID array -> Netgss_bindings.gss_OID_set
  val map_cb :
    int ->
    string ->
    int -> string -> string -> Netgss_bindings.gss_channel_bindings_t
  val no_channel_bindings : unit -> Netgss_bindings.gss_channel_bindings_t
  val no_context : unit -> Netgss_bindings.gss_ctx_id_t
  val is_no_context : Netgss_bindings.gss_ctx_id_t -> bool
  val no_credential : unit -> Netgss_bindings.gss_cred_id_t
  val is_no_credential : Netgss_bindings.gss_cred_id_t -> bool
  val no_name : unit -> Netgss_bindings.gss_name_t
  val is_no_name : Netgss_bindings.gss_name_t -> bool
  val no_oid : unit -> Netgss_bindings.gss_OID
  val no_oid_set : unit -> Netgss_bindings.gss_OID_set
  val gss_indefinite : unit -> int32
end
ocamlnet-4.1.2/doc/html-main/Netxdr.html0000644000175000017500000020670412731530353016544 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netxdr

Module Netxdr

module Netxdr: sig .. end
External Data Representation


This module supports the "external data representation", or XDR for short. XDR is a means to pack structured values as strings and it serves to transport such values across character streams even between computers with different architectures.

XDR values must be formed according to an XDR type. Such types are usually written in a notation that is close to the C notation of structured types. There are some important details where XDR is better than C:

  • direct support for strings
  • arrays may have fixed or variable length
  • unions must have a discriminator
  • no pointers. The notation *t is allowed, but means something different, namely "t option" in O'Caml notation.
  • recursive types are possible and behave like recursive types in O'Caml. For example,
         struct *list {
           int value;
           next list;
         }
       
    is a list of integer values and equivalent to
         type intlist = intlist_el option
          and intlist_el = { value : int; next : intlist }
       
See RFC 1014 for details about XDR.

This module defines:

  • XDR types
  • XDR type terms
  • XDR type systems
  • XDR type term systems
In "type terms" you can see the components from which the type has been formed, while a "type" is an opaque representation that has been checked and for that some preprocessing has been done.

A "type system" is a collection of several types that have names and that can refer to previously defined types (i.e. a sequence of "typedef"s). As with simple types, there is an extensive and an opaque representation.

A typical way of using this module is to define an "XDR type term system" by simply writing an O'Caml expression. After that, this system is validated and you get the "type system". From now on, you can refer to the types defined in the system by name and get the corresponding "XDR types". Once you have an XDR type you can use it to pack or unpack an XDR value.

Values possible for XDR types. This is straight-forward, except the "_fast" variants:

type xdr_value = 
| XV_int of Netnumber.int4
| XV_uint of Netnumber.uint4
| XV_hyper of Netnumber.int8
| XV_uhyper of Netnumber.uint8
| XV_enum of string
| XV_float of Netnumber.fp4
| XV_double of Netnumber.fp8
| XV_opaque of string
| XV_string of string
| XV_array of xdr_value array
| XV_struct of (string * xdr_value) list
| XV_union_over_int of (Netnumber.int4 * xdr_value)
| XV_union_over_uint of (Netnumber.uint4 * xdr_value)
| XV_union_over_enum of (string * xdr_value)
| XV_void
| XV_enum_fast of int (*
The integer is the _position_ in the X_enum list, sorted by enum values (ascending). For example, if we have X_enum [ "A", 4; "B", 2; "C", 6 ] the element "B" has the position 0, because 2 is the lowest number
*)
| XV_struct_fast of xdr_value array (*
The array elements are in the same order as declared in X_struct
*)
| XV_union_over_enum_fast of (int * xdr_value) (*
The integer is the _position_ in the X_enum list. "position" means the same as for XV_enum_fast
*)
| XV_array_of_string_fast of string array (*
To be used with an X_array or X_array_fixed with an inner type of X_string
*)
| XV_mstring of Netxdr_mstring.mstring
| XV_direct of exn * int * (exn -> xdr_value)
val xv_true : xdr_value
val xv_false : xdr_value
See x_bool
val xv_none : xdr_value
val xv_some : xdr_value -> xdr_value
See x_optional

Terms that describe possible XDR types:

  • X_int: integer (32 bit)
  • X_uint: unsigned integer
  • X_hyper: hyper (64 bit signed integer)
  • X_uhyper: unsigned hyper
  • X_enum [x1,i1; ...]: enum { x1 = i1, ... }
  • X_float: float (32 bit fp number)
  • X_double: double (64 bit fp number)
  • X_opaque_fixed n: opaque[n]
  • X_opaque n: opaque<n>
  • X_string n: string<n>
  • X_mstring(name,n): _managed string<n> (see below)
  • X_array_fixed (t,n): t[n]
  • X_array (t,n): t<n>
  • X_struct [x1,t1;...]: struct { t1 x1; ...}
  • X_union_over_int ([n1,t1;...], None): union switch(int) {case n1: t1; ...}
  • X_union_over_int ([n1,t1;...], Some t): union switch(int) {case n1: t1; ...; default t}
  • X_union_over_uint ([n1,t1;...], None): union switch(unsigned int) {case n1: t1; ...}
  • X_union_over_uint ([n1,t1;...], Some t): union switch(unsigned int) {case n1: t1; ...; default t}
  • X_union_over_enum (e, [n1,t1;...], None): union switch(e) {case n1:t1; ...} where e is an enumeration type
  • X_union_over_enum (e, [n1,t1;...], Some t): union switch(e) {case n1:t1; ...; default t} where e is an enumeration type
  • X_void: void
The X_type constructor is only useful for types interpreted relative to a type system. Then it refers to a named type in this system.

The X_param constructor includes a reference to an arbitrary type which must first be given when packing or unpacking values. (A "lazy" type reference.) Additionally, the values for parameters may be encrypted or decrypted.

Example how to define a recursive type:

X_rec ("a", X_array ( X_struct ["value", X_int; "next", X_refer "a"], 1))

Managed strings are represented as X_mstring(name,n). The name refers to the preferred factory for managed strings (needs to be passed to the XDR unpacker). Values for managed strings are objects of type Netxdr_mstring.mstring.

The term X_direct(t,read,write,size,expand) is generated by ocamlrpcgen at positions suitable for direct mapping. In this case, the XDR byte representation is directly mapped to the final Ocaml value bypassing the intermediate representation defined in this module. t is the mapped type. The function read is called as read s cursor len in order to map the XDR bytes at !cursor in s. The cursor must be advanced to the end position. len is the number of valid bytes in s (i.e. s.(len-1) is the last one). The result of read is an arbitrary exception which needs to be postprocessed by ocamlrpcgen-generated code. The function write is called as write x s cursor: The value encapsulated in exception x is written to string s at position cursor. Like for read the cursor is advanced by the number of written bytes. There must be enough space in s. The function size can be used to determine the number of written bytes beforehand.

type xdr_type_term = 
| X_int
| X_uint
| X_hyper
| X_uhyper
| X_enum of (string * Netnumber.int4) list
| X_float
| X_double
| X_opaque_fixed of Netnumber.uint4
| X_opaque of Netnumber.uint4
| X_string of Netnumber.uint4
| X_mstring of string * Netnumber.uint4
| X_array_fixed of xdr_type_term * Netnumber.uint4
| X_array of xdr_type_term * Netnumber.uint4
| X_struct of (string * xdr_type_term) list
| X_union_over_int of (Netnumber.int4 * xdr_type_term) list * xdr_type_term option
| X_union_over_uint of (Netnumber.uint4 * xdr_type_term) list * xdr_type_term option
| X_union_over_enum of xdr_type_term * (string * xdr_type_term) list
* xdr_type_term option
| X_void
| X_type of string
| X_param of string
| X_rec of (string * xdr_type_term)
| X_refer of string
| X_direct of xdr_type_term * (Bytes.t -> int Pervasives.ref -> int -> exn)
* (exn -> Bytes.t -> int Pervasives.ref -> unit) * (exn -> int)
* (exn -> xdr_value)
type xdr_type 
This is the validated version of xdr_type_term. Note that it does not contain X_type constructors, i.e. is completely expanded. It is allowed that an xdr_type contains X_param constructors (parameters). The set of occurring parameters can be determined very quickly for an xdr_type.
type xdr_type_term_system = (string * xdr_type_term) list 
Bind names to types. In a correct system you can only refer to previously defined types, i.e. the type called n must be defined in the list before it can be used via X_type n. It is possible to use this module without the means of type systems, but often code is more readable if types are defined in an environment allowing bindings to names.
type xdr_type_system 
A validated type system.
val x_bool : xdr_type_term
Common abbreviation for boolean types. Has values xv_true and xv_false.
val x_optional : xdr_type_term -> xdr_type_term
Common abbreviation for optional types. Has values xv_none and xv_some v.
val x_opaque_max : xdr_type_term
Common abbreviation for opaque data of arbitrary length
val x_string_max : xdr_type_term
Common abbreviation for strings of arbitrary length
val x_mstring_max : string -> xdr_type_term
Common abbreviation for mstrings of arbitrary length
val x_array_max : xdr_type_term -> xdr_type_term
Common abbreviation for arrays of arbitrary length
exception Dest_failure
raised if the dest_* function are applied to non-matching xdr_value
val dest_xv_int : xdr_value -> Netnumber.int4
val dest_xv_uint : xdr_value -> Netnumber.uint4
val dest_xv_hyper : xdr_value -> Netnumber.int8
val dest_xv_uhyper : xdr_value -> Netnumber.uint8
val dest_xv_enum : xdr_value -> string
val dest_xv_enum_fast : xdr_value -> int
val dest_xv_float : xdr_value -> Netnumber.fp4
val dest_xv_double : xdr_value -> Netnumber.fp8
val dest_xv_opaque : xdr_value -> string
val dest_xv_string : xdr_value -> string
val dest_xv_mstring : xdr_value -> Netxdr_mstring.mstring
val dest_xv_array : xdr_value -> xdr_value array
val dest_xv_array_of_string_fast : xdr_value -> string array
val dest_xv_struct : xdr_value -> (string * xdr_value) list
val dest_xv_struct_fast : xdr_value -> xdr_value array
val dest_xv_union_over_int : xdr_value -> Netnumber.int4 * xdr_value
val dest_xv_union_over_uint : xdr_value -> Netnumber.uint4 * xdr_value
val dest_xv_union_over_enum : xdr_value -> string * xdr_value
val dest_xv_union_over_enum_fast : xdr_value -> int * xdr_value
val dest_xv_void : xdr_value -> unit
val map_xv_enum_fast : xdr_type -> xdr_value -> int32
Works for both XV_enum and XV_enum_fast
val map_xv_struct_fast : xdr_type -> xdr_value -> xdr_value array
Works for both XV_struct and XV_struct_fast
val map_xv_union_over_enum_fast : xdr_type -> xdr_value -> int * int32 * xdr_value
Works for both XV_union_over_enum and XV_union_over_enum_fast. Returns the triple (k,i,x):
  • k: Position of the selected value in the T_enum array
  • i: value of the enum
  • x: selected arm of the union

exception Xdr_format of string
Format error found during unpacking a string
exception Xdr_format_message_too_long of xdr_value
The message is too long and cannot be packed into a string
exception Xdr_failure of string
Usually a problem during packing

You must use these two functions to obtain validated types and type systems. They fail with "validate_xdr_type" resp. "validate_xdr_type_system" if the parameters are incorrect.
val validate_xdr_type : xdr_type_term -> xdr_type
val validate_xdr_type_system : xdr_type_term_system -> xdr_type_system
val params : xdr_type -> string list
return the X_param parameters contained in the type

Get the unvalidated version back:

  • Note that X_type constructions are always resolved

val xdr_type_term : xdr_type -> xdr_type_term
val xdr_type_term_system : xdr_type_system -> xdr_type_term_system

You can expand any type term relative to a (validated) type system. For example: expanded_xdr_type sys1 (X_type "xy") extracts the type called "xy" defined in sys1. Expansion removes all X_type constructions in a type term.
val expanded_xdr_type : xdr_type_system -> xdr_type_term -> xdr_type
val expanded_xdr_type_term : xdr_type_term_system -> xdr_type_term -> xdr_type_term
val are_compatible : xdr_type -> xdr_type -> bool
are_compatible: currently not implemented
val value_matches_type : xdr_value ->
xdr_type -> (string * xdr_type) list -> bool
Is the value properly formed with respect to this type? The third argument of this function is a list of parameter instances. Note that all parameters must be instantiated to compare a value with a type and that the parameters instances are not allowed to have parameters themselves.

Encrypted parameters are not supported here.


Packing and unpacking



Packing and unpacking



pack_xdr_value v t p print: Serialize v into a string conforming to the XDR standard where v matches t. In p the parameter instances are given. All parameters must be given, and the parameters must not contain parameters themselves. The fourth argument, print, is a function which is evaluated for the pieces of the resultant string. You can use pack_xdr_value_as_string to get the whole string at once.

unpack_xdr_value s t p: Unserialize a string to a value matching t. If this operation fails you get an Xdr_format exception explaining what the reason for the failure is. Mostly the cause for failures is that t isn't the type of the value. Note that there are some implementation restrictions limiting the number of elements in array, strings and opaque fields. If you get such an error this normally still means that the value is not of the expected type, because these limits have no practical meaning (they are still higher than the usable address space).

Packing and unpacking



pack_xdr_value v t p print: Serialize v into a string conforming to the XDR standard where v matches t. In p the parameter instances are given. All parameters must be given, and the parameters must not contain parameters themselves. The fourth argument, print, is a function which is evaluated for the pieces of the resultant string. You can use pack_xdr_value_as_string to get the whole string at once.

unpack_xdr_value s t p: Unserialize a string to a value matching t. If this operation fails you get an Xdr_format exception explaining what the reason for the failure is. Mostly the cause for failures is that t isn't the type of the value. Note that there are some implementation restrictions limiting the number of elements in array, strings and opaque fields. If you get such an error this normally still means that the value is not of the expected type, because these limits have no practical meaning (they are still higher than the usable address space).

Encryption: The encode and decode functions can be used to encrypt/decrypt parameters (placeholders in the type marked with X_param pname for a parameter name pname). The encode argument may list for each parameter an encoding function:

 encode = [ pname1, encoder1; pname2, encoder2; ... ] 

The functions encoder are called with the XDR-packed parameter value, and return the encrypted value.

Likewise, the decode argument may list for each parameter a decoding function:

 decode = [ pname1, decoder1; pname2, decoder2; ... ] 

The call style of the decoder functions is a bit more complicated, though. They are called as

 let (xdr_s, n) = decoder s pos len 

meaning that the decoder starts decoding at position pos of string s, and that at most len bytes can be decoded. It returns the decoded string xdr_s (which is then unpacked), and in n the number of consumed input bytes is returned.

Exceptions raised in encoders or decoders fall through unmodified.

type encoder = Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list 
see text above
type decoder = Bytes.t -> int -> int -> Bytes.t * int 
see text above
val pack_xdr_value : ?encode:(string * encoder) list ->
xdr_value ->
xdr_type ->
(string * xdr_type) list -> (Bytes.t -> unit) -> unit
val pack_xdr_value_as_bytes : ?rm:bool ->
?encode:(string * encoder) list ->
xdr_value ->
xdr_type -> (string * xdr_type) list -> Bytes.t
val pack_xdr_value_as_string : ?rm:bool ->
?encode:(string * encoder) list ->
xdr_value ->
xdr_type -> (string * xdr_type) list -> string
rm: If true, four null bytes are prepended to the string for the record mark

Changed in Ocamlnet-3.3: these functions raise Xdr_failure in case of errors.

val pack_xdr_value_as_mstrings : ?rm:bool ->
?encode:(string * encoder) list ->
xdr_value ->
xdr_type ->
(string * xdr_type) list -> Netxdr_mstring.mstring list
The concatanated mstrings are the packed representation

Changed in Ocamlnet-3.3: this function raises Xdr_failure in case of errors.

type xdr_value_version = [ `Ocamlrpcgen | `V1 | `V2 | `V3 | `V4 ] 
Selects which version of xdr_value is returned by unpack_xdr_value. During the development of Ocamlnet several incompatible changes were made, but by selecting a certain version these changes can be hidden from the caller.

  • `V1: This version refers to the original xdr_value definition, which only included XV_int, XV_uint, XV_hyper, XV_uhyper, XV_enum, XV_float, XV_double, XV_opaque, XV_string, XV_array, XV_struct, XV_union_over_int, XV_union_over_uint, XV_union_over_enum, and XV_void.
  • `V2: This version is available since the rpc-0.4 distribution, and added the tags XV_enum_fast, XV_struct_fast, and XV_union_over_enum_fast.
  • `V3: In Ocamlnet-3.0 the tag XV_array_of_string_fast was added.
  • `V4: In Ocamlnet-3.5 the tag XV_direct was added.
  • `Ocamlrpcgen: This refers to the version that must be used if the returned xdr_value is processed by code generated with ocamlrpcgen.
The default is still `V1, for ultimate backward compatibility. The switch fast=true selects `Ocamlrpcgen (it was always used for this purpose, despite its name).
val unpack_xdr_value : ?pos:int ->
?len:int ->
?fast:bool ->
?prefix:bool ->
?mstring_factories:Netxdr_mstring.named_mstring_factories ->
?xv_version:xdr_value_version ->
?decode:(string * decoder) list ->
Bytes.t ->
xdr_type -> (string * xdr_type) list -> xdr_value
val unpack_xdr_value_l : ?pos:int ->
?len:int ->
?fast:bool ->
?prefix:bool ->
?mstring_factories:Netxdr_mstring.named_mstring_factories ->
?xv_version:xdr_value_version ->
?decode:(string * decoder) list ->
Bytes.t ->
xdr_type -> (string * xdr_type) list -> xdr_value * int
prefix: whether it is ok that the string is longer than the message (default: false)

mstring_factories: when a T_mstring(name,_) type is found, the factory is looked up in this hash table under name, and if this fails under the name "*". If there is no such factory, unpacking fails! (Default: empty table.)

xv_version: Selects a certain version of the returned xdr_value terms. See Netxdr.xdr_value_version for details. Set this to `Ocamlrpcgen if you decode the xdr_value with ocamlrpcgen-generated decoders.

fast: Setting this to true is a deprecated way to set xv_version=`Ocamlrpcgen.

The variant unpack_xdr_value_l returns not only the decoded value, but also the actual length in bytes.

The exceptions Xdr_format and Xdr_format_message_too_long may be raised.

val unpack_xdr_value_str : ?pos:int ->
?len:int ->
?fast:bool ->
?prefix:bool ->
?mstring_factories:Netxdr_mstring.named_mstring_factories ->
?xv_version:xdr_value_version ->
?decode:(string * decoder) list ->
string ->
xdr_type -> (string * xdr_type) list -> xdr_value * int
Same for strings
ocamlnet-4.1.2/doc/html-main/type_Nethttp_fs.html0000644000175000017500000007151312731530353020455 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_fs sig
  type read_flag =
      [ `Binary
      | `Dummy
      | `Header of (string * string) list
      | `Skip of int64
      | `Streaming ]
  type read_file_flag =
      [ `Binary | `Dummy | `Header of (string * string) list ]
  type write_flag =
      [ `Binary
      | `Create
      | `Dummy
      | `Exclusive
      | `Header of (string * string) list
      | `Streaming
      | `Truncate ]
  type write_file_flag =
      [ `Binary
      | `Create
      | `Dummy
      | `Exclusive
      | `Header of (string * string) list
      | `Link
      | `Truncate ]
  class type http_stream_fs =
    object
      method cancel : unit -> unit
      method copy : Netfs.copy_flag list -> string -> string -> unit
      method last_response_header : Nethttp.http_header
      method last_response_status : Nethttp.http_status * int * string
      method mkdir : Netfs.mkdir_flag list -> string -> unit
      method nominal_dot_dot : bool
      method path_encoding : Netconversion.encoding option
      method path_exclusions : (int * int) list
      method pipeline : Nethttp_client.pipeline
      method read :
        Nethttp_fs.read_flag list -> string -> Netchannels.in_obj_channel
      method read_file :
        Nethttp_fs.read_file_flag list -> string -> Netfs.local_file
      method readdir : Netfs.readdir_flag list -> string -> string list
      method readlink : Netfs.readlink_flag list -> string -> string
      method remove : Netfs.remove_flag list -> string -> unit
      method rename : Netfs.rename_flag list -> string -> string -> unit
      method rmdir : Netfs.rmdir_flag list -> string -> unit
      method size : Netfs.size_flag list -> string -> int64
      method symlink : Netfs.symlink_flag list -> string -> string -> unit
      method test : Netfs.test_flag list -> string -> Netfs.test_type -> bool
      method test_list :
        Netfs.test_flag list -> string -> Netfs.test_type list -> bool list
      method translate : string -> string
      method write :
        Nethttp_fs.write_flag list -> string -> Netchannels.out_obj_channel
      method write_file :
        Nethttp_fs.write_file_flag list -> string -> Netfs.local_file -> unit
    end
  class http_fs :
    ?config_pipeline:(Nethttp_client.pipeline -> unit) ->
    ?streaming:bool ->
    ?tmp_directory:string ->
    ?tmp_prefix:string ->
    ?path_encoding:Netconversion.encoding ->
    ?enable_read_for_directories:bool ->
    ?enable_ftp:bool -> string -> http_stream_fs
  val http_fs :
    ?config_pipeline:(Nethttp_client.pipeline -> unit) ->
    ?streaming:bool ->
    ?tmp_directory:string ->
    ?tmp_prefix:string ->
    ?path_encoding:Netconversion.encoding ->
    ?enable_read_for_directories:bool ->
    ?enable_ftp:bool -> string -> Nethttp_fs.http_stream_fs
  val find_flag : ('-> 'b option) -> 'a list -> 'b
end
ocamlnet-4.1.2/doc/html-main/Neturl_ldap.html0000644000175000017500000004723112731530353017547 0ustar gerdgerd Ocamlnet 4 Reference Manual : Neturl_ldap

Module Neturl_ldap

module Neturl_ldap: sig .. end
LDAP-specific URLs


This is an extension of Neturl for LDAP. Note that you can simply use Neturl.parse_url to parse LDAP URLs. Find useful accessor functions below to get LDAP-specific parts.
val ldap_url_dn : ?encoded:bool -> Neturl.url -> string
val ldap_url_attributes : ?encoded:bool -> Neturl.url -> string list
val ldap_url_scope : Neturl.url -> [ `Base | `One | `Sub ]
val ldap_url_filter : ?encoded:bool -> Neturl.url -> string
val ldap_url_extensions : ?encoded:bool -> Neturl.url -> (bool * string * string option) list
Return components of the URL. The functions return decoded strings unless encoded:true is set. If the component does not exist, the exception Not_found is raised. If the component cannot be parsed, Malformed_URL is raised.
val ldap_url_provides : ?dn:bool ->
?attributes:bool ->
?scope:bool -> ?filter:bool -> ?extensions:bool -> Neturl.url -> bool
Whether all the selected URL components are present and the accessor can return them (even if empty)
val make_ldap_url : ?encoded:bool ->
?host:string ->
?addr:Unix.inet_addr ->
?port:int ->
?socksymbol:Netsockaddr.socksymbol ->
?dn:string ->
?attributes:string list ->
?scope:[ `Base | `One | `Sub ] ->
?filter:string ->
?extensions:(bool * string * string option) list -> unit -> Neturl.url
Create an LDAP URL
ocamlnet-4.1.2/doc/html-main/type_Netmcore_buffer.html0000644000175000017500000006021612731530353021442 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_buffer sig
  type 'h buffer
  type 'h buffer_descr
  val create : Netmcore.res_id -> int -> '-> 'Netmcore_buffer.buffer
  val destroy : 'Netmcore_buffer.buffer -> unit
  val start : 'Netmcore_buffer.buffer -> int
  val length : 'Netmcore_buffer.buffer -> int
  val contents : 'Netmcore_buffer.buffer -> string
  val sub : 'Netmcore_buffer.buffer -> int -> int -> string
  val blit_to_bytes :
    'Netmcore_buffer.buffer -> int -> Bytes.t -> int -> int -> unit
  val blit_to_string :
    'Netmcore_buffer.buffer -> int -> Bytes.t -> int -> int -> unit
  val blit_to_memory :
    'Netmcore_buffer.buffer ->
    int -> Netsys_mem.memory -> int -> int -> unit
  val access :
    'Netmcore_buffer.buffer -> int -> (Bytes.t -> int -> int -> 'a) -> 'a
  val add_string : 'Netmcore_buffer.buffer -> string -> unit
  val add_substring :
    'Netmcore_buffer.buffer -> string -> int -> int -> unit
  val add_sub_string :
    'Netmcore_buffer.buffer -> string -> int -> int -> unit
  val add_submemory :
    'Netmcore_buffer.buffer -> Netsys_mem.memory -> int -> int -> unit
  val add_sub_memory :
    'Netmcore_buffer.buffer -> Netsys_mem.memory -> int -> int -> unit
  val delete_hd : 'Netmcore_buffer.buffer -> int -> unit
  val clear : 'Netmcore_buffer.buffer -> unit
  val header : 'Netmcore_buffer.buffer -> 'h
  val descr_of_buffer :
    'Netmcore_buffer.buffer -> 'Netmcore_buffer.buffer_descr
  val buffer_of_descr :
    Netmcore.res_id ->
    'Netmcore_buffer.buffer_descr -> 'Netmcore_buffer.buffer
  val heap : 'Netmcore_buffer.buffer -> Obj.t Netmcore_heap.heap
end
ocamlnet-4.1.2/doc/html-main/Netsys_digests.digest-c.html0000644000175000017500000004504712731530353022006 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_digests.digest

Class type Netsys_digests.digest

class type digest = object .. end

method name : string
The name conventionally follows the <uppercasestring>-<size> format, e.g. "MD5-128", "SHA1-160", or "SHA2-256".
method iana_hash_fn : iana_hash_fn option
Whether registered at IANA, and if so, which ID we use here
method iana_name : string option
The name as registered by IANA (if registered)
method oid : int array option
The OID (if registered)
method size : int
The size of the digest string in bytes
method block_length : int
The block length of the hash function (for HMAC) in bytes
method create : unit -> digest_ctx
Start digestion
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_gssapi.server_key_verifier.html0000644000175000017500000004114512731530353026523 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_gssapi.server_key_verifier object method scram_credentials : string -> Netmech_scram.credentials endocamlnet-4.1.2/doc/html-main/type_Rpc_portmapper.html0000644000175000017500000006751112731530353021337 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper sig
  type t
  val create :
    ?esys:Unixqueue.event_system -> Rpc_client.connector -> Rpc_portmapper.t
  val create_inet :
    ?esys:Unixqueue.event_system ->
    string -> Rpc.protocol -> Rpc_portmapper.t
  val create_local : ?esys:Unixqueue.event_system -> unit -> Rpc_portmapper.t
  val shut_down : Rpc_portmapper.t -> unit
  val null : Rpc_portmapper.t -> unit
  val null'async : Rpc_portmapper.t -> ((unit -> unit) -> unit) -> unit
  val set :
    Rpc_portmapper.t ->
    Netnumber.uint4 -> Netnumber.uint4 -> Rpc.protocol -> int -> bool
  val set'async :
    Rpc_portmapper.t ->
    Netnumber.uint4 ->
    Netnumber.uint4 ->
    Rpc.protocol -> int -> ((unit -> bool) -> unit) -> unit
  val set_rpcbind :
    Rpc_portmapper.t ->
    Netnumber.uint4 -> Netnumber.uint4 -> string -> string -> string -> bool
  val set_rpcbind'async :
    Rpc_portmapper.t ->
    Netnumber.uint4 ->
    Netnumber.uint4 ->
    string -> string -> string -> ((unit -> bool) -> unit) -> unit
  val unset :
    Rpc_portmapper.t ->
    Netnumber.uint4 -> Netnumber.uint4 -> Rpc.protocol -> int -> bool
  val unset'async :
    Rpc_portmapper.t ->
    Netnumber.uint4 ->
    Netnumber.uint4 ->
    Rpc.protocol -> int -> ((unit -> bool) -> unit) -> unit
  val unset_rpcbind :
    Rpc_portmapper.t ->
    Netnumber.uint4 -> Netnumber.uint4 -> string -> string -> string -> bool
  val unset_rpcbind'async :
    Rpc_portmapper.t ->
    Netnumber.uint4 ->
    Netnumber.uint4 ->
    string -> string -> string -> ((unit -> bool) -> unit) -> unit
  val getport :
    Rpc_portmapper.t ->
    Netnumber.uint4 -> Netnumber.uint4 -> Rpc.protocol -> int
  val getport'async :
    Rpc_portmapper.t ->
    Netnumber.uint4 ->
    Netnumber.uint4 -> Rpc.protocol -> ((unit -> int) -> unit) -> unit
  val getaddr_rpcbind :
    Rpc_portmapper.t ->
    Netnumber.uint4 -> Netnumber.uint4 -> string -> string -> string option
  val getaddr_rpcbind'async :
    Rpc_portmapper.t ->
    Netnumber.uint4 ->
    Netnumber.uint4 ->
    string -> string -> ((unit -> string option) -> unit) -> unit
  val dump :
    Rpc_portmapper.t ->
    (Netnumber.uint4 * Netnumber.uint4 * Rpc.protocol * int) list
  val dump'async :
    Rpc_portmapper.t ->
    ((unit -> (Netnumber.uint4 * Netnumber.uint4 * Rpc.protocol * int) list) ->
     unit) ->
    unit
  val port_of_program : Rpc_program.t -> string -> Rpc.protocol -> int
  val sockaddr_of_program_rpcbind :
    Rpc_program.t -> string -> string -> Unix.sockaddr * Rpc.protocol
end
ocamlnet-4.1.2/doc/html-main/Uq_engines.datagram_socket_provider-c.html0000644000175000017500000004321512731530353024652 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.datagram_socket_provider

Class type Uq_engines.datagram_socket_provider

class type datagram_socket_provider = object .. end

method create_datagram_socket : datagram_type ->
Unixqueue.event_system ->
wrapped_datagram_socket engine
ocamlnet-4.1.2/doc/html-main/Netunichar.html0000644000175000017500000004341712731530353017400 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netunichar

Module Netunichar

module Netunichar: sig .. end
Unicode character information

val to_lower : int -> int
Converts the input letter to lowercase. Returns the input unchanged if it is no letter, or there is no lowercase equivalent.

This bases on the 1:1 lowercase transformation of letters, and ignores any transformation mapping one letter to several chars.

val to_upper : int -> int
Same for uppercase conversion
val to_title : int -> int
Same for titlecase conversion
ocamlnet-4.1.2/doc/html-main/type_Netplex_main.html0000644000175000017500000005473512731530353020771 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_main sig
  type cmdline_config
  val args :
    ?defaults:Netplex_main.cmdline_config ->
    unit -> (Arg.key * Arg.spec * Arg.doc) list * Netplex_main.cmdline_config
  val create :
    ?config_filename:string ->
    ?config_tree:Netplex_types.config_tree ->
    ?pidfile:string option ->
    ?foreground:bool -> unit -> Netplex_main.cmdline_config
  val modify :
    ?config_filename:string ->
    ?config_tree:Netplex_types.config_tree ->
    ?pidfile:string option ->
    ?foreground:bool ->
    Netplex_main.cmdline_config -> Netplex_main.cmdline_config
  val config_filename : Netplex_main.cmdline_config -> string
  val config_filename_opt : Netplex_main.cmdline_config -> string option
  val config_tree_opt :
    Netplex_main.cmdline_config -> Netplex_types.config_tree option
  val pidfile : Netplex_main.cmdline_config -> string option
  val foreground : Netplex_main.cmdline_config -> bool
  val startup :
    ?late_initializer:(Netplex_types.config_file ->
                       Netplex_types.controller -> unit) ->
    ?config_parser:(string -> Netplex_types.config_file) ->
    Netplex_types.parallelizer ->
    Netplex_types.logger_factory list ->
    Netplex_types.workload_manager_factory list ->
    Netplex_types.processor_factory list ->
    Netplex_main.cmdline_config -> unit
  val run :
    ?config_parser:(string -> Netplex_types.config_file) ->
    late_initializer:(Netplex_types.config_file ->
                      Netplex_types.controller -> 'a) ->
    extract_result:(Netplex_types.controller -> '-> 'b) ->
    Netplex_types.parallelizer ->
    Netplex_types.logger_factory list ->
    Netplex_types.workload_manager_factory list ->
    Netplex_types.processor_factory list -> Netplex_main.cmdline_config -> 'b
end
ocamlnet-4.1.2/doc/html-main/Netchannels.input_channel-c.html0000644000175000017500000004314112731530353022602 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_channel

Class Netchannels.input_channel

class input_channel : ?onclose:unit -> unit -> Pervasives.in_channel -> in_obj_channel
Creates an input channel from an in_channel, which must be open.

The method pos_in reflects the real position in the channel as returned by Pervasives.pos_in. This works for both seekable and non-seekable channels.

The method close_in also closes the underlying in_channel.

The function onclose is called after the in_channel has been closed.


ocamlnet-4.1.2/doc/html-main/Uq_client.html0000644000175000017500000007253412731530353017225 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_client

Module Uq_client

module Uq_client: sig .. end
Support for socket clients


Support for socket clients

Support for socket clients

Note that Win32 named pipes are also supported by the following API's, although they are not sockets. These pipes have a feature set comparable to Unix domain sockets.
type inetspec = [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
| `Sock_inet_byname of Unix.socket_type * string * int ]
type sockspec = [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
| `Sock_inet_byname of Unix.socket_type * string * int
| `Sock_unix of Unix.socket_type * string ]
Extended names for socket addresses. Currently, these naming schemes are supported:
  • `Sock_unix(stype,path): Names the Unix domain socket at path. The socket type stype is an auxiliary piece of information, but not a distinguishing part of the name. path = "" refers to anonymous sockets. Otherwise, the path must be an absolute path name.
  • `Sock_inet(stype,addr,port): Names the Internet socket of type stype bound to the IP address addr and the port. If stype = Unix.SOCK_STREAM, a TCP socket is meant, and if stype = Unix.SOCK_DGRAM, a UDP socket is meant. It is allowed that addr = Unix.inet_addr_any. If port = 0, the name is to be considered as incomplete.
  • `Sock_inet_byname(stype,name,port): Names the Internet socket of type stype bound to the IP address corresponding to the name, and bound to the port. It is unspecified which naming service is used to resolve name to an IP address, and how it is used. If the name cannot be resolved, no socket is meant; this is usually an error. stype is interpreted as for `Sock_inet. If port = 0, the name is to be considered as incomplete.
It is currently not possible to name IP sockets that are bound to several IP addresses but not all IP addresses of the host.
val sockspec_of_sockaddr : Unix.socket_type -> Unix.sockaddr -> sockspec
Converts a normal socket address to the extended form
val sockspec_of_socksymbol : Unix.socket_type -> Netsockaddr.socksymbol -> sockspec
Converts a Netsockaddr.socksymbol to this form
type connect_address = [ `Command of string * (int -> Unixqueue.event_system -> unit)
| `Socket of sockspec * connect_options
| `W32_pipe of Netsys_win32.pipe_mode * string ]
Specifies the service to connect to:

  • `Socket(addr,opts): Connect to the passed socket address
  • `Command(cmd,handler): The cmd is started with the shell, and stdin and stdout are used to transfer data to the process and from the process, respectively. Only SOCK_STREAM type is supported. Note that the passed file descriptors are normal pipes, not sockets (so the descriptors can be individually closed).

    There is not any kind of error detection, so the command should be failsafe. stderr of the command is connected with stderr of the caller process.

    No provisions are taken to wait for the process; this is the task of the caller. After the process has been started, the handler is invoked with the process ID and the event system to give the caller a chance to arrange that the process will be waited for.

  • `W32_pipe(mode,name): A Win32 named pipe

type connect_options = Uq_engines.connect_options = {
   conn_bind : sockspec option; (*
Bind the connecting socket to this address (same family as the connected socket required). None: Use an anonymous port.
*)
}
val default_connect_options : connect_options
Returns the default options
type connect_status = [ `Command of Unix.file_descr * int
| `Socket of Unix.file_descr * sockspec
| `W32_pipe of Unix.file_descr ]
This type corresponds with Uq_engines.connect_address: An engine connecting with an address `X will return a status of `X.

  • `Socket(fd,addr): fd is the client socket connected with the service. addr is the socket address of the client that must be used by the server to reach the client.
  • `Command(fd, pid): fd is the Unix domain socket connected with the running command. pid is the process ID.
  • `W32_pipe fd: fd is the proxy descriptor of the connected Win32 named pipe endpoint. See Netsys_win32 how to get the w32_pipe object to access the pipe. The proxy descriptor cannot be used for I/O.

val client_endpoint : connect_status -> Unix.file_descr
Returns the client endpoint contained in the connect_status
val client_channel : Uq_engines.connect_status -> float -> Netchannels.raw_io_channel
client_channel st timeout: returns a bidirectional channel for st that times out after timeout seconds of waiting.
class type client_endpoint_connector = object .. end
This class type provides engines to connect to a service.
val connect_e : ?proxy:#Uq_engines.client_endpoint_connector ->
Uq_engines.connect_address ->
Unixqueue.event_system -> Uq_engines.connect_status Uq_engines.engine
This engine connects to a socket as specified by the connect_address, optionally using the proxy, and changes to the state `Done(status) when the connection is established.

If the proxy does not support the connect_address, the class will raise Addressing_method_not_supported.

The descriptor fd (part of the connect_status) is in non-blocking mode, and the close-on-exec flag is set. It is the task of the caller to close this descriptor.

The engine attaches automatically to the event system, and detaches when it is possible to do so. This depends on the type of the connection method. For direct socket connections, the engine can often detach immediately when the conection is established. For proxy connections it is required that the engine copies data to and from the file descriptor. In this case, the engine detaches when the file descriptor is closed.

It is possible that name service queries block execution.

If name resolution fails, the engine will enter `Error(Uq_resolver.Host_not_found name).

val connect : ?proxy:#Uq_engines.client_endpoint_connector ->
Uq_engines.connect_address -> float -> Uq_engines.connect_status
connect addr tmo: Runs connect_e for this addr, and returns the result. After tmo seconds, Uq_engines.Timeout will be raised.

Example of using connect_e: This engine e connects to the "echo" service as provided by inetd, sends a line of data to it, and awaits the response.

	let e =
	  Uq_engines.connector
	    (`Socket(`Sock_inet_byname(Unix.SOCK_STREAM, "localhost", 7),
		     Uq_engines.default_connect_options))
	    esys
	  ++ (fun cs ->
		match cs with
		  | `Socket(fd,_) ->
		      let mplex =
			Uq_engines.create_multiplex_controller_for_connected_socket
			  ~supports_half_open_connection:true
			  fd esys in
		      let d_unbuf = `Multiplex mplex in
		      let d = `Buffer_in(Uq_io.create_in_buffer d_unbuf) in
		      Uq_io.output_string_e d_unbuf "This is line1\n"
		      ++ (fun () ->
			    Uq_io.input_line_e d 
			    ++ (fun s ->
				  print_endline s;
				  eps_e (`Done()) esys
			       )
			 )
		  | _ -> assert false
	     )
    

ocamlnet-4.1.2/doc/html-main/Netencoding.QuotedPrintable.html0000644000175000017500000005223212731530353022631 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.QuotedPrintable

Module Netencoding.QuotedPrintable

module QuotedPrintable: sig .. end


This module implements the "Quoted Printable" encoding as described in RFC 2045.

This implementation assumes that the encoded string has a text MIME type. On input both CR/LF and LF are accepted as end-of-line (eol) terminators, but the output normalizes the eol delimiter as the crlf argument specifies. Note that this implies that

  • If crlf, the output uses CR/LF as line separator as MIME prescribes
  • the encoding is not invertible for binary data

val encode : ?crlf:bool -> ?pos:int -> ?len:int -> string -> string
Encodes the string and returns it.

Since OcamlNet 0.98, soft line breaks are added to the output to ensure that all output lines have a length <= 76 bytes.

Note unsafe characters: As recommended by RFC 2045, the characters !#$@[]^`|{}~ and the double quotes are additionally represented as hex tokens. Furthermore, the letter 'F' is considered as unsafe if it occurs at the beginning of the line, so the encoded text never contains the word "From" at the beginning of a line.

If pos and/or len are passed, only the substring starting at pos (default: 0) with length len (default: rest of the string) is encoded.

If crlf is set (the default), the output text uses CR/LF as line separator. Otherwise only LF is used.

val encode_tstring : ?crlf:bool -> ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
Same for tagged string inputs. The result are always bytes, though
val encode_poly : ?crlf:bool ->
?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t
Polymorphic version
val decode : ?pos:int -> ?len:int -> string -> string
Decodes the string and returns it.

Most format errors cause an Invalid_argument exception.

If pos and/or len are passed, only the substring starting at pos (default: 0) with length len (default: rest of the string) is decoded.

val decode_tstring : ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
Same for tagged string inputs. The result are always bytes, though
val decode_poly : ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t
Polymorphic version
class encoding_pipe : ?crlf:bool -> unit -> Netchannels.pipe
This pipe encodes the data written into the pipe.
class decoding_pipe : unit -> Netchannels.pipe
This pipe decodes the data written into the pipe.
ocamlnet-4.1.2/doc/html-main/Nethttp_client.generic_auth_handler-c.html0000644000175000017500000004264212731530353024634 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.generic_auth_handler

Class Nethttp_client.generic_auth_handler

class generic_auth_handler : #key_handler -> (module Nethttp.HTTP_CLIENT_MECHANISM) list -> auth_handler
Authenticate with the passed generic HTTP mechanisms

ocamlnet-4.1.2/doc/html-main/Netx509.KP.html0000644000175000017500000004447212731530353016767 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509.KP

Module Netx509.KP

module KP: sig .. end
Key purpose IDs as returned by parse_ext_key_usage

val kp_server_auth : Netx509.oid
val kp_client_auth : Netx509.oid
val kp_code_signing : Netx509.oid
val kp_email_protection : Netx509.oid
val kp_time_stamping : Netx509.oid
val kp_ocsp_signing : Netx509.oid
val ext_key_purposes : (Netx509.oid * Netx509.ext_key_usage_flag * string) list
ocamlnet-4.1.2/doc/html-main/Netchannels.output_buffer-c.html0000644000175000017500000004312112731530353022642 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_buffer

Class Netchannels.output_buffer

class output_buffer : ?onclose:unit -> unit -> Buffer.t -> out_obj_channel
This output channel writes the data into the passed buffer.

The method pos_out returns the number of written octets.


onclose : this function is called when the close_out method is invoked, just after the underlying descriptor has been closed.

ocamlnet-4.1.2/doc/html-main/Uq_mt.html0000644000175000017500000005701012731530353016357 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_mt

Module Uq_mt

module Uq_mt: sig .. end

Using engines in multi-threaded programs




Monitors can be used to coordinate access to a resource from several threads so that only one thread comes into contact with the resource. Of course, the resources we talk about must have an engine interface. For example, the resource could be an RPC client. In contrast to a critical section (protected with mutexes), the accesses are not serialized, but simply pushed onto the same event system, and run there concurrently. Effectively, the monitor translates heavy-weight threading (kernel threads) into light-weight threading (engines).
type monitor 
A thread monitor governs which threads have access to a set of engines running together on an event system
val create_monitor : Unixqueue.event_system -> monitor
Creates a new monitor. The passed event system becomes the inner event system of the monitor. All engines attached to the monitor will use this event system.
val monitor_run : monitor ->
(Unixqueue.event_system -> 'a -> 'b Uq_engines.engine) -> 'a -> 'b
let result = monitor_run mon f outer_esys arg: Runs another engine within the monitor. The engine inner_e is created as

 let inner_e = f inner_esys arg 

where inner_esys is the event system of the monitor. It is obligatory that inner_e uses this event system.

When inner_e reaches a final state, the thread leaves the monitor, and the result of inner_e is returned (or the recorded exception is thrown).

The "special effect" of the monitor is that several threads can share the same monitor, even at the same time. All parallel running engines inner_e will use the same event system inner_esys. Of course, this also means that they run in the same thread. Note that it is possible that the monitor switches the thread it uses for executing the event system (and the engines). In particular, this can happen when one of the inner engines finishes, and the thread that put this engine into the monitor was chosen as the thread for executing the event system. When this happens, another thread waiting for the monitor will be selected for running the event system.

If an inner engine establishes configurations that are not bound to the lifetime of the inner engine, there is no guarantee that these additional events and handlers will be considered when the inner engine ends. For example, if the engine starts a timer to run an action later, it is not said that the action is carried out at all if the engine terminates before.

Exceptions falling through to the caller of the event system are logged and otherwise ignored.

It is possible to use monitors in single-threaded programs - this is treated as if only one thread was using the monitor in a multi-threaded program.

val monitor_do : monitor -> ('a -> 'b) -> 'a -> 'b
let result = monitor_do mon f arg: Just runs f arg in the scope of the monitor, and returns the result.
val monitor_async : monitor -> ('a -> ((unit -> 'b) -> unit) -> unit) -> 'a -> 'b
let result = monitor_async f arg: For calling RPC-style asynchronous clients. If f is called like f arg emit, the result is passed back by calling emit (fun () -> result).

Example: Threads sharing an RPC client

In this example we want to achieve that several threads can use the same RPC client. This type of client is not thread-safe, but it is able to run asynchronously. Because of this, the requests coming from several threads can be concurrently handled.

Prepare the RPC client and the monitor: We assume that M_clnt is the generated RPC module with the client, and that we access program P at version V.

      let esys = Unixqueue.create_unix_event_system
      let rpc = M_clnt.P.V.create_client ~esys connector protocol
      let mon = Uq_mt.create_monitor esys
    

It is essential that the RPC client and the monitor use the same esys.

Next, let's assume we are in a spawned thread, and we want to call an RPC procedure M_clnt.P.V.proc. The trick here is to use the asynchronous variant M_clnt.P.V.proc'async, and to call it via the monitor:

      let result = Uq_mt.monitor_async mon (M_clnt.P.V.proc'async rpc) arg
    

The procedure is called with argument arg and returns the result. The monitor waits until the asynchronous call is done, so this appears as a synchronous call to the user.

If you need to call functions to configure and control the RPC client, use monitor_do:

      let sockaddr = Uq_mt.monitor_do mon Rpc_client.get_peer_name rpc
    

ocamlnet-4.1.2/doc/html-main/type_Uq_libevent.POLLSET.html0000644000175000017500000004142012731530353021727 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_libevent.POLLSET sig
  val create_pollset : unit -> Netsys_pollset.pollset
  val create_event_system : unit -> Unixqueue.event_system
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.output_async_mplex.html0000644000175000017500000004175312731530353025743 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.output_async_mplex ?onclose:[ `Ignore | `Write_eof ] ->
?onshutdown:Uq_engines_compat.onshutdown_out_spec ->
?buffer_size:int ->
Uq_engines_compat.multiplex_controller ->
Uq_engines_compat.async_out_channel_engine
ocamlnet-4.1.2/doc/html-main/type_Nettls_support.html0000644000175000017500000005135012731530353021401 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_support sig
  type credentials = [ `Anonymous | `X509 of Netx509.x509_certificate ]
  type raw_credentials = [ `Anonymous | `X509 of string ]
  type cred_type = [ `Anonymous | `X509 ]
  class type tls_session_props =
    object
      method addressed_server : string option
      method cipher_algo : string
      method cipher_suite_type : string
      method compression_algo : string
      method endpoint_credentials : Nettls_support.credentials
      method endpoint_credentials_raw : Nettls_support.raw_credentials
      method endpoint_credentials_type : Nettls_support.cred_type
      method id : string
      method kx_algo : string
      method mac_algo : string
      method peer_credentials : Nettls_support.credentials
      method peer_credentials_raw : Nettls_support.raw_credentials
      method peer_credentials_type : Nettls_support.cred_type
      method protocol : string
    end
  val get_tls_session_props :
    Netsys_crypto_types.tls_endpoint -> Nettls_support.tls_session_props
  val get_tls_user_name : Nettls_support.tls_session_props -> string
  val squash_file_tls_endpoint :
    (module Netsys_crypto_types.FILE_TLS_ENDPOINT->
    (module Netsys_crypto_types.TLS_ENDPOINT)
  val is_endpoint_host : string -> Nettls_support.tls_session_props -> bool
end
ocamlnet-4.1.2/doc/html-main/Netbuffer.html0000644000175000017500000011174012731530353017213 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netbuffer

Module Netbuffer

module Netbuffer: sig .. end
A Netbuffer.t is a buffer that can grow and shrink dynamically.

type t 
val create : int -> t
Creates a netbuffer which allocates initially this number of bytes. The logical length is zero.
val contents : t -> string
Returns the contents of the buffer as fresh string.
val to_bytes : t -> Bytes.t
Returns the contents of the buffer as fresh string.
val to_tstring_poly : t -> 's Netstring_tstring.tstring_kind -> 's
Return the buffer in the format as selected by the arg
val to_tstring : t -> 'a Netstring_tstring.tstring_kind -> Netsys_types.tstring
Returns the buffer as tagged string, selecting the chosen representation
val length : t -> int
Returns the logical length of the buffer

Extracting strings


val get : t -> int -> char
get nb pos: Get the character at pos
val nth : t -> int -> char
Alias for get
val sub : t -> int -> int -> string
sub nb k n: returns the n characters starting at position n from netbuffer nb as fresh string
val sub_bytes : t -> int -> int -> Bytes.t
Same for bytes

Extraction with blit


val blit_to_bytes : t -> int -> Bytes.t -> int -> int -> unit
blit_to_bytes nb srcpos dest destpos len: Copies the len bytes at position srcpos from nb to the string dest at position destpos.
val blit_to_string : t -> int -> Bytes.t -> int -> int -> unit
Deprecated."Use blit_to_bytes instead."
val blit : t -> int -> Bytes.t -> int -> int -> unit
Compatibility name for blit_to_bytes
val blit_to_memory : t -> int -> Netsys_mem.memory -> int -> int -> unit
blit_to_memory nb srcpos dest destpos len: Copies the len bytes at position srcpos from nb to the membuffer dest at position destpos.
val blit_to_tbuffer : t -> int -> Netsys_types.tbuffer -> int -> int -> unit
Blits to a tagged buffer

Appending strings


val add_string : t -> string -> unit
add_string nb s: Adds a copy of the string s to the logical end of the netbuffer nb. If necessary, nb grows.
val add_bytes : t -> Bytes.t -> unit
Same for bytes
val add_tstring : t -> Netsys_types.tstring -> unit
Same for tagged string
val add_tstring_poly : t -> 's Netstring_tstring.tstring_ops -> 's -> unit
Polymorphic version
val add_substring : t -> string -> int -> int -> unit
add_substring nb s k n: Adds the substring of s starting at position k with length n to the logical end of the netbuffer nb. If necessary, nb grows.

This is semantically the same as add_string nb (String.sub s k n), but the extra copy is avoided.

val add_subbytes : t -> Bytes.t -> int -> int -> unit
Same for bytes
val add_subtstring : t -> Netsys_types.tstring -> int -> int -> unit
Same for tagged string
val add_sub_string : t -> string -> int -> int -> unit
Deprecated."Use add_substring instead."
val add_submemory : t -> Netsys_mem.memory -> int -> int -> unit
Same as add_substring, but gets data from a memory buffer
val add_sub_memory : t -> Netsys_mem.memory -> int -> int -> unit
Deprecated."Use add_submemory instead."
val add_subtstring_poly : t -> 's Netstring_tstring.tstring_ops -> 's -> int -> int -> unit
Polymorphic version
val add_char : t -> char -> unit
add_char nb c: Adds a single char at the end of the buffer
val add_char_2 : t -> char -> char -> unit
add_char_2 nb c1 c2: Adds two chars at the end of the buffer
val add_char_4 : t -> char -> char -> char -> char -> unit
add_char_4 nb c1 c2 c3 c4: Adds four chars at the end of the buffer
val add_inplace : ?len:int -> t -> (Bytes.t -> int -> int -> int) -> int
add_inplace nb f: Calls the function f to add bytes to the netbuffer nb. The arguments of f are the buffer, the position in the buffer, and the maximum length. The function f must return the actual number of added bytes; this number is also returned by add_inplace.

Example: let n = add_inplace nb (Pervasives.input ch)

The argument len is the number of bytes to add (second argument of f). It defaults to the number of free bytes in the buffer after space for at least one byte has been allocated.

val add_buffer : t -> t -> unit
add_buffer nb1 nb2: Adds the contents of nb2 to the end of nb1
val area_for_additions : ?len:int -> t -> Bytes.t * int * int
val advance : t -> int -> unit
These two functions work together, so that the effect of add_inplace can be obtained in two steps. First, the user calls
        let (s,pos,len) = area_for_additions nb
      
to get the area where to put new data of length n, with n <= len. After this the data is made valid by
        advance n
      


Inserting strings


val insert_string : t -> int -> string -> unit
insert_string nb p s: Inserts the value of string s at position p into the netbuffer nb
val insert_substring : t -> int -> string -> int -> int -> unit
insert_string nb p s k n: Inserts a substring of string s at position p into the netbuffer nb. The substring is denoted by position k and has length n
val insert_sub_string : t -> int -> string -> int -> int -> unit
Deprecated."Use insert_substring instead."
val insert_subbytes : t -> int -> Bytes.t -> int -> int -> unit
Same for bytes
val insert_subtstring : t -> int -> Netsys_types.tstring -> int -> int -> unit
Same for tagged string
val insert_submemory : t -> int -> Netsys_types.memory -> int -> int -> unit
Same for memory
val insert_char : t -> int -> char -> unit
insert_char nb p c: Inserts character c at position p into the netbuffer nb

Overwriting strings


val set : t -> int -> char -> unit
set nb pos c: Sets the character at pos to c
val put_string : t -> int -> string -> unit
put_string nb pos s: Copies the string s to the position pos of netbuffer nb
val blit_from_string : string -> int -> t -> int -> int -> unit
blit_from_string src srcpos dest destpos len: Copies the len bytes at position srcpos from the string src to the netbuffer dest at position destpos.

It is possible to copy the string beyond the end of the buffer. The buffer is automatically enlarged in this case.

val blit_from_bytes : Bytes.t -> int -> t -> int -> int -> unit
Same for bytes
val blit_from_memory : Netsys_types.memory -> int -> t -> int -> int -> unit
Same for memory
val blit_from_tstring : Netsys_types.tstring -> int -> t -> int -> int -> unit
Same for tagged string

Deleting


val delete : t -> int -> int -> unit
delete nb k n: Deletes the n bytes at position k of netbuffer nb in-place.

The netbuffer does not shrink, however, i.e. the free space is not given back to the memory manager.

val clear : t -> unit
Deletes all contents from the buffer. As delete, the netbuffer does not shrink.
val reset : t -> unit
Empty the buffer, deallocate the internal string, and replace it with a new string of length n that was allocated by Netbuffer.create n.
val try_shrinking : t -> unit
try_shrinking nb: If the length of the buffer is less than half of the allocated space, the netbuffer is reallocated in order to save memory.

Searching


val index_from : t -> int -> char -> int
index_from nb k c: Searches the character c in the netbuffer beginning at position k. If found, the position of the left-most occurence is returned. Otherwise, Not_found is raised.

Miscelleneous


val unsafe_buffer : t -> Bytes.t
Warning! This is a low-level function! Returns the current string that internally holds the buffer. The byte positions 0 to length - 1 actually store the contents of the buffer. You can directly read and modify the buffer. Note that there is no protection if you read or write positions beyond the length of the buffer.
val print_buffer : t -> unit
For the toploop
ocamlnet-4.1.2/doc/html-main/Nettls_support.tls_session_props-c.html0000644000175000017500000005145712731530353024357 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_support.tls_session_props

Class type Nettls_support.tls_session_props

class type tls_session_props = object .. end
Direct access to TLS properties of a session

method id : string
The ID of the session (non-printable string)
method addressed_server : string option
The name of the server (for name-based virtual servers). This may be unavailable, because this information is exchanged via a TLS extension.
method cipher_suite_type : string
A string describing the authentication and privacy mechanism that is in effect:
  • "X509": X509 certificates are used
  • "OPENPGP": OpenPGP certificates are used
  • "ANON": anonymous credentials
  • "SRP": SRP credentials
  • "PSK": PSK credentials

method endpoint_credentials : credentials
Returns the decoded credentials of this endpoint
method endpoint_credentials_type : cred_type
The type of credentials
method endpoint_credentials_raw : raw_credentials
Returns the credentials in the raw form. For X509 certicates, this is the DER encoding
method peer_credentials : credentials
Returns the decoded peer credentials
method peer_credentials_type : cred_type
The type of credentials
method peer_credentials_raw : raw_credentials
Returns the peer credentials in the raw form. For X509 certicates, this is the DER encoding
method cipher_algo : string
The name of the algorithm for encrypting the data stream, e.g. "AES-128-CBC".
method kx_algo : string
The name of the key exchange algorithm, e.g. "RSA"
method mac_algo : string
The name of the data integrity algorithm (actually only the digest algorithm for HMAC), e.g. "SHA1"
method compression_algo : string
The name of the compression algorithm (or "NULL"), on the TLS layer. E.g. "DEFLATE".
method protocol : string
The name of the TLS protocol version, e.g. "TLS1.0"
ocamlnet-4.1.2/doc/html-main/Netcgi_apache.Apache.html0000644000175000017500000004346312731530353021173 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache

Module Netcgi_apache.Apache

module Apache: sig .. end
Interface to Apache API.

module Table: sig .. end
module Server: sig .. end
module Connection: sig .. end
module Request: sig .. end
ocamlnet-4.1.2/doc/html-main/Netsys_digests.html0000644000175000017500000005451012731530353020303 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_digests

Module Netsys_digests

module Netsys_digests: sig .. end
Cryptographic digests (hashes)

type iana_hash_fn = [ `MD2 | `MD5 | `SHA_1 | `SHA_224 | `SHA_256 | `SHA_384 | `SHA_512 ] 
The hash functions contained in the IANA registry (http://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xhtml).
class type digest_ctx = object .. end
class type digest = object .. end

The following functions use the current digest module (as retrieved by Netsys_crypto.current_digests), unless the impl argument is passed.
val digests : ?impl:(module Netsys_crypto_types.DIGESTS) ->
unit -> digest list
List of supported digests
val find : ?impl:(module Netsys_crypto_types.DIGESTS) -> string -> digest
find name: get the digest name.

The name conventionally follows the <uppercasestring>-<size> format, e.g. "MD5-128", "SHA1-160", or "SHA2-256".

val digest_tstring : digest -> Netsys_types.tstring -> string
Digest a string
val digest_bytes : digest -> Bytes.t -> string
Digest a string
val digest_string : digest -> string -> string
Digest a string
val digest_mstrings : digest -> Netsys_types.mstring list -> string
Digest a sequence of mstrings
val hmac : digest -> string -> digest
hmac dg key: returns the digest context computing the HMAC construction (RFC-2104).

The key must not be longer than dg#block_length.

val iana_find : ?impl:(module Netsys_crypto_types.DIGESTS) ->
iana_hash_fn -> digest
iana_find name: get the digest name
val iana_alist : (string * iana_hash_fn) list
maps the IANA name to the hash function id
val iana_rev_alist : (iana_hash_fn * string) list
the reverse
val oid_alist : (int array * iana_hash_fn) list
maps the OID to the hash function id
val oid_rev_alist : (iana_hash_fn * int array) list
the reverse
val name_alist : (string * iana_hash_fn) list
maps the OCamlnet name to the hash function id
val name_rev_alist : (iana_hash_fn * string) list
the reverse
ocamlnet-4.1.2/doc/html-main/type_Netchannels.output_channel.html0000644000175000017500000004115212731530353023624 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_channel ?onclose:(unit -> unit) ->
Pervasives.out_channel -> Netchannels.out_obj_channel
ocamlnet-4.1.2/doc/html-main/type_Netsys_oothr.mutex.html0000644000175000017500000004156212731530353022201 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr.mutex object
  method lock : unit -> unit
  method repr : exn
  method try_lock : unit -> bool
  method unlock : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/Nethttp_fs.http_stream_fs-c.html0000644000175000017500000005547412731530353022665 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_fs.http_stream_fs

Class type Nethttp_fs.http_stream_fs

class type http_stream_fs = object .. end

method read : read_flag list -> string -> Netchannels.in_obj_channel
Additional flag:
  • `Header h: Set these headers in the submitted GET request

method read_file : read_file_flag list -> string -> Netfs.local_file
Additional flag:
  • `Header h: Set these headers in the submitted GET request

method write : write_flag list -> string -> Netchannels.out_obj_channel
Additional flag:
  • `Header h: Set these headers in the submitted PUT request

method write_file : write_file_flag list -> string -> Netfs.local_file -> unit
Additional flag:
  • `Header h: Set these headers in the submitted PUT request

method last_response_header : Nethttp.http_header
Returns the header of the HTTP response of the last operation. Generally, the header is set when the last operation returns normally (no exception was raised). In case of write, the header is first set when the stream is closed.

Raises Not_found if the last operation did not receive a header (or not fully).

method last_response_status : Nethttp.http_status * int * string
Return the response status of the last operation, as triple (symbolic_code,numeric_code,text). This triple is set in the same way as the response header. Raises Not_found if unavailable.
method pipeline : Nethttp_client.pipeline
The HTTP pipeline backing this file system
method translate : string -> string
Translates a path into a URL
method path_encoding : Netconversion.encoding option
method path_exclusions : (int * int) list
method nominal_dot_dot : bool
method size : Netfs.size_flag list -> string -> int64
method test : Netfs.test_flag list -> string -> Netfs.test_type -> bool
method test_list : Netfs.test_flag list -> string -> Netfs.test_type list -> bool list
method remove : Netfs.remove_flag list -> string -> unit
method rename : Netfs.rename_flag list -> string -> string -> unit
method symlink : Netfs.symlink_flag list -> string -> string -> unit
method readdir : Netfs.readdir_flag list -> string -> string list
method readlink : Netfs.readlink_flag list -> string -> string
method mkdir : Netfs.mkdir_flag list -> string -> unit
method rmdir : Netfs.rmdir_flag list -> string -> unit
method copy : Netfs.copy_flag list -> string -> string -> unit
method cancel : unit -> unit
ocamlnet-4.1.2/doc/html-main/Netplex_encap.Make_encap.html0000644000175000017500000004417712731530353022113 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_encap.Make_encap

Functor Netplex_encap.Make_encap

module Make_encap: 
functor (T : TYPE) -> ENCAP with type t = T.t
Create an encapsulation module
Parameters:
T : TYPE

type t 
val wrap : t -> Netplex_encap.encap
val unwrap : Netplex_encap.encap -> t
Raises Netplex_encap.Type_mismatch if the value does not fit
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.epsilon_engine.html0000644000175000017500000004127312731530353024774 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.epsilon_engine 'Uq_engines_compat.engine_state ->
Unixqueue.event_system -> ['t] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/type_Netsys_types.mstring.html0000644000175000017500000004420012731530353022523 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_types.mstring object
  method as_bytes : Bytes.t * int
  method as_memory : Netsys_types.memory * int
  method as_string : string * int
  method blit_to_bytes : int -> Bytes.t -> int -> int -> unit
  method blit_to_memory : int -> Netsys_types.memory -> int -> int -> unit
  method blit_to_string : int -> Bytes.t -> int -> int -> unit
  method length : int
  method preferred : [ `Bytes | `Memory ]
end
ocamlnet-4.1.2/doc/html-main/type_Netfs.stream_fs.html0000644000175000017500000005230612731530353021377 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netfs.stream_fs object
  method cancel : unit -> unit
  method copy : Netfs.copy_flag list -> string -> string -> unit
  method mkdir : Netfs.mkdir_flag list -> string -> unit
  method nominal_dot_dot : bool
  method path_encoding : Netconversion.encoding option
  method path_exclusions : (int * int) list
  method read : Netfs.read_flag list -> string -> Netchannels.in_obj_channel
  method read_file : Netfs.read_file_flag list -> string -> Netfs.local_file
  method readdir : Netfs.readdir_flag list -> string -> string list
  method readlink : Netfs.readlink_flag list -> string -> string
  method remove : Netfs.remove_flag list -> string -> unit
  method rename : Netfs.rename_flag list -> string -> string -> unit
  method rmdir : Netfs.rmdir_flag list -> string -> unit
  method size : Netfs.size_flag list -> string -> int64
  method symlink : Netfs.symlink_flag list -> string -> string -> unit
  method test : Netfs.test_flag list -> string -> Netfs.test_type -> bool
  method test_list :
    Netfs.test_flag list -> string -> Netfs.test_type list -> bool list
  method write :
    Netfs.write_flag list -> string -> Netchannels.out_obj_channel
  method write_file :
    Netfs.write_file_flag list -> string -> Netfs.local_file -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.in_obj_channel_delegation.html0000644000175000017500000004107712731530353025725 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.in_obj_channel_delegation ?close:bool -> Netchannels.in_obj_channel -> Netchannels.in_obj_channelocamlnet-4.1.2/doc/html-main/type_Netchannels.input_string.html0000644000175000017500000004106412731530353023323 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_string ?pos:int -> ?len:int -> string -> Netchannels.in_obj_channelocamlnet-4.1.2/doc/html-main/Nethttpd_types.empty_environment-c.html0000644000175000017500000004664512731530353024325 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.empty_environment

Class virtual Nethttpd_types.empty_environment

class virtual empty_environment : object .. end
This class implements an environment with defined internal containers. These containers are empty, but fully functional. The following methods are empty and should be redefined:
  • send_output_header
  • send_file
  • log_error
  • log_props
The virtual methods, of course, must be defined!
Inherits
val mutable config : Netcgi.config
val mutable protocol : Nethttp.protocol
val mutable in_header : Nethttp.http_header
val mutable out_header : Nethttp.http_header
val mutable properties : (string * string) list
val mutable in_channel : Netchannels.in_obj_channel
val mutable out_channel : Netchannels.out_obj_channel
val mutable tls_session_props : Nettls_support.tls_session_props option
ocamlnet-4.1.2/doc/html-main/type_Ocamlnet4.html0000644000175000017500000004061212731530353020161 0ustar gerdgerd Ocamlnet 4 Reference Manual : Ocamlnet4 sig  endocamlnet-4.1.2/doc/html-main/type_Netplex_log.html0000644000175000017500000005667512731530353020633 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_log sig
  class type generic_config =
    object
      method log_component : string
      method log_format : string
      method log_max_level : Netplex_types.level
      method log_subchannel : string
    end
  val channel_logger : Pervasives.out_channel -> Netplex_types.logger
  val channel_logger_from_obj :
    Netplex_log.generic_config ->
    Pervasives.out_channel -> Netplex_types.logger
  val stderr_logger_factory : Netplex_types.logger_factory
  val file_logger : string -> Netplex_types.logger
  val file_logger_from_obj :
    Netplex_log.generic_config -> string -> Netplex_types.logger
  val file_logger_factory : Netplex_types.logger_factory
  class type multi_file_config =
    object
      method log_component : string
      method log_directory : string
      method log_files :
        (string * string *
         [ `Alert
         | `All
         | `Crit
         | `Debug
         | `Emerg
         | `Err
         | `Info
         | `Notice
         | `Warning ] * string * string)
        list
      method log_format : string
      method log_max_level : Netplex_types.level
      method log_subchannel : string
    end
  val multi_file_logger :
    Netplex_log.multi_file_config -> Netplex_types.logger
  val multi_file_logger_factory : Netplex_types.logger_factory
  class type syslog_config =
    object
      method log_component : string
      method log_facility : Netsys_posix.syslog_facility
      method log_format : string
      method log_identifier : string
      method log_max_level : Netplex_types.level
      method log_subchannel : string
    end
  val syslog_logger : Netplex_log.syslog_config -> Netplex_types.logger
  val syslog_logger_factory : Netplex_types.logger_factory
  val logger_factories : Netplex_types.logger_factory list
  val level_weight : Netplex_types.level -> int
  val level_of_string : string -> Netplex_types.level
end
ocamlnet-4.1.2/doc/html-main/Netgssapi_auth.Manage.html0000644000175000017500000004377212731530353021451 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_auth.Manage

Functor Netgssapi_auth.Manage

module Manage: 
functor (G : Netsys_gssapi.GSSAPI) -> sig .. end
Parameters:
G : Netsys_gssapi.GSSAPI


General management
val delete_context : G.context option -> unit -> unit
Deletes the context, ignoring any error
val format_status : ?fn:string -> ?minor_status:int32 -> Netsys_gssapi.major_status -> string
ocamlnet-4.1.2/doc/html-main/Netftp_data_endpoint.in_record_channel-c.html0000644000175000017500000004603112731530353025277 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.in_record_channel

Class type Netftp_data_endpoint.in_record_channel

class type in_record_channel = object .. end
An in_record_channel can be used to read files with record structure. This is purely abstract, as Unix does not support such files natively, so this kind of channel is usually mapped to a flat representation when stored in a real file, e.g. record boundaries become newline characters.
Inherits
method input_eor : unit -> unit
Skips over the remaining data of the current record and the record boundary to the next record. Raises End_of_file when the current record is the "EOF" record (see below for explanations).

A record channel can be read as follows: After opening the channel, one can read the contents of the first record with the input method. The end of the record is indicated by an End_of_file exception. By calling input_eor, the next record is opened and can be read.

After the last real record, there is always a special "EOF" record which is empty, and must be ignored by applications processing records. This means, after opening an empty channel, the current record is this "EOF" record, and input_eor raises End_of_file. After reading a non-empty channel, one can do input_eor after the last regular record, and the following input_eor raises End_of_file.

ocamlnet-4.1.2/doc/html-main/Nethttp_client.basic_auth_handler-c.html0000644000175000017500000004506712731530353024305 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.basic_auth_handler

Class Nethttp_client.basic_auth_handler

class basic_auth_handler : ?enable_reauth:bool -> ?skip_challenge:bool -> #key_handler -> auth_handler
Basic authentication. Authentication information is obtained by the passed key_handler. Note that basic authentication is insecure and should only be run over TLS. But even then, the server obtains the password in clear. Use other methods if possible.

enable_reauth: If set to true, a quicker authentication mode is enabled: when a request is sent out, it is checked whether a previous request/response cycle exists that needed authentication. If so, the same credentials are added to the request. Normally, the request would be sent without credentials first, and only after getting the authentication challenge the request is resent with the credentials. Reauthentication is only done for the same realm and the same domain. The path of the request URI, however, may be different.

skip_challenge: This option enables a mode so that the credentials are added to HTTP requests even before any response has been seen by the server. This adds additional security risks, and may cause that credentials are sent to servers that forge their identity. As no challenge is known, the realm string is simply assumed to be "anywhere".


ocamlnet-4.1.2/doc/html-main/type_Rpc_portmapper_clnt.Make'PMAP.V2.html0000644000175000017500000005600112731530353024236 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt.Make'PMAP.V2 sig
  type t = U'C.t
  val _program : Rpc_program.t
  val pmapproc_null :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res
  val pmapproc_null'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res) -> unit) ->
    unit
  val pmapproc_set :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res
  val pmapproc_set'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res) -> unit) -> unit
  val pmapproc_unset :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res
  val pmapproc_unset'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res) -> unit) ->
    unit
  val pmapproc_getport :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res
  val pmapproc_getport'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res) -> unit) ->
    unit
  val pmapproc_dump :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res
  val pmapproc_dump'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res) -> unit) ->
    unit
  val pmapproc_callit :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res
  val pmapproc_callit'async :
    U'C.t ->
    Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg ->
    ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res) -> unit) ->
    unit
end
ocamlnet-4.1.2/doc/html-main/type_Netgzip.input_gzip.html0000644000175000017500000004074412731530353022150 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgzip.input_gzip Gzip.in_channel -> Netchannels.in_obj_channelocamlnet-4.1.2/doc/html-main/Netx509_pubkey_crypto.html0000644000175000017500000005215212731530353021427 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey_crypto

Module Netx509_pubkey_crypto

module Netx509_pubkey_crypto: sig .. end
X.509 public key cryptography - wrappers


This module uses the current cryptography provider to actually run operations.

Note that typically not all encryption and signing schemes are implemented. For instance, GnuTLS only provides those schemes that are needed for TLS (so far RSA for encryption, and RSA/DSA/ECDSA for signing). Also note that we require GnuTLS-3.0 or newer for public key cryptography.

exception Unsupported_algorithm of Netoid.t
Raises if the crypto backend does not support an algorithm
val is_encryption_supported : Netx509_pubkey.encrypt_alg -> bool
Whether this algorithm is supported
val is_signing_supported : Netx509_pubkey.sign_alg -> bool
Whether this algorithm is supported
val encrypt : Netx509_pubkey.encrypt_alg -> Netx509_pubkey.pubkey -> string -> string
Encrypt the string.

Note that length restrictions apply, depending on the algorithm and the bit size of the key. For instance, with a 2048-bit RSA key you can at most encrypt 245 bytes.

val decrypt : Netx509_pubkey.encrypt_alg -> Netx509_pubkey.privkey -> string -> string
Decrypt the string
val verify : Netx509_pubkey.sign_alg -> Netx509_pubkey.pubkey -> string -> string -> bool
verify alg key plaintext signature: Checks the signature, and returns true on success.
val sign : Netx509_pubkey.sign_alg -> Netx509_pubkey.privkey -> string -> string
let signature = sign alg key plaintext: Creates a signature.

Unlike for encryption there is no length restriction.


Example: Using RSA for encryption

First create RSA keys:

openssl genrsa -out rsa.key 2048
openssl rsa -in rsa.key -pubout -out rsa.pub

Read the keys in:

let priv_ch = Netchannels.input_channel(open_in "rsa.key")
let priv = Netx509_pubkey.read_privkey_from_pem priv_ch
let () = priv_ch#close_in()

let pub_ch = Netchannels.input_channel(open_in "rsa.pub")
let pub = Netx509_pubkey.read_pubkey_from_pem pub_ch
let () = pub_ch#close_in()

Encrypt something:

let () = Nettls_gnutls.init()
let e = encrypt Netx509_pubkey.Encryption.rsa pub "secret"

Decrypt:

let d = decrypt Netx509_pubkey.Encryption.rsa priv e

Note that encryption with public keys is restricted to very short messages (e.g. 245 bytes for a 2048 bits RSA key). Typically, only a random second key is encrypted, and the second key is used with a symmetric cipher.
ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.sender.html0000644000175000017500000004155012731530353022105 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.sender src:#Uq_transfer.async_in_channel ->
dst:Unix.file_descr ->
?close_src:bool ->
?close_dst:bool -> Unixqueue.event_system -> [unit] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.http_engine_processing_context.html0000644000175000017500000004105212731530353027754 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_engine_processing_context object method engine : unit Uq_engines.engine endocamlnet-4.1.2/doc/html-main/type_Netencoding.Base64.encoding_pipe.html0000644000175000017500000004126112731530353024416 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Base64.encoding_pipe ?linelength:int ->
?crlf:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipe
ocamlnet-4.1.2/doc/html-main/Netfs.stream_fs-c.html0000644000175000017500000006770012731530353020562 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netfs.stream_fs

Class type Netfs.stream_fs

class type stream_fs = object .. end

method path_encoding : Netconversion.encoding option
The encoding must be ASCII-compatible (Netconversion.is_ascii_compatible). If None the ASCII encoding is assumed for codes 0-127, and no meaning is defined for byte codes 128-255.
method path_exclusions : (int * int) list
Code points that must not occur in path components between slashes. This is given as ranges (from,to). The code points are interpreted as Unicode code points if an encoding is available, and as byte codes otherwise. For example, for Unix the code points 0 and 47 (slash) are normally the only excluded code points.
method nominal_dot_dot : bool
Whether the effect of .. can be obtained by stripping off the last path component, i.e. whether Filename.dirname path <=> path ^ "/.."
method read : read_flag list -> string -> Netchannels.in_obj_channel
read flags filename: Opens the file filename for reading, and returns the input stream. Flags:
  • `Skip n: Skips the first n bytes of the file. On many filesystems this is more efficient than reading n bytes and dropping them; however, there is no guarantee that this optimization exists.
  • `Binary: Opens the file in binary mode (if there is such a distinction)
  • `Streaming for network filesystems: If possible, open the file in streaming mode, and avoid to copy the whole file to the local disk before returning the Netchannels.in_obj_channel. Streaming mode is faster, but has also downsides. Especially, the implementation of read can do less to recover from transient network problems (like retrying the whole download). Support for this flag is optional, and it is ignored if there is no extra streaming mode.

method read_file : read_file_flag list -> string -> local_file
read_file flags filename: Opens the file filename for reading, and returns the contents as a local_file. Use the method filename to get the file name of the local file. The file may be temporary, but this is not required. The method close of the returned object should be called when the file is no longer needed. In case of a temporary file, the file can then be deleted. Flags:
  • `Binary: Opens the file in binary mode (if there is such a distinction)

method write : write_flag list -> string -> Netchannels.out_obj_channel
write flags filename: Opens (and optionally creates) the filename for writing, and returns the output stream. Flags:
  • `Create: If the file does not exist, create it
  • `Truncate: If the file exists, truncate it to zero before writing
  • `Exclusive: The `Create is done exclusively
  • `Binary: Opens the file in binary mode (if there is such a distinction)
  • `Streaming: see read (above) for explanations
Some filesystems refuse this operation if neither `Create nor `Truncate is specified because overwriting an existing file is not supported. There are also filesystems that cannot even modify files by truncating them first, but only allow to write to new files.

It is unspecified whether the file appears in the directory directly after calling write or first when the stream is closed.

method write_file : write_file_flag list -> string -> local_file -> unit
write_file flags filename localfile: Opens the file filename for writing, and copies the contents of the localfile to it. It is ensured that the method close of localfile is called once the operation is finished (whether successful or not). Flags:
  • `Create: If the (remote) file does not exist, create it
  • `Truncate: If the file exists, truncate it to zero before writing
  • `Exclusive: The `Create is done exclusively
  • `Binary: Opens the file in binary mode (if there is such a distinction)
  • `Link: Allows that the destination file is created as a hard link of the original file. This is tried whatever other mode is specified. If not successful, a copy is done instead.

method size : size_flag list -> string -> int64
Returns the size of a file. Note that there is intentionally no distinction between text and binary mode - implementations must always assume binary mode.
method test : test_flag list -> string -> test_type -> bool
Returns whether the test is true. For filesystems that know symbolic links, the test operation normally follows symlinks (except for the `N and `H tests). By specifying the `Link flag symlinks are not followed.
method test_list : test_flag list -> string -> test_type list -> bool list
Similar to test but this function performs all tests in the list at once, and returns a bool for each test.
method remove : remove_flag list -> string -> unit
Removes the file or symlink. Implementation are free to also support the removal of empty directories.

Flags:

  • `Recursive: Remove the contents of the non-empty directory recursively. This is an optional feature. There needs not to be any protection against operations done by other processes that affect the directory tree being deleted.

method rename : rename_flag list -> string -> string -> unit
Renames the file. There is no guarantee that a rename is atomic
method symlink : symlink_flag list -> string -> string -> unit
symlink flags oldpath newpath: Creates a symlink. This is an exclusive create, i.e. the operation fails if newpath already exists.
method readdir : readdir_flag list -> string -> string list
Reads the contents of a directory. Whether "." and ".." are returned is platform-dependent. The entries can be returned in any order.
method readlink : readlink_flag list -> string -> string
Reads the target of a symlink
method mkdir : mkdir_flag list -> string -> unit
Creates a new directory. Flags:
  • `Path: Creates missing parent directories. This is an optional feature. (If not supported, ENOENT is reported.)
  • `Nonexcl: Non-exclusive create.

method rmdir : rmdir_flag list -> string -> unit
Removes an empty directory
method copy : copy_flag list -> string -> string -> unit
Copies a file to a new name. This does not descent into directories. Also, symlinks are resolved, and the linked file is copied.
method cancel : unit -> unit
Cancels any ongoing write. The user must also call the close_out method after cancelling. The effect is that after the close no more network activity will occur.
ocamlnet-4.1.2/doc/html-main/type_Uq_resolver.engine.html0000644000175000017500000004250512731530353022110 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_resolver.engine object
  method abort : unit -> unit
  method event_system : Unixqueue.event_system
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : ('Uq_resolver.engine -> bool) -> unit
  method state : 'Uq_resolver.engine_state
end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.digest_auth_handler-c.html0000644000175000017500000004376212731530353024503 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.digest_auth_handler

Class Nethttp_client.digest_auth_handler

class digest_auth_handler : #key_handler -> auth_handler
Digest authentication. Authentication information is obtained by the passed key_handler.

This handler is compatible with RFCs 2069, 2617 and 7616. In particular, the following protocol options are available:

  • The algorithms MD5, MD5-sess, SHA256 and SHA256-sess are implemented
  • The quality of protection mode "auth" is implemented. The optional mode "auth-int" has been omitted.
  • The information of the Authentication-Info header is completely ignored
This handler is implemented on top of Netmech_digest_http.Digest.

ocamlnet-4.1.2/doc/html-main/type_Netmech_digest_http.Digest_mutual.html0000644000175000017500000004066512731530354025132 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_digest_http.Digest_mutual Nethttp.HTTP_CLIENT_MECHANISMocamlnet-4.1.2/doc/html-main/type_Uq_engines.html0000644000175000017500000025001612731530354020432 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines sig
  exception Closed_channel
  exception Broken_communication
  exception Watchdog_timeout
  exception Timeout
  exception Addressing_method_not_supported
  exception Cancelled
  type 't engine_state =
      [ `Aborted | `Done of '| `Error of exn | `Working of int ]
  type 't final_state = [ `Aborted | `Done of '| `Error of exn ]
  val string_of_state : 'Uq_engines.engine_state -> string
  class type ['t] engine =
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        ('Uq_engines.engine -> bool) -> unit
      method state : 'Uq_engines.engine_state
    end
  class ['t] delegate_engine : '#Uq_engines.engine -> ['t] engine
  val when_state :
    ?is_done:('-> unit) ->
    ?is_error:(exn -> unit) ->
    ?is_aborted:(unit -> unit) ->
    ?is_progressing:(int -> unit) -> '#Uq_engines.engine -> unit
  class ['a] signal_engine :
    Unixqueue.event_system ->
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification : ('a engine -> bool) -> unit
      method signal : 'Uq_engines.final_state -> unit
      method state : 'a engine_state
    end
  val signal_engine :
    Unixqueue.event_system ->
    'Uq_engines.engine * ('Uq_engines.final_state -> unit)
  class ['a, 'b] map_engine :
    map_done:('-> 'Uq_engines.engine_state) ->
    ?map_error:(exn -> 'Uq_engines.engine_state) ->
    ?map_aborted:(unit -> 'Uq_engines.engine_state) ->
    ?propagate_working:bool -> '#Uq_engines.engine -> ['b] engine
  val map_engine :
    map_done:('-> 'Uq_engines.engine_state) ->
    ?map_error:(exn -> 'Uq_engines.engine_state) ->
    ?map_aborted:(unit -> 'Uq_engines.engine_state) ->
    ?propagate_working:bool -> '#Uq_engines.engine -> 'Uq_engines.engine
  class ['a, 'b] fmap_engine :
    '#Uq_engines.engine ->
    ('Uq_engines.final_state -> 'Uq_engines.final_state) -> ['b] engine
  val fmap_engine :
    '#Uq_engines.engine ->
    ('Uq_engines.final_state -> 'Uq_engines.final_state) ->
    'Uq_engines.engine
  class ['a] meta_engine :
    '#Uq_engines.engine -> ['Uq_engines.final_state] engine
  val meta_engine :
    '#Uq_engines.engine -> 'Uq_engines.final_state Uq_engines.engine
  class ['t] epsilon_engine :
    'Uq_engines.engine_state -> Unixqueue.event_system -> ['t] engine
  val epsilon_engine :
    'Uq_engines.engine_state ->
    Unixqueue.event_system -> 'Uq_engines.engine
  class ['a, 'b] seq_engine :
    '#Uq_engines.engine -> ('-> '#Uq_engines.engine) -> ['b] engine
  val seq_engine :
    '#Uq_engines.engine ->
    ('-> '#Uq_engines.engine) -> 'Uq_engines.engine
  class ['a, 'b] qseq_engine :
    '#Uq_engines.engine -> ('-> '#Uq_engines.engine) -> ['b] engine
  val qseq_engine :
    '#Uq_engines.engine ->
    ('-> '#Uq_engines.engine) -> 'Uq_engines.engine
  class ['a] stream_seq_engine :
    '->
    ('-> '#Uq_engines.engine) Stream.t ->
    Unixqueue.event_system -> ['a] engine
  val stream_seq_engine :
    '->
    ('-> '#Uq_engines.engine) Stream.t ->
    Unixqueue.event_system -> 'Uq_engines.engine
  class ['a, 'b] sync_engine :
    '#Uq_engines.engine -> '#Uq_engines.engine -> ['a * 'b] engine
  val sync_engine :
    '#Uq_engines.engine ->
    '#Uq_engines.engine -> ('a * 'b) Uq_engines.engine
  class ['a, 'b] msync_engine :
    '#Uq_engines.engine list ->
    ('-> '-> 'b) -> '-> Unixqueue.event_system -> ['b] engine
  val msync_engine :
    '#Uq_engines.engine list ->
    ('-> '-> 'b) -> '-> Unixqueue.event_system -> 'Uq_engines.engine
  class ['a] delay_engine :
    float ->
    (unit -> '#Uq_engines.engine) -> Unixqueue.event_system -> ['a] engine
  val delay_engine :
    float ->
    (unit -> '#Uq_engines.engine) ->
    Unixqueue.event_system -> 'Uq_engines.engine
  class ['a] timeout_engine :
    float -> exn -> 'Uq_engines.engine -> ['a] engine
  val timeout_engine :
    float -> exn -> 'Uq_engines.engine -> 'Uq_engines.engine
  class watchdog : float -> '#Uq_engines.engine -> [unit] engine
  val watchdog : float -> '#Uq_engines.engine -> unit Uq_engines.engine
  class type ['a] serializer_t =
    object
      method serialized :
        (Unixqueue.event_system -> 'Uq_engines.engine) ->
        'Uq_engines.engine
    end
  class ['a] serializer : Unixqueue.event_system -> ['a] serializer_t
  val serializer : Unixqueue.event_system -> 'Uq_engines.serializer_t
  class type ['a] prioritizer_t =
    object
      method prioritized :
        (Unixqueue.event_system -> 'Uq_engines.engine) ->
        int -> 'Uq_engines.engine
    end
  class ['a] prioritizer : Unixqueue.event_system -> ['a] prioritizer_t
  val prioritizer : Unixqueue.event_system -> 'Uq_engines.prioritizer_t
  class type ['a] cache_t =
    object
      method abort : unit -> unit
      method get_engine : unit -> 'Uq_engines.engine
      method get_opt : unit -> 'a option
      method invalidate : unit -> unit
      method put : '-> unit
    end
  class ['a] cache :
    (Unixqueue.event_system -> 'Uq_engines.engine) ->
    Unixqueue.event_system -> ['a] cache_t
  val cache :
    (Unixqueue.event_system -> 'Uq_engines.engine) ->
    Unixqueue.event_system -> 'Uq_engines.cache_t
  class ['t] engine_mixin :
    'Uq_engines.engine_state ->
    Unixqueue.event_system ->
    object
      method event_system : Unixqueue.event_system
      method private notify : unit -> unit
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        ('Uq_engines.engine -> bool) -> unit
      method private set_state : 'Uq_engines.engine_state -> unit
      method state : 'Uq_engines.engine_state
    end
  module Operators :
    sig
      val ( ++ ) :
        '#Uq_engines.engine ->
        ('-> '#Uq_engines.engine) -> 'Uq_engines.engine
      val ( >> ) :
        '#Uq_engines.engine ->
        ('Uq_engines.final_state -> 'Uq_engines.final_state) ->
        'Uq_engines.engine
      val eps_e :
        'Uq_engines.engine_state ->
        Unixqueue.event_system -> 'Uq_engines.engine
    end
  class poll_engine :
    ?extra_match:(exn -> bool) ->
    (Unixqueue.operation * float) list ->
    Unixqueue.event_system ->
    object
      method abort : unit -> unit
      method event_system : Unixqueue.event_system
      method group : Unixqueue.group
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification :
        (Unixqueue.event engine -> bool) -> unit
      method restart : unit -> unit
      method state : Unixqueue.event engine_state
    end
  class ['a] input_engine :
    (Unix.file_descr -> 'a) ->
    Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
  class ['a] output_engine :
    (Unix.file_descr -> 'a) ->
    Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine
  class poll_process_engine :
    ?period:float ->
    pid:int -> Unixqueue.event_system -> [Unix.process_status] engine
  class type async_out_channel =
    object
      method can_output : bool
      method close_out : unit -> unit
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method pos_out : int
      method request_notification : (unit -> bool) -> unit
    end
  class type async_in_channel =
    object
      method can_input : bool
      method close_in : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method pos_in : int
      method request_notification : (unit -> bool) -> unit
    end
  class type async_out_channel_engine =
    object
      method abort : unit -> unit
      method can_output : bool
      method close_out : unit -> unit
      method event_system : Unixqueue.event_system
      method flush : unit -> unit
      method output : Bytes.t -> int -> int -> int
      method pos_out : int
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification : (unit engine -> bool) -> unit
      method state : unit engine_state
    end
  type copy_task =
      [ `Bidirectional of Unix.file_descr * Unix.file_descr
      | `Tridirectional of
          Unix.file_descr * Unix.file_descr * Unix.file_descr
      | `Uni_socket of Unix.file_descr * Unix.file_descr
      | `Unidirectional of Unix.file_descr * Unix.file_descr ]
  class type async_in_channel_engine =
    object
      method abort : unit -> unit
      method can_input : bool
      method close_in : unit -> unit
      method event_system : Unixqueue.event_system
      method input : Bytes.t -> int -> int -> int
      method pos_in : int
      method request_notification : (unit -> bool) -> unit
      method request_proxy_notification : (unit engine -> bool) -> unit
      method state : unit engine_state
    end
  class type multiplex_controller =
    object
      method alive : bool
      method cancel_reading : unit -> unit
      method cancel_shutting_down : unit -> unit
      method cancel_writing : unit -> unit
      method event_system : Unixqueue.event_system
      method inactivate : unit -> unit
      method mem_supported : bool
      method read_eof : bool
      method reading : bool
      method shutting_down : bool
      method start_mem_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_mem_writing :
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_shutting_down :
        ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
      method start_writing :
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_writing_eof :
        when_done:(exn option -> unit) -> unit -> unit
      method supports_half_open_connection : bool
      method tls_session : (string * string) option
      method tls_session_props : Nettls_support.tls_session_props option
      method tls_stashed_endpoint : unit -> exn
      method writing : bool
      method wrote_eof : bool
    end
  exception Mem_not_supported
  class type datagram_multiplex_controller =
    object
      method alive : bool
      method cancel_reading : unit -> unit
      method cancel_shutting_down : unit -> unit
      method cancel_writing : unit -> unit
      method event_system : Unixqueue.event_system
      method inactivate : unit -> unit
      method mem_supported : bool
      method read_eof : bool
      method reading : bool
      method received_from : Unix.sockaddr
      method send_to : Unix.sockaddr -> unit
      method shutting_down : bool
      method start_mem_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_mem_writing :
        when_done:(exn option -> int -> unit) ->
        Netsys_mem.memory -> int -> int -> unit
      method start_reading :
        ?peek:(unit -> unit) ->
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_shutting_down :
        ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
      method start_writing :
        when_done:(exn option -> int -> unit) ->
        Bytes.t -> int -> int -> unit
      method start_writing_eof :
        when_done:(exn option -> unit) -> unit -> unit
      method supports_half_open_connection : bool
      method tls_session : (string * string) option
      method tls_session_props : Nettls_support.tls_session_props option
      method tls_stashed_endpoint : unit -> exn
      method writing : bool
      method wrote_eof : bool
    end
  type onshutdown_out_spec =
      [ `Action of
          Uq_engines.async_out_channel_engine ->
          Uq_engines.multiplex_controller ->
          unit Uq_engines.engine_state -> unit
      | `Ignore
      | `Initiate_shutdown ]
  type onshutdown_in_spec =
      [ `Action of
          Uq_engines.async_in_channel_engine ->
          Uq_engines.multiplex_controller ->
          unit Uq_engines.engine_state -> unit
      | `Ignore
      | `Initiate_shutdown ]
  type inetspec =
      [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
      | `Sock_inet_byname of Unix.socket_type * string * int ]
  type sockspec =
      [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
      | `Sock_inet_byname of Unix.socket_type * string * int
      | `Sock_unix of Unix.socket_type * string ]
  type connect_address =
      [ `Command of string * (int -> Unixqueue.event_system -> unit)
      | `Socket of Uq_engines.sockspec * Uq_engines.connect_options
      | `W32_pipe of Netsys_win32.pipe_mode * string ]
  and connect_options = { conn_bind : Uq_engines.sockspec option; }
  type connect_status =
      [ `Command of Unix.file_descr * int
      | `Socket of Unix.file_descr * Uq_engines.sockspec
      | `W32_pipe of Unix.file_descr ]
  class type client_endpoint_connector =
    object
      method connect :
        Uq_engines.connect_address ->
        Unixqueue.event_system -> Uq_engines.connect_status Uq_engines.engine
    end
  type listen_address =
      [ `Socket of Uq_engines.sockspec * Uq_engines.listen_options
      | `W32_pipe of
          Netsys_win32.pipe_mode * string * Uq_engines.listen_options ]
  and listen_options = { lstn_backlog : int; lstn_reuseaddr : bool; }
  class type server_endpoint_acceptor =
    object
      method accept :
        unit ->
        (Unix.file_descr * Uq_engines.inetspec option) Uq_engines.engine
      method multiple_connections : bool
      method server_address : Uq_engines.connect_address
      method shut_down : unit -> unit
    end
  class type server_endpoint_listener =
    object
      method listen :
        Uq_engines.listen_address ->
        Unixqueue.event_system ->
        Uq_engines.server_endpoint_acceptor Uq_engines.engine
    end
  type datagram_type = [ `Inet6_udp | `Inet_udp | `Unix_dgram ]
  class type wrapped_datagram_socket =
    object
      method datagram_type : Uq_engines.datagram_type
      method descriptor : Unix.file_descr
      method recvfrom :
        Bytes.t ->
        int -> int -> Unix.msg_flag list -> int * Uq_engines.sockspec
      method sendto :
        Bytes.t ->
        int -> int -> Unix.msg_flag list -> Uq_engines.sockspec -> int
      method shut_down : unit -> unit
      method socket_domain : Unix.socket_domain
      method socket_protocol : int
      method socket_type : Unix.socket_type
    end
  class type datagram_socket_provider =
    object
      method create_datagram_socket :
        Uq_engines.datagram_type ->
        Unixqueue.event_system ->
        Uq_engines.wrapped_datagram_socket Uq_engines.engine
    end
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Netsys_posix.post_fork_handler-c.html0000644000175000017500000004236212731530354023730 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_posix.post_fork_handler

Class type Netsys_posix.post_fork_handler

class type post_fork_handler = object .. end
A post_fork_handler is a named function unit -> unit

method name : string
method run : unit -> unit
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.poll_process_engine.html0000644000175000017500000004125612731530354026031 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.poll_process_engine ?period:float ->
pid:int ->
Unixqueue.event_system -> [Unix.process_status] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/Netmime.html0000644000175000017500000007151112731530354016673 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime

Module Netmime

module Netmime: sig .. end
Netmime contains high-level classes and functions to process mail and MIME messages.

Contents

The tutorial has been moved to Netmime_tut. Parsers for MIME headers are now in Netmime_header. Parser and printers for MIME channels are now in Netmime_channels.


Types


type store = [ `File of string | `Memory ] 
Specifies where to store the body of a mail message. `Memory means in-memory, `File name means in the file name. The body is stored in decoded form (i.e. without transfer encoding).
exception Immutable of string
Raised if it is tried to modify a read-only value. The string denotes the function or method where the incident happened.

MIME headers and bodies are defined in two steps. First the subtype describing read access is defined (mime_header_ro, and mime_body_ro), and after that the full class type including write access is defined (mime_header, and mime_body).

The idea is that you can write functions that take an ro value as input to indicate that they do not modify the value. For example:

 let number_of_fields (h:#mime_header_ro) =
   List.length (h#fields) 

This function accepts both mime_header, and mime_header_ro values as input, but the typing ensures that the function cannot mutate anything.

There is another way to ensure that a header or body is not modified. The read-only flag can be set when creating the object, and this flag causes that all trials to modify the value will raise the exception Immutable. Of course, such trials of mutation are only detected at run-time.

The advantage of the read-only flag is that it even works if mutation depends on a condition, but it can be ensured that this condition is never true. Furthermore, typing is much simpler (getting subtyping correct can be annoying).

class type mime_header_ro = object .. end
This is the read-only version of a MIME header.
class type mime_header = object .. end
A MIME header with both read and write method.
class type mime_body_ro = object .. end
This is the read-only version of a MIME body.
class type mime_body = object .. end
A MIME body with both read and write method.

One can consider the pair (mime_header, mime_body) as simple MIME message with one header and one body. Of course, this simple representation does not support multi-part messages (attachments). For that reason, the complex_mime_message was invented: The body can be further structured as a sequence of parts that are complex messages themselves.

For example, a mail message with an attachment is usually represented as

 (mail_header, `Parts [ (main_header, `Body main_body);
                        (att_header, `Body att_body) ] ) 

Here, mail_header is the real header of the mail message. main_header is the header of the main message, usually only containing the content type of main_body, the body of the main message. The attachment has also its own att_header, again usually only containing the content type, and the data of the attachment can be found in att_body.

Nowadays, mails have often even a more complicated structure with `Parts containing nested `Parts. As complex_mime_message is recursive, any kind of nesting can be easily represented.

type complex_mime_message = mime_header * complex_mime_body 
type complex_mime_body = [ `Body of mime_body | `Parts of complex_mime_message list ] 
type complex_mime_message_ro = mime_header_ro * complex_mime_body_ro 
type complex_mime_body_ro = [ `Body of mime_body_ro
| `Parts of complex_mime_message_ro list ]
The read-only view of a complex_mime_message

Note: `Parts [], i.e. `Parts together with an empty list, is considered as illegal. Such a value cannot be transformed into printable text.
type mime_message = mime_header * [ `Body of mime_body ] 
Simple MIME message, in a form that is compatible with complex ones.
type mime_message_ro = mime_header_ro * [ `Body of mime_body_ro ] 
Read-only variant of simple messages

Classes


class basic_mime_header : (string * string) list -> mime_header
An implementation of mime_header.
val basic_mime_header : (string * string) list -> mime_header
Same as function
class wrap_mime_header : #mime_header -> mime_header
Wraps the inner header
class wrap_mime_header_ro : #mime_header_ro -> mime_header
Wraps the inner header but disallows modifications.
val wrap_mime_header_ro : #mime_header_ro -> mime_header
Same as function
class memory_mime_body : string -> mime_body
An implementation of mime_body where the value is stored in-memory.
val memory_mime_body : string -> mime_body
Same as function
class file_mime_body : ?fin:bool -> string -> mime_body
An implementation of mime_body where the value is stored in an external file.
val file_mime_body : ?fin:bool -> string -> mime_body
Same as function
class wrap_mime_body : #mime_body -> mime_body
Wraps the inner body
class wrap_mime_body_ro : #mime_body_ro -> mime_body
Wraps the inner body but disallows modifications.
val wrap_mime_body_ro : #mime_body_ro -> mime_body
Same as function
val wrap_complex_mime_message_ro : complex_mime_message_ro -> complex_mime_message
ocamlnet-4.1.2/doc/html-main/type_Rpc_client.auth_session.html0000644000175000017500000004425112731530354023124 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.auth_session object
  method auth_protocol : Rpc_client.auth_protocol
  method next_credentials :
    Rpc_client.t ->
    Rpc_program.t ->
    string ->
    Netnumber.uint4 ->
    string * string * string * string * Netxdr.encoder option *
    Netxdr.decoder option
  method server_accepts :
    Rpc_client.t -> Netnumber.uint4 -> string -> string -> unit
  method server_rejects :
    Rpc_client.t ->
    Netnumber.uint4 -> Rpc.server_error -> Rpc_client.reject_code
end
ocamlnet-4.1.2/doc/html-main/type_Netstring_pcre.html0000644000175000017500000006546512731530354021337 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstring_pcre sig
  type regexp = Pcre.regexp
  type split_result =
    Pcre.split_result =
      Text of string
    | Delim of string
    | Group of int * string
    | NoGroup
  type result
  val regexp : string -> Netstring_pcre.regexp
  val regexp_case_fold : string -> Netstring_pcre.regexp
  val quote : string -> string
  val regexp_string : string -> Netstring_pcre.regexp
  val regexp_string_case_fold : string -> Netstring_pcre.regexp
  val string_match :
    Netstring_pcre.regexp -> string -> int -> Netstring_pcre.result option
  val bytes_match :
    Netstring_pcre.regexp -> Bytes.t -> int -> Netstring_pcre.result option
  val search_forward :
    Netstring_pcre.regexp -> string -> int -> int * Netstring_pcre.result
  val search_forward_bytes :
    Netstring_pcre.regexp -> Bytes.t -> int -> int * Netstring_pcre.result
  val search_backward :
    Netstring_pcre.regexp -> string -> int -> int * Netstring_pcre.result
  val search_backward_bytes :
    Netstring_pcre.regexp -> Bytes.t -> int -> int * Netstring_pcre.result
  val matched_string : Netstring_pcre.result -> string -> string
  val matched_bytes : Netstring_pcre.result -> Bytes.t -> Bytes.t
  val match_beginning : Netstring_pcre.result -> int
  val match_end : Netstring_pcre.result -> int
  val matched_group : Netstring_pcre.result -> int -> string -> string
  val matched_group_bytes :
    Netstring_pcre.result -> int -> Bytes.t -> Bytes.t
  val group_beginning : Netstring_pcre.result -> int -> int
  val group_end : Netstring_pcre.result -> int -> int
  val global_replace : Netstring_pcre.regexp -> string -> string -> string
  val replace_first : Netstring_pcre.regexp -> string -> string -> string
  val global_substitute :
    Netstring_pcre.regexp ->
    (Netstring_pcre.result -> string -> string) -> string -> string
  val substitute_first :
    Netstring_pcre.regexp ->
    (Netstring_pcre.result -> string -> string) -> string -> string
  val split : Netstring_pcre.regexp -> string -> string list
  val bounded_split : Netstring_pcre.regexp -> string -> int -> string list
  val split_delim : Netstring_pcre.regexp -> string -> string list
  val bounded_split_delim :
    Netstring_pcre.regexp -> string -> int -> string list
  val full_split :
    Netstring_pcre.regexp -> string -> Netstring_pcre.split_result list
  val bounded_full_split :
    Netstring_pcre.regexp ->
    string -> int -> Netstring_pcre.split_result list
  val string_before : string -> int -> string
  val string_after : string -> int -> string
  val first_chars : string -> int -> string
  val last_chars : string -> int -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_plex.html0000644000175000017500000005422112731530354020576 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_plex sig
  val factory :
    ?config:Netcgi.config ->
    ?enable:[ `AJP | `FCGI | `SCGI ] list ->
    ?name:string ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?exn_handler:Netcgi.exn_handler ->
    ?configure:(Netplex_types.config_file ->
                Netplex_types.address -> Netplex_types.processor_hooks) ->
    (Netplex_types.container -> Netcgi.cgi -> unit) ->
    Netplex_types.processor_factory
  type mountpoint = [ `Mount_at of string | `Mount_dir of string ]
  val fcgi_processor :
    ?config:Netcgi.config ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?exn_handler:Netcgi.exn_handler ->
    ?timeout:float ->
    ?mount:Netcgi_plex.mountpoint ->
    (Netplex_types.container -> Netcgi_fcgi.cgi -> unit) ->
    Netplex_types.processor
  val scgi_processor :
    ?config:Netcgi.config ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?exn_handler:Netcgi.exn_handler ->
    ?timeout:float ->
    ?mount:Netcgi_plex.mountpoint ->
    (Netplex_types.container -> Netcgi.cgi -> unit) ->
    Netplex_types.processor
  val ajp_processor :
    ?config:Netcgi.config ->
    ?output_type:Netcgi.output_type ->
    ?arg_store:Netcgi.arg_store ->
    ?exn_handler:Netcgi.exn_handler ->
    ?timeout:float ->
    ?mount:Netcgi_plex.mountpoint ->
    (Netplex_types.container -> Netcgi.cgi -> unit) ->
    Netplex_types.processor
end
ocamlnet-4.1.2/doc/html-main/Rpc_intro_gss.html0000644000175000017500000011312012731530354020101 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_intro_gss

Rpc_intro_gss


Securing RPC with the GSSAPI

This text explains how to enable strong authentication and strong encryption on RPC connections.

The GSSAPI

The GSSAPI (Generic Security Service API) is an interface between the security provider (i.e. the authentication/encryption provider) and the application needing security features. The GSSAPI is a standard (RFC 2743). The GSSAPI is often already implemented by operating systems or by security systems like Kerberos. This means, there is usually a library on the C level containing the C functions defining GSSAPI.

The nice thing about GSSAPI is the mechanism genericy: The API can provide access to multiple security mechanisms, and it is possible to wrap almost every security mechanism in the form of GSSAPI.

As mentioned, GSSAPI only covers the encryption and integrity protection of messages, not of continuous streams. In so far there is not much intersection with SSL, which only handles such streams. For message-oriented protocols such as RPC the feature set of GSSAPI is naturally the better choice. There is a standard called RPCSEC-GSS defining the details of how GSSAPI is to be used for ONCRPC (RFC 2203).

There is a more general introduction to the GSSAPI in this chapter: Gssapi.

The GSSAPI in Ocaml

The GSSAPI is defined as a class type Netsys_gssapi.gss_api. We do not want to go much into detail - for using the GSSAPI it is not required to understand everything. The class type is "feature compatible" with the standard C version of the API (RFC 2744) allowing it to interface with implementations of GSSAPI available in C. (Note that this has not been done when this text is written.)

A class type has been chosen because this allows it that each security provider can define an independent class implementing the GSSAPI. This is different than in the C bindings of GSSAPI where only one provider can exist at a time (linked into the program), although the provider can manage several mechanisms.

When using GSSAPI you will be confronted with OIDs, names, and credentials. These concepts are defined in the Netsys_gssapi module:

  • An OID (object identifier) is a IANA-registered number helping to identify especially security mechanisms, and styles of naming principals (user and system identities). OIDs are also used in other contexts (e.g. ASN-1, X500).
  • Names come in various forms, and because of this, GSSAPI uses opaque objects for names, not strings. Names can e.g. identify users. There are various styles (name types). For example, users are often identified by a simple string ("guest") whereas service names also include the host name where the service runs ("emailserver@machine"). As names are opaque, they can be imported from a string representation to the opaque object and they can be converted back to strings.
  • Credentials are pieces of information allowing the security mechanism to check whether a connected participant has actually a certain name. A simple example is a password.
OIDs are represented as oid = int array. There are a number of predefined OIDs, e.g.

An empty array is often used to mean the default (e.g. default mechanism).

Names are represented as Netsys_gssapi.name. This object has almost no methods - which is intended because names are opaque to users outside the GSSAPI implementation. The GSSAPI defines methods to import and export names:

  • Netsys_gssapi.gss_api.import_name allows one to convert a pair of a name type and a string to the opaque Netsys_gssapi.name object. The name type is an OID.
  • Netsys_gssapi.gss_api.display_name is roughly the reverse operation (but see below).
  • Netsys_gssapi.gss_api.export_name converts an opaque name to a binary string. It is ensured that another call of import_name with the same string restores the opaque name.
Note that, at least for certain security mechanisms, there may be several ways of writing the name of a principal, or there might be naming elements spanning several mechanisms. This is an issue when names need to be compared. Generally, it may lead to wrong results when names are compared by displaying or exporting them, and then comparing the resulting strings. There is a special Netsys_gssapi.gss_api.compare_name method for comparisons, and Netsys_gssapi.gss_api.canonicalize_name may also be useful in this context.

For RPC, the ways of referring to names have been simplified - more on that below.

Credentials are also opaque objects - Netsys_gssapi.credential. It is generally assumed that a GSSAPI implementation can look up the right credentials for a principal that is identified by name. For example, the GSSAPI provider for SCRAM can be equipped with a "keyring", i.e. a callback that maps user names to passwords.

SCRAM

SCRAM (Salted Challenge Response Authentication Mechanism) is a relatively new security mechanism (RFC 5802) with interesting properties:

  • It is a password-based authentication scheme
  • No complicated helpers like certification authorities or ticket servers are required for deployment
  • The password is not transmitted during authentication (because of the challenge/response style)
  • The server needs not to store the password in cleartext. Only the salted password is needed, and it is not possible to use a salted password on the client (i.e. it is fruitless to steal the password database)
  • Not only the client authenticates to the server, but also vice versa - the protocol proves to the client that the server has access to the salted password
  • The server does not have a name
There is an extension for SCRAM so that AES-128 encryption and SHA-1 integrity protection become available in GSSAPI context.

SCRAM is implemented in Netmech_scram. The GSSAPI encapsulation is done in Netmech_scram_gssapi.

Some more words on names and credentials: Clients have to impersonate as a user, given by a simple unstructured string. The RFC requires that this string is UTF-8, and that certain Unicode normalizations need to be applied before use. This is not implemented right now (SASLprep is missing). Because of this, only US-ASCII user names are accepted. The same applies to the passwords.

In SCRAM, the client needs to know the password in cleartext. The server, however, usually only stores a triple

 (salted_password, salt, iteration_count) 

in the authentication database. The iteration_count is a constant defined by the server (should be >= 4096). The salt is a random string that is created when the user entry is added to the database. The function Netmech_scram.create_salt can be used for this. The salted_password can be computed from the two other parameters and the password with Netmech_scram.salt_password.

The GSSAPI encapsulation of SCRAM is Netmech_scram_gssapi.scram_gss_api. This class

class scram_gss_api : 
        ?client_key_ring:client_key_ring ->
        ?server_key_verifier:server_key_verifier ->
        Netmech_scram.profile ->
          Netsys_gssapi.gss_api

takes a few arguments. The profile can be just obtained by calling

Netmech_scram.profile `GSSAPI

which is usally the right thing here (one can also set a few parameters at this point). Depending on whether the class is needed for clients or servers, one passes either client_key_ring or server_key_verifier.

Netmech_scram_gssapi.client_key_ring is an object like

let client_key_ring =
  object
    method password_of_user_name user =
      match user with
       | "guest" -> "guest"
       | "gerd" -> "I won't reveal it"
       | _ -> raise Not_found

    method default_user_name = Some "guest"
  end

that mainly returns the passwords of users and that optionally defines a default user. (E.g. the default user could be set to the current login name of the process running the client.)

Netmech_scram_gssapi.server_key_verifier provides the credentials for password verification, e.g.

let server_key_verifier =
  object
    method scram_credentials user =
      match user with
       | "guest" ->
            ("\209\002U?,/Vu\253&\140\196j\158{b]\221\140\029", 
             "68bd268fe5e948a7e171a4df9ef6450a", 
             4096)
       | "gerd" ->
            ("\135\202\182P\142\r\175?\222\156\201bA\188\1296\154\197v\142",
             "5e51d100ace8d1a69cd4d015ac5da947", 
             4096)
       | _ -> raise Not_found
  end

Enabling SCRAM for RPC clients

Basically, an RPC client is created by a call like

let client = Rpc_client.create2 m prog esys

or by invoking ocamlrpcgen-created wrappers of this call. How can we enable SCRAM authentication?

Assumed we already created the gss_api object by instantiating the class Netmech_scram_gssapi.scram_gss_api this is done in two steps:

  • Create the authentication method on RPC level:
      let cconf = Netsys_gssapi.create_client_config
                    ~mech_type:Netmech_scram.scram_mech () in
      let am = 
        Rpc_auth_gssapi.client_auth_method
          ~user_name_interpretation:(`Plain_name Netsys_gssapi.nt_user_name)
          gss_api cconf
      
  • Add this method to the client:
      Rpc_client.set_auth_methods client [am]
      
Optionally, one can also do a third step:

  • Set the user (if you do not want to impersonate the default user):
      Rpc_client.set_user_name client (Some "gerd")
      
That's it!

Of course, am can be shared by several clients. This does not mean, however, that the clients share the security contexts. For each client a separate context is created (i.e. the authentication protocol starts from the beginning).

Both TCP and UDP are supported. Note that especially for UDP there might be issues with retransmitted client requests after running into timeouts. The problem is that retransmitted requests and the following responses look different on the wire than the original messages, and because of this the client can only accept a response when it is the response to the latest retransmission. This makes the retransmission feature less reliable. Best is to avoid UDP.

The function Rpc_auth_gssapi.client_auth_method takes a cconf object controlling details of the security context creation. This object is returned by Netsys_gssapi.create_client_config:

  • By setting ~privacy:`Required it is ensured that encryption and integrity protection are both enabled. If the security mechanism does not provide this, the function fails.
  • The default is ~privacy:`If_possible. This means that privacy is enabled if the mechanism supports it.
  • There is a second argument ~integrity only controlling integrity protection. It comes into play if full privacy is not available or if it is disabled with ~privacy:`None. If integrity protection is on but full privacy is off the messages are not encrypted but only signed with a checksum.
  • One can also turn both features off: ~privacy:`None and ~integrity:`None. In this case, the messages are neither enrypted nor protected. The authentication protocol at the beginning of a session is unaffected and is done nevertheless. This may be an option if you only want to authenticate a TCP connection but not protect the connection. For UDP it is strongly discouraged to use this mode - it is very easy to hack this.
  • Of course, the RPC server has the last word which protection level is acceptable.
SCRAM is a simple security mechanism, and for advanced ones you may need to set more objects in cconf. In particular for Kerberos, it is required to set target_name to the server principal.

You might have wondered why we pass

~user_name_interpretation:(`Plain_name Netsys_gssapi.nt_user_name)

to client_auth_method. As described above, there are various ways how to represent names. In the RPC context we need a simple string. The user_name_interpretation argument selects how the opaque GSSAPI names are converted to strings.

Enabling SCRAM for RPC proxies

The Rpc_proxy module is a higher-level encapsulation of RPC clients providing additional reliability features. One can also configure the proxies to use authentication:

This could e.g. look like

let config =
  Rpc_proxy.ManagedClient.create_mclient_config
    ...
    ~auth_methods:[am]
    ~user_name:(Some "gerd")
    ...
    ()

The config value can then, as usual, be passed to Rpc_proxy.ManagedClient.create_mclient.

Enabling SCRAM for RPC servers

The general procedure for enabling authentication is similar to that in client context:

  • Create the authentication method on RPC level:
     
      let sconf = Netsys_gssapi.create_server_config 
                    ~each_types:[Netmech_scram.scram_mech] () in
      let am = 
        Rpc_auth_gssapi.server_auth_method
          ~user_name_format:`Plain_name
          gss_api sconf
      
  • Add this method to the server:
      Rpc_server.set_auth_methods server [am]
      
The method am can be shared by several servers.

Each connection to a server normally opens a new security context (or better, the context handles are kept private per connection). There is a special mode, however, permitting a more liberal setting: By passing ~shared_context:true to Rpc_auth_gssapi.server_auth_method independent connections can share security contexts if they know the security handles. Although the Ocamlnet client does not support this mode, it might be required for interoperability with other implementations. Also, for UDP servers this mode must be enabled - each UDP request/response pair is considered as a new connection by the RPC server (in some sense this is a peculiarity of the implementation).

You can get the name of the authenticated user with the function Rpc_server.get_user. The way of translating opaque GSSAPI names to strings can be selected with the ~user_name_format argument of Rpc_auth_gssapi.server_auth_method.

The sconf object has, like in the client case, a number of additional options. By setting ~privacy:`Required one can demand that only privacy-protected messages are accepted. ~integrity:`Required demands that at least integrity-protected messages are used. For more advanced mechanisms than SCRAM more options may be needed. In particular, for Kerberos you need at least to set the acceptor_name to the name of the Kerberos principal of the server.

Enabling SCRAM in Netplex context

The question is where to call Rpc_server.set_auth_methods.

RPC services are created by using Rpc_netplex.rpc_factory. This function has an argument setup which is a callback for configuring the server. Usually, this callback is used to bind the RPC procedure functions to the server object. This is also the ideal place to set the authentication method.

Pitfall: Note that setup may also be called for dummy servers that are not connected to real file descriptors. Netplex does this to find out how the server will be configured (especially it is interested in the list of procedures). If this is an issue you can test for a dummy server with Rpc_server.is_dummy.

Security considerations

SCRAM seems to be an excellent choice for a password-based authentication protocol. Of course, it has all the well-known weaknesses of the password approach (e.g. dictionary attacks are possible), but otherwise it is certainly state of the art.

The RPC messages are encrypted with AES-128. This is not configurable.

Integrity protection is obtained by using SHA-1 hashes. This is also not configurable.

Some parts of the RPC messages are not fully protected: Headers and error responses. This means that the numbers identifying the called RPC procedures are not privacy-protected. They are only integrity-protected.

Error responses are completely unprotected.


ocamlnet-4.1.2/doc/html-main/type_Crypto.html0000644000175000017500000004060712731530354017620 0ustar gerdgerd Ocamlnet 4 Reference Manual : Crypto sig  endocamlnet-4.1.2/doc/html-main/type_Netplex_types.socket_controller.html0000644000175000017500000004337212731530354024737 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.socket_controller object
  method container_state :
    (Netplex_types.container_id * string * Netplex_types.container_state *
     bool)
    list
  method disable : unit -> unit
  method enable : unit -> unit
  method restart : unit -> unit
  method shutdown : unit -> unit
  method start_containers : int -> int
  method state : Netplex_types.socket_state
  method stop_containers : Netplex_types.container_id list -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netmime.memory_mime_body.html0000644000175000017500000004066712731530354023277 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.memory_mime_body string -> Netmime.mime_bodyocamlnet-4.1.2/doc/html-main/Netplex_kit.protocol_switch_processor-c.html0000644000175000017500000004340012731530354025317 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.protocol_switch_processor

Class Netplex_kit.protocol_switch_processor

class protocol_switch_processor : (string * Netplex_types.processor) list -> Netplex_types.processor
The arg is a list of pairs (proto_name, proto_proc). All mentioned processors are merged into a single processor. When a TCP connection arrives, it depends on the protocol which processor is actually activated. (Every socket is bound to a protocol, so this can be derived from the socket.)

It is up to the user whether the merge makes sense.


ocamlnet-4.1.2/doc/html-main/type_Netsys_global.html0000644000175000017500000004614012731530354021143 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_global sig
  type variable
  val access : string -> Netsys_global.variable
  val get : Netsys_global.variable -> string
  val set : Netsys_global.variable -> string -> unit
  val get_v : Netsys_global.variable -> string * int64
  val set_v : Netsys_global.variable -> string -> int64
  val iter : (string -> string -> int64 -> unit) -> unit
  class type propagator =
    object
      method propagate : string -> string -> int64
      method update : string -> int64 -> (string * int64) option
    end
  val get_propagator : unit -> Netsys_global.propagator option
  val set_propagator : Netsys_global.propagator option -> unit
  val internal_set : string -> string -> int64 -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_polysocket.html0000644000175000017500000005205312731530354022077 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_polysocket sig
  type 'a polyendpoint =
      'Netsys_polypipe.polypipe * 'Netsys_polypipe.polypipe
  type 'a polyclient
  type 'a polyserver
  val create_client : int -> 'Netsys_polysocket.polyclient
  val connect :
    'Netsys_polysocket.polyclient ->
    'Netsys_polysocket.polyserver -> unit
  val endpoint :
    synchronous:bool ->
    nonblock:bool ->
    'Netsys_polysocket.polyclient -> 'Netsys_polysocket.polyendpoint
  val close_client : 'Netsys_polysocket.polyclient -> unit
  val set_connect_notify :
    'Netsys_polysocket.polyclient -> (unit -> unit) -> unit
  val connect_descr : 'Netsys_polysocket.polyclient -> Unix.file_descr
  val create_server : unit -> 'Netsys_polysocket.polyserver
  val accept :
    nonblock:bool ->
    'Netsys_polysocket.polyserver -> 'Netsys_polysocket.polyendpoint
  val refuse : nonblock:bool -> 'Netsys_polysocket.polyserver -> unit
  val pending_connection : 'Netsys_polysocket.polyserver -> bool
  val close_server : 'Netsys_polysocket.polyserver -> unit
  val set_accept_notify :
    'Netsys_polysocket.polyserver -> (unit -> unit) -> unit
  val accept_descr : 'Netsys_polysocket.polyserver -> Unix.file_descr
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.input_async_mplex.html0000644000175000017500000004133512731530354025537 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.input_async_mplex ?onshutdown:Uq_engines_compat.onshutdown_in_spec ->
?buffer_size:int ->
Uq_engines_compat.multiplex_controller ->
Uq_engines_compat.async_in_channel_engine
ocamlnet-4.1.2/doc/html-main/Netauth.html0000644000175000017500000005276412731530354016716 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netauth

Module Netauth

module Netauth: sig .. end
Some primitives for authentication

val hmac : h:(string -> string) ->
b:int -> l:int -> k:string -> message:string -> string
The HMAC algorithm of RFC 2104. The function h is the hash function. b and l are properties of h (see the RFC or below). The string k is the key, up to b bytes. The message is authenticated.

The key k should ideally have length l. If this cannot be ensured by other means, one should pass k = h any_k.

Common values of b and l:

  • For h=MD5: b=64, l=16
  • For h=SHA-1: b=64, l=20
See also Netsys_digests.hmac for a better implementation.
type key_type = [ `Kc | `Ke | `Ki ] 
Key types:
  • `Kc is used for computing checksums
  • `Ke is used for encrypting confidential messages
  • `Ki is used for computing integrity checksums for encrypted messages

val derive_key_rfc3961_simplified : encrypt:(string -> string) ->
random_to_key:(string -> string) ->
block_size:int -> k:int -> usage:int -> key_type:key_type -> string
Derives a special key from a base key, as described in RFC 3961.

  • encrypt: Encrypts the argument with the base key and the initial cipher state.
  • random_to_key: Converts a random string of size k to a key
  • block_size: The block size of the cipher underlying encrypt. It is ensured that encrypt is called with strings having exactly this many bits. (The c parameter in the RFC text.) Minimum: 40.
  • k: The input size for random_to_key in bits. Must be divisible by 8.
  • usage: The usage number (here restricted to 0-255, although the RFC would allow 32 bits). Examples for usage numbers can be found in RFC 4121 section 2.
  • key_type: Which key type to derive
The output is a key as produced by random_to_key.

Bitstring operations


val xor_s : string -> string -> string
Performs the bitwise XOR of these strings (which must have the same length)
val add_1_complement : string -> string -> string
The addition algorithm for 1's-complement numbers. The two numbers to add are given as bitstrings (big endian), and must have the same length
val rotate_right : int -> string -> string
Rotate the (big-endian) bitstring to the right by n bits. This also works for negative n (left rotation), and for n whose absolute value is greater or equal than the bit length of the string.
val n_fold : int -> string -> string
Blumenthal's n-fold algorithm for an n that is divisible by 8. (RFC 3961, section 5.1)
ocamlnet-4.1.2/doc/html-main/type_Rpc_server.default_socket_config.html0000644000175000017500000004061612731530354024772 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.default_socket_config Rpc_server.socket_configocamlnet-4.1.2/doc/html-main/type_Rpc_packer.html0000644000175000017500000007430112731530354020407 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_packer sig
  type packed_value
  val pack_call :
    ?encoder:Netxdr.encoder ->
    Rpc_program.t ->
    Netnumber.uint4 ->
    string ->
    string ->
    string -> string -> string -> Netxdr.xdr_value -> Rpc_packer.packed_value
  val pack_call_pseudo :
    Rpc_program.t ->
    Netnumber.uint4 ->
    string ->
    string ->
    string -> string -> string -> Netxdr.xdr_value -> Rpc_packer.packed_value
  val pack_call_gssapi_header :
    Rpc_program.t ->
    Netnumber.uint4 -> string -> string -> string -> Rpc_packer.packed_value
  val unpack_call :
    ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
    ?decoder:Netxdr.decoder ->
    Rpc_program.t ->
    string ->
    Rpc_packer.packed_value ->
    Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 *
    string * string * string * string * Netxdr.xdr_value
  val unpack_call_frame :
    Rpc_packer.packed_value ->
    Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 *
    string * string * string * string
  val unpack_call_frame_l :
    Rpc_packer.packed_value ->
    Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 * Netnumber.uint4 *
    string * string * string * string * int
  val extract_call_gssapi_header : Rpc_packer.packed_value -> int
  val unpack_call_body :
    ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
    ?decoder:Netxdr.decoder ->
    Rpc_program.t ->
    string -> Rpc_packer.packed_value -> int -> Netxdr.xdr_value
  val unpack_call_body_raw : Rpc_packer.packed_value -> int -> string
  val unpack_call_body_raw_bytes : Rpc_packer.packed_value -> int -> Bytes.t
  val pack_successful_reply :
    ?encoder:Netxdr.encoder ->
    Rpc_program.t ->
    string ->
    Netnumber.uint4 ->
    string -> string -> Netxdr.xdr_value -> Rpc_packer.packed_value
  val pack_successful_reply_pseudo :
    Rpc_program.t ->
    string ->
    Netnumber.uint4 ->
    string -> string -> Netxdr.xdr_value -> Rpc_packer.packed_value
  val pack_successful_reply_raw :
    Netnumber.uint4 ->
    string ->
    string -> Netxdr_mstring.mstring list -> Rpc_packer.packed_value
  val pack_accepting_reply :
    Netnumber.uint4 ->
    string -> string -> Rpc.server_error -> Rpc_packer.packed_value
  val pack_accepting_reply_pseudo :
    Netnumber.uint4 ->
    string -> string -> Rpc.server_error -> Rpc_packer.packed_value
  val pack_rejecting_reply :
    Netnumber.uint4 -> Rpc.server_error -> Rpc_packer.packed_value
  val pack_rejecting_reply_pseudo :
    Netnumber.uint4 -> Rpc.server_error -> Rpc_packer.packed_value
  val unpack_reply :
    ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
    ?decoder:Netxdr.decoder ->
    Rpc_program.t ->
    string ->
    Rpc_packer.packed_value ->
    Netnumber.uint4 * string * string * Netxdr.xdr_value
  val unpack_reply_verifier :
    Rpc_program.t -> string -> Rpc_packer.packed_value -> string * string
  val peek_xid : Rpc_packer.packed_value -> Netnumber.uint4
  val peek_auth_error : Rpc_packer.packed_value -> Rpc.server_error option
  val length_of_packed_value : Rpc_packer.packed_value -> int
  val string_of_packed_value : Rpc_packer.packed_value -> string
  val bytes_of_packed_value : Rpc_packer.packed_value -> Bytes.t
  val mstrings_of_packed_value :
    Rpc_packer.packed_value -> Netxdr_mstring.mstring list
  val packed_value_of_string : string -> Rpc_packer.packed_value
  val packed_value_of_bytes : Bytes.t -> Rpc_packer.packed_value
  val packed_value_of_mstrings :
    Netxdr_mstring.mstring list -> Rpc_packer.packed_value
  val prefix_of_packed_value : Rpc_packer.packed_value -> int -> string
  val xdr_of_pseudo_value : Rpc_packer.packed_value -> Netxdr.xdr_value
  val pseudo_value_of_xdr : Netxdr.xdr_value -> Rpc_packer.packed_value
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.buffered_raw_in_channel.html0000644000175000017500000004132212731530354025405 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.buffered_raw_in_channel ?eol:string list ->
?buffer_size:int ->
?pass_through:int ->
Netchannels.raw_in_channel -> Netchannels.enhanced_raw_in_channel
ocamlnet-4.1.2/doc/html-main/type_Uq_mt.html0000644000175000017500000004465512731530354017434 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_mt sig
  type monitor
  val create_monitor : Unixqueue.event_system -> Uq_mt.monitor
  val monitor_run :
    Uq_mt.monitor ->
    (Unixqueue.event_system -> '-> 'Uq_engines.engine) -> '-> 'b
  val monitor_do : Uq_mt.monitor -> ('-> 'b) -> '-> 'b
  val monitor_async :
    Uq_mt.monitor -> ('-> ((unit -> 'b) -> unit) -> unit) -> '-> 'b
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_pmanage.pmanage.html0000644000175000017500000004402412731530354022721 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pmanage.pmanage object
  method register : Netsys_pmanage.pm_obj list -> unit
  method register_file : string -> unit
  method register_posix_sem : string -> unit
  method register_posix_shm : string -> unit
  method register_sem_cont : string -> unit
  method registered : Netsys_pmanage.pm_obj list
  method unlink : unit -> unit
  method unregister_file : string -> unit
  method unregister_posix_sem : string -> unit
  method unregister_posix_shm : string -> unit
  method unregister_sem_cont : string -> unit
end
ocamlnet-4.1.2/doc/html-main/Netlog.html0000644000175000017500000005420512731530354016526 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netlog

Module Netlog

module Netlog: sig .. end
Basic logging facility

The purpose of this module is to define a mutable logging function which ensures to be always pointing to a valid logging implementation. By default, the function prints the messages to stderr, prepended by a timestamp. In Netplex context, the implementation is changed so that the Netplex logger is used instead (see Netplex_log), and the log and logf functions below have the same effect as the counterparts in Netplex_cenv with the same name.


type level = [ `Alert | `Crit | `Debug | `Emerg | `Err | `Info | `Notice | `Warning ] 
The log levels (syslog-like)
type logger = level -> string -> unit 
A logging function takes a level, and the message
val channel_logger : Pervasives.out_channel -> level -> logger
channel_logger ch lev: Prints all messages with a level of lev and higher to the channel ch. The output buffer is flushed after each message,
val current_logger : logger Pervasives.ref
The variable containing the current logger function. Defaults to channel_logger stderr `Debug at program startup. Assign something else to this variable in order to change the log destination or the log level.

Note that the function Netplex_main.run modifies current_logger so log messages are forwarded to the Netplex logger. It is then the Netplex framework that determines log destination and level.

val log : level -> string -> unit
Writes a log message
val logf : level -> ('a, unit, string, unit) Pervasives.format4 -> 'a
Writes a log message like printf
val level_weight : level -> int
A number correspondig to the level
val level_of_string : string -> level
val string_of_level : level -> string
Convert level names to strings and vice versa
val level_names : string array
The level names indexed by weight
type format = [ `ISO | `Std ] 
val format_timestamp : format -> int -> float * int -> string
format_timestamp fmt digits (seconds,nanos): Formats the timestamp (seconds,nanos) and returns the string. Pass in digits the number of digits for fractional seconds.

  • `Std: This is the "%c" format of Netdate
  • `ISO: ISO-8601 format

val current_formatter : (float * int -> string) Pervasives.ref
The current timestamp formatter

Example: Change the format of timestamps to ISO with a precision of milliseconds:

        Netlog.current_formatter := Netlog.format_timestamp `ISO 3
      

module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netstream.sub_stream.html0000644000175000017500000004114712731530354022445 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstream.sub_stream ?len:int ->
?delimiter:string -> Netstream.in_obj_stream -> Netstream.in_obj_stream
ocamlnet-4.1.2/doc/html-main/type_Uq_server.html0000644000175000017500000005277612731530354020325 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_server sig
  type listen_address =
      [ `Socket of Uq_engines.sockspec * Uq_server.listen_options
      | `W32_pipe of
          Netsys_win32.pipe_mode * string * Uq_server.listen_options ]
  and listen_options =
    Uq_engines.listen_options = {
    lstn_backlog : int;
    lstn_reuseaddr : bool;
  }
  val default_listen_options : Uq_server.listen_options
  val listen_on_inet_socket :
    Unix.inet_addr ->
    int -> Unix.socket_type -> Uq_server.listen_options -> Unix.file_descr
  val listen_on_unix_socket :
    string -> Unix.socket_type -> Uq_server.listen_options -> Unix.file_descr
  val listen_on_w32_pipe :
    Netsys_win32.pipe_mode ->
    string -> Uq_server.listen_options -> Unix.file_descr
  val listen_on : Uq_server.listen_address -> Unix.file_descr
  class type server_endpoint_acceptor =
    object
      method accept :
        unit ->
        (Unix.file_descr * Uq_engines.inetspec option) Uq_engines.engine
      method multiple_connections : bool
      method server_address : Uq_engines.connect_address
      method shut_down : unit -> unit
    end
  class direct_acceptor :
    ?close_on_shutdown:bool ->
    ?preclose:(unit -> unit) ->
    Unix.file_descr -> Unixqueue.event_system -> server_endpoint_acceptor
  val listener :
    ?proxy:#Uq_engines.server_endpoint_listener ->
    Uq_server.listen_address ->
    Unixqueue.event_system ->
    Uq_server.server_endpoint_acceptor Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.output_engine-c.html0000644000175000017500000004262212731530354024042 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.output_engine

Class Uq_engines_compat.output_engine

class ['a] output_engine : (Unix.file_descr -> 'a) -> Unix.file_descr -> float -> Unixqueue.event_system -> ['a] engine

ocamlnet-4.1.2/doc/html-main/type_Netftp_data_endpoint.out_record_channel.html0000644000175000017500000004531412731530354026325 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.out_record_channel object
  method close_out : unit -> unit
  method flush : unit -> unit
  method output : Bytes.t -> int -> int -> int
  method output_buffer : Buffer.t -> unit
  method output_byte : int -> unit
  method output_bytes : Bytes.t -> unit
  method output_channel : ?len:int -> Netchannels.in_obj_channel -> unit
  method output_char : char -> unit
  method output_eor : unit -> unit
  method output_string : string -> unit
  method pos_out : int
  method really_output : Bytes.t -> int -> int -> unit
  method really_output_string : string -> int -> int -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Nettls_gnutls.Digests.html0000644000175000017500000004064712731530354022612 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.Digests Netsys_crypto_types.DIGESTSocamlnet-4.1.2/doc/html-main/Uq_engines.delegate_engine-c.html0000644000175000017500000004222412731530354022707 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.delegate_engine

Class Uq_engines.delegate_engine

class ['t] delegate_engine : 't #engine -> ['t] engine
Turns an engine value into a class

ocamlnet-4.1.2/doc/html-main/Netsaslprep.html0000644000175000017500000004370012731530354017574 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsaslprep

Module Netsaslprep

module Netsaslprep: sig .. end
The SASLprep algorithm (RFC 4013)


This module implements the SASLprep string preparation algorithm, often used for normalizing passwords.

Note that SASLprep is SLOOOOOOW, and should really only be used on short strings like passwords.

This version of SASLprep doesn't check for unassigned codepoints.

exception SASLprepError
Raised when a string cannot be transformed
val saslprep_a : int array -> int array
Transform a string given as array of Unicode code points
val saslprep : string -> string
Transform a string given as UTF-8 string
ocamlnet-4.1.2/doc/html-main/type_Shell_fs.shell_stream_fs.html0000644000175000017500000005244712731530354023255 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_fs.shell_stream_fs object
  method cancel : unit -> unit
  method copy : Netfs.copy_flag list -> string -> string -> unit
  method last_stderr : string
  method mkdir : Netfs.mkdir_flag list -> string -> unit
  method nominal_dot_dot : bool
  method path_encoding : Netconversion.encoding option
  method path_exclusions : (int * int) list
  method read : Netfs.read_flag list -> string -> Netchannels.in_obj_channel
  method read_file : Netfs.read_file_flag list -> string -> Netfs.local_file
  method readdir : Netfs.readdir_flag list -> string -> string list
  method readlink : Netfs.readlink_flag list -> string -> string
  method remove : Netfs.remove_flag list -> string -> unit
  method rename : Netfs.rename_flag list -> string -> string -> unit
  method rmdir : Netfs.rmdir_flag list -> string -> unit
  method size : Netfs.size_flag list -> string -> int64
  method symlink : Netfs.symlink_flag list -> string -> string -> unit
  method test : Netfs.test_flag list -> string -> Netfs.test_type -> bool
  method test_list :
    Netfs.test_flag list -> string -> Netfs.test_type list -> bool list
  method write :
    Netfs.write_flag list -> string -> Netchannels.out_obj_channel
  method write_file :
    Netfs.write_file_flag list -> string -> Netfs.local_file -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_sasl.html0000644000175000017500000007453012731530354020651 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl sig
  type sasl_mechanism = (module Netsys_sasl_types.SASL_MECHANISM)
  type credentials = (string * string * (string * string) list) list
  module Info :
    sig
      val mechanism_name : Netsys_sasl.sasl_mechanism -> string
      val client_first :
        Netsys_sasl.sasl_mechanism -> [ `No | `Optional | `Required ]
      val server_sends_final_data : Netsys_sasl.sasl_mechanism -> bool
      val supports_authz : Netsys_sasl.sasl_mechanism -> bool
    end
  module Client :
    sig
      type session
      val create_session :
        mech:Netsys_sasl.sasl_mechanism ->
        user:string ->
        authz:string ->
        creds:Netsys_sasl.credentials ->
        params:(string * string * bool) list ->
        unit -> Netsys_sasl.Client.session
      val state :
        Netsys_sasl.Client.session -> Netsys_sasl_types.client_state
      val configure_channel_binding :
        Netsys_sasl.Client.session ->
        Netsys_sasl_types.cb -> Netsys_sasl.Client.session
      val restart : Netsys_sasl.Client.session -> Netsys_sasl.Client.session
      val process_challenge :
        Netsys_sasl.Client.session -> string -> Netsys_sasl.Client.session
      val emit_response :
        Netsys_sasl.Client.session -> Netsys_sasl.Client.session * string
      val channel_binding :
        Netsys_sasl.Client.session -> Netsys_sasl_types.cb
      val user_name : Netsys_sasl.Client.session -> string
      val authz_name : Netsys_sasl.Client.session -> string
      val stash_session : Netsys_sasl.Client.session -> string
      val resume_session :
        Netsys_sasl.sasl_mechanism -> string -> Netsys_sasl.Client.session
      val session_id : Netsys_sasl.Client.session -> string option
      val prop : Netsys_sasl.Client.session -> string -> string
      val gssapi_props :
        Netsys_sasl.Client.session -> Netsys_gssapi.client_props
    end
  module Server :
    sig
      type session
      type 'credentials init_credentials =
          (string * string * (string * string) list) list -> 'credentials
      type lookup = {
        lookup :
          'c.
            Netsys_sasl.sasl_mechanism ->
            'Netsys_sasl.Server.init_credentials ->
            string -> string -> 'c option;
      }
      val create_session :
        mech:Netsys_sasl.sasl_mechanism ->
        lookup:Netsys_sasl.Server.lookup ->
        params:(string * string * bool) list ->
        unit -> Netsys_sasl.Server.session
      val process_response :
        Netsys_sasl.Server.session -> string -> Netsys_sasl.Server.session
      val process_response_restart :
        Netsys_sasl.Server.session ->
        string -> bool -> Netsys_sasl.Server.session * bool
      val emit_challenge :
        Netsys_sasl.Server.session -> Netsys_sasl.Server.session * string
      val stash_session : Netsys_sasl.Server.session -> string
      val resume_session :
        mech:Netsys_sasl.sasl_mechanism ->
        lookup:Netsys_sasl.Server.lookup ->
        string -> Netsys_sasl.Server.session
      val session_id : Netsys_sasl.Server.session -> string option
      val prop : Netsys_sasl.Server.session -> string -> string
      val gssapi_props :
        Netsys_sasl.Server.session -> Netsys_gssapi.server_props
      val user_name : Netsys_sasl.Server.session -> string
      val authz_name : Netsys_sasl.Server.session -> string
      val channel_binding :
        Netsys_sasl.Server.session -> Netsys_sasl_types.cb
    end
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.http_processor_config.html0000644000175000017500000004475212731530354026260 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.http_processor_config object
  method config_announce_server : Nethttpd_kernel.announcement
  method config_cgi : Netcgi.config
  method config_error_response :
    Nethttpd_types.error_response_params -> string
  method config_limit_pipeline_length : int
  method config_limit_pipeline_size : int
  method config_log_access : Nethttpd_types.full_info -> unit
  method config_log_error : Nethttpd_types.request_info -> string -> unit
  method config_max_header_length : int
  method config_max_reqline_length : int
  method config_max_trailer_length : int
  method config_suppress_broken_pipe : bool
  method config_timeout : float
  method config_timeout_next_request : float
  method config_tls : Netsys_crypto_types.tls_config option
  method config_tls_cert_props : bool
  method config_tls_remote_user : bool
end
ocamlnet-4.1.2/doc/html-main/type_Uq_datagram.html0000644000175000017500000005105612731530354020565 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_datagram sig
  type datagram_type = [ `Inet6_udp | `Inet_udp | `Unix_dgram ]
  class type wrapped_datagram_socket =
    object
      method datagram_type : Uq_datagram.datagram_type
      method descriptor : Unix.file_descr
      method recvfrom :
        Bytes.t ->
        int -> int -> Unix.msg_flag list -> int * Uq_engines.sockspec
      method sendto :
        Bytes.t ->
        int -> int -> Unix.msg_flag list -> Uq_engines.sockspec -> int
      method shut_down : unit -> unit
      method socket_domain : Unix.socket_domain
      method socket_protocol : int
      method socket_type : Unix.socket_type
    end
  class type datagram_socket_provider =
    object
      method create_datagram_socket :
        Uq_datagram.datagram_type ->
        Unixqueue.event_system ->
        Uq_datagram.wrapped_datagram_socket Uq_engines.engine
    end
  val datagram_provider :
    ?proxy:#Uq_datagram.datagram_socket_provider ->
    Uq_datagram.datagram_type ->
    Unixqueue.event_system ->
    Uq_datagram.wrapped_datagram_socket Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_gssapi.poly_gss_api.html0000644000175000017500000014665212731530354023671 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.poly_gss_api object
  method accept_sec_context :
    context:'context option ->
    acceptor_cred:'credential ->
    input_token:Netsys_gssapi.token ->
    chan_bindings:Netsys_gssapi.channel_bindings option ->
    out:(src_name:'name ->
         mech_type:Netsys_gssapi.oid ->
         output_context:'context option ->
         output_token:Netsys_gssapi.token ->
         ret_flags:Netsys_gssapi.ret_flag list ->
         time_rec:Netsys_gssapi.time ->
         delegated_cred:'credential ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method acquire_cred :
    desired_name:'name ->
    time_req:Netsys_gssapi.time ->
    desired_mechs:Netsys_gssapi.oid_set ->
    cred_usage:Netsys_gssapi.cred_usage ->
    out:(cred:'credential ->
         actual_mechs:Netsys_gssapi.oid_set ->
         time_rec:Netsys_gssapi.time ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method add_cred :
    input_cred:'credential ->
    desired_name:'name ->
    desired_mech:Netsys_gssapi.oid ->
    cred_usage:Netsys_gssapi.cred_usage ->
    initiator_time_req:Netsys_gssapi.time ->
    acceptor_time_req:Netsys_gssapi.time ->
    out:(output_cred:'credential ->
         actual_mechs:Netsys_gssapi.oid_set ->
         initiator_time_rec:Netsys_gssapi.time ->
         acceptor_time_rec:Netsys_gssapi.time ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method canonicalize_name :
    input_name:'name ->
    mech_type:Netsys_gssapi.oid ->
    out:(output_name:'name ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method compare_name :
    name1:'name ->
    name2:'name ->
    out:(name_equal:bool ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method context_time :
    context:'context ->
    out:(time_rec:Netsys_gssapi.time ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method delete_sec_context :
    context:'context ->
    out:(minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method display_minor_status :
    status_value:Netsys_gssapi.minor_status ->
    mech_type:Netsys_gssapi.oid ->
    out:(status_strings:string list ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method display_name :
    input_name:'name ->
    out:(output_name:string ->
         output_name_type:Netsys_gssapi.oid ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method duplicate_name :
    name:'name ->
    out:(dest_name:'name ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method export_name :
    name:'name ->
    out:(exported_name:string ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method export_sec_context :
    context:'context ->
    out:(interprocess_token:Netsys_gssapi.interprocess_token ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method get_mic :
    context:'context ->
    qop_req:Netsys_gssapi.qop ->
    message:Netsys_gssapi.message ->
    out:(msg_token:Netsys_gssapi.token ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method import_name :
    input_name:string ->
    input_name_type:Netsys_gssapi.oid ->
    out:(output_name:'name ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method import_sec_context :
    interprocess_token:Netsys_gssapi.interprocess_token ->
    out:(context:'context option ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method indicate_mechs :
    out:(mech_set:Netsys_gssapi.oid_set ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method init_sec_context :
    initiator_cred:'credential ->
    context:'context option ->
    target_name:'name ->
    mech_type:Netsys_gssapi.oid ->
    req_flags:Netsys_gssapi.req_flag list ->
    time_req:float option ->
    chan_bindings:Netsys_gssapi.channel_bindings option ->
    input_token:Netsys_gssapi.token option ->
    out:(actual_mech_type:Netsys_gssapi.oid ->
         output_context:'context option ->
         output_token:Netsys_gssapi.token ->
         ret_flags:Netsys_gssapi.ret_flag list ->
         time_rec:Netsys_gssapi.time ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method inquire_context :
    context:'context ->
    out:(src_name:'name ->
         targ_name:'name ->
         lifetime_req:Netsys_gssapi.time ->
         mech_type:Netsys_gssapi.oid ->
         ctx_flags:Netsys_gssapi.ret_flag list ->
         locally_initiated:bool ->
         is_open:bool ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method inquire_cred :
    cred:'credential ->
    out:(name:'name ->
         lifetime:Netsys_gssapi.time ->
         cred_usage:Netsys_gssapi.cred_usage ->
         mechanisms:Netsys_gssapi.oid_set ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method inquire_cred_by_mech :
    cred:'credential ->
    mech_type:Netsys_gssapi.oid ->
    out:(name:'name ->
         initiator_lifetime:Netsys_gssapi.time ->
         acceptor_lifetime:Netsys_gssapi.time ->
         cred_usage:Netsys_gssapi.cred_usage ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method inquire_mechs_for_name :
    name:'name ->
    out:(mech_types:Netsys_gssapi.oid_set ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method inquire_names_for_mech :
    mechanism:Netsys_gssapi.oid ->
    out:(name_types:Netsys_gssapi.oid_set ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method is_no_credential : 'credential -> bool
  method is_no_name : 'name -> bool
  method no_credential : 'credential
  method no_name : 'name
  method process_context_token :
    context:'context ->
    token:Netsys_gssapi.token ->
    out:(minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method provider : string
  method unwrap :
    context:'context ->
    input_message:Netsys_gssapi.message ->
    output_message_preferred_type:[ `Bytes | `Memory ] ->
    out:(output_message:Netsys_gssapi.message ->
         conf_state:bool ->
         qop_state:Netsys_gssapi.qop ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method verify_mic :
    context:'context ->
    message:Netsys_gssapi.message ->
    token:Netsys_gssapi.token ->
    out:(qop_state:Netsys_gssapi.qop ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method wrap :
    context:'context ->
    conf_req:bool ->
    qop_req:Netsys_gssapi.qop ->
    input_message:Netsys_gssapi.message ->
    output_message_preferred_type:[ `Bytes | `Memory ] ->
    out:(conf_state:bool ->
         output_message:Netsys_gssapi.message ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
  method wrap_size_limit :
    context:'context ->
    conf_req:bool ->
    qop_req:Netsys_gssapi.qop ->
    req_output_size:int ->
    out:(max_input_size:int ->
         minor_status:Netsys_gssapi.minor_status ->
         major_status:Netsys_gssapi.major_status -> unit -> 't) ->
    unit -> 't
end
ocamlnet-4.1.2/doc/html-main/type_Unixqueue.unix_event_system.html0000644000175000017500000004067512731530354024124 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue.unix_event_system unit -> Unixqueue.event_systemocamlnet-4.1.2/doc/html-main/Nettls_gnutls.GNUTLS_ENDPOINT.TLS.html0000644000175000017500000004327112731530354023120 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.GNUTLS_ENDPOINT.TLS

Module Nettls_gnutls.GNUTLS_ENDPOINT.TLS

module TLS: Nettls_gnutls.GNUTLS_PROVIDER 

include Netsys_crypto_types.TLS_PROVIDER
val gnutls_session : endpoint -> Nettls_gnutls_bindings.gnutls_session_t
Get the gnutls_session of the endpoint
val gnutls_credentials : credentials -> Nettls_gnutls_bindings.gnutls_credentials
Get the gnutls_credentials of the generic credentials
ocamlnet-4.1.2/doc/html-main/type_Uq_client.client_endpoint_connector.html0000644000175000017500000004154212731530354025511 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_client.client_endpoint_connector object
  method connect :
    Uq_client.connect_address ->
    Unixqueue.event_system -> Uq_client.connect_status Uq_engines.engine
end
ocamlnet-4.1.2/doc/html-main/Netsys_ciphers.cipher-c.html0000644000175000017500000004574412731530354022001 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_ciphers.cipher

Class type Netsys_ciphers.cipher

class type cipher = object .. end

method name : string
The name of the cipher
method mode : string
The mode of the cipher
method key_lengths : (int * int) list
Supported key lengths as pairs min,max. If there is a recommended key length, this is the first.
method iv_lengths : (int * int) list
Supported iv lengths as pairs min,max. If there is a recommended iv length, this is the first.
method block_constraint : int
The buffers used with encrypt/decrypt must have a length that is a multiple of this number. (In ECB mode this is the block size.)
method supports_aead : bool
Whether this cipher integrates authentication
method create : string -> padding -> cipher_ctx
create c p key: create a new cipher context for key. If not set, the initialization vector is assumed to be zero, and the header the empty string.

The cipher context can be used for either encrypting or decrypting a single message.

ocamlnet-4.1.2/doc/html-main/type_Netnumber.LE.html0000644000175000017500000004055012731530354020573 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber.LE ENCDECocamlnet-4.1.2/doc/html-main/Netcgi_apache.Apache.Connection.html0000644000175000017500000004377512731530354023300 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache.Connection

Module Netcgi_apache.Apache.Connection

module Connection: sig .. end

type t 
Apache conn_rec structure.
val remote_ip : t -> string
conn_rec remote_ip field.
Raises Not_found if NULL.
val remote_host : t -> string
conn_rec remote_host field.
Raises Not_found if NULL.
ocamlnet-4.1.2/doc/html-main/Netchannels.compl_in_channel-c.html0000644000175000017500000004671612731530354023257 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.compl_in_channel

Class type Netchannels.compl_in_channel

class type compl_in_channel = object .. end
Further methods usually supported by ocamlnet channel implementations. These methods are only reasonable when the channel is of blocking type, i.e. waits for input when not enough data are available to perform an operation. Implementations may choose to fail when they detect the channel is non-blocking.

method really_input : Bytes.t -> int -> int -> unit
Reads exactly as many octets from the channel as the second int argument specifies. The octets are placed at the position denoted by the first int argument into the string.

When the end of the channel is reached before the passed number of octets are read, the exception End_of_file is raised.

method really_input_string : int -> string
really_input_string ic len reads len characters from channel ic and returns them in a new string. Raise End_of_file if the end of file is reached before len characters have been read.
method input_char : unit -> char
Reads exactly one character from the channel, or raises End_of_file
method input_line : unit -> string
Reads the next line from the channel. When the channel is already at the end before input_line is called, the exception End_of_file is raised.
method input_byte : unit -> int
Reads exactly one octet from the channel and returns its code, or raises End_of_file
ocamlnet-4.1.2/doc/html-main/Netcgi_common.simple_arg-c.html0000644000175000017500000004246412731530354022424 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_common.simple_arg

Class Netcgi_common.simple_arg

class simple_arg : ?ro:bool -> string -> string -> rw_cgi_argument
See Netcgi.Argument.simple. We reveal more of the object than Netcgi.Argument.simple for the backward compatibility layer.

ocamlnet-4.1.2/doc/html-main/Netchannels.raw_out_channel-c.html0000644000175000017500000004411712731530354023130 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_out_channel

Class type Netchannels.raw_out_channel

class type raw_out_channel = object .. end
Basic Unix-level class type for output channels as used by ocamlnet. In addition to the recommended standard, ocamlnet always support a position counter
Inherits
method pos_out : int
Returns the current channel position. This position can be expected to be consistent with the returned number of bytes of output, i.e. when output returns n, the position is advanced by n.

As seek operations are outside the scope of Netchannels, implementations may or may not take seek operations into account.

ocamlnet-4.1.2/doc/html-main/Netplex_mutex.html0000644000175000017500000004745312731530354020146 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mutex

Module Netplex_mutex

module Netplex_mutex: sig .. end
Netplex-wide mutexes


These are mutexes that work in both multi-processing and multi-threading netplex environments. They are implemented on top of Netplex_semaphore, and use the same name space for named objects.

For implementation issues, see Netplex_semaphore.

It is not required to create mutexes: A mutex is automatically created when the name is used for the first time. Mutexes are initially always in unlocked state.

Mutexes do not stack: A container cannot lock a mutex several times. (The second lock attempt would result in a deadlock.)

There is no deadlock detection.

If a container holding mutexes terminates the mutexes are automatically unlocked.

Mutex are not owned by their container. It is allowed that a different container unlocks the mutex.

Technically, a mutex named n is implemented by a semaphore n. If the mutex is locked, the semaphore has the value 0, and if it is unlocked, it has value 1.

Thread safety: Full. The functions can be called from any thread.

val plugin : Netplex_types.plugin
To enable mutexes, call the controller's add_plugin method with this object as argument. This can e.g. be done in the post_add_hook of the processor.

The following functions can only be invoked in container contexts. Outside of such a context the exception Netplex_cenv.Not_in_container_thread is raised.
type mutex 
val access : string -> mutex
Access the named mutex. If the mutex does not exist, it is created in unlocked state
val lock : mutex -> unit
Wait until the mutex is free, and locks it
val unlock : mutex -> unit
Unlocks the mutex. This is a no-op if the mutex is not locked
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_kernel.http_response.html0000644000175000017500000004377112731530354024373 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_response object
  method advance : int -> unit
  method bidirectional_phase : bool
  method body_size : int64
  method close_connection : bool
  method front_token : Nethttpd_kernel.front_token
  method protocol : Nethttp.protocol
  method send : Nethttpd_kernel.resp_token -> unit
  method send_queue_empty : bool
  method set_callback : (unit -> unit) -> unit
  method set_state : Nethttpd_kernel.resp_state -> unit
  method state : Nethttpd_kernel.resp_state
  method transfer_encoding : Nethttpd_kernel.transfer_coding
end
ocamlnet-4.1.2/doc/html-main/type_Shell_intro.html0000644000175000017500000004061412731530354020620 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_intro sig  endocamlnet-4.1.2/doc/html-main/Uq_engines_compat.wrapped_datagram_socket-c.html0000644000175000017500000004524712731530354026035 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.wrapped_datagram_socket

Class type Uq_engines_compat.wrapped_datagram_socket

class type wrapped_datagram_socket = object .. end

method descriptor : Unix.file_descr
method sendto : Bytes.t ->
int -> int -> Unix.msg_flag list -> sockspec -> int
method recvfrom : Bytes.t ->
int -> int -> Unix.msg_flag list -> int * sockspec
method shut_down : unit -> unit
method datagram_type : datagram_type
method socket_domain : Unix.socket_domain
method socket_type : Unix.socket_type
method socket_protocol : int
ocamlnet-4.1.2/doc/html-main/Netcompression.html0000644000175000017500000004555612731530354020317 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcompression

Module Netcompression

module Netcompression: sig .. end
Registry for compression algorithms


This registry is initially empty. The Netgzip module can be used to register the gzip algorithm, just run

 Netgzip.init() 

to get this effect.

val register : iana_name:string ->
?encoder:(unit -> Netchannels.io_obj_channel) ->
?decoder:(unit -> Netchannels.io_obj_channel) -> unit -> unit
Registers a compression algorithm. The algorithm is given as a pair of functions returning Netchannels.io_obj_channel.
val lookup_encoder : iana_name:string -> unit -> Netchannels.io_obj_channel
Returns the encoder, or raises Not_found
val lookup_decoder : iana_name:string -> unit -> Netchannels.io_obj_channel
Returns the decoder, or raises Not_found
val all_encoders : unit -> string list
val all_decoders : unit -> string list
The iana names of all encoders and decoders, resp.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.meta_engine.html0000644000175000017500000004122412731530354022703 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.meta_engine '#Uq_engines.engine -> ['Uq_engines.final_state] Uq_engines.engineocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.extended_async_environment.html0000644000175000017500000005722112731530354027077 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.extended_async_environment object
  method cgi_auth_type : string
  method cgi_gateway_interface : string
  method cgi_https : bool
  method cgi_path_info : string
  method cgi_path_translated : string
  method cgi_properties : (string * string) list
  method cgi_property : ?default:string -> string -> string
  method cgi_query_string : string
  method cgi_remote_addr : string
  method cgi_remote_host : string
  method cgi_remote_ident : string
  method cgi_remote_user : string
  method cgi_request_method : string
  method cgi_request_uri : string
  method cgi_script_name : string
  method cgi_server_name : string
  method cgi_server_port : int option
  method cgi_server_protocol : string
  method cgi_server_software : string
  method config : Netcgi.config
  method cookie : string -> Netcgi.Cookie.t
  method cookies : Netcgi.Cookie.t list
  method input_body_size : int64
  method input_ch_async : Uq_engines.async_in_channel
  method input_channel : Netchannels.in_obj_channel
  method input_content_length : int
  method input_content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method input_content_type_string : string
  method input_header : Netmime.mime_header
  method input_header_field : ?default:string -> string -> string
  method input_header_fields : (string * string) list
  method log_error : string -> unit
  method log_props : (string * string) list -> unit
  method multiple_input_header_field : string -> string list
  method multiple_output_header_field : string -> string list
  method out_channel : Netchannels.out_obj_channel
  method output_ch : Netchannels.out_obj_channel
  method output_ch_async : Uq_engines.async_out_channel
  method output_header : Netmime.mime_header
  method output_header_field : ?default:string -> string -> string
  method output_header_fields : (string * string) list
  method output_state : Nethttpd_types.output_state ref
  method protocol : Nethttp.protocol
  method remote_socket_addr : Unix.sockaddr
  method request_body_rejected : bool
  method send_file : Unix.file_descr -> int64 -> unit
  method send_output_header : unit -> unit
  method server_socket_addr : Unix.sockaddr
  method set_multiple_output_header_field : string -> string list -> unit
  method set_output_header_field : string -> string -> unit
  method set_output_header_fields : (string * string) list -> unit
  method set_status : Nethttp.http_status -> unit
  method tls_session_props : Nettls_support.tls_session_props option
  method user_agent : string
end
ocamlnet-4.1.2/doc/html-main/Netsys_pollset_win32.html0000644000175000017500000004532412731530354021351 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset_win32

Module Netsys_pollset_win32

module Netsys_pollset_win32: sig .. end
Pollsets for Win32

exception Too_many_descriptors
val pollset : unit -> Netsys_pollset.pollset
This is a pollset implementation that works for
  • sockets, and
  • named pipes as provided by Netsys_win32 (add the descriptors returned by pipe_descr or pipe_server_descr to the pollset)
The number of descriptors that can be added to the pollset has a quite low limit (usually 63 sockets or 31 pipes). If the number is exceeded the exception Too_many_descriptors is raised (by add).

POLLERR, POLLHUP, and POLLNVAL are not detected by this impl.

val threaded_pollset : unit -> Netsys_pollset.pollset
This implementation overcomes the limit on the number of descriptors one can add to the set. It is, however, only available for multi-threaded programs, because it uses helper threads.
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.redirected_environment.html0000644000175000017500000004153612731530354026115 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.redirected_environment ?in_header:Nethttp.http_header ->
?properties:(string * string) list ->
?in_channel:Netchannels.in_obj_channel ->
Nethttpd_types.extended_environment -> Nethttpd_types.extended_environment
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_kernel.modify_http_protocol_config.html0000644000175000017500000004241212731530354027261 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.modify_http_protocol_config ?config_max_reqline_length:int ->
?config_max_header_length:int ->
?config_max_trailer_length:int ->
?config_limit_pipeline_length:int ->
?config_limit_pipeline_size:int ->
?config_announce_server:Nethttpd_kernel.announcement ->
?config_suppress_broken_pipe:bool ->
?config_tls:Netsys_crypto_types.tls_config option ->
Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.poll_engine-c.html0000644000175000017500000004347312731530354023455 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.poll_engine

Class Uq_engines_compat.poll_engine

class poll_engine : ?extra_match:exn -> bool -> (Unixqueue.operation * float) list -> Unixqueue.event_system -> object .. end
Inherits
method restart : unit -> unit
method group : Unixqueue.group
ocamlnet-4.1.2/doc/html-main/type_Netmime.basic_mime_header.html0000644000175000017500000004073112731530354023333 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.basic_mime_header (string * string) list -> Netmime.mime_headerocamlnet-4.1.2/doc/html-main/Netconversion.conversion_pipe-c.html0000644000175000017500000004631512731530354023556 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netconversion.conversion_pipe

Class Netconversion.conversion_pipe

class conversion_pipe : ?subst:int -> string -> in_enc:encoding -> out_enc:encoding -> unit -> Netchannels.io_obj_channel
This pipeline class (see Netchannels for more information) can be used to recode a netchannel while reading or writing. The argument in_enc is the input encoding, and out_enc is the output encoding.

The channel must consist of a whole number of characters. If it ends with an incomplete multi-byte character, however, this is detected, and the exception Malformed_code will be raised. This exception is also raised for other encoding errors in the channel data.

Example. Convert ISO-8859-1 to UTF-8 while writing to the file "output.txt":

    let ch = new output_channel (open_out "output.txt") in
    let encoder = 
      new conversion_pipe ~in_enc:`Enc_iso88591 ~out_enc:`Enc_utf8 () in
    let ch' = new output_filter encoder ch in
    ... (* write to ch' *)
    ch' # close_out();
    ch  # close_out();  (* you must close both channels! *)
 

If you write as UTF-16, don't forget to output the byte order mark yourself, as the channel does not do this.

Example. Convert UTF-16 to UTF-8 while reading from the file "input.txt":

    let ch = new input_channel (open_in "input.txt") in
    let encoder = 
      new conversion_pipe ~in_enc:`Enc_utf16 ~out_enc:`Enc_utf8 () in
    let ch' = new input_filter ch encoder in
    ... (* read from ch' *)
    ch' # close_in();
    ch  # close_in();  (* you must close both channels! *)
 


subst : This function is invoked for code points of in_enc that cannot be represented in out_enc, and the result of the function invocation is substituted (directly, without any further conversion). Restriction: The string returned by subst must not be longer than 50 bytes. If subst is missing, Cannot_represent is raised in this case.

ocamlnet-4.1.2/doc/html-main/type_Netsys_signal.html0000644000175000017500000004667012731530354021170 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_signal sig
  val register_handler :
    ?library:string ->
    ?priority:int ->
    ?keep_default:bool ->
    name:string -> signal:int -> callback:(int -> unit) -> unit -> unit
  val register_exclusive_handler :
    name:string -> signal:int -> install:(unit -> unit) -> unit -> unit
  val restore_management : int -> unit
  val keep_away_from : int -> unit
  type action = [ `Callback of int -> unit | `Install of unit -> unit ]
  type entry = {
    sig_number : int;
    sig_library : string option;
    sig_priority : int;
    sig_keep_default : bool;
    sig_name : string;
    sig_action : Netsys_signal.action;
  }
  val list : unit -> Netsys_signal.entry list
  val keep_away_list : unit -> int list
  val init : unit -> unit
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/type_Uq_transfer.copier.html0000644000175000017500000004112612731530354022106 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.copier Uq_transfer.copy_task -> Unixqueue.event_system -> [unit] Uq_engines.engineocamlnet-4.1.2/doc/html-main/Netsys_oothr.mtprovider-c.html0000644000175000017500000004636312731530354022416 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_oothr.mtprovider

Class type Netsys_oothr.mtprovider

class type mtprovider = object .. end

method single_threaded : bool
Whether this is a single-threaded program. In this case, a number of methods change their meaning, as described below.
method create_thread : 's 't. ('s -> 't) -> 's -> thread
In a multi-threaded program: Starts a new thread, and calls the passed function with the passed argument in the new thread (like Thread.create). In a single-threaded program: fails.
method self : thread
In a multi-threaded program: Returns the currently running thread. Subsequent calls of self can return different objects for the same thread, but the id method will always return the same number. In a single-threaded program: Returns a dummy object (see below).
method yield : unit -> unit
In a multi-threaded program: gives a hint that another thread should better run now. In a single-threaded program: this is a no-op.
method create_mutex : unit -> mutex
In a multi-threaded program: Creates a mutex and returns the object. In a single-threaded program: Returns a dummy mutex object (see below).
method create_condition : unit -> condition
In a multi-threaded program: Creates a condition variable and returns the object. In a single-threaded program: Returns a dummy variable (see below).
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.receiver-c.html0000644000175000017500000004265712731530354022771 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.receiver

Class Uq_engines_compat.receiver

class receiver : src:Unix.file_descr -> dst:#async_out_channel -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system -> [unit] engine

ocamlnet-4.1.2/doc/html-main/Nethttpd_kernel.http_protocol_hooks-c.html0000644000175000017500000004310412731530354024746 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_protocol_hooks

Class type Nethttpd_kernel.http_protocol_hooks

class type http_protocol_hooks = object .. end
Allows it to set hooks for Nethttpd_kernel.http_protocol

method tls_set_cache : store:(string -> string -> unit) ->
remove:(string -> unit) -> retrieve:(string -> string) -> unit
Sets the functions for accessing the session cache
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.modify_http_processor_config.html0000644000175000017500000004375012731530354027624 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.modify_http_processor_config ?modify_http_protocol_config:(Nethttpd_kernel.http_protocol_config ->
                              Nethttpd_kernel.http_protocol_config) ->
?config_timeout_next_request:float ->
?config_timeout:float ->
?config_cgi:Netcgi.config ->
?config_error_response:(Nethttpd_types.error_response_params -> string) ->
?config_log_error:(Nethttpd_types.request_info -> string -> unit) ->
?config_log_access:(Nethttpd_types.full_info -> unit) ->
?config_tls_cert_props:bool ->
?config_tls_remote_user:bool ->
Nethttpd_reactor.http_processor_config ->
Nethttpd_reactor.http_processor_config
ocamlnet-4.1.2/doc/html-main/Netplex_controller.Debug.html0000644000175000017500000004164512731530354022211 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_controller.Debug

Module Netplex_controller.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.server_socket_acceptor-c.html0000644000175000017500000004251112731530354025710 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.server_socket_acceptor

Class type Uq_engines_compat.server_socket_acceptor

class type server_socket_acceptor = server_endpoint_acceptor

ocamlnet-4.1.2/doc/html-main/Uq_engines.multiplex_controller-c.html0000644000175000017500000005207312731530354024101 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.multiplex_controller

Class type Uq_engines.multiplex_controller

class type multiplex_controller = object .. end
This definition has now been moved to Uq_multiplex.multiplex_controller

method alive : bool
method mem_supported : bool
method event_system : Unixqueue.event_system
method tls_session_props : Nettls_support.tls_session_props option
method tls_session : (string * string) option
method tls_stashed_endpoint : unit -> exn
method reading : bool
method start_reading : ?peek:(unit -> unit) ->
when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
method start_mem_reading : ?peek:(unit -> unit) ->
when_done:(exn option -> int -> unit) ->
Netsys_mem.memory -> int -> int -> unit
method cancel_reading : unit -> unit
method writing : bool
method start_writing : when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
method start_mem_writing : when_done:(exn option -> int -> unit) ->
Netsys_mem.memory -> int -> int -> unit
method supports_half_open_connection : bool
method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit
method cancel_writing : unit -> unit
method read_eof : bool
method wrote_eof : bool
method shutting_down : bool
method start_shutting_down : ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
method cancel_shutting_down : unit -> unit
method inactivate : unit -> unit
ocamlnet-4.1.2/doc/html-main/Netsys.html0000644000175000017500000017514412731530354016571 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys

Module Netsys

module Netsys: sig .. end
System calls missing in the Unix module


Generic file descriptors



Generic file descriptors



Not all OS provide generic read/write functions, or some emulation layer does not allow to use a descriptor with read/write. In the following functions, the style of the descriptor can be passed along with the descriptor to select the right I/O method. Effectively, the fd_style indicates which I/O function to call. Sometimes it is mandatory to call this function, sometimes it is only a good advice because the function provides the best interface for the kind of descriptor.
type fd_style = [ `Read_write
| `Recv_send of Unix.sockaddr * Unix.sockaddr
| `Recv_send_implied
| `Recvfrom_sendto
| `TLS of Netsys_crypto_types.file_tls_endpoint
| `W32_event
| `W32_input_thread
| `W32_output_thread
| `W32_pipe
| `W32_pipe_server
| `W32_process ]
Some information what kind of operations are reasonable for descriptors:
  • `Read_write: The descriptor is neither a socket not one of the other special cases, so only read/write is possible if read/write is possible at all. This style is also used if it is meaningless to use data I/O like read/write at all.
  • `Recv_send(sockaddr,peeraddr): The descriptor is a connected socket. recv/send are the preferred operations.
  • `Recvfrom_sendto: The descriptor is an unconnected socket, and it is possible to ask for addresses when exchanging data, so recvfrom/sendto are the preferred operations.
  • `Recv_send_implied: The descriptor is a socket with implied connection. There are no socket addresses. recv/send are the preferred operations. It is not possible to call getsockname or getpeername.
  • `W32_pipe: The descriptor is a proxy descriptor for a Win32 named pipe as returned by Netsys_win32.pipe_descr.
  • `W32_pipe_server: The descriptor is a proxy descriptor for a Win32 pipe server as returned by Netsys_win32.pipe_server_descr.
  • `W32_event: The descriptor is a Win32 proxy descriptor for an event as returned by Netsys_win32.create_event. It is not possible to read/write with these descriptors.
  • `W32_process: The descriptor is a proxy descriptor for a Win32 process as returned by Netsys_win32.create_process. It is not possible to read/write with these descriptors.
  • `W32_input_thread: The descriptor is a proxy descriptor for a Win32-specific input thread as returned by Netsys_win32.create_input_thread.
  • `W32_output_thread: The descriptor is a proxy descriptor for a Win32-specific output thread as returned by Netsys_win32.create_output_thread.
  • `TLS endpoint: A TLS tunnel is running over the descriptor. The details of the tunnel can be found in endpoint. Note that it is allowed that the endpoint uses a second descriptor for either reading or writing (i.e. reading and writing go via different descriptors). In this case, it is sufficient that one of these descriptors is accompanied with `TLS endpoint.
Win32: For the exact meaning of proxy descriptors, please see Netsys_win32. In short, a proxy descriptor is an abstract handle for the I/O object. The handle itself cannot be used for I/O, however, but only some specialized function. The proxy descriptor can only be used to dereference the I/O object. Note that the following functions like gread and gwrite automatically look up the I/O object behind the proxy and call the right I/O function.
val get_fd_style : Unix.file_descr -> fd_style
Get the file descriptor style.

The following styles cannot be determined automatically:

  • `TLS

val gread : fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> int
gread fd_style fd s pos len: Reads up to len bytes from descriptor fd which is supposed to support the I/O style fd_style, i.e. the right system call (read, recv, recvfrom) is chosen to read from the descriptor. After n <= len bytes have been read these are put into string s at positions pos to pos+n-1, and n is returned. The function can fail with any I/O exception defined for the actually performed I/O operation. Whether the operation is blocking or non-blocking depends on the descriptor.

If len>0 but n=0 the end of the input data is reached.

val gread_tbuf : fd_style ->
Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> int
Same for a tagged buffer
val blocking_gread : fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> int
let p = blocking_gread fd_style fd s pos len: Like gread up to len bytes are read from fd and stored in s. If the I/O operation is blocking but the descriptor is in non-blocking mode, this function blocks until the operation can be performed. If the operation is interrupted by a signal it is automatically restarted.

If n < len the end of the input data is reached (where n is the returned number).

See wait_until_readable below for further information which types of descriptors can be handled in non-blocking mode.

val blocking_gread_tbuf : fd_style ->
Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> int
Same for a tagged buffer
val really_gread : fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> unit
really_read fd_style fd s pos len: Reads exactly len bytes from fd and stores them in s starting at pos. If the end of file condition is seen before len bytes are read, the exception End_of_file is raised, and it is unspecified how many bytes have been stored in s. Like blocking_gread, non-blocking descriptors are forced to block until the operation becomes possible, and interruptions by signals are handled.

See wait_until_readable below for further information which types of descriptors can be handled in non-blocking mode.

val really_gread_tbuf : fd_style ->
Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> unit
Same for a tagged buffer
val gwrite : fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> int
gwrite fd_style fd s pos len: Writes up to len bytes to descriptor fd which is supposed to support the I/O style fd_style, i.e. the right system call (write, send, sendto) is chosen to write to the descriptor. . The n <= len written bytes are taken from string s, starting at position pos until pos+n-1. The number n is returned. The function can fail with any I/O exception defined for the actually performed I/O operation. Whether the operation is blocking or non-blocking depends on the descriptor.
val gwrite_tstr : fd_style ->
Unix.file_descr -> Netsys_types.tstring -> int -> int -> int
Same for a tagged string
val gwrite_tbuf : fd_style ->
Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> int
Same for a tagged buffer
val really_gwrite : fd_style -> Unix.file_descr -> Bytes.t -> int -> int -> unit
really_write fd_style fd s pos len: Writes exactly the len bytes from s to fd starting at pos. If the I/O operation is blocking but the descriptor is in non-blocking mode, this function blocks until the operation can be performed. If the operation is interrupted by a signal it is automatically restarted.

See wait_until_writable below for further information which types of descriptors can be handled in non-blocking mode.

val really_gwrite_tstr : fd_style ->
Unix.file_descr -> Netsys_types.tstring -> int -> int -> unit
Same for a tagged string
val really_gwrite_tbuf : fd_style ->
Unix.file_descr -> Netsys_types.tbuffer -> int -> int -> unit
Same for a tagged buffer
exception Shutdown_not_supported
See gshutdown
val gshutdown : fd_style -> Unix.file_descr -> Unix.shutdown_command -> unit
gshutdown fd_style fd cmd: If there is the possibility to shut down the connection for this kind of descriptor, the shutdown is tried. It is possible that the function raises the EAGAIN Unix error if the shutdown operation is non-blocking, and currently not possible. It is suggested to wait until the descriptor is writable, and to try again then.

If there is no shutdown operation for this kind of descriptor, the exception Shutdown_not_supported is raised. In this case it is usually sufficient to close the descriptor (gclose, see below), and when all descriptors to the resource are closed, the resource is shut down by the OS.

Details by fd_style:

  • `Recv_send and `Recv_send_implied: The socket is shut down as requested by Unix.shutdown. This only triggers the shutdown, but does not wait until it is completed. Also, errors are usually not immediately reported.
  • `W32_pipe: It is only possible to request SHUTDOWN_ALL for these descriptors. For other shutdown types, the error EPERM is reported. The shutdown is synchronous and completed when the function returns.
  • `W32_pipe_server: It is only possible to request SHUTDOWN_ALL for these descriptors. For other shutdown types, the error EPERM is reported. A shutdown means here to stop accepting new connections. The shutdown is synchronous and completed when the function returns.
  • `W32_output_thread: It is only possible to request SHUTDOWN_SEND for these descriptors. A SHUTDOWN_ALL is also interpreted as SHUTDOWN_SEND, and a SHUTDOWN_RECEIVE is ignored. A shutdown means here that the EOF is appended to the output buffer, and when the output thread has written the buffer contents, the underlying descriptor (not fd!) will be closed. The shutdown operation is non-blocking. If it is not possible at the moment of calling, the error EAGAIN is reported.
  • `TLS: The shutdown only affects the tunnel as such, but not the underlying connection. SHUTDOWN_SEND and SHUTDOWN_ALL are supported. SHUTDOWN_RECEIVE is ignored.
  • Other styles raise Shutdown_not_supported.

val is_readable : fd_style -> Unix.file_descr -> bool
val is_writable : fd_style -> Unix.file_descr -> bool
val is_prird : fd_style -> Unix.file_descr -> bool
Test whether the descriptor would not block if one of the input, output, or priority input operations were done.

On POSIX systems the tests work for a wide variety of descriptor types (but not for regular files which are assumed to be always readable and writable). If the poll interface is available it is preferred over the select interface to conduct the test.

On Win32, the tests are limited to sockets, named pipes and event objects. (The latter two only in the form provided by Netsys_win32, see there.)

For `TLS fd styles, the functions are "best effort" only.

Generally, if the blocking status cannot be determined for a class of I/O operations, the functions return true, in the hope that it is better to block than to never conduct the operation.

val wait_until_readable : fd_style -> Unix.file_descr -> float -> bool
val wait_until_writable : fd_style -> Unix.file_descr -> float -> bool
val wait_until_prird : fd_style -> Unix.file_descr -> float -> bool
Wait until an operation for a single descriptor becomes possible. The float argument is the timeout (negative value means no timeout). Returns whether the operation is possible (true). Otherwise, there was a timeout (false).

On POSIX systems this works for a wide variety of descriptor types (but not for regular files which are assumed to be always readable and writable). If the poll interface is available it is preferred over the select interface to wait for I/O. The functions also catch interruptions by signals.

On Win32, waiting is limited to sockets, named pipes and event objects. (The latter two only in the form provided by Netsys_win32, see there.)

For `TLS fd styles, the functions are "best effort" only.

Generally, if waiting is not supported for a class of I/O operations, the functions return immediately true, in the hope that it is better to block than to never conduct the operation.

val gclose : fd_style -> Unix.file_descr -> unit
Shuts down the system object referenced by the descriptor so far possible, and closes the descriptor.

Errors are logged to Netlog as `Crit events, and do not generate exceptions.

The exact semantics of the close operation varies from descriptor style to descriptor style. Generally, gclose assumes that all I/O is done, and all buffers are flushed, and that one can tear down the underlying communication circuits. gclose is always the right choice when the I/O channel needs to be aborted after a fatal error, and it does not matter whether errors occur or not. If a data connection needs to be orderly closed (i.e. without data loss), one should first try to finish the communication, either by protocol means (e.g. wait for ACK messages), or by calling gshutdown first (see above).


Functions for sockets


val wait_until_connected : Unix.file_descr -> float -> bool
After a non-blocking connect has been initiated, this function can be used to wait until (1) the connect is successful, or (2) the connect fails, or (3) the operation times out. The float argument is the timeout value (negative value means no timeout). The function returns true for the cases (1) and (2), and false for case (3). The cases (1) and (2) can be further analyzed by calling connect_check (see below).

On POSIX, this function is identical to wait_until_writable. On Win32 the wait condition is slightly different.

On Win32, this function also tolerates client proxy descriptors for Win32 named pipes. However, there is no waiting - the function immediately returns.

val connect_check : Unix.file_descr -> unit
Tests whether the socket is connected with the peer after calling Unix.connect. If the socket is connected, the function returns normally. Otherwise, the current socket error is raised as a Unix.Unix_error exception. This function is intended to be called after a non-blocking connect has been initiated, and the success or error is indicated (e.g. after wait_until_connected returns).

Side effect: The per-socket error code may be reset.

On Win32, this function also tolerates client proxy descriptors for Win32 named pipes. However, there is no real check - the function immediately returns.

val domain_of_inet_addr : Unix.inet_addr -> Unix.socket_domain
Returns the socket domain of Internet addresses, i.e. whether the address is IPv4 or IPv6
val protostring_of_inet_addr : Unix.inet_addr -> string
val inet_addr_of_protostring : string -> Unix.inet_addr
Converts an IP address to the 4 bytes (IPv4) or 16 bytes (IPv6) representation in network byte order, and vice-versa
val getpeername : Unix.file_descr -> Unix.sockaddr
like Unix.getpeername, but errors are fixed up. ENOTCONN is ensured when the socked is unconnected or shut down.

Helper functions


val is_absolute : string -> bool
Whether this file path is absolute. Works for Unix and Win32.
val abspath : string -> string
Return an absolute path for this file. When Netsys_posix.realpath is available, this function is called, and the canonical path is returned. On Win32, first an arbitrary absolute path is created, and then the path is tried to be simplified by resolving "." and "..". If neither method works, the function raises Invalid_argument.

Note that the file needs to exist in general.

val restart : ('a -> 'b) -> 'a -> 'b
restart f arg calls f arg, and restarts this call if the exception Unix_error(EINTR,_,_) is caught.

Note that there are some cases where this handling of EINTR is not sufficient:

  • Functions that have a timeout argument like Unix.select: When EINTR is caught the timeout should be adjusted.
  • Unix.connect with a blocking descriptor because this is not well-enough specified by POSIX

val restart_tmo : (float -> 'b) -> float -> 'b
restart_tmo f tmo calls f with a timeout argument tmo, and restarted the call if the exception Unix_error(EINTR,_,_) is caught. In the restart case, the timeout argument is reduced by the already elapsed time.

Negative timeout arguments are interpreted as "no timeout".

val restarting_select : Unix.file_descr list ->
Unix.file_descr list ->
Unix.file_descr list ->
float -> Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
A wrapper around Unix.select that handles the EINTR condition.

Note: This function calls Unix.select and shares all pros and cons with Unix.select. In particular, the OS often sets a limit on the number (and/or the numeric value) of the descriptors (e.g. for Linux it is 1024, for Windows it is 64). On Ocaml 3.11 the Windows version of Unix.select includes some support for other types of descriptors than sockets.

val restart_wait : [ `R | `W ] -> fd_style -> Unix.file_descr -> ('a -> 'b) -> 'a -> 'b
restart_wait mode fd_style fd f arg: Calls f arg, and handles the following exceptions:
  • Unix_error(EINTR,_,_): Just calls f again
  • Unix_error(EAGAIN,_,_): waits until fd is readable or writable as designated by mode, and calls f again
  • Unix_error(EWOUDLBLOCK,_,_): same
  • Netsys_types.EAGAIN_RD: waits until fd is readable, and calls f again
  • Netsys_types.EAGAIN_WR: waits until fd is writable, and calls f again

val sleep : float -> unit
val restarting_sleep : float -> unit
Sleep for the passed time. restarting_sleep additionally handles EINTR.
val unix_error_of_code : int -> Unix.error
Converts an integer error into the corresponding variant
val int64_of_file_descr : Unix.file_descr -> int64
Returns the file descriptor as int64 number. Works for all OS.
val string_of_fd : Unix.file_descr -> string
Return a string describing the descriptor (for debugging)
val string_of_sockaddr : ?norm:bool -> Unix.sockaddr -> string
Returns a human-readable string describing the address (for debug messages). If norm, IPv4 addresses mapped to the IPv6 address space are returned in the normal dotted quad format (i.e. x.y.z.u instead of ::ffff:x.y.z.u).

Note that the reverse (parsing such a string) can be accomplished with Netsockaddr.socksymbol_of_string and Uq_resolver.sockaddr_of_socksymbol.

val string_of_fd_style : fd_style -> string
Returns a string describing the fd style (debugging)
val is_stdin : Unix.file_descr -> bool
val is_stdout : Unix.file_descr -> bool
val is_stderr : Unix.file_descr -> bool
Returns whether the descriptors are stdin/stdout/stderr
val set_close_on_exec : Unix.file_descr -> unit
val clear_close_on_exec : Unix.file_descr -> unit
Working versions of the functions with the same name in Unix
val _exit : int -> unit
Exit the program immediately without running the atexit handlers. The argument is the exit code, just as for exit.

IPv6


val is_ipv6_system : unit -> bool
Whether IPv6 is available and usable. At the moment this tests for the presence of a global IPv6 address on any interface. The test also requires that the getifaddrs() call is available. The test can be overridden with set_ipv6_system.
val set_ipv6_system : bool -> unit
Sets whether IPv6 is usable

IP addresses


val logand_inet_addr : Unix.inet_addr -> Unix.inet_addr -> Unix.inet_addr
Returns the bitwise AND of the two argument addresses
val logor_inet_addr : Unix.inet_addr -> Unix.inet_addr -> Unix.inet_addr
Returns the bitwise OR of the two argument addresses
val logxor_inet_addr : Unix.inet_addr -> Unix.inet_addr -> Unix.inet_addr
Returns the bitwise XOR of the two argument addresses
val lognot_inet_addr : Unix.inet_addr -> Unix.inet_addr
Returns the bitwise NOT of the argument address
val norm_inet_addr : Unix.inet_addr -> Unix.inet_addr
Normalization: If the input address is an IPv4 address mapped into the IPv6 address space, the IPv4 address is extracted. Otherwise, the input address is returned unchanged.
val ipv6_inet_addr : Unix.inet_addr -> Unix.inet_addr
IPv6-ification: If the input address is for IPv4, it is mapped to the IPv6 address space (so an IPv6 socket can be bound)
val is_ipv4_inet_addr : Unix.inet_addr -> bool
Whether the address is an IPv4 address (including IPv4 addresses mapped into the IPv6 adress space)
val is_ipv6_inet_addr : Unix.inet_addr -> bool
Whether the address is an IPv6 address (excluding IPv4 addresses mapped into the IPv6 adress space)
val is_multicast_inet_addr : Unix.inet_addr -> bool
Whether the address is a multicast address (either IPv4 or IPv6)

Multicast Functions


val mcast_set_loop : Unix.file_descr -> bool -> unit
Whether sent multicast messages are received by the sending host
val mcast_set_ttl : Unix.file_descr -> int -> unit
Set TTL/hops value
val mcast_add_membership : Unix.file_descr -> Unix.inet_addr -> Unix.inet_addr -> unit
Join a multicast group.

First inet addr is the group to join. Second inet addr selects the network interface (or Unix.inet_addr_any).

val mcast_drop_membership : Unix.file_descr -> Unix.inet_addr -> Unix.inet_addr -> unit
Leave a multicast group.

First inet addr is the group to leave. Second inet addr selects the network interface (or Unix.inet_addr_any).


Profiling


val moncontrol : bool -> unit
Interface to the moncontrol routine of the GPROF profiler. moncontrol false stops profiling; moncontrol true starts profiling again.

This is a no-op if the program is not compiler for profiling.


Further Documentation



Further Documentation



How to orderly close I/O channels

After reading from uni-directional descriptors, and seeing the EOF, it is usually sufficient to call gclose to free OS resources.

After writing to uni-directional descriptors one should call gshutdown to send an EOF (SHUTDOWN_SEND). For some descriptors one will get the exception Shutdown_not_supported which can be ignored in this context The gshutdown function cannot, however, report in all cases whether the operation was successful. As a rule of thumb, error reporting works for local data connections, but not always for remote connections, and there is no way to fix this. After writing EOF, call gclose to free OS resources.

For bidirectional connections, it is even more complicated. If the connection is local, a bidirectional connection behaves much like a pair of unidirectional connections. However, in the network case, we have to go down to the protocol level.

For TCP the golden rule is that the client initiates the connection, and the client finishes the connection. The case that the server finishes the connection is not well-specified - or better, the server needs the ACK from the client after triggering the connection termination. In practice we have the cases:

  • Client sends EOF, and server replies with EOF: This is the normal case for which TCP is designed. Client code can invoke gshutdown with SHUTDOWN_SEND and then waits until the EOF from the server arrives, and then gcloses the descriptor. It may happen that the client gets an error if some problem occurs, so this is reliable from the perspective of the client. The server first sees the EOF from the client, and then responds with another gshutdown, followed by gclose. From the server's perspective it does not matter whether the operation results in an error or not - the client has lost interest anyway.
  • Client sends EOF, and server replies with data, and then EOF. Here, the client has to read the final data, and then wait for the server's EOF after sending its own EOF. On the server's side, some data is written before the final EOF. The question is how the server can be sure that the data really arrived. Unfortunately, there is no way to do so. The server may not get all errors because these may arrive at the server computer after gshutdown. There is no way to fix this. (One should better fix the application protocol. Note that even prominent researchers trapped into this problem. For example, the first version of HTTP had this problem.)
  • Server sends EOF, and client replies with EOF: This is the difficult case. Here, the server wants to be sure that the data sent immediately before its EOF really arrives at the client. After gshutdown it is forbidden to immediately gclose, because this may result in a connection reset. Instead, the server has to wait for the client's EOF. (This is called "lingering".) If the client's EOF is seen one can gclose.
  • Server sends EOF, and client replies with data, followed by EOF: I admit I don't know whether TCP can handle this somehow.


Further Documentation



How to orderly close I/O channels

After reading from uni-directional descriptors, and seeing the EOF, it is usually sufficient to call gclose to free OS resources.

After writing to uni-directional descriptors one should call gshutdown to send an EOF (SHUTDOWN_SEND). For some descriptors one will get the exception Shutdown_not_supported which can be ignored in this context The gshutdown function cannot, however, report in all cases whether the operation was successful. As a rule of thumb, error reporting works for local data connections, but not always for remote connections, and there is no way to fix this. After writing EOF, call gclose to free OS resources.

For bidirectional connections, it is even more complicated. If the connection is local, a bidirectional connection behaves much like a pair of unidirectional connections. However, in the network case, we have to go down to the protocol level.

For TCP the golden rule is that the client initiates the connection, and the client finishes the connection. The case that the server finishes the connection is not well-specified - or better, the server needs the ACK from the client after triggering the connection termination. In practice we have the cases:

  • Client sends EOF, and server replies with EOF: This is the normal case for which TCP is designed. Client code can invoke gshutdown with SHUTDOWN_SEND and then waits until the EOF from the server arrives, and then gcloses the descriptor. It may happen that the client gets an error if some problem occurs, so this is reliable from the perspective of the client. The server first sees the EOF from the client, and then responds with another gshutdown, followed by gclose. From the server's perspective it does not matter whether the operation results in an error or not - the client has lost interest anyway.
  • Client sends EOF, and server replies with data, and then EOF. Here, the client has to read the final data, and then wait for the server's EOF after sending its own EOF. On the server's side, some data is written before the final EOF. The question is how the server can be sure that the data really arrived. Unfortunately, there is no way to do so. The server may not get all errors because these may arrive at the server computer after gshutdown. There is no way to fix this. (One should better fix the application protocol. Note that even prominent researchers trapped into this problem. For example, the first version of HTTP had this problem.)
  • Server sends EOF, and client replies with EOF: This is the difficult case. Here, the server wants to be sure that the data sent immediately before its EOF really arrives at the client. After gshutdown it is forbidden to immediately gclose, because this may result in a connection reset. Instead, the server has to wait for the client's EOF. (This is called "lingering".) If the client's EOF is seen one can gclose.
  • Server sends EOF, and client replies with data, followed by EOF: I admit I don't know whether TCP can handle this somehow.


Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Netsys_gssapi.server_config.html0000644000175000017500000004227212731530354024025 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_gssapi.server_config object
  method acceptor_name : (string * Netsys_gssapi.oid) option
  method flags : (Netsys_gssapi.req_flag * Netsys_gssapi.support_level) list
  method integrity : Netsys_gssapi.support_level
  method mech_types : Netsys_gssapi.oid list
  method privacy : Netsys_gssapi.support_level
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.poll_process_engine-c.html0000644000175000017500000004263112731530354025206 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.poll_process_engine

Class Uq_engines_compat.poll_process_engine

class poll_process_engine : ?period:float -> pid:int -> Unixqueue.event_system -> [Unix.process_status] engine

ocamlnet-4.1.2/doc/html-main/type_Netaddress.html0000644000175000017500000004606312731530354020436 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaddress sig
  type local_part = string
  type domain = string
  type addr_spec = Netaddress.local_part * Netaddress.domain option
  class mailbox :
    ?name:string ->
    string list ->
    Netaddress.addr_spec ->
    object
      method name : string
      method route : string list
      method spec : Netaddress.addr_spec
    end
  class group :
    string ->
    Netaddress.mailbox list ->
    object
      method mailboxes : Netaddress.mailbox list
      method name : string
    end
  type t = [ `Group of Netaddress.group | `Mailbox of Netaddress.mailbox ]
  exception Parse_error of int * string
  val parse : string -> Netaddress.t list
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi_dbi.DBI_POOL.html0000644000175000017500000004217212731530354021614 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_dbi.DBI_POOL sig
  type connection
  val get :
    Netcgi.cgi ->
    ?host:string ->
    ?port:string ->
    ?user:string ->
    ?password:string -> string -> Netcgi_dbi.DBI_POOL.connection
end
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_types.extended_environment.html0000644000175000017500000005662212731530354025605 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types.extended_environment object
  method cgi_auth_type : string
  method cgi_gateway_interface : string
  method cgi_https : bool
  method cgi_path_info : string
  method cgi_path_translated : string
  method cgi_properties : (string * string) list
  method cgi_property : ?default:string -> string -> string
  method cgi_query_string : string
  method cgi_remote_addr : string
  method cgi_remote_host : string
  method cgi_remote_ident : string
  method cgi_remote_user : string
  method cgi_request_method : string
  method cgi_request_uri : string
  method cgi_script_name : string
  method cgi_server_name : string
  method cgi_server_port : int option
  method cgi_server_protocol : string
  method cgi_server_software : string
  method config : Netcgi.config
  method cookie : string -> Netcgi.Cookie.t
  method cookies : Netcgi.Cookie.t list
  method input_body_size : int64
  method input_channel : Netchannels.in_obj_channel
  method input_content_length : int
  method input_content_type :
    unit -> string * (string * Netmime_string.s_param) list
  method input_content_type_string : string
  method input_header : Netmime.mime_header
  method input_header_field : ?default:string -> string -> string
  method input_header_fields : (string * string) list
  method log_error : string -> unit
  method log_props : (string * string) list -> unit
  method multiple_input_header_field : string -> string list
  method multiple_output_header_field : string -> string list
  method out_channel : Netchannels.out_obj_channel
  method output_ch : Netchannels.out_obj_channel
  method output_header : Netmime.mime_header
  method output_header_field : ?default:string -> string -> string
  method output_header_fields : (string * string) list
  method output_state : Nethttpd_types.output_state Pervasives.ref
  method protocol : Nethttp.protocol
  method remote_socket_addr : Unix.sockaddr
  method request_body_rejected : bool
  method send_file : Unix.file_descr -> int64 -> unit
  method send_output_header : unit -> unit
  method server_socket_addr : Unix.sockaddr
  method set_multiple_output_header_field : string -> string list -> unit
  method set_output_header_field : string -> string -> unit
  method set_output_header_fields : (string * string) list -> unit
  method set_status : Nethttp.http_status -> unit
  method tls_session_props : Nettls_support.tls_session_props option
  method user_agent : string
end
ocamlnet-4.1.2/doc/html-main/Netsendmail.html0000644000175000017500000011416712731530354017545 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsendmail

Module Netsendmail

module Netsendmail: sig .. end
Functions to compose and send electronic mails

Contents

The tutorial has been moved to Netsendmail_tut.


Composing Messages

The core function is Netsendmail.compose generating a MIME mail. The mail can be sent with Netsendmail.sendmail, written to an object channel with Netmime.write_mime_message, or postprocessed by a user function.

The call to compose can be as easy as

 compose ~from_addr:("me", "me@domain.net") 
            ~to_addrs:["you", "you@domain.com"]
            ~subject:"I have a message for you"
            "Hello, this is my message!\n"
 

This call generates the message as Netmime.complex_mime_message, and can be directly sent with Netsendmail.sendmail.

The compose function is the simplified interface; alternatively one can also generate the mail by calling Netsendmail.wrap_mail, Netsendmail.wrap_parts, and Netsendmail.wrap_attachment, getting more fine-grained control of certain options.

val compose : ?in_charset:Netconversion.encoding ->
?out_charset:Netconversion.encoding ->
?from_addr:string * string ->
?cc_addrs:(string * string) list ->
?bcc_addrs:(string * string) list ->
?content_type:string * (string * Netmime_string.s_param) list ->
?container_type:string * (string * Netmime_string.s_param) list ->
?attachments:Netmime.complex_mime_message list ->
to_addrs:(string * string) list ->
subject:string -> string -> Netmime.complex_mime_message
Composes a mail message with a main text, and optionally a number of attachments.

The addresses from_addr, to_addrs, cc_addrs, and bcc_addrs are passed as pairs (human_readable,formal) where human_readable is an arbitrary printable string identifying the sender/receiver, and where formal is the RFC-822 mailbox specification. An example is ("Stolpmann, Gerd", "gerd@gerd-stolpmann.de").

The subject can be any text.

The anonymous string argument is the main text of the mail.

The resulting message is always a correct MIME message.


in_charset : All passed texts (except the formal addresses) must be encoded in in_charset. Default: `Enc_iso88591. As another exception, setting content_type explicitly prevents the main text from being converted, and in_charset does not have a meaning for the main text.
out_charset : The encoded words in the generated header fields, if necessary, and the main text are encoded in out_charset. Default: `Enc_iso88591. It is required that out_charset is ASCII-compatible. As a special rule, setting content_type explicitly prevents the main text from being converted to out_charset.
content_type : The content type of the main text. The list is the list of parameters attached to the type, e.g. ("text/plain", ["charset", mk_param "ISO-8859-1"]) (see Netmime_string.mk_param). When this argument is set, the main text is no longer converted to out_charset. By default, when this argument is missing, the main text is converted from in_charset to out_charset, and the content type becomes "text/plain; charset=<out_charset>".
container_type : The content type of the container wrapping the main text and the attachment into one entity (only used if attachments are present). This defaults to ("multipart/mixed", []). This must be either a "multipart" or "message" type.
attachments : An optional list of attachments. Should be generated with wrap_attachment.

Character Set Conversion

The impact of in_charset and out_charset on the generated mail is not very obvious. The charset arguments may have an effect on the mail header and the mail body.

The mail header can only be composed of ASCII characters (7 bit). To circumvent this restriction the MIME standard specifies a special format, the so-called encoded words. These may only be used in some places, and compose knows where: In the subject, and the non-formal part of mail addresses. The out_charset is the character set used in the generated mail. The in_charset is the character set the strings are encoded you pass to compose. It is a good idea to have in_charset = out_charset, or at least choose out_charset as a superset of in_charset, because this ensures that the character set conversion succeeds.

If the mail header does not make use of the additional non-ASCII characters, the encoded words will be avoided.

The mail body is only subject of character set conversion if the content_type is not passed to compose. In this case, the function sets it to text/plain, and converts the message from in_charset to out_charset.

Adding Attachments

To generate the attachments, call Netsendmail.wrap_attachment, e.g.

 compose ...
      ~attachments:[ wrap_attachment  
                       ~content_type:("application/octet-stream", [])
                       (new Netmime.file_mime_body "file.tar.gz") ]
 

There are a number of kinds of attaching files, identified by container_type. The default is multipart/mixed, meaning that the parts of the mail are mixed messages and files. One can give a hint whether to display the parts directly in the mailer program (so-called inline attachments), or whether to suggest that the file is saved to disk ("real" attachments). This hint is contained in the Content-disposition header, see wrap_attachment how to set it.

For a discusion of the other container_types see the Netsendmail.tutorial at the end of this document.

val wrap_attachment : ?in_charset:Netconversion.encoding ->
?out_charset:Netconversion.encoding ->
?content_id:string ->
?content_description:string ->
?content_location:string ->
?content_disposition:string * (string * Netmime_string.s_param) list ->
content_type:string * (string * Netmime_string.s_param) list ->
Netmime.mime_body -> Netmime.complex_mime_message
Generates a header for the mime_body. The returned value is intended to be used as input for the attachments argument of the compose function:

 compose ...
    ~attachments:[ wrap_attachment
                      ~content_type:("audio/wav", [])
                      (new file_mime_body "music.wav") ]
 

The header contains at least the Content-type and the Content-transfer-encoding fields. The latter is currently always "base64", but it is possible that the function is changed in the future to also generate "quoted-printable" when applicable.


in_charset : The encoding of the content_description argument. Default: `Enc_iso88591.
out_charset : The encoding of the generated Content-Description header. Default: `Enc_iso88591.
content_id : Optionally sets the Content-ID header field. The passed string is the ID value without the embracing angle brackets. The Content-ID can be used to refer to the attachment from other parts of the mail, e.g. in multipart/related mails HTML documents can include hyperlinks to attachments using the URL syntax cid:ID where ID is the ID value.
content_description : The Content-Description header
content_location : The Content-Location header. This must be a valid URL, only composed of 7 bit characters, and with escaped unsafe characters
content_disposition : Optionally sets the Content-disposition header. Frequent values are
  • ("inline", []) : Indicates that the attachment is displayed together with the main text
  • ("attachment", ["filename", Netmime_string.mk_param fn]) : Indicates that the attachment should be stored onto the disk. The parameter fn is the suggested file name. Note that fn should only consist of ASCII characters unless the charset argument of mk_param is set to a different character encoding.
content_type : Specifies the content type with main type and list of parameters. Example: ("text/plain", ["charset", Netmime_string.mk_param "ISO-8859-1" ]) (see Netmime_string.mk_param)
val wrap_mail : ?in_charset:Netconversion.encoding ->
?out_charset:Netconversion.encoding ->
?from_addr:string * string ->
?cc_addrs:(string * string) list ->
?bcc_addrs:(string * string) list ->
to_addrs:(string * string) list ->
subject:string ->
Netmime.complex_mime_message -> Netmime.complex_mime_message
Sets the mail-related header fields in the input message, and returns a message ready for delivery. Transfer- and delivery-related header fields are removed from the message first, and the new fields are set to the values passed to this function.

The arguments are like in Netsendmail.compose.

The input message should have at least a Content-type header, but this is not enforced.

Use this function as an alternative to Netsendmail.compose, if the message is already available as complex_mime_message, e.g. to re-send a parsed mail message to a new destination.


Note: Resending Messages

Note that mails generated by wrap_mail always appear as new mails, not as forwarded or replied mails. In order to do the latter a different way of processing the message is needed.

val wrap_parts : ?in_charset:Netconversion.encoding ->
?out_charset:Netconversion.encoding ->
?content_type:string * (string * Netmime_string.s_param) list ->
?content_id:string ->
?content_description:string ->
?content_location:string ->
?content_disposition:string * (string * Netmime_string.s_param) list ->
Netmime.complex_mime_message list -> Netmime.complex_mime_message
Generates an intermediate container for multipart attachments. Use this if you want to bundle a set of attachments as a single attachment.


in_charset : The encoding of the content_description argument. Default: `Enc_iso88591.
out_charset : The encoding of the generated Content-Description header. Default: `Enc_iso88591.
content_type : The Content-Type header. Default: multipart/mixed
content_id : The Content-ID header, without the angle brackets
content_description : The Content-Description header
content_location : The Content-Location header. This must be a valid URL, only composed of 7 bit characters, and with escaped unsafe characters
content_disposition : The Content-Disposition header

Low-level
val create_address_list_tokens : ?in_charset:Netconversion.encoding ->
?out_charset:Netconversion.encoding ->
(string * string) list -> Netmime_string.s_token list
Returns the list of s_tokens representing email addresses as structured value. The addresses are passed as list of pairs (human_readable, formal) as in the compose function above. The returned structured field value can be formatted and filled into a mail header. For example, to set the "To" header to "Stolpmann, Gerd" <gerd@gerd-stolpmann.de> use
 let sval = create_address_list_tokens ["Stolpmann, Gerd",
                                        "gerd@gerd-stolpmann.de"] in
 header # update_field "to" (format_field_value "to" sval)
 
This ensures that the field is correctly quoted, that appropriate encodings are applied and that long values are folded into several lines.


in_charset : The character encoding used for human_readable. Defaults to `Enc_iso88591.
out_charset : The character encoding used in the generated encoded word. This encoding must be ASCII-compatible. Defaults to `Enc_iso88591.
val create_text_tokens : ?in_charset:Netconversion.encoding ->
?out_charset:Netconversion.encoding -> string -> Netmime_string.s_token list
Returns the list of s_tokens representing an informal text as structured value. The text is passed as simple string. The returned structured field value can be formatted and filled into a mail header. For example, to set the "Subject" header to "I have to say something", use
 let sval = create_text_tokens "I have to say something" in
 header # update_field "subject" (format_field_value "subject" sval)
 
This ensures that the field is correctly quoted, that appropriate encodings are applied and that long values are folded into several lines.


in_charset : The character encoding used for the input string. Defaults to `Enc_iso88591.
out_charset : The character encoding used in the generated encoded words. This encoding must be ASCII-compatible. Defaults to `Enc_iso88591.
val format_field_value : string -> Netmime_string.s_token list -> string
To put sval, an s_token list, into the header field name, call

header # update_field name (format_field_value name sval)

The field value is folded into several lines, if necessary.


Sending Messages


val sendmail : ?mailer:string -> ?crlf:bool -> Netmime.complex_mime_message -> unit
Sends the passed message. The mailer program must be sendmail-compatible (this can be assumed on all Unix systems, even if a non-sendmail mailer is installed).

The mailer program is the command passed as mailer, which is by default a reasonable compile-time setting.

With crlf one can determine the EOL convention for the message piped to the mailer program: If crlf, CR/LF is used, if not crlf, only LF is used. The default is false for Unix systems.

See also Netsmtp.sendmail for a way to send emails via SMTP.

ocamlnet-4.1.2/doc/html-main/type_Netplex_sharedvar.Make_var_type.html0000644000175000017500000004200412731530354024574 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sharedvar.Make_var_type functor (T : Netplex_cenv.TYPE->
  sig type t = T.t val get : string -> t val set : string -> t -> unit end
ocamlnet-4.1.2/doc/html-main/Netmcore_condition.html0000644000175000017500000006703712731530354021127 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_condition

Module Netmcore_condition

module Netmcore_condition: sig .. end
Condition variables


Condition variables are here defined as values that reside in shared heaps (Netmcore_heap), for example in the header field of Netmcore_array or somewhere else in heap-allocated data structures.

In order to ensure that the condition variable is in the heap, the special function create_condition must be used to initialize it there. As create_condition requires a mutator as argument, this is only possible by calling create_condition from the callback of Netmcore_heap.modify.

Condition variables are special values, and cannot be copied or moved.

Condition variables are implemented on top of semaphores. Compared to the pthreads version of condition variables, the user needs here to allocate special wait_entry slots, one for each process. An entry can be used for all condition variables a process needs to wait for. (Actually, such entries also exist in typical pthreads implementations, but are hidden from the user in the thread control block. We just don't have here a place where we could allocate process-specific shared memory.)

Since Ocamlnet-3.5, there are also special wait entries wait_entry_e which can be used to wait from within a running Unixqueue. For each such wait entry, however, a named pipe needs to be allocated.

type condition 
The condition variable
type wait_entry 
Each process that wants to wait needs a wait_entry. These entries can be used for several condition variables, so typically each process has only one entry for each heap.
type wait_entry_e 
A special kind of wait_entry for intergration into an event loop
type wait_set 
A set of wait_entry, for easier management. This set can e.g. be stored side by side with the condition variable(s). It is important that the wait_set resides in the same shared heap as the condition variable.
val dummy_condition : unit -> condition
A dummy condition is non-functional, but can be used to put something into condition-typed variables
val dummy_wait_set : unit -> wait_set
A dummy wait_set is non-functional, but can be used to put something into wait_set-typed variables
val create_condition : Netmcore_heap.mutator -> condition
create m: Creates a condition variable, and pushes it to the heap, using the mutator m.

After being pushed to the heap, the variable can be used. It is nonsense to copy it outside the heap.

val create_wait_set : Netmcore_heap.mutator -> wait_set
Creates a wait_set in the heap designated by the mutator
val alloc_wait_entry : Netmcore_heap.mutator ->
wait_set -> wait_entry
Allocates a wait_entry
val free_wait_entry : Netmcore_heap.mutator ->
wait_set -> wait_entry -> unit
Frees a wait_entry
val alloc_wait_entry_e : Netmcore_heap.mutator ->
wait_set -> string -> wait_entry_e
alloc_wait_entry_e mut set filename: Allocates a new wait entry with notification via named pipe. The filename must refer to an existing named pipe.
val free_wait_entry_e : Netmcore_heap.mutator ->
wait_set -> wait_entry_e -> unit
Frees a wait_entry_e. The named pipe is deleted.
val wait : wait_entry ->
condition -> Netmcore_mutex.mutex -> unit
wait we c m atomically unlocks the mutex m and suspends the calling process on the condition variable c. The process will restart after the condition variable c has been signalled. The mutex m is locked again before wait returns.

At the time of calling, the wait_entry we must not be used to manage another wait. When allocating a separate wait_entry per process this problem does not occur.

val wait_e : ?debug_name:string ->
wait_entry_e ->
condition ->
Netmcore_mutex.mutex ->
Unixqueue.event_system ->
(unit -> 'a Uq_engines.engine) -> 'a Uq_engines.engine
Like wait, but the suspension is done by waiting on a named pipe event (i.e. "nonblocking suspension"):

wait_e we c m esys cont atomically unlocks the mutex m and suspends the calling engine on the condition variable c. The engine will restart after the condition variable c has been signalled. The mutex m is locked again, at which time cont is called. The result of cont() is the result of wait_e.

At the time of calling, the wait_entry_e we must not be used to manage another wait_e. When allocating a separate wait_entry_e per process (or thread within the process) this problem does not occur.

val signal : condition -> unit
signal c restarts one of the processes waiting on the condition variable c.
val broadcast : condition -> unit
broadcast c restarts all processes waiting on the condition variable c.
val pipe_name : wait_entry_e -> string
Returns the name of the pipe
val destroy_condition : condition -> unit
val destroy_wait_set : wait_set -> unit
Destroys these objects
module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netnumber.html0000644000175000017500000010340612731530354017233 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netnumber

Module Netnumber

module Netnumber: sig .. end
Binary encodings of numbers


This is the successor of the Rtypes module

This is the successor of the Rtypes module

Numeric types


type int4 
32 bit signed integer
type int8 
64 bit signed integer
type uint4 
32 bit unsigned integer
type uint8 
64 bit unsigned integer
type fp4 
single precision float (IEEE "float")
type fp8 
double precision float (IEEE "double")
exception Cannot_represent of string
raised if a conversion can't be done
exception Out_of_range
raised if string position out of range

Basic encoding/decoding functions


val mk_int4 : char * char * char * char -> int4
val mk_int8 : char * char * char * char * char * char * char * char -> int8
val mk_uint4 : char * char * char * char -> uint4
val mk_uint8 : char * char * char * char * char * char * char * char -> uint8
mk_<t> create integer values from character tuples. In these tuples the MSB is the first component and the LSB the last.
val dest_int4 : int4 -> char * char * char * char
val dest_int8 : int8 -> char * char * char * char * char * char * char * char
val dest_uint4 : uint4 -> char * char * char * char
val dest_uint8 : uint8 -> char * char * char * char * char * char * char * char
dest_<t> destroy integer values and returns the corresponding char tuples.
val mk_fp4 : char * char * char * char -> fp4
val mk_fp8 : char * char * char * char * char * char * char * char -> fp8
val dest_fp4 : fp4 -> char * char * char * char
val dest_fp8 : fp8 -> char * char * char * char * char * char * char * char

Conversions



Conversions



Conversions from int to (u)int and vice versa. On 32-bit computers, the type int can hold 31-bit signed integers (including the sign, i.e. one bit cannot be used). On 64-bit computers, the type int can hold 63-bit signed integers (including the sign, i.e. one bit cannot be used). The int_of_xxx functions raise Cannot_represent if the number to convert is too big (or too small) to be represented as int. Note that this depends on the word size of your architecture.
val int_of_int4 : int4 -> int
val int_of_uint4 : uint4 -> int
val int_of_int8 : int8 -> int
val int_of_uint8 : uint8 -> int
val int4_of_int : int -> int4
val uint4_of_int : int -> uint4
val int8_of_int : int -> int8
val uint8_of_int : int -> uint8
val int32_of_int4 : int4 -> int32
val int32_of_uint4 : uint4 -> int32
val int32_of_int8 : int8 -> int32
val int32_of_uint8 : uint8 -> int32
val int4_of_int32 : int32 -> int4
val uint4_of_int32 : int32 -> uint4
val int8_of_int32 : int32 -> int8
val uint8_of_int32 : int32 -> uint8
val int64_of_int4 : int4 -> int64
val int64_of_uint4 : uint4 -> int64
val int64_of_int8 : int8 -> int64
val int64_of_uint8 : uint8 -> int64
val int4_of_int64 : int64 -> int4
val uint4_of_int64 : int64 -> uint4
val int8_of_int64 : int64 -> int8
val uint8_of_int64 : int64 -> uint8

Casts from uint4/uint8 to int32/int64. Here, the sign is ignored and simply considered as a bit.
val logical_uint4_of_int32 : int32 -> uint4
val logical_int32_of_uint4 : uint4 -> int32
val logical_uint8_of_int64 : int64 -> uint8
val logical_int64_of_uint8 : uint8 -> int64
val fp8_of_fp4 : fp4 -> fp8
val fp4_of_fp8 : fp8 -> fp4
Note fp4_of_fp8: This conversion is not exact. It is quite normal that precision is lost. Numbers too small or too large for fp4 are converted to the "infinity" value.
val float_of_fp4 : fp4 -> float
val float_of_fp8 : fp8 -> float
val fp4_of_float : float -> fp4
val fp8_of_float : float -> fp8
Note fp4_of_float: The same problems as in fp4_of_fp8 may arise

Comparisons



Comparisons



The comparisons "=" and "<>" work for all numbers.

For signed integers, the operators "<", "<=", ">", and ">=" work, too. The unsigned integer type use representation that are not compatible with these operators, and the following functions need to be called.

For fp4 and fp8 there are no comparison functions - convert to float first and compare then.

val lt_uint4 : uint4 -> uint4 -> bool
lt_uint4 is true iff the first value is less than the second value as unsigned int
val le_uint4 : uint4 -> uint4 -> bool
val gt_uint4 : uint4 -> uint4 -> bool
val ge_uint4 : uint4 -> uint4 -> bool
Other comparisons
val lt_uint8 : uint8 -> uint8 -> bool
lt_uint8 is true iff the first value is less than the second value as unsigned int
val le_uint8 : uint8 -> uint8 -> bool
val gt_uint8 : uint8 -> uint8 -> bool
val ge_uint8 : uint8 -> uint8 -> bool
Other comparisons

Minimum/maximum values


val min_int4 : int4
val min_uint4 : uint4
val min_int8 : int8
val min_uint8 : uint8
val max_int4 : int4
val max_uint4 : uint4
val max_int8 : int8
val max_uint8 : uint8
module type ENCDEC = sig .. end
module BE: ENCDEC 
Encoders/decoders for big endian - network byte order
module LE: ENCDEC 
Encoders/decoders for little endian
module HO: ENCDEC 
Encoders/decoders for host byte order - which is either little endian or big endian, depending on the CPU (or CPU mode)
ocamlnet-4.1.2/doc/html-main/Netchannels.input_string-c.html0000644000175000017500000004344512731530354022510 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_string

Class Netchannels.input_string

class input_string : ?pos:int -> ?len:int -> string -> in_obj_channel
Creates an input channel from a (constant) string.

The method pos_in reflects the real position in the string, i.e. a character read at position k can be found at s.[k] in the string s.


pos : The data of the channel begins at this position of the string. Default: 0
len : The data of the channel consists of this number of bytes. Default: until the end of the string

ocamlnet-4.1.2/doc/html-main/Rpc_simple_client.html0000644000175000017500000005044012731530354020726 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_simple_client

Module Rpc_simple_client

module Rpc_simple_client: sig .. end
Synchronous API for RPC clients


This is a synchronous client that suffices for most applications of RPC.
type t 
The type of simple clients
val create : Rpc_client.connector -> Rpc.protocol -> Rpc_program.t -> t
Create a simple client that connects with the given server using the given protocol type. The program argument specifies the remote program.
val call : t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
call simple_client procedure_name procedure_arg: Call the procedure with the given name and the given argument. Returns the result of the procedure on success; otherwise raises an exception.

Note that it is possible that the connection is aborted and the client is reset. In this case call raises an exception but it is currently difficult to recognize this case. Other reasons may be that the server refuses the call (e.g. because of missing authentication).

Frequent exceptions:

  • Rpc.Rpc_server condition: The server did not like the call; the 'condition' explains why
  • Rpc.Rpc_cannot_unpack reason: Got a badly formatted message.
  • Rpc_client.Message_lost: The stream ended before there was any reply (perhaps not even the call could be sent over the stream)
  • Rpc_client.Message_timeout: There was no reply for the specified period of time
  • Rpc_client.Communication_error x: An I/O error or a serious internal error happened Failure s: Mostly: The internal state of the client does not allow to do another call
Note that only the Rpc_server exception has clear semantics as it is known that the procedure has not been invoked. It is a good choice to shut down the connection if one of the other exceptions happens. (Note that the connection may already have been shutted down, but it is ok to shut down twice.)
val shut_down : t -> unit
Shut the connection down. After the client has been shutted down, it is not possible to call further remote procedures. Throw the client away and create a new one if you want to continue.
ocamlnet-4.1.2/doc/html-main/Netchannels.raw_in_channel_delegation-c.html0000644000175000017500000004253712731530354025126 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.raw_in_channel_delegation

Class Netchannels.raw_in_channel_delegation

class raw_in_channel_delegation : ?close:bool -> raw_in_channel -> raw_in_channel

ocamlnet-4.1.2/doc/html-main/Ipv6.html0000644000175000017500000005375512731530354016133 0ustar gerdgerd Ocamlnet 4 Reference Manual : Ipv6

Ipv6


IPv6 Support

We need to distinguish between:

  • IPv6 is compiled into OCamlnet
  • IPv6 is enabled
If the Ocaml runtime detects that IPv6 is available on the OS, IPv6 will also be compiled into OCamlnet. The does not mean, however, that IPv6 is enabled at runtime, which should only be done if IPv6 traffic can be routed.

How to enable

For Linux and BSD systems IPv6 is automatically enabled when a network interface is detected with a global IPv6 address. This check is done by Netsys.is_ipv6_system.

You can override what this function returns by calling Netsys.set_ipv6_system. This is needed on other OS where the automatic check does not work, and of course also when IPv6 needs to be turned off.

String-processing functions

Recognize IPv4 and IPv6 addresses with Netsys.is_ipv4_inet_addr and Netsys.is_ipv6_inet_addr, respectively.

The Neturl module can parse URLs containing IPv6 addresses, e.g. http://[fe80::224:7eff:fedf:59ff]/path. The address must be included in square brackets, following common Internet standards. These square brackets remain in place if the host part of the URL is extracted from the URL with Neturl.url_host. Note that Unix.inet_addr_of_string cannot process such brackets. Because of this, another function Neturl.url_addr has been added which returns the IP address directly.

For simple host/port pairs like localhost:3128 another abstraction has been added, Netsockaddr. With Netsockaddr.socksymbol_of_string one can parse such pairs, and IPv6 addresses are supported. Again, these addresses need to be enclosed in square brackets.

Note that it is possible to map IPv4 addresses into the IPv6 address space. Such addresses have the form ::ffff:XXXX:XXXX where XXXX:XXXX is the IPv4 address. Such addresses are normally written ::ffff:x.y.z.u so that the IPv4 address is denoted as the well-known dotted quadruple. You get such addresses when a server socket is bound to :: and receives IPv4 traffic. The consequence is that the same IPv4 address exists in two forms, namely as native IPv4 address and as IPv4-mapped-to-IPv6 address. Use Netsys.norm_inet_addr to normalize an address and Netsys.ipv6_inet_addr to enforce the mapped form.

Protocols

The protocol interpreters for HTTP, FTP, and SOCKS have been carefully reviewed, and the necessary changes have been done.

The implementations for SMTP, POP, and the web connectors do not contain IP addresses (or are uncritical).

Regarding SunRPC, the Portmapper protocol does not support IPv6. To cope with that, some support for RPCBIND, the successor of Portmapper, has been added. First the required RPCBIND requests are tried, and if it is detected that RPCBIND is unavailable, the old Portmapper requests are done instead. Note that in the latter case IPv6 is not possible.

Name service

The central name service module is Uq_resolver. The name resolver is now pluggable, and there are two versions:

  • Uq_resolver.default_resolver bases on gethostbyname, and is typically IPv4-only (but this is OS-dependent).
  • Uq_resolver.gai_resolver bases on getaddrinfo, and supports both IPv4 and IPv6. One can set which address types are enabled. getaddrinfo may not be available on all platforms, but it always available for platforms supporting IPv6.
If Netsys.is_ipv6_system returns true, the standard resolver is automatically changed to Uq_resolver.gai_resolver in order to allow IPv6 name lookups.
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.http_engine_processing_config.html0000644000175000017500000004235112731530354027541 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_engine_processing_config object
  method config_synch_input :
    (Netchannels.in_obj_channel -> unit) ->
    Uq_engines.async_in_channel -> unit
  method config_synch_output :
    (Netchannels.out_obj_channel -> unit) ->
    Uq_engines.async_out_channel -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netx509_pubkey.Signing.html0000644000175000017500000004710712731530354022472 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey.Signing sig
  val rsa_with_sha1 : Netx509_pubkey.sign_alg
  val rsa_with_sha224 : Netx509_pubkey.sign_alg
  val rsa_with_sha256 : Netx509_pubkey.sign_alg
  val rsa_with_sha384 : Netx509_pubkey.sign_alg
  val rsa_with_sha512 : Netx509_pubkey.sign_alg
  val rsassa_pss :
    hash_function:Netx509_pubkey.hash_function ->
    maskgen_function:Netx509_pubkey.maskgen_function ->
    salt_length:int -> Netx509_pubkey.sign_alg
  val dsa_with_sha1 : Netx509_pubkey.sign_alg
  val dsa_with_sha224 : Netx509_pubkey.sign_alg
  val dsa_with_sha256 : Netx509_pubkey.sign_alg
  val ecdsa_with_sha1 : Netx509_pubkey.sign_alg
  val ecdsa_with_sha224 : Netx509_pubkey.sign_alg
  val ecdsa_with_sha256 : Netx509_pubkey.sign_alg
  val ecdsa_with_sha384 : Netx509_pubkey.sign_alg
  val ecdsa_with_sha512 : Netx509_pubkey.sign_alg
  val eddsa : Netx509_pubkey.sign_alg
  val catalog :
    (string * string list * Netx509_pubkey.sign_alg * Netx509_pubkey.oid)
    list
  val alg_id_of_sign_alg : Netx509_pubkey.sign_alg -> Netx509_pubkey.alg_id
  val key_oid_of_sign_alg : Netx509_pubkey.sign_alg -> Netx509_pubkey.oid
end
ocamlnet-4.1.2/doc/html-main/Netsys_pollset_generic.html0000644000175000017500000005317412731530354022025 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset_generic

Module Netsys_pollset_generic

module Netsys_pollset_generic: sig .. end
Returns a good standard implementation of pollset for this platform. It will be good for cases where only a small to medium number of descriptors is watched (several hundred should be ok). It is no problem when the pollset lives only for a short time. Also, it is not strictly necessary to call the dispose method after use.

On POSIX platforms, this returns a Netsys_pollset_posix.poll_based_pollset.

On Win32, this returns Netsys_pollset_win32.pollset in single-threaded programs, and a Netsys_pollset_win32.threaded_pollset in multi-threaded programs. Note that Win32 restricts the number of descriptors that can be watched per thread to 64. The threaded_pollset version overcomes this limit, but it is only available if your program is compiled for multi-threading. Because of this, it may be useful to enable multi-threading for your program even when your code does not make use of it otherwise.


val standard_pollset : unit -> Netsys_pollset.pollset
Returns a good standard implementation of pollset for this platform. It will be good for cases where only a small to medium number of descriptors is watched (several hundred should be ok). It is no problem when the pollset lives only for a short time. Also, it is not strictly necessary to call the dispose method after use.

On POSIX platforms, this returns a Netsys_pollset_posix.poll_based_pollset.

On Win32, this returns Netsys_pollset_win32.pollset in single-threaded programs, and a Netsys_pollset_win32.threaded_pollset in multi-threaded programs. Note that Win32 restricts the number of descriptors that can be watched per thread to 64. The threaded_pollset version overcomes this limit, but it is only available if your program is compiled for multi-threading. Because of this, it may be useful to enable multi-threading for your program even when your code does not make use of it otherwise.

val performance_pollset : unit -> Netsys_pollset.pollset
Returns the best available pollset on this platform for high performance servers that have to deal with many different file descriptors. Note that this pollset may have higher initial costs, and may not be suitable for cases where pollsets live only for a short time. Also, make sure the dispose method is called after use.

On some POSIX platforms this is backed by Netsys_pollset_posix.accelerated_pollset. See the documentation there for possible problems. If no better implementation is available, this is the same as standard_pollset.

val select_emulation : Netsys_pollset.pollset ->
Unix.file_descr list ->
Unix.file_descr list ->
Unix.file_descr list ->
float -> Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
let select = select_emulation pset: Returns a function with the same meaning as Unix.select. It is emulated on top of pset.

Using the function is only recommended when the lists of file descriptors are short. Long lists impose a big performance penalty.

Unlike Unix.select the descriptors may be returned in any order.

ocamlnet-4.1.2/doc/html-main/Nethttpd_services.Debug.html0000644000175000017500000004163612731530354022024 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_services.Debug

Module Nethttpd_services.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/type_Netmech_spnego_http.Default.html0000644000175000017500000004057012731530354023717 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_spnego_http.Default PROFILEocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.cache_t.html0000644000175000017500000004234612731530354023367 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.cache_t object
  method abort : unit -> unit
  method get_engine : unit -> 'Uq_engines_compat.engine
  method get_opt : unit -> 'a option
  method invalidate : unit -> unit
  method put : '-> unit
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.direct_acceptor.html0000644000175000017500000004145212731530354025130 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.direct_acceptor ?close_on_shutdown:bool ->
?preclose:(unit -> unit) ->
Unix.file_descr ->
Unixqueue.event_system -> Uq_engines_compat.server_endpoint_acceptor
ocamlnet-4.1.2/doc/html-main/type_Netencoding.Url.html0000644000175000017500000004237312731530354021340 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Url sig
  val decode : ?plus:bool -> ?pos:int -> ?len:int -> string -> string
  val encode : ?plus:bool -> string -> string
  val mk_url_encoded_parameters : (string * string) list -> string
  val dest_url_encoded_parameters : string -> (string * string) list
end
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.epsilon_engine-c.html0000644000175000017500000004261312731530354024153 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.epsilon_engine

Class Uq_engines_compat.epsilon_engine

class ['t] epsilon_engine : 't engine_state -> Unixqueue.event_system -> ['t] engine

ocamlnet-4.1.2/doc/html-main/Netcgi1_compat.Netcgi_env.html0000644000175000017500000005773012731530354022221 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi_env

Module Netcgi1_compat.Netcgi_env

module Netcgi_env: sig .. end

type input_mode = [ `Standard ] 
This is not used anywhere. Moreover this is protocol dependent.
type input_state = [ `Received_body
| `Received_header
| `Receiving_body
| `Receiving_header
| `Start ]
This is not the business of the user. Rather than to document #set_input_state as such, we prefer not to allow the user to have access to it at the first place...
type output_mode = [ `Standard ] 
This is not used anywhere. Moreover "non-parsed header" is not supported by all connectors.
type output_state = [ `End
| `Sending_body
| `Sending_header
| `Sending_part_body
| `Sending_part_header
| `Sent_body
| `Sent_header
| `Sent_part_body
| `Sent_part_header
| `Start ]
This is not the business of the user. In the new API, it is handled transparently.
type protocol_version = Nethttp.protocol_version 
type protocol_attribute = Nethttp.protocol_attribute 
type protocol = Nethttp.protocol 
type workaround = [ `Work_around_MSIE_Content_type_bug | `Work_around_backslash_bug ] 
The Work_around_ part has been dropped as it is clear at the spot of use.
type cgi_config = {
   tmp_directory : string;
   tmp_prefix : string;
   permitted_http_methods : string list; (*
Now has type [`GET | `HEAD | `POST | `DELETE | `PUT] list for coherence with Netcgi.cgi#request_method.
*)
   permitted_input_content_types : string list;
   input_content_length_limit : int;
   workarounds : workaround list;
}
Now simply called Netcgi.config.
val default_config : cgi_config
val of_compat_config : cgi_config -> Netcgi.config
Portage: of_compat_config c transform the old configuration c into one suitable for the new interface.
val to_compat_config : Netcgi.config -> cgi_config
Portage: to_compat_config c transform the new configuration c into one suitable for the old interface.
class type cgi_environment = object .. end
val to_compat_environment : Netcgi.cgi_environment -> cgi_environment
Portage: to_compat_environment e converts the new environment e to the old interface.
val of_compat_environment : cgi_environment -> Netcgi.cgi_environment
Portage: of_compat_environment e converts the old environment e to the new interface.
ocamlnet-4.1.2/doc/html-main/Netstream.sub_stream-c.html0000644000175000017500000004421312731530354021621 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstream.sub_stream

Class Netstream.sub_stream

class sub_stream : ?len:int -> ?delimiter:string -> in_obj_stream -> in_obj_stream
A sub stream is the part of the whole stream from the current position to an arbitrary other position that is determined by len and delimiter. len specifies the maximum length of the sub stream. delimiter is an arbitrary string that indicates the end of the sub stream (the delimiter is not part of the sub stream; i.e. the sub stream ends immediately before the delimiter).

While reading from the sub stream, not only the current position of the sub stream moves, but also the current position of the main stream. This means that it must be avoided to read data from the main stream while the sub stream is in use. The typical pattern is:

  • Read from the main stream until the beginning of a section is recognized
  • Create a sub stream at this point
  • Read from the sub stream until EOF
  • Continue reading the main stream. The next character of the main stream is exactly the character following the EOF of the sub stream


ocamlnet-4.1.2/doc/html-main/type_Netmcore_heap.html0000644000175000017500000006661212731530354021115 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_heap sig
  type 'a heap
  type 'a descr
  val create_heap : Netmcore.res_id -> int -> '-> 'Netmcore_heap.heap
  val minimum_size : '-> int
  val root : 'Netmcore_heap.heap -> 'a
  val descr_of_heap : 'Netmcore_heap.heap -> 'Netmcore_heap.descr
  val heap_of_descr :
    Netmcore.res_id -> 'Netmcore_heap.descr -> 'Netmcore_heap.heap
  type mutator
  val modify : 'Netmcore_heap.heap -> (Netmcore_heap.mutator -> 'r) -> 'r
  val add : Netmcore_heap.mutator -> '-> 'a
  val add_immutable : Netmcore_heap.mutator -> '-> 'a
  val add_uniform_array : Netmcore_heap.mutator -> int -> '-> 'a array
  val add_init_array :
    Netmcore_heap.mutator -> int -> (int -> 'a) -> 'a array
  val add_some : Netmcore_heap.mutator -> '-> 'a option
  val add_string : Netmcore_heap.mutator -> int -> string
  val pin : Netmcore_heap.mutator -> '-> unit
  val copy : '-> 'a
  val with_value : 'Netmcore_heap.heap -> (unit -> 'b) -> ('-> 'c) -> 'c
  val with_value_2 :
    'Netmcore_heap.heap -> (unit -> 'b * 'c) -> ('b * '-> 'z) -> 'z
  val with_value_3 :
    'Netmcore_heap.heap ->
    (unit -> 'b * 'c * 'd) -> ('b * 'c * '-> 'z) -> 'z
  val with_value_4 :
    'Netmcore_heap.heap ->
    (unit -> 'b * 'c * 'd * 'e) -> ('b * 'c * 'd * '-> 'z) -> 'z
  val with_value_5 :
    'Netmcore_heap.heap ->
    (unit -> 'b * 'c * 'd * 'e * 'f) -> ('b * 'c * 'd * 'e * '-> 'z) -> 'z
  val with_value_n :
    'Netmcore_heap.heap -> (unit -> 'b list) -> ('b list -> 'c) -> 'c
  val destroy : 'Netmcore_heap.heap -> unit
  val gc : 'Netmcore_heap.heap -> unit
  val pool : 'Netmcore_heap.heap -> Netmcore.res_id
  val mut_pool : Netmcore_heap.mutator -> Netmcore.res_id
  val sem_container : 'Netmcore_heap.heap -> Netsys_sem.container
  val mut_sem_container : Netmcore_heap.mutator -> Netsys_sem.container
  val debug_info : 'Netmcore_heap.heap -> string
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Netplex_kit.protocol_switch_factory-c.html0000644000175000017500000004530112731530354024751 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.protocol_switch_factory

Class Netplex_kit.protocol_switch_factory

class protocol_switch_factory : string -> (string * Netplex_types.processor_factory) list -> Netplex_types.processor_factory
protocol_switch_factory name merge_list: Merges the factories in merge_list to a single factory. Which factory is selected depends on the protocol.

For example:

          service {
            name = "...";
            protocol {
               name = "A"; ...;
            }
            protocol {
               name = "B"; ...;
            }
            processor {
               type = "merged";
               A {
                  ...
               }
               B {
                  ...
               }
            }
          }
      

Here, two protocols A and B are defined, and there is a subsection in processor for each of the protocols configuring the used service. "merged" is the name of the merged factories.

For example, A could be an RPC interface, and B could be an HTTP interface providing the same service.

For every protocol in merge_list there must be a subsection in processor for the protocol. This subsection configures then the processor. It is not an error not to create sockets for a protocol in merge_list.


ocamlnet-4.1.2/doc/html-main/type_Netaux.KMP.html0000644000175000017500000004213512731530354020230 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netaux.KMP sig
  type pattern
  val make_pattern : string -> Netaux.KMP.pattern
  val find_pattern :
    Netaux.KMP.pattern -> ?pos:int -> ?len:int -> Bytes.t -> int
end
ocamlnet-4.1.2/doc/html-main/type_Netftp_data_endpoint.in_record_channel.html0000644000175000017500000004355312731530354026127 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.in_record_channel object
  method close_in : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method input_byte : unit -> int
  method input_char : unit -> char
  method input_eor : unit -> unit
  method input_line : unit -> string
  method pos_in : int
  method really_input : Bytes.t -> int -> int -> unit
  method really_input_string : int -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netx509_pubkey.Keyagreement.html0000644000175000017500000004340712731530354023513 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netx509_pubkey.Keyagreement sig
  val dh : Netx509_pubkey.kex_alg
  val ec : Netx509_pubkey.kex_alg
  val ecdh : Netx509_pubkey.kex_alg
  val ecmqv : Netx509_pubkey.kex_alg
  val kea : Netx509_pubkey.kex_alg
  val catalog :
    (string * string list * Netx509_pubkey.kex_alg * Netx509_pubkey.oid) list
  val alg_id_of_kex_alg : Netx509_pubkey.kex_alg -> Netx509_pubkey.alg_id
  val key_oid_of_kex_alg : Netx509_pubkey.kex_alg -> Netx509_pubkey.oid
end
ocamlnet-4.1.2/doc/html-main/type_Netcgi.cgi_activation.html0000644000175000017500000004056512731530354022536 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi.cgi_activation Netcgi.cgiocamlnet-4.1.2/doc/html-main/type_Netchannels.output_netbuffer.html0000644000175000017500000004114212731530354024174 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_netbuffer ?onclose:(unit -> unit) -> Netbuffer.t -> Netchannels.out_obj_channelocamlnet-4.1.2/doc/html-main/Netchannels_crypto.crypto_out_filter-c.html0000644000175000017500000004362012731530354025132 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto.crypto_out_filter

Class type Netchannels_crypto.crypto_out_filter

class type crypto_out_filter = object .. end
Encrypt or decrypt data while writing to a channel
Inherits
method supports_aead : bool
Whether the cipher supports authentication, and will provide a MAC
method mac : unit -> string
Get the MAC of the processed data
ocamlnet-4.1.2/doc/html-main/type_Netmech_crammd5_sasl.CRAM_MD5.html0000644000175000017500000004066412731530354023546 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_crammd5_sasl.CRAM_MD5 Netsys_sasl_types.SASL_MECHANISMocamlnet-4.1.2/doc/html-main/type_Netmech_spnego_http.SPNEGO.html0000644000175000017500000004137312731530354023330 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_spnego_http.SPNEGO functor (P : PROFILE) (G : Netsys_gssapi.GSSAPI->
  Nethttp.HTTP_CLIENT_MECHANISM
ocamlnet-4.1.2/doc/html-main/type_Netglob.user_info.html0000644000175000017500000004127012731530354021717 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netglob.user_info object
  method home_directory : string -> string
  method path_encoding : Netconversion.encoding option
end
ocamlnet-4.1.2/doc/html-main/type_Nettls_gnutls.GNUTLS.html0000644000175000017500000004057112731530354022220 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.GNUTLS GNUTLS_PROVIDERocamlnet-4.1.2/doc/html-main/type_Uq_engines.timeout_engine.html0000644000175000017500000004124412731530354023445 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.timeout_engine float -> exn -> 'Uq_engines.engine -> ['a] Uq_engines.engineocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi.html0000644000175000017500000004767512731530354022421 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi sig
  type argument_processing = [ `Automatic | `File | `Memory ]
  type operating_type =
      [ `Direct of string
      | `Transactional of
          Netcgi1_compat.Netcgi_env.cgi_config ->
          Netchannels.out_obj_channel -> Netchannels.trans_out_obj_channel ]
  class simple_argument :
    ?ro:bool -> string -> string -> Netcgi_types.cgi_argument
  class mime_argument :
    ?work_around_backslash_bug:bool ->
    string -> Netmime.mime_message -> Netcgi_types.cgi_argument
  class std_activation :
    ?env:Netcgi1_compat.Netcgi_env.cgi_environment ->
    ?processing:(string ->
                 Netmime.mime_header ->
                 Netcgi1_compat.Netcgi.argument_processing) ->
    ?operating_type:Netcgi1_compat.Netcgi.operating_type ->
    unit -> Netcgi_types.cgi_activation
  val buffered_transactional_optype : Netcgi1_compat.Netcgi.operating_type
  val tempfile_transactional_optype : Netcgi1_compat.Netcgi.operating_type
end
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_modes.Symmetric_cipher.html0000644000175000017500000005451012731530354024656 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_modes.Symmetric_cipher

Module Netsys_crypto_modes.Symmetric_cipher

module Symmetric_cipher: sig .. end


Access symmetric ciphers
type sc_ctx = {
   set_iv : string -> unit;
   set_header : string -> unit;
   encrypt : Netsys_types.memory -> Netsys_types.memory -> unit;
   decrypt : Netsys_types.memory -> Netsys_types.memory -> bool;
   mac : unit -> string;
}
type sc = {
   name : string;
   mode : string;
   key_lengths : (int * int) list;
   iv_lengths : (int * int) list;
   block_constraint : int;
   supports_aead : bool;
   create : string -> sc_ctx;
}
val extract : (module Netsys_crypto_types.SYMMETRIC_CRYPTO) ->
string * string -> sc
extract scrypto (name,mode): returns the cipher called name in mode as scipher, or raises Not_found
val extract_all : (module Netsys_crypto_types.SYMMETRIC_CRYPTO) ->
sc list
Extracts all ciphers
val cbc_of_ecb : sc ->
sc
For a given cipher in ECB mode, a new cipher in CBC mode is returned. Raises Not_found if the input is not in ECB mode.
val ofb_of_ecb : sc ->
sc
For a given cipher in ECB mode, a new cipher in OFB mode is returned. Raises Not_found if the input is not in ECB mode.
val ctr_of_ecb : sc ->
sc
For a given cipher in ECB mode, a new cipher in CTR mode is returned. Raises Not_found if the input is not in ECB mode.
ocamlnet-4.1.2/doc/html-main/Nethttpd_types.html0000644000175000017500000010235112731530354020310 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_types

Module Nethttpd_types

module Nethttpd_types: sig .. end
Type definitions for the HTTP daemon

Contents




Many types can also be found in the Nethttp module (part of netstring). Furthermore, Netcgi_env and Netcgi_types are of interest (part of cgi).

Many types can also be found in the Nethttp module (part of netstring). Furthermore, Netcgi_env and Netcgi_types are of interest (part of cgi).

Exceptions


exception Standard_response of Nethttp.http_status * Nethttp.http_header option * string option
Some HTTP containers allow you to raise this exception. The standard response corresponding to http_status is sent back to the client. If the third argument exists, an entry into the error log is written.

Environment


type output_state = [ `End | `Sending | `Start ] 
val string_of_output_state : output_state -> string
Debugging
class type virtual v_extended_environment = object .. end
An extension of cgi_environment for use with the daemon.
class type extended_environment = object .. end
Same as v_extended_environment, but no virtual methods

Construction of environments


class virtual empty_environment : object .. end
This class implements an environment with defined internal containers.
class redirected_environment : ?in_header:Nethttp.http_header -> ?properties:(string * string) list -> ?in_channel:Netchannels.in_obj_channel -> extended_environment -> extended_environment
This class overlays the input-side containers of an existing environment.

Auxiliary Functions for Environments


val output_static_response : #extended_environment ->
Nethttp.http_status -> Nethttp.http_header option -> string -> unit
Outputs the string argument as response body, together with the given status and the header (optional). Response header fields are set as follows:
  • The Content-Length is set to the length of the string.
  • The Content-Type is set to "text/html" unless given by the header.
If the header is not passed, the header of the environment is taken. If the header argument exists, however, it overrides the header of the environment.
val output_file_response : #extended_environment ->
Nethttp.http_status ->
Nethttp.http_header option -> string -> int64 -> int64 -> unit
Outputs the contents of a file as response body, together with the given status and the header (optional). The string is the file name. The first int64 number is the position in the file where to start, and the second number is the length of the body. Response header fields are set as follows:
  • The Content-Length is set to the length of the string.
  • The Content-Type is set to "text/html" unless given by the header.
Note that Content-Range is not set automatically, even if the file is only partially transferred.

If the header is not passed, the header of the environment is taken. If the header argument exists, however, it overrides the header of the environment.

The function raises Sys_error when the file cannot be read.


Generating error responses, logging


class type request_info = object .. end
class type full_info = object .. end
class create_full_info : response_status_code:int -> request_body_rejected:bool -> output_header:Nethttp.http_header -> output_body_size:int64 -> request_info -> full_info
Creates a full_info object by adding to a request_info object
class type error_response_params = object .. end
class type min_config = object .. end
Minimal configuration needed for output_std_response
val output_std_response : #min_config ->
#extended_environment ->
Nethttp.http_status -> Nethttp.http_header option -> string option -> unit
Outputs a "standard response" for the http_status. The string argument is an optional entry into the error log.

If the header is not passed, an empty header is taken. If the header argument exists, this header is taken. The header of the environment is never taken.


Service Providers

Service providers are defined using the three class types:

  • http_service: The service provider as such. When a HTTP header has been received, and the service provider is invoked, it returns an object fitting to the next class type, http_service_receiver. This object is tagged with `Accept_body; at this point there are also alternate ways of processing, see below.
  • http_service_receiver: The task of this object is to receive the request body. When the body has been completely received, the object is notified, and returns a third object of type http_service_generator.
  • http_service_generator: The task of this object is to generate the response.
An implementor is free to define only one class that satisfies all three class types at once. However, this is only an option.

The three objects reflect three stages of HTTP processing. The stages have made explicit to allow the implementor of services to intercept the points in time when the processing of the next stage begins. Furthermore, in multi-threaded environments it is allowed that the stages are performed in the contexts of different threads.

In addition to the three-stage model there also several faster paths of processing:

  • `Reject_body can be used to refuse the acceptance of the request body when it is already clear that an error response is sent back. This path skips the stage http_service_receiver.
  • `Static can be used to send a constant string back (only to be used when the string needs not to be computed)
  • `File can be used to send the contents of a file back (only to be used when the file already exists)

exception Redirect_request of string * Nethttp.http_header
The "early" redirect is only allowed in stage 1 of HTTP processing. The string argument is the new URI path of the request. The header can also be exchanged except the fields that are needed to decode the request body. It is not possible to change the method.
exception Redirect_response of string * Nethttp.http_header
The "late" redirect is only allowed in stage 3 of HTTP processing. The string argument is the new URI path of the request. The header can also be exchanged except the fields that are needed to decode the request body. The method is always changed to GET.
class type http_service_generator = object .. end
class type http_service_receiver = object .. end
type http_service_reaction = [ `Accept_body of http_service_receiver
| `File of
Nethttp.http_status * Nethttp.http_header option * string * int64 * int64
| `Reject_body of http_service_generator
| `Static of Nethttp.http_status * Nethttp.http_header option * string
| `Std_response of
Nethttp.http_status * Nethttp.http_header option * string option ]
Indicates the immediate reaction upon an arriving HTTP header:
  • `Accept_body is the regular way of processing requests. If necessary, the client is told to continue sending the rest of the request.
  • `Reject_body can be used when the body of the request is not needed, and the response will be negative.
  • `Static means to send the header and a constant string back as response. The header is taken from the environment if not explicitly passed, Note: The Content-Length header is automatically added. The Content-Type defaults to "text/html".
  • `File is similar to this, but the data come from a file. The file is specified by an absolute pathname. The range of the file is given by the start position and the length of the range. The header is taken from the environment if not explicitly passed, Note: The Content-Length header is automatically added. The Content-Type defaults to "text/html".
  • `Std_response is similar to `Static, however the body is the standard text for the status code. If the header is omitted, it is taken as empty. The third argument is an optional entry into the error log. Note: The Content-Length header is automatically added. The Content-Type defaults to "text/html".

class type ['a] http_service = object .. end

Helpers


val update_alist : ('a * 'b) list -> ('a * 'b) list -> ('a * 'b) list
update_alist updl l: Returns the alist with all elements of updl and all elements of l that are not member of updl.
ocamlnet-4.1.2/doc/html-main/type_Netencoding.html0000644000175000017500000011343012731530354020570 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding sig
  module Base64 :
    sig
      val encode :
        ?pos:int ->
        ?len:int ->
        ?linelength:int ->
        ?crlf:bool -> ?plus:char -> ?slash:char -> string -> string
      val encode_tstring :
        ?pos:int ->
        ?len:int ->
        ?linelength:int ->
        ?crlf:bool ->
        ?plus:char -> ?slash:char -> Netsys_types.tstring -> Bytes.t
      val encode_poly :
        ?pos:int ->
        ?len:int ->
        ?linelength:int ->
        ?crlf:bool ->
        ?plus:char ->
        ?slash:char -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
      val decode :
        ?pos:int ->
        ?len:int ->
        ?accept_spaces:bool -> ?plus:char -> ?slash:char -> string -> string
      val decode_tstring :
        ?pos:int ->
        ?len:int ->
        ?accept_spaces:bool ->
        ?plus:char -> ?slash:char -> Netsys_types.tstring -> Bytes.t
      val decode_poly :
        ?pos:int ->
        ?len:int ->
        ?accept_spaces:bool ->
        ?plus:char ->
        ?slash:char -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
      class encoding_pipe :
        ?linelength:int ->
        ?crlf:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipe
      class decoding_pipe :
        ?accept_spaces:bool ->
        ?plus:char -> ?slash:char -> unit -> Netchannels.pipe
    end
  module QuotedPrintable :
    sig
      val encode : ?crlf:bool -> ?pos:int -> ?len:int -> string -> string
      val encode_tstring :
        ?crlf:bool -> ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
      val encode_poly :
        ?crlf:bool ->
        ?pos:int ->
        ?len:int -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
      val decode : ?pos:int -> ?len:int -> string -> string
      val decode_tstring :
        ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
      val decode_poly :
        ?pos:int ->
        ?len:int -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
      class encoding_pipe : ?crlf:bool -> unit -> Netchannels.pipe
      class decoding_pipe : unit -> Netchannels.pipe
    end
  module Q :
    sig
      val encode : ?pos:int -> ?len:int -> string -> string
      val encode_tstring :
        ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
      val encode_poly :
        ?pos:int ->
        ?len:int -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
      val decode : ?pos:int -> ?len:int -> string -> string
      val decode_tstring :
        ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
      val decode_poly :
        ?pos:int ->
        ?len:int -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
    end
  module Url :
    sig
      val decode : ?plus:bool -> ?pos:int -> ?len:int -> string -> string
      val encode : ?plus:bool -> string -> string
      val mk_url_encoded_parameters : (string * string) list -> string
      val dest_url_encoded_parameters : string -> (string * string) list
    end
  module Html :
    sig
      val encode_from_latin1 : string -> string
      val decode_to_latin1 : string -> string
      val unsafe_chars_html4 : string
      val encode :
        in_enc:Netconversion.encoding ->
        ?out_enc:Netconversion.encoding ->
        ?prefer_name:bool -> ?unsafe_chars:string -> unit -> string -> string
      val encode_tstring :
        in_enc:Netconversion.encoding ->
        out_kind:'Netstring_tstring.tstring_kind ->
        ?out_enc:Netconversion.encoding ->
        ?prefer_name:bool ->
        ?unsafe_chars:string -> unit -> Netsys_types.tstring -> 's
      val encode_poly :
        in_enc:Netconversion.encoding ->
        in_ops:'Netstring_tstring.tstring_ops ->
        out_kind:'Netstring_tstring.tstring_kind ->
        ?out_enc:Netconversion.encoding ->
        ?prefer_name:bool -> ?unsafe_chars:string -> unit -> '-> 't
      type entity_set = [ `Empty | `Html | `Xml ]
      val decode :
        in_enc:Netconversion.encoding ->
        out_enc:Netconversion.encoding ->
        ?lookup:(string -> string) ->
        ?subst:(int -> string) ->
        ?entity_base:Netencoding.Html.entity_set -> unit -> string -> string
      val decode_tstring :
        in_enc:Netconversion.encoding ->
        out_kind:'Netstring_tstring.tstring_kind ->
        out_enc:Netconversion.encoding ->
        ?lookup:(string -> string) ->
        ?subst:(int -> string) ->
        ?entity_base:Netencoding.Html.entity_set ->
        unit -> Netsys_types.tstring -> 's
      val decode_poly :
        in_enc:Netconversion.encoding ->
        in_ops:'Netstring_tstring.tstring_ops ->
        out_kind:'Netstring_tstring.tstring_kind ->
        out_enc:Netconversion.encoding ->
        ?lookup:(string -> string) ->
        ?subst:(int -> string) ->
        ?entity_base:Netencoding.Html.entity_set -> unit -> '-> 't
    end
  val to_hex : ?lc:bool -> string -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netmcore_condition.html0000644000175000017500000005371212731530354022163 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_condition sig
  type condition
  type wait_entry
  type wait_entry_e
  type wait_set
  val dummy_condition : unit -> Netmcore_condition.condition
  val dummy_wait_set : unit -> Netmcore_condition.wait_set
  val create_condition :
    Netmcore_heap.mutator -> Netmcore_condition.condition
  val create_wait_set : Netmcore_heap.mutator -> Netmcore_condition.wait_set
  val alloc_wait_entry :
    Netmcore_heap.mutator ->
    Netmcore_condition.wait_set -> Netmcore_condition.wait_entry
  val free_wait_entry :
    Netmcore_heap.mutator ->
    Netmcore_condition.wait_set -> Netmcore_condition.wait_entry -> unit
  val alloc_wait_entry_e :
    Netmcore_heap.mutator ->
    Netmcore_condition.wait_set -> string -> Netmcore_condition.wait_entry_e
  val free_wait_entry_e :
    Netmcore_heap.mutator ->
    Netmcore_condition.wait_set -> Netmcore_condition.wait_entry_e -> unit
  val wait :
    Netmcore_condition.wait_entry ->
    Netmcore_condition.condition -> Netmcore_mutex.mutex -> unit
  val wait_e :
    ?debug_name:string ->
    Netmcore_condition.wait_entry_e ->
    Netmcore_condition.condition ->
    Netmcore_mutex.mutex ->
    Unixqueue.event_system ->
    (unit -> 'Uq_engines.engine) -> 'Uq_engines.engine
  val signal : Netmcore_condition.condition -> unit
  val broadcast : Netmcore_condition.condition -> unit
  val pipe_name : Netmcore_condition.wait_entry_e -> string
  val destroy_condition : Netmcore_condition.condition -> unit
  val destroy_wait_set : Netmcore_condition.wait_set -> unit
  module Debug : sig val enable : bool Pervasives.ref end
end
ocamlnet-4.1.2/doc/html-main/Netmech_plain_sasl.html0000644000175000017500000004442512731530354021071 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_plain_sasl

Module Netmech_plain_sasl

module Netmech_plain_sasl: sig .. end
The PLAIN SASL mechanism (RFC 4616).

Key facts:

  • This mechanism sends user name, authorization name and password as cleartext
  • There is no support for channel binding within the mechanism.
  • It is insecure, and should only be used over channels that are otherwise secured.
Parameters:
  • Both create_client_session and create_server_session accept the boolean parameter "mutual". If true, however, authentication fails immediately, as mutual authentication cannot be supported.
  • The same is true for the boolean parameter "secure", because PLAIN is insecure.
As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of PLAIN should pass user names and passwords through Netsaslprep.saslprep.

module PLAIN: Netsys_sasl_types.SASL_MECHANISM 
The PLAIN SASL mechanism (RFC 4616).
ocamlnet-4.1.2/doc/html-main/Uq_server.html0000644000175000017500000005713612731530354017257 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_server

Module Uq_server

module Uq_server: sig .. end

Server sockets




Server sockets


type listen_address = [ `Socket of Uq_engines.sockspec * listen_options
| `W32_pipe of Netsys_win32.pipe_mode * string * listen_options ]
Specifies the resource to listen on:

  • `Socket(addr,opts): It is listened on a socket with address addr
  • `W32_pipe(mode,name,opts): It is listened on a pipe server with name which accepts pipe connections in mode.

type listen_options = Uq_engines.listen_options = {
   lstn_backlog : int; (*
The length of the queue of not yet accepted connections.
*)
   lstn_reuseaddr : bool; (*
Whether to allow that the address can be immediately reused after the previous listener has its socket shut down. (Only for Internet sockets.)
*)
}
val default_listen_options : listen_options
Returns the default options
val listen_on_inet_socket : Unix.inet_addr ->
int -> Unix.socket_type -> listen_options -> Unix.file_descr
listen_on_inet_socket addr port stype opts: Creates a TCP or UDP server socket for IPv4 or IPv6, depending on the type of address. The socket is listening.

As special cases, the addresses "::1" and "::" are always understood even if IPv6 is not avaiable, and treated as the corresponding IPv4 addresses (127.0.0.1 and 0.0.0.0, resp.) instead.

val listen_on_unix_socket : string -> Unix.socket_type -> listen_options -> Unix.file_descr
listen_on_unix_socket path stype opts: Creates a Unix Domain server socket for the given path. The socket is listening.

On Win32, Unix Domain sockets are emulated by opening an Internet socket on the loopback interface, and by writing the port number to path.

val listen_on_w32_pipe : Netsys_win32.pipe_mode ->
string -> listen_options -> Unix.file_descr
listen_on_w32_pipe mode path opts: Creates a Win32 pipe server and returns the proxy descriptor.
val listen_on : listen_address -> Unix.file_descr
listen_on addr: Creates a server endpoint for addr
class type server_endpoint_acceptor = object .. end
This class type is for service providers that listen for connections.
class direct_acceptor : ?close_on_shutdown:bool -> ?preclose:unit -> unit -> Unix.file_descr -> Unixqueue.event_system -> server_endpoint_acceptor
An implementation of server_endpoint_acceptor for sockets and Win32 named pipes.
val listener : ?proxy:#Uq_engines.server_endpoint_listener ->
listen_address ->
Unixqueue.event_system ->
server_endpoint_acceptor Uq_engines.engine
This engine creates a server socket listening on the listen_address. If passed, the proxy is used to create the server socket.

On success, the engine goes to state `Done acc, where acc is the acceptor object (see above). The acceptor object can be used to accept incoming connections.

ocamlnet-4.1.2/doc/html-main/Uq_engines.seq_engine-c.html0000644000175000017500000004453312731530354021732 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.seq_engine

Class Uq_engines.seq_engine

class [['a, 'b]] seq_engine : 'a #engine -> ('a -> 'b #engine) -> ['b] engine
This engine runs two engines in sequential order. It is called

 let eng_s = new seq_engine eng_a f 

When eng_a goes to the state `Done arg, the function f is called to obtain

 let eng_b = f arg 

eng_b runs until it is also in state `Done.

If eng_a or eng_b go to states `Aborted or `Error, the sequential engine eng_s does so, too. If eng_s is aborted, this request will be forwarded to the currently active engine, eng_a or eng_b.

If calling f results in an exception, this is handled as if eng_a signaled an exception.


ocamlnet-4.1.2/doc/html-main/Netmech_scram.Debug.html0000644000175000017500000004214412731530354021072 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram.Debug

Module Netmech_scram.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enable debugging of this module
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.server_socket_listener-c.html0000644000175000017500000004250612731530354025741 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.server_socket_listener

Class type Uq_engines_compat.server_socket_listener

class type server_socket_listener = server_endpoint_listener

ocamlnet-4.1.2/doc/html-main/Rpc_auth_gssapi.html0000644000175000017500000005107512731530354020413 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_auth_gssapi

Module Rpc_auth_gssapi

module Rpc_auth_gssapi: sig .. end
GSS-API for RPC authentication

type user_name_format = [ `Exported_name | `Plain_name | `Prefixed_name ] 
What to return as user name:
  • `Exported_name: the exported name in binary format (as described in RFC 2078, section 3.2). This format can only be read back by the gss_api object generating the name.
  • `Prefixed_name: the display name in a text format "{<oid>}<namestring>".
  • `Plain_name: the string part of the display name

val server_auth_method : ?shared_context:bool ->
?user_name_format:user_name_format ->
?seq_number_window:int ->
?max_age:float ->
(module Netsys_gssapi.GSSAPI) ->
Netsys_gssapi.server_config -> Rpc_server.auth_method
Creates an authentication method from a GSS-API interface.

Options:

  • shared_context: Whether this method maintains only one security context for all connections. By default, each connection has a security context of its own. For UDP, this option needs to be set, because each UDP request is considered as creating a new connection.
  • user_name_format: Defaults to `Prefixed_name.
  • seq_number_window: If set, the server checks for replayed requests. The integer is the length of the check window (see RFC 2203 section 5.3.3.1). If omitted, no such checks are performed (the default).
  • max_age: The maximum lifetime for security contexts (in seconds). If not specified, the time is taken from the GSSAPI credential.

type support_level = [ `If_possible | `None | `Required ] 
type user_name_interpretation = [ `Exported_name | `Plain_name of Netsys_gssapi.oid | `Prefixed_name ] 
val client_auth_method : ?user_name_interpretation:user_name_interpretation ->
(module Netsys_gssapi.GSSAPI) ->
Netsys_gssapi.client_config -> Rpc_client.auth_method
Creates an authentication method from a GSS-API interface.

Options:

  • user_name_format: Defaults to `Prefixed_name.

module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Netsys_sasl.Client.html0000644000175000017500000005514712731530354021030 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sasl.Client

Module Netsys_sasl.Client

module Client: sig .. end

type session 
val create_session : mech:Netsys_sasl.sasl_mechanism ->
user:string ->
authz:string ->
creds:Netsys_sasl.credentials ->
params:(string * string * bool) list -> unit -> session
The new client session authenticate as user and authorizes as authz (empty string if not applicable). The credentials are creds.

user and authz must be encoded in UTF-8.

The parameters are given as list (name,value,critical). Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a Failure exception. Non-critical parameters are ignored if they are unknown to the mechanism.

val state : session -> Netsys_sasl_types.client_state
report the state (whether expecting challenges or responding)
val configure_channel_binding : session ->
Netsys_sasl_types.cb -> session
Configure GS2-style channel binding
val restart : session -> session
Restart the session for another authentication round. The session must be in state `OK.
val process_challenge : session -> string -> session
Process the challenge from the server. The state must be `Wait. As an exception, this function can also be called for the initial challenge from the server, even if the state is `Emit.
val emit_response : session -> session * string
Emit a new response. The state must be `Emit.
val channel_binding : session -> Netsys_sasl_types.cb
Whether the client suggests or demands channel binding
val user_name : session -> string
The user name
val authz_name : session -> string
The authorization name
val stash_session : session -> string
Serializes the session as string
val resume_session : Netsys_sasl.sasl_mechanism -> string -> session
Unserializes the session
val session_id : session -> string option
Optionally return a string that can be used to identify the client session. Not all mechanisms support this.
val prop : session -> string -> string
Get a mechanism-specific property of the session. E.g. this can be the "realm" sent by the server.
val gssapi_props : session -> Netsys_gssapi.client_props
Get the GSSAPI props, or raise Not_found
ocamlnet-4.1.2/doc/html-main/Nethttpd_engine.modify_http_engine_config-c.html0000644000175000017500000004515412731530354026037 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.modify_http_engine_config

Class Nethttpd_engine.modify_http_engine_config

class modify_http_engine_config : ?modify_http_protocol_config:Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config -> ?modify_http_processor_config:Nethttpd_reactor.http_processor_config ->
Nethttpd_reactor.http_processor_config -> ?config_input_flow_control:bool -> ?config_output_flow_control:bool -> http_engine_config ->
http_engine_config
Modifies the passed config object as specified by the optional arguments.

modify_http_protocol_config and modify_http_processor_config: These functions can be used to modify the parts of the config object that are inherited from http_protocol_config and http_processor_config, respectively: For example:

        let new_cfg =
          new modify_http_engine_config
            ~modify_http_protocol_config:
               (new Nethttpd_kernel.modify_http_protocol_config
                  ~config_suppress_broken_pipe:true)
            ~modify_http_processor_config:
               (new Nethttpd_reactor.modify_http_processor_config
                  ~config_timeout:15.0)
            old_cfg
      


ocamlnet-4.1.2/doc/html-main/Netmech_spnego_http.PROFILE.html0000644000175000017500000004514112731530354022371 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_spnego_http.PROFILE

Module type Netmech_spnego_http.PROFILE

module type PROFILE = sig .. end

val acceptable_transports_http : Nethttp.transport_layer_id list
Which transport IDs are acceptable for authenticated requests on unencrypted connections. For new requests, the first ID of this list is the preferred ID.
val acceptable_transports_https : Nethttp.transport_layer_id list
Which transport IDs are acceptable for authenticated requests on HTTPS-secured connections. For new requests, the first ID of this list is the preferred ID.
val enable_delegation : bool
Whether to allow delegation of the credentials to the server. Enabling this means that the server can impersonate the local identity, so use with care. Also, getting tokens carrying the delegation information can be time-consuming (and the HTTP client will simply block while doing so).
val deleg_credential : exn option
If you already have a credential, you can set this value to the exception Credential c (from the GSSAPI provider).
ocamlnet-4.1.2/doc/html-main/type_Netsys_xdr.html0000644000175000017500000004326712731530354020507 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_xdr sig
  external s_read_int4_64_unsafe : Bytes.t -> int -> int
    = "netsys_s_read_int4_64" "noalloc"
  external s_write_int4_64_unsafe : Bytes.t -> int -> int -> unit
    = "netsys_s_write_int4_64" "noalloc"
  external s_read_string_array_unsafe :
    Bytes.t -> int -> int -> int32 -> string array -> int
    = "netsys_s_read_string_array"
end
ocamlnet-4.1.2/doc/html-main/Netsys_pollset_win32.Debug.html0000644000175000017500000004206412731530354022374 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_pollset_win32.Debug

Module Netsys_pollset_win32.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module
ocamlnet-4.1.2/doc/html-main/Netcgi_apache.Apache.Table.html0000644000175000017500000005011312731530354022210 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_apache.Apache.Table

Module Netcgi_apache.Apache.Table

module Table: sig .. end

type t 
Apache table structure.
val get : t -> string -> string
Table.get tbl key returns the corresponding entry in the table. The key is matched case-insensitively. The first key will retrieved in case there are more than one entry in the table for the key.
Raises Not_found otherwise.
val get_all : t -> string -> string list
Table.get_all tbl key same as Table.get tbl key except it returns all values corresponding to the key.
val fields : t -> (string * string) list
Table.fields tbl returns a list of (key, value) pairs consisting of all entries of the table tbl.
val clear : t -> unit
Table.clear tbl removes all key/value pairs from the table tbl.
val set : t -> string -> string -> unit
Table.set tbl key value sets the (key, value) pair in the table tbl. If one or more key/value pairs already exists with the same key they will be deleted and replaced with (key, value).
val add : t -> string -> string -> unit
Table.add tbl key value adds the (key, value) pair in the table tbl. This does not erase any existing pairs.
val unset : t -> string -> unit
Table.unset tbl key delete every key/value pair associated with the key from the table tbl.
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.engine_mixin.html0000644000175000017500000004357612731530354023115 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.engine_mixin 'Uq_engines.engine_state ->
Unixqueue.event_system ->
object
  method event_system : Unixqueue.event_system
  method private notify : unit -> unit
  method request_notification : (unit -> bool) -> unit
  method request_proxy_notification : ('Uq_engines.engine -> bool) -> unit
  method private set_state : 'Uq_engines.engine_state -> unit
  method state : 'Uq_engines.engine_state
end
ocamlnet-4.1.2/doc/html-main/Uq_multiplex.multiplex_controller-c.html0000644000175000017500000006714512731530354024502 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_multiplex.multiplex_controller

Class type Uq_multiplex.multiplex_controller

class type multiplex_controller = object .. end
A multiplex_controller is a quite low-level device to abstract bidirectional socket connections. It is independent of any real device.

There can be a reader, a writer (or both), or alternatively, the shutdown process may be in progress. One cannot have more than one reader and more than more writer.


method alive : bool
If the controller is alive, the socket is not yet completely down.
method mem_supported : bool
Whether start_mem_reading and start_mem_writing are possible
method event_system : Unixqueue.event_system
Returns the event system
method tls_session_props : Nettls_support.tls_session_props option
If TLS is enabled, this returns the session properties. These are first available after the TLS handshake.
method tls_session : (string * string) option
If TLS is enabled, this returns (session_id, session_data). This is first available after the TLS handshake.
method tls_stashed_endpoint : unit -> exn
Returns the TLS endpoint in stashed form. Note that the multiplex controller becomes immediately unusable.
method reading : bool
True iff there is a reader
method start_reading : ?peek:(unit -> unit) ->
when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
Start reading from the connection. When data is available, the when_done callback is invoked. The int is the number of read bytes. It is 0 if an error occurred which is indicated by the exception. The exception End_of_file is used when the end of the data stream is reached. The exception Cancelled indicates that reading has been cancelled in the meantime.

This starts one-time read job only, i.e. it is not restarted after when_done has been invoked.

It is an error to start reading several times.

The function peek is called immediately before data is read in from the underlying communication channel.

For getting an engine-based version of start_reading, use a signal_engine:

 
    let (e, signal) = signal_engine esys in
    mplex # start_reading ~when_done:(fun xo n -> signal (xo,n)) ...
 
Now e will transition to `Done(x0,n) when the read is done.
method start_mem_reading : ?peek:(unit -> unit) ->
when_done:(exn option -> int -> unit) ->
Netsys_mem.memory -> int -> int -> unit
Same as start_reading, but puts the data into a memory buffer. There is an optimization for the case that the descriptor is a connected socket, or supports Unix.read. If this is not possible the method raises Mem_not_supported.
method cancel_reading : unit -> unit
Cancels the read job. The when_done callback is invoked with the number of bytes read so far (which may be 0) and the exception Cancelled.

It is no error if there is no reader.

method writing : bool
True iff there is a writer
method start_writing : when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
Start writing to the connection. When data is written, the when_done callback is invoked. The int is the number of written bytes. It is 0 if an error occurred which is indicated by the exception. The exception Cancelled indicates that writing has been cancelled in the meantime.

This starts one-time write job only, i.e. it is not restarted after when_done has been invoked.

It is an error to start writing several times.

See the comment for start_reading for how to get an engine-based version of this method.

method start_mem_writing : when_done:(exn option -> int -> unit) ->
Netsys_mem.memory -> int -> int -> unit
Same as start_writing, but takes the data from a memory buffer. There is an optimization for the case that the descriptor is a connected socket, or supports Unix.write. If this is not possible the method raises Mem_not_supported.
method supports_half_open_connection : bool
Whether the underlying transport mechanism can close the write side of the connection only (half-open connection).
method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit
Start writing the EOF marker to the connection. When it is written, the when_done callback is invoked. The exception Cancelled indicates that writing has been cancelled in the meantime.

This starts one-time write job only, i.e. it is not restarted after when_done has been invoked.

It is an error to start writing several times. It is an error to write EOF when the socket does not support half-open connections.

See the comment for start_reading for how to get an engine-based version of this method.

method cancel_writing : unit -> unit
Cancels the write job. The when_done callback is invoked with the number of bytes read so far (which may be 0) and the exception Canelled.

It is no error if there is no writer.

method read_eof : bool
Whether the EOF marker has been read
method wrote_eof : bool
Whether the EOF marker has been written
method shutting_down : bool
True iff the shutdown is in progress
method start_shutting_down : ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
Start shutting down the connection. After going through the shutdown procedure, the when_done callback is invoked. The exception indicates whether an error happened. Cancelled means that the shutdown operation has been cancelled in the meantime.

The underlying file descriptor (if any) is not closed. A shutdown is only a protocol handshake. After a shutdown, both read_eof and wrote_eof are true. Call inactivate to close the descriptor.

Optionally, one can linger for a certain period of time. It is only lingered when the EOF was written before the EOF is seen on input. Defaults to linger 60.0. Set to 0 to turn off.

See the comment for start_reading for how to get an engine-based version of this method.

method cancel_shutting_down : unit -> unit
Cancels the shutdown procedure. After that, the state of the connection is undefined. The when_done callback is invoked with the exception Cancelled.

It is no error if no shutdown is in progress.

method inactivate : unit -> unit
Inactivates the connection immediately, and releases any resources the controller is responsible for (e.g. closes file descriptors). Note that this is more than cancelling all pending operations and shutting the connection down. However, the details of this method are implementation-defined. Callbacks are not invoked.
ocamlnet-4.1.2/doc/html-main/Netgssapi_support.html0000644000175000017500000006305312731530354021030 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_support

Module Netgssapi_support

module Netgssapi_support: sig .. end
Support functions for GSS-API

val oid_to_der : Netsys_gssapi.oid -> string

Encodings


val der_to_oid : string -> int Pervasives.ref -> Netsys_gssapi.oid
Convert OID's to/from DER. der_to_oid takes a cursor as second arg.
val oid_to_der_value : Netsys_gssapi.oid -> string
val der_value_to_oid : string -> int Pervasives.ref -> int -> Netsys_gssapi.oid
Convert OID's to/from DER. This variant does not include the header (hex 06 plus length). der_value_to_oid takes a cursor and the length in bytes.
val wire_encode_token : Netsys_gssapi.oid -> Netsys_gssapi.token -> string
val wire_decode_token : string -> int Pervasives.ref -> Netsys_gssapi.oid * Netsys_gssapi.token
Encode tokens as described in section 3.1 of RFC 2078. This is usually only done for the initiating token.
val encode_exported_name : Netsys_gssapi.oid -> string -> string
val decode_exported_name : string -> int Pervasives.ref -> Netsys_gssapi.oid * string
Encode names as described in section 3.2 of RFC 2078
val gs2_encode_saslname : string -> string
val gs2_decode_saslname : string -> string
Encodes "," and "=" characters, and forbids null bytes, and checks whether the names are UTF-8-encoded (as required for the "saslname" production in section 4 of RFC 5801). Fails if something is wrong.
val parse_kerberos_name : string -> string list * string option
let (name_components, realm_opt) = parse_kerberos_name s: Returns the slash-separated name components as name_components, and the realm following "@" as realm_opt.

Fails on parse error.


Create tokens



Create tokens



Format of the tokens: see RFC 4121
val create_mic_token : sent_by_acceptor:bool ->
acceptor_subkey:bool ->
sequence_number:int64 ->
get_mic:(Netsys_gssapi.message -> string) ->
message:Netsys_gssapi.message -> string
Create a MIC token:

  • sent_by_acceptor: whether this token comes from the acceptor
  • acceptor_subkey: see RFC
  • sequence_number: a sequence number
  • get_mic: the checksum function (e.g. Netmech_scram.Cryptosystem.get_mic)
  • message: the message to be signed
The function returns the MIC token
val parse_mic_token_header : string -> bool * bool * int64
Returns the triple (sent_by_acceptor, acceptor_subkey, sequence_number) from the header of a MIC token that is passed to this function as string. Fails if not parsable
val verify_mic_token : get_mic:(Netsys_gssapi.message -> string) ->
message:Netsys_gssapi.message -> token:string -> bool
Verifies the MIC token with get_mic, and returns true if the verification is successful
val create_wrap_token_conf : sent_by_acceptor:bool ->
acceptor_subkey:bool ->
sequence_number:int64 ->
get_ec:(int -> int) ->
encrypt_and_sign:(Netsys_gssapi.message -> Netsys_gssapi.message) ->
message:Netsys_gssapi.message -> Netsys_gssapi.message
Wraps a message so that it is encrypted and signed (confidential).

  • sent_by_acceptor: whether this token comes from the acceptor
  • acceptor_subkey: see RFC
  • sequence_number: a sequence number
  • get_ec: This function returns the "extra count" number for the size of the plaintext w/o filler (e.g. use Netmech_scram.Cryptosystem.get_ec).
  • encrypt_and_sign: the encryption function from the cryptosystem. The plaintext is passed to this function, and the ciphertext with the appended signature must be returned in the string.
  • message: the payload message
The function returns the token wrapping the message.
val parse_wrap_token_header : Netsys_gssapi.message -> bool * bool * bool * int64
let (sent_by_acceptor, sealed, acceptor_subkey, sequence_number) = parse_wrap_token_header token

Fails if the token cannot be parsed.

val unwrap_wrap_token_conf : decrypt_and_verify:(Netsys_gssapi.message -> Netsys_gssapi.message) ->
token:Netsys_gssapi.message -> Netsys_gssapi.message
Unwraps the token using the decryption function decrypt_and_verify from the cryptosystem.

The functions fails if there is a format error, or the integrity check fails.

Non-confidential messages cannot be unwrapped with this function.


Token functions for non-confidential messages are still missing
ocamlnet-4.1.2/doc/html-main/type_Uq_tcl.tcl_event_system.html0000644000175000017500000004103612731530354023152 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_tcl.tcl_event_system ?run:Uq_tcl.runner -> unit -> Unixqueue.event_systemocamlnet-4.1.2/doc/html-main/type_Rpc_portmapper_clnt.html0000644000175000017500000020432112731530354022350 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_portmapper_clnt sig
  module Make'PMAP :
    functor (U'C : Rpc_client_pre.USE_CLIENT->
      sig
        module V2 :
          sig
            type t = U'C.t
            val _program : Rpc_program.t
            val pmapproc_null :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res
            val pmapproc_null'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_null'res) ->
               unit) ->
              unit
            val pmapproc_set :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res
            val pmapproc_set'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_set'res) ->
               unit) ->
              unit
            val pmapproc_unset :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res
            val pmapproc_unset'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_unset'res) ->
               unit) ->
              unit
            val pmapproc_getport :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res
            val pmapproc_getport'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_getport'res) ->
               unit) ->
              unit
            val pmapproc_dump :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res
            val pmapproc_dump'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_dump'res) ->
               unit) ->
              unit
            val pmapproc_callit :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res
            val pmapproc_callit'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V2'pmapproc_callit'res) ->
               unit) ->
              unit
          end
        module V3 :
          sig
            type t = U'C.t
            val _program : Rpc_program.t
            val rpcbproc_null :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res
            val rpcbproc_null'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_null'res) ->
               unit) ->
              unit
            val rpcbproc_set :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res
            val rpcbproc_set'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_set'res) ->
               unit) ->
              unit
            val rpcbproc_unset :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res
            val rpcbproc_unset'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_unset'res) ->
               unit) ->
              unit
            val rpcbproc_getaddr :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res
            val rpcbproc_getaddr'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_getaddr'res) ->
               unit) ->
              unit
            val rpcbproc_dump :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res
            val rpcbproc_dump'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_dump'res) ->
               unit) ->
              unit
            val rpcbproc_callit :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res
            val rpcbproc_callit'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_callit'res) ->
               unit) ->
              unit
            val rpcbproc_gettime :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res
            val rpcbproc_gettime'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_gettime'res) ->
               unit) ->
              unit
            val rpcbproc_uaddr2taddr :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res
            val rpcbproc_uaddr2taddr'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_uaddr2taddr'res) ->
               unit) ->
              unit
            val rpcbproc_taddr2uaddr :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res
            val rpcbproc_taddr2uaddr'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V3'rpcbproc_taddr2uaddr'res) ->
               unit) ->
              unit
          end
        module V4 :
          sig
            type t = U'C.t
            val _program : Rpc_program.t
            val rpcbproc_null :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res
            val rpcbproc_null'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_null'res) ->
               unit) ->
              unit
            val rpcbproc_set :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res
            val rpcbproc_set'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_set'res) ->
               unit) ->
              unit
            val rpcbproc_unset :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res
            val rpcbproc_unset'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_unset'res) ->
               unit) ->
              unit
            val rpcbproc_getaddr :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res
            val rpcbproc_getaddr'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddr'res) ->
               unit) ->
              unit
            val rpcbproc_dump :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res
            val rpcbproc_dump'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_dump'res) ->
               unit) ->
              unit
            val rpcbproc_bcast :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res
            val rpcbproc_bcast'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_bcast'res) ->
               unit) ->
              unit
            val rpcbproc_gettime :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res
            val rpcbproc_gettime'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_gettime'res) ->
               unit) ->
              unit
            val rpcbproc_uaddr2taddr :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res
            val rpcbproc_uaddr2taddr'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_uaddr2taddr'res) ->
               unit) ->
              unit
            val rpcbproc_taddr2uaddr :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res
            val rpcbproc_taddr2uaddr'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_taddr2uaddr'res) ->
               unit) ->
              unit
            val rpcbproc_getversaddr :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res
            val rpcbproc_getversaddr'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getversaddr'res) ->
               unit) ->
              unit
            val rpcbproc_indirect :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res
            val rpcbproc_indirect'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_indirect'res) ->
               unit) ->
              unit
            val rpcbproc_getaddrlist :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res
            val rpcbproc_getaddrlist'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getaddrlist'res) ->
               unit) ->
              unit
            val rpcbproc_getstat :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res
            val rpcbproc_getstat'async :
              U'C.t ->
              Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'arg ->
              ((unit -> Rpc_portmapper_aux.t_PMAP'V4'rpcbproc_getstat'res) ->
               unit) ->
              unit
          end
      end
end
ocamlnet-4.1.2/doc/html-main/Netmime.wrap_mime_header-c.html0000644000175000017500000004236512731530354022407 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.wrap_mime_header

Class Netmime.wrap_mime_header

class wrap_mime_header : #mime_header -> mime_header
Wraps the inner header

ocamlnet-4.1.2/doc/html-main/type_Netsys.Debug.html0000644000175000017500000004077712731530354020662 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/Netgssapi_auth.Auth.html0000644000175000017500000005737312731530354021165 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netgssapi_auth.Auth

Functor Netgssapi_auth.Auth

module Auth: 
functor (G : Netsys_gssapi.GSSAPI) ->
functor (C : CONFIG) -> sig .. end
Parameters:
G : Netsys_gssapi.GSSAPI
C : CONFIG


Status
val check_status : ?fn:string -> ?minor_status:int32 -> Netsys_gssapi.major_status -> unit
If the major_status indicates an error, an error string is formed, optionally including the function name fn and the detailed information derived from minor_status. Then, the function C.raise_error is called with the string as argument.

Client configuration
val get_initiator_name : Netsys_gssapi.client_config -> G.name
val get_initiator_cred : initiator_name:G.name -> Netsys_gssapi.client_config -> G.credential
val acquire_initiator_cred : initiator_name:G.name -> Netsys_gssapi.client_config -> G.credential
val get_target_name : ?default:string * Netsys_gssapi.oid -> Netsys_gssapi.client_config -> G.name
val get_client_flags : Netsys_gssapi.client_config -> Netsys_gssapi.req_flag list
val check_client_flags : Netsys_gssapi.client_config -> Netsys_gssapi.ret_flag list -> unit
val init_sec_context : initiator_cred:G.credential ->
context:G.context option ->
target_name:G.name ->
req_flags:Netsys_gssapi.req_flag list ->
chan_bindings:Netsys_gssapi.channel_bindings option ->
input_token:Netsys_gssapi.token option ->
Netsys_gssapi.client_config ->
G.context * Netsys_gssapi.token * Netsys_gssapi.ret_flag list *
Netsys_gssapi.client_props option
Calls G.init_sec_context, and returns (out_context,out_token,flags,props_opt). If props_opt is returned the context setup is done.

Checks already for errors, and client flags.


Server configuration
val get_acceptor_name : Netsys_gssapi.server_config -> G.name
val get_acceptor_cred : acceptor_name:G.name -> Netsys_gssapi.server_config -> G.credential
val get_server_flags : Netsys_gssapi.server_config -> Netsys_gssapi.req_flag list
val check_server_flags : Netsys_gssapi.server_config -> Netsys_gssapi.ret_flag list -> unit
val accept_sec_context : acceptor_cred:G.credential ->
context:G.context option ->
chan_bindings:Netsys_gssapi.channel_bindings option ->
input_token:Netsys_gssapi.token ->
Netsys_gssapi.server_config ->
G.context * Netsys_gssapi.token * Netsys_gssapi.ret_flag list *
Netsys_gssapi.server_props option
Calls G.accept_sec_context, and returns (out_context,out_token,flags,props_opt). If props_opt is returned the context setup is done.

Checks already for errors, and server flags.


Helpers
val get_display_name : G.name -> string * Netsys_gssapi.oid
val get_exported_name : G.name -> string
ocamlnet-4.1.2/doc/html-main/type_Netchannels.in_obj_channel.html0000644000175000017500000004332512731530354023531 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.in_obj_channel object
  method close_in : unit -> unit
  method input : Bytes.t -> int -> int -> int
  method input_byte : unit -> int
  method input_char : unit -> char
  method input_line : unit -> string
  method pos_in : int
  method really_input : Bytes.t -> int -> int -> unit
  method really_input_string : int -> string
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.rec_out_channel_delegation.html0000644000175000017500000004110212731530354026113 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.rec_out_channel_delegation ?close:bool -> Netchannels.rec_out_channel -> Netchannels.rec_out_channelocamlnet-4.1.2/doc/html-main/Rpc_client.blocking_socket_config-c.html0000644000175000017500000004246612731530354024272 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.blocking_socket_config

Class Rpc_client.blocking_socket_config

class blocking_socket_config : socket_config
blocking connect configuration as class

ocamlnet-4.1.2/doc/html-main/index_classes.html0000644000175000017500000020646512731530354020131 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of classes

Index of classes


A
aggressive_cache [Nethttp_client_conncache]
This type of cache tries to keep connections as long open as possible.
augment_raw_in_channel [Netchannels]
This class implements the methods from compl_in_channel by calling the methods of raw_in_channel.
augment_raw_out_channel [Netchannels]
This class implements the methods from compl_out_channel by calling the methods of raw_out_channel.

B
basic_auth_handler [Nethttp_client]
Basic authentication.
basic_mime_header [Netmime]
An implementation of mime_header.
blocking_socket_config [Rpc_client]
blocking connect configuration as class
buffered_raw_in_channel [Netchannels]
This class adds a buffer to the underlying raw_in_channel.
buffered_raw_out_channel [Netchannels]
This class adds a buffer to the underlying raw_out_channel.
buffered_trans_channel [Netchannels]
A transactional output channel with a transaction buffer implemented in memory
buffering_engine_processing_config [Nethttpd_engine]
Implements the synchronisation by buffering

C
cache [Uq_engines_compat]
cache [Uq_engines]
new cache f esys: A cache that runs f esys to obtain values
call_engine [Shell_uq]
This engine corresponds to Shell.call.
cgi [Netcgi_common]
cgi env op meth args constructs Netcgi.cgi objects.
cgi_environment [Netcgi_common]
new cgi_environment ~config ~properties ~input_header out_obj generates a Netcgi.cgi_environment object, from the arguments.
client [Netpop]
The class client implements the POP3 protocol.
client [Netsmtp]
connect [Netpop]
connect addr timeout: Connects with the server at addr, and configure that I/O operations time out after timeout seconds of waiting.
connect [Netsmtp]
connect addr timeout: Connects with the server at addr, and configure that I/O operations time out after timeout seconds of waiting.
conversion_pipe [Netconversion]
This pipeline class (see Netchannels for more information) can be used to recode a netchannel while reading or writing.
copier [Uq_engines_compat]
copier [Uq_transfer]
This engine copies data between file descriptors as specified by the copy_task argument.
create_full_info [Nethttpd_types]
Creates a full_info object by adding to a request_info object

D
data_converter [Netftp_data_endpoint]
Creates a data conversion pipe converting fromrepr to torepr.
decoding_pipe [Netencoding.QuotedPrintable]
This pipe decodes the data written into the pipe.
decoding_pipe [Netencoding.Base64]
This pipe decodes the data written into the pipe.
default_socket_config [Rpc_server]
default_socket_config [Rpc_client]
Default configuration as class
deflating_pipe [Netgzip]
A deflating (compressing) pipe for gzip data, to be used in filters
delay_engine [Uq_engines_compat]
delay_engine [Uq_engines]
let de = delay_engine d f esys: The engine e = f() is created after d seconds, and the result of e becomes the result of de.
delegate_engine [Uq_engines_compat]
delegate_engine [Uq_engines]
Turns an engine value into a class
delete [Nethttp_client]
Argument: URI
delete_call [Nethttp_client]
digest_auth_handler [Nethttp_client]
Digest authentication.
direct_acceptor [Uq_engines_compat]
direct_acceptor [Uq_server]
An implementation of server_endpoint_acceptor for sockets and Win32 named pipes.
direct_socket_acceptor [Uq_engines_compat]

E
empty_environment [Nethttpd_types]
This class implements an environment with defined internal containers.
empty_fs [Netfs]
This is a class where all methods fail with ENOSYS.
empty_processor_hooks [Netplex_kit]
This is an empty set of processor hooks, i.e.
encoding_pipe [Netencoding.QuotedPrintable]
This pipe encodes the data written into the pipe.
encoding_pipe [Netencoding.Base64]
This pipe encodes the data written into the pipe.
engine_mixin [Uq_engines_compat]
engine_mixin [Uq_engines]
A useful class fragment that implements state and request_notification.
epsilon_engine [Uq_engines_compat]
epsilon_engine [Uq_engines]
This engine transitions from its initial state `Working 0 in one step ("epsilon time") to the passed constant state.

F
file_mime_body [Netmime]
An implementation of mime_body where the value is stored in an external file.
fmap_engine [Uq_engines_compat]
fmap_engine [Uq_engines]
Similar to map_engine but different calling conventions: The mapping function is called when the argument engine reaches a final state, and this state can be mapped to another final state.
ftp_client [Netftp_client]
The ftp client is a user session that may even span several connections.
ftp_data_receiver [Netftp_data_endpoint]
This engine receives data on a FTP data connection, and forwards them to a local receiver.
ftp_data_sender [Netftp_data_endpoint]
This engine sends data over a FTP data connection coming from a local sender.
ftp_fs [Netftp_fs]
ftp_fs base_url: Access the FTP file system rooted at base_url.

G
generic_auth_handler [Nethttp_client]
Authenticate with the passed generic HTTP mechanisms
generic_call [Nethttp_client]
This class is an implementation of http_call.
get [Nethttp_client]
Argument: URI
get_call [Nethttp_client]
group [Netaddress]
A group has a name, and consists of a number of mailboxes.
gtk_event_system [Uq_gtk]
This class is an alternate implementation of the Unixqueue event systems for the Glib event loop.

H
head [Nethttp_client]
Argument: URI
head_call [Nethttp_client]
http_engine [Nethttpd_engine]
This engine processes the requests arriving on the file descriptor using the Unix event system.
http_environment [Nethttpd_reactor]
For private use only
http_fs [Nethttp_fs]
http_fs base_url: Accesses the HTTP file system rooted at base_url.
http_protocol [Nethttpd_kernel]
The core event loop of the HTTP daemon
http_reactor [Nethttpd_reactor]
The http_reactor allows one to pull the next request from a connected client, and to deliver the response to the protocol engine.
http_response_impl [Nethttpd_kernel]
Exported for debugging and testing only

I
in_obj_channel_delegation [Netchannels]
inflating_pipe [Netgzip]
An inflating (uncompressing) pipe for gzip data, to be used in filters
input_async_descr [Uq_engines_compat]
input_async_descr [Uq_transfer]
The corresponding class for asynchronous input channels.
input_async_mplex [Uq_engines_compat]
input_async_mplex [Uq_transfer]
Creates an asynchronous input channel reading from the multiplex controller.
input_bytes [Netchannels]
Same for constant bytes
input_channel [Netchannels]
Creates an input channel from an in_channel, which must be open.
input_command [Netchannels]
Runs the command with /bin/sh, and reads the data the command prints to stdout.
input_deflate [Netgzip]
let ch' = new input_deflate ch: Reading data from ch' deflates data read from ch.
input_descr [Netchannels]
Creates a raw_in_channel for the passed file descriptor, which must be open for reading.
input_engine [Uq_engines_compat]
input_engine [Uq_engines]
Generic input engine for reading from a file descriptor: let e = new input_engine f fd tmo - Waits until the file descriptor becomes readable, and calls then let x = f fd to read from the descriptor.
input_filter [Netchannels]
An input_filter filters the data read from it through the io_obj_channel (usually a pipe after the data have been retrieved from the passed in_obj_channel.
input_gzip [Netgzip]
A Gzip.in_channel turned into a Netchannels.in_obj_channel
input_inflate [Netgzip]
let ch' = new input_inflate ch: Reading data from ch' inflates data read from ch.
input_memory [Netchannels]
Same for constant memory
input_stream [Netstream]
Make an in_obj_stream on top of an in_obj_channel.
input_string [Netchannels]
Creates an input channel from a (constant) string.

J
job_engine [Shell_sys]
The job_engine watches the job, and looks whether the processes are finished, and if so, it records the process statuses.

K
key_ring [Nethttp_client]
The key_ring is a cache for keys.

L
lift_raw_out_channel [Netchannels]
This class implements the methods from compl_out_channel by calling the methods of raw_out_channel.
lift_rec_in_channel [Netchannels]
This class implements pos_in and the methods from compl_in_channel by calling the methods of rec_in_channel.
lift_rec_out_channel [Netchannels]
This class implements pos_out and the methods from compl_out_channel by calling the methods of rec_out_channel.
lingering_close [Nethttpd_kernel]
Closes a file descriptor using the "lingering close" algorithm.
local_fsys [Netglob]
local_user_info [Netglob]
lwt_backend [Uq_lwt]
Adapter for turning an Ocamlnet event_system into an Lwt Lwt_engine.t.

M
mailbox [Netaddress]
A mailbox has a name, optionally a route (not used nowadays), and a formal address specification.
map_engine [Uq_engines_compat]
map_engine [Uq_engines]
The map_engine observes the argument engine, and when the state changes to `Done, `Error, or `Aborted, the corresponding mapping function is called, and the resulting state becomes the state of the mapped engine.
memory_mime_body [Netmime]
An implementation of mime_body where the value is stored in-memory.
meta_engine [Uq_engines_compat]
meta_engine [Uq_engines]
maps the final state s to `Done s
mime_arg [Netcgi_common]
mime_argument [Netcgi1_compat.Netcgi]
mime_argument [Netcgi]
Old deprecated MIME argument class.
modify_http_engine_config [Nethttpd_engine]
Modifies the passed config object as specified by the optional arguments.
modify_http_processor_config [Nethttpd_reactor]
Modifies the passed config object as specified by the optional arguments.
modify_http_protocol_config [Nethttpd_kernel]
Modifies the passed config object as specified by the optional arguments
modify_http_reactor_config [Nethttpd_reactor]
Modifies the passed config object as specified by the optional arguments.
mp [Netplex_mp]
Uses Unix.fork to create new threads.
msync_engine [Uq_engines_compat]
msync_engine [Uq_engines]
Multiple synchronization: let me = new msync_engine el f x0 esys - Runs the engines in el in parallel, and waits until all are `Done.
mt [Netplex_mt]
Uses Thread.create to create new threads

O
of_stream_fs [Netglob]
options [Nethttp_client]
Argument: URI or "*"
options_call [Nethttp_client]
out_obj_channel_delegation [Netchannels]
output_async_descr [Uq_engines_compat]
output_async_descr [Uq_transfer]
This engine implements an async_out_channel for the output descriptor dst.
output_async_mplex [Uq_engines_compat]
output_async_mplex [Uq_transfer]
Creates an asynchronous output channel writing to the multiplex controller (see also output_async_descr for the corresponding class writing to a single descriptor).
output_buffer [Netchannels]
This output channel writes the data into the passed buffer.
output_channel [Netchannels]
Creates an output channel writing into an out_channel.
output_command [Netchannels]
Runs the command with /bin/sh, and data written to the channel is piped to stdin of the command.
output_deflate [Netgzip]
let ch' = new output_deflate ch: Data written to ch' is deflated and written to ch.
output_descr [Netchannels]
Creates a raw_out_channel for the passed file descriptor, which must be open for writing.
output_engine [Uq_engines_compat]
output_engine [Uq_engines]
Generic output engine for writing to a file descriptor: let e = new output_engine f fd tmo - Waits until the file descriptor becomes writable, and calls then let x = f fd to write to the descriptor.
output_filter [Netchannels]
An output_filter filters the data written to it through the io_obj_channel (usually a pipe), and writes the filtered data to the passed out_obj_channel.
output_gzip [Netgzip]
A Gzip.out_channel turned into a Netchannels.out_obj_channel
output_inflate [Netgzip]
let ch' = new output_inflate ch: Data written to ch' is inflated and written to ch.
output_netbuffer [Netchannels]
This output channel writes the data into the passed netbuffer.
output_null [Netchannels]
This output channel discards all written data.

P
performance_event_system [Unixqueue]
The implementation using Netsys_pollset_generic.performance_pollset.
pipe [Netchannels]
A pipe has two internal buffers (realized by Netbuffer).
pipeline [Nethttp_client]
A pipeline is a queue of HTTP calls to perform
poll_engine [Uq_engines_compat]
poll_engine [Uq_engines]
This engine waits until one of the passed operations can be carried out, or until one of the operations times out.
poll_process_engine [Uq_engines_compat]
poll_process_engine [Uq_engines]
This class is deprecated! Use the classes in Shell_uq instead.
pollset_event_system [Unixqueue_pollset]
post [Nethttp_client]
Arguments: URI, parameter list to be transferred as application/x-www-form-urlencoded body
post_call [Nethttp_client]
post_raw [Nethttp_client]
Arguments: URI, body
prioritizer [Uq_engines_compat]
prioritizer [Uq_engines]
Creates a prioritizer
processor_base [Netplex_kit]
A virtual (incomplete) base class for processors.
processor_hooks_delegation [Netplex_kit]
Takes a hooks object, and makes a class of it.
protocol_switch_factory [Netplex_kit]
protocol_switch_factory name merge_list: Merges the factories in merge_list to a single factory.
protocol_switch_processor [Netplex_kit]
The arg is a list of pairs (proto_name, proto_proc).
proxy_client [Uq_socks5]
The object created by new proxy_client addr can be passed as proxy to the Uq_engines.connector, Uq_engines.listener, and Uq_engines.datagram_provider functions to use the SOCKS proxy for connections, servers, and datagram socket, respectively.
pseudo_async_in_channel [Uq_engines_compat]
pseudo_async_in_channel [Uq_transfer]
Takes a Netchannels.raw_in_channel as an asynchronous channel.
pseudo_async_out_channel [Uq_engines_compat]
pseudo_async_out_channel [Uq_transfer]
Takes a Netchannels.raw_out_channel as an asynchronous channel.
put [Nethttp_client]
Arguments: URI, body
put_call [Nethttp_client]

Q
qseq_engine [Uq_engines_compat]
qseq_engine [Uq_engines]

R
raw_in_channel_delegation [Netchannels]
raw_out_channel_delegation [Netchannels]
read_in_record_channel [Netftp_data_endpoint]
Provides an in_record_channel that takes newline characters as EOR representation.
rec_in_channel_delegation [Netchannels]
rec_out_channel_delegation [Netchannels]
receiver [Uq_engines_compat]
receiver [Uq_transfer]
This engine copies all data from the src file descriptor to the dst output channel.
redirected_environment [Nethttpd_types]
This class overlays the input-side containers of an existing environment.
restrictive_cache [Nethttp_client_conncache]
A restrictive cache closes connections as soon as there are no pending requests.

S
select_based_event_system [Unixqueue_select]
This the old Unix.select-based imeplementation of event systems which was the default one until Ocamlnet-2.2.
sender [Uq_engines_compat]
sender [Uq_transfer]
This engine copies all data from the src input channel to the dst file descriptor.
seq_engine [Uq_engines_compat]
seq_engine [Uq_engines]
This engine runs two engines in sequential order.
serializer [Uq_engines_compat]
serializer [Uq_engines]
Creates a serializer
shell_fs [Shell_fs]
signal_engine [Uq_engines_compat]
signal_engine [Uq_engines]
let se = new signal_engine esys: The engine se remains in `Working 0 until the method se # signal x is called.
simple_arg [Netcgi_common]
simple_argument [Netcgi1_compat.Netcgi]
simple_argument [Netcgi]
Old deprecated simple argument class.
socket_descr [Netchannels]
Creates a raw_io_channel for the passed socket descriptor, which must be open for reading and writing, and not yet shut down in either direction.
standard_event_system [Unixqueue]
The standard implementation of an event system.
std_activation [Netcgi1_compat.Netcgi]
stream_seq_engine [Uq_engines_compat]
stream_seq_engine [Uq_engines]
let se = new stream_seq_engine x0 s esys: The constructed engine se fetches functions f : 'a -> 'a #engine from the stream s, and runs the engines obtained by calling these functions e = f x one after the other.
sub_stream [Netstream]
A sub stream is the part of the whole stream from the current position to an arbitrary other position that is determined by len and delimiter.
sync_engine [Uq_engines_compat]
sync_engine [Uq_engines]
This engine runs two engines in parallel, and waits until both are `Done (synchronization).

T
tcl_event_system [Uq_tcl]
This class is an alternate implementation of the Unixqueue event systems for the TCL event loop.
telnet_session [Nettelnet_client]
A telnet session
tempfile_trans_channel [Netchannels]
A transactional output channel with a transaction buffer implemented as temporary file
template [Netcgi_modtpl]
new template ?filename tpl computes a new template from the string tpl.
timeout_engine [Uq_engines_compat]
timeout_engine [Uq_engines]
timeout_engine d x e: If the engine e finishes within d seconds, the result remains unchanged.
tls_endpoint [Netchannels_crypto]
This class is slightly more efficient than tls_layer, and to preferred if you have direct access to the file descriptors.
tls_layer [Netchannels_crypto]
Adds TLS security to an already established connection, here made available as separate channels for input and output.
tls_socket_config [Rpc_server]
TLS configuration as class
tls_socket_config [Rpc_client]
TLS configuration as class
trace [Nethttp_client]
Arguments: URI, maximum number of hops
trace_call [Nethttp_client]

U
unbound_async_call [Rpc_client]
Same as unbound_async_call, but with an engine API.
unified_auth_handler [Nethttp_client]
Support both digest and basic authentication, with preference to digest.
unix_event_system [Unixqueue]
An alternate name for standard_event_system, provided for backward compatibility.

W
watchdog [Uq_engines_compat]
watchdog [Uq_engines]
A watchdog engine checks whether the argument engine makes progress, and if there is no progress for the passed number of seconds, the engine is aborted, and the watchdog state changes to `Error Watchdog_timeout.
wrap_mime_body [Netmime]
Wraps the inner body
wrap_mime_body_ro [Netmime]
Wraps the inner body but disallows modifications.
wrap_mime_header [Netmime]
Wraps the inner header
wrap_mime_header_ro [Netmime]
Wraps the inner header but disallows modifications.
write_out_record_channel [Netftp_data_endpoint]
Provides an out_record_channel that represents EOR as newline character.

X
x509_certificate_from_ASN1 [Netx509]
Parses the passed ASN.1 value and returns the certificate object
x509_certificate_from_DER [Netx509]
Parses the passed DER string and returns the certificate object
x509_dn_from_ASN1 [Netx509]
Returns the DN object for a Name entity
x509_dn_from_string [Netx509]
Returns the DN object for an RFC 4514-encoded string
ocamlnet-4.1.2/doc/html-main/type_Netplex_kit.protocol_switch_processor.html0000644000175000017500000004103312731530354026140 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_kit.protocol_switch_processor (string * Netplex_types.processor) list -> Netplex_types.processorocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.input_engine.html0000644000175000017500000004156012731530354024462 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.input_engine (Unix.file_descr -> 'a) ->
Unix.file_descr ->
float -> Unixqueue.event_system -> ['a] Uq_engines_compat.engine
ocamlnet-4.1.2/doc/html-main/Netencoding.Q.html0000644000175000017500000004541612731530354017736 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Q

Module Netencoding.Q

module Q: sig .. end


The "Q" encoding as described by RFC 2047.
val encode : ?pos:int -> ?len:int -> string -> string
Note: All characters except alphanumeric characters are protected by hex tokens. In particular, spaces are represented as "=20", not as "_".
val encode_tstring : ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
Same for tagged string inputs. The result are always bytes, though
val encode_poly : ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t
Polymorphic version
val decode : ?pos:int -> ?len:int -> string -> string
Q-decode a string
val decode_tstring : ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
Same for tagged string inputs. The result are always bytes, though
val decode_poly : ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t
Polymorphic version
ocamlnet-4.1.2/doc/html-main/type_Netchannels.input_memory.html0000644000175000017500000004114212731530354023323 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_memory ?pos:int -> ?len:int -> Netsys_types.memory -> Netchannels.in_obj_channelocamlnet-4.1.2/doc/html-main/Netftp_data_endpoint.write_out_record_channel-c.html0000644000175000017500000004306612731530354026720 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.write_out_record_channel

Class Netftp_data_endpoint.write_out_record_channel

class write_out_record_channel : repr:text_data_repr -> Netchannels.out_obj_channel -> out_record_channel
Provides an out_record_channel that represents EOR as newline character.


repr : Determines the newline character to use

ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.direct_acceptor-c.html0000644000175000017500000004261212731530354024306 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.direct_acceptor

Class Uq_engines_compat.direct_acceptor

class direct_acceptor : ?close_on_shutdown:bool -> ?preclose:unit -> unit -> Unix.file_descr -> Unixqueue.event_system -> server_endpoint_acceptor

ocamlnet-4.1.2/doc/html-main/Netchannels.input_memory-c.html0000644000175000017500000004243512731530354022510 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_memory

Class Netchannels.input_memory

class input_memory : ?pos:int -> ?len:int -> Netsys_types.memory -> in_obj_channel
Same for constant memory

ocamlnet-4.1.2/doc/html-main/type_Netsys_ciphers.cipher_ctx.html0000644000175000017500000004507112731530354023471 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_ciphers.cipher_ctx object
  method block_constraint : int
  method decrypt :
    last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int
  method decrypt_bytes : Bytes.t -> Bytes.t
  method decrypt_string : string -> string
  method encrypt :
    last:bool -> Netsys_types.memory -> Netsys_types.memory -> int * int
  method encrypt_bytes : Bytes.t -> Bytes.t
  method encrypt_string : string -> string
  method mac : unit -> string
  method padding : Netsys_ciphers.padding
  method set_header : string -> unit
  method set_iv : string -> unit
  method supports_aead : bool
end
ocamlnet-4.1.2/doc/html-main/type_Netchannels.lift_rec_in_channel.html0000644000175000017500000004107712731530354024550 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.lift_rec_in_channel ?start_pos_in:int -> Netchannels.rec_in_channel -> Netchannels.in_obj_channelocamlnet-4.1.2/doc/html-main/Netftp_data_endpoint.out_record_channel-c.html0000644000175000017500000004503012731530354025477 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netftp_data_endpoint.out_record_channel

Class type Netftp_data_endpoint.out_record_channel

class type out_record_channel = object .. end
An out_record_channel can be used to output files with record structure. This is purely abstract, as Unix does not support such files natively, so this kind of channel is usually mapped to a flat representation when stored in a real file, e.g. record boundaries become newline characters.
Inherits
method output_eor : unit -> unit
Finishes the current record.

The record model is as follows: At the beginning of the channel, or after output_eor, a new record can be potentially started. However, the record counts only as existing when either at least one byte is output, or the record is explicitly ended with a output_eor call.

This rule allows it to represent channels containing no records. There is an ambiguity at the end of the channel, however: It is possible that there are characters between the last EOR and the EOF. This could also be represented by printing another EOR just before EOF. The preferred representation is the latter.

This model correlates to the usual rules for line-structured files, so think EOR = EOL.

ocamlnet-4.1.2/doc/html-main/type_Uq_engines.datagram_multiplex_controller.html0000644000175000017500000005262412731530354026564 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.datagram_multiplex_controller object
  method alive : bool
  method cancel_reading : unit -> unit
  method cancel_shutting_down : unit -> unit
  method cancel_writing : unit -> unit
  method event_system : Unixqueue.event_system
  method inactivate : unit -> unit
  method mem_supported : bool
  method read_eof : bool
  method reading : bool
  method received_from : Unix.sockaddr
  method send_to : Unix.sockaddr -> unit
  method shutting_down : bool
  method start_mem_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_mem_writing :
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_shutting_down :
    ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
  method start_writing :
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit
  method supports_half_open_connection : bool
  method tls_session : (string * string) option
  method tls_session_props : Nettls_support.tls_session_props option
  method tls_stashed_endpoint : unit -> exn
  method writing : bool
  method wrote_eof : bool
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines.map_engine.html0000644000175000017500000004247412731530354022542 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.map_engine map_done:('-> 'Uq_engines.engine_state) ->
?map_error:(exn -> 'Uq_engines.engine_state) ->
?map_aborted:(unit -> 'Uq_engines.engine_state) ->
?propagate_working:bool -> '#Uq_engines.engine -> ['b] Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_kernel.http_protocol_config.html0000644000175000017500000004245712731530354025723 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel.http_protocol_config object
  method config_announce_server : Nethttpd_kernel.announcement
  method config_limit_pipeline_length : int
  method config_limit_pipeline_size : int
  method config_max_header_length : int
  method config_max_reqline_length : int
  method config_max_trailer_length : int
  method config_suppress_broken_pipe : bool
  method config_tls : Netsys_crypto_types.tls_config option
end
ocamlnet-4.1.2/doc/html-main/Netsys_signal.html0000644000175000017500000006315012731530354020117 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_signal

Module Netsys_signal

module Netsys_signal: sig .. end
Signal handler framework

This module defines a simple framework for setting signal handlers. When two modules want to set the handler for the same signal, the framework decides in which order the handlers are executed.

The module also defines an empty handler for Sys.sigpipe, so this signal is ignored by the program (and you get a Unix.Unix_error(EPIPE,_,_) exception instead).

If you don't like that Netsys sets the Sigpipe handler, you can undo this:

Sys.set_signal Sys.sigpipe Sys.Signal_default;;
Netsys_signal.keep_away_from Sys.sigpipe;;
    

Win32: Only Sys.sigint handlers can effectively be registered. Registrations for other signal types are accepted but ignored.


val register_handler : ?library:string ->
?priority:int ->
?keep_default:bool ->
name:string -> signal:int -> callback:(int -> unit) -> unit -> unit
This function registers a handler called name for signal number signal. The handler function is callback. The int argument of the callback is the signal number.

By default, the handler is an application handler. If library is set, the handler is for this library. The name passed as library is the findlib name of the library.

By registering another handler for the same library, name, and signal, the old handler is overridden.

When several handlers are defined for the same signal, all handlers are executed that are defined for the signal (when the signal happens). The order of execution is given by priority. The handler functions are executed in ascending priority order. If the priority number is equal for two handlers, the order is undefined.

The priority defaults to 0 for library handlers, and to 100 for application handlers. Libraries should only use values from 0 to 99, and applications only from 100 to 199.

If all handlers for a certain signal set keep_default, then there will be a special action after all signal handlers have been executed. The special action emulates the default behavior for the signal. For now, there is only a simple emulation: If the signal terminates the process, the process is immediately exited with code 126. If the default behaviour is "no-op", nothing happens. We don't try (yet) to do better (emulate core-dumps, emulate the right process status) because this is difficult in the general case.

The handler definition takes place immediately.

Any exceptions occuring during the execution of a handler are caught and ignored.

val register_exclusive_handler : name:string -> signal:int -> install:(unit -> unit) -> unit -> unit
An exclusive handler for a signal is the only handler for the signal. If it is tried to register another handler when there is already an exclusive handler, the second registration fails. Also, an exclusive handler cannot be registered when there is already a normal handler for the signal. It is, however, possible to replace the registered exclusive handler by another exclusive handler for the same signal.

An exclusive handler is installed by running the install function, which can e.g. call Sys.set_signal to define the handler. Other methods (e.g. use some C wrapper) are also possible. It is assumed that install overrides any existing handler.

val restore_management : int -> unit
restore_management signo: Restores signal handling management for signo as defined by the handler list for this signal. Calling restore_management makes sense when the signal handler has been overridden with Sys.set_signal, but at some point this module is again responsible for managing the signal handling for this signal.
val keep_away_from : int -> unit
keep_away_from signo: This signal signo is added to the "keep away list". This means that this module will never try to change the signal behavior again for signo. Even restore_management will not restore the signal handling again. This function should only by called by applications wishing to do the signal handling all themselves.

This function does not have any effect on the already installed handlers. It is nevertheless useful for applications calling Sys.set_signal directly to ensure that Netsys_signal will never again try to override the handler.

type action = [ `Callback of int -> unit | `Install of unit -> unit ] 
`Callback is used for normal handlers, and `Install for exclusive handlers.
type entry = {
   sig_number : int;
   sig_library : string option;
   sig_priority : int;
   sig_keep_default : bool;
   sig_name : string;
   sig_action : action;
}
val list : unit -> entry list
Returns the list of signal handlers
val keep_away_list : unit -> int list
Returns the "keep away list".
val init : unit -> unit
Call this function to ensure that this module is initialized. It is also possible to call any other function. After initialization the Sigpipe handler is set.

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/Nethttp_client.put-c.html0000644000175000017500000004224212731530354021307 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.put

Class Nethttp_client.put

class put : string -> string -> http_call
Arguments: URI, body

ocamlnet-4.1.2/doc/html-main/type_Netchannels.input_bytes.html0000644000175000017500000004112512731530354023142 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_bytes ?pos:int -> ?len:int -> Bytes.t -> Netchannels.in_obj_channelocamlnet-4.1.2/doc/html-main/Netmcore_mempool.Debug.html0000644000175000017500000004222312731530354021624 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_mempool.Debug

Module Netmcore_mempool.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enable debugging
val enable_alloc : bool Pervasives.ref
Trace allocation and deallocation
ocamlnet-4.1.2/doc/html-main/Nettls_gnutls.GNUTLS_ENDPOINT.html0000644000175000017500000004252512731530354022460 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nettls_gnutls.GNUTLS_ENDPOINT

Module type Nettls_gnutls.GNUTLS_ENDPOINT

module type GNUTLS_ENDPOINT = sig .. end

module TLS: Nettls_gnutls.GNUTLS_PROVIDER 
val endpoint : TLS.endpoint
ocamlnet-4.1.2/doc/html-main/type_Nethttpd_reactor.Debug.html0000644000175000017500000004101112731530354022664 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_reactor.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Uq_transfer.input_async_descr.html0000644000175000017500000004134512731530354024344 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_transfer.input_async_descr src:Unix.file_descr ->
?buffer_size:int ->
?close_src:bool ->
Unixqueue.event_system -> Uq_transfer.async_in_channel_engine
ocamlnet-4.1.2/doc/html-main/type_Netplex_sharedvar.Make_vv.html0000644000175000017500000004310012731530354023374 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sharedvar.Make_vv functor (T : Netplex_cenv.TYPE->
  sig
    type t = T.t
    type var
    val access : string -> var
    val get : var -> t
    val set : var -> t -> unit
    val version : var -> int64
    val update : var -> bool
  end
ocamlnet-4.1.2/doc/html-main/Netplex_types.logger_factory-c.html0000644000175000017500000004326412731530354023371 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.logger_factory

Class type Netplex_types.logger_factory

class type logger_factory = object .. end

method name : string
method create_logger : config_file ->
address -> controller -> logger
ocamlnet-4.1.2/doc/html-main/type_Netmime.wrap_mime_body.html0000644000175000017500000004100312731530354022721 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmime.wrap_mime_body #Netmime.mime_body -> Netmime.mime_bodyocamlnet-4.1.2/doc/html-main/Netsys_signal.Debug.html0000644000175000017500000004200312731530354021136 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_signal.Debug

Module Netsys_signal.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
Enables Netlog-style debugging of this module
ocamlnet-4.1.2/doc/html-main/type_Netchannels.output_command.html0000644000175000017500000004107212731530354023634 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.output_command ?onclose:(unit -> unit) -> string -> Netchannels.out_obj_channelocamlnet-4.1.2/doc/html-main/Rpc_server.socket_config-c.html0000644000175000017500000004330212731530354022440 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_server.socket_config

Class type Rpc_server.socket_config

class type socket_config = object .. end

method listen_options : Uq_engines.listen_options
method multiplexing : dbg_name:string Pervasives.ref ->
close_inactive_descr:bool ->
Rpc.protocol ->
Unix.file_descr ->
Unixqueue.event_system ->
Rpc_transport.rpc_multiplex_controller Uq_engines.engine
ocamlnet-4.1.2/doc/html-main/type_Netplex_mbox.Make_mbox_type.html0000644000175000017500000004245312731530354023747 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mbox.Make_mbox_type functor (T : Netplex_cenv.TYPE->
  sig
    type t = T.t
    type mbox
    val create : string -> mbox
    val send : mbox -> t -> unit
    val receive : mbox -> t
  end
ocamlnet-4.1.2/doc/html-main/type_Netmcore_ref.html0000644000175000017500000004625112731530354020751 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_ref sig
  type 't sref
  type 't sref_descr
  val sref : Netmcore.res_id -> '-> 'Netmcore_ref.sref
  val assign : 'Netmcore_ref.sref -> '-> unit
  val deref_ro : 'Netmcore_ref.sref -> 't
  val deref_p : 'Netmcore_ref.sref -> ('-> 'a) -> 'a
  val deref_c : 'Netmcore_ref.sref -> 't
  val heap : 'Netmcore_ref.sref -> Obj.t Netmcore_heap.heap
  val descr_of_sref : 'Netmcore_ref.sref -> 'Netmcore_ref.sref_descr
  val sref_of_descr :
    Netmcore.res_id -> 'Netmcore_ref.sref_descr -> 'Netmcore_ref.sref
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_mp.html0000644000175000017500000004214012731530354020445 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mp sig
  class mp :
    ?keep_fd_open:bool ->
    ?terminate_tmo:int -> unit -> Netplex_types.parallelizer
  val mp :
    ?keep_fd_open:bool ->
    ?terminate_tmo:int -> unit -> Netplex_types.parallelizer
end
ocamlnet-4.1.2/doc/html-main/Gssapi.html0000644000175000017500000010476612731530354016534 0ustar gerdgerd Ocamlnet 4 Reference Manual : Gssapi

Gssapi


The GSSAPI

The GSSAPI is a cryptographic API allowing the authentication of clients and servers, and provides integrity and privacy protection of messages. There is often already a GSSAPI library installed on system level (e.g. MIT Kerberos or Heimdal), and this library provides such services in a portable way. There are many crypto mechanisms specified for GSSAPI, and worthwhile to mention are:

  • Kerberos 5
  • SPNEGO
  • SCRAM
The GSSAPI as such is a C API. OCamlnet defines the "OCamlized" version Netsys_gssapi.GSSAPI as a first-class module. We don't want to go here into detail how the GSSAPI functions are called, but instead explain how you can use the GSSAPI together with the network protocol implementations in OCamlnet.

OPAM users: Note that the OPAM package for OCamlnet does not build the GSSAPI module by default. The trigger for this is the presence of the conf-gssapi OPAM package, i.e. do opam install conf-gssapi to rebuild with GSSAPI.

Compatibility

So far, OCamlnet only supports the base interface as speficied in the RFCs 2743 and 2744. There are interesting extensions, in particular for setting session parameters and for getting credentials with passwords. These will be added in future OCamlnet releases.

The GSSAPI on Windows: Microsoft "sort of" implements the GSSAPI. However, instead of using the C API specified by the IETF Windows goes its own proprietary way. At this point, OCamlnet does not support the SSPI API Windows provides, as it would exceed the resources of the developers. Note that there is also an edition of MIT Kerberos for Windows, and this could be an easy path to get full GSSAPI support. It has not yet been tested, though (any feedback on this is welcome).

The system-level GSSAPI: network logins

Getting acces to the system-level GSSAPI library is simple:

The function definitions in Netgss.System are actually wrappers around the system-level GSSAPI.

What you can do with the system-level GSSAPI: The common way of using it is that by calling the GSSAPI with default values you can log in to any network services secured with it. For example, if there is Kerberos deployed in the local network, the GSSAPI would then make a Kerberos login. This is probably the most likely scenario. Of course, there could also be some other network authentication service, and the GSSAPI could be configured to use this other service for doing network logins. The point here is that the client program needs not to know which authentication mechanism is deployed in the network.

When used in this way, it is common that the client program requesting access to secured services need not know the credentials (i.e. access tickets or passwords). The system-level GSSAPI knows how to get the credentials and how to use them for a service login. Of course, this also means you can only login as system user (i.e. if you are "tim" on your local machine, you'll also be "tim" when logging in to a network service).

It is outside the scope of this text how you can configure the system-level GSSAPI so that the default login method is the default network login.

The system-level GSSAPI may also make other mechanisms available to client programs. In this case, you need to request specific authentication mechanisms and not just the default. Often, it is also required to set these mechanisms up in a special way (e.g. provide a database with passwords). The GSSAPI as such does not address these configuration issues. It only includes functions for using a mechanism in a protocol.

Defining a GSSAPI module on OCaml level

As we are only using the GSSAPI functions from OCaml, it is also possible to define a GSSAPI module directly in OCaml instead of wrapping C functions. Within OCamlnet, there is so far only Netmech_scram_gssapi following this path. The nice aspect of this approach is that we can configure the security mechanism directly, without having to edit files or using obscure helper functions, e.g.

  let gssapi =
    Netmech_scram_gssapi.scran_gss_api
      ~client_key_ring
      (Netmech_scram.profile `GSSAPI `Sha1)

Here, the client_key_ring contains already the client credentials, which then need not to be passed through the GSSAPI functions.

Passing the GSSAPI module to a protocol interpreter

The GSSAPI is passed as first-class module to the protocol interpreter. In the above code, the variable gssapi is already such a module.

At the time of writing this text, these interpreters support the GSSAPI:

Sometimes, the gssapi variable can be directly passed to the protocol interpreter, but even in this case some extra configuration is sometimes needed. An example of this is Netftp_fs:

let fs =
  Netftp_fs.ftp_fs
    ...
    ~gssapi_provider:gssapi
    ...
    "ftp://user@host/path"

The protocol interpreters assume then reasonable defaults: they select the default authentication mechanism, and assume the default identity. This is usually the right thing when you do a system-level network login.

However, even in this case there are a few things that may need tuning:

  • which service is addressed
  • whether integrity protection or even privacy protection is enabled
  • whether other options are enabled, e.g. delegation
Most protocol interpreters can be configured to use non-default values. For Netftp_fs and some other interpreters you can also pass a gssap_config argument, which is an instance of Netsys_gssapi.client_config. For example, to enforce encryption, you'd do:

let gssapi_config =
  Netsys_gssapi.create_client_config
    ~privacy:`Required
    ()

let fs =
  Netftp_fs.ftp_fs
    ...
    ~gssapi_provider:gssapi
    ~gssapi_config
    ...
    "ftp://user@host/path"

(By default, this is set to `If_possible.)

The GSSAPI and SASL

SASL is a authentication framework that is very similar to GSSAPI. The main difference is that SASL is directly defined as protocol, whereas GSSAPI takes the detour and first defines a protocol API, and then describes how to use this API in a concrete protocol. Because of the absence of the API, SASL is a lot simpler, and also has fewer features. So far, SASL is mainly used for challenge/response password authentication whereas GSSAPI targets complicated authentication suites such as Kerberos.

Nevertheless, both approaches are similar enough that it is possible to encapsulate any GSSAPI authentication exchange as SASL exchange. This is called "bridging". This way it is possible to use GSSAPI for protocols that only have a SASL option. Note that there is no standard for the opposite direction, as SASL is commonly seen as the weaker standard, and there was so far not enough support for wrapping SASL mechanisms so that they are usable from GSSAPI (but note that there are mechanisms which are defined for both SASL and GSSAPI, e.g. SCRAM).

In Ocamlnet, there are two bridging methods:

Let's have a look at an example: POP only supports SASL. For logging in to your maildrop using Kerberos you need to use a bridge. The Ocamlnet implementation Netpop provides a function for authenticating a client with an existing connection to a server. For a normal password login using SASL the Netpop.authenticate call could look like

Netpop.authenticate
  ~sasl_mechs:[ (module Netmech_scram_sasl.SCRAM_SHA1);
                (module Netmech_digest_sasl.DIGEST_MD5);
              ]
  ~user:"tom"
  ~creds:[ "password", "sEcReT", [] ]
  client

For GSSAPI, you mainly need to wrap the GSSAPI provider with some additional configuration. In particular, you need to pass the name of the service that is addressed. For POP, this name normally is the string "pop@" followed by the fully-qualified host name.

module K = Netmech_krb5_sasl.Krb5_gs1(Netgss.System)

Netpop.authenticate
  ~sasl_mechs:[ (module K) ]
  ~sasl_params:[ "gssapi-acceptor", "pop@mail.provider.com", false ]
  ~user:"any"
  ~creds:[]
  client

Note that the user name is ignored in this case, and that there are no credentials.

The GSSAPI authentication loop

As an API, this authentication framework defines a handful of functions. Only four of these are the really important ones doing all the work whereas the remaining ones play only an assisting role:

  • init_sec_context: This function is repeatedly called by the client for authentication. After the first call, it generates a token, which needs to be sent to the server. The server responds with a response token, which is fed ot the next invocation of init_sec_context. This loop goes on until init_sec_context signals that the authentication is successful (or failed). In the positive case, the caller gets an initialized security context.
  • accept_sec_context: This function is the counterpart in the server. Tokens coming from the client are passed as arguments to accept_sec_context, and the output of the function includes the response tokens. If the authentication is successful, the server also gets a security context.
  • wrap: After the authentication, this function can be called to sign and/or encrypt a message.
  • unwrap: This is the function to check the signature and/or to decrypt the message.
So the login procedure only consists in the exchange of tokens emitted and received by init_sec_context and accept_sec_context. Once the authentication is done, the functions wrap and unwrap can be used to securely exchange messages.

Often a protocol utilizes only the authentication service from GSSAPI and does not wrap any messages (e.g. HTTP or the bridges for SASL). In this case, it is highly recommended to use another security layer such as TLS to protect the data exchange. Other protocols, however, securely wrap messages and need not the help of TLS. An excample of the latter is FTP.

Mechanism names

The GSSAPI identifies authentication mechanisms by OIDs. (If you did not yet encounter them, OIDs are a standardized way of naming "objects" that often configure network protocols. OIDs are sequences of integers. There is some support in Netoid.) Examples:

  • [| 1;2;840;113554;1;2;2 |] is the OID of Kerberos
  • [| 1;3;6;1;5;5;14 |] is the OID of SCRAM
In Ocamlnet, OIDs are represented as int array.

Principal names

The "principal" is the identity of a client or server with respect to the authentication protocol. For clients, this is usually a user name, and for servers a service name. The GSSAPI defines a few common ways of naming principals:

  • NT_USER_NAME: This is the user name as a simple unstructured string, e.g. "tim".
  • NT_MACHINE_UID_NAME: This is the numeric user name as a binary number (big endian)
  • NT_STRING_UID_NAME. The numeric user name as a decimal number
  • NT_HOSTNAME_SERVICE: This name identifies the service by combining a service name like "imap" or "ftp" with the hostname: "service\@host"
As Kerberos is frequently used via GSSAPI, it may also be helpful to use Kerberos principals directly:

  • NT_KRB5_PRINCIPAL_NAME: This name type follows the Kerberos rules, e.g. "tim@REALM" for users or "ftp/hostname@REALM" for services.
Like mechanisms, name types are identified by OID:

Where OCamlnet needs a principal name, it usually expects the pair of a string and an OID:

 string * Netoid.oid 

For example, look at the target_name argument of Netsys_gssapi.create_client_config.

There are also a few helper functions:

Limitations

So far there is no good support for:

  • Wrapping passwords into the GSSAPI credential type. This primarily means that it is unspecified how a user proves its identity. For the system-level GSSAPI this means you can only authenticate as the default principal, i.e. as the user you already be on the system level. It is not possible to log in as another user.
and probably other GSSAPI options I'm not aware of.


ocamlnet-4.1.2/doc/html-main/type_Netcgi1_compat.Netcgi.std_activation.html0000644000175000017500000004233012731530354025412 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi1_compat.Netcgi.std_activation ?env:Netcgi1_compat.Netcgi_env.cgi_environment ->
?processing:(string ->
             Netmime.mime_header -> Netcgi1_compat.Netcgi.argument_processing) ->
?operating_type:Netcgi1_compat.Netcgi.operating_type ->
unit -> Netcgi1_compat.Netcgi_types.cgi_activation
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.client_endpoint_connector.html0000644000175000017500000004163012731530354027224 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.client_endpoint_connector object
  method connect :
    Uq_engines_compat.connect_address ->
    Unixqueue.event_system ->
    Uq_engines_compat.connect_status Uq_engines_compat.engine
end
ocamlnet-4.1.2/doc/html-main/Rpc_client.unbound_async_call-c.html0000644000175000017500000004430412731530354023440 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_client.unbound_async_call

Class Rpc_client.unbound_async_call

class unbound_async_call : t -> Rpc_program.t -> string -> Netxdr.xdr_value -> [Netxdr.xdr_value] Uq_engines.engine
Same as unbound_async_call, but with an engine API. The engine is initially in state `Working 0. When the call is finished, the engine transitions to `Done r where r is the response value. If an error happens, it transitions to `Error e where e is the exception.

One can abort the engine, but one caveat: This does not stop the transmission of the current message (the underlying RPC transporter doing this is not aborted). Aborting can only prevent that a message is sent before it is sent, and it can remove the call from the housekeeping data structures before the response arrives. Of course, one can shut the client down to achieve immediate stop of data transmission.


ocamlnet-4.1.2/doc/html-main/type_Netsendmail.html0000644000175000017500000005604112731530354020602 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsendmail sig
  val compose :
    ?in_charset:Netconversion.encoding ->
    ?out_charset:Netconversion.encoding ->
    ?from_addr:string * string ->
    ?cc_addrs:(string * string) list ->
    ?bcc_addrs:(string * string) list ->
    ?content_type:string * (string * Netmime_string.s_param) list ->
    ?container_type:string * (string * Netmime_string.s_param) list ->
    ?attachments:Netmime.complex_mime_message list ->
    to_addrs:(string * string) list ->
    subject:string -> string -> Netmime.complex_mime_message
  val wrap_attachment :
    ?in_charset:Netconversion.encoding ->
    ?out_charset:Netconversion.encoding ->
    ?content_id:string ->
    ?content_description:string ->
    ?content_location:string ->
    ?content_disposition:string * (string * Netmime_string.s_param) list ->
    content_type:string * (string * Netmime_string.s_param) list ->
    Netmime.mime_body -> Netmime.complex_mime_message
  val wrap_mail :
    ?in_charset:Netconversion.encoding ->
    ?out_charset:Netconversion.encoding ->
    ?from_addr:string * string ->
    ?cc_addrs:(string * string) list ->
    ?bcc_addrs:(string * string) list ->
    to_addrs:(string * string) list ->
    subject:string ->
    Netmime.complex_mime_message -> Netmime.complex_mime_message
  val wrap_parts :
    ?in_charset:Netconversion.encoding ->
    ?out_charset:Netconversion.encoding ->
    ?content_type:string * (string * Netmime_string.s_param) list ->
    ?content_id:string ->
    ?content_description:string ->
    ?content_location:string ->
    ?content_disposition:string * (string * Netmime_string.s_param) list ->
    Netmime.complex_mime_message list -> Netmime.complex_mime_message
  val create_address_list_tokens :
    ?in_charset:Netconversion.encoding ->
    ?out_charset:Netconversion.encoding ->
    (string * string) list -> Netmime_string.s_token list
  val create_text_tokens :
    ?in_charset:Netconversion.encoding ->
    ?out_charset:Netconversion.encoding ->
    string -> Netmime_string.s_token list
  val format_field_value : string -> Netmime_string.s_token list -> string
  val sendmail :
    ?mailer:string -> ?crlf:bool -> Netmime.complex_mime_message -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.TLS_PROVIDER.html0000644000175000017500000011003212731530354024412 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.TLS_PROVIDER sig
  type config
  type credentials
  type endpoint
  module Exc : TLS_EXCEPTIONS
  val error_message : string -> string
  type dh_params =
      [ `Generate of int | `PKCS3_DER of string | `PKCS3_PEM_file of string ]
  val create_config :
    ?algorithms:string ->
    ?dh_params:Netsys_crypto_types.TLS_PROVIDER.dh_params ->
    ?verify:(Netsys_crypto_types.TLS_PROVIDER.endpoint ->
             bool -> bool -> bool) ->
    peer_auth:[ `None | `Optional | `Required ] ->
    credentials:Netsys_crypto_types.TLS_PROVIDER.credentials ->
    unit -> Netsys_crypto_types.TLS_PROVIDER.config
  type crt_list = [ `DER of string list | `PEM_file of string ]
  type crl_list = [ `DER of string list | `PEM_file of string ]
  type private_key =
      [ `DSA of string
      | `EC of string
      | `PEM_file of string
      | `PKCS8 of string
      | `PKCS8_encrypted of string
      | `RSA of string ]
  val create_x509_credentials :
    ?system_trust:bool ->
    ?trust:Netsys_crypto_types.TLS_PROVIDER.crt_list list ->
    ?revoke:Netsys_crypto_types.TLS_PROVIDER.crl_list list ->
    ?keys:(Netsys_crypto_types.TLS_PROVIDER.crt_list *
           Netsys_crypto_types.TLS_PROVIDER.private_key * string option)
          list ->
    unit -> Netsys_crypto_types.TLS_PROVIDER.credentials
  val create_endpoint :
    role:[ `Client | `Server ] ->
    recv:(Netsys_types.memory -> int) ->
    send:(Netsys_types.memory -> int -> int) ->
    peer_name:string option ->
    Netsys_crypto_types.TLS_PROVIDER.config ->
    Netsys_crypto_types.TLS_PROVIDER.endpoint
  val stash_endpoint : Netsys_crypto_types.TLS_PROVIDER.endpoint -> exn
  val restore_endpoint :
    recv:(Netsys_types.memory -> int) ->
    send:(Netsys_types.memory -> int -> int) ->
    exn -> Netsys_crypto_types.TLS_PROVIDER.endpoint
  val resume_client :
    recv:(Netsys_types.memory -> int) ->
    send:(Netsys_types.memory -> int -> int) ->
    peer_name:string option ->
    Netsys_crypto_types.TLS_PROVIDER.config ->
    string -> Netsys_crypto_types.TLS_PROVIDER.endpoint
  type state =
      [ `Accepting
      | `Data_r
      | `Data_rs
      | `Data_rw
      | `Data_w
      | `End
      | `Handshake
      | `Refusing
      | `Start
      | `Switching ]
  val get_state :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Netsys_crypto_types.TLS_PROVIDER.state
  type raw_credentials = [ `Anonymous | `X509 of string ]
  val at_transport_eof : Netsys_crypto_types.TLS_PROVIDER.endpoint -> bool
  val hello : Netsys_crypto_types.TLS_PROVIDER.endpoint -> unit
  val bye :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Unix.shutdown_command -> unit
  val verify : Netsys_crypto_types.TLS_PROVIDER.endpoint -> unit
  val get_config :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Netsys_crypto_types.TLS_PROVIDER.config
  val get_endpoint_creds :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Netsys_crypto_types.TLS_PROVIDER.raw_credentials
  val get_peer_creds :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Netsys_crypto_types.TLS_PROVIDER.raw_credentials
  val get_peer_creds_list :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Netsys_crypto_types.TLS_PROVIDER.raw_credentials list
  val switch :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Netsys_crypto_types.TLS_PROVIDER.config -> unit
  val accept_switch :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Netsys_crypto_types.TLS_PROVIDER.config -> unit
  val refuse_switch : Netsys_crypto_types.TLS_PROVIDER.endpoint -> unit
  val send :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Netsys_types.memory -> int -> int
  val recv :
    Netsys_crypto_types.TLS_PROVIDER.endpoint -> Netsys_types.memory -> int
  val recv_will_not_block : Netsys_crypto_types.TLS_PROVIDER.endpoint -> bool
  val get_session_id : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
  val get_session_data : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
  val get_cipher_suite_type :
    Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
  val get_cipher_algo : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
  val get_kx_algo : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
  val get_mac_algo : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
  val get_compression_algo :
    Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
  val get_cert_type : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
  val get_protocol : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
  type server_name = [ `Domain of string ]
  val get_addressed_servers :
    Netsys_crypto_types.TLS_PROVIDER.endpoint ->
    Netsys_crypto_types.TLS_PROVIDER.server_name list
  val set_session_cache :
    store:(string -> string -> unit) ->
    remove:(string -> unit) ->
    retrieve:(string -> string) ->
    Netsys_crypto_types.TLS_PROVIDER.endpoint -> unit
  val implementation_name : string
  val implementation : unit -> exn
end
ocamlnet-4.1.2/doc/html-main/type_Netsys_crypto_types.html0000644000175000017500000016604112731530354022452 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types sig
  module type TLS_EXCEPTIONS =
    sig
      exception EAGAIN_RD
      exception EAGAIN_WR
      exception TLS_switch_request
      exception TLS_switch_response of bool
      exception TLS_error of string
      exception TLS_warning of string
    end
  module type TLS_PROVIDER =
    sig
      type config
      type credentials
      type endpoint
      module Exc : TLS_EXCEPTIONS
      val error_message : string -> string
      type dh_params =
          [ `Generate of int
          | `PKCS3_DER of string
          | `PKCS3_PEM_file of string ]
      val create_config :
        ?algorithms:string ->
        ?dh_params:Netsys_crypto_types.TLS_PROVIDER.dh_params ->
        ?verify:(Netsys_crypto_types.TLS_PROVIDER.endpoint ->
                 bool -> bool -> bool) ->
        peer_auth:[ `None | `Optional | `Required ] ->
        credentials:Netsys_crypto_types.TLS_PROVIDER.credentials ->
        unit -> Netsys_crypto_types.TLS_PROVIDER.config
      type crt_list = [ `DER of string list | `PEM_file of string ]
      type crl_list = [ `DER of string list | `PEM_file of string ]
      type private_key =
          [ `DSA of string
          | `EC of string
          | `PEM_file of string
          | `PKCS8 of string
          | `PKCS8_encrypted of string
          | `RSA of string ]
      val create_x509_credentials :
        ?system_trust:bool ->
        ?trust:Netsys_crypto_types.TLS_PROVIDER.crt_list list ->
        ?revoke:Netsys_crypto_types.TLS_PROVIDER.crl_list list ->
        ?keys:(Netsys_crypto_types.TLS_PROVIDER.crt_list *
               Netsys_crypto_types.TLS_PROVIDER.private_key * string option)
              list ->
        unit -> Netsys_crypto_types.TLS_PROVIDER.credentials
      val create_endpoint :
        role:[ `Client | `Server ] ->
        recv:(Netsys_types.memory -> int) ->
        send:(Netsys_types.memory -> int -> int) ->
        peer_name:string option ->
        Netsys_crypto_types.TLS_PROVIDER.config ->
        Netsys_crypto_types.TLS_PROVIDER.endpoint
      val stash_endpoint : Netsys_crypto_types.TLS_PROVIDER.endpoint -> exn
      val restore_endpoint :
        recv:(Netsys_types.memory -> int) ->
        send:(Netsys_types.memory -> int -> int) ->
        exn -> Netsys_crypto_types.TLS_PROVIDER.endpoint
      val resume_client :
        recv:(Netsys_types.memory -> int) ->
        send:(Netsys_types.memory -> int -> int) ->
        peer_name:string option ->
        Netsys_crypto_types.TLS_PROVIDER.config ->
        string -> Netsys_crypto_types.TLS_PROVIDER.endpoint
      type state =
          [ `Accepting
          | `Data_r
          | `Data_rs
          | `Data_rw
          | `Data_w
          | `End
          | `Handshake
          | `Refusing
          | `Start
          | `Switching ]
      val get_state :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_crypto_types.TLS_PROVIDER.state
      type raw_credentials = [ `Anonymous | `X509 of string ]
      val at_transport_eof :
        Netsys_crypto_types.TLS_PROVIDER.endpoint -> bool
      val hello : Netsys_crypto_types.TLS_PROVIDER.endpoint -> unit
      val bye :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Unix.shutdown_command -> unit
      val verify : Netsys_crypto_types.TLS_PROVIDER.endpoint -> unit
      val get_config :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_crypto_types.TLS_PROVIDER.config
      val get_endpoint_creds :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_crypto_types.TLS_PROVIDER.raw_credentials
      val get_peer_creds :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_crypto_types.TLS_PROVIDER.raw_credentials
      val get_peer_creds_list :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_crypto_types.TLS_PROVIDER.raw_credentials list
      val switch :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_crypto_types.TLS_PROVIDER.config -> unit
      val accept_switch :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_crypto_types.TLS_PROVIDER.config -> unit
      val refuse_switch : Netsys_crypto_types.TLS_PROVIDER.endpoint -> unit
      val send :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_types.memory -> int -> int
      val recv :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_types.memory -> int
      val recv_will_not_block :
        Netsys_crypto_types.TLS_PROVIDER.endpoint -> bool
      val get_session_id :
        Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
      val get_session_data :
        Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
      val get_cipher_suite_type :
        Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
      val get_cipher_algo :
        Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
      val get_kx_algo : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
      val get_mac_algo : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
      val get_compression_algo :
        Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
      val get_cert_type : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
      val get_protocol : Netsys_crypto_types.TLS_PROVIDER.endpoint -> string
      type server_name = [ `Domain of string ]
      val get_addressed_servers :
        Netsys_crypto_types.TLS_PROVIDER.endpoint ->
        Netsys_crypto_types.TLS_PROVIDER.server_name list
      val set_session_cache :
        store:(string -> string -> unit) ->
        remove:(string -> unit) ->
        retrieve:(string -> string) ->
        Netsys_crypto_types.TLS_PROVIDER.endpoint -> unit
      val implementation_name : string
      val implementation : unit -> exn
    end
  module type TLS_CONFIG =
    sig module TLS : TLS_PROVIDER val config : TLS.config end
  module type TLS_ENDPOINT =
    sig module TLS : TLS_PROVIDER val endpoint : TLS.endpoint end
  module type FILE_TLS_ENDPOINT =
    sig
      module TLS : TLS_PROVIDER
      val endpoint : TLS.endpoint
      val rd_file : Unix.file_descr
      val wr_file : Unix.file_descr
    end
  module type SYMMETRIC_CRYPTO =
    sig
      type scipher
      val ciphers : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher list
      val find :
        string * string -> Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher
      val name : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> string
      val mode : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> string
      val key_lengths :
        Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> (int * int) list
      val iv_lengths :
        Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> (int * int) list
      val block_constraint :
        Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> int
      val supports_aead :
        Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher -> bool
      type scipher_ctx
      val create :
        Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher ->
        string -> Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx
      val set_iv :
        Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx -> string -> unit
      val set_header :
        Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx -> string -> unit
      val encrypt :
        Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx ->
        Netsys_types.memory -> Netsys_types.memory -> unit
      val decrypt :
        Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx ->
        Netsys_types.memory -> Netsys_types.memory -> bool
      val mac : Netsys_crypto_types.SYMMETRIC_CRYPTO.scipher_ctx -> string
    end
  module type DIGESTS =
    sig
      type digest
      val digests : Netsys_crypto_types.DIGESTS.digest list
      val find : string -> Netsys_crypto_types.DIGESTS.digest
      val name : Netsys_crypto_types.DIGESTS.digest -> string
      val size : Netsys_crypto_types.DIGESTS.digest -> int
      val block_length : Netsys_crypto_types.DIGESTS.digest -> int
      type digest_ctx
      val create :
        Netsys_crypto_types.DIGESTS.digest ->
        Netsys_crypto_types.DIGESTS.digest_ctx
      val add :
        Netsys_crypto_types.DIGESTS.digest_ctx -> Netsys_types.memory -> unit
      val finish : Netsys_crypto_types.DIGESTS.digest_ctx -> string
    end
  module type PUBKEY_CRYPTO =
    sig
      type public_key
      type private_key
      type pin_callback
      type algorithm
      val supported_x509 : int array list
      val algorithm_x509 :
        int array ->
        string option -> Netsys_crypto_types.PUBKEY_CRYPTO.algorithm
      val import_public_key_x509 :
        string -> Netsys_crypto_types.PUBKEY_CRYPTO.public_key
      val import_public_key_uri :
        string -> Netsys_crypto_types.PUBKEY_CRYPTO.public_key
      val import_public_key_uri_with_pin :
        Netsys_crypto_types.PUBKEY_CRYPTO.pin_callback ->
        string -> Netsys_crypto_types.PUBKEY_CRYPTO.public_key
      type x509_private_key = string * string
      val import_private_key_x509 :
        Netsys_crypto_types.PUBKEY_CRYPTO.x509_private_key ->
        Netsys_crypto_types.PUBKEY_CRYPTO.private_key
      val import_private_key_uri :
        string -> Netsys_crypto_types.PUBKEY_CRYPTO.private_key
      val import_private_key_uri_with_pin :
        Netsys_crypto_types.PUBKEY_CRYPTO.pin_callback ->
        string -> Netsys_crypto_types.PUBKEY_CRYPTO.private_key
      val import_public_key_from_private :
        Netsys_crypto_types.PUBKEY_CRYPTO.private_key ->
        Netsys_crypto_types.PUBKEY_CRYPTO.public_key
      val simple_pin_callback :
        (unit -> string) -> Netsys_crypto_types.PUBKEY_CRYPTO.pin_callback
      val encrypt :
        Netsys_crypto_types.PUBKEY_CRYPTO.algorithm ->
        Netsys_crypto_types.PUBKEY_CRYPTO.public_key -> string -> string
      val decrypt :
        Netsys_crypto_types.PUBKEY_CRYPTO.algorithm ->
        Netsys_crypto_types.PUBKEY_CRYPTO.private_key -> string -> string
      val verify :
        Netsys_crypto_types.PUBKEY_CRYPTO.algorithm ->
        Netsys_crypto_types.PUBKEY_CRYPTO.public_key ->
        string -> string -> bool
      val sign :
        Netsys_crypto_types.PUBKEY_CRYPTO.algorithm ->
        Netsys_crypto_types.PUBKEY_CRYPTO.private_key -> string -> string
    end
  type tls_provider = (module Netsys_crypto_types.TLS_PROVIDER)
  type tls_config = (module Netsys_crypto_types.TLS_CONFIG)
  type tls_endpoint = (module Netsys_crypto_types.TLS_ENDPOINT)
  type file_tls_endpoint = (module Netsys_crypto_types.FILE_TLS_ENDPOINT)
  type symmetric_crypto = (module Netsys_crypto_types.SYMMETRIC_CRYPTO)
  type digests = (module Netsys_crypto_types.DIGESTS)
  type pubkey_crypto = (module Netsys_crypto_types.PUBKEY_CRYPTO)
end
ocamlnet-4.1.2/doc/html-main/Netsys_tmp.html0000644000175000017500000004360712731530354017447 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_tmp

Module Netsys_tmp

module Netsys_tmp: sig .. end
Temporary files

val tmp_directory : unit -> string
Return the directory for temporary files. This is used as global default for functions that need such a directory. It is initialized with a reasonable default (OS-dependent).
val tmp_prefix : string -> string
tmp_prefix p: Enhance the prefix for temporary files by appending some digits to p. It is not ensures that the prefix is unique, though.
val set_tmp_directory : string -> unit
Set the directory for temporary files
ocamlnet-4.1.2/doc/html-main/type_Netchannels_crypto.html0000644000175000017500000006522512731530354022205 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels_crypto sig
  class type tls_channel =
    object
      method close_in : unit -> unit
      method close_out : unit -> unit
      method flush : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method output : Bytes.t -> int -> int -> int
      method pos_in : int
      method pos_out : int
      method tls_endpoint : Netsys_crypto_types.tls_endpoint
    end
  class tls_layer :
    ?start_pos_in:int ->
    ?start_pos_out:int ->
    ?resume:string ->
    role:[ `Client | `Server ] ->
    rd:Netchannels.raw_in_channel ->
    wr:Netchannels.raw_out_channel ->
    peer_name:string option -> Netsys_crypto_types.tls_config -> tls_channel
  class tls_endpoint :
    ?start_pos_in:int ->
    ?start_pos_out:int ->
    ?resume:string ->
    role:[ `Client | `Server ] ->
    peer_name:string option ->
    Unix.file_descr -> Netsys_crypto_types.tls_config -> tls_channel
  class type crypto_out_filter =
    object
      method close_out : unit -> unit
      method flush : unit -> unit
      method mac : unit -> string
      method output : Bytes.t -> int -> int -> int
      method output_buffer : Buffer.t -> unit
      method output_byte : int -> unit
      method output_bytes : Bytes.t -> unit
      method output_channel : ?len:int -> Netchannels.in_obj_channel -> unit
      method output_char : char -> unit
      method output_string : string -> unit
      method pos_out : int
      method really_output : Bytes.t -> int -> int -> unit
      method really_output_string : string -> int -> int -> unit
      method supports_aead : bool
    end
  class type crypto_in_filter =
    object
      method close_in : unit -> unit
      method input : Bytes.t -> int -> int -> int
      method input_byte : unit -> int
      method input_char : unit -> char
      method input_line : unit -> string
      method mac : unit -> string
      method pos_in : int
      method really_input : Bytes.t -> int -> int -> unit
      method really_input_string : int -> string
      method supports_aead : bool
    end
  val encrypt_out :
    Netsys_ciphers.cipher_ctx ->
    Netchannels.out_obj_channel -> Netchannels_crypto.crypto_out_filter
  val encrypt_in :
    Netsys_ciphers.cipher_ctx ->
    Netchannels.in_obj_channel -> Netchannels_crypto.crypto_in_filter
  val decrypt_out :
    Netsys_ciphers.cipher_ctx ->
    Netchannels.out_obj_channel -> Netchannels_crypto.crypto_out_filter
  val decrypt_in :
    Netsys_ciphers.cipher_ctx ->
    Netchannels.in_obj_channel -> Netchannels_crypto.crypto_in_filter
end
ocamlnet-4.1.2/doc/html-main/Netsys_sem.Debug.html0000644000175000017500000004155512731530354020460 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_sem.Debug

Module Netsys_sem.Debug

module Debug: sig .. end

val enable : bool Pervasives.ref
ocamlnet-4.1.2/doc/html-main/type_Netchannels.input_descr.html0000644000175000017500000004132612731530354023117 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.input_descr ?blocking:bool ->
?start_pos_in:int ->
?fd_style:Netsys.fd_style -> Unix.file_descr -> Netchannels.raw_in_channel
ocamlnet-4.1.2/doc/html-main/Nethttp_client.options_call-c.html0000644000175000017500000004221512731530354023165 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.options_call

Class Nethttp_client.options_call

class options_call : http_call

ocamlnet-4.1.2/doc/html-main/type_Netcgi_modtpl.template.html0000644000175000017500000004364512731530354022747 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_modtpl.template ?filename:string ->
string ->
object
  method callback : string -> (string list -> string) -> unit
  method conditional : string -> bool -> unit
  method output : Netcgi.cgi -> unit
  method set : string -> string -> unit
  method source : string
  method table : string -> Netcgi_modtpl.table_row list -> unit
  method to_channel : Pervasives.out_channel -> unit
  method to_string : string
end
ocamlnet-4.1.2/doc/html-main/Netplex_admin.html0000644000175000017500000014245312731530354020070 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_admin

Netplex_admin


Netplex Administration Guide

Applications created with the Netplex framework all share the following configuration settings and allow some basic administration commands. This is only a common minimum - the applications typically define more than this.

Configuration

The Netplex config file has the following layout:

netplex {
  controller { <settings> };    (* only one controller section *)
  service { <settings> };       (* as many service sections as running services *)
  ...
  service { <settings> };
  (* The application can define further types of sections *)
}

Configuration: The controller section

This section configures the controller component. The task of the controller is to start the containers for the workload, and logging.

netplex {
  controller {
    socket_directory = "<path>";
    max_level = "<debuglevel>";
    logging { <settings> };    (* several logging destinations possible *)
    ...
    logging { <settings> };
  };
  ...
}

Settings:

  • socket_directory: The Netplex framework needs a directory where to create Unix domain sockets. These sockets are needed for communication between the started containers. If omitted, the directory defaults to /tmp/netplex-<id> (where the id part is derived from the file location of the configuration). It is not allowed that several running Netplex instances share these directories, and hence it is strongly recommended to change this default. If the path is not absolute, it is made absolute by prepending the path of the working directory at the time Netplex is started (usually the program start). Note that the paths of Unix domain sockets are limited to 107 bytes for historic reasons, so the socket_directory should not be put too deeply into the file hierarchy.
  • max_level: This can be set to globally limit the log level. Defaults to "debug", i.e. no maximum.
Log levels are (same as for syslog):
  • emerg
  • alert
  • crit
  • err
  • warning
  • notice
  • info
  • debug
Every logging section defines a logging destination. Log messages are written to all destinations that do not filter the messages out. There are several types of logging sections:

Logging to stderr

This type writes log messages to stderr:

netplex {
  controller {
    logging {
      type = "stderr";                        (* mandatory *)
      format = "<format string>";             (* optional *)
      component = "<name_of_component>";      (* optional *)
      subchannel = "<name_of_subchannel>";    (* optional *)
      max_level = "<max_level>";              (* optional *)
    };
    ...
  };
  ...
}

The settings format, component, subchannel, and max_level may also occur in the other types of logging definitions, and are explained below.

Logging to a file

This writes the log messages to a single file.

netplex {
  controller {
    logging {
      type = "file";                          (* mandatory *)
      file = "<path>";                        (* mandatory *)
      format = "<format string>";             (* optional *)
      component = "<name_of_component>";      (* optional *)
      subchannel = "<name_of_subchannel>";    (* optional *)
      max_level = "<max_level>";              (* optional *)
    };
    ...
  };
  ...
}

Settings:

  • file: The file to which the messages are appended. If not existing, the file is created. The file path must be absolute.
The settings format, component, subchannel, and max_level may also occur in the other types of logging definitions, and are explained below.

Logging to multiple files

This logging definition directs to create several files in a common directory.

netplex {
  controller {
    logging {
      type = "multi_file";                    (* mandatory *)
      directory = "<path>";                   (* mandatory *)
      format = "<format string>";             (* optional *)
      file { <settings> };
      ...
      file { <settings> };
    };
    ...
  };
  ...
}

The settings in the file section:

  file {
    file = "<name>";                        (* mandatory *)
    format = "<format string>";             (* optional *)
    component = "<name_of_component>";      (* optional *)
    subchannel = "<name_of_subchannel>";    (* optional *)
    max_level = "<max_level>";              (* optional *)
  };

Settings:

  • directory: The absolute path of the directory where to create the log files managed by the file subsections
  • file: The name of the file in this directory
The settings format, component, subchannel, and max_level may also occur in the other types of logging definitions, and are explained below. Note that a format setting in the file section overrides the definition in logging for the respective file.

Logging to syslog

The log messages are sent to the syslog device of the system (Unix only).

netplex {
  controller {
    logging {
      type = "syslog";                        (* mandatory *)
      identifier = "<identifier>";            (* optional *)
      facility = "<facility>";                (* optional *)
      format = "<format string>";             (* optional *)
      component = "<name_of_component>";      (* optional *)
      subchannel = "<name_of_subchannel>";    (* optional *)
      max_level = "<max_level>";              (* optional *)
    };
    ...
  };
  ...
}

Settings:

  • identifier: A string prefixing each message. Default: empty.
  • facility: The syslog facility name. Defaults to "default".
Facility names:
  • authpriv
  • cron
  • daemon
  • ftp
  • kern
  • local0 to local7
  • lpr
  • mail
  • news
  • syslog
  • user
  • uucp
  • default

Common settings in logging

format: This parameter defines how the log messages look like. This is a string containing variables in dollar notation ($name or ${name}). The following variable specifications are defined:

  • timestamp: the time in standard format
  • timestamp:<format> the time in custom format where <format> is a Netdate format string
  • timestamp:unix: the time in seconds since the epoch
  • component: the name of the component emitting the log message
  • subchannel: the name of the subchannel
  • level: the log level
  • message: the log message
The standard format string is
 [${timestamp}] [${component}] [${level}] ${message} 

component: This parameter filters messages by the component emitting the messages. The component name is here the Netplex service name, i.e. the name parameter in the service section (see below). The parameter may be set to the component name, or to a pattern matching component names. The wildcard * can be used in the pattern.

Default: *

subchannel: Netplex allows it to have several log channels per component. There is normally only the main log channel, but components can define additional channels. For example, a web server may have a separate log channel for access logging. This parameter filters messages by the subchannel identifier. Again it is possible to use the wildcard *.

The main log channel has the empty string as subchannel identifier, hence subchannel="" restricts the messages to the main channel.

Default: *

max_level: Restricts the log level of the printed messages. See above for possible levels.

Examples for logging definitions

1. Write everything to stderr:

  logging { type="stderr" }

2. Write a separate file for each log level:

  logging {
    type = "multi_file";
    directory = "/var/log/myapp";
    file {
      max_level = "debug";
      file = "all_debug.log";
    };
    file {
      max_level = "info";
      file = "all_info.log";
    };
    ... (* and so on ... *)
    file {
      max_level = "emerg";
      file = "all_emerg.log";
    };
  }

3. Write errors to syslog, but write access logs to a file:

  logging {
    type = "syslog";
    max_level = "err";
    subchannel = "";    (* i.e. only the main log channel goes here *)
  };
  logging {
    type = "file";
    file = "/var/log/myapp/access.log";
    subchannel = "access";
  }

Configuration: The service section

Each service section instructs Netplex to start containers for the service. If a service type is only defined by the application, but does not appear in the config file, no containers will be started!

A service section looks like:

netplex {
  service {
    name = "<name>";                 (* mandatory *)
    user = "<user>";                 (* optional *)
    group = "<group>";               (* optional *)
    startup_timeout = <float>;       (* optional *)
    conn_limit = <int>;              (* optional *)
    gc_when_idle = <bool>;           (* optional *)
    protocol { <settings> };         (* at least one *)
    ...
    protocol { <settings> };         (* at least one *)
    processor { <settings> };        (* mandatory *)
    workload_manager { <settings> }; (* mandatory *)
  };
  ...
}

The name of the service is a freely chosen identifier. It is used to reference the service, e.g. in log messages.

Each protocol section defines a set of sockets with common properties. The idea here is that a service may define several protocols for accessing it, e.g. an HTTP-based protocol and an RPC-based protocol. For each protocol there can then be several sockets.

The processor section is the connection to the application which must have defined the type of processor that is referenced here. The task of the processor is to accept incoming connections and to process them.

The workload_manager section defines how many containers (i.e. subprocesses or threads) are created for serving incoming connections.

Settings:

  • user: If the program is started as user root, it is possible to change the user for subprocesses. This parameter is the user name for all subprocesses created for this service. This is only possible when Netplex is running in the multi-processing mode, not in the multi-threading mode. Default: do not change the user.
  • group: Same for the group
  • startup_timeout: If a subprocess does not start up within this period of time, it is considered as dysfunctional, and killed again. This misbehavior usually occurs because the initialization function of the subprocess hangs. This setting has only an effect in multi-processing mode. Default: 60 seconds. A negative value turns this feature off.
  • conn_limit: If set, a container is automatically shut down if it has processed this number of connections. This is sometimes useful if there is a memory leak in the container, or memory is not reclaimed quickly enough. Of course, one can only fight memory problems in multi-processing mode this way. Default: no limit.
  • gc_when_idle: If true, the Ocaml garbage collector is run if a container is idle for one second.

The protocol subsection

It looks like:

netplex {
  service {
    protocol {
      name = "<protoname>";      (* mandatory *)
      lstn_backlog = <int>;      (* optional *)
      lstn_reuseaddr = <bool>;   (* optional *)
      so_keepalive = <bool>;     (* optional *)
      tcp_nodelay = <bool>;      (* optional *)
      local_chmod = "...";       (* optional *)
      local_chown = "...";       (* optional *)
      address { <settings> };    (* at least one *)
      ...
      address { <settings> };    (* at least one *)
    };
    ...
  };
  ...
}

Settings:

  • name: The name of the protocol. This is an arbitrary identifier. The name is passed to some hook functions.
  • lstn_backlog: The value of the backlog parameter of the listen system call. When a TCP connection is being accepted, the kernel does this first on its own, and passes the accepted connection to the application at the next opportunity (i.e. the accept system call). Because of this connections can queue up in the kernel, i.e. connections that are accepted but not yet passed to the application. This parameter is the maximum length of this queue. Note that there is usually also a kernel-defined maximum (e.g. 128 on Linux). If you get spurious EAGAIN errors on the client side this might be an indication to increase this parameter.
  • lstn_reuseaddr: Whether to allow immediate reuse of socket addresses. Defaults to true.
  • so_keepalive: Whether to enable the TCP keep-alive feature which is useful to detect unresponsive TCP connections (after a very long timeout only, though). Defaults to false.
  • tcp_nodelay: Whether to disable the Nagle algorithm for TCP. Normally, TCP packets are minimally delayed before they are sent to the network in the hope that the application makes more data available that could be put into the same packet. Especially on local networks it is often not important how many packets are really sent out, and by enabling this option latencies can be, sometimes drastically, reduced. Defaults to false.
  • local_chmod: For Unix Domain sockets, this sets the file permission bits. E.g. local_chmod = "0o700"
  • local_chown: For Unix Domain sockets, this sets the owner and group of the socket. E.g. local_chown = "owner:group". Both settings can also be given numerically.
Specifying socket addresses:
  • address { type="internet"; bind="<ip>:<port>" }: An IPv4 or IPv6 socket. The IP address can also given as host name which is looked up at Netplex startup. Use 0.0.0.0 as the IPv4 catch-all address. IPv6 addresses must be put into brackets. Use [:0] as the IPv6 catch-all address.
  • address { type="local"; path="<path>" }: This is a OS-dependent default IPC mechanism for local connections. On Unix, local means Unix Domain sockets. On Win32, local means the w32_pipe_file mechanism (see below). In path, the name of the Unix Domain socket or the file with the pipe name must be specified.
  • address { type="unixdomain"; path="<path>" }: Unix domain sockets. In path give the path.
  • address { type="socket_file"; path="<path>" }: An emulation of Unix Domain sockets: A server socket bound to 127.0.0.1 and an anonymous port is used instead. The port number is written to a file. The file must be given as path.
  • address { type="w32_pipe"; path="<path>" }: Win32 named pipes. The name of the pipe is given as path. This must be a name of the form "\\.\pipe\<name>". The pipe server is configured so that only clients on the same system can connect to it.
  • address { type="w32_pipe_file"; path="<path>" }: An emulation of Unix Domain sockets: A named pipe with an unpredictable random name is created instead. The name of this pipe is written to the file given by path.
  • address { type="container" }: This special address causes that a separate local socket is created for each started container. The name of the socket file is automatically chosen. The names of the socket files can be queried with Netplex_cenv.lookup_container_sockets. This type of socket is useful to control the load sent to each container directly.

The processor subsection

This section depends on the Netplex processor connected with it. At minimum, this section has only a parameter type that is the name of a defined Netplex processor type:

netplex {
  service {
    processor {
      type = "<type>";
      ... (* rest depends on the type *)
    };
    ...
  };
  ...
}

There are a number of processor types coming with Ocamlnet:

See these modules for how to configure the processors defined by them.

Configuration: The workload_manager section

The workload manager determines how many containers (processes or threads) are running for each service.

The constant workload manager

The constant workload manager starts a fixed number of containers. If containers are shut down or crash, new containers are automatically launched to replace the missing ones.

The config section looks like:

netplex {
  service {
    workload_manager {
      type = "constant";
      threads = <n>;
    }
  }
}

Note that the parameter threads is also interpreted in multi-processing mode (as number of processes).

Since Ocamlnet-3.5, there are two optional settings:

  • max_jobs_per_thread: This number can be set to the maximum number of connections a thread or process can be assigned simultaneously. By default there is no limit.
  • greedy_accepts: This is a boolean (values true or false). If this mode is turned on, processes accept new connections more aggressively. This may improve the performance for very high connect rates (e.g. for more than 1000 new connections per second). The downside is that the load is assigned to processes in a less balanced way.

The dynamic workload manager

The dynamic workload manager starts as many containers as needed to handle the current load. Initially, a certain minimum number is started. If it turns out that too many containers become busy, more containers are started until a maximum is reached. If too many containers become idle containers are shut down.

netplex {
  service {
    workload_manager {
      type = "dynamic";
      max_jobs_per_thread = <n>;            (* optional, default: 1 *)
      recommended_jobs_per_thread = <n>;    (* optional *)
      min_free_jobs_capacity = <n>;         (* mandatory *)
      max_free_jobs_capacity = <n>;         (* mandatory *)
      max_threads = <n>;                    (* mandatory *)
    }
  }
}

A thread is here a container, even in multi-processing mode. A job is a TCP connection processed by a container. It is possible that a container can process several jobs at the same time (but only a few service types support this, e.g. RPC servers), and the whole calculation is based on the job capacity, i.e. the number of jobs all containers can execute in parallel.

The workload manager adjusts the number of containers so that there is always free capacity for min_free_jobs_capacity, but the free capacity does not exceed max_free_jobs_capacity. Also, the number of containers is capped by max_threads.

As mentioned, in most cases a container can only run one job at a time (this is meant with max_jobs_per_thread=1). Then min_free_jobs_capacity is just the minimum number of idle containers, and max_free_jobs_capacity the maximum number.

If more than one job can be executed, set max_jobs_per_thread to a value bigger than one. The workload manager assigns the components then up to this number of TCP connections to process. A component is filled up with jobs until it is full before jobs are assigned to the next container.

The latter behavior can be modified by recommended_jobs_per_thread. This must be a number less than or equal to max_jobs_per_thread, and it means that the containers normally only get the recommended number of jobs until they are "full", and only for very high workloads this scheme is left, and even more jobs are assigned to the containers until the maximum is reached. A common configuration is to set recommended_jobs_per_thread=1, so that each container gets first only up to one job, and only if the maximum number of containers are running, additional jobs can be assigned.

There are also a few rarely used options for the dynamic workload manager:

  • greedy_accepts: This is a boolean (values true or false). If this mode is turned on, processes accept new connections more aggressively. This may improve the performance for very high connect rates (e.g. for more than 1000 new connections per second). The downside is that the load is assigned to processes in a less balanced way. Note that this mode only works for asynchronously implemented processors. (Since Ocamlnet-3.5.)

The netplex-admin command

Ocamlnet installs a little utility command netplex-admin that can be used to administer a running Netplex program.

$ netplex-admin -help
Usage: netplex-admin [ options ] [ admin_cmd arg ... ]
  -sockdir <dir>  Set the socket directory of the Netplex to administer
  -conf <file>  Get the socket directory from this config file
  -list   List available Netplex services
  -containers   List available Netplex services with container details
  -enable <name>  Enable service <name>
  -disable <name>  Disable service <name>
  -restart <name>  Restart service <name>
  -restart-all   Restart all services
  -shutdown   Shutdown the whole Netplex
  -reopen-logfiles   Reopen logfiles (if possible)
  -unlink   Unlink persistent kernel objects
  -receiver <pat>  Restrict receivers of admin messages to services matching <pat>

The utility talks to the running program, and needs the socket directory for this. Either specify it directly with the -sockdir argument, or indirectly via the config file (-conf).

The -list and -containers switches allow it to get some introspection into the running conglomerate of processes or threads. For -list the services and the socket addresses are printed. For -containers even more details are emitted, including the process IDs.

The -enable, -disable, and -restart commands allow it to manage the set of running services. A service can be disabled, which means that all containers are shut down. Note that this does not mean that incoming TCP connections are rejected. They are just not processed. If enabled again, the containers are started again for the service, and the processing of TCP connections is resumed (including the connections that were accepted during the downtime). Disabling a service is useful for temporarily stopping the service, e.g. because it would interfer with other admin tasks.

A restart means to disable and re-enable the service. It may be useful for cleanly reinitializing a service.

With -restart-all even all services are restarted that are running within the Netplex framework.

A -shutdown starts the shutdown sequence. The shutdown is announced to all containers, and in a second step, the containers are terminated. Finally, the master process is also stopped.

The command -reopen-logfiles is meaningful for all file-based logging definitions. The current set of files is closed, and reopened again. This is useful as post-action after log file rotation (see below).

-unlink: see below.

netplex-admin can also be used to send so-called admin messages to the containers. These messages have a name and optionally arguments:

$ netplex-admin ... name arg1 arg2 ...

Generally, the possible admin commands must be defined by the Netplex processors. A few commands are defined by default, though:

  • netplex.threadlist: Outputs information about threads and processes to the log file
  • netplex.logger.set_max_level <level>: Changes the maximum log level to the level passed in the argument
  • netplex.debug.enable <module>: Enables debug logging (as controlled by Netlog.Debug for the module named in the argument.
  • netplex.debug.disable <module>: Disables debug logging (as controlled by Netlog.Debug for the module named in the argument.
  • netplex.fd_table: prints the file descriptor tracking table to the log file
  • netplex.connections: prints information about current TCP connections to the log file
  • netplex.mem.major: triggers a major GC run
  • netplex.mem.compact: triggers a GC compaction
  • netplex.mem.pools: output information about Ocamlnet pools to the log file
  • netplex.mem.stats: output information about the memory managed by the Ocaml runtime to the log file

How to configure log file rotation

logrotate is a common utility to perform log file rotation. It can be easily used together with Netplex. The essential point is to run netplex-admin -reopen-logfiles as post action to the rotation. This stanza is an example how to configure the rotation in a logrotate config file:

/var/log/myapp/file.log
{
	weekly
        rotate 10
        missingok
        sharedscripts
        postrotate
                /some/path/bin/netplex-admin \
                        -sockdir /var/lib/myapp/sockdir \
                        -reopen-logfiles
        endscript
}

Deleting persistent kernel objects

For some functionality, Netplex programs allocate persistent kernel objects:

  • POSIX shared memory
  • POSIX named semaphores
  • Temporary regular files
These objects are effectively only used temporarily, but the available system interfaces only allow it to allocate them in a kernel-persisting manner. This means that the objects are not automatically released if the program ends, like most other system resources, but that they remain in memory after termination. If they were just left there behind, they would consume memory forever.

Of course, most Netplex programs are carefully written, and delete these objects if the program ends in a regular way. However, after a crash the programs normally don't have a chance to delete the objects. In order to allow administrative removal, many Netplex programs write the names of these objects into a special file netplex.pmanage residing in the socket directory. The netplex-admin command has a special mode in order to perform the deletion:

netplex-admin -sockdir /path/to/sockdir -unlink

Some operating systems have actually means for adminstering the kind of objects managed this way, but some have not. For example, Linux reflects the objects as normal files in the /dev/shm directory. As a counter example, there is no administration possibility in OS X.

(For programmers: The Netplex interface to access netplex.pmanage is Netplex_cenv.pmanage.)
ocamlnet-4.1.2/doc/html-main/type_Netxdr_mstring.mstring.html0000644000175000017500000004417612731530354023036 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netxdr_mstring.mstring object
  method as_bytes : Bytes.t * int
  method as_memory : Netsys_mem.memory * int
  method as_string : string * int
  method blit_to_bytes : int -> Bytes.t -> int -> int -> unit
  method blit_to_memory : int -> Netsys_mem.memory -> int -> int -> unit
  method blit_to_string : int -> Bytes.t -> int -> int -> unit
  method length : int
  method preferred : [ `Bytes | `Memory ]
end
ocamlnet-4.1.2/doc/html-main/Shell_sys.job_engine-c.html0000644000175000017500000004242512731530354021562 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell_sys.job_engine

Class Shell_sys.job_engine

class job_engine : Unixqueue.event_system -> job_instance -> [unit] job_handler_engine_type
The job_engine watches the job, and looks whether the processes are finished, and if so, it records the process statuses. Also, the engine takes care of pumping producer data into the job, and of collecting consumer data.

ocamlnet-4.1.2/doc/html-main/type_Nethttpd_engine.http_request_notification.html0000644000175000017500000004154412731530354026754 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_engine.http_request_notification object
  method environment : Nethttpd_engine.extended_async_environment
  method req_state : Nethttpd_engine.engine_req_state
  method schedule_finish : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.datagram_multiplex_controller.html0000644000175000017500000005263312731530354030127 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.datagram_multiplex_controller object
  method alive : bool
  method cancel_reading : unit -> unit
  method cancel_shutting_down : unit -> unit
  method cancel_writing : unit -> unit
  method event_system : Unixqueue.event_system
  method inactivate : unit -> unit
  method mem_supported : bool
  method read_eof : bool
  method reading : bool
  method received_from : Unix.sockaddr
  method send_to : Unix.sockaddr -> unit
  method shutting_down : bool
  method start_mem_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_mem_writing :
    when_done:(exn option -> int -> unit) ->
    Netsys_mem.memory -> int -> int -> unit
  method start_reading :
    ?peek:(unit -> unit) ->
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_shutting_down :
    ?linger:float -> when_done:(exn option -> unit) -> unit -> unit
  method start_writing :
    when_done:(exn option -> int -> unit) -> Bytes.t -> int -> int -> unit
  method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit
  method supports_half_open_connection : bool
  method tls_session : (string * string) option
  method tls_session_props : Nettls_support.tls_session_props option
  method tls_stashed_endpoint : unit -> exn
  method writing : bool
  method wrote_eof : bool
end
ocamlnet-4.1.2/doc/html-main/type_Netplex_types.workload_manager.html0000644000175000017500000004267112731530354024521 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.workload_manager object
  method adjust :
    Netplex_types.socket_service -> Netplex_types.socket_controller -> unit
  method capacity :
    Netplex_types.container_id ->
    Netplex_types.container_state -> Netplex_types.capacity
  method hello : Netplex_types.controller -> unit
  method shutdown : unit -> unit
end
ocamlnet-4.1.2/doc/html-main/Nethttpd_kernel.html0000644000175000017500000010661212731530354020430 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttpd_kernel

Module Nethttpd_kernel

module Nethttpd_kernel: sig .. end

The protocol kernel of the HTTP daemon

This module mainly defines the http_protocol class which implements the exchange of messages with a HTTP client. The request messages are represented as sequence of req_token values. The response is encapsulated in a separate http_response class. The contents of the response are represented as sequence of resp_token values.


type fatal_error = [ `Broken_pipe
| `Broken_pipe_ignore
| `Message_too_long
| `Server_error
| `TLS_error of string * string
| `Timeout
| `Unix_error of Unix.error ]
These are the serious protocol violations after that the daemon stops any further processing.

Note that `Timeout refers to a timeout in the middle of a request. `Broken_pipe_ignore is the "harmless" version of `Broken_pipe (see config_suppress_broken_pipe).

Long messages are fatal because it is suspected that they are denial of service attacks. The kernel generates `Message_too_long only for long headers, not for long bodies.

Fatal server errors can happen when exceptions are not properly handled. As last resort the HTTP daemon closes the connection without notifying the client.

`TLS_error means any error on the TLS level. The two strings identify the problem as for Netsys_tls.Error.

val string_of_fatal_error : fatal_error -> string
Convert error to a string, for logging
type bad_request_error = [ `Bad_header
| `Bad_header_field of string
| `Bad_request_line
| `Bad_trailer
| `Format_error of string
| `Protocol_not_supported
| `Request_line_too_long
| `Unexpected_eof ]
A bad request is a violation where the current request cannot be decoded, and it is not possible to accept further requests over the current connection.
val string_of_bad_request_error : bad_request_error -> string
Convert error to a string, for logging
val status_of_bad_request_error : bad_request_error -> Nethttp.http_status
Returns the best response code for the error
type data_chunk = Bytes.t * int * int 
A data_chunk is a substring of a string. The substring is described by the triple (s, pos, len) where s is the container, pos is the position where the substring begins, and len its length.
type status_line = int * string 
= (code, phrase)
type transfer_coding = [ `Chunked | `Identity ] 
type resp_token = [ `Resp_action of unit -> unit
| `Resp_body of data_chunk
| `Resp_end
| `Resp_header of Nethttp.http_header
| `Resp_info_line of status_line * Nethttp.http_header
| `Resp_status_line of status_line
| `Resp_trailer of Nethttp.http_trailer ]
The resp_token represents a textual part of the response to send:
  • `Resp_info_line is an informational status line (code=100..199). There can be several informational lines, and they can be accompanied with their own headers. Such lines are only sent to HTTP/1.1 clients.
  • `Resp_status_line is the final status line to send (code >= 200)
  • `Resp_header is the whole response header to send
  • `Resp_body is the next part of the response body to send.
  • `Resp_trailer is the whole response trailer to send (currently ignored)
  • `Resp_action is special because it does not directly represent a token to send. The argument is a function which is called when the token is the next token on the active event queue. The function is also called when the event queue is dropped because of an error (the state of the response object indicates this). The function must not raise exceptions except Unix_error, and it must not block.

val resp_100_continue : resp_token
The predefined token for the "100 Continue" response
type resp_state = [ `Active | `Dropped | `Error | `Inhibited | `Processed | `Queued ] 
The response state:
  • `Inhibited = it is not yet allowed to start the response
  • `Queued = the response waits on the queue for activation
  • `Active = the response is currently being transmitted
  • `Processed = the response has been completely sent
  • `Error = an error occurred during the transmission of this response
  • `Dropped = an earlier response forced to close the connection, and this response is dequeued

type front_token = [ `Resp_end | `Resp_wire_data of data_chunk ] 
Tokens generated by http_response:
  • `Resp_wire_data are data tokens.
  • `Resp_end indicates the end of the response.

exception Send_queue_empty
type announcement = [ `As of string | `Ignore | `Ocamlnet | `Ocamlnet_and of string ] 
See config
class type http_response = object .. end
Encapsultation of the HTTP response for a single request
class http_response_impl : ?close:bool -> ?suppress_body:bool -> int64 -> Nethttp.protocol -> announcement -> http_response
Exported for debugging and testing only
val send_static_response : http_response ->
Nethttp.http_status -> Nethttp.http_header option -> Bytes.t -> unit
Sends the string argument as response body, together with the given status and the header (optional). Response header fields are set as follows:
  • The Content-Length is set to the length of the string.
  • The Content-Type is set to "text/html" unless given by the header. If the header object is passed in, these modifications are done directly in this object as side effect.

val send_file_response : http_response ->
Nethttp.http_status ->
Nethttp.http_header option -> Unix.file_descr -> int64 -> unit
Sends the contents of a file as response body, together with the given status and the header (optional). The descriptor must be a file descriptor (that cannot block). The int64 number is the length of the body. Response header fields are set as follows:
  • The Content-Length is set to the length of the string.
  • The Content-Type is set to "text/html" unless given by the header.
Note that Content-Range is not set automatically, even if the file is only partially transferred.

If the header object is passed in, these modifications are done directly in this object as side effect.

The function does not send the file immediately, but rather sets the http_response object up that the next chunk of the file is added when the send queue becomes empty. This file will be closed when the transfer is done.

type request_line = Nethttp.http_method * Nethttp.protocol 
The method (including the URI), and the HTTP version
type req_token = [ `Bad_request_error of
bad_request_error * http_response
| `Eof
| `Fatal_error of fatal_error
| `Req_body of data_chunk
| `Req_end
| `Req_expect_100_continue
| `Req_header of
request_line * Nethttp.http_header *
http_response
| `Req_trailer of Nethttp.http_trailer
| `Timeout ]
A req_token represents a textual part of the received request:
  • `Req_header is the full received header. Together with the header, the corresponding http_response object is returned which must be used to transmit the response.
  • `Req_expect_100_continue is generated when the client expects that the server sends a "100 Continue" response (or a final status code) now. One should add `Resp_info_line resp_100_continue to the send queue if the header is acceptable, or otherwise generate an error response. In any case, the rest of the request must be read until `Req_end.
  • `Req_body is a part of the request body. The transfer-coding, if any, is already decoded.
  • `Req_trailer is the received trailer
  • `Req_end indicates the end of the request (the next request may begin immediately).
  • `Eof indicates the end of the stream
  • `Bad_request_error indicates that the request violated the HTTP protocol in a serious way and cannot be decoded. It is required to send a "400 Bad Request" response. The following token will be `Eof.
  • `Fatal_error indicates that the connection crashed. The following token will be `Eof.
  • `Timeout means that nothing has been received for a certain amount of time, and the protocol is in a state that the next request can begin. The following token will be `Eof.
Note that it is always allowed to send tokens to the client. The protocol implementation takes care that the response is transmitted at the right point in time.
val string_of_req_token : req_token -> string
For debugging
exception Recv_queue_empty
class type http_protocol_config = object .. end
Configuration values for the HTTP kernel
val default_http_protocol_config : http_protocol_config
Default config:
  • config_max_reqline_length = 32768
  • config_max_header_length = 65536
  • config_max_trailer_length = 32768
  • config_limit_pipeline_length = 5
  • config_limit_pipeline_size = 65536
  • config_announce_server = `Ocamlnet
  • config_suppress_broken_pipe = false
  • config_tls = None

class modify_http_protocol_config : ?config_max_reqline_length:int -> ?config_max_header_length:int -> ?config_max_trailer_length:int -> ?config_limit_pipeline_length:int -> ?config_limit_pipeline_size:int -> ?config_announce_server:announcement -> ?config_suppress_broken_pipe:bool -> ?config_tls:Netsys_crypto_types.tls_config option -> http_protocol_config -> http_protocol_config
Modifies the passed config object as specified by the optional arguments
class type http_protocol_hooks = object .. end
Allows it to set hooks for Nethttpd_kernel.http_protocol
class http_protocol : #http_protocol_config -> Unix.file_descr -> object .. end
The core event loop of the HTTP daemon
class lingering_close : ?preclose:unit -> unit -> Unix.file_descr -> object .. end
Closes a file descriptor using the "lingering close" algorithm.

Debugging


module Debug: sig .. end
ocamlnet-4.1.2/doc/html-main/type_Nethttp_client.head_call.html0000644000175000017500000004060612731530354023216 0ustar gerdgerd Ocamlnet 4 Reference Manual : Nethttp_client.head_call Nethttp_client.http_callocamlnet-4.1.2/doc/html-main/Netstream.html0000644000175000017500000005065012731530354017240 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netstream

Module Netstream

module Netstream: sig .. end
A netstream is an input channel that is read block by block. The fragment of the channel currently loaded into memory is called the current window of the netstream. The window can be thought as look-ahead buffer.

Picture:

 0                pos_in        pos_in + window_length            EOF
 +------------------+-------------------+--------------------------+
                    ====================
                     The current window
 

You can use a netstream like an in_obj_channel, and read characters and strings from the stream. The bytes come first from the look-ahead buffer, and if there are not enough bytes, they are loaded from the underlying channel. After every read operation it is tried to enlarge the window such that it contains at least one block.

If you want that the window becomes larger, you can call want (to enlarge the window to a certain size) or want_another_block (to load just another block from the underlying channel). Note that this affects only the current window and not the future size of the window.

Note Buffer_underrun: netstreams can cope with underruns of underlying channels. An underrun happens when it is not possible to ensure the minimum window size. However, it is possible that the window size sinks under the minimum, but the Buffer_underrun is deferred until the next call of an input method. Furthermore, there is a problem in the skip method which may only be partially executed, i.e. the method skips some bytes and then raises Buffer_underrun.


class type in_obj_stream = object .. end
An in_obj_stream extends in_obj_channel by look-ahead methods
class input_stream : ?len:int -> ?block_size:int -> Netchannels.in_obj_channel -> in_obj_stream
Make an in_obj_stream on top of an in_obj_channel.
class sub_stream : ?len:int -> ?delimiter:string -> in_obj_stream -> in_obj_stream
A sub stream is the part of the whole stream from the current position to an arbitrary other position that is determined by len and delimiter.
val print_in_obj_stream : Format.formatter -> in_obj_stream -> unit
A top-loop printer for streams
ocamlnet-4.1.2/doc/html-main/type_Unixqueue_select.sb_event_system.html0000644000175000017500000005261712731530354025103 0ustar gerdgerd Ocamlnet 4 Reference Manual : Unixqueue_select.sb_event_system object
  method add_abort_action :
    Unixqueue_util.group -> (Unixqueue_util.group -> exn -> unit) -> unit
  method add_close_action :
    Unixqueue_util.group ->
    Unix.file_descr * (Unix.file_descr -> unit) -> unit
  method add_event : Unixqueue_util.event -> unit
  method add_handler :
    Unixqueue_util.group ->
    (Unixqueue.event_system ->
     Unixqueue_util.event Equeue.t -> Unixqueue_util.event -> unit) ->
    unit
  method add_resource :
    Unixqueue_util.group -> Unixqueue_util.operation * float -> unit
  method add_weak_resource :
    Unixqueue_util.group -> Unixqueue_util.operation * float -> unit
  method clear : Unixqueue_util.group -> unit
  method exists_resource : Unixqueue_util.operation -> bool
  method is_running : bool
  method new_group : unit -> Unixqueue_util.group
  method new_wait_id : unit -> Unixqueue_util.wait_id
  method private queue_events :
    Unix.file_descr list * Unix.file_descr list * Unix.file_descr list ->
    bool
  method remove_resource :
    Unixqueue_util.group -> Unixqueue_util.operation -> unit
  method run : unit -> unit
  method private setup :
    unit ->
    Unix.file_descr list * Unix.file_descr list * Unix.file_descr list *
    float
  method private source : Unixqueue_util.event Equeue.t -> unit
  method when_blocking : (unit -> unit) -> unit
end
ocamlnet-4.1.2/doc/html-main/Netsys_crypto_types.SYMMETRIC_CRYPTO.html0000644000175000017500000006104312731530354024060 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netsys_crypto_types.SYMMETRIC_CRYPTO

Module type Netsys_crypto_types.SYMMETRIC_CRYPTO

module type SYMMETRIC_CRYPTO = sig .. end


Symmetric cryptographic ciphers.

Users should not call functions of the provider directly, but use Netsys_ciphers, or another higher-level layer.

type scipher 
Describes a cipher
val ciphers : scipher list
List of supported ciphers. OCamlnet implements a number of modes anyway, and it is normally only required to implement "ECB" here. If there is special hardware acceleration, though, it is an option to provide accelerated modes too (e.g. some CPUs support AES-GCM specially).
val find : string * string -> scipher
find (name,mode): Looks up a cipher by name and mode, or raises Not_found
val name : scipher -> string
Returns the name. This should follow the convention <uppercasestring>-<size>, e.g. "AES-128" or "TWOFISH-128". The size is normally the key size.
val mode : scipher -> string
Returns the mode. Modes are "ECB", "CBC", "OFB", "CTR", "STREAM", "GCM".

Note that the mode needs not to deal with padding (this is done on a higher level).

val key_lengths : scipher -> (int * int) list
Supported key lengths as pairs min,max. If there is a recommended key length, this should be the first.
val iv_lengths : scipher -> (int * int) list
Supported iv lengths as pairs min,max. If there is a recommended iv length, this should be the first.
val block_constraint : scipher -> int
The buffers used with encrypt/decrypt must have a length that is a multiple of this number. (In ECB mode, this is the block size.)
val supports_aead : scipher -> bool
Whether this cipher integrates authentication
type scipher_ctx 
A cipher context stores processing data while encrypting or decrypting data
val create : scipher ->
string -> scipher_ctx
create c key: create a new cipher context for key. If not set, the initialization vector is zero, and the header the empty string.
val set_iv : scipher_ctx -> string -> unit
set_iv cctx iv: Sets the initialization vector. This is only allowed before encrypting or decrypting data
val set_header : scipher_ctx -> string -> unit
set_header cctx data: Sets the additional header that is authenticated for AEAD schemes. The header must have been set before starting the encryption or decryption (otherwise it is assumed to be the empty string).

For non-AEAD schemes, the header is ignored for encryption, and must be empty for decryption.

val encrypt : scipher_ctx ->
Netsys_types.memory -> Netsys_types.memory -> unit
encrypt cctx inbuf outbuf: Encrypts the data in inbuf and writes the result into outbuf. Both buffers must have the same size. It is not allowed to pass the same buffer as inbuf and outbuf.

In order to encrypt long texts, it is allowed to call encrypt several times in sequence.

val decrypt : scipher_ctx ->
Netsys_types.memory -> Netsys_types.memory -> bool
decrypt cctx inbuf outbuf: Decrypts the data in inbuf and writes the result into outbuf. Both buffers must have the same size. It is not allowed to pass the same buffer as inbuf and outbuf.

The function returns true on success, and false if a problem is detected.

In order to decrypt long texts, it is allowed to call decrypt several times in sequence.

val mac : scipher_ctx -> string
Returns the MAC for AEAD ciphers. This is updated after encrypt/decrypt. This function fails for non-AEAD ciphers.
ocamlnet-4.1.2/doc/html-main/Netmcore_matrix.html0000644000175000017500000005605612731530354020444 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_matrix

Module Netmcore_matrix

module Netmcore_matrix: sig .. end
Shared 2-dimensional arrays (matrices)

type ('e, 'h) sarray2 
Arrays where the elements have type 'e and the header has type 'h
type ('e, 'h) sarray2_descr 
The marshallable descriptor of a shared matrix
val create : Netmcore.res_id ->
int -> 'e array array -> 'h -> ('e, 'h) sarray2
create pool_id n2 a h: Creates a matrix by deeply copying a normal array a and using the copy of h as header. In n2 one has to pass the second dimension.
val make : Netmcore.res_id -> int -> int -> 'e -> 'h -> ('e, 'h) sarray2
make pool_id n1 n2 x h: Creates a matrix of the passed number of elements (n1 * n2), copies the element x, and initializes each element of the new array with the single copy of x. The value h is copied and used as header.
val init : Netmcore.res_id ->
int -> int -> (int -> int -> 'e) -> 'h -> ('e, 'h) sarray2
init pool_id n1 n2 f h: Creates a matrix of the passed number of elements (n1 * n2), and for getting the element at position k the function f k is run, and the copy of the result is written to the position. The header is set to the copy of h.
val set : ('e, 'a) sarray2 -> int -> int -> 'e -> unit
set sa k1 k2 x: Sets the (k1,k2)-th element of the matrix sa to a deep copy of x.
val get_ro : ('e, 'a) sarray2 -> int -> int -> 'e
get_ro sa k1 k2: Gets the (k1,k2)-th element of the matrix sa. Note that there is no guarantee that this value still exists if it is returned, and a parallely running set changes this element. If such values are accessed the program may crash!
val get_p : ('e, 'b) sarray2 -> int -> int -> ('e -> 'a) -> 'a
get_p sa k1 k2 f: Gets the (k1,k2)-th element of the matrix sa and call f with this element, and returns the result of f. During the execution of f the requested element cannot be garbage collected.
val get_c : ('e, 'a) sarray2 -> int -> int -> 'e
get_c sa k1 k2: Gets a copy of the (k1,k2)-th element of the matrix sæ
val dim : ('a, 'b) sarray2 -> int * int
Returns the dimenstions
val header : ('a, 'h) sarray2 -> 'h
Returns the header
val deref : ('e, 'a) sarray2 -> 'e array array
Returns the raw array in shared memory for unprotected access
val heap : ('a, 'b) sarray2 -> Obj.t Netmcore_heap.heap
Return the backing heap structure
val descr_of_sarray2 : ('e, 'h) sarray2 -> ('e, 'h) sarray2_descr
Returns the descriptor
val sarray2_of_descr : Netmcore.res_id ->
('e, 'h) sarray2_descr -> ('e, 'h) sarray2
Look up the matrix for this descriptor
ocamlnet-4.1.2/doc/html-main/Uq_datagram.datagram_socket_provider-c.html0000644000175000017500000004347312731530354025011 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_datagram.datagram_socket_provider

Class type Uq_datagram.datagram_socket_provider

class type datagram_socket_provider = object .. end
This is a factory for wrapped_datagram_socket objects.

method create_datagram_socket : datagram_type ->
Unixqueue.event_system ->
wrapped_datagram_socket Uq_engines.engine
Creates an engine that creates a wrapped_datagram_socket object and that sets up any further resources the objects needs.
ocamlnet-4.1.2/doc/html-main/type_Netplex_sharedvar.VV_TYPE.html0000644000175000017500000004353712731530354023216 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_sharedvar.VV_TYPE sig
  type t
  type var
  val access : string -> Netplex_sharedvar.VV_TYPE.var
  val get : Netplex_sharedvar.VV_TYPE.var -> Netplex_sharedvar.VV_TYPE.t
  val set :
    Netplex_sharedvar.VV_TYPE.var -> Netplex_sharedvar.VV_TYPE.t -> unit
  val version : Netplex_sharedvar.VV_TYPE.var -> int64
  val update : Netplex_sharedvar.VV_TYPE.var -> bool
end
ocamlnet-4.1.2/doc/html-main/type_Netmcore_mempool.html0000644000175000017500000004643712731530354021653 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_mempool sig
  exception Out_of_pool_memory
  val create_mempool : ?alloc_really:bool -> int -> Netmcore.res_id
  val alloc_mem : Netmcore.res_id -> int -> Netsys_mem.memory
  val size_mem : Netmcore.res_id -> Netsys_mem.memory -> int
  val size_mem_at_addr : Netmcore.res_id -> nativeint -> int
  val free_mem : Netmcore.res_id -> Netsys_mem.memory -> unit
  val stats : Netmcore.res_id -> int * int * int
  val debug_info : Netmcore.res_id -> string
  val shm_name : Netmcore.res_id -> string
  val sem_container : Netmcore.res_id -> Netsys_sem.container
  val unlink_mempool : Netmcore.res_id -> unit
  module Debug :
    sig
      val enable : bool Pervasives.ref
      val enable_alloc : bool Pervasives.ref
    end
end
ocamlnet-4.1.2/doc/html-main/Shell.html0000644000175000017500000013755112731530354016353 0ustar gerdgerd Ocamlnet 4 Reference Manual : Shell

Module Shell

module Shell: sig .. end
Calls external programs, creates pipelines, etc. (simplified interface)


Signal handlers: When you call the function call, signal handlers are automatically installed by Shell_sys.install_job_handlers, unless this installation has already been performed. You can configure these handlers by Shell_sys.configure_job_handlers. The handlers remain in effect even after call returns.

Note that this has a global side effect on the whole process, because there is only one set of signal handlers.

Signal handlers: When you call the function call, signal handlers are automatically installed by Shell_sys.install_job_handlers, unless this installation has already been performed. You can configure these handlers by Shell_sys.configure_job_handlers. The handlers remain in effect even after call returns.

Note that this has a global side effect on the whole process, because there is only one set of signal handlers.

Calling commands and pipelines



Signal handlers: When you call the function call, signal handlers are automatically installed by Shell_sys.install_job_handlers, unless this installation has already been performed. You can configure these handlers by Shell_sys.configure_job_handlers. The handlers remain in effect even after call returns.

Note that this has a global side effect on the whole process, because there is only one set of signal handlers.

Calling commands and pipelines



The following functions are simplified versions of the Shell_sys.job abstraction.
exception Subprocess_error of (string * Unix.process_status) list
The string contains the called commands in a readable representation. The list enumerates the return codes of the processes that have been started for the commands.
type producer 
A producer generates data sent to a called process
type consumer 
A consumer receives data from a called process
type assignment 
An assignment redirects file descriptors while calling a process
val command : ?cmdname:string ->
?arguments:string array ->
?chdir:string ->
?environment:Shell_sys.environment ->
?descriptors:Unix.file_descr list ->
?assignments:assignment list -> string -> Shell_sys.command
Creates a command descriptor, to be used in call. The anonymous string argument is the name of the executable to invoke. If the name contains a '/', it is simply interpreted as the filename of the executable. Otherwise the command is searched in the current PATH.


cmdname : The name of the command passed in argv[0]. By default, this argument is derived from the name of the executable.
arguments : The arguments of the command (starting with the first real argument, skipping cmdname). By default [] .
chdir : Before the command is executed it is changed to this directory.
environment : The environment of the command. By default, the current environment
descriptors : The list of file descriptors to share with the current process; all other file descriptors will be closed. By default, [stdin; stdout; stderr] .
assignments : The list of descriptor assignments. The assignments are applied one after the other. By default empty.
val cmd : ?cmdname:string ->
?chdir:string ->
?environment:Shell_sys.environment ->
?descriptors:Unix.file_descr list ->
?assignments:assignment list ->
string -> string list -> Shell_sys.command
The same as command but with a slightly different interface: Use
 cmd "ls" [ "/dir/file" ] 
instead of
 command ~arguments:[|"/dir/file"|] "ls" 

The named arguments have the same meanings as in command.

val call : ?ignore_error_code:bool ->
?mode:Shell_sys.group_mode ->
?stdin:producer ->
?stdout:consumer ->
?stderr:consumer -> Shell_sys.command list -> unit
Starts the pipeline represented by the list of commands; i.e. if [c1;c2;...;cN] is passed, this corresponds to the pipeline c1 | c2 | ... | cN (in shell notation).

The function returns normally if all processes can be started and terminate regularly with exit code 0. If a process terminates with some other exit code, and ignore_error_code is set, the function returns normally, too. The latter does not apply if a process terminates because of a signal (which triggers always the exception Subprocess_error).

If a process terminates with an exit code other than 0 and ignore_error_code is not set (the default), or if a process is terminated because of a signal, the exception Subprocess_error will be raised. For every command the process result is included in the exception argument.

If a process cannot be started (e.g. because of insufficient resources), the function will try to shut down the already running part of the pipeline by sending SIGTERM to these processes. It is not checked whether the processes actually terminate (no "wait" for them); an appropriate exception will be raised. In the case that it is not even possible to perform these cleanup actions, the exception Shell_sys.Fatal_error will be raised.

When the function raises an exception other than Subprocess_error, a serious error condition has happened, and it is recommended to exit the program as soon as possible.


ignore_error_code : If true, exit codes other than 0 of the subprocesses are ignored. This does not apply to signals, however. By default false.
mode : See Shell_sys.run_job for a detailed description of this parameter. By default Same_as_caller.
stdin : If present, the first process of the pipeline reads input data from this procucer. By default, there is no such producer.
stdout : If present, the last process of the pipeline writes output data to this consumer. By default, there is no such consumer.
stderr : If present, all processes of the pipeline write their error messages to this consumer. By default, there is no such consumer.
val setup_job : ?stdin:producer ->
?stdout:consumer ->
?stderr:consumer ->
Shell_sys.command list -> Shell_sys.job * Unix.file_descr list
Creates a job like call, but does not execute it. In addition to the job, the file descriptors are returned that must be closed when the job is done.
val postprocess_job : ?ignore_error_code:bool -> Shell_sys.job_instance -> unit
Looks at the error codes of the job, and raises Subprocess_error when there is an error that cannot be ignored. As error conditions are considered non-zero exit codes of any called processes, or signals terminating any of the called processes.


ignore_error_code : If true, exit codes other than 0 of the subprocesses are ignored. This does not apply to signals, however. By default false.
val assign : src:Unix.file_descr -> target:Unix.file_descr -> assignment
Arranges a redirection such that writing to src or reading from src will actually write to target or read from target (i.e., the target descriptor is duplicated and replaces the src descriptor just before the process is launched.)

Note that assignments work only if the descriptors are shared with the called process, so they must also be contained in the descriptors list of command or cmd. Furthermore, the close-on-exec flag must not be set.

val (>&) : Unix.file_descr -> Unix.file_descr -> assignment
Same as assign, but infix notation. For example, stdout >& stderr creates an assignment such that all output to stdout is redirected to stderr.

f >& g is the same as assign ~src:f target:g. It should be used for output assignments (as in the Bourne shell).

val (<&) : Unix.file_descr -> Unix.file_descr -> assignment
Same as assign, but infix notation. For example, stdin <& f creates an assignment such that the called process reads from the open file descriptor f.

f <& g is the same as assign ~src:f target:g. It should be used for input assignments (as in the Bourne shell).

val assigned_pair : assignment -> Unix.file_descr * Unix.file_descr
Returns the target and the source of the assignment as pair of descriptors (target,src).
val stdin : Unix.file_descr
val stdout : Unix.file_descr
val stderr : Unix.file_descr
The standard descriptors; defined here for convenience.
val from_string : ?pos:int -> ?len:int -> ?epipe:(unit -> unit) -> string -> producer
Creates a producer taking the data from a string s. After these data are sent, the pipeline is closed.


pos : The position in s where the data slice to transfer begins. By default 0.
len : The length of the data slice to transfer. By default, all bytes from the start position pos to the end of the string are taken.
epipe : This function is called when the pipeline breaks (EPIPE). Default: the empty function. EPIPE exceptions are always caught, and implicitly handled by closing the pipeline.
val from_stream : ?epipe:(unit -> unit) -> string Stream.t -> producer
Creates a producer taking the data from a stream of strings. After the data are sent, the pipeline is closed.


epipe : This function is called when the pipeline breaks (EPIPE). Default: the empty function. EPIPE exceptions are always caught, and implicitly handled by closing the pipeline.
val from_function : producer:(Unix.file_descr -> bool) -> unit -> producer
Creates a producer taking the data from a function. See Shell_sys.add_producer for the meaning of the producer function.
val from_file : string -> producer
Creates a producer taking the data from the file whose name is passed to this function.
val from_fd : Unix.file_descr -> producer
Creates a producer taking the data from the file descriptor passed to this function.
val from_dev_null : producer
A producer taking the data from /dev/null.
val to_buffer : Buffer.t -> consumer
Creates a consumer writing the data into the passed buffer.
val to_function : consumer:(Unix.file_descr -> bool) -> unit -> consumer
Creates a consumer writing the data by calling a function. See Shell_sys.add_consumer for the meaning of the consumer function.
val to_file : ?append:bool -> string -> consumer
Creates a consumer writing the data into the file whose name is passed to this function. Unless append is given, the file is truncated and overwritten. If append is true, the data are appended to the file. By default, append is false.
val to_fd : Unix.file_descr -> consumer
Creates a consumer redirecting the data to the file descriptor
val to_dev_null : consumer
A consumer redirecting the data to /dev/null.

Examples

The following examples show toploop sessions using Shell.

Examples

The following examples show toploop sessions using Shell.

Invoking simple commands

Call the command "ls" without redirection:

 # call [ command "ls" ];;
 IDEAS       s1.ml~      shell.mli~      shell_sys.ml~  unix_exts.ml
 META        shell.a     shell.ml~       shell_sys.o    unix_exts.mli
 Makefile    shell.cma   shell_sys.cmi   t              unix_exts.mli~
 Makefile~   shell.cmi   shell_sys.cmo   testjob        unix_exts.ml~
 depend      shell.cmo   shell_sys.cmx   testjob~       unix_exts.o
 libshell.a  shell.cmxa  shell_sys.ml    unix_exts.cmi  unix_exts_c.c
 log         shell.ml    shell_sys.mli   unix_exts.cmo  unix_exts_c.c~
 s1.ml       shell.mli   shell_sys.mli~  unix_exts.cmx  unix_exts_c.o
 \- : unit = ()
 

Redirecting stdout to a buffer

The output of "ls" is collected in the buffer b:

 # let b = Buffer.create 10;;
 val b : Buffer.t = <abstr>
 # call ~stdout:(to_buffer b) [ command "ls" ];;
 \- : unit = ()
 # Buffer.contents b;;
 \- : string =
 "IDEAS\nMETA\nMakefile\nMakefile~\ndepend\n..."
 

Subprocess errors are caught and propagated to the caller

Because "/a" does not exist, "ls" will fail. The command writes the message to stderr (not redirected here), and returns with an exit code of 1, triggering an exception:

 # call [ command ~arguments:[| "/a" |] "ls" ];;
 /bin/ls: /a: No such file or directory
 Uncaught exception: Shell.Subprocess_error ["/bin/ls", Unix.WEXITED 1].
 

Redirecting stderr, too

Here, the message written to stderr is collected in b:

 # Buffer.clear b;;
 \- : unit = ()
 # call ~stderr:(to_buffer b) [ command ~arguments:[| "/a" |] "ls" ];;
 Uncaught exception: Shell.Subprocess_error ["/bin/ls", Unix.WEXITED 1].
 # Buffer.contents b;;
 \- : string = "/bin/ls: /a: No such file or directory\n"
 

Pipelines

Here, the output of "cat" becomes the input of "sort":

 # call [ command ~arguments:[|"META"|] "cat"; command "sort" ];;
 archive(byte) = "shell.cma"
 archive(native) = "shell.cmxa"
 description = "Unix shell functions"
 linkopts = "-cclib -lshell"
 requires = "unix str"
 version = "0.0"
 \- : unit = ()
 

Combining pipelines and redirections

The same, but the output of "sort" is collected in the buffer b:

 # Buffer.clear b;;
 \- : unit = ()
 # call ~stdout:(to_buffer b) [ command ~arguments:[|"META"|] "cat"; command "sort" ];;
 \- : unit = ()
 # Buffer.contents b;;
 \- : string =
 "archive(byte) = \"shell.cma\"\narchive(native) = \"shell.cmxa\"\ndescription = \"Unix shell functions\"\nlinkopts = \"-cclib -lshell\"\nrequires = \"unix str\"\nversion = \"0.0\"\n"
 

Redirection from a string

The contents of the string s are written to the input of "sort":

 # let s = "f\na\nd\nc\n";;
 val s : string = "f\na\nd\nc\n"
 # call ~stdin:(from_string s) [ command "sort" ];;
 a
 c
 d
 f
 \- : unit = ()
 

Combined redirections

It is possible to have several redirections. Here, the string s is sorted by "sort", and the output is collected in the buffer b:

 # Buffer.clear b;;
 \- : unit = ()
 # call ~stdout:(to_buffer b) ~stdin:(from_string s) [ command "sort" ];;
 \- : unit = ()
 # Buffer.contents b;;
 \- : string = "a\nc\nd\nf\n"
 

Redirections combined with assignments

Here, the output and errors of "ls" are both collected in the buffer b:

 # Buffer.clear b;;
 \- : unit = ()
 # call ~stdout:(to_buffer b) 
        [ command 
            ~assignments:[ stderr >& stdout ] 
            ~arguments:[| "/a" |] 
            "ls" ];;
 Uncaught exception: Shell.Subprocess_error ["/bin/ls", Unix.WEXITED 1].
 # Buffer.contents b;;
 \- : string = "/bin/ls: /a: No such file or directory\n"
 

Final notes

Of course, all features can be combined arbitrarily.

Note that error reporting is better than in a traditional shell, because the exit codes of all started commands are returned. (Shells usually only return the exit code of the last command of a pipeline.)

For non-standard pipelines, you can also use the functions in Shell_sys. "call" is a simple concatenation of Shell_sys invocations.

Examples

The following examples show toploop sessions using Shell.

Invoking simple commands

Call the command "ls" without redirection:

 # call [ command "ls" ];;
 IDEAS       s1.ml~      shell.mli~      shell_sys.ml~  unix_exts.ml
 META        shell.a     shell.ml~       shell_sys.o    unix_exts.mli
 Makefile    shell.cma   shell_sys.cmi   t              unix_exts.mli~
 Makefile~   shell.cmi   shell_sys.cmo   testjob        unix_exts.ml~
 depend      shell.cmo   shell_sys.cmx   testjob~       unix_exts.o
 libshell.a  shell.cmxa  shell_sys.ml    unix_exts.cmi  unix_exts_c.c
 log         shell.ml    shell_sys.mli   unix_exts.cmo  unix_exts_c.c~
 s1.ml       shell.mli   shell_sys.mli~  unix_exts.cmx  unix_exts_c.o
 \- : unit = ()
 

Redirecting stdout to a buffer

The output of "ls" is collected in the buffer b:

 # let b = Buffer.create 10;;
 val b : Buffer.t = <abstr>
 # call ~stdout:(to_buffer b) [ command "ls" ];;
 \- : unit = ()
 # Buffer.contents b;;
 \- : string =
 "IDEAS\nMETA\nMakefile\nMakefile~\ndepend\n..."
 

Subprocess errors are caught and propagated to the caller

Because "/a" does not exist, "ls" will fail. The command writes the message to stderr (not redirected here), and returns with an exit code of 1, triggering an exception:

 # call [ command ~arguments:[| "/a" |] "ls" ];;
 /bin/ls: /a: No such file or directory
 Uncaught exception: Shell.Subprocess_error ["/bin/ls", Unix.WEXITED 1].
 

Redirecting stderr, too

Here, the message written to stderr is collected in b:

 # Buffer.clear b;;
 \- : unit = ()
 # call ~stderr:(to_buffer b) [ command ~arguments:[| "/a" |] "ls" ];;
 Uncaught exception: Shell.Subprocess_error ["/bin/ls", Unix.WEXITED 1].
 # Buffer.contents b;;
 \- : string = "/bin/ls: /a: No such file or directory\n"
 

Pipelines

Here, the output of "cat" becomes the input of "sort":

 # call [ command ~arguments:[|"META"|] "cat"; command "sort" ];;
 archive(byte) = "shell.cma"
 archive(native) = "shell.cmxa"
 description = "Unix shell functions"
 linkopts = "-cclib -lshell"
 requires = "unix str"
 version = "0.0"
 \- : unit = ()
 

Combining pipelines and redirections

The same, but the output of "sort" is collected in the buffer b:

 # Buffer.clear b;;
 \- : unit = ()
 # call ~stdout:(to_buffer b) [ command ~arguments:[|"META"|] "cat"; command "sort" ];;
 \- : unit = ()
 # Buffer.contents b;;
 \- : string =
 "archive(byte) = \"shell.cma\"\narchive(native) = \"shell.cmxa\"\ndescription = \"Unix shell functions\"\nlinkopts = \"-cclib -lshell\"\nrequires = \"unix str\"\nversion = \"0.0\"\n"
 

Redirection from a string

The contents of the string s are written to the input of "sort":

 # let s = "f\na\nd\nc\n";;
 val s : string = "f\na\nd\nc\n"
 # call ~stdin:(from_string s) [ command "sort" ];;
 a
 c
 d
 f
 \- : unit = ()
 

Combined redirections

It is possible to have several redirections. Here, the string s is sorted by "sort", and the output is collected in the buffer b:

 # Buffer.clear b;;
 \- : unit = ()
 # call ~stdout:(to_buffer b) ~stdin:(from_string s) [ command "sort" ];;
 \- : unit = ()
 # Buffer.contents b;;
 \- : string = "a\nc\nd\nf\n"
 

Redirections combined with assignments

Here, the output and errors of "ls" are both collected in the buffer b:

 # Buffer.clear b;;
 \- : unit = ()
 # call ~stdout:(to_buffer b) 
        [ command 
            ~assignments:[ stderr >& stdout ] 
            ~arguments:[| "/a" |] 
            "ls" ];;
 Uncaught exception: Shell.Subprocess_error ["/bin/ls", Unix.WEXITED 1].
 # Buffer.contents b;;
 \- : string = "/bin/ls: /a: No such file or directory\n"
 

Final notes

Of course, all features can be combined arbitrarily.

Note that error reporting is better than in a traditional shell, because the exit codes of all started commands are returned. (Shells usually only return the exit code of the last command of a pipeline.)

For non-standard pipelines, you can also use the functions in Shell_sys. "call" is a simple concatenation of Shell_sys invocations.
ocamlnet-4.1.2/doc/html-main/Netplex_log.generic_config-c.html0000644000175000017500000004311212731530354022731 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_log.generic_config

Class type Netplex_log.generic_config

class type generic_config = object .. end

method log_format : string
method log_component : string
method log_subchannel : string
method log_max_level : Netplex_types.level
ocamlnet-4.1.2/doc/html-main/Uq_libevent.Make.html0000644000175000017500000004433212731530354020427 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_libevent.Make

Functor Uq_libevent.Make

module Make: 
functor (L : LIBOEVENT) -> POLLSET
Instantiate this module. Just do

  let P = Make(Liboevent)
      

and then call P.create_pollset() to create a pollset object, or P.create_event_system() to create an event_system.

(N.B. This functor saves Ocamlnet from being directly dependent on Liboevent.)

Parameters:
L : LIBOEVENT

val create_pollset : unit -> Netsys_pollset.pollset
val create_event_system : unit -> Unixqueue.event_system
ocamlnet-4.1.2/doc/html-main/Uq_engines_compat.async_out_channel_engine-c.html0000644000175000017500000004311312731530354026172 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.async_out_channel_engine

Class type Uq_engines_compat.async_out_channel_engine

class type async_out_channel_engine = object .. end
Inherits
ocamlnet-4.1.2/doc/html-main/Netplex_types.logger-c.html0000644000175000017500000004511412731530354021636 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.logger

Class type Netplex_types.logger

class type logger = object .. end
A logger receives log messages

A logger receives log messages

method log_subch : component:string ->
subchannel:string -> level:level -> message:string -> unit
Receive a log message of level from component. The component string is the name of the socket service emitting the message. Optionally, one can specify a subchannel when a single component needs to write to several log files. For example, a subchannel of "access" could select the access log of a webserver. The main log file is selected by passing the empty string as subchannel.
method log : component:string -> level:level -> message:string -> unit
Same as log_subch when subchannel is set to the empty string. This means that the message is sent to the main log file of the component.
method reopen : unit -> unit
Reopen the log files
ocamlnet-4.1.2/doc/html-main/Rpc_util.html0000644000175000017500000004615412731530354017063 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_util

Module Rpc_util

module Rpc_util: sig .. end
Utility functions

type verbosity = [ `Name_abbrev_args | `Name_full_args | `Name_only ] 
How verbose the RPC ftrace is:
  • `Name_only: For each RPC call only the name is logged
  • `Name_abbrev_args: The name and the abbreviated argument list are logged
  • `Name_full_args: The name and the full argument list are logged

val string_of_request : verbosity -> Rpc_program.t -> string -> Netxdr.xdr_value -> string
Return the string representation of this call request
val string_of_response : verbosity -> Rpc_program.t -> string -> Netxdr.xdr_value -> string
Return the string representation of this call response
val string_of_value : Netxdr.xdr_type_term -> Netxdr.xdr_value -> string
Return a string representation of the value which must have the passed type
val hex_dump_m : Netsys_mem.memory -> int -> int -> string
val hex_dump_b : Bytes.t -> int -> int -> string
Format the contents as hex sequence
ocamlnet-4.1.2/doc/html-main/Netchannels.buffered_raw_out_channel-c.html0000644000175000017500000004346512731530354024777 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netchannels.buffered_raw_out_channel

Class Netchannels.buffered_raw_out_channel

class buffered_raw_out_channel : ?buffer_size:int -> ?pass_through:int -> raw_out_channel -> raw_out_channel
This class adds a buffer to the underlying raw_out_channel.


buffer_size : The size of the buffer, by default 4096.
pass_through : If the write request has at least this size, and the buffer is currently empty, the buffer will be bypassed. Defaults to max_int, i.e. it is off.

ocamlnet-4.1.2/doc/html-main/type_Netencoding.Q.html0000644000175000017500000004506712731530354021001 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Q sig
  val encode : ?pos:int -> ?len:int -> string -> string
  val encode_tstring :
    ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
  val encode_poly :
    ?pos:int -> ?len:int -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
  val decode : ?pos:int -> ?len:int -> string -> string
  val decode_tstring :
    ?pos:int -> ?len:int -> Netsys_types.tstring -> Bytes.t
  val decode_poly :
    ?pos:int -> ?len:int -> 'Netstring_tstring.tstring_ops -> '-> Bytes.t
end
ocamlnet-4.1.2/doc/html-main/Netencoding.Base64.html0000644000175000017500000005360112731530354020555 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netencoding.Base64

Module Netencoding.Base64

module Base64: sig .. end


Base64 encoding as described in RFC 2045
val encode : ?pos:int ->
?len:int ->
?linelength:int ->
?crlf:bool -> ?plus:char -> ?slash:char -> string -> string
Compute the "base 64" encoding of the given string argument. Note that the result is a string that only contains the characters a-z, A-Z, 0-9, +, /, =, and optionally spaces, CR and LF characters.

If pos and/or len are passed, only the substring starting at pos (default: 0) with length len (default: rest of the string) is encoded.

The result is divided up into lines not longer than linelength (without counting the line separator); default: do not divide lines. If linelength is smaller than 4, no line division is performed. If linelength is not divisible by 4, the produced lines are a bit shorter than linelength.

If crlf (default: false) the lines are ended by CRLF; otherwise they are only ended by LF. (You need the crlf option to produce correct MIME messages.)

By default, the 63rd character of the alphabet is '+', and the 64th character is '/'. By passing plus and slash you can choose different characters.

val encode_tstring : ?pos:int ->
?len:int ->
?linelength:int ->
?crlf:bool -> ?plus:char -> ?slash:char -> Netsys_types.tstring -> Bytes.t
Same for tagged string inputs. The result are always bytes, though
val encode_poly : ?pos:int ->
?len:int ->
?linelength:int ->
?crlf:bool ->
?plus:char ->
?slash:char -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t
Polymorphic version
val decode : ?pos:int ->
?len:int ->
?accept_spaces:bool -> ?plus:char -> ?slash:char -> string -> string
Decodes the given string argument.

If pos and/or len are passed, only the substring starting at pos (default: 0) with length len (default: rest of the string) is decoded.

If accept_spaces (default: false) is set, the function ignores white space contained in the string to decode (otherwise the function fails if it finds white space). Furthermore, the character '>' is considered as "space", too (so you don't have trouble with mbox mailboxes that accidentally quote "From").

By default, the 63rd character of the alphabet is '+', and the 64th character is '/'. By passing plus and slash you can choose different characters.

val decode_tstring : ?pos:int ->
?len:int ->
?accept_spaces:bool ->
?plus:char -> ?slash:char -> Netsys_types.tstring -> Bytes.t
Same for tagged string inputs. The result are always bytes, though
val decode_poly : ?pos:int ->
?len:int ->
?accept_spaces:bool ->
?plus:char ->
?slash:char -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t
Polymorphic version
class encoding_pipe : ?linelength:int -> ?crlf:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipe
This pipe encodes the data written into the pipe.
class decoding_pipe : ?accept_spaces:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipe
This pipe decodes the data written into the pipe.
ocamlnet-4.1.2/doc/html-main/type_Netplex_mbox.MBOX.html0000644000175000017500000004254112731530354021547 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_mbox.MBOX sig
  type t
  type mbox
  val create : string -> Netplex_mbox.MBOX.mbox
  val send : Netplex_mbox.MBOX.mbox -> Netplex_mbox.MBOX.t -> unit
  val receive : Netplex_mbox.MBOX.mbox -> Netplex_mbox.MBOX.t
end
ocamlnet-4.1.2/doc/html-main/type_Uq_engines_compat.prioritizer.html0000644000175000017500000004104612731530354024357 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines_compat.prioritizer Unixqueue.event_system -> ['a] Uq_engines_compat.prioritizer_tocamlnet-4.1.2/doc/html-main/type_Netconversion.conversion_pipe.html0000644000175000017500000004143012731530354024370 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netconversion.conversion_pipe ?subst:(int -> string) ->
in_enc:Netconversion.encoding ->
out_enc:Netconversion.encoding -> unit -> Netchannels.io_obj_channel
ocamlnet-4.1.2/doc/html-main/Netcgi_fcgi.cgi-c.html0000644000175000017500000004573512731530354020470 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netcgi_fcgi.cgi

Class type Netcgi_fcgi.cgi

class type cgi = object .. end
The usual Netcgi.cgi class with FCGI specific methods.
Inherits
method role : [ `Authorizer | `Filter | `Responder ]
A FastCGI application can fulfill each of the following three roles:

  • `Responder: This is the usual role. In this case the application is expected to act like a CGI program: It receives all the information associated with an HTTP request and generates an HTTP response.
  • `Authorizer: An Authorizer FastCGI application receives all the information associated with an HTTP request and generates an authorized/unauthorized decision.
  • `Filter: A Filter FastCGI application receives all the information associated with an HTTP request, plus an extra stream of data from a file stored on the Web server, and generates a "filtered" version of the data stream as an HTTP response.

method data : Netchannels.in_obj_channel
This the the channel on which the filter data is available. All methods of the object raise Netchannels.Closed_channel if the role is not `Filter.
method data_length : int
How many bytes of the data are available.
method data_mtime : float
The data last modification time, expressed as an integer number of seconds since the epoch (January 1, 1970 UTC).
ocamlnet-4.1.2/doc/html-main/type_Netmcore_tut.html0000644000175000017500000004061512731530354021007 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_tut sig  endocamlnet-4.1.2/doc/html-main/type_Equeue.html0000644000175000017500000005000312731530354017560 0ustar gerdgerd Ocamlnet 4 Reference Manual : Equeue sig
  type 'a t
  exception Reject
  exception Terminate
  exception Out_of_handlers
  val create :
    ?string_of_event:('-> string) -> ('Equeue.t -> unit) -> 'Equeue.t
  val add_event : 'Equeue.t -> '-> unit
  val add_handler : 'Equeue.t -> ('Equeue.t -> '-> unit) -> unit
  val run : 'Equeue.t -> unit
  val is_running : 'Equeue.t -> bool
  module Debug :
    sig
      type debug_target = [ `Any | `Process of int | `Thread of int ]
      val enable : bool Pervasives.ref
      val set_debug_mode : bool -> unit
      val set_debug_target : Equeue.Debug.debug_target -> unit
      val test_debug_target : Equeue.Debug.debug_target -> bool
    end
end
ocamlnet-4.1.2/doc/html-main/type_Rpc_auth_gssapi.Debug.html0000644000175000017500000004101012731530354022465 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_auth_gssapi.Debug sig val enable : bool Pervasives.ref endocamlnet-4.1.2/doc/html-main/type_Equeue_howto.html0000644000175000017500000004061512731530354021010 0ustar gerdgerd Ocamlnet 4 Reference Manual : Equeue_howto sig  endocamlnet-4.1.2/doc/html-main/Uq_lwt.html0000644000175000017500000004334012731530354016547 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_lwt

Module Uq_lwt

module Uq_lwt: sig .. end
Compatibility with Lwt


Lwt is another library for event-driven programming. Here are some helpers for running Lwt code on top of Ocamlnet event queues.

This is for Lwt-2.3 or better.

See also the comments in Engines and LWT.

class lwt_backend : Unixqueue.event_system -> object .. end
Adapter for turning an Ocamlnet event_system into an Lwt Lwt_engine.t.
ocamlnet-4.1.2/doc/html-main/type_Rpc_proxy.html0000644000175000017500000012742312731530354020327 0ustar gerdgerd Ocamlnet 4 Reference Manual : Rpc_proxy sig
  module ReliabilityCache :
    sig
      type rcache
      type rcache_policy =
          [ `Any_failing_port_disables_host
          | `Failing_port_disables_host of int
          | `Independent
          | `None ]
      type rcache_config = {
        rcache_policy : Rpc_proxy.ReliabilityCache.rcache_policy;
        rcache_disable_timeout_min : float;
        rcache_disable_timeout_max : float;
        rcache_threshold : int;
        rcache_availability :
          Rpc_proxy.ReliabilityCache.rcache -> Unix.sockaddr -> bool;
      }
      val create_rcache_config :
        ?policy:Rpc_proxy.ReliabilityCache.rcache_policy ->
        ?disable_timeout_min:float ->
        ?disable_timeout_max:float ->
        ?threshold:int ->
        ?availability:(Rpc_proxy.ReliabilityCache.rcache ->
                       Unix.sockaddr -> bool) ->
        unit -> Rpc_proxy.ReliabilityCache.rcache_config
      val create_rcache :
        Rpc_proxy.ReliabilityCache.rcache_config ->
        Rpc_proxy.ReliabilityCache.rcache
      val rcache_config :
        Rpc_proxy.ReliabilityCache.rcache ->
        Rpc_proxy.ReliabilityCache.rcache_config
      val global_rcache_config :
        unit -> Rpc_proxy.ReliabilityCache.rcache_config
      val set_global_rcache_config :
        Rpc_proxy.ReliabilityCache.rcache_config -> unit
      val global_rcache : unit -> Rpc_proxy.ReliabilityCache.rcache
      val derive_rcache :
        Rpc_proxy.ReliabilityCache.rcache ->
        Rpc_proxy.ReliabilityCache.rcache_config ->
        Rpc_proxy.ReliabilityCache.rcache
      val incr_rcache_error_counter :
        Rpc_proxy.ReliabilityCache.rcache -> Unix.sockaddr -> unit
      val reset_rcache_error_counter :
        Rpc_proxy.ReliabilityCache.rcache -> Unix.sockaddr -> unit
      val sockaddr_is_enabled :
        Rpc_proxy.ReliabilityCache.rcache -> Unix.sockaddr -> bool
      val host_is_enabled :
        Rpc_proxy.ReliabilityCache.rcache -> Unix.inet_addr -> bool
    end
  module ManagedClient :
    sig
      type mclient
      type mclient_config = {
        mclient_rcache : Rpc_proxy.ReliabilityCache.rcache;
        mclient_socket_config : Rpc_client.socket_config;
        mclient_idle_timeout : float;
        mclient_programs : Rpc_program.t list;
        mclient_msg_timeout : float;
        mclient_msg_timeout_is_fatal : bool;
        mclient_exception_handler : (exn -> unit) option;
        mclient_auth_methods : Rpc_client.auth_method list;
        mclient_user_name : string option;
        mclient_initial_ping : bool;
        mclient_max_response_length : int option;
        mclient_mstring_factories :
          Netxdr_mstring.named_mstring_factories option;
      }
      exception Service_unavailable
      val create_mclient_config :
        ?rcache:Rpc_proxy.ReliabilityCache.rcache ->
        ?socket_config:Rpc_client.socket_config ->
        ?idle_timeout:float ->
        ?programs:Rpc_program.t list ->
        ?msg_timeout:float ->
        ?msg_timeout_is_fatal:bool ->
        ?exception_handler:(exn -> unit) ->
        ?auth_methods:Rpc_client.auth_method list ->
        ?user_name:string option ->
        ?initial_ping:bool ->
        ?max_response_length:int ->
        ?mstring_factories:Netxdr_mstring.named_mstring_factories ->
        unit -> Rpc_proxy.ManagedClient.mclient_config
      val create_mclient :
        Rpc_proxy.ManagedClient.mclient_config ->
        Rpc_client.connector ->
        Unixqueue.event_system -> Rpc_proxy.ManagedClient.mclient
      type state = [ `Connecting | `Down | `Up of Unix.sockaddr option ]
      val mclient_state :
        Rpc_proxy.ManagedClient.mclient -> Rpc_proxy.ManagedClient.state
      val mclient_serial : Rpc_proxy.ManagedClient.mclient -> int
      val pending_calls : Rpc_proxy.ManagedClient.mclient -> int
      val event_system :
        Rpc_proxy.ManagedClient.mclient -> Unixqueue.event_system
      val shut_down : Rpc_proxy.ManagedClient.mclient -> unit
      val sync_shutdown : Rpc_proxy.ManagedClient.mclient -> unit
      val trigger_shutdown :
        Rpc_proxy.ManagedClient.mclient -> (unit -> unit) -> unit
      val record_unavailability : Rpc_proxy.ManagedClient.mclient -> unit
      val enforce_unavailability : Rpc_proxy.ManagedClient.mclient -> unit
      val set_batch_call : Rpc_proxy.ManagedClient.mclient -> unit
      val rpc_engine :
        Rpc_proxy.ManagedClient.mclient ->
        (Rpc_proxy.ManagedClient.mclient ->
         '-> ((unit -> 'b) -> unit) -> unit) ->
        '-> 'Uq_engines.engine
      val compare :
        Rpc_proxy.ManagedClient.mclient ->
        Rpc_proxy.ManagedClient.mclient -> int
      type t = mclient
      val use : t -> Rpc_program.t -> unit
      val unbound_sync_call :
        t -> Rpc_program.t -> string -> Netxdr.xdr_value -> Netxdr.xdr_value
      val unbound_async_call :
        t ->
        Rpc_program.t ->
        string ->
        Netxdr.xdr_value -> ((unit -> Netxdr.xdr_value) -> unit) -> unit
      val xdr_ctx : t -> Netxdr.ctx
    end
  module ManagedSet :
    sig
      type mset
      type mset_policy = [ `Balance_load | `Failover ]
      type mset_config = {
        mset_mclient_config : Rpc_proxy.ManagedClient.mclient_config;
        mset_policy : Rpc_proxy.ManagedSet.mset_policy;
        mset_pending_calls_max : int;
        mset_pending_calls_norm : int;
        mset_idempotent_max : int;
        mset_idempotent_wait : float;
      }
      exception Cluster_service_unavailable
      val create_mset_config :
        ?mclient_config:Rpc_proxy.ManagedClient.mclient_config ->
        ?policy:Rpc_proxy.ManagedSet.mset_policy ->
        ?pending_calls_max:int ->
        ?pending_calls_norm:int ->
        ?idempotent_max:int ->
        ?idempotent_wait:float -> unit -> Rpc_proxy.ManagedSet.mset_config
      val create_mset :
        Rpc_proxy.ManagedSet.mset_config ->
        (Rpc_client.connector * int) array ->
        Unixqueue.event_system -> Rpc_proxy.ManagedSet.mset
      val mset_pick :
        ?from:int list ->
        Rpc_proxy.ManagedSet.mset -> Rpc_proxy.ManagedClient.mclient * int
      val mset_services :
        Rpc_proxy.ManagedSet.mset -> (Rpc_client.connector * int) array
      val mset_load : Rpc_proxy.ManagedSet.mset -> int array
      val event_system : Rpc_proxy.ManagedSet.mset -> Unixqueue.event_system
      val shut_down : Rpc_proxy.ManagedSet.mset -> unit
      val sync_shutdown : Rpc_proxy.ManagedSet.mset -> unit
      val trigger_shutdown :
        Rpc_proxy.ManagedSet.mset -> (unit -> unit) -> unit
      val idempotent_async_call :
        ?from:int list ->
        Rpc_proxy.ManagedSet.mset ->
        (Rpc_proxy.ManagedClient.mclient ->
         '-> ((unit -> 'b) -> unit) -> unit) ->
        '-> ((unit -> 'b) -> unit) -> unit
      val idempotent_sync_call :
        ?from:int list ->
        Rpc_proxy.ManagedSet.mset ->
        (Rpc_proxy.ManagedClient.mclient ->
         '-> ((unit -> 'b) -> unit) -> unit) ->
        '-> 'b
    end
end
ocamlnet-4.1.2/doc/html-main/index_types.html0000644000175000017500000064321312731530354017634 0ustar gerdgerd Ocamlnet 4 Reference Manual : Index of types

Index of types


A
ac_by_host [Nethttpd_services]
The service is protected by the access control rule
ac_by_host_rule [Nethttpd_services]
Access control by host: `Allow: Only the listed hosts are allowed; all other are denied, `Deny: The listed hosts are denied; all other are allowed
access_description_flag [Netx509]
action [Netsys_signal]
`Callback is used for normal handlers, and `Install for exclusive handlers.
addr_spec [Netaddress]
The pair local_part@domain as O'Caml type.
address [Netsys_gssapi]
Addresses tagged by address types
address [Netplex_types]
advice [Netsys_posix]
alg_id [Netx509_pubkey]
alg_param [Netx509_pubkey]
algorithm [Netsys_crypto_types.PUBKEY_CRYPTO]
announcement [Nethttpd_kernel]
See config
anon_semaphore [Netsys_sem]
anon_semaphore [Netsys_posix]
arg_store [Netcgi]
This is the type of functions arg_store so that arg_store env name header tells whether to `Discard the argument or to store it into a `File or in `Memory.
arg_store [Netcgi_common]
arg_store_type [Netcgi_common]
argument_processing [Netcgi1_compat.Netcgi]
armor_spec [Netascii_armor]
Which types of armor to decode, and how.
armor_type [Netascii_armor]
armored_message [Netascii_armor]
Messages: `Plain m: The body m is written as-is, `Base64 m: The body m needs to be BASE-64-encoded in order to create the ASCII armor, `OpenPGP(h,m,chksum): There is a header h, a body m which will be BASE-64-encoded, and a checksum chksum
armored_message_ro [Netascii_armor]
The read-only version of armored_message
assignment [Shell]
An assignment redirects file descriptors while calling a process
at_flag [Netsys_posix]
auth_challenge [Nethttp.Header]
The type of a single challenge, used during authentication.
auth_credentials [Nethttp.Header]
The type of a single credentials response, used during authentication.
auth_peeker [Rpc_server]
auth_result [Rpc_server]
auth_status [Nethttp_client]
Status of HTTP-level authentication: `None: Authentication wasn't tried., `OK: The authentication protocol finished. What this means exactly depends on the protocol. For most protocols it just means that the server authenticated the client. For some protocols it may also mean that the client authenticated the server (mutual authentication)., `Auth_error: The authentication protocol did not succeed. Note that this state can also be reached for an otherwise successful HTTP response (i.e. code 200) when the client could not authenticate the server and the protocol demands this., `Reroute trans_id: The request should be retried on a new connection for the transport identified by trans_id, `Continue: The authentication is still in progress. Normally the user should not see this state as the engine automatically continues the protocol. The argument of `Continue is private., `Continue_reroute: the combination of continue and reroute: the auth protocol continues, but the next request must be sent on the indicated transport.
authority_access_description_flag [Netx509]
authority_key_identifier [Netx509]

B
bad_request_error [Nethttpd_kernel]
A bad request is a violation where the current request cannot be decoded, and it is not possible to accept further requests over the current connection.
bind_creds [Netldap]
binding [Rpc_server]
binding_async [Rpc_server]
binding_sync [Rpc_server]
bitstring_value [Netasn1.Value]
buffer [Netmcore_buffer]
A buffer with a header of type 'h
buffer_descr [Netmcore_buffer]
The marshallable buffer descriptor

C
cache_control [Netcgi1_compat.Netcgi_types]
cache_control [Netcgi]
This is only a small subset of the HTTP 1.1 cache control features, but they are usually sufficient, and they work for HTTP/1.0 as well.
cache_control [Netcgi_common]
cache_control_token [Nethttp]
The cache control token for the Cache-control header
call_args [Rpc_portmapper_aux]
call_result [Rpc_portmapper_aux]
calling_error [Netsys_gssapi]
Possible errors caused by the caller
camlbox [Netcamlbox]
A camlbox may receive messages of type 'a
camlbox_address [Netcamlbox]
The address of a camlbox is a string that does not contain slashes.
camlbox_sender [Netcamlbox]
An endpoint that may send messages of type 'a to a camlbox
capacity [Netplex_types]
How many connections a container can accept in addition to the existing connections: `Normal_quality(n,greedy): It can accept n connections with normal service quality, n > 0, `Low_quality(n,greedy): It can accept n connections with low service quality (e.g. because it is already quite loaded), n > 0, `Unavailable: No capacity free The greedy flag sets whether greedy accepts are allowed.
cb [Netsys_sasl_types]
Possible channel bindings: `None: this is the default, `SASL_none_but_advertise: the client supports channel binding and advertises this. For this time, the SCRAM protocol is run without channel binding, though. (Only available in the SASL profile.), `SASL_require(type,data): Require channel binding. E.g. type="tls-unique", and data is set to the channel identifier (RFC 5929). (Only available in the SASL profile.), `GSSAPI data: use this channel binding for GSS-API This type is shared by SASL and GSSAPI providers.
cb [Netmech_scram]
Using the same channel binding type as for SASL
cgi_config [Netcgi1_compat.Netcgi_env]
Now simply called Netcgi.config.
cgi_cookie [Netcgi1_compat.Netcgi_types]
channel_bindings [Netsys_gssapi]
Channel binding as tuple (initiator_address, acceptor_address, application_data)
charset [Netconversion]
A charset is simply a set of code points.
client_session [Netsys_sasl_types.SASL_MECHANISM]
client_session [Netmech_scram]
Session context for clients
client_session [Nethttp.HTTP_CLIENT_MECHANISM]
client_state [Netsys_sasl_types]
The state of the client session: `Wait: it is waited for the server challenge., `Emit: a new client response can be emitted., `OK: the authentication protocol succeeded, `Auth_error: authentication error (it is unspecified which); the string may be used for logging), `Stale: The client session is refused as too old. The password, though, is correct. Otherwise this is the same as `Emit, i.e. the authentication process can continue.
clock [Netsys_posix]
clock_id [Netsys_posix]
close_mode [Netchannels]
Whether a close_out implies a commit or rollback operation
cmd [Netftp_client]
An FTP command.
cmd_state [Netftp_client]
The command state: `Not_connected: Not connected., `Init: Just connected, no greeting message arrived yet, `Success: Got the greeting message/last command was successful, `Proto_error: currently unused, `Temp_failure: Last command was not successful, and the code was between 400 and 499, `Perm_failure: Last command was not successful, and the code was between 500 and 599, `Rename_seq: Used instead of `Success after the RNFR command, `Restart_seq: Used instead of `Success after the REST command, `User_pass_seq: Used instead of `Success after the USER command when a password must be typed in, `User_acct_seq: Used instead of `Success after the USER command when an account ID must be typed in, `Pass_acct_seq: Used instead of `Success after the PASS command when an account iD must be typed in, `Preliminary: a reply with code 100 to 199. There will be another final reply for the command, `Auth_data: an ADAT reply inidicating that another round of authentication is necessary.
cmdline_config [Netplex_main]
color [Netsys_mem]
command [Shell_sys]
A command describes how to start a new process
command_context [Shell_fs]
command_interpreter [Shell_fs]
The interpreter runs the command, and fills in sfs_status
compiled_localization [Netdate]
complex_mime_body [Netmime]
complex_mime_body_ro [Netmime]
The read-only view of a complex_mime_message
complex_mime_message [Netmime]
complex_mime_message_ro [Netmime]
compute_resource_repr [Netmcore]
Centrally managed resources include: `File name: (Temporary) file name (absolute name), `Posix_shm name: Shared memory objects with name, `Posix_shm_sc(name,p): Shared memory objects with name, and attached container for semaphores with prefix p, `Posix_shm_preallocated(name,m): Shared memory objects already allocated by the master process. These objects are passed over to the worker processes by inheritance, and are always mapped at the same address. m is the bigarray mapping the object., `Posix_shm_preallocated_sc(name,m.p): Same, plus attached container for semaphores with prefix p, `Posix_sem name: Semaphores with name, `Fork_point(inh,f): Fork points where let pid=f arg fork a new process with argument arg. pid is the process identifier. The list inh are resources inherited from the master., `Joint_point f: Joint points where let res=f pid wait until the process pid terminates. If res is non-None it is the result value. If it is None, no result was passed back (including all pathological cases like crashes) Except fork and join points, these resources are also added to the pmanage object of Netplex (see Netplex_cenv.pmanage and Netsys_pmanage).
compute_resource_type [Netmcore]
condition [Netmcore_condition]
The condition variable
config [Netsys_crypto_types.TLS_PROVIDER]
config [Netcgi]
config [Netcgi_common]
config_error_response [Nethttpd_plex]
Three type abbreviations for logging functions
config_log_access [Nethttpd_plex]
config_log_error [Nethttpd_plex]
config_tree [Netplex_types]
conn_state [Nethttp_client_conncache]
A TCP connection may be either `Inactive, i.e.
connect_address [Uq_engines_compat]
connect_address [Uq_client]
Specifies the service to connect to:
connect_address [Uq_engines]
connect_options [Uq_engines_compat]
connect_options [Uq_client]
connect_options [Uq_engines]
connect_status [Uq_engines_compat]
connect_status [Uq_client]
This type corresponds with Uq_engines.connect_address: An engine connecting with an address `X will return a status of `X.
connect_status [Uq_engines]
connection [Netcgi_dbi.DBI_DRIVER]
connection [Netcgi_dbi.DBI_POOL]
connection_cache [Nethttp_client]
connection_directive [Netcgi]
Directive how to go on with the current connection: `Conn_close: Just shut down and close descriptor, `Conn_close_linger: Linger, shut down, and close descriptor, `Conn_keep_alive: Check for another request on the same connection, `Conn_error e: Shut down and close descriptor, and handle the exception e
connection_id [Rpc_server]
identifies the connection of a session.
connector [Rpc_server]
connector [Rpc_client]
const_str_datum_p [Nettls_gnutls_bindings]
consumer [Shell]
A consumer receives data from a called process
container [Netsys_sem]
The container of the semaphore is the shared memory object
container_id [Netplex_types]
Such objects identify containers.
container_state [Netplex_types]
The container state for workload management: `Accepting(n,t): The container is accepting further connections. It currently processes n connections. The last connection was accepted at time t (seconds since the epoch)., `Busy: The container does not accept connections, `Starting t: The container was started at time t and is not yet ready., `Shutting_down: The container is being shutted down.
context [Netsys_gssapi.GSSAPI]
A context is also opaque.
cookie [Nethttp]
Compatibility name.
copy_flag [Netfs]
copy_task [Uq_engines_compat]
copy_task [Uq_transfer]
Specifies the task the copier class has to do:
copy_task [Uq_engines]
create_process_option [Netsys_win32]
cred_type [Nettls_support]
The type of credential types
cred_usage [Netsys_gssapi]
credential [Netsys_gssapi.GSSAPI]
A credential is opaque for the caller of the GSS-API.
credentials [Netsys_sasl]
Credentials are given as list (type,value,params).
credentials [Netsys_crypto_types.TLS_PROVIDER]
credentials [Netsys_sasl_types.SASL_MECHANISM]
credentials [Netmech_scram]
Two forms of providing credentials: `Salted_password(spw,salt,iteration_count): get the salted password with spw = salt_password h password salt iteration_count, `Stored(stkey, srvkey, salt, iteration_count): get the pair (stkey, srvkey) with stored_key h password salt iteration_count
credentials [Nettls_support]
The types of credentials
credentials [Nethttp.HTTP_CLIENT_MECHANISM]
crl_list [Netsys_tls]
Certificate revocation lists are given either as:
crl_list [Netsys_crypto_types.TLS_PROVIDER]
Certificate revocation lists are given either as:
crt_list [Netsys_tls]
Certificates are given either as:
crt_list [Netsys_crypto_types.TLS_PROVIDER]
Certificates are given either as:
ctrl_op [Netshm]
cursor [Netconversion]
custom_ops [Netsys_mem]

D
data_chunk [Nethttpd_kernel]
A data_chunk is a substring of a string.
data_manager [Netshm_data]
The data manager consists of several manager functions.
datagram_type [Uq_engines_compat]
datagram_type [Uq_datagram]
- `Unix_dgram: Datagrams over Unix domain sockets `Inet_udp: Internet v4 UDP protocol, `Inet6_udp: Internet v6 UDP protocol
datagram_type [Uq_engines]
debug_target [Equeue.Debug]
decoder [Netxdr]
see text above
deref_aliases [Netldap]
What to do when aliases (server-dereferenced symbolic links) are found in the tree: `Never: do not dereference aliases but return them as part of the search result, `In_searching: when aliases are found in the children of the base object dereference the aliases, and continue the search there, and repeat this recursively if needed, `Finding_base_obj: dereference alises in base objects but not in children, `Always: always dereference aliases
descr [Netmcore_heap]
A descriptor ("address") pointing to the heap.
descr_state [Netftp_data_endpoint]
Describes the state of the socket used for data transfers.
dh_params [Netsys_tls]
Diffie-Hellman parameters:
dh_params [Netsys_crypto_types.TLS_PROVIDER]
Diffie-Hellman parameters:
digest [Netsys_crypto_types.DIGESTS]
Describes a digest
digest_ctx [Netsys_crypto_types.DIGESTS]
A digest context stores state while digesting data
digests [Netsys_crypto_types]
dlogger [Netlog.Debug]
Debug logger: The first string is the module name, and the second is the message
dn [Netdn]
This is the raw version of the DN: a sequence of relative DNs, and a relative DN is a set of (type,value) pairs.
document [Nethtml]
The type document represents parsed HTML documents:
domain [Netaddress]
The domain of the mailbox
dynamic_service [Nethttpd_services]

E
element_class [Nethtml]
Element classes are a property used in the HTML DTD.
empty_flags [Nettls_gnutls_bindings]
empty_flags_flag [Nettls_gnutls_bindings]
encap [Netplex_encap]
An encapsulated value with a type identifier
encap [Netplex_types]
encap [Nethttpd_plex]
encoder [Netxdr]
see text above
encoding [Netconversion]
The polymorphic variant enumerating the supported encodings.
encrypt_alg [Netx509_pubkey]
endpoint [Netsys_crypto_types.TLS_PROVIDER]
engine_req_state [Nethttpd_engine]
engine_state [Uq_engines_compat]
engine_state [Uq_engines]
The type of states with result values of type 't: `Working n: The engine is working. The number n counts the number of events that have been processed., `Done arg: The engine has completed its task without errors. The argument arg is the result value of the engine, `Error exn: The engine has aborted because of an error. The argument exn describes the error as an exception., `Aborted: The engine has aborted because the abort method was called
engine_state [Uq_resolver]
entity_set [Netencoding.Html]
entry [Netsys_signal]
entry [Netftp_client]
A file entry (name, facts).
entry_perm [Netftp_client]
Permissions: `Append: append to file possible, `Create: file can be created in this dir, `Delete: file or dir can be deleted, `Enter: dir can be entered, `Rename: file or dir can be renamed, `List: dir can be listed, `Mkdir: subdir can be created in this dir, `Delete_member: a file or dir can be deleted in this directory, `Read: a file can be retrieved, `Write: a file can be stored
entry_type [Netftp_client]
Types: `File: entry refers to file, `Cdir: entry refers to the directory being listed, `Pdir: entry is a parent of the directory being listed, `Dir: entry refers to directory, `Other: entry is neither file nor directory
environment [Shell_sys]
The abstract type of a process environment
eq [Netplex_types]
Equality witness
error_code [Nettls_gnutls_bindings]
etag [Nethttp]
Entity tags can be weak or strong
event [Uq_libevent.LIBOEVENT]
event [Unixqueue]
An event is triggered when the condition of an operation becomes true, when a signal happens, or when the event is (artificially) added to the event queue (add_event, below).
event_aggregator [Netsys_posix]
event_callback [Uq_libevent.LIBOEVENT]
event_flags [Uq_libevent.LIBOEVENT]
event_source [Netsys_posix]
exn_handler [Netcgi]
A function of type exn_handler allows to define a custom handler of uncaught exceptions raised by the unit -> unit parameter.
ext_key_usage_flag [Netx509]
extended_address [Netplex_types]
Possible addresses: `Socket s: The socket at this socket address, `Socket_file f: The file f contains the (anonymous) port number of a socket bound to 127.0.0.1 (This is meant as substitute for Unix Domain sockets on Win32.), `W32_pipe name: The Win32 pipe with this name which must be of the form "\\.\pipe\<pname>", `W32_pipe_file f: The file f contains the (random) name of a Win32 pipe, `Container(socket_dir,service_name,proto_name,thread_id): The special endpoint of the container for service_name that is running as thread_id. It is system-dependent what this endpoint "is" in reality, usually a socket or named pipe. If any container of a service is meant, the value `Any is substituted as a placeholder for a not yet known thread_id., `Internal name: an internal service called name. Internal sockets are only available for multithreaded programs, and are registered at Netplex_internal.
extfd [Netplex_types]
Internally used

F
fatal_error [Nethttpd_kernel]
These are the serious protocol violations after that the daemon stops any further processing.
fd_action [Netsys_posix]
fd_style [Netsys]
Some information what kind of operations are reasonable for descriptors: `Read_write: The descriptor is neither a socket not one of the other special cases, so only read/write is possible if read/write is possible at all. This style is also used if it is meaningless to use data I/O like read/write at all., `Recv_send(sockaddr,peeraddr): The descriptor is a connected socket. recv/send are the preferred operations., `Recvfrom_sendto: The descriptor is an unconnected socket, and it is possible to ask for addresses when exchanging data, so recvfrom/sendto are the preferred operations., `Recv_send_implied: The descriptor is a socket with implied connection. There are no socket addresses. recv/send are the preferred operations. It is not possible to call getsockname or getpeername., `W32_pipe: The descriptor is a proxy descriptor for a Win32 named pipe as returned by Netsys_win32.pipe_descr. , `W32_pipe_server: The descriptor is a proxy descriptor for a Win32 pipe server as returned by Netsys_win32.pipe_server_descr. , `W32_event: The descriptor is a Win32 proxy descriptor for an event as returned by Netsys_win32.create_event. It is not possible to read/write with these descriptors., `W32_process: The descriptor is a proxy descriptor for a Win32 process as returned by Netsys_win32.create_process. It is not possible to read/write with these descriptors., `W32_input_thread: The descriptor is a proxy descriptor for a Win32-specific input thread as returned by Netsys_win32.create_input_thread. , `W32_output_thread: The descriptor is a proxy descriptor for a Win32-specific output thread as returned by Netsys_win32.create_output_thread. , `TLS endpoint: A TLS tunnel is running over the descriptor. The details of the tunnel can be found in endpoint. Note that it is allowed that the endpoint uses a second descriptor for either reading or writing (i.e. reading and writing go via different descriptors). In this case, it is sufficient that one of these descriptors is accompanied with `TLS endpoint. Win32: For the exact meaning of proxy descriptors, please see Netsys_win32.
file_kind [Netfs]
file_option [Nethttpd_services]
Add-on features for file services: `Enable_gzip: Deprecated. Same as `Enable_cooked_compression., `Enable_cooked_compression: Modifies the way compressed files are handled. Normally it is required that one accesses the compressed file (with suffix such as "gz") directly to get it in compressed form. If this option is enabled, though, the server also compresses the base file (without suffix such as "gz"), but only if the base file is accompanied by a compressed version (with suffix). E.g. if there is "foo" and "foo.gz", this enables that the accesses to "foo" can make use of compression., `Enable_index_file: If enabled, accesses to directories are redirected to index files. The possible file names are given in the string list. E.g. `Enable_index_file ["index.html"; "index.htm"]. It is redirected to these files, so these can be handled by different services if neccessary., `Enable_listings: If enabled, directory listings are generated by calling the argument function. The PATH_TRANSLATED property of the environment contains the absolute name of the directory to list. The PATH_INFO property is the corresponding URI path. SCRIPT_NAME is meaningless., `Override_compression_suffixes l: Tags the file suffixes in l as compression schemes. A pair (suffix,ce) sets that the suffix means the content encoding ce. Knowing this is important for determining the media type of the file.
file_service [Nethttpd_services]
Describes a file service
file_tls_endpoint [Netsys_crypto_types]
filename [Netftp_client]
There are several methods how to specify filenames: `NVFS name: The "Network Virtual File System" is the normal way of accessing FTP files. The client walks into the directory containing the file using CWD and CDUP commands, and calls the file operation from this directory. For simplicity, this client interprets slashes in name as path component separators. The FTP server will never see these slashes., `TVFS name: The optional "Trivial Network File System" avoids the CWD and CDUP commands. The tagged name is normalized (double slashed removed etc.), and is passed to the server as-is. Before using the faster TVFS one should check whether it is supported (feature "TVFS"). Note that even for TVFS there are no special files "." and ".."!, `Verbatim name: The string name is passed to the server without transforming it in any way.
filter [Netldap]
Filter: `Equality_match(attr_descr, value), `Substrings(attr_descr, prefix_match, substring_matches, suffix_match), `Greater_or_equal(attr_descr,value), `Less_or_equal(attr_descr,value), `Present(attr_descr), `Approx_match(attr_descr,value), `Extensible_match(matching_rule_id, attr_descr, value, dn_attrs) Here, attr_descr is the name of the attribute, either given by an OID (in dotted representation) or a by a descriptive name.
final_state [Uq_engines_compat]
final_state [Uq_engines]
Same as engine_state without `Working.
flags [Netgss_bindings]
flags_flag [Netgss_bindings]
fork_point [Netmcore_process]
A fork point can start a new process with argument 'a
form_code [Netftp_client]
The form_code has a meaning when FTP is used to print files: `Non_print: This is not the case., `Telnet: Telnet control codes are used for vertical movement, `ASA: ASA (Fortran) control codes are used for vertical movement
format [Netlog]
fp4 [Netnumber]
single precision float (IEEE "float")
fp8 [Netnumber]
double precision float (IEEE "double")
from_uni_list [Netmappings]
front_token [Nethttpd_kernel]
Tokens generated by http_response: `Resp_wire_data are data tokens., `Resp_end indicates the end of the response.
ftp_auth [Netftp_client]
ftp_data_prot [Netftp_client]
Meaning: `C: no protection (clear), `S: integrity protection, `E: encryption without integrity protection, `P: integrity protection and encryption (= privacy)
ftp_data_prot [Netftp_data_endpoint]
ftp_method [Netftp_client]
An ftp_method is a small procedure doing some task
ftp_protector [Netftp_data_endpoint]
The functions for encrypting (wrapping) and decrypting (unwrapping) messages when an RFC 2228 security layer is active.
ftp_state [Netftp_client]
The ftp_state reflects the knowledge of the client about what has been agreed upon with the server.
fwd_mode [Shell_sys]
Determines whether and how keyboard signals (SIGINT, SIGQUIT) are forwarded from the caller to the new child.

G
general_name [Netx509]
General names: `Other_name(oid, value): the oid determines the extension name format, `Rfc822_name n: an email address n (ASCII encoded), `DNS_name n: an Internet domain n (ASCII encoded - no internationalization), `X400_address v: an X.400 address, which is not decoded here and just given as unparsed ASN.1 value v, `Directory_name n: a directory name n (i.e. a name using the syntax of distinguished names), `Edi_party_name(assigner,party), both names as UTF-8, `Uniform_resource_identifier uri: this uri (ASCII-encoded, no internationalization), `IP_address(dom,addr,mask): the address with mask, `Registered oid: a symbolical pre-registered name known under oid
glob_expr [Netglob]
glob_expr_atom [Netglob]
Atoms:
glob_mode [Netglob]
Modes: `Existing_paths: Only paths are returned that really exist, `All_paths: Generated paths not including *, ? and bracket expressions are returned even if they do not exist. For example, globbing for "fictive{1,2,3}" would return ["ficitve1";"fictive2";"fictive3"] independent of whether these files exist., `All_words: Patterns that cannot be resolved are returned as-is (like the shell does)
glob_set [Netglob]
A set of code points is given as a list of ranges (from,to), with from <= to.
gnutls_alert_description_t [Nettls_gnutls_bindings]
gnutls_alert_level_t [Nettls_gnutls_bindings]
gnutls_anon_client_credentials_t [Nettls_gnutls_bindings]
gnutls_anon_server_credentials_t [Nettls_gnutls_bindings]
gnutls_certificate_credentials_t [Nettls_gnutls_bindings]
gnutls_certificate_import_flags [Nettls_gnutls_bindings]
gnutls_certificate_import_flags_flag [Nettls_gnutls_bindings]
gnutls_certificate_print_formats_t [Nettls_gnutls_bindings]
gnutls_certificate_request_t [Nettls_gnutls_bindings]
gnutls_certificate_status_t [Nettls_gnutls_bindings]
gnutls_certificate_status_t_flag [Nettls_gnutls_bindings]
gnutls_certificate_type_t [Nettls_gnutls_bindings]
gnutls_certificate_verify_flags [Nettls_gnutls_bindings]
gnutls_certificate_verify_flags_flag [Nettls_gnutls_bindings]
gnutls_channel_binding_t [Nettls_gnutls_bindings]
gnutls_cipher_algorithm_t [Nettls_gnutls_bindings]
gnutls_cipher_hd_t [Nettls_gnutls_bindings]
gnutls_close_request_t [Nettls_gnutls_bindings]
gnutls_compression_method_t [Nettls_gnutls_bindings]
gnutls_credentials [Nettls_gnutls_bindings]
gnutls_credentials_type_t [Nettls_gnutls_bindings]
gnutls_dh_params_t [Nettls_gnutls_bindings]
gnutls_digest_algorithm_t [Nettls_gnutls_bindings]
gnutls_ecc_curve_t [Nettls_gnutls_bindings]
gnutls_handshake_description_t [Nettls_gnutls_bindings]
gnutls_info_access_what_t [Nettls_gnutls_bindings]
gnutls_init_flags [Nettls_gnutls_bindings]
gnutls_init_flags_flag [Nettls_gnutls_bindings]
gnutls_kx_algorithm_t [Nettls_gnutls_bindings]
gnutls_mac_algorithm_t [Nettls_gnutls_bindings]
gnutls_openpgp_crt_status_t [Nettls_gnutls_bindings]
gnutls_openpgp_keyring_t [Nettls_gnutls_bindings]
gnutls_params_type_t [Nettls_gnutls_bindings]
gnutls_pk_algorithm_t [Nettls_gnutls_bindings]
gnutls_pkcs_encrypt_flags_t [Nettls_gnutls_bindings]
gnutls_pkcs_encrypt_flags_t_flag [Nettls_gnutls_bindings]
gnutls_priority_t [Nettls_gnutls_bindings]
gnutls_privkey_t [Nettls_gnutls_bindings]
gnutls_privkey_type_t [Nettls_gnutls_bindings]
gnutls_protocol_t [Nettls_gnutls_bindings]
gnutls_psk_client_credentials_t [Nettls_gnutls_bindings]
gnutls_psk_key_flags [Nettls_gnutls_bindings]
gnutls_psk_server_credentials_t [Nettls_gnutls_bindings]
gnutls_pubkey_t [Nettls_gnutls_bindings]
gnutls_sec_param_t [Nettls_gnutls_bindings]
gnutls_server_name_type_t [Nettls_gnutls_bindings]
gnutls_session_t [Nettls_gnutls_bindings]
gnutls_sign_algorithm_t [Nettls_gnutls_bindings]
gnutls_srp_client_credentials_t [Nettls_gnutls_bindings]
gnutls_srp_server_credentials_t [Nettls_gnutls_bindings]
gnutls_supplemental_data_format_type_t [Nettls_gnutls_bindings]
gnutls_x509_crl_t [Nettls_gnutls_bindings]
gnutls_x509_crt_fmt_t [Nettls_gnutls_bindings]
gnutls_x509_crt_t [Nettls_gnutls_bindings]
gnutls_x509_privkey_t [Nettls_gnutls_bindings]
gnutls_x509_subject_alt_name_t [Nettls_gnutls_bindings]
group [Unixqueue]
A group is an abstract tag for a set of events, resources, and event handlers.
group_action [Shell_sys]
Determines in which process group the new process will run
group_mode [Shell_sys]
Specifies how the job instance is related to process groups
gss_OID [Netgss_bindings]
gss_OID_set [Netgss_bindings]
gss_buffer_t [Netgss_bindings]
gss_channel_bindings_t [Netgss_bindings]
gss_cred_id_t [Netgss_bindings]
gss_cred_usage_t [Netgss_bindings]
gss_ctx_id_t [Netgss_bindings]
gss_name_t [Netgss_bindings]
gss_qop_t [Netgss_bindings]

H
hash_function [Netx509_pubkey]
header_kind [Nethttp_client]
The `Base header is set by the user of http_call and is never changed during processing the call.
heap [Netmcore_heap]
A heap where the type of the root element is 'a
host [Nethttpd_services]
For name- and IP-based virtual hosting this record describes the individual host.
host_distributor [Nethttpd_services]
Describes virtual hosting by pairs (host,service): If host matches the incoming request, the corresponding service is performed to generate the response.
how_to_reconnect [Nethttp_client]
How to deal with automatic reconnections, especially when the connection crashes.
how_to_redirect [Nethttp_client]
http_method [Nethttp]
Method name, URI
http_method [Netcgi]
http_method [Netcgi_common]
http_options [Nethttp_client]
Options for the whole pipeline.
http_service_reaction [Nethttpd_types]
Indicates the immediate reaction upon an arriving HTTP header: `Accept_body is the regular way of processing requests. If necessary, the client is told to continue sending the rest of the request., `Reject_body can be used when the body of the request is not needed, and the response will be negative., `Static means to send the header and a constant string back as response. The header is taken from the environment if not explicitly passed, Note: The Content-Length header is automatically added. The Content-Type defaults to "text/html"., `File is similar to this, but the data come from a file. The file is specified by an absolute pathname. The range of the file is given by the start position and the length of the range. The header is taken from the environment if not explicitly passed, Note: The Content-Length header is automatically added. The Content-Type defaults to "text/html"., `Std_response is similar to `Static, however the body is the standard text for the status code. If the header is omitted, it is taken as empty. The third argument is an optional entry into the error log. Note: The Content-Length header is automatically added. The Content-Type defaults to "text/html".
http_status [Nethttp]
HTTP response status:
httpd_factory [Nethttpd_plex]
The type of the nethttpd_processor function

I
iana_hash_fn [Netsys_digests]
The hash functions contained in the IANA registry (http://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xhtml).
identity [Rpc_auth_sys]
Specifies the user: `Effective_user: Take the effective user of the process, `Real_user: Take the real user of the process, `This_user(uid,gid,sup_groups,hostname): Pretend to be this user
in_bdevice [Uq_io]
Devices with look-ahead
in_buffer [Uq_io]
in_device [Uq_io]
Currently supported devices for input: `Polldescr(st,fd,esys): The poll system call is used with file descriptor fd to wait for incoming data. The event system esys is the underlying event queue. This works well for pipes, sockets etc. but not for normal files. The style st can be obtained from fd via Netsys.get_fd_style., `Multiplex mplex: The multiplex controller mplex is used as device. , `Buffer buf: Data comes from the buffer buf (which in turn is connected with a second device), `Count_in(f,d): Data is read from d, and every time a few bytes n are read the function f n is called (which may raise an exception) Generally, it is not well supported to read in parallel several times from the same device.
in_record [Rpc_transport]
in_rule [Rpc_transport]
inactive_data [Nethttp_client_conncache]
inetspec [Uq_engines_compat]
inetspec [Uq_client]
inetspec [Uq_engines]
inherit_request [Netmcore]
init_credentials [Netsys_sasl.Server]
A function for preparing credentials, provided by the mechanism.
init_value_flag [Netsys_mem]
input_mode [Netcgi1_compat.Netcgi_env]
This is not used anywhere.
input_result [Netchannels]
This type is for the method enhanced_input of enhanced_raw_in_channel.
input_state [Netcgi1_compat.Netcgi_env]
This is not the business of the user.
int32_array [Netshm]
int4 [Netnumber]
32 bit signed integer
int8 [Netnumber]
64 bit signed integer
int_value [Netasn1.Value]
internal_pipe [Rpc_server]
internal_pipe [Rpc_client]
internal_pipe [Rpc_transport]
internal_socket [Rpc_server]
internal_socket [Rpc_client]
interprocess_token [Netsys_gssapi]
Interprocess tokens.
io_device [Uq_io]
Bidirectional devices
ioprio [Netsys_posix]
ioprio_target [Netsys_posix]

J
job [Shell_sys]
job_instance [Shell_sys]
job_status [Shell_sys]
Indicates the status of the job
join_point [Netmcore_process]
A join point can wait until a process finishes with a result 'b

K
kex_alg [Netx509_pubkey]
key_type [Netauth]
Key types: `Kc is used for computing checksums, `Ke is used for encrypting confidential messages, `Ki is used for computing integrity checksums for encrypted messages
key_usage [Nettls_gnutls_bindings]
key_usage_flag [Nettls_gnutls_bindings]
key_usage_flag [Netx509]
kind_check [Netplex_types]
Helper type for a polymorphic check whether a kind this the expected kind

L
langinfo [Netsys_posix]
ldap_connection [Netldap]
level [Netlog]
The log levels (syslog-like)
level [Netsys_posix]
level [Netplex_types]
Log levels, modeled after syslog
lexbuf [Netulex.Ulexing]
linear_distributor [Nethttpd_services]
Services are selected by calling the selector function.
listen_address [Uq_engines_compat]
listen_address [Uq_server]
Specifies the resource to listen on:
listen_address [Uq_engines]
listen_options [Uq_engines_compat]
listen_options [Uq_server]
listen_options [Uq_engines]
local_part [Netaddress]
Usually the user name
local_receiver [Netftp_data_endpoint]
The local_receiver is the object that gets the data received over the data connection.
local_sender [Netftp_data_endpoint]
The local_sender is the object that provides the data sent over the data connection.
localization [Netdate]
locking_method [Netshm]
The locking method is used to ensure that parallel read and write operations to the memory object do not interfer with each other.
logger [Netlog]
A logging function takes a level, and the message
lookup [Netsys_sasl.Server]
see create_session
loop_flags [Uq_libevent.LIBOEVENT]

M
major_status [Netsys_gssapi]
The major status consists of these three elements.
mapping [Rpc_portmapper_aux]
maskgen_function [Netx509_pubkey]
match_result [Nethttp]
mbox [Netplex_mbox.MBOX]
The type of the mailboxes
mclient [Rpc_proxy.ManagedClient]
A managed client
mclient_config [Rpc_proxy.ManagedClient]
memory [Nettls_gnutls_bindings]
memory [Netsys_mem]
We consider 1-dimensional bigarrays of chars as memory buffers.
memory [Netsys_types]
We consider 1-dimensional bigarrays of chars as memory buffers.
memory [Netgss_bindings]
memory_pool [Netsys_mem]
A pool of memory blocks that are all the same size and page-aligned (if the OS supports this).
message [Netsys_gssapi]
Messages are represented as lists of mstring
method_distributor [Nethttpd_services]
The first service is selected for which the method filter accepts the request
method_filter [Nethttpd_services]
The request is only accepted if listed (for `Limit), or if not listed (for `Limit_except).
mime_message [Netmime]
Simple MIME message, in a form that is compatible with complex ones.
mime_message_ro [Netmime]
Read-only variant of simple messages
mime_scanner [Netmime_string]
The opaque type of a scanner for structured values
minor_status [Netsys_gssapi]
The minor status is provider-specific.
mkdir_flag [Netfs]
mode [Rpc]
mode2 [Rpc_server]
Determines the type of the server for create2:
mode2 [Rpc_client]
Determines the type of the client for create2:
model_constraint [Nethtml]
Model constraints define the possible sub elements of an element: `Inline: The sub elements must belong to the class `Inline, `Block: The sub elements must be members of the classes `Block or `Essential_block, `Flow: The sub elements must belong to the classes `Inline, `Block, or `Essential_block, `Empty: There are no sub elements, `Any: Any sub element is allowed, `Special: The element has special content (e.g. <script>). Functionally equivalent to `Empty, `Elements l: Only these enumerated elements may occur as sub elements, `Or(m1,m2): One of the constraints m1 or m2 must hold, `Except(m1,m2): The constraint m1 must hold, and m2 must not hold, `Sub_exclusions(l,m): The constraint m must hold; furthermore, the elements enumerated in list l are not allowed as direct or indirect subelements, even if m or the model of a subelement would allow them. The difference to `Except(m, `Elements l) is that the exclusion is inherited to the subelements. The `Sub_exclusions expression must be toplevel, i.e. it must not occur within an `Or, `Except, or another 'Sub_exclusions expression. Note that the members of the class `Everywhere are allowed everywhere, regardless of whether the model constraint allows them or not.
monitor [Uq_mt]
A thread monitor governs which threads have access to a set of engines running together on an event system
mountpoint [Netcgi_plex]
mset [Rpc_proxy.ManagedSet]
a managed set
mset_config [Rpc_proxy.ManagedSet]
mset_policy [Rpc_proxy.ManagedSet]
Sets in which order managed clients are picked from the services array passed to create_mset: `Failover: Picks an element from the first service in services that is enabled and has free capacity. That means that the first service is preferred until it is maxed out or it fails, then the second service is preferred, and so on., `Balance_load: Picks an element from the service in services that is enabled and has the lowest load.
multipart_style [Netmime_channels]
How to parse multipart messages: `None: Do not handle multipart messages specially. Multipart bodies are not further decoded, and returned as `Body b where b is the transfer-encoded text representation., `Flat: If the top-level message is a multipart message, the parts are separated and returned as list. If the parts are again multipart messages, these inner multipart messages are not furher decoded and returned as `Body b., `Deep: Multipart messages are recursively decoded and returned as tree structure. This value determines how far the complex_mime_message structure is created for a parsed MIME message.
mutator [Netmcore_heap]
Mutators allow it to push new values onto the heap.
mutex [Netplex_mutex]
mutex [Netmcore_mutex]
mutex_type [Netmcore_mutex]
Types: `Normal mutexes have no checks for deadlocks., `Errorcheck mutexes check whether the process locks the mutex again, and fail in this case. Also, only the owning process can unlock a mutex., `Recursive mutexes allow that the owner locks several times. The same number of unlock requests need to be issued to give up the ownership

N
name [Netsys_gssapi.GSSAPI]
A name is also opaque
named_mstring_factories [Netxdr_mstring]
named_semaphore [Netsys_posix]
net_nettle_cipher_ctx_t [Nettls_nettle_bindings]
net_nettle_cipher_t [Nettls_nettle_bindings]
net_nettle_gcm_aes_ctx_t [Nettls_nettle_bindings]
net_nettle_hash_ctx_t [Nettls_nettle_bindings]
net_nettle_hash_t [Nettls_nettle_bindings]
netbuf [Rpc_portmapper_aux]
netscape_cookie [Nethttp]
These are old-style cookies, as introduced by Netscape.
node_type [Netsys_posix]
not_event [Netsys_posix]

O
oid [Netsys_gssapi]
OIDs like "1.3.6.1.5.6.2" as array of int's.
oid [Netx509_pubkey]
OIDs are just integer sequences
oid [Netx509]
OIDs are just integer sequences
oid [Netdn]
oid_set [Netsys_gssapi]
A set of OID's.
onshutdown_in_spec [Uq_engines_compat]
onshutdown_in_spec [Uq_transfer]
See class input_async_mplex for explanations
onshutdown_in_spec [Uq_engines]
onshutdown_out_spec [Uq_engines_compat]
onshutdown_out_spec [Uq_transfer]
See class output_async_mplex for explanations
onshutdown_out_spec [Uq_engines]
operating_type [Netcgi1_compat.Netcgi]
operation [Netldap]
operation [Unixqueue]
An operation specifies the condition to wait for.
other_url_spec [Netcgi1_compat.Netcgi_types]
other_url_spec [Netcgi]
Determines how an URL part is generated: `Env: Take the value from the environment., `This v: Use this value v. It must already be URL-encoded., `None: Do not include this part into the URL.
other_url_spec [Netcgi_common]
out_buffer [Uq_io]
Buffers that can be attached to a device to get buffered I/O
out_device [Uq_io]
Currently supported devices for output: `Polldescr(fd,esys): The poll system call is used with file descriptor fd to wait until data can be output. The event system esys is the underlying event queue. This works well for pipes, sockets etc. but not for normal files., `Multiplex mplex: The multiplex controller mplex is used as device. , `Buffer buf: Data is written to the buffer buf (which in turn is connected with a second device), `Count_out(f,d): Data is written to d, and every time a few bytes n are written the function f n is called (which may raise an exception) Generally, it is not well supported to write in parallel several times to the same device.
output_mode [Netcgi1_compat.Netcgi_env]
This is not used anywhere.
output_state [Nethttpd_types]
output_state [Netcgi1_compat.Netcgi_env]
This is not the business of the user.
output_type [Netcgi]
The ouput type determines how generated data is buffered.
output_type [Netcgi_common]

P
packed_value [Rpc_packer]
padding [Netsys_ciphers]
Padding schemes:
parallelization_type [Netplex_types]
Type of parallelization: `Multi_processing on a single host, `Multi_threading on a single host, `Controller_attached means that the service runs within the controller. This is (for now) only allowed for controller-internal services.
param_value [Nethttp.Header]
Parameters may occur quoted (`Q) or as already decoded values (`V)
param_value [Netplex_types]
param_value_or_any [Netplex_types]
pattern [Netglob]
Input for Netglob.glob
pattern [Netaux.KMP]
pc [Netasn1.Value]
peer [Nethttp_client_conncache]
pg_spec [Netsys_posix]
pin_callback [Netsys_crypto_types.PUBKEY_CRYPTO]
pipe_mode [Netsys_win32]
pm_obj [Netsys_pmanage]
pmaplist [Rpc_portmapper_aux]
pmaplist_p [Rpc_portmapper_aux]
poll_act_events [Netsys_posix]
Poll events.
poll_array [Netsys_posix]
The array of poll_cell entries
poll_cell [Netsys_posix]
The poll cell refers to the descriptor poll_fd.
poll_req_events [Netsys_posix]
poly_cursor [Netconversion]
A cursor denotes a character position in an encoded string.
polyclient [Netsys_polysocket]
A client, connected or unconnected
polyclient_box [Netplex_types]
This type pairs a polysocket_kind with a polyclient as GADT.
polyendpoint [Netsys_polysocket]
An endpoint is simply a pair (rd,wr) where rd is a polypipe open for reading, and wr is a polypipe open for writing.
polypipe [Netsys_polypipe]
polyserver [Netsys_polysocket]
A server
polyserver_box [Netplex_types]
This type pairs a polysocket_kind with a polyserver as GADT.
polysocket_kind [Netplex_types]
List possible argument types for polysockets (Netsys_polysocket), which are the basis for internal services.
polysocket_kind_box [Netplex_types]
Boxed version of polysocket_kind where the type parameter is hidden
port [Netftp_client]
The port of the data connection: `Active means that the server initiates the data connection to the listening client, and in the case of `Passive the client initiates the data connection to the listening server.
posix_timer [Netsys_posix]
prefix [Netsys_sem]
A name starting with a slash.
private_api [Nethttp_client]
The private part of the http_call class type
private_key [Netsys_tls]
Private keys are given either as:
private_key [Netsys_crypto_types.PUBKEY_CRYPTO]
private_key [Netsys_crypto_types.TLS_PROVIDER]
Private keys are given either as:
privkey [Netx509_pubkey]
process [Shell_sys]
A process is the running instance of a command (a Unix process)
process_id [Netmcore]
This tagged integer identifies processes.
producer [Shell]
A producer generates data sent to a called process
profile [Netmech_scram]
Profile
protocol [Rpc]
protocol [Nethttp]
The base protocol.
protocol [Netcgi1_compat.Netcgi_env]
protocol_attribute [Nethttp]
protocol_attribute [Netcgi1_compat.Netcgi_env]
protocol_version [Nethttp]
protocol_version [Netcgi1_compat.Netcgi_env]
proxy_type [Nethttp_client]
ptype [Netmech_scram]
Profile types: `GSSAPI: as defined in RFC 5802, the gs2-header is omitted, `SASL: as defined in RFC 5802
pubkey [Netx509_pubkey]
Public key info: the key as such plus the algorithm.
pubkey_crypto [Netsys_crypto_types]
public_key [Netsys_crypto_types.PUBKEY_CRYPTO]

Q
qop [Netsys_gssapi]
Quality-of-proctection parameters are mechanism-specific.
query_string_spec [Netcgi1_compat.Netcgi_types]
query_string_spec [Netcgi]
Determines how the query part of URLs is generated: `Env: The query string of the current request., `This l: The query string is created from the specified argument list l., `None: The query string is omitted., `Args: deprecated, use `This (left for backward compatibility).
query_string_spec [Netcgi_common]

R
r [Netplex_cenv.FUN_TYPE]
result type
r [Netplex_cenv.LEVER]
result type
raw_credentials [Netsys_crypto_types.TLS_PROVIDER]
The encoded credentials: `X509 s: The X509 certificate in DER encoding, `Anonymous: no certificate or other key is available
raw_credentials [Nettls_support]
The encoded credentials: `X509 s: The X509 certificate in DER encoding, `Anonymous: no certificate or other key is available
rcache [Rpc_proxy.ReliabilityCache]
The cache
rcache_config [Rpc_proxy.ReliabilityCache]
rcache_policy [Rpc_proxy.ReliabilityCache]
How failures of individual ports are interpreted: `Independent: When a connection to a remote port repeatedly fails, only this port is disabled, `Failing_port_disables_host p: When a connection to the TCP port p repeatedly fails, the whole remote host is disabled. Other ports do not disable the host, but are treated as in `Independent., `Any_failing_port_disables_host: When a connection to any TCP port repeatedly fails, the whole remote host is disabled, `None: Nothing is disabled Note that the rcache_availability hook is not affected by the policy; this hook is called anyway.
read_file_flag [Netfs]
read_file_flag [Nethttp_fs]
read_flag [Netfs]
read_flag [Nethttp_fs]
read_policy [Netcgi_apache.Apache.Request]
Policy to apply by setup_client_block if the request message indicates a body.
readdir_flag [Netfs]
readlink_flag [Netfs]
real_value [Netasn1.Value]
regexp [Netstring_str]
The type of regular expressions
regexp [Netstring_pcre]
The type of regular expressions; now based on Pcre
reject_code [Rpc_client]
Reaction on authentication problems: `Fail: Stop here, and report to user, `Retry: Just try again with current session, `Renew: Drop the current session, and get a new session from the current auth_method, `Next: Try the next authentication method
remove_flag [Netfs]
rename_flag [Netfs]
reply [Netftp_client]
Reply code plus text
representation [Netftp_client]
The representation of the transferred file: `ASCII: An ASCII variant is used, i.e. the server sends files in ASCII encoding with CR/LF as end-of-line marker. Supported by all servers., `EBCDIC: An EBCDIC variant is used, i.e. the server sends files in EBCDIC encoding with NEL as end-of-line marker, `Image: The file is transferred in its original binary representation. Supported by all servers. "Local" representations are not supported.
representation [Netcgi1_compat.Netcgi_types]
Embedded in the single place of use.
representation [Netcgi_common]
req_flag [Netsys_gssapi]
Flags for the init_sec_context method
req_token [Nethttpd_kernel]
A req_token represents a textual part of the received request: `Req_header is the full received header. Together with the header, the corresponding http_response object is returned which must be used to transmit the response., `Req_expect_100_continue is generated when the client expects that the server sends a "100 Continue" response (or a final status code) now. One should add `Resp_info_line resp_100_continue to the send queue if the header is acceptable, or otherwise generate an error response. In any case, the rest of the request must be read until `Req_end., `Req_body is a part of the request body. The transfer-coding, if any, is already decoded., `Req_trailer is the received trailer, `Req_end indicates the end of the request (the next request may begin immediately)., `Eof indicates the end of the stream, `Bad_request_error indicates that the request violated the HTTP protocol in a serious way and cannot be decoded. It is required to send a "400 Bad Request" response. The following token will be `Eof., `Fatal_error indicates that the connection crashed. The following token will be `Eof., `Timeout means that nothing has been received for a certain amount of time, and the protocol is in a state that the next request can begin. The following token will be `Eof. Note that it is always allowed to send tokens to the client.
request_line [Nethttpd_kernel]
The method (including the URI), and the HTTP version
request_method [Netcgi1_compat.Netcgi_types]
request_method [Netcgi_common]
res_id [Netmcore]
This tagged integer identifies resources.
resolver [Nethttp_client]
A name resolver is a function r called as r esys name reply.
resp_state [Nethttpd_kernel]
The response state: `Inhibited = it is not yet allowed to start the response, `Queued = the response waits on the queue for activation, `Active = the response is currently being transmitted, `Processed = the response has been completely sent, `Error = an error occurred during the transmission of this response, `Dropped = an earlier response forced to close the connection, and this response is dequeued
resp_token [Nethttpd_kernel]
The resp_token represents a textual part of the response to send: `Resp_info_line is an informational status line (code=100..199). There can be several informational lines, and they can be accompanied with their own headers. Such lines are only sent to HTTP/1.1 clients., `Resp_status_line is the final status line to send (code >= 200), `Resp_header is the whole response header to send, `Resp_body is the next part of the response body to send., `Resp_trailer is the whole response trailer to send (currently ignored), `Resp_action is special because it does not directly represent a token to send. The argument is a function which is called when the token is the next token on the active event queue. The function is also called when the event queue is dropped because of an error (the state of the response object indicates this). The function must not raise exceptions except Unix_error, and it must not block.
response_body_storage [Nethttp_client]
How to create the response body: `Memory: The response body is in-memory, `File f: The response body is stored into the file whose name is returned by f(), `Body f: The response body is stored into the object returned by f(), `Device f: The response is directly forwarded to the device obtained by f() (new since Ocamlnet-3.3) When the function f is called in the latter cases the response header has already been received, and can be retrieved with the response_header method of the call object.
result [Rpc_transport]
result [Netstring_str]
The type of matching results
result [Netstring_pcre]
The type of matching results
result [Netcgi_apache.Handler]
result_code [Netldap]
result_eof [Rpc_transport]
ret_flag [Netsys_gssapi]
Flags for the accept_sec_context method
rmdir_flag [Netfs]
routine_error [Netsys_gssapi]
Possible errors caused by the provider
rp__list [Rpc_portmapper_aux]
rpcb [Rpc_portmapper_aux]
rpcb_entry [Rpc_portmapper_aux]
rpcb_entry_list [Rpc_portmapper_aux]
rpcb_entry_list_ptr [Rpc_portmapper_aux]
rpcb_rmtcallargs [Rpc_portmapper_aux]
rpcb_rmtcallres [Rpc_portmapper_aux]
rpcb_stat [Rpc_portmapper_aux]
rpcb_stat_byvers [Rpc_portmapper_aux]
rpcblist_ptr [Rpc_portmapper_aux]
rpcbs_addrlist [Rpc_portmapper_aux]
rpcbs_addrlist_ptr [Rpc_portmapper_aux]
rpcbs_proc [Rpc_portmapper_aux]
rpcbs_rmtcalllist [Rpc_portmapper_aux]
rpcbs_rmtcalllist_ptr [Rpc_portmapper_aux]
rule [Rpc_server]
runner [Uq_tcl]
runner [Uq_gtk]

S
s [Netplex_cenv.FUN_TYPE]
argument type
s [Netplex_cenv.LEVER]
argument type
s_extended_token [Netmime_string]
An opaque type containing the information of s_token plus: where the token occurs, RFC-2047 access functions
s_option [Netmime_string]
s_param [Netmime_string]
The type of encoded parameters (RFC 2231)
s_token [Netmime_string]
A token may be one of: QString s: The quoted string s, i.e a string between double quotes. Quoted pairs are already decoded in s., Control c: The control character c (0-31, 127, 128-255), Special c: The special character c, i.e. a character from the specials list, DomainLiteral s: The bracketed string s, i.e. a string between brackets. Quoted pairs are already decoded in s., Comment: A string between parentheses. This kind of token is only generated when the option Return_comments is in effect., EncodedWord((charset,lang),encoding,encoded_word): An RFC-2047 style encoded word: charset is the name of the character set; lang is the language specifier (from RFC 2231) or ""; encoding is either "Q" or "B"; and encoded_word is the word encoded in charset and encoding. This kind of token is only generated when the option Recognize_encoded_words is in effect (if not, Atom is generated instead)., Atom s: A string which is neither quoted not bracketed nor written in RFC 2047 notation, and which is not a control or special character, i.e. the "rest", End: The end of the string
sarray [Netmcore_array]
Arrays where the elements have type 'e and the header has type 'h
sarray2 [Netmcore_matrix]
Arrays where the elements have type 'e and the header has type 'h
sarray2_descr [Netmcore_matrix]
The marshallable descriptor of a shared matrix
sarray_descr [Netmcore_array]
The marshallable descriptor of a shared array
sasl_mechanism [Netsys_sasl]
sc [Netsys_crypto_modes.Symmetric_cipher]
sc_ctx [Netsys_crypto_modes.Symmetric_cipher]
scipher [Netsys_crypto_types.SYMMETRIC_CRYPTO]
Describes a cipher
scipher_ctx [Netsys_crypto_types.SYMMETRIC_CRYPTO]
A cipher context stores processing data while encrypting or decrypting data
scope [Netldap]
The scope of the search: `Base: only the base object, `One: only the direct children of the base object, `Sub: the base object and all direct and indirect children
search_result [Netldap]
Search results are either entries or references: `Entry(object_dn, [(attr_descr, values); ...]), `Reference urls: The entry is not present on this server but can be looked up by following one of the urls
sem_kind [Netsys_posix]
sem_open_flag [Netsys_sem]
sem_open_flag [Netsys_posix]
sem_wait_behavior [Netsys_sem]
sem_wait_behavior [Netsys_posix]
semaphore [Netsys_posix]
semaphore [Netmcore_sem]
serial [Netlog.Debug]
A serial number for the optional tracking of ownership
server_error [Rpc]
server_error [Netmech_scram]
Error codes of this protocol
server_name [Netsys_crypto_types.TLS_PROVIDER]
server_session [Netsys_sasl_types.SASL_MECHANISM]
server_session [Netmech_scram]
Session context for servers
server_state [Netsys_sasl_types]
The state of the server session: `Wait: it is waited for the client response., `Emit: a new server challenge can be emitted., `OK: the authentication protocol succeeded, `Auth_error: authentication error (it is unspecified which; the string may be used for logging), `Restart session_id: this state can be entered after getting the first client response. It means that the saved session session_id may be restarted by calling server_process_response_restart with the client response.
service_factory [Nethttpd_plex]
The service factory function is called when a service configuration section of a certain type needs to be read.
session [Rpc_server]
identifies a pair of a call and a reply
session [Netsys_sasl.Server]
session [Netsys_sasl.Client]
shm_descr [Netshm]
A shared memory descriptor refers to a shared memory object.
shm_name [Netshm]
A shm_name is a name for a shared memory object.
shm_open_flag [Netsys_posix]
shm_table [Netshm]
shm_type [Netshm]
sig_action [Netsys_posix]
sign_alg [Netx509_pubkey]
simplified_dtd [Nethtml]
A simplified_dtd is an associative list of tuples (element_name, (element_class, constraint)): For every element_name it is declared that it is a member of element_class, and that the sub elements must satisfy constraint.
size_flag [Netfs]
sockaddr [Rpc_transport]
socket_state [Netplex_types]
The state of a socket: `Enabled: The controller allows containers to accept connections. Note that this does not necessarily means that there such containers., `Disabled: It is not allowed to accept new connections. The socket is kept open, however., `Restarting b: The containers are being restarted. The boolean argument says whether the socket will be enabled after that., `Down: The socket is down/closed
sockspec [Uq_engines_compat]
sockspec [Uq_client]
Extended names for socket addresses.
sockspec [Uq_engines]
socksymbol [Netsockaddr]
Symbolic socket names:
specific_keys [Netmech_scram]
The specific keys to use
split_result [Netstring_str]
split_result [Netstring_pcre]
squeue [Netmcore_queue]
Queues where the elements have type 'e and the header has type 'h
squeue_descr [Netmcore_queue]
The marshallble descriptor of queues
sref [Netmcore_ref]
sref_descr [Netmcore_ref]
The marshallable descriptor of a reference
state [Rpc_proxy.ManagedClient]
The state: `Down: The initial state, and also reached after a socket error, or after one of the shutdown functions is called. Although `Down, there might still some cleanup to do. When RPC functions are called, the client is automatically revived., `Connecting: This state is used while the initial ping is done. It does not reflect whether the client is really TCP-connected. Without initial ping, this state cannot occur., `Up s: The client is (so far known) up and can be used. s is the socket address of the local socket
state [Netsys_crypto_types.TLS_PROVIDER]
The state of a session:
state [Netpop]
status [Nethttp_client]
Condensed status information of a HTTP call: `Unserved: The call has not yet been finished, `HTTP_protocol_error e: An error on HTTP level occurred. Corresponds to the exception Http_protocol., `Successful: The call is successful, and the response code is between 200 and 299., `Redirection: The call is successful, and the response code is between 300 and 399., `Client_error: The call failed with a response code between 400 and 499., `Server_error: The call failed for any other reason.
status [Netcgi1_compat.Netcgi_types]
status_line [Nethttpd_kernel]
= (code, phrase)
status_type_t [Netgss_bindings]
std_activation [Nethttpd_services]
The way the Netcgi_types.cgi_activation object is created.
std_activation_options [Nethttpd_services]
These are options for `Std_activation.
store [Netmime]
Specifies where to store the body of a mail message.
store [Netcgi1_compat.Netcgi_types]
Embedded in the single place of use.
store [Netcgi_common]
str_datum [Nettls_gnutls_bindings]
str_datum_p [Nettls_gnutls_bindings]
string_like [Uq_io]
The user can pass data buffers that base either on bytes or on bigarrays of char (memory).
structure [Netftp_client]
The client supports two structures: `File_structure: Files are simply contiguous streams of bytes, `Record_structure: Files are sequences of records. FTP does not make a difference between variable and fixed length records. It is not forbidden that the records are themselves structured into lines, in fact it can happen that end-of-line markers are contained in binary records. Operating systems that support record-structured files often store text files in this format, i.e. every line is stored in its own record, without end-of-line marker. If record structure is selected by a STRU command, it is recommended to use the classes Netftp_data_endpoint.out_record_channel and Netftp_data_endpoint.in_record_channel for the local representation of the files, otherwise the records may be incorrectly mapped to the local conventions. Page-structured files (i.e.
subject_access_description_flag [Netx509]
suppl_status [Netsys_gssapi]
Further flags
support_level [Rpc_auth_gssapi]
support_level [Netsys_gssapi]
support_level [Netftp_client]
symlink_flag [Netfs]
symmetric_crypto [Netsys_crypto_types]
synchronization [Nethttp_client]
This type determines whether to keep requests and responses synchronized or not.
syslog_facility [Netsys_posix]
The facilities.
syslog_option [Netsys_posix]
The syslog options: `Cons: Fall back to console logging if syslog is unavailable, `Ndelay: Open the connection immediately, `Odelay: Open the connection at the first call syslog (default), `Nowait: Do not wait until it is ensured that the message is sent, `Pid: Log the PID with every message

T
t [Rpc_server]
represents a server for an RPC program
t [Rpc_portmapper]
represents a client for the Portmapper/RPCBIND daemon
t [Rpc_portmapper_clnt.Make'PMAP.V4]
t [Rpc_portmapper_clnt.Make'PMAP.V3]
t [Rpc_portmapper_clnt.Make'PMAP.V2]
t [Rpc_simple_client]
The type of simple clients
t [Rpc_client.USE_CLIENT]
The client type
t [Rpc_client]
The type of RPC clients
t [Rpc_program]
Type of RPC programs
t [Netoid]
t [Netpagebuffer]
t [Nethttp.Cookie]
Functions to manipulate cookies.
t [Netdate]
t [Netbuffer]
t [Netaddress]
The union of mailbox and group
t [Netshm_array]
t [Netshm_hashtbl]
t [Netplex_mbox.MBOX]
The type of messages
t [Netplex_encap.TYPE]
t [Netplex_encap.ENCAP]
t [Netplex_sharedvar.VV_TYPE]
t [Netplex_cenv.TYPE]
t [Netplex_cenv.LEVER]
t [Netplex_cenv.VAR_TYPE]
t [Netmcore_hashtbl]
The type of hash tables from type 'a to type 'b and a header of type 'h
t [Netcgi.Cookie]
Mutable cookie type.
t [Netcgi_common.Cookie]
t [Netcgi_apache.Handler]
The type of handler functions.
t [Netcgi_apache.Apache.Request]
Apache request_rec structure.
t [Netcgi_apache.Apache.Connection]
Apache conn_rec structure.
t [Netcgi_apache.Apache.Server]
Apache server_rec structure.
t [Netcgi_apache.Apache.Table]
Apache table structure.
t [Equeue]
This is the type of an event system with events of type 'a
t_PMAP'V2'pmapproc_callit'arg [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_callit'res [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_dump'arg [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_dump'res [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_getport'arg [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_getport'res [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_null'arg [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_null'res [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_set'arg [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_set'res [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_unset'arg [Rpc_portmapper_aux]
t_PMAP'V2'pmapproc_unset'res [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_callit'arg [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_callit'res [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_dump'arg [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_dump'res [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_getaddr'res [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_gettime'arg [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_gettime'res [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_null'arg [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_null'res [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_set'arg [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_set'res [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_unset'arg [Rpc_portmapper_aux]
t_PMAP'V3'rpcbproc_unset'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_bcast'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_bcast'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_dump'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_dump'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_getaddr'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_getaddr'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_getaddrlist'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_getaddrlist'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_getstat'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_getstat'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_gettime'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_gettime'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_getversaddr'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_getversaddr'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_indirect'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_indirect'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_null'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_null'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_set'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_set'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_taddr2uaddr'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_taddr2uaddr'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_uaddr2taddr'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_uaddr2taddr'res [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_unset'arg [Rpc_portmapper_aux]
t_PMAP'V4'rpcbproc_unset'res [Rpc_portmapper_aux]
t_descr [Netmcore_hashtbl]
The marshallable descriptor of a shared hash table
table_row [Netcgi_modtpl]
tag_class [Netasn1.Value]
tbuffer [Netsys_types]
A tagged buffer.
telnet_command [Nettelnet_client]
A telnet_command is the interpretation of the octets in a Telnet session, i.e.
telnet_connector [Nettelnet_client]
Connectors: Telnet_connect(host,port): The client connects to this port., Telnet_socket s: The client uses an already connected socket. Why Telnet_socket? Telnet is a symmetrical protocol; client and servers implement the same protocol features (the only difference is the environment: a client is typically connected with a real terminal; a server is connected with a pseudo terminal).
telnet_negotiated_option [Nettelnet_client]
telnet_negotiated_option: names for the most common options, and the generic name Telnet_option for other options.
telnet_option_state [Nettelnet_client]
An option has one of three states: Not_negotiated: There was no negotiation about the option. This means that the option is turned off (but this client is allowed to reject it explicitly), Accepted: Both sides have accepted the option., Rejected: One side has rejected the option. This also means that the option is off, but the client refuses to send further acknoledgements that the option is off (to avoid endless negotiation loops).
telnet_options [Nettelnet_client]
telnet_options: modifies the behaviour of the client.
test_flag [Netfs]
test_type [Netfs]
Tests: `N: the file name exists, `E: the file exists, `D: the file exists and is a directory, `F: the file exists and is regular, `H: the file exists and is a symlink (possibly to a non-existing target), `R: the file exists and is readable, `W: the file exists and is writable, `X: the file exists and is executable, `S: the file exists and is non-empty
text_data_repr [Netftp_data_endpoint]
Possible representation of text data: `ASCII means an ASCII-compatible encoding where the newline character is represented by CR/LF.
thread_sys_id [Netplex_types]
A system-specific identifier of the thread/process
time [Netsys_gssapi]
time_subtype [Netasn1.Value]
time_value [Netasn1.Value]
timer [Netplex_cenv]
A timer
timer_expiration [Netsys_posix]
timespec [Netsys_posix]
(t,t_nanos): Specifies a time by a base time t to which the nanoseconds t_nanos are added.
tls_config [Netsys_crypto_types]
tls_endpoint [Netsys_crypto_types]
tls_mode [Netldap]
Options: `Disabled: do not negotiate TLS, `Immediate: assume that the connection directly requires TLS, `StartTLS: upgrade an initially unprotected connection to TLS, `StartTLS_if_possible: upgrade an unprotected connection to TLS if possible (i.e. if supported by both ends of the connection)
tls_provider [Netsys_crypto_types]
token [Netsys_gssapi]
Authentication tokens.
transfer_coding [Nethttpd_kernel]
transmission_mode [Netftp_client]
The transmission mode selects how the data are encoded in the data connection.
transmission_mode [Netftp_data_endpoint]
The transmission mode as described in RFC 959.
transport_layer_id [Nethttp]
transport_layer_id [Nethttp_client]
The ID identifies a requirement for the transport channel, especially whether plain HTTP is sufficient, or HTTPS needs to be used, and if so, whether there are further requirements for the TLS context.
transport_layer_id [Nethttp_client_conncache]
tstring [Netsys_types]
A tagged string which is considered as immutable.
tstring_box [Netstring_tstring]
GADT for hiding the type parameter
tstring_kind [Netstring_tstring]
GADT for encoding the string type (string/bytes/bigarray)
tstring_ops [Netstring_tstring]
Operations to call on strings
tstring_ops_box [Netstring_tstring]
GADT for hiding the type parameter
tstring_polybox [Netstring_tstring]
GADT for hiding the type parameter.
type_name [Netasn1.Type_name]

U
uaddr [Rpc_portmapper_aux]
uint4 [Netnumber]
32 bit unsigned integer
uint8 [Netnumber]
64 bit unsigned integer
unicode_lexbuf [Netulex.ULB]
uri_distributor [Nethttpd_services]
Describes that services are bound to URI prefixes.
url [Neturl]
Values of type url describe concrete URLs.
url_syntax [Neturl]
Values of type url_syntax describe which components of an URL are recognized, which are allowed (and optional), and which are required.
url_syntax_option [Neturl]
user_name_format [Rpc_auth_gssapi]
What to return as user name: `Exported_name: the exported name in binary format (as described in RFC 2078, section 3.2). This format can only be read back by the gss_api object generating the name., `Prefixed_name: the display name in a text format "{<oid>}<namestring>"., `Plain_name: the string part of the display name
user_name_format [Rpc_auth_sys]
How Rpc_server.get_user returns the user as string: `Full: The format includes all transmitted details: "<uid>.<gid>.<gid1>.<gid2>...@<hostname>". All user and group IDs are numeric. The first two numbers, <uid> and <gid> are always present. The other numbers are the supplementary group IDs and can be omitted. The <hostname> is the name passed in the credentials., `UID: The string is the numeric user ID, `Custom f: The string is returned by the function f. The arguments are uid, gid, the array of the supplementary group IDs and the hostname.
user_name_interpretation [Rpc_auth_gssapi]

V
valid_glob_expr [Netglob]
A validated glob_expr
value [Netasn1.Value]
var [Netplex_sharedvar.VV_TYPE]
var [Netcgi_modtpl]
variable [Netsys_global]
verbosity [Rpc_util]
How verbose the RPC ftrace is: `Name_only: For each RPC call only the name is logged, `Name_abbrev_args: The name and the abbreviated argument list are logged, `Name_full_args: The name and the full argument list are logged
versioned_value [Netplex_sharedvar]
Cache for the current value

W
w32_console_attr [Netsys_win32]
w32_console_info [Netsys_win32]
w32_console_mode [Netsys_win32]
See the msdn docs for GetConsoleMode for details
w32_event [Netsys_win32]
w32_input_thread [Netsys_win32]
w32_object [Netsys_win32]
w32_output_thread [Netsys_win32]
w32_pipe [Netsys_win32]
A pipe endpoint
w32_pipe_server [Netsys_win32]
A pipe server.
w32_process [Netsys_win32]
A handle to spawned processes
wait_entry [Netmcore_condition]
Each process that wants to wait needs a wait_entry.
wait_entry_e [Netmcore_condition]
A special kind of wait_entry for intergration into an event loop
wait_id [Unixqueue]
A wait identifier is used to distinguish between several timers, see type operation.
wait_set [Netmcore_condition]
A set of wait_entry, for easier management.
watched_subprocess [Netsys_posix]
wd_spec [Netsys_posix]
with_cursor_fun [Netconversion]
with_fun [Netstring_tstring]
A polymorphic function for strings
workaround [Netcgi1_compat.Netcgi_env]
The Work_around_ part has been dropped as it is clear at the spot of use.
write_common [Netfs]
The intersection of write_flag and write_file_flag
write_file_flag [Netfs]
write_file_flag [Nethttp_fs]
write_flag [Netfs]
write_flag [Nethttp_fs]
write_op [Netshm]

X
x509_private_key [Netsys_crypto_types.PUBKEY_CRYPTO]
(format,data), using the formats: "RSA", "DSA", "DH", "EC".
xdr_type [Netxdr]
This is the validated version of xdr_type_term.
xdr_type_system [Netxdr]
A validated type system.
xdr_type_term [Netxdr]
xdr_type_term_system [Netxdr]
Bind names to types.
xdr_value [Netxdr]
xdr_value_version [Netxdr]
Selects which version of xdr_value is returned by unpack_xdr_value.
xmap_value [Nethtml]
ocamlnet-4.1.2/doc/html-main/Netmcore_sem.html0000644000175000017500000005117012731530354017714 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_sem

Module Netmcore_sem

module Netmcore_sem: sig .. end
Semaphores


Semaphores are here defined as values that reside in shared heaps (Netmcore_heap), for example in the header field of Netmcore_array or somewhere else in heap-allocated data structures.

In order to ensure that the semaphore is in the heap, the special function create must be used to initialize it there. As create requires a mutator as argument, this is only possible by calling create from the callback of Netmcore_heap.modify.

Semaphores are special values, and cannot be copied or moved.

Note that Netsys_posix provides wrappers for direct use of the semaphore functionality of the OS. These wrappers, however, cannot be used together with heaps, because semaphores are there represented as bigarrays, which cannot be pushed to heaps. This module here uses a trick to make it possible nevertheless.

type semaphore 
val dummy : unit -> semaphore
A dummy semaphore is non-functional, but can be used to put something into semaphore-typed variables
val create : Netmcore_heap.mutator -> int -> semaphore
create m value: Creates a semaphore with initial value, and pushes it to the heap, using the mutator m.

After being pushed to the heap, the semaphore can be used. It is nonsense to copy it outside the heap.

val destroy : semaphore -> unit
Destroys the semaphore
val getvalue : semaphore -> int
Returns the value of the semaphore
val post : semaphore -> unit
Increments the semaphore by one, and notifies one of the waiting processes.
val wait : semaphore -> Netsys_posix.sem_wait_behavior -> unit
Decrements the semaphore by one. Semaphores cannot become negative. If the semaphore is already 0, the wait behavior defines how to go on:
  • Netsys_posix.SEM_WAIT_BLOCK: Wait until the semaphore is posted
  • Netsys_posix.SEM_WAIT_NONBLOCK: Raise EAGAIN
Waiting is restarted after running a signal handler.
ocamlnet-4.1.2/doc/html-main/Uq_engines.async_in_channel_engine-c.html0000644000175000017500000004320712731530354024432 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_engines.async_in_channel_engine

Class type Uq_engines.async_in_channel_engine

class type async_in_channel_engine = object .. end
Inherits
ocamlnet-4.1.2/doc/html-main/type_Netmech_scram_sasl.SHA256_PLUS.html0000644000175000017500000004057312731530354023646 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmech_scram_sasl.SHA256_PLUS PROFILEocamlnet-4.1.2/doc/html-main/Netmcore_camlbox.html0000644000175000017500000004675412731530354020571 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netmcore_camlbox

Module Netmcore_camlbox

module Netmcore_camlbox: sig .. end
Camlboxes for use in netmulticore programs

val create_camlbox : string -> int -> int -> 'a Netcamlbox.camlbox * Netmcore.res_id
create_camlbox prefix n size: Creates a new camlbox with a unique name derived from prefix. prefix must not contain any slahes. The box can have up to n messages of size bytes.

The returned camlbox can receive messages. It is only meaningful in the process that created it, and only this process can receive messages.

Other processes can send messages to this box. They first have to look up the sender object via lookup_camlbox_sender below.

It is suggested that the result of create_camlbox is immediately coerced to the right type t, e.g.

        let box = (create_camlbox prefix n size : t camlbox * res_id)
      
as this ensures type safety for all following operations.
val lookup_camlbox_address : Netmcore.res_id -> Netcamlbox.camlbox_address
Returns the address of the camlbox identified by this resource ID
val lookup_camlbox_sender : Netmcore.res_id -> 'a Netcamlbox.camlbox_sender
lookup_camlbox_sender res_id: Returns the sender object of the camlbox identified by this resource ID

It is suggested that the result of lookup_camlbox_sender is immediately coerced to the right type t, e.g.

        let box = (lookup_camlbox_sender id : t camlbox_sender)
      
as this ensures type safety for all following operations.
ocamlnet-4.1.2/doc/html-main/Netdate.html0000644000175000017500000013276612731530354016673 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netdate

Module Netdate

module Netdate: sig .. end
Support for common date/time parsing and formatting. Many routines refer to the epoch, which for Unix is 00:00:00 UTC, January 1, 1970. Timestamps given as "seconds since the epoch" ignore leap seconds.

type t = {
   year : int; (*
complete year
*)
   month : int; (*
1..12
*)
   day : int; (*
1..31
*)
   hour : int; (*
0..23
*)
   minute : int; (*
0..59
*)
   second : int; (*
0..60 (60=leapsecond)
*)
   nanos : int; (*
nanoseconds, new since Ocamlnet-3.5
*)
   zone : int; (*
in minutes; 60 = UTC+0100
*)
   week_day : int; (*
0 = sunday; -1 if not given
*)
}
val localzone : int
The offset in minutes for the local time zone from the UTC. This is the zone from the time when the program was started. For long-running programs, it is possible that the zone changes when daylight savings become effective or non-effective.
val localzone_nodst : int
Returns the offset for the local time zone for the case that daylight savings are not effective.
val get_localzone : unit -> int
Retrieves the current offset for the local time zone, taking daylight savings into account.
val create : ?localzone:bool -> ?zone:int -> ?nanos:int -> float -> t
Convert the time (seconds since the epoch) to a date/time record

The nanos are added to the float as nanoseconds.

If zone is set this zone is taken. Otherwise, if localzone is set, the local timezone is used that is valid at the requested time. Otherwise, UTC is used.

Note that create ~localzone:true t is different from create ~zone:(get_localzone()) t because the latter assumes the timezone that is in effect when the function is called, and not the timezone at the time t.

type localization = {
   full_day_names : string array; (*
Element k contains the name of the week day k (0=Sunday)
*)
   abbr_day_names : string array; (*
Element k contains the abbreviated name of the week day k (0=Sunday)
*)
   parsed_day_names : string list array; (*
Element k contains a list of all possible names of the week day k. The list includes full and abbreviated names, but can also contain any other allowed name (aliases). The names here are in lowercase characters.
*)
   full_month_names : string array; (*
Element k contains the name of the month day k (0=January)
*)
   abbr_month_names : string array; (*
Element k contains the abbreviated name of the month day k (0=January)
*)
   parsed_month_names : string list array; (*
Element k contains a list of all possible names of the month k. The list includes full and abbreviated names, but can also contain any other allowed name (aliases). The names here are in lowercase characters.
*)
   timezone_names : (string * int * bool) list; (*
A list of pairs (name,offset,isdst) of timezones. The offset is in minutes.
*)
   am_particle : string; (*
A particle for "AM"
*)
   pm_particle : string; (*
A particle for "PM"
*)
   d_format : string; (*
Format string for date according to the locale
*)
   t_format : string; (*
Format string for time according to the locale
*)
   d_t_format : string; (*
Format string for date and time according to the locale
*)
   t_format_ampm : string; (*
Format string for time, using am and pm, according to the locale
*)
   char_encoding : string; (*
The character encoding of this locale
*)
}
type compiled_localization 
val posix_l9n : localization
The standard POSIX localization (English names)
val l9n_from_locale : string -> localization
Retrieves the localization from the passed locale (use "" for the standard locale). Timezone names are not provided by the locale

This function is not available on Windows (the POSIX localization is always returned).

val compile_l9n : localization -> compiled_localization
Preprocess the localization data for faster parsing and printing
val parse : ?localzone:bool ->
?zone:int -> ?l9n:compiled_localization -> string -> t
Parse a string and return a date/time record.

The following particles are recognized (by example):

  • Date: 1971/06/22
  • Date: 06/22/1971
  • Date: 1971-06-22
  • Date: 22-June-1971
  • Date: 22.06.1971
  • Date: June 22, 1971
  • Date: 22 June 1971
  • Date (2 digit year): 06/22/71
  • Date (2 digit year): 22.06.71
  • Date (2 digit year): 71-06-22
  • Date (2 digit year): 22-June-71
  • Month names (June, Jun)
  • Weekday names (Monday, Mon)
  • Time: 14:55
  • Time: 14:55:28
  • Time: 14:55:28.6754 (the fractional part is not returned)
  • Time may be preceded by T
  • Time zone: identifiers like UTC, CET, or Z
  • Time zone: +01:00, -01:00, only following time
  • Time zone: +0100, -0100, only following time
Years must have 2 or 4 digits. 2-digit years >= 70 are interpreted as 1900+x. 2-digit years < 70 are interpreted as 2000+x. Support for 2-digit years will be removed in a future version of Ocamlnet. (Support for 3-digit years is already removed in Ocamlnet 3.0.)

The names of months and weekdays are recognized that are configured with the l9n argument. By default, English names are recognized.

A date must be given. Time, time zones, and weekdays are optional. A missing time is reported as "00:00:00". A missing weekday is reported by setting week_day=(-1). A missing time zone is reported by setting zone to the passed default (which is determined from the zone and localzone arguments as for create).

It is not checked whether the parsed numbers make sense (e.g. whether months are between 1 and 12).

Date/time strings as defined in RFC 3339 are supported since Ocamlnet 3.0.

val since_epoch : t -> float
Convert a date/time record into the time (seconds since the epoch), rounded down to the next integral number.
val since_epoch_timespec : t -> float * int
Returns the seconds since the epoch as pair (seconds,nanos)
val since_epoch_approx : t -> float
Same, but the nanos are added to the seconds. The precision of floats is not sufficient to represent this precisely, so the result is only an approximation.
val week_day : t -> int
Returns the week day. If the week_day field is (-1) the week day is computed.
val year_day : t -> int
Returns the year day (range 0 to 365)
val iso8601_week_pair : t -> int * int
Returns (week_number, year) for the ISO-8601 definition of weeks. The week starts with Monday, and has numbers 1-53. A week is considered to be part of the year into which four or more days fall.
val parse_epoch : ?l9n:compiled_localization ->
?localzone:bool -> ?zone:int -> string -> float
Parse a string and return the time (integral seconds since the epoch)
val parse_epoch_timespec : ?l9n:compiled_localization ->
?localzone:bool -> ?zone:int -> string -> float * int
Parse a string and return the time (seconds and nanos since the epoch)
val parse_epoch_approx : ?l9n:compiled_localization ->
?localzone:bool -> ?zone:int -> string -> float
Parse a string and return the time (approximate seconds since the epoch)
val format_to : ?l9n:compiled_localization ->
Netchannels.out_obj_channel -> fmt:string -> t -> unit
Format a date/time record according to the format string and outputs the resulting string to the channel.

The format string consists of zero or more conversion specifications and ordinary characters. All ordinary characters are output directly to the channel. A conversion specification consists of the '%' character and one other character.

The conversion specifications are:

  • %A: full weekday name.
  • %a: abbreviated weekday name.
  • %B: full month name.
  • %b: abbreviated month name.
  • %C: (year / 100) as an integer; single digits are preceded by a zero.
  • %c: the preferred date+time representation of l9n
  • %D: equivalent to "%m/%d/%y".
  • %d: day of the month as an integer (01-31); single digits are preceded by a zero.
  • %e: day of the month as an integer (1-31).
  • %F: equivalent to "%Y-%m-%d" (ISO 8601)
  • %G: the year of the week according to the ISO-8601 week definition
  • %g: same as %G but uses a two-digit year
  • %H: hour (24-hour clock) as an integer (00-23).
  • %h: the same as %b.
  • %I: hour (12-hour clock) as an integer (01-12).
  • %j: day of the year as an integer (001-366).
  • %k: hour (24-hour clock) as an integer (0-23); single digits are preceded by a blank.
  • %l: hour (12-hour clock) as an integer (1-12); single digits are preceded by a blank.
  • %M: minute as an integer (00-59).
  • %m: month as an integer (01-12).
  • %n: a newline.
  • %p: "AM" or "PM" as defined in l9n, in uppercase
  • %P: "am" or "pm" as defined in l9n, in lowercase
  • %R: equivalent to "%H:%M".
  • %r: the time in am/pm notation according to l9n
  • %S: second as an integer (00-60). This format accepts a precision argument, e.g. %.3S to print the second with three digits after the dot.
  • %s: number of seconds since the epoch
  • %T: equivalent to "%H:%M:%S".
  • %t: a tab.
  • %U: week number of the year (Sunday as the first day of the week) as an integer (00-53).
  • %u weekday (Monday as the first day of the week) as an integer (1-7).
  • %V: week number of the year (ISO-8601 definition, use together with %G or %g
  • %W: week number of the year (Monday as the first day of the week) as an integer (00-53).
  • %w: weekday (Sunday as the first day of the week) as an integer (0-6).
  • %X: representation of the time according to l9n
  • %x: representation of the date according to l9n
  • %Y: year with century as an integer.
  • %y: year without century as an integer (00-99).
  • %z: time zone offset from UTC; a leading plus sign stands for east of UTC, a minus sign for west of UTC, hours and minutes follow with two digits each and no delimiter between them (common form for RFC 822 date headers).
  • %Z: same as %z
  • %:z: time zone with colon, e.g. +05:00 (new since Ocamlnet 3)
  • %%: a `%' character.
If l9n is not passed, the default is the POSIX localization (English names).
val format : ?l9n:compiled_localization -> fmt:string -> t -> string
Format a date/time record as a string
val mk_date : ?localzone:bool -> ?zone:int -> ?nanos:int -> fmt:string -> float -> string
Format the seconds (plus nanos if present) as a string
val mk_mail_date : ?localzone:bool -> ?zone:int -> float -> string
Convert the time (seconds since the epoch) to a date string that conforms to RFC 1123 (which updates RFC 822).

Example: "Sun, 06 Nov 1994 08:49:37 -0500".

val mk_usenet_date : ?localzone:bool -> ?zone:int -> float -> string
Convert the time (seconds since the epoch) to a date string that conforms to RFC 1036 (which obsoletes RFC 850).

Example: "Sunday, 06-Nov-94 08:49:37 -0500".

Note that this format has only two digits for the year.

val mk_internet_date : ?localzone:bool -> ?zone:int -> ?digits:int -> float -> string
Convert the time (seconds since the epoch) to a date string that conforms to RFC 3339. This is the most modern format, and should be used if permitted by the network protocol. Pass in digits the number of digits for the fractional part of seconds.

Example: "1996-12-19T16:39:57.89-08:00".

ocamlnet-4.1.2/doc/html-main/Netplex_types.processor_factory-c.html0000644000175000017500000004332712731530354024131 0ustar gerdgerd Ocamlnet 4 Reference Manual : Netplex_types.processor_factory

Class type Netplex_types.processor_factory

class type processor_factory = object .. end

method name : string
method create_processor : controller_config ->
config_file -> address -> processor
ocamlnet-4.1.2/doc/html-main/type_Uq_client.html0000644000175000017500000005655612731530354020275 0ustar gerdgerd Ocamlnet 4 Reference Manual : Uq_client sig
  type inetspec =
      [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
      | `Sock_inet_byname of Unix.socket_type * string * int ]
  type sockspec =
      [ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
      | `Sock_inet_byname of Unix.socket_type * string * int
      | `Sock_unix of Unix.socket_type * string ]
  val sockspec_of_sockaddr :
    Unix.socket_type -> Unix.sockaddr -> Uq_client.sockspec
  val sockspec_of_socksymbol :
    Unix.socket_type -> Netsockaddr.socksymbol -> Uq_client.sockspec
  type connect_address =
      [ `Command of string * (int -> Unixqueue.event_system -> unit)
      | `Socket of Uq_client.sockspec * Uq_client.connect_options
      | `W32_pipe of Netsys_win32.pipe_mode * string ]
  and connect_options =
    Uq_engines.connect_options = {
    conn_bind : Uq_client.sockspec option;
  }
  val default_connect_options : Uq_client.connect_options
  type connect_status =
      [ `Command of Unix.file_descr * int
      | `Socket of Unix.file_descr * Uq_client.sockspec
      | `W32_pipe of Unix.file_descr ]
  val client_endpoint : Uq_client.connect_status -> Unix.file_descr
  val client_channel :
    Uq_engines.connect_status -> float -> Netchannels.raw_io_channel
  class type client_endpoint_connector =
    object
      method connect :
        Uq_client.connect_address ->
        Unixqueue.event_system -> Uq_client.connect_status Uq_engines.engine
    end
  val connect_e :
    ?proxy:#Uq_engines.client_endpoint_connector ->
    Uq_engines.connect_address ->
    Unixqueue.event_system -> Uq_engines.connect_status Uq_engines.engine
  val connect :
    ?proxy:#Uq_engines.client_endpoint_connector ->
    Uq_engines.connect_address -> float -> Uq_engines.connect_status
end
ocamlnet-4.1.2/RELNOTES0000644000175000017500000000362312731530350013125 0ustar gerdgerd---------------------------------------------------------------------- Intro ---------------------------------------------------------------------- These are release notes for ocamlnet-3.0. Major changes include: - Port to Win32 - The new Rpc_proxy layer - Netplex has been extended (Netplex_sharedvar etc.) - New implementation of the Shell library for starting subprocesses - Uniform debugging with Netlog.Debug - Exception printers (Netexn) - Coordination of signal handling in Netsys_signal - New foundation for Unixqueue via pollsets - Extended Unixqueue engines (e.g. Uq_io) - More system calls in netsys - Camlboxes as an efficient way of message passing between processes - The netcgi1 library has been dropped in favor of netcgi2 Also, there are lots of smaller improvements and bug fixes. ---------------------------------------------------------------------- Known Problems ---------------------------------------------------------------------- There are known problems in this preview release: - The port to Win32 is incomplete and still alpha quality - Sometimes, DNS errors are just reported by the exception Not_found - In netcgi2-plex, the "mount_dir" and "mount_at" options are not yet implemented. - In netclient, aggressive caching of HTTP connections is still buggy. Do not use this option (by default, it is not enabled). - The FTP client is still incomplete. ---------------------------------------------------------------------- Resources ---------------------------------------------------------------------- The current development version is available in Subversion: https://godirepo.camlcity.org/svn/lib-ocamlnet2 Note that the ocamlnet file tree in Sourceforge refers to ocamlnet-1 only. There is a mailing list for Ocamlnet development: http://sourceforge.net/mail/?group_id=19774 In case of problems, you can also contact me directly: Gerd Stolpmann ocamlnet-4.1.2/src/0000755000175000017500000000000012731530351012533 5ustar gerdgerdocamlnet-4.1.2/src/equeue-gtk2/0000755000175000017500000000000012731530351014671 5ustar gerdgerdocamlnet-4.1.2/src/equeue-gtk2/META.in0000644000175000017500000000036512731530351015753 0ustar gerdgerdversion = "@VERSION@" description = "Ocamlnet - Event queues, integrated into GTK2 event loop" requires = "unix equeue lablgtk2" archive(byte) = "equeue_gtk2.cma" archive(native) = "equeue_gtk2.cmxa" archive(native,gprof) = "equeue_gtk2.p.cmxa" ocamlnet-4.1.2/src/equeue-gtk2/Makefile.pre0000644000175000017500000000056712731530351017126 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PRE = 1 PKGNAME = equeue-gtk2 GENERATE = META NODEP = @true include ./Makefile.gtk include $(TOP_DIR)/Makefile.rules # Do not include that in the clean list because these symlinks are # created by "configure". # CLEAN_LIST += uq_gtk.ml uq_gtk.mli Makefile distclean:: rm -f Makefile uq_gtk.ml uq_gtk.mli uq_gtk_helper.ml ocamlnet-4.1.2/src/equeue-gtk2/Makefile.gtk0000644000175000017500000000022112731530351017110 0ustar gerdgerd# Selects the gtk version: GTK_PKG = lablgtk2 GTK_VERSION = GTK2 ARCHIVE = equeue_gtk2 FL_NAME = equeue-gtk2 GTK_DEFINES += $(GTK_EXTRA_DEFINES) ocamlnet-4.1.2/src/netgss-system/0000755000175000017500000000000012731530351015360 5ustar gerdgerdocamlnet-4.1.2/src/netgss-system/Makefile0000644000175000017500000000165012731530351017022 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf # include Makefile.conf PKGNAME = netgss-system OBJECTS = netgss_bindings.cmo netgss_util.cmo netgss.cmo COBJECTS = netgss_bindings_stubs.o DOBJECTS = netgss_bindings.mli netgss.mli LINK_OPTIONS = $(NETGSS_LINK_OPTIONS) #LINK_OPTIONS = -lkrb5 CC_OPTIONS = $(NETGSS_CFLAGS) CC_OPTIONS_FOR_netgss_bindings_stubs.c = -ccopt -Wno-unused-function \ -ccopt -DNETGSS_VARIANT_"$(NETGSS_VARIANT)" INCLUDES = $(INC_NETSYS) $(INC_NETSTRING) OCAMLC_OPTIONS += $(STRING_OPTS) OCAMLOPT_OPTIONS += $(STRING_OPTS) PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" DOC_IGNORABLE = true include $(TOP_DIR)/Makefile.rules .PHONY: cobjects cobjects: $(COBJECTS) netgss_bindings.ml: done_reconfigure @: netgss_bindings.mli: done_reconfigure @: netgss_bindings_stubs.c: done_reconfigure @: done_reconfigure: gssapi.descr gssapi.c gssapi.ml gssapi.mli ./reconfigure include depend ocamlnet-4.1.2/src/netgss-system/configure0000755000175000017500000000600512731530351017270 0ustar gerdgerd#! /bin/sh # Env: # GSSAPI_CFLAGS # GSSAPI_LIBS have_gssapi=0 stdlib=`ocamlc -where` rm -f config.h config.sh config.mk ulimit -c 0 # no coredumps compiler="ocamlc -custom" if ocamlopt; then compiler=ocamlopt; fi log="config.log" rm -f $log touch $log out="config.h" rm -f $out touch $out mkdir -p testdir ###################################################################### # Programs linked with ocamlc have more libraries linked in by default. # Because of this, we use ocamlopt if available. call_ocamlc () { echo '$' $compiler -ccopt "$GSSAPI_CFLAGS" -cclib "$GSSAPI_LIBS" "$@" >>$log ( cd testdir; $compiler -ccopt "$GSSAPI_CFLAGS" -cclib "$GSSAPI_LIBS" "$@" ) >>$log 2>&1 return $? } check_fun() { macro="$1" fun="$2" } ###################################################################### check_gssapi() { fun=gss_init_sec_context echo "# FUN $fun" >> $log cat <testdir/main.ml external test : unit -> unit = "do_test" let () = test() EOF cat <testdir/test.c #ifdef __APPLE__ #include #else #include #endif #include "caml/mlvalues.h" value do_test (value dummy) { (void) & $fun; return 0; } EOF if call_ocamlc -o test test.c main.ml; then have_gssapi=1 variant="INCLUDE_GSSAPI" else have_gssapi=0 fi } check_shishi() { fun=gss_init_sec_context echo "# FUN $fun" >> $log cat <testdir/main.ml let () = () EOF cat <testdir/test.c #include int main (int argc, char *argv[], char *envp[]) { (void) & $fun; return 0; } EOF if call_ocamlc -o test test.c main.ml; then have_gssapi=1 variant="INCLUDE_GSS" else have_gssapi=0 fi } printf "Checking for GSSAPI/Kerberos... " if [ -n "$GSSAPI_LIBS" -o -n "$GSSAPI_CFLAGS" ]; then check_gssapi if [ $have_gssapi -eq 0 ]; then check_shishi fi else case `uname -s` in Darwin) GSSAPI_LIBS="-framework GSS" GSSAPI_CFLAGS="" check_gssapi ;; *) for lib in -lgssglue -lgssapi_krb5 -lgssapi; do GSSAPI_LIBS="$lib" check_gssapi if [ $have_gssapi -gt 0 ]; then break; fi done if [ $have_gssapi -eq 0 ]; then GSSAPI_LIBS="-lgss" check_shishi fi esac fi if [ $have_gssapi -gt 0 ]; then echo "found ($GSSAPI_LIBS)" else echo "not found" exit 1 fi if [ $have_gssapi -gt 0 ]; then # The vars in config.sh are picked up by reconfigure echo "GSSAPI_CFLAGS='$GSSAPI_CFLAGS'" >>config.sh echo "GSSAPI_LIBS='$GSSAPI_LIBS'" >>config.sh echo "GSSAPI_VARIANT=$variant" >>config.sh # The vars in config.mk are appended to Makefile.conf echo "# GSSAPI" >> config.mk echo "NETGSS_CFLAGS = $GSSAPI_CFLAGS" >>config.mk echo "NETGSS_LINK_OPTIONS = $GSSAPI_LIBS" >> config.mk echo "NETGSS_VARIANT = $variant" >>config.mk ./reconfigure fi ocamlnet-4.1.2/src/netgss-system/gssapi.ml0000644000175000017500000000435412731530351017206 0ustar gerdgerd(* This file is included into netgss_bindings.ml *) exception Null_pointer type memory = (char,Bigarray.int8_unsigned_elt,Bigarray.c_layout) Bigarray.Array1.t external buffer_of_string : string -> int -> int -> gss_buffer_t = "netgss_buffer_of_string" external buffer_of_bytes : Bytes.t -> int -> int -> gss_buffer_t = "netgss_buffer_of_string" external buffer_of_memory : memory -> gss_buffer_t = "netgss_buffer_of_memory" external string_of_buffer : gss_buffer_t -> string = "netgss_string_of_buffer" external bytes_of_buffer : gss_buffer_t -> Bytes.t = "netgss_string_of_buffer" external netgss_memory_of_buffer : gss_buffer_t -> memory = "netgss_memory_of_buffer" let hide_reference x _ = x := None let memory_of_buffer buf = let buf_opt = ref (Some buf) in let finalizer = hide_reference buf_opt in let m = try netgss_memory_of_buffer buf with Null_pointer -> Bigarray.Array1.create Bigarray.char Bigarray.c_layout 0 in Gc.finalise finalizer m; m external release_buffer : gss_buffer_t -> unit = "netgss_release_buffer" external oid_of_der : string -> gss_OID = "netgss_oid_of_string" external der_of_oid : gss_OID -> string = "netgss_string_of_oid" external array_of_oid_set : gss_OID_set -> gss_OID array = "netgss_array_of_oid_set" external oid_set_of_array : gss_OID array -> gss_OID_set = "netgss_oid_set_of_array" external map_cb : int -> string -> int -> string -> string -> gss_channel_bindings_t = "netgss_map_cb" external no_channel_bindings : unit -> gss_channel_bindings_t = "netgss_no_cb" external no_context : unit -> gss_ctx_id_t = "netgss_no_ctx" external is_no_context : gss_ctx_id_t -> bool = "netgss_is_no_ctx" external no_credential : unit -> gss_cred_id_t = "netgss_no_cred" external is_no_credential : gss_cred_id_t -> bool = "netgss_is_no_cred" external no_name : unit -> gss_name_t = "netgss_no_name" external is_no_name : gss_name_t -> bool = "netgss_is_no_name" external gss_indefinite : unit -> int32 = "netgss_indefinite" external no_oid : unit -> gss_OID = "netgss_no_oid" external no_oid_set : unit -> gss_OID_set = "netgss_no_oid_set" let () = Callback.register_exception "Netgss_bindings.Null_pointer" Null_pointer ocamlnet-4.1.2/src/netgss-system/reconfigure0000755000175000017500000000466112731530351017625 0ustar gerdgerd#! /bin/sh # Env: # GSSAPI_CFLAGS # GSSAPI_LIBS if [ -f config.sh ]; then # configure wrote the env into this file: . ./config.sh export GSSAPI_CFLAGS GSSAPI_LIBS fi stdlib=`ocamlc -where` rm -f config.h ulimit -c 0 # no coredumps compiler="ocamlc -custom" if ocamlopt; then compiler=ocamlopt; fi log=`pwd`/"config.log" rm -f $log touch $log out="config.h" rm -f $out touch $out mkdir -p testdir ###################################################################### # Programs linked with ocamlc have more libraries linked in by default. # Because of this, we use ocamlopt if available. call_ocamlc () { echo '$' $compiler -ccopt "$GSSAPI_CFLAGS" -cclib "$GSSAPI_LIBS" "$@" >>$log ( cd testdir; $compiler -ccopt "$GSSAPI_CFLAGS" -cclib "$GSSAPI_LIBS" "$@" ) >>$log 2>&1 return $? } init_header() { echo "Checking presence of $1" echo "# HEADER $1" >> $log cat <testdir/test.c #include #include <$1> EOF call_ocamlc -c test.c } check_enum () { macro="$1" enum="$2" echo "Checking enum $enum" echo "# ENUM $enum" >> $log cat <testdir/test.c #include $add_include int main (int argc, char *argv[], char *envp[]) { int n; n = $enum; return 0; } EOF if call_ocamlc -c test.c; then echo "#define $macro" >>$out else echo "#undef $macro" >>$out fi } check_fun() { macro="$1" fun="$2" echo "Checking function $fun" echo "# FUN $fun" >> $log cat <testdir/main.ml let () = () EOF cat <testdir/test.c #include $add_include int main (int argc, char *argv[], char *envp[]) { (void) & $fun; return 0; } EOF if call_ocamlc -o test test.c main.ml; then echo "#define $macro" >>$out else echo "#undef $macro" >>$out fi } check_type() { macro="$1" ty="$2" echo "Checking type $ty" echo "# TYPE $ty" >> $log cat <testdir/test.c #include $add_include int main (int argc, char *argv[], char *envp[]) { $ty x; return 0; } EOF if call_ocamlc -c test.c; then echo "#define $macro" >>$out else echo "#undef $macro" >>$out fi } ###################################################################### echo "Generating stubs" rm -f config_checks.sh echo "$ ocaml -I ../../tools gssapi.descr" >>$log ocaml -I ../../tools gssapi.descr || exit 1 . ./config_checks.sh touch done_reconfigure ocamlnet-4.1.2/src/netgss-system/netgss_util.ml0000644000175000017500000001606312731530351020260 0ustar gerdgerd(* $Id$ *) (* Utilities for the generated object encapsulation *) open Netsys_gssapi open Netgss_bindings let identity x = x let _OM_uint32_of_int32 = identity let _int32_of_OM_uint32 = identity let calling_errors = [| `None; `Inaccessible_read; `Inaccessible_write; `Bad_structure |] let routine_errors = [| `None; `Bad_mech; `Bad_name; `Bad_nametype; `Bad_bindings; `Bad_status; `Bad_mic; `No_cred; `No_context; `Defective_token; `Defective_credential; `Credentials_expired; `Context_expired; `Failure; `Bad_QOP; `Unauthorized; `Unavailable; `Duplicate_element; `Name_not_mn; |] let suppl_status_flags = [| `Continue_needed; `Duplicate_token; `Old_token; `Unseq_token; `Gap_token; |] let decode_status n : major_status = let bits_calling_error = Int32.to_int(Int32.shift_right_logical n 24) in let bits_routine_error = Int32.to_int(Int32.logand (Int32.shift_right_logical n 16) 0xffl) in let bits_suppl_info = Int32.to_int(Int32.logand n 0xffffl) in try if bits_calling_error >= Array.length calling_errors then raise Not_found; if bits_routine_error >= Array.length routine_errors then raise Not_found; let suppl_info, _ = Array.fold_left (fun (l, k) flag -> let is_set = (1 lsl k) land bits_suppl_info <> 0 in if is_set then (flag :: l, k+1) else (l, k+1) ) ([], 0) suppl_status_flags in (calling_errors.(bits_calling_error), routine_errors.(bits_routine_error), suppl_info ) with | Not_found -> failwith "Netgss.decode_status" let _gss_ctx_id_t_of_context_option = function | None -> no_context() | Some ctx -> ctx let _context_option_of_gss_ctx_id_t ctx = if is_no_context ctx then None else Some ctx let _gss_buffer_t_of_token s = buffer_of_string s 0 (String.length s) let _gss_buffer_t_of_token_option = function | Some s -> buffer_of_string s 0 (String.length s) | None -> buffer_of_string "" 0 0 (* should be ok for GSS_C_NO_BUFFER *) (* In the following, all *_of_gss_buffer_t functions are destructive, and release (if possible) the buffer arg. This is ok, because these buffer args are output buffers from GSSAPI. *) let _token_of_gss_buffer_t buf = let s = string_of_buffer buf in release_buffer buf; s let _gss_buffer_t_of_message (ml : Netxdr_mstring.mstring list) = match ml with | [] -> buffer_of_string "" 0 0 | [ m ] -> ( match m#preferred with | `Memory -> (* No copy in this case: buffer_of_memory takes the data area of mem2 as data area of the gss_buffer_t. It is ensured that mem2 cannot be collected before buf. *) let (mem1, pos) = m#as_memory in let mem2 = Bigarray.Array1.sub mem1 pos m#length in buffer_of_memory mem2 | `Bytes -> let (str, pos) = m#as_bytes in buffer_of_bytes str pos m#length ) | _ -> let len = Netxdr_mstring.length_mstrings ml in let mem = Bigarray.Array1.create Bigarray.char Bigarray.c_layout len in Netxdr_mstring.blit_mstrings_to_memory ml mem; buffer_of_memory mem let _message_of_gss_buffer_t pref_type buf = match pref_type with | `Memory -> let mem = memory_of_buffer buf in [ Netxdr_mstring.memory_to_mstring mem ] (* It is ok not to copy here, i.e. mem and buf share the same data area. buf will not be used for anything else after this call. Also, memory_of_buffer ensures that buf cannot be collected before mem (with a tricky finalizer). *) | `Bytes -> let str = bytes_of_buffer buf in release_buffer buf; [ Netxdr_mstring.bytes_to_mstring str ] let cb_typed_string = function | `Unspecified s -> (0, s) | `Local s -> (1, s) | `Inet addr -> (2, Netsys.protostring_of_inet_addr addr) | `Nulladdr -> (255, "") | `Other(n,s) -> (Int32.to_int n,s) (* FIXME *) let _gss_channel_bindings_t_of_cb_option cb_opt = match cb_opt with | None -> no_channel_bindings() | Some (i,a,data) -> let (i_ty, i_str) = cb_typed_string i in let (a_ty, a_str) = cb_typed_string a in map_cb i_ty i_str a_ty a_str data let _oid_of_gss_OID gss_oid = try let der = der_of_oid gss_oid in let p = ref 0 in Netgssapi_support.der_value_to_oid der p (String.length der) with Not_found -> [| |] let _gss_OID_of_oid oid = if oid = [| |] then no_oid() else let der = Netgssapi_support.oid_to_der_value oid in oid_of_der der let _oid_set_of_gss_OID_set gss_set = try let gss_oid_a = array_of_oid_set gss_set in let oid_a = Array.map _oid_of_gss_OID gss_oid_a in Array.to_list oid_a with Not_found -> [] let _gss_OID_set_of_oid_set set = let set_a = Array.of_list set in let gss_oid_a = Array.map _gss_OID_of_oid set_a in oid_set_of_array gss_oid_a let _time_of_OM_uint32 n = if n = gss_indefinite() then `Indefinite else (* be careful with negative values. In C, the numbers are unsigned *) if n >= 0l then `This (Int32.to_float n) else let offset = (-2.0) *. Int32.to_float Int32.min_int in `This (Int32.to_float n +. offset) let uint32_of_float t = if t >= Int32.to_float Int32.max_int +. 1.0 then let offset = (-2.0) *. Int32.to_float Int32.min_int in let t1 = t -. offset in let t2 = min t1 (Int32.to_float Int32.max_int) in Int32.of_float t2 else Int32.of_float(max t 0.0) let _OM_uint32_of_time = function | `Indefinite -> gss_indefinite() | `This t -> uint32_of_float t let _OM_uint32_of_time_opt = function | None -> 0l | Some t -> uint32_of_float t let _OM_uint32_of_wrap_size n = if n < 0 || Int64.of_int n > Int64.of_int32 Int32.max_int then failwith "Netgss: wrap size out of range"; Int32.of_int n let _wrap_size_of_OM_uint32 n = (* the output is normally smaller than the input *) if n < 0l || Int64.of_int32 n > Int64.of_int max_int then failwith "Netgss: wrap size out of range"; Int32.to_int n let _flags_of_req_flags flags = (flags : Netsys_gssapi.req_flag list :> flags) let gss_display_minor_status min_status mech_type = let out_major = ref 0l in let out_minor = ref 0l in let l = ref [] in let mctx = ref 0l in let cont = ref true in while !cont do let (major, minor, new_mctx, display_string) = Netgss_bindings.gss_display_status min_status `Mech_code mech_type !mctx in out_major := major; out_minor := minor; mctx := new_mctx; let success = Int32.logand major 0xffff0000l = 0l in if success then l := display_string :: !l; cont := !mctx <> 0l && success; done; let strings = List.map string_of_buffer (List.rev !l) in (!out_major, !out_minor, strings) ocamlnet-4.1.2/src/netgss-system/META.in0000644000175000017500000000027012731530351016435 0ustar gerdgerddescription = "Ocamlnet - GSSAPI bindings" requires = "unix,bigarray,netsys,netstring" version = "@VERSION@" archive(byte) = "netgss-system.cma" archive(native) = "netgss-system.cmxa" ocamlnet-4.1.2/src/netgss-system/Makefile.pre0000644000175000017500000000110312731530351017600 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PRE = 1 PKGNAME = netgss-system GENERATE = META netgss_bindings.ml netgss_bindings.mli \ netgss_bindings_stubs.c done_reconfigure include $(TOP_DIR)/Makefile.rules CLEAN_LIST += netgss_bindings.ml \ netgss_bindings.mli \ netgss_bindings_stubs.c \ done_reconfigure netgss_bindings.ml: done_reconfigure @: netgss_bindings.mli: done_reconfigure @: netgss_bindings_stubs.c: done_reconfigure @: done_reconfigure: gssapi.descr gssapi.c gssapi.ml gssapi.mli ./reconfigure ocamlnet-4.1.2/src/netgss-system/gssapi.c0000644000175000017500000002425712731530351017024 0ustar gerdgerd/* This file is included into netgss_bindings_stubs.c */ #ifdef __APPLE__ #include #else #ifdef NETGSS_VARIANT_INCLUDE_GSS #include #else #include #endif #endif /* In the following tag=0 means that the value was allocated by the GSSAPI provider, and needs to be deallocated by the special GSSAPI function for this purpose. tag=1 means that we allocated the value, and are also responsible for freeing it. tag=2 means something special. */ static value twrap_gss_buffer_t(long tag, gss_buffer_t buf); static value twrap_gss_OID(long tag, gss_OID oid); static value twrap_gss_OID_set(long tag, gss_OID_set set); static value wrap_gss_channel_bindings_t(gss_channel_bindings_t cb); static value wrap_gss_ctx_id_t(gss_ctx_id_t ctx); static value wrap_gss_cred_id_t(gss_cred_id_t cred); static value wrap_gss_name_t(gss_name_t name); static value wrap_gss_OID(gss_OID oid); static value wrap_gss_OID_set(gss_OID_set set); static gss_buffer_t unwrap_gss_buffer_t(value); static gss_OID unwrap_gss_OID(value); static gss_OID_set unwrap_gss_OID_set(value); static gss_ctx_id_t unwrap_gss_ctx_id_t(value); static gss_name_t unwrap_gss_name_t(value); static gss_cred_id_t unwrap_gss_cred_id_t(value); static long tag_gss_buffer_t(value); static void attach_gss_buffer_t(value, value); typedef OM_uint32 flags; typedef int status_type_t; #define raise_null_pointer netgss_null_pointer static void netgss_null_pointer(void) { caml_raise_constant(*caml_named_value ("Netgss_bindings.Null_pointer")); } static void netgss_free_buffer_contents(long tag, gss_buffer_t buf) { if (buf->value != NULL) { if (tag == 0) { OM_uint32 major, minor; major = gss_release_buffer(&minor, buf); if ((major & 0xffff0000) != 0) fprintf(stderr, "Netgss: error from gss_release_buffer\n"); } else { if (tag == 1) { stat_free(buf->value); } } } buf->value = NULL; buf->length = 0; } static void netgss_free_buffer(long tag, gss_buffer_t buf) { netgss_free_buffer_contents(tag, buf); /* The descriptor is always allocated by us: */ stat_free(buf); } static gss_buffer_t netgss_alloc_buffer(void) { gss_buffer_t buf; buf = (gss_buffer_t) stat_alloc(sizeof(gss_buffer_desc)); buf->value = NULL; buf->length = 0; return buf; } static void init_gss_buffer_t(gss_buffer_t *p) { gss_buffer_t buf; buf = netgss_alloc_buffer(); buf->length = 0; buf->value = NULL; *p = buf; } CAMLprim value netgss_release_buffer(value b) { gss_buffer_t buf; buf = unwrap_gss_buffer_t(b); netgss_free_buffer_contents(tag_gss_buffer_t(b), buf); return Val_unit; } CAMLprim value netgss_buffer_of_string(value s, value pos, value len) { gss_buffer_t buf; if (Long_val(len) < 0 || Long_val(pos) < 0 || Long_val(pos) > caml_string_length(s) - Long_val(len)) invalid_argument("buffer_of_string"); buf = netgss_alloc_buffer(); buf->length = Long_val(len); buf->value = stat_alloc(buf->length); memcpy(buf->value, String_val(s) + Long_val(pos), buf->length); return twrap_gss_buffer_t(1, buf); } CAMLprim value netgss_buffer_of_memory(value m) { value r; gss_buffer_t buf; buf = netgss_alloc_buffer(); buf->length = caml_ba_byte_size(Caml_ba_array_val(m)); buf->value = Caml_ba_data_val(m); r = twrap_gss_buffer_t(2, buf); attach_gss_buffer_t(r, m); return r; } CAMLprim value netgss_string_of_buffer(value b) { gss_buffer_t buf; value s; buf = unwrap_gss_buffer_t(b); if (buf->value == NULL) { s = caml_alloc_string(0); } else { s = caml_alloc_string(buf->length); memcpy(String_val(s), buf->value, buf->length); } return s; } CAMLprim value netgss_memory_of_buffer(value b) { gss_buffer_t buf; value m; buf = unwrap_gss_buffer_t(b); if (buf->value == NULL) netgss_null_pointer(); m = caml_ba_alloc_dims(CAML_BA_UINT8 | CAML_BA_C_LAYOUT, 1, buf->value, buf->length); return m; } static void netgss_free_oid(long tag, gss_OID buf) { if (tag == 0 || buf == GSS_C_NO_OID) { /* OIDs from the provider are to be considered as read-only */ } else { stat_free(buf->elements); stat_free(buf); } } static gss_OID netgss_alloc_oid(void) { return (gss_OID) stat_alloc(sizeof(gss_OID_desc)); } static gss_OID netgss_copy_oid(gss_OID buf) { gss_OID out; if (buf == GSS_C_NO_OID) { out = GSS_C_NO_OID; } else { out = netgss_alloc_oid(); out->length = buf->length; out->elements = stat_alloc(buf->length); memcpy(out->elements, buf->elements, buf->length); } return out; } CAMLprim value netgss_oid_of_string(value s) { gss_OID buf; buf = netgss_alloc_oid(); buf->length = caml_string_length(s); buf->elements = stat_alloc(buf->length); memcpy(buf->elements, String_val(s), buf->length); return twrap_gss_OID(1, buf); } CAMLprim value netgss_string_of_oid(value b) { gss_OID buf; value s; buf = unwrap_gss_OID(b); if (buf == GSS_C_NO_OID) caml_raise_not_found(); s = caml_alloc_string(buf->length); memcpy(String_val(s), buf->elements, buf->length); return s; } static void netgss_free_oid_set(long tag, gss_OID_set set) { if (tag == 0 || set == GSS_C_NO_OID_SET) { OM_uint32 major, minor; major = gss_release_oid_set(&minor, &set); if ((major & 0xffff0000) != 0) fprintf(stderr, "Netgss: error from gss_release_oid_set\n"); } else { size_t k; for (k=0; k < set->count; k++) { netgss_free_oid(1, set->elements+k); } stat_free(set->elements); stat_free(set); } } static gss_OID_set netgss_alloc_oid_set(void) { return (gss_OID_set) stat_alloc(sizeof(gss_OID_set_desc)); } CAMLprim value netgss_array_of_oid_set(value varg) { CAMLparam1(varg); CAMLlocal2(v1, v2); gss_OID_set set; size_t k, count; set = unwrap_gss_OID_set(varg); if (set == GSS_C_NO_OID_SET) count = 0; else count = set->count; /* no other way than to always copy the members */ v1 = caml_alloc(count, 0); for (k=0; kelements+k)); Store_field(v1, k, v2); } CAMLreturn(v1); } CAMLprim value netgss_oid_set_of_array(value varg) { gss_OID_set set; gss_OID buf; gss_OID *p; size_t k; value v1; if (Wosize_val(varg) == 0) return twrap_gss_OID_set(1, GSS_C_NO_OID_SET); set = netgss_alloc_oid_set(); set->count = Wosize_val(varg); set->elements = stat_alloc(sizeof(gss_OID) * set->count); for (k=0; kcount; k++) { v1 = Field(varg, k); buf = unwrap_gss_OID(v1); p = &(set->elements) + k; *p = netgss_copy_oid(buf); } return twrap_gss_OID_set(1, set); } static void netgss_free_cred_id(long tag, gss_cred_id_t x) { OM_uint32 major, minor; if (x != GSS_C_NO_CREDENTIAL) { major = gss_release_cred(&minor, &x); if ((major & 0xffff0000) != 0) fprintf(stderr, "Netgss: error from gss_release_cred\n"); } } static void netgss_free_ctx_id(long tag, gss_ctx_id_t x) { OM_uint32 major, minor; if (x != GSS_C_NO_CONTEXT) { major = gss_delete_sec_context(&minor, &x, GSS_C_NO_BUFFER); if ((major & 0xffff0000) != 0) fprintf(stderr, "Netgss: error from gss_delete_sec_context\n"); } } static void netgss_free_name(long tag, gss_name_t x) { OM_uint32 major, minor; if (x != GSS_C_NO_NAME) { major = gss_release_name(&minor, &x); if ((major & 0xffff0000) != 0) fprintf(stderr, "Netgss: error from gss_release_name\n"); } } CAMLprim value netgss_no_cb(value dummy) { return wrap_gss_channel_bindings_t(GSS_C_NO_CHANNEL_BINDINGS); } CAMLprim value netgss_map_cb(value iaddrty, value iaddr, value aaddrty, value aaddr, value data) { gss_channel_bindings_t cb; size_t iaddr_len, aaddr_len, data_len; iaddr_len = caml_string_length(iaddr); aaddr_len = caml_string_length(aaddr); data_len = caml_string_length(data); cb = (gss_channel_bindings_t) stat_alloc(sizeof(struct gss_channel_bindings_struct)); cb->initiator_addrtype = Int_val(iaddrty); cb->initiator_address.length = iaddr_len; cb->initiator_address.value = stat_alloc(iaddr_len); memcpy(cb->initiator_address.value, String_val(iaddr), iaddr_len); cb->acceptor_addrtype = Int_val(aaddrty); cb->acceptor_address.length = aaddr_len; cb->acceptor_address.value = stat_alloc(aaddr_len); memcpy(cb->acceptor_address.value, String_val(aaddr), aaddr_len); cb->application_data.length = data_len; cb->application_data.value = stat_alloc(data_len); memcpy(cb->application_data.value, String_val(data), data_len); return wrap_gss_channel_bindings_t(cb); } CAMLprim value netgss_no_ctx(value dummy) { return wrap_gss_ctx_id_t(GSS_C_NO_CONTEXT); } CAMLprim value netgss_is_no_ctx(value context) { gss_ctx_id_t ctx; ctx = unwrap_gss_ctx_id_t(context); return Val_bool(ctx == GSS_C_NO_CONTEXT); } CAMLprim value netgss_no_cred(value dummy) { return wrap_gss_cred_id_t(GSS_C_NO_CREDENTIAL); } CAMLprim value netgss_is_no_cred(value cred) { return Val_bool(unwrap_gss_cred_id_t(cred) == GSS_C_NO_CREDENTIAL); } CAMLprim value netgss_no_name(value dummy) { return wrap_gss_name_t(GSS_C_NO_NAME); } CAMLprim value netgss_is_no_name(value name) { return Val_bool(unwrap_gss_name_t(name) == GSS_C_NO_NAME); } CAMLprim value netgss_indefinite(value dummy) { return caml_copy_int32(GSS_C_INDEFINITE); } CAMLprim value netgss_no_oid(value dummy) { return wrap_gss_OID(GSS_C_NO_OID); } CAMLprim value netgss_no_oid_set(value dummy) { return wrap_gss_OID_set(GSS_C_NO_OID_SET); } static void netgss_free_cb(gss_channel_bindings_t x) { if (x != NULL) { stat_free(x->initiator_address.value); stat_free(x->acceptor_address.value); stat_free(x->application_data.value); } } ocamlnet-4.1.2/src/netgss-system/netgss.mli0000644000175000017500000000064612731530351017374 0ustar gerdgerd(* $Id$ *) (** This is the system-wide version of GSSAPI *) (** {b OPAM users}: Note that the OPAM package for OCamlnet does not build with GSSAPI support by default. The trigger for this is the presence of the [conf-gssapi] OPAM package, i.e. do [opam install conf-gssapi] to include the [netgss-system] library in a rebuild. *) module System : Netsys_gssapi.GSSAPI (** This is the system-wide version of GSSAPI *) ocamlnet-4.1.2/src/netgss-system/gssapi.mli0000644000175000017500000000221112731530351017345 0ustar gerdgerd(* This file is included into netgss_bindings.mli *) exception Null_pointer type memory = (char,Bigarray.int8_unsigned_elt,Bigarray.c_layout) Bigarray.Array1.t val buffer_of_string : string -> int -> int -> gss_buffer_t val buffer_of_bytes : Bytes.t -> int -> int -> gss_buffer_t val buffer_of_memory : memory -> gss_buffer_t val string_of_buffer : gss_buffer_t -> string val bytes_of_buffer : gss_buffer_t -> Bytes.t val memory_of_buffer : gss_buffer_t -> memory val release_buffer : gss_buffer_t -> unit val oid_of_der : string -> gss_OID val der_of_oid : gss_OID -> string val array_of_oid_set : gss_OID_set -> gss_OID array val oid_set_of_array : gss_OID array -> gss_OID_set val map_cb : int -> string -> int -> string -> string -> gss_channel_bindings_t val no_channel_bindings : unit -> gss_channel_bindings_t val no_context : unit -> gss_ctx_id_t val is_no_context : gss_ctx_id_t -> bool val no_credential : unit -> gss_cred_id_t val is_no_credential : gss_cred_id_t -> bool val no_name : unit -> gss_name_t val is_no_name : gss_name_t -> bool val no_oid : unit -> gss_OID val no_oid_set : unit -> gss_OID_set val gss_indefinite : unit -> int32 ocamlnet-4.1.2/src/netgss-system/gssapi.descr0000644000175000017500000005423412731530351017700 0ustar gerdgerd(* -*- tuareg -*- *) open Printf #use "stubgen.ml" let types = [ "gss_buffer_t", tagged_abstract_ptr "netgss_free_buffer"; "gss_OID", tagged_abstract_ptr ~nullok:true "netgss_free_oid"; "gss_OID_set", tagged_abstract_ptr ~nullok:true "netgss_free_oid_set"; "gss_cred_id_t", tagged_abstract_ptr ~nullok:true "netgss_free_cred_id"; "gss_ctx_id_t", tagged_abstract_ptr ~nullok:true ~gen_set:true "netgss_free_ctx_id"; "gss_name_t", tagged_abstract_ptr ~nullok:true "netgss_free_name"; "gss_channel_bindings_t", abstract_ptr ~nullok:true "netgss_free_cb"; "gss_cred_usage_t", `Enum [ "GSS_C_|BOTH"; "GSS_C_|INITIATE"; "GSS_C_|ACCEPT" ]; "flags", `Flags [ "GSS_C_|DELEG_FLAG"; "GSS_C_|MUTUAL_FLAG"; "GSS_C_|REPLAY_FLAG"; "GSS_C_|SEQUENCE_FLAG"; "GSS_C_|CONF_FLAG"; "GSS_C_|INTEG_FLAG"; "GSS_C_|ANON_FLAG"; "GSS_C_|PROT_READY_FLAG"; "GSS_C_|TRANS_FLAG"; ]; "gss_qop_t", `Enum [ "GSS_C_|QOP_DEFAULT" ]; "status_type_t", `Enum [ "GSS_C_|GSS_CODE"; "GSS_C_|MECH_CODE"; ]; ] (* OM_uint32: refer to this as "OM_uint32/int32" *) let standard ?(optional=false) ?(options=[]) decl = let (name, result, params) = parse decl in (name, params @ [ "result", (if result = "void" then `Return_ignore else `Return), result ], (if optional then [ `Optional ] else []) @ options ) let functions = [ standard ~options:[`Blocking] "OM_uint32/int32 \ gss_accept_sec_context( \ OUT OM_uint32/int32 minor_status, \ IN_OUT gss_ctx_id_t context, \ gss_cred_id_t acceptor_cred, \ gss_buffer_t input_token, \ gss_channel_bindings_t chan_bindings, \ OUT gss_name_t src_name, \ OUT gss_OID mech_type, \ OUT_NOPTR gss_buffer_t output_token, \ OUT flags ret_flags, \ OUT OM_uint32/int32 time_rec, \ OUT gss_cred_id_t delegated_cred)"; standard ~options:[`Blocking] "OM_uint32/int32 \ gss_acquire_cred( \ OUT OM_uint32/int32 minor_status, \ gss_name_t desired_name, \ OM_uint32/int32 time_req, \ gss_OID_set desired_mechs, \ gss_cred_usage_t cred_usage, \ OUT gss_cred_id_t cred, \ OUT gss_OID_set actual_mechs, \ OUT OM_uint32/int32 time_rec)"; standard ~options:[`Blocking] "OM_uint32/int32 \ gss_init_sec_context( \ OUT OM_uint32/int32 minor_status, \ gss_cred_id_t initiator_cred, \ IN_OUT gss_ctx_id_t context, \ gss_name_t target_name, \ gss_OID mech_type, \ flags req_flags, \ OM_uint32/int32 time_req, \ gss_channel_bindings_t chan_bindings, \ gss_buffer_t input_token, \ OUT gss_OID actual_mech_type, \ OUT_NOPTR gss_buffer_t output_token, \ OUT flags ret_flags, \ OUT OM_uint32/int32 time_rec)"; standard ~options:[`Blocking] "OM_uint32/int32 \ gss_process_context_token( \ OUT OM_uint32/int32 minor_status, \ gss_ctx_id_t context, \ gss_buffer_t token)"; standard "OM_uint32/int32 \ gss_context_time( \ OUT OM_uint32/int32 minor_status, \ gss_ctx_id_t context, \ OUT OM_uint32/int32 time_rec)"; standard ~options:[`Blocking] "OM_uint32/int32 \ gss_get_mic( \ OUT OM_uint32/int32 minor_status, \ gss_ctx_id_t context, \ OM_uint32/int32 qop_req, \ gss_buffer_t message, \ OUT_NOPTR gss_buffer_t msg_token)"; standard ~options:[`Blocking] "OM_uint32/int32 \ gss_verify_mic( \ OUT OM_uint32/int32 minor_status, \ gss_ctx_id_t context, \ gss_buffer_t message, \ gss_buffer_t token, \ OUT OM_uint32/int32 qop_state)"; standard ~options:[`Blocking] "OM_uint32/int32 \ gss_wrap( \ OUT OM_uint32/int32 minor_status, \ gss_ctx_id_t context, \ bool conf_req, \ OM_uint32/int32 qop_req, \ gss_buffer_t input_message, \ OUT bool conf_state, \ OUT_NOPTR gss_buffer_t output_message)"; standard ~options:[`Blocking] "OM_uint32/int32 \ gss_unwrap( \ OUT OM_uint32/int32 minor_status, \ gss_ctx_id_t context, \ gss_buffer_t input_message, \ OUT_NOPTR gss_buffer_t output_message, \ OUT bool conf_state, \ OUT OM_uint32/int32 qop_state)"; standard "OM_uint32/int32 \ gss_display_status( \ OUT OM_uint32/int32 minor_status, \ OM_uint32/int32 status_value, \ status_type_t status_type, \ gss_OID mech_type, \ IN_OUT OM_uint32/int32 message_context, \ OUT_NOPTR gss_buffer_t status_string)"; standard "OM_uint32/int32 \ gss_indicate_mechs( \ OUT OM_uint32/int32 minor_status, \ OUT gss_OID_set mech_set)"; standard "OM_uint32/int32 \ gss_compare_name( \ OUT OM_uint32/int32 minor_status, \ gss_name_t name1, \ gss_name_t name2, \ OUT bool name_equal)"; standard "OM_uint32/int32 \ gss_display_name( \ OUT OM_uint32/int32 minor_status, \ gss_name_t input_name, \ OUT_NOPTR gss_buffer_t output_name, \ OUT gss_OID output_name_type)"; standard "OM_uint32/int32 \ gss_import_name( \ OUT OM_uint32/int32 minor_status, \ gss_buffer_t input_name, \ gss_OID input_name_type, \ OUT gss_name_t output_name)"; standard "OM_uint32/int32 \ gss_inquire_cred( \ OUT OM_uint32/int32 minor_status, \ gss_cred_id_t cred, \ OUT gss_name_t name, \ OUT OM_uint32/int32 lifetime, \ OUT gss_cred_usage_t cred_usage, \ OUT gss_OID_set mechanisms)"; standard "OM_uint32/int32 \ gss_inquire_context( \ OUT OM_uint32/int32 minor_status, \ gss_ctx_id_t context, \ OUT gss_name_t src_name, \ OUT gss_name_t targ_name, \ OUT OM_uint32/int32 lifetime_req, \ OUT gss_OID mech_type, \ OUT flags ctx_flags, \ OUT bool locally_initiated, \ OUT bool is_open)"; standard "OM_uint32/int32 \ gss_wrap_size_limit( \ OUT OM_uint32/int32 minor_status, \ gss_ctx_id_t context, \ bool conf_req, \ OM_uint32/int32 qop_req, \ OM_uint32/int32 req_output_size, \ OUT OM_uint32/int32 max_input_size)"; standard ~options:[`Blocking] "OM_uint32/int32 \ gss_add_cred( \ OUT OM_uint32/int32 minor_status, \ gss_cred_id_t input_cred, \ gss_name_t desired_name, \ gss_OID desired_mech, \ gss_cred_usage_t cred_usage, \ OM_uint32/int32 initiator_time_req, \ OM_uint32/int32 acceptor_time_req, \ OUT gss_cred_id_t output_cred, \ OUT gss_OID_set actual_mechs, \ OUT OM_uint32/int32 initiator_time_rec, \ OUT OM_uint32/int32 acceptor_time_rec)"; standard "OM_uint32/int32 \ gss_inquire_cred_by_mech( \ OUT OM_uint32/int32 minor_status, \ gss_cred_id_t cred, \ gss_OID mech_type, \ OUT gss_name_t name, \ OUT OM_uint32/int32 initiator_lifetime, \ OUT OM_uint32/int32 acceptor_lifetime, \ OUT gss_cred_usage_t cred_usage)"; standard ~options: [ `Post "if (context__c == GSS_C_NO_CONTEXT) set_gss_ctx_id_t(context, GSS_C_NO_CONTEXT);"; ] "OM_uint32/int32 \ gss_export_sec_context( \ OUT OM_uint32/int32 minor_status, \ IN_PTR gss_ctx_id_t context, \ OUT_NOPTR gss_buffer_t interprocess_token)"; standard "OM_uint32/int32 \ gss_import_sec_context( \ OUT OM_uint32/int32 minor_status, \ gss_buffer_t interprocess_token, \ OUT gss_ctx_id_t context)"; standard "OM_uint32/int32 \ gss_inquire_names_for_mech( \ OUT OM_uint32/int32 minor_status, \ gss_OID mechanism, \ OUT gss_OID_set name_types)"; standard "OM_uint32/int32 \ gss_inquire_mechs_for_name( \ OUT OM_uint32/int32 minor_status, \ gss_name_t name, \ OUT gss_OID_set mech_types)"; standard "OM_uint32/int32 \ gss_export_name( \ OUT OM_uint32/int32 minor_status, \ gss_name_t name, \ OUT_NOPTR gss_buffer_t exported_name)"; standard "OM_uint32/int32 \ gss_duplicate_name( \ OUT OM_uint32/int32 minor_status, \ gss_name_t name, \ OUT gss_name_t dest_name)"; standard "OM_uint32/int32 \ gss_canonicalize_name( \ OUT OM_uint32/int32 minor_status, \ gss_name_t input_name, \ gss_OID mech_type, \ OUT gss_name_t output_name)"; standard ~options:[ `Pre "output_token__c = GSS_C_NO_BUFFER;"; `Post "if ((result__c & 0xffff0000) == 0) set_gss_ctx_id_t(context, GSS_C_NO_CONTEXT);"; ] "OM_uint32/int32 \ gss_delete_sec_context( \ OUT OM_uint32/int32 minor_status, \ IN_PTR gss_ctx_id_t context, \ IN_IGNORE gss_buffer_t output_token)"; ] let optional_types = [] let optional_functions = [] (* Generate the module Netgss_bindings *) let () = generate ~c_file:"gssapi.c" ~ml_file:"gssapi.ml" ~mli_file:"gssapi.mli" ~modname:"netgss_bindings" ~types ~functions ~optional_functions ~optional_types ~free: [] ~init: [ "gss_buffer_t" ] ~hashes:[] ~enum_of_string:[] () (* Generate the implementation of Netgss: *) let mapping = (* (c_type, fn_name, arg_name, ocaml_type). "*" is a wildcard *) [ "gss_buffer_t", "*", "message", "message"; "gss_buffer_t", "*", "input_message", "message"; "gss_buffer_t", "*", "output_message", "message"; "gss_buffer_t", "gss_init_sec_context", "input_token", "token_option"; "gss_buffer_t", "*", "*", "token"; "gss_ctx_id_t", "gss_accept_sec_context", "*", "context_option"; "gss_ctx_id_t", "gss_import_sec_context", "*", "context_option"; "gss_ctx_id_t", "gss_init_sec_context", "*", "context_option"; "flags", "gss_init_sec_context", "req_flags", "req_flags"; "gss_channel_bindings_t","*", "*", "cb_option"; "gss_OID", "*", "*", "oid"; "gss_OID_set", "*", "*", "oid_set"; "OM_uint32/int32", "gss_wrap_size_limit", "req_output_size", "wrap_size"; "OM_uint32/int32", "gss_wrap_size_limit", "max_input_size", "wrap_size"; "OM_uint32/int32", "gss_init_sec_context", "time_req", "time_opt"; "OM_uint32/int32", "*", "time_req", "time"; "OM_uint32/int32", "*", "initiator_time_req", "time"; "OM_uint32/int32", "*", "acceptor_time_req", "time"; "OM_uint32/int32", "*", "time_rec", "time"; "OM_uint32/int32", "*", "initiator_time_rec", "time"; "OM_uint32/int32", "*", "acceptor_time_rec", "time"; "OM_uint32/int32", "*", "lifetime", "time"; "OM_uint32/int32", "*", "lifetime_req", "time"; "OM_uint32/int32", "*", "initiator_lifetime", "time"; "OM_uint32/int32", "*", "acceptor_lifetime", "time"; "OM_uint32/int32", "*", "*", "int32"; ] let map_name fn_name arg_name ty_name = try let (_, _, _, oname) = List.find (fun (n1, n2, n3, n4) -> n1 = ty_name && (n2 = fn_name || n2 = "*") && (n3 = arg_name || n3 = "*") ) mapping in oname with | Not_found -> ty_name let prep_ty_name ty_name = try let p = String.index ty_name '/' in String.sub ty_name 0 p with Not_found -> ty_name let strip_gss name = if String.length name >= 4 && String.sub name 0 4 = "gss_" then String.sub name 4 (String.length name - 4) else name (* delete_sec_context: - missing *) let fixup_accept_sec_context = (* the output args for the method: pairs (new_name, old_name) *) [ "src_name", "src_name"; "mech_type", "mech_type"; "output_context", "context"; (* ! *) "output_token", "output_token"; "ret_flags", "ret_flags"; "time_rec", "time_rec"; "delegated_cred", "delegated_cred"; ] let fixup_export_sec_context = (* delete the output context *) [ "interprocess_token", "interprocess_token"; ] let fixup_init_sec_context = [ "actual_mech_type", "actual_mech_type"; "output_context", "context"; (* ! *) "output_token", "output_token"; "ret_flags", "ret_flags"; "time_rec", "time_rec"; ] let fixups = [ "gss_accept_sec_context", fixup_accept_sec_context; "gss_export_sec_context", fixup_export_sec_context; "gss_init_sec_context", fixup_init_sec_context ] let fixup fn_name out_params = try let fixup_list = List.assoc fn_name fixups in List.map (fun (ocaml_name, c_name) -> let (_, p_kind, p_type) = try List.find (fun (n,_,_) -> n = c_name) out_params with Not_found -> failwith (sprintf "Not found: fn=%s c_name=%s" fn_name c_name) in (ocaml_name, c_name, p_kind, p_type) ) fixup_list with | Not_found -> List.map (fun (n, p_kind, p_type) -> (n,n,p_kind,p_type)) out_params let functions = List.filter (fun (n, _, _) -> n <> "gss_display_status") functions @ [ "gss_display_minor_status", [ "status_value", `In, "int32"; "mech_type", `In, "gss_OID"; "status_strings", `Out, "string list"; ], [] ] let () = let f = open_out "netgss.ml" in fprintf f "(* generated file, do not edit *)\n"; fprintf f "module System : Netsys_gssapi.GSSAPI = struct\n"; fprintf f " open Netsys_gssapi\n"; fprintf f " open Netgss_bindings\n"; fprintf f " include Netgss_util\n"; fprintf f "\n"; fprintf f " type credential = gss_cred_id_t\n"; fprintf f " type context = gss_ctx_id_t\n"; fprintf f " type name = gss_name_t\n"; fprintf f " type context_option = context option\n"; fprintf f " type cb_option = channel_bindings option\n"; fprintf f " type ret_flags = ret_flag list\n"; fprintf f " type time_opt = float option\n"; fprintf f " type wrap_size = int\n"; fprintf f " type req_flags = req_flag list\n"; fprintf f " type token_option = token option\n"; fprintf f "\n"; fprintf f " exception Credential of credential\n"; fprintf f " exception Context of context\n"; fprintf f " exception Name of name\n"; fprintf f "\n"; fprintf f " class type gss_api = \ [ credential, name, context ] Netsys_gssapi.poly_gss_api\n"; fprintf f "\n"; fprintf f " let interface : gss_api =\n"; fprintf f " ( object\n"; fprintf f " method provider = \"Netsys_gssapi.System\"\n"; fprintf f " method no_credential = no_credential()\n"; fprintf f " method no_name = no_name()\n"; fprintf f " method is_no_credential = is_no_credential\n"; fprintf f " method is_no_name = is_no_name\n"; let indent = " " in List.iter (fun (fn_name, params, _) -> fprintf f "%smethod %s :\n" indent (strip_gss fn_name); (* First generate the (polymorphic) method type: *) fprintf f "%s 't .\n" indent; let input_params = List.filter (fun (p_name, p_kind, _) -> (p_kind = `In || p_kind = `In_out || p_kind = `In_ptr) && p_name <> "minor_status" ) params in let output_params = List.filter (fun (p_name, p_kind, _) -> (p_kind = `Out || p_kind = `Out_noptr || p_kind = `In_out) && p_name <> "minor_status" ) params in let output_params_fixed = fixup fn_name output_params in List.iter (fun (p_name, p_kind, p_type) -> let ocaml_type = map_name fn_name p_name p_type in fprintf f "%s %s:%s ->\n" indent p_name ocaml_type; ) input_params; (* HACK for wrap/unwrap: *) if fn_name = "gss_unwrap" || fn_name = "gss_wrap" then ( fprintf f "%s output_message_preferred_type:[`Bytes|`Memory] ->\n" indent ); fprintf f "%s out:(\n" indent; List.iter (fun (p_name_ocaml, p_name, p_kind, p_type) -> let ocaml_type = map_name fn_name p_name p_type in fprintf f "%s %s:%s ->\n" indent p_name_ocaml ocaml_type; ) output_params_fixed; fprintf f "%s minor_status:minor_status ->\n" indent; fprintf f "%s major_status:major_status ->\n" indent; fprintf f "%s unit ->\n" indent; fprintf f "%s 't\n" indent; fprintf f "%s ) -> unit -> 't =\n" indent; (* Now generate the method body: *) fprintf f "%s fun" indent; List.iter (fun (p_name, p_kind, p_type) -> fprintf f " ~%s" p_name ) input_params; (* HACK for wrap/unwrap: *) if fn_name = "gss_unwrap" || fn_name = "gss_wrap" then ( fprintf f " ~output_message_preferred_type" ); fprintf f " ~out () ->\n"; (* Buffer management: *) let have_buffers = List.exists (fun (_, _, p_type) -> p_type = "gss_buffer_t") input_params in if have_buffers then ( fprintf f "%s let buffers = ref [] in\n" indent; fprintf f "%s let release_soon f arg = \ let buf = f arg in \ buffers := buf :: !buffers; \ buf in\n" indent; ); (* Catching call results: *) fprintf f "%s let major_status, minor_status" indent; List.iter (fun (p_name, p_kind, p_type) -> fprintf f ", %s" p_name ) output_params; fprintf f " = \n"; (* Call: *) fprintf f "%s %s" indent fn_name; (* Arguments: *) List.iter (fun (p_name, p_kind, p_type) -> let ocaml_type = map_name fn_name p_name p_type in let in_convert0 = if p_type = ocaml_type then "identity" else sprintf "_%s_of_%s" (prep_ty_name p_type) ocaml_type in let in_convert = if p_type = "gss_buffer_t" then "release_soon " ^ in_convert0 else in_convert0 in fprintf f "\n%s (%s %s)" indent in_convert p_name ) input_params; if input_params = [] then fprintf f "\n%s ()" indent; fprintf f " in\n"; (* Buffer management: *) if have_buffers then fprintf f "%s List.iter release_buffer !buffers;\n" indent; (* Invoke the "out" function: *) fprintf f "%s out" indent; (* Out arguments: *) List.iter (fun (p_name_ocaml, p_name, p_kind, p_type) -> let ocaml_type = map_name fn_name p_name p_type in let out_convert = if p_type = ocaml_type then "identity" else if ocaml_type = "message" then "(_message_of_gss_buffer_t output_message_preferred_type)" else sprintf "_%s_of_%s" ocaml_type (prep_ty_name p_type) in fprintf f "\n%s ~%s:(%s %s)" indent p_name_ocaml out_convert p_name ) output_params_fixed; (* Standard out arguments: *) fprintf f "\n%s ~minor_status" indent; fprintf f "\n%s ~major_status:(decode_status major_status)" indent; fprintf f "\n%s ()\n" indent; ) functions; fprintf f " end\n"; fprintf f " )\n"; fprintf f "end\n"; close_out f ocamlnet-4.1.2/src/netshm/0000755000175000017500000000000012731530350014030 5ustar gerdgerdocamlnet-4.1.2/src/netshm/netshm_data.ml0000644000175000017500000002340612731530350016656 0ustar gerdgerd(* $Id$ *) type 'a data_manager = { to_int32_array : 'a -> Netshm.int32_array; of_int32_array : Netshm.int32_array list -> 'a; of_int32_array_prefix : (Netshm.int32_array list -> 'a option) option; hash_fn : 'a -> int32 } let int32_manager = { to_int32_array = (fun n -> let v = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout 1 in v.{ 0 } <- n; v); of_int32_array = (fun l -> match l with | [ v ] -> if Bigarray.Array1.dim v <> 1 then raise(Netshm.Corrupt_file "Netshm_data.int32_manager: Cannot decode"); v.{ 0 } | _ -> raise(Netshm.Corrupt_file "Netshm_data.int32_manager: Cannot decode") ); of_int32_array_prefix = None; hash_fn = (fun n -> n) } let int64_manager = { to_int32_array = (fun n -> let v = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout 2 in v.{ 0 } <- Int64.to_int32 (Int64.shift_right_logical n 32); v.{ 1 } <- Int64.to_int32 n; v); of_int32_array = (fun l -> match l with | [ v ] -> if Bigarray.Array1.dim v <> 2 then raise(Netshm.Corrupt_file "Netshm_data.int64_manager: Cannot decode"); Int64.logor (Int64.shift_left (Int64.of_int32 v.{ 0 }) 32) (Int64.logand (Int64.of_int32 v.{ 1 }) 0xffff_ffffL) | [ v; u ] -> (* Note: reverse order! *) if Bigarray.Array1.dim u <> 1 || Bigarray.Array1.dim v <> 1 then raise(Netshm.Corrupt_file "Netshm_data.int64_manager: Cannot decode"); Int64.logor (Int64.shift_left (Int64.of_int32 u.{ 0 }) 32) (Int64.logand (Int64.of_int32 v.{ 0 }) 0xffff_ffffL) | _ -> raise(Netshm.Corrupt_file "Netshm_data.int64_manager: Cannot decode") ); of_int32_array_prefix = None; hash_fn = Int64.to_int32 } let sel_32_or_64_manager to32 of32 to64 of64 = match Sys.word_size with | 32 -> { to_int32_array = (fun n -> int32_manager.to_int32_array (to32 n)); of_int32_array = (fun l -> of32 (int32_manager.of_int32_array l)); of_int32_array_prefix = None; hash_fn = to32 } | 64 -> { to_int32_array = (fun n -> int64_manager.to_int32_array (to64 n)); of_int32_array = (fun l -> of64 (int64_manager.of_int32_array l)); of_int32_array_prefix = None; hash_fn = (fun n -> Int64.to_int32 (to64 n)) } | _ -> assert false let nativeint_manager = sel_32_or_64_manager Nativeint.to_int32 Nativeint.of_int32 Int64.of_nativeint Int64.to_nativeint let int_manager = sel_32_or_64_manager Int32.of_int Int32.to_int Int64.of_int Int64.to_int let int32_array_manager = { to_int32_array = (fun v -> v); of_int32_array = (fun l -> let size = List.fold_left (fun acc v -> acc + Bigarray.Array1.dim v) 0 l in let v_total = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout size in let size' = List.fold_left (fun start' v -> let len = Bigarray.Array1.dim v in let start = start' - len in Bigarray.Array1.blit v (Bigarray.Array1.sub v_total start len); start) size l in assert(size' = 0); v_total); of_int32_array_prefix = None; hash_fn = (fun v -> Int32.of_int (Hashtbl.hash v)) } let string_manager = { to_int32_array = (fun s -> let s_len = String.length s in if Int32.of_int s_len > Int32.max_int then failwith "Netshm_data: string too long"; let size = if s_len = 0 then 1 else (s_len - 1) / 4 + 2 in let v = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout size in v.{ 0 } <- Int32.of_int s_len; let m = Netsys_mem.memory_of_bigarray_1 v in Netsys_mem.blit_string_to_memory s 0 m 4 s_len; v ); of_int32_array = (fun l -> if l = [] then raise(Netshm.Corrupt_file "Netshm_data.string_manager: Cannot decode"); let size = ref 0 in let v_last = ref None in List.iter (fun v -> size := !size + Bigarray.Array1.dim v; v_last := Some v ) l; let s_len = ( match !v_last with | None -> assert false | Some v -> if Bigarray.Array1.dim v = 0 then raise(Netshm.Corrupt_file "Netshm_data.string_manager: Cannot decode"); Int32.to_int v.{ 0 } ) in let s_len_4 = s_len mod 4 in let size' = if s_len = 0 then 1 else (s_len - 1) / 4 + 2 in if !size <> size' then raise(Netshm.Corrupt_file "Netshm_data.string_manager: Cannot decode"); let pos = ref !size in let s = Bytes.create s_len in let s_pos = ref s_len in List.iter (fun v -> let l = Bigarray.Array1.dim v in let has_last_content_word = !pos = !size && s_len > 0 in pos := !pos - l; let has_length_word = !pos = 0 in let m = Netsys_mem.memory_of_bigarray_1 v in let bsize = 4 * l - (if has_last_content_word && s_len_4 <> 0 then 4 - s_len_4 else 0 ) - (if has_length_word then 4 else 0 ) in s_pos := !s_pos - bsize; Netsys_mem.blit_memory_to_bytes m (if has_length_word then 4 else 0) s !s_pos bsize; ) l; assert (!pos = 0); assert (!s_pos = 0); Bytes.unsafe_to_string s ); of_int32_array_prefix = None; hash_fn = (fun v -> Int32.of_int (Hashtbl.hash v)) } let pair_manager x_manager y_manager = { to_int32_array = (fun (x,y) -> let vx = x_manager.to_int32_array x in let vy = y_manager.to_int32_array y in let lx = Bigarray.Array1.dim vx in let ly = Bigarray.Array1.dim vy in let size = lx + ly + 1 in let v = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout size in v.{ 0 } <- Int32.of_int lx; Bigarray.Array1.blit vx (Bigarray.Array1.sub v 1 lx); Bigarray.Array1.blit vy (Bigarray.Array1.sub v (lx+1) ly); v ); of_int32_array = (fun l -> if l = [] then raise(Netshm.Corrupt_file "Netshm_data.pair_manager: Cannot decode"); let l' = List.rev l in let vl = List.hd l' in assert(Bigarray.Array1.dim vl > 0); let lx = Int32.to_int vl.{0} in let l1 = ref [] in let l2 = ref [] in let c1 = ref 0 in List.iter (fun v -> let l = Bigarray.Array1.dim v in let p0 = if !c1 = 0 then 1 else 0 in let p1 = if !c1 < lx then ( let r = min (l - p0) (lx - !c1) in if p0 = 0 && r = l then l1 := v :: !l1 else l1 := (Bigarray.Array1.sub v p0 r) :: !l1; c1 := !c1 + r; p0+r ) else p0 in if !c1 = lx then ( let r = l - p1 in if p1 = 0 then l2 := v :: !l2 else l2 := (Bigarray.Array1.sub v p1 r) :: !l2; ) ) l'; let x = x_manager.of_int32_array !l1 in let y = y_manager.of_int32_array !l2 in (x,y) ); of_int32_array_prefix = None; hash_fn = (fun v -> Int32.of_int (Hashtbl.hash v)) } let left_pair_manager x_manager = { to_int32_array = (fun x -> failwith "Netshm_data.left_pair_manager: Encoding not supported" ); of_int32_array = (fun l -> if l = [] then raise(Netshm.Corrupt_file "Netshm_data.left_pair_manager: Cannot decode"); let l' = List.rev l in let vl = List.hd l' in let lx = Int32.to_int vl.{0} in let l1 = ref [] in let c1 = ref 0 in List.iter (fun v -> let l = Bigarray.Array1.dim v in let p0 = if !c1 = 0 then 1 else 0 in if !c1 < lx then ( let r = min (l - p0) (lx - !c1) in if p0 = 0 && r = l then l1 := v :: !l1 else l1 := (Bigarray.Array1.sub v p0 r) :: !l1; c1 := !c1 + r; ); ) l'; x_manager.of_int32_array !l1 ); of_int32_array_prefix = Some (fun l -> let size = ref 0 in let last = ref None in List.iter (fun v -> size := !size + Bigarray.Array1.dim v; last := Some v ) l; ( match !last with | None -> None | Some last -> let lx = Int32.to_int last.{0} in if !size >= lx + 1 then ( let l1 = ref [] in let c1 = ref 0 in List.iter (fun v -> let l = Bigarray.Array1.dim v in let p0 = if !c1 = 0 then 1 else 0 in if !c1 < lx then ( let r = min (l - p0) (lx - !c1) in if p0 = 0 && r = l then l1 := v :: !l1 else l1 := (Bigarray.Array1.sub v p0 r) :: !l1; c1 := !c1 + r; ); ) (List.rev l); Some(x_manager.of_int32_array !l1) ) else None ) ); hash_fn = (fun v -> Int32.of_int (Hashtbl.hash v)) } let option_manager x_manager = { to_int32_array = (fun x_opt -> match x_opt with | Some x -> let vx = x_manager.to_int32_array x in let lx = Bigarray.Array1.dim vx in let v = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout (lx+1) in v.{ 0 } <- 1l; Bigarray.Array1.blit vx (Bigarray.Array1.sub v 1 lx); v | None -> let v = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout 1 in v.{ 0 } <- 0l; v ); of_int32_array = (fun l -> if l = [] then raise(Netshm.Corrupt_file "Netshm_data.option_manager: Cannot decode"); let l' = List.rev l in let vl = List.hd l' in let x0 = vl.{0} in if x0 = 0l then ( if Bigarray.Array1.dim vl <> 1 || List.length l <> 1 then raise(Netshm.Corrupt_file "Netshm_data.option_manager: Cannot decode"); None ) else if x0 = 1l then ( let l1 = ref [] in let is_first = ref true in List.iter (fun v -> if !is_first then ( let l = Bigarray.Array1.dim v in l1 := (Bigarray.Array1.sub v 1 (l-1)) :: !l1 ) else l1 := v :: !l1; is_first := false ) l'; Some(x_manager.of_int32_array !l1) ) else raise(Netshm.Corrupt_file "Netshm_data.option_manager: Cannot decode") ); of_int32_array_prefix = None; hash_fn = (fun v -> Int32.of_int (Hashtbl.hash v)) } ocamlnet-4.1.2/src/netshm/Makefile0000644000175000017500000000067012731530350015473 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PKGNAME = netshm OBJECTS = netshm.cmo netshm_data.cmo netshm_hashtbl.cmo netshm_array.cmo DOBJECTS = netshm.mli netshm_data.mli netshm_hashtbl.mli netshm_array.mli \ netshm_intro.txt INCLUDES += $(INC_NETSYS) OCAMLC_OPTIONS += $(STRING_OPTS) OCAMLOPT_OPTIONS += $(STRING_OPTS) PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" include $(TOP_DIR)/Makefile.rules include depend ocamlnet-4.1.2/src/netshm/netshm_hashtbl.mli0000644000175000017500000000742612731530350017547 0ustar gerdgerd(* $Id$ *) (** Hash tables in shared memory *) type ('a, 'b) t val manage : ?pagesize:int -> ?init:int -> 'a Netshm_data.data_manager -> 'b Netshm_data.data_manager -> Netshm.locking_method -> Netshm.shm_descr -> ('a,'b) t (** Manages a shared memory object as a hash table like [Netshm.manage], * and additionally represent arbitrary O'Caml values. * * It is essential that the same data managers are passed as at the time * when the hash table was initialized. * * For example, to get a hash table from [int] to [string], use * {[ manage Netshm_data.int_manager Netshm_data.string_manager lm sd ]} *) val add : ('a,'b) t -> 'a -> 'b -> unit (** [add tbl key value]: Adds the binding of [key] to [value] to the * table. Previous bindings are not removed, but simply hidden. *) val find : ('a,'b) t -> 'a -> 'b (** [find tbl key]: Finds the current binding of [key] in [tbl] or * raises [Not_found] if no such binding exists. *) val find_all : ('a,'b) t -> 'a -> 'b list (** [find_all tbl key] returns the list of all data * associated with [key] in [tbl]. * The current binding is returned first, then the previous * bindings, in reverse order of introduction in the table. *) val mem : ('a,'b) t -> 'a -> bool (** [mem tbl key] checks if [key] is bound in [tbl]. *) val remove : ('a,'b) t -> 'a -> unit (** [remove tbl key] removes the current binding of [key] in [tbl], * restoring the previous binding if it exists. * It does nothing if [key] is not bound in [tbl]. *) val replace : ('a,'b) t -> 'a -> 'b -> unit (** [replace tbl key value] replaces the current binding of [key] * in [tbl] by a binding of [key] to [value]. If [key] is unbound in [tbl], * a binding of [key] to [value] is added to [tbl]. *) val iter : ('a -> 'b -> unit) -> ('a,'b) t -> unit (** [iter f tbl] applies [f] to all bindings in table [tbl]. * [f] receives the key as first argument, and the associated value * as second argument. Each binding is presented exactly once to [f]. * The order in which the bindings are passed to [f] is unspecified. * However, if the table contains several bindings for the same key, * they are passed to [f] in reverse order of introduction, that is, * the most recent binding is passed first. * * While the iteration is in progress, the table is locked. * That means you cannot modify it during the iteration. *) val iter_keys : ('a -> unit) -> ('a,'b) t -> unit (** [iter_keys f tbl] applies [f] to all keys in table [tbl]. If there * are several bindings for a key, [f] is only called once. * * While the iteration is in progress, the table is locked. * That means you cannot modify it during the iteration. *) val fold : ('a -> 'b -> 'c -> 'c) -> ('a,'b) t -> 'c -> 'c (** [fold f tbl init] computes * [(f kN dN ... (f k1 d1 init)...)], * where [k1 ... kN] are the keys of all bindings in [tbl], * and [d1 ... dN] are the associated values. * Each binding is presented exactly once to [f]. * The order in which the bindings are passed to [f] is unspecified. * However, if the table contains several bindings for the same key, * they are passed to [f] in reverse order of introduction, that is, * the most recent binding is passed first. * * While the iteration is in progress, the table is locked. * That means you cannot modify it during the iteration. *) val length : ('a,'b) t -> int (** [length tbl] returns the number of bindings in [tbl]. * Multiple bindings are counted multiply, so [length] * gives the number of times [iter] calls its first argument. *) val shm_table : ('a,'b) t -> Netshm.shm_table (** Returns the underlying shared memory table used to implement hash * tables. *) ocamlnet-4.1.2/src/netshm/netshm_data.mli0000644000175000017500000000504112731530350017022 0ustar gerdgerd(* $Id$ *) (** Data representation for shared memory *) type 'a data_manager = { to_int32_array : 'a -> Netshm.int32_array; (** Represent the value as an [int32_array] *) of_int32_array : Netshm.int32_array list -> 'a; (** Read the value back from its [int32_array] representation. * The array is given as list of array fragments in reverse * order. The fragments must not be empty. *) of_int32_array_prefix : (Netshm.int32_array list -> 'a option) option; (** Read the value back from its [int32_array] representation. * Unlike [of_int32_array], it is allowed to pass a prefix * of the whole array to this function. As [of_int32_array], * this prefix is given as list of array fragments in reverse * order. The function may return [None] if it is not yet * possible to reconstruct the value. Otherwise the value is * returned as [Some v]. *) hash_fn : 'a -> int32 (** Hash function *) } (** The data manager consists of several manager functions. * [of_int32_array_prefix] is optional. *) val int32_manager : int32 data_manager (** Represents an [int32] as one-element [int32_array] *) val int64_manager : int64 data_manager (** Represents an [int64] as two-element [int32_array] *) val nativeint_manager : nativeint data_manager (** Uses either [int32_manager] or [int64_manager] to represent [nativeint], * depending on the size of [nativeint]. *) val int_manager : int data_manager (** Uses either [int32_manager] or [int64_manager] to represent [int], * depending on the size of [int]. *) val int32_array_manager : Netshm.int32_array data_manager (** The identity representation manager *) val string_manager : string data_manager (** Represents a string in the following way. The first element * is the size of the string. The following elements store the * bytes. The last word is filled up with zero bytes if necessary. *) val pair_manager : 'a data_manager -> 'b data_manager -> ('a * 'b) data_manager (** Creates a compound manager for pairs from two input managers *) val left_pair_manager : 'a data_manager -> 'a data_manager (** Uses the same representation as [pair_manager], but the resulting * data manager only reads the left value of the pair. * * This data manager does not support [to_int32_array]. *) val option_manager : 'a data_manager -> 'a option data_manager (** Creates a data manager from an input data manager for optional values *) ocamlnet-4.1.2/src/netshm/netshm_intro.txt0000644000175000017500000002723112731530350017307 0ustar gerdgerd{1 Shared Memory for IPC} The [netshm] library implements a number of practical schemes to manage shared memory. Here we give a tutorial how to use that functions. {2 What kind of shared memory we talk about} In general, shared memory is a memory region that is mapped into several address spaces. The O'Caml language already supports one kind of shared memory out of the box, the so-called multi-threading. Here, several execution threads access the same memory, and thus can access the same data. There are a lot of accompanying techniques allowing one to manage shared memory (mutexes, condition variables, event channels, etc.). Of course, the [netshm] library does not use this kind of shared memory (it is effectively even incompatible with multi-threading to some degree). Here, memory is shared by independent processes. This means that any process on the computer can access a shared memory object provided - the process knows the global name of the object, and - the process has the access rights. It is not necessary that the processes have something else in common (e.g. that one process is created by the other, etc.). {2 Types of shared memory provided by the OS} In the Unix world, there are (at least) two common APIs to access global shared memory objects: - System V shared memory - POSIX shared memory The [netshm] library has an extensible interface that can support several system APIs. Currently, however, there is only an implementation for POSIX shared memory. In addition to that, it is also possible to access file-backed memory. Note that not all OS support POSIX shared memory. To check, look at the value of [Netsys.have_posix_shm()]. {2 Global names} The module {!Netshm} defines the possible global names: {[ type shm_name = [ `POSIX of string * string | `File of string ] ]} For POSIX shared memory you must take a [`POSIX] global name, for file-backed memory a [`File] name. A [`POSIX] global name has two strings as arguments: [(file_name,mem_name)]. The [file_name] points to a normal file, usually located in the [/tmp] hierarchy. This file is only used for management and locking purposes. The [mem_name] is the actual POSIX memory object. This name looks like a file name, but actually lives in a different name space. It must begin with a slash, followed by the name that must not contain further slashes. An exampe: [`POSIX("/tmp/sample", "/sample")]. {2 Opening shared memory objects} There is the function {!Netshm.open_shm} that works much like [Unix.openfile]. For example, {[ let sd = Netshm.open_shm (`POSIX("/tmp/sample","/sample")) [Unix.O_CREAT; Unix.O_RDWR] 0o666 ]} opens [/sample] for read-write access, and if the object does not exist yet, it is created with mode 0o666. The returned result is a so-called shared memory descriptor. In order to create unique new objects, you can also use {!Netshm.create_unique_shm}. This function takes a pattern for the global name, and creates a new object with a unique name based on the pattern. This is done by replacing all ['X'] letters in the string argument by random characters until a new name has been found. For example: {[ let sd = Netshm.create_unique_shm (`POSIX("/tmp/myprogram.XXXXX","/myprogram.XXXXX")) 0o666 ]} The actual name is returned by {!Netshm.name_of_shm}. Like files, shared memory objects must be closed after usage: {[ Netshm.close_shm sd ]} Of course, the object continues to exist after the descriptor has been closed. There is a special function {!Netshm.unlink_shm} to delete objects. It is discouraged to open shared memory objects several times in parallel from the same process, as locking methods (see below) are confused by this. If you create several processes by calling [Unix.fork] it is required that every process opens the shared memory object anew. It is not sufficient to open the object in the master process, and to use it in the child processes after forking. This will cause subtle malfunctions. {2 Data structures} The {!Netshm} module contains only the algorithms for the primitve data structure, a hash table from [int32] to bigarrays of [int32] elements. {!Netshm_hashtbl} and {!Netshm_array} have user-friendlier data structures: - {!Netshm_hashtbl} is a hash table from type s to t, where both s and t can be any so-called manageable type (see below). - {!Netshm_array} is an array of elements, again of one of the mentioned manageable types. Arrays can be sparse. The element types are restricted to those types that can be managed with {!Netshm_data}. In principle, this can be any type for which you can write a data manager. {!Netshm_data} contains only data managers for these types: - [int] - [int32] - [int64] - [nativeint] - [string] - pairs of two manageable types (pairs of pairs are allowed) For example, to get a data manager for the pair of an [int] and a [string], one can do {[ let dm = Netshm_data.pair_manager Netshm_data.int_manager Netshm_data.string_manager ]} [dm] has then type [(int * string) data_manager]. In order to view a shared memory object as hash table or array, it is necessary to [manage] it: {[ let sd = Netshm.open_shm (`POSIX("/tmp/sample", "/sample")) [Unix.O_RDWR] 0 in let tab = Netshm_hashtbl.manage Netshm_data.string_manager dm `No_locking sd ]} The [manage] function for hash tables takes the data managers for keys and values of the table, a thing called [`No_locking], and the shared memory descriptor [sd] as input. It returns the abstract value that represents the hash table. What [`No_locking] means will become clearer below. After being managed, you can access [tab] like a hash table: {[ Netshm_hashtbl.add tab "First Key" (1, "First value") let (n, s) = Netshm_hashtbl.find tab "First Key" ]} Note that neither input nor output values of managed objects are placed in shared memory. They are normal O'Caml values for which no restrictions apply. The shared memory is totally hidden from user code (actually, there are two functions in {!Netshm} that exhibit values that reside in this memory, but they should only be used by experts). The [manage] function for arrays is slightly different. In particular, only one data manager must be given. {2 Concurrent Access} If [`No_locking] is effective, nothing is done by netshm to make concurrent accesses by several processes to the same object safe. The implications depend on what you do. If you only read, everything is ok. If there is a writer, it is possible that netshm cannot access the object properly in certain situations, and it is even possible that the internal structures of the object are destroyed. In order to avoid such problems, you can specify a locking method other than [`No_locking]. Currently there is only [`Record_locking]. It is sufficient to pass [`Record_locking] to the [manage] functions - the rest works automatically: {[ let tab = Netshm_hashtbl.manage Netshm_data.string_manager dm `Record_locking sd ]} Record locking bases on the [Unix.lockf] function. It has been chosen as primary locking method because it is available everywhere - although it is not the fastest method. The effect of locking is that every read access places read locks on the relevant parts of the object, and that every write access acquires the needed write locks. The locking scheme is rather fine-grained and allows true parallel accesses when a reader and a writer manipulate the same key of the hash table. Two writers, however, lock each other out. {2 Grouping} Consider this piece of code: {[ let v = Netshm_hashtbl.find tab k in let v' = compute_something v in Netshm_hashtbl.replace tab k v' ]} This is a so-called read-modify-write cycle. If several processes do this in parallel, the execution of the cycles can overlap. For example, it is possible that process P writes the modified value v' while process Q checks for the value of this key. The outcome of such overlapping cycles is quite random: In the best case, computations are repeated, in the worst case, results of computations are lost. {!Netshm} has the function {!Netshm.group} to avoid such effects: {[ Netshm.group (Netshm_hashtbl.shm_table tab) (fun () -> let v = Netshm_hashtbl.find tab k in let v' = compute_something v in Netshm_hashtbl.replace tab k v' ) () ]} Note that you need {!Netshm_hashtbl.shm_table} to get the underlying primitive table in order to use [group]. The effect of [group] is that conflicting accesses to the same parts of the memory object are deferred, so that they do not overlap anymore (technically, the release of the locks is deferred). However, another phenomenon is now possible: Deadlocks. Deadlock situations usually occur between the locking requirements of a reader and a function that removes a value ([remove] or [replace]). Imagine what happens when processes P and Q execute the same grouped read-modify-write cycle almost at the same time: - First, both P and Q read-lock the read value - Second, one process is a little bit faster (say P), and wants to replace the value, thus needing a write lock. It cannot get the write lock now because Q still has a read lock - Third, Q wants to replace the value, needing a write lock. It cannot get the write lock now because P still has a read lock If nothing else happened, both processes would wait forever. Fortunately, record locking includes deadlock detection. One process is notified that there is a deadlock. The netshm user gets the {!Netshm.Deadlock} exception. In a simple read-modifiy-write cycle, this exception is quite harmless: The [replace] call is interrupted before it got the chance to modify the table. The suggested strategy to cope with that is to sleep for a moment to let the other process do its job and to restart the cycle from the beginning. In a more complicated cycle, it can happen that a value is already written, and the second trial to write a value triggers the exception. Well, written is written, and there is no mechanism to "undo" the chaos. Best strategy: avoid such cycles, or use another way to store values in a shared storage (e.g. database system). {2 Persistency of shared memory} Note that POSIX shared memory is not automatically released when the process terminates. Instead, such memory objects persist until explicitly deleted (just like files). {b If you forget to delete such objects, RAM will be consumed until the system is rebooted!} There is a helper data structure in {!Netsys_pmanage} helping to find and delete memory: If you have an object [`POSIX(tmp_name, mem_name)], the file [tmp_name] contains a line pointing to [mem_name], e.g. {[ R POSIX_SHM "/my_object" ]} You can use {!Netsys_pmanage} to read this line and to unlink the object: {[ let m = Netsys_pmanage.pmanage tmp_name in m # unlink() ]} {2 Applications} I hope it has become clear that netshm is only useful for simple applications as there is no support for transactions. Another fundamental limitation is that the file format is non-portable (netshm files written on platform A may not be readable on platform B). Ideas: - Servers using multi-processing where the processes must share some state (e.g. sessions) - Scientific computations implemented on a multi-CPU system with multi-processing, where the processes put their results into shared memory - Using netshm as fast persistent lookup table {2 Limits} The maximum size of a memory object depends on the [pagesize] and [init] parameters of the [manage] call. Roughly, the maximum size is pagesize * init * 32768 which is about 8 G for the defaults [pagesize] = 256 and [init] = 1000. Usually, other limits are hit first. The hash table and array elements use 32 bit numbers for their bookkeeping, e.g. strings can have at most a length of 2 ^ 31 - 1 bytes. ocamlnet-4.1.2/src/netshm/netshm_array.ml0000644000175000017500000000574712731530350017073 0ustar gerdgerd(* $Id$ *) open Netshm open Netshm_data type 'a t = { table : shm_table; htbl : (int, 'a) Netshm_hashtbl.t; (* We use the hash table to store the normal elements. For the * length of the array, we use the index (-1) which is mapped * to an int instead of 'a. Implemented by bypassing htbl in this * case. *) idx_only_manager : int data_manager; idx_len_manager : (int * int) data_manager; default_val : 'a; } let shm_table t = t.table let with_length f t = let r = ref None in Netshm.read_blocks t.table (-1l) (fun frag_opt -> match frag_opt with | Some frag -> let length = Int32.to_int frag.{ 0 } in r := Some (f length); raise Break | None -> assert false ); match !r with | None -> assert false | Some x -> x let length t = with_length (fun l -> l) t let get t k = with_length (fun length -> if k < 0 || k >= length then invalid_arg "Netshm_array.get: index out of bounds"; try Netshm_hashtbl.find t.htbl k with | Not_found -> t.default_val ) t ;; let set t k x = with_length (fun length -> if k < 0 || k >= length then invalid_arg "Netshm_array.set: index out of bounds"; Netshm_hashtbl.replace t.htbl k x ) t let resize t n = if n < 0 then invalid_arg "Netshm_array.resize"; with_length (fun old_len -> (* First remove any element at indexes >= n *) if n < old_len then ( let l = ref [] in Netshm_hashtbl.iter_keys (fun idx -> if idx >= n then l := idx :: !l ) t.htbl; List.iter (fun idx -> Netshm_hashtbl.remove t.htbl idx ) !l ); (* Finally just set the new length field: *) Netshm.write_blocks t.table [] (-1l) (fun frag_opt -> match frag_opt with | Some frag -> frag.{ 0 } <- Int32.of_int n; raise Break | None -> assert false ) ) t let default_value t = t.default_val let shm_table t = t.table let manage ?pagesize ?init defval val_manager lm sd = let shm_init = match init with | Some n -> Some 1000 | None -> None in let idx_manager = Netshm_data.int_manager in let htbl = Netshm_hashtbl.manage ?pagesize ?init:shm_init idx_manager val_manager lm sd in let table = Netshm_hashtbl.shm_table htbl in let idx_only_manager = left_pair_manager idx_manager in let idx_len_manager = pair_manager idx_manager Netshm_data.int_manager in let t = { table = table; htbl = htbl; idx_only_manager = idx_only_manager; idx_len_manager = idx_len_manager; default_val = defval } in Netshm.group table (fun () -> if not (Netshm.mem table (-1l)) then let length_field = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout 1 in length_field.{ 0 } <- 0l; Netshm.add table (-1l) length_field ) (); ( match init with | None -> () | Some n -> resize t n ); t ocamlnet-4.1.2/src/netshm/META.in0000644000175000017500000000030612731530350015105 0ustar gerdgerdversion = "@VERSION@" description = "Ocamlnet - Shared memory" requires = "unix netsys bigarray" archive(byte) = "netshm.cma" archive(native) = "netshm.cmxa" archive(native,gprof) = "netshm.p.cmxa" ocamlnet-4.1.2/src/netshm/Makefile.pre0000644000175000017500000000026612731530350016261 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PRE = 1 PKGNAME = netshm GENERATE = META PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" include $(TOP_DIR)/Makefile.rules ocamlnet-4.1.2/src/netshm/netshm_hashtbl.ml0000644000175000017500000001126712731530350017374 0ustar gerdgerd(* $Id$ *) open Netshm open Netshm_data type ('a, 'b) t = { table : shm_table; key_only_manager : 'a data_manager; key_val_manager : ('a * 'b) data_manager; key_hash_fn : 'a -> int32; } let manage ?pagesize ?init key_manager val_manager lm sd = let t = Netshm.manage ?pagesize ?init lm sd in let key_only_manager = left_pair_manager key_manager in let key_val_manager = pair_manager key_manager val_manager in { table = t; key_only_manager = key_only_manager; key_val_manager = key_val_manager; key_hash_fn = key_manager.hash_fn; } let shm_table t = t.table let add t k v = let h = t.key_hash_fn k in let kv_array = t.key_val_manager.to_int32_array (k,v) in Netshm.add t.table h kv_array ;; let find t k = let decode_key = match t.key_only_manager.of_int32_array_prefix with | None -> assert false | Some f -> f in let h = t.key_hash_fn k in let data = ref [] in let v_opt = ref None in read_blocks t.table h (fun data_frag_opt -> match data_frag_opt with | Some data_frag -> data := data_frag :: !data; ( match decode_key !data with | None -> () | Some k' -> if k <> k' then ( data := []; raise Netshm.Next ) ) | None -> (* Important: we must decode the data while the binding is * read-locked! *) let (k',v) = t.key_val_manager.of_int32_array !data in assert (k = k'); v_opt := Some v; raise Netshm.Break ); ( match !v_opt with | None -> raise Not_found | Some v -> v ) ;; let find_all t k = let decode_key = match t.key_only_manager.of_int32_array_prefix with | None -> assert false | Some f -> f in let h = t.key_hash_fn k in let data = ref [] in let l = ref [] in read_blocks t.table h (fun data_frag_opt -> match data_frag_opt with | Some data_frag -> data := data_frag :: !data; ( match decode_key !data with | None -> () | Some k' -> if k <> k' then ( data := []; raise Netshm.Next ) ) | None -> (* Important: we must decode the data while the binding is * read-locked! *) let (k',v) = t.key_val_manager.of_int32_array !data in assert (k = k'); l := v :: !l; data := [] ); List.rev !l ;; let mem t k = let decode_key = match t.key_only_manager.of_int32_array_prefix with | None -> assert false | Some f -> f in let h = t.key_hash_fn k in let data = ref [] in let is_mem = ref false in read_blocks t.table h (fun data_frag_opt -> match data_frag_opt with | Some data_frag -> data := data_frag :: !data; ( match decode_key !data with | None -> () | Some k' -> if k <> k' then ( data := []; raise Netshm.Next ) ) | None -> is_mem := true; raise Netshm.Break ); !is_mem ;; let remove t k = let decode_key = match t.key_only_manager.of_int32_array_prefix with | None -> assert false | Some f -> f in let h = t.key_hash_fn k in let data = ref [] in let can_stop = ref false in write_blocks t.table [`Remove_binding] h (fun data_frag_opt -> if !can_stop then raise Break; match data_frag_opt with | Some data_frag -> data := data_frag :: !data; ( match decode_key !data with | None -> `Nop | Some k' -> if k <> k' then ( data := []; raise Netshm.Next ); can_stop := true; `Remove_binding ) | None -> assert false ) ;; let replace t k v = Netshm.group t.table (fun () -> remove t k; add t k v ) () let iter f t = Netshm.iter (fun _ data -> let (k,v) = t.key_val_manager.of_int32_array [ data ] in f k v ) t.table ;; let iter_keys f t = let decode_key = match t.key_only_manager.of_int32_array_prefix with | None -> assert false | Some f -> f in let last_key = ref None in let data = ref [] in Netshm.iter_keys (fun shm_key -> Netshm.read_blocks t.table shm_key (fun data_frag_opt -> match data_frag_opt with | Some data_frag -> data := data_frag :: !data; ( match decode_key !data with | None -> () | Some k as sk -> if sk <> !last_key then f k; last_key := sk; data := []; raise Netshm.Next ) | None -> () ); ) t.table ;; let fold f t x0 = Netshm.fold (fun _ data acc -> let (k,v) = t.key_val_manager.of_int32_array [ data ] in f k v acc) t.table x0 ;; let length t = Netshm.length t.table ocamlnet-4.1.2/src/netshm/netshm_array.mli0000644000175000017500000000455612731530350017241 0ustar gerdgerd(* $Id$ *) (** Arrays in shared memory *) type 'a t val manage : ?pagesize:int -> ?init:int -> 'a -> 'a Netshm_data.data_manager -> Netshm.locking_method -> Netshm.shm_descr -> 'a t (** Manages a shared memory object as an array, * including the representation of arbitrary O'Caml values. * The first argument of type ['a] is the default value of the * array elements. * * This bases on [Netshm.manage], and the arguments [pagesize], * [locking_method] and [shm_descr] are documented there. * * If an empty memory object is managed, it is initialized as * array with zero elements. If a non-empty memory object is * managed, it must contain a valid array structure. * The size of the array is then the same as when the array * was managed the last time. * * By passing [init] with argument [n], the array is reinitialized as * array with [n] elements containing the default value. * * It is essential that the same data managers are passed as at the time * when the array was initialized. * * Arrays are implemented as [(int32, 'a) Netshm_hashtbl.t]. *) val length : 'a t -> int (** Returns the length of the array *) val get : 'a t -> int -> 'a (** [get a k]: Returns the contents of the array element number [k] where * [0 <= k < length a]. * * If you do [module Array = Netshm_array] in your code you can also * use the notation [a.(k)]. *) val set : 'a t -> int -> 'a -> unit (** [set a k x]: Sets the contents of the array element number [k] to [x] * where [0 <= k < length a]. * * If you do [module Array = Netshm_array] in your code you can also * use the notation [a.(k) <- x]. *) (* val swap : 'a t -> int -> int -> unit (** [swap a j k]: Swaps the contents of the array elements [j] and [k]. * This function is a lot more efficient than programming swapping with * [get] and [set]. *) *) val resize : 'a t -> int -> unit (** [resize a n]: Resizes the array to length [n]. If the array is enlarged * the new elements will be initialized to the default value. *) val default_value : 'a t -> 'a (** Returns the default value *) val shm_table : 'a t -> Netshm.shm_table (** Returns the underlying shared memory table used to implement hash * tables *) ocamlnet-4.1.2/src/netshm/netshm.ml0000644000175000017500000012427712731530350015675 0ustar gerdgerd(* $Id$ *) (* FILE FORMAT: * * Page 0 is called the master page, and is usally not modified: * * 0/0: File magic 0 * 0/1: File magic 1 * 0/2: File magic 2 * 0/3: File magic 3 * 0/4: Base_shm version number * 0/5: Pointer to descriptor page * * The descriptor page [d] contains global data that must be frequently * updated: * * d/0: Descriptor magic * d/1: Total number of pages * d/2: Size of the hash table S (used plus free entries) * d/3: Number of used entries in the hash table * d/4: Total number of bindings * d/5: Pointer to the first free content page (head of free list) * d/6: Number of free content pages * d/7: unused * d/8: Pointer to first extent of hash table * d/9: Size of first extent of hash table in pages * d/10: Pointer to first extent of hash table or 0 if unused * d/11: Size of first extent of hash table in pages or 0 if unused * ... * d/38: Pointer to 16th extent of hash table or 0 if unused * d/39: Size of first extent of hash table in pages or 0 if unused * * The hash table is the array concatenation of 1 to 16 extents. Extents * are added when the hash table is resized. Extents are contiguous * sequences of pages. * * The hash table array consists of S cells. Every cell has four words: * * 0: Key * 1: Pointer to content page. * 0 means: Unused cell * -1 means: Used cell but there is currenty no binding * 2: Spare word used for resizing * 3: Spare word used for resizing * * Every hash table page contains P/4-1 cells (when P is the number of * words per page). The four first words of the page have a special meaning: * * 0: Hash table page magic * 1: Sequential number of the page in the table * 2: unused * 3: unused * * Used content pages have this layout: * * c/0: Content page magic * c/1: Key * c/2: Pointer to next content page for this entry (or 0) * c/3: Pointer to first content page of next binding for this key, or 0 * c/4: Position where the value begins (which word) * c/5: Length of the value in words * c/6 - P-1: Content words * * Follow-up content pages: * * c'/0: Follow-up content page magic * c'/1: Key * c'/2: Pointer to next content page for this entry (or 0) * c'/3: Sequence number of this content page * c'/4 - P-1: Content words * * The position in c/4 is relative to the concatenated content * areas, i.e. position 0 is c/6 etc. * * Free content pages: * * f/0: Free page magic * f/1: Pointer to next free page or 0 * * LOCKING * * Locking is page-wise. * * A Lock of the descriptor page is also interpreted as a lock for the * whole hash table. * * A lock of the first content page is also interpreted as a lock of * the remaining content pages of the entry. * * - Reading a single entry: * * 1. Read-lock descriptor page * 2. Look up entry * 3. Read-lock content page * 4, Unlock descriptor page * 5. Read content * 6. Unlock content page * * - Reading all bindings: * * 1. Read-lock descriptor page * 2. Look up entry * 3. Read-lock 1st content page * 4, Unlock descriptor page * 5. Read 1st content * 6. Lock 2nd content page * 7. Unlock 1st content page * 8. Read 2nd content * 9. Lock 3rd content page * 10. Unlock 2nd content page * ... * N. Unlock n-th content page * * - Adding a single entry: * * 1. Write-lock descriptor page * 2. If necessary, do a resize pass (see below) * 4. Find entry in hash table and fill it * 4. Find free content page(s) and fill it/them * 5. Unlock descriptor page * * - Removing a single entry: * * 1. Write-lock descriptor page * 2. Modify hash table * 3. Write-lock old content page * 4. Make the old content page a free page * 5. Unlock descriptor page * 6. Unlock content page *) open Printf module Int = struct type t = int let compare = (Pervasives.compare : int -> int -> int) end module IntMap = Map.Make(Int) (**********************************************************************) (* shm_descr *) (**********************************************************************) type shm_type = [ `POSIX | `File ] type shm_descr = { shm_type : shm_type; file_name : string; file_fd : Unix.file_descr; posix_name : string; mutable posix_fd : Unix.file_descr option; mutable is_open : bool } let supported_types = ( if Netsys_posix.have_posix_shm() then [ `POSIX ] else [] ) @ [ `File ] type shm_name = [ `POSIX of string * string | `File of string ] let shm_type_of_name = function | `POSIX _ -> `POSIX | `File _ -> `File let rndsrc = Random.State.make_self_init() let chars = [| '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; 'A'; 'B'; 'C'; 'D'; 'E'; 'F'; 'G'; 'H'; 'I'; 'J'; 'K'; 'L'; 'M'; 'N'; 'O'; 'P'; 'Q'; 'R'; 'S'; 'T'; 'U'; 'V'; 'W'; 'X'; 'Y'; 'Z' |] (* We do not include lower case chars because there are case-insensitive * file systems *) let open_shm ?(unique=false) name flags perm = let inst_string n = (* Replace 'X' with random chars *) let n' = Bytes.of_string n in for k = 0 to String.length n - 1 do if Bytes.get n' k = 'X' then Bytes.set n' k chars.( Random.State.int rndsrc (Array.length chars) ) done; Bytes.to_string n' in let rec attempt f k n = if k = 1000 then failwith "Netshm.create_shm: Unable to generate name for \ shared memory object"; try let name = if unique then inst_string n else n in (f name, name) with | Unix.Unix_error(Unix.EEXIST,_,_) when unique -> attempt f (k+1) n in match name with | `File nm -> let fd, name = attempt (fun n -> Unix.openfile n flags perm) 1 nm in { shm_type = `File; file_name = name; file_fd = fd; posix_name = ""; posix_fd = None; is_open = true } | `POSIX(file_n,mem_n) -> let fd, name = attempt (fun n -> Unix.openfile n flags perm) 1 file_n in let mem_flags = List.flatten (List.map (function | Unix.O_RDONLY -> [ Netsys_posix.SHM_O_RDONLY ] | Unix.O_RDWR -> [ Netsys_posix.SHM_O_RDWR ] | Unix.O_CREAT -> [ Netsys_posix.SHM_O_CREAT ] | Unix.O_EXCL -> [ Netsys_posix.SHM_O_EXCL ] | Unix.O_TRUNC -> [ Netsys_posix.SHM_O_TRUNC ] | Unix.O_WRONLY -> invalid_arg "Netsys.open_shm: O_WRONLY not supported" | _ -> [] ) flags) in let mem_fd, mem_name = attempt (fun n -> Netsys_posix.shm_open n mem_flags perm) 1 mem_n in let n64_1 = (Unix.LargeFile.fstat fd).Unix.LargeFile.st_size in let n64_2 = (Unix.LargeFile.fstat mem_fd).Unix.LargeFile.st_size in if n64_1 = 0L && n64_2 = 0L then ( let ch = Unix.out_channel_of_descr fd in fprintf ch "R POSIX_SHM %S\n%!" mem_name; ); { shm_type = `POSIX; file_name = name; file_fd = fd; posix_name = mem_name; posix_fd = Some mem_fd; is_open = true } let create_unique_shm name perm = open_shm ~unique:true name [ Unix.O_RDWR; Unix.O_CREAT; Unix.O_EXCL ] perm let name_of_shm shm = match shm.shm_type with | `File -> `File shm.file_name | `POSIX -> `POSIX(shm.file_name,shm.posix_name) let close_shm shm = ( match shm.posix_fd with | Some fd -> Unix.close fd; shm.posix_fd <- None | None -> () ); if shm.is_open then ( Unix.close shm.file_fd; shm.is_open <- false ) let unlink_shm = function | `File name -> Unix.unlink name | `POSIX(f_name,m_name) -> Netsys_posix.shm_unlink m_name; Unix.unlink f_name let chmod_shm_fd fd perm = ( try Unix.fchmod fd perm with Unix.Unix_error(Unix.EINVAL,_,_) -> () (* OSX seems to throw EINVAL here *) ) let chmod_shm shm perm = if not shm.is_open then failwith "Netshm.chmod_shm: descriptor is not open"; chmod_shm_fd shm.file_fd perm; ( match shm.posix_fd with | None -> () | Some fd -> chmod_shm_fd fd perm ) let chown_shm_fd fd uid gid = Unix.fchown fd uid gid let chown_shm shm uid gid = if not shm.is_open then failwith "Netshm.chown_shm: descriptor is not open"; chown_shm_fd shm.file_fd uid gid; ( match shm.posix_fd with | None -> () | Some fd -> chown_shm_fd fd uid gid ) let mem_fd shm = assert(shm.is_open); match shm.posix_fd with | None -> shm.file_fd | Some fd -> fd let size_of_shm shm = if not shm.is_open then failwith "Netshm.size_of_shm: descriptor is not open"; let fd = mem_fd shm in let n64 = (Unix.LargeFile.fstat fd).Unix.LargeFile.st_size in if n64 > Int64.of_int max_int then failwith "Netshm.size_of_shm: Shared memory object too large"; Int64.to_int n64 let resize_shm shm n = if not shm.is_open then failwith "Netshm.resize_shm: descriptor is not open"; let fd = mem_fd shm in Unix.LargeFile.ftruncate fd (Int64.of_int n) let map_int32matrix_fd fd is_open rows cols = Bigarray.Array2.map_file fd Bigarray.int32 Bigarray.c_layout true rows cols let map_int32matrix shm rows cols = let fd = mem_fd shm in Bigarray.Array2.map_file fd Bigarray.int32 Bigarray.c_layout true rows cols let dummy_int32matrix() = Bigarray.Array2.create Bigarray.int32 Bigarray.c_layout 0 0 (**********************************************************************) (* locking *) (**********************************************************************) type locking_method = [ `No_locking | `Record_locking ] let best_locking_method _ = `Record_locking type lock_type = Read | Write exception Deadlock (* record_locking_descr represents the locking requirements. rld_table * maps pages to a list of locking requirements for the pages. The * strongest requirement is passed through to the lockf interface. *) type record_locking_descr = { rld_sd : shm_descr; mutable rld_table : (lock_type list ref) IntMap.t; rld_pagesize : int; } let rec rl_do_lock rld page lt = if not rld.rld_sd.is_open then failwith "Netshm: Shared memory object is not open"; let fd = rld.rld_sd.file_fd in try ignore(Unix.lseek fd (page * rld.rld_pagesize) Unix.SEEK_SET); Unix.lockf fd (if lt = Read then Unix.F_RLOCK else Unix.F_LOCK) 1; with | Unix.Unix_error(Unix.EDEADLK,_,_) -> raise Deadlock | Unix.Unix_error(Unix.EINTR,_,_) -> rl_do_lock rld page lt let rl_lock rld page lt = try let lt_list = IntMap.find page rld.rld_table in ( match lt with | Read -> lt_list := Read :: !lt_list | Write -> if not(List.mem Write !lt_list) then rl_do_lock rld page Write; lt_list := Write :: !lt_list ) with | Not_found -> rl_do_lock rld page lt; rld.rld_table <- IntMap.add page (ref [ lt ]) rld.rld_table let rl_unlock rld page = (* releases the last (most recent) lock requirement for [page] *) if not rld.rld_sd.is_open then failwith "Netshm: Shared memory object is not open"; let fd = rld.rld_sd.file_fd in try let lt_list = IntMap.find page rld.rld_table in ( match !lt_list with | [ _ ] -> (* release lock entirely *) ignore(Unix.lseek fd (page * rld.rld_pagesize) Unix.SEEK_SET); Unix.lockf fd Unix.F_ULOCK 1; rld.rld_table <- IntMap.remove page rld.rld_table; | Read :: lt_list' -> lt_list := lt_list' | Write :: lt_list' -> if not(List.mem Write lt_list') then rl_do_lock rld page Read; (* downgrade from Write to Read *) lt_list := lt_list' | [] -> assert false ) with | Not_found -> () type locking_descr = [ `No_locking | `Record_locking of record_locking_descr ] let create_locking_descr sd pagesize lm = match lm with | `No_locking -> `No_locking | `Record_locking -> `Record_locking { rld_sd = sd; rld_table = IntMap.empty; rld_pagesize = pagesize; } (* A groupable locking descriptor has the property that one can wrap * several operations as a "group". The locks are not released while * the operations of the group are executed. This has the effect that * the group is executed atomically. *) type groupable_locking_descr = { gld : locking_descr; mutable gld_groups : int; mutable gld_deferred_unlocks : int list } let gld_lock gld p ltype = ( match gld.gld with | `Record_locking rld -> rl_lock rld p ltype; | `No_locking -> () ); if gld.gld_groups > 0 then gld.gld_deferred_unlocks <- p :: gld.gld_deferred_unlocks ;; let gld_unlock gld p = if gld.gld_groups = 0 then ( match gld.gld with | `Record_locking rld -> rl_unlock rld p | `No_locking -> () ); ;; let gld_start gld = gld.gld_groups <- gld.gld_groups + 1 let gld_end gld = gld.gld_groups <- gld.gld_groups - 1; if gld.gld_groups = 0 then ( List.iter (fun p -> gld_unlock gld p ) gld.gld_deferred_unlocks; gld.gld_deferred_unlocks <- [] ) let create_gld sd pagesize lm = { gld = create_locking_descr sd pagesize lm; gld_groups = 0; gld_deferred_unlocks = [] } (**********************************************************************) (* shm_table *) (**********************************************************************) type shm_table = { sd : shm_descr; lm : groupable_locking_descr; mutable mem : (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array2.t; pagesize : int; (* in words! *) dpage : int; (* descriptor page *) mutable self_locked : bool; (* Whether locked against mutations by this process *) } type int32_array = (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array1.t exception Corrupt_file of string exception Next exception Break let file_magic1 = 0xde871209l let file_magic2 = 0xde881209l let file_magic3 = 0xde871309l let file_magic4 = 0xde87120al let descriptor_magic = 0x6712DE9Fl let content1_magic = 0x12DE9F67l let content2_magic = 0xDE9F6712l let hash_table_magic = 0x9F6712DEl let free_page_magic = 0xf3eef3eel let to_int = match Sys.word_size with | 32 -> let max32 = Int32.of_int max_int in let min32 = Int32.of_int min_int in (fun n -> if n > max32 || n < min32 then raise(Corrupt_file "Integer too large"); Int32.to_int n ) | 64 -> Int32.to_int | _ -> assert false ;; let of_int = match Sys.word_size with | 32 -> Int32.of_int | 64 -> let max32 = Int32.to_int Int32.max_int in let min32 = Int32.to_int Int32.min_int in (fun n -> if n > max32 || n < min32 then raise(Corrupt_file "Integer too large"); Int32.of_int n ) | _ -> assert false ;; let remap t pages = let mem = map_int32matrix t.sd pages t.pagesize in t.mem <- mem; ;; let lock_page t p ltype = gld_lock t.lm p ltype ;; let unlock_page t p = gld_unlock t.lm p ;; let unlock_protect t l f arg = try f arg with | error -> List.iter (fun p -> unlock_page t p) l; raise error let self_locked t f arg = let old = t.self_locked in t.self_locked <- true; try let r = f arg in t.self_locked <- old; r with | error -> t.self_locked <- old; raise error let group t f arg = try gld_start t.lm; let r = f arg in gld_end t.lm; r with | error -> gld_end t.lm; raise error let hash_cell t k = (* Returns the k-th hash cell as pair (page, position), or Not_found *) let entries_per_page = t.pagesize / 4 - 1 in let rec find_hash_cell ext k = if ext < 16 then ( let pos = 2 * ext + 8 in let ext_page = t.mem.{ t.dpage, pos } in let ext_size = t.mem.{ t.dpage, pos+1 } in if ext_page = 0l || ext_size = 0l then raise Not_found; let ext_length = (to_int ext_size) * entries_per_page in if k < ext_length then let ext_offset = k / entries_per_page in let ext_pos = k mod entries_per_page in ((to_int ext_page) + ext_offset, ext_pos * 4 + 4) else find_hash_cell (ext+1) (k - ext_length) ) else raise Not_found in find_hash_cell 0 k ;; let quad_probing = [| 0; 1; 4; 9; 16; 25; 36; 49; 64; 81 |] let rec hash_lookup t key seq spare_flag = (* Finds [key] in the hash table and returns the entry as triple * (page, position, found). [found] indicates whether the [key] * was actually found. If not, the entry is the unused entry that * will store [key]. * * seq is used to find the hash entry and must be initially 0l. * * spare_flag: If set, the spare entries are returned instead of the * normal ones. *) let remainder x y = let r = Int32.rem x y in if r >= 0l then r else Int32.add y r in let total_pages = t.mem.{ t.dpage, 1 } in let ht_size = t.mem.{ t.dpage, 2 } in let (ht_page, ht_pos) = try let offset = (* The first ten positions in this probing sequence are the same as * for quadratic probing. Then we simply continue with linear probing. * This way, we get most of the good properties of quadratic hashing, * but there is no size restriction on the table. *) if seq <= 9l then Int32.of_int quad_probing.( Int32.to_int seq ) else Int32.add 72l seq in hash_cell t (to_int (remainder (Int32.add key offset) ht_size)) with | Not_found -> raise(Corrupt_file "Too few hash table extents found") in if ht_page <= 0 || (of_int ht_page) >= total_pages then raise(Corrupt_file "Bad page number found"); if ht_pos < 0 || ht_pos >= t.pagesize then raise(Corrupt_file "Bad page position found"); let spare_offset = if spare_flag then 2 else 0 in let ht_key = t.mem.{ ht_page, ht_pos+spare_offset } in let ht_ptr = t.mem.{ ht_page, ht_pos+spare_offset+1 } in if ht_ptr = 0l then (ht_page, ht_pos, false) else if ht_key = key then (ht_page, ht_pos, true) else hash_lookup t key (Int32.succ seq) spare_flag ;; let alloc_hash_extent t seq n = let q_ht = (t.pagesize-4) / 4 in (* entries per ht page *) let total_pages = t.mem.{ t.dpage, 1 } in let total_pages' = to_int total_pages + n in remap t total_pages'; t.mem.{ t.dpage, 1 } <- of_int total_pages'; t.mem.{ t.dpage, 2 } <- Int32.add t.mem.{ t.dpage, 2 } (of_int (n * q_ht)); for k = 0 to n-1 do let p = to_int total_pages + k in t.mem.{ p, 0 } <- hash_table_magic; t.mem.{ p, 1 } <- of_int (seq + k); t.mem.{ p, 2 } <- 0l; t.mem.{ p, 3 } <- 0l; for k = 0 to q_ht - 1 do t.mem.{ p, 0 + 4*k } <- 0l; t.mem.{ p, 1 + 4*k } <- 0l; t.mem.{ p, 2 + 4*k } <- 0l; t.mem.{ p, 3 + 4*k } <- 0l; done done; to_int total_pages ;; let add_hash_extent t = (* The new extent is twice as large as the largest extent *) let rec loop count largest ext = if ext < 16 then ( let pos = 2 * ext + 8 in let ext_page = t.mem.{ t.dpage, pos } in let ext_size = t.mem.{ t.dpage, pos+1 } in if ext_page = 0l || ext_size = 0l then ( (* found the empty slot *) let n = 2 * largest in let pg = alloc_hash_extent t count n in t.mem.{ t.dpage, pos } <- of_int pg; t.mem.{ t.dpage, pos+1 } <- of_int n; ) else ( loop (count + to_int ext_size) (max (to_int ext_size) largest) (ext+1) ) ) else failwith "add: cannot add further hash table extent" in loop 0 0 0 ;; let iter_hash_table t f = let q_ht = (t.pagesize-4) / 4 in (* entries per ht page *) let rec loop ext = if ext < 16 then ( let pos = 2 * ext + 8 in let ext_page = t.mem.{ t.dpage, pos } in let ext_size = t.mem.{ t.dpage, pos+1 } in if ext_page <> 0l && ext_size <> 0l then ( for k = 0 to to_int ext_size - 1 do let p = to_int ext_page + k in for j = 0 to q_ht - 1 do let q = 4 + j*4 in f p q done done; loop (ext+1) ) ) in loop 0 ;; let refill_hash_table t = let fill_spare () = iter_hash_table t (fun p q -> let ht_key = t.mem.{ p, q } in let ht_ptr = t.mem.{ p, q+1 } in if ht_ptr <> 0l && ht_ptr <> (-1l) then ( let (ht_page, ht_pos, ht_found) = hash_lookup t ht_key 0l true in if ht_found then raise(Corrupt_file "Duplicate key found in hash table"); t.mem.{ ht_page, ht_pos + 2 } <- ht_key; t.mem.{ ht_page, ht_pos + 3 } <- ht_ptr; ) ) in let copy_back () = iter_hash_table t (fun p q -> t.mem.{ p, q } <- t.mem.{ p, q+2 }; t.mem.{ p, q+1 } <- t.mem.{ p, q+3 }; t.mem.{ p, q+2 } <- 0l; t.mem.{ p, q+3 } <- 0l; ) in fill_spare (); copy_back () ;; let hash_lookup_for_addition t key = (* Returns (page, pos, inc). * inc is true if a new ht cell was allocated *) let (ht_page_0, ht_pos_0, ht_found_0) = hash_lookup t key 0l false in if ht_found_0 then (ht_page_0, ht_pos_0, false) else ( (* We have to allocate another cell of the hash table. Check whether * we have to resize the hash table! *) let n_used = to_int t.mem.{ t.dpage, 3 } in let n_total = to_int t.mem.{ t.dpage, 2 } in if n_used * 2 > n_total then ( (* more than 1/2 is used, so resize *) add_hash_extent t; refill_hash_table t; (* Note: total_pages has changed! *) let (ht_page_1, ht_pos_1, ht_found_1) = hash_lookup t key 0l false in assert(not ht_found_1); (ht_page_1, ht_pos_1, true) ) else ( (ht_page_0, ht_pos_0, true) ) ) ;; (* Iterate over all bindings for a given key *) type iterator = { i_table : shm_table; i_key : int32; i_total_pages : int32; mutable i_binding_pg : int; (* 1st page of current binding *) mutable i_next_binding_pg : int; (* 1st page of next binding *) mutable i_current_pg : int; (* current page of current binding *) mutable i_current : int32_array; (* same, the page itself *) mutable i_next_pg : int; (* next page of current binding *) mutable i_seq : int; (* sequence number *) mutable i_start_val : int; (* start position of value fragment *) mutable i_len_val : int; (* length of value fragment *) mutable i_rest_len_val : int; (* rem. length of value after fragment *) } (* Note: the iterator functions do not do any locking *) let start_binding it pg = (* Go to the start of the binding at page [pg] *) let current = Bigarray.Array2.slice_left it.i_table.mem pg in let cp_magic = current.{ 0 } in let cp_key = current.{ 1 } in let cp_cpage' = current.{ 2 } in let cp_cpage_next = current.{ 3 } in let cp_val_pos = current.{ 4 } in let cp_val_len = current.{ 5 } in if cp_magic <> content1_magic then raise(Corrupt_file "Bad content1 magic"); if cp_key <> it.i_key then raise(Corrupt_file "Wrong content page"); if cp_cpage' < 0l || cp_cpage' >= it.i_total_pages then raise(Corrupt_file "Page pointer out of bounds"); if cp_cpage_next < 0l || cp_cpage' >= it.i_total_pages then raise(Corrupt_file "Page pointer out of bounds"); if cp_val_pos < 0l || cp_val_len < 0l then raise(Corrupt_file "Negative string pointers"); let ca_start = 6 in (* first word of content area is at pos 6 *) let ca_len = it.i_table.pagesize - ca_start in let cp_cpage' = to_int cp_cpage' in let cp_cpage_next = to_int cp_cpage_next in let cp_val_pos = to_int cp_val_pos in let cp_val_len = to_int cp_val_len in if cp_val_pos >= ca_len then raise(Corrupt_file "value does not start in first content page"); let len_val = min ca_len cp_val_len in it.i_binding_pg <- pg; it.i_next_binding_pg <- cp_cpage_next; it.i_current_pg <- pg; it.i_current <- current; it.i_next_pg <- cp_cpage'; it.i_seq <- 0; it.i_start_val <- cp_val_pos + ca_start; it.i_len_val <- len_val; it.i_rest_len_val <- cp_val_len - len_val; ;; let create_iterator t key total_pages pg = (* Create an iterator for the list of bindings starting at page [pg] *) let current = Bigarray.Array2.slice_left t.mem pg in let it = { i_table = t; i_key = key; i_total_pages = total_pages; i_binding_pg = 0; i_next_binding_pg = 0; i_current_pg = 0; i_current = current; i_next_pg = 0; i_seq = 0; i_start_val = 0; i_len_val = 0; i_rest_len_val = 0; } in start_binding it pg; it ;; let next_page it = (* Switches to the next page of the current binding. * Precondition: it.i_next_pg <> 0 *) let pg = it.i_next_pg in assert(pg <> 0); let current = Bigarray.Array2.slice_left it.i_table.mem pg in let cp'_magic = current.{ 0 } in let cp'_key = current.{ 1 } in let cp'_cpage' = current.{ 2 } in let cp'_seq = current.{ 3 } in if cp'_magic <> content2_magic then raise(Corrupt_file "Bad content2 magic"); if cp'_key <> it.i_key then raise(Corrupt_file "Wrong content page"); if cp'_cpage' < 0l || cp'_cpage' >= it.i_total_pages then raise(Corrupt_file "Page pointer out of bounds"); if cp'_seq <> of_int (it.i_seq + 1) then raise(Corrupt_file "Bad sequence number"); let ca_start = 4 in (* first word of content area is at pos 4 *) let ca_len = it.i_table.pagesize - ca_start in let len_val = min ca_len it.i_rest_len_val in it.i_current_pg <- pg; it.i_current <- current; it.i_next_pg <- to_int cp'_cpage'; it.i_seq <- it.i_seq + 1; it.i_start_val <- ca_start; it.i_len_val <- len_val; it.i_rest_len_val <- it.i_rest_len_val - len_val ;; let next_binding it = start_binding it it.i_next_binding_pg ;; (* the read_blocks implementation bases on iterators *) let rec read_blocks_start t key f total_pages prev_pg pg () = lock_page t pg Read; if prev_pg > 0 then unlock_page t prev_pg; let followup = unlock_protect t [ pg ] (fun () -> let it = create_iterator t key total_pages pg in read_blocks_extract it f pg ) () in followup () and read_blocks_extract it f pg () = let followup = unlock_protect it.i_table [ pg ] (fun () -> let val_frag = Bigarray.Array1.sub it.i_current it.i_start_val it.i_len_val in try self_locked it.i_table f (Some val_frag); if it.i_next_pg <> 0 then ( next_page it; read_blocks_extract it f pg ) else ( self_locked it.i_table f None; raise Next ) with | Next -> read_blocks_next it f pg | Break -> (fun () -> unlock_page it.i_table pg) ) () in followup() and read_blocks_next it f prev_pg () = let pg = it.i_next_binding_pg in if pg <> 0 then ( lock_page it.i_table pg Read; unlock_page it.i_table prev_pg; next_binding it; read_blocks_extract it f pg () ) else unlock_page it.i_table prev_pg ;; let read_blocks t key f = lock_page t t.dpage Read; unlock_protect t [ t.dpage ] (fun () -> let total_pages = t.mem.{ t.dpage, 1 } in if Bigarray.Array2.dim1 t.mem <> (to_int total_pages) then remap t (to_int total_pages); let (ht_page, ht_pos, ht_found) = hash_lookup t key 0l false in if ht_found then ( let ht_ptr = t.mem.{ ht_page, ht_pos+1 } in if ht_ptr = (-1l) then ( (* key is unbound *) unlock_page t t.dpage; () ) else if ht_ptr > 0l && ht_ptr < total_pages then ( (* The following call will unlock t.dpage *) read_blocks_start t key f total_pages t.dpage (to_int ht_ptr) () ) else raise(Corrupt_file "Bad page number found") ) else ( (* key is unbound *) unlock_page t t.dpage; () ) ) () ;; let find_all t key = let l = ref [] in let v = ref [] in let v_size = ref 0 in read_blocks t key (fun val_frag_opt -> match val_frag_opt with | Some val_frag -> v := val_frag :: !v; v_size := !v_size + Bigarray.Array1.dim val_frag | None -> let v_total = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout !v_size in List.iter (fun val_frag -> let len = Bigarray.Array1.dim val_frag in v_size := !v_size - len; Bigarray.Array1.blit val_frag (Bigarray.Array1.sub v_total !v_size len) ) !v; assert(!v_size = 0); l := v_total :: !l; v := [] ); List.rev !l ;; exception Done of int32_array let find t key = let v = ref [] in let v_size = ref 0 in try read_blocks t key (fun val_frag_opt -> match val_frag_opt with | Some val_frag -> v := val_frag :: !v; v_size := !v_size + Bigarray.Array1.dim val_frag | None -> (* Important: we must concatenate the fragments while * the binding is read-locked! *) let v_total = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout !v_size in List.iter (fun val_frag -> let len = Bigarray.Array1.dim val_frag in v_size := !v_size - len; Bigarray.Array1.blit val_frag (Bigarray.Array1.sub v_total !v_size len) ) !v; assert(!v_size = 0); raise (Done v_total) ); raise Not_found with | Done v_total -> v_total ;; let mem t key = try read_blocks t key (fun _ -> raise Exit); false with | Exit -> true ;; let iter_keys f t = lock_page t t.dpage Read; unlock_protect t [ t.dpage ] (fun () -> let total_pages = t.mem.{ t.dpage, 1 } in if Bigarray.Array2.dim1 t.mem <> (to_int total_pages) then remap t (to_int total_pages); iter_hash_table t (fun p q -> let ht_key = t.mem.{ p, q } in let ht_ptr = t.mem.{ p, q+1 } in if ht_ptr <> 0l && ht_ptr <> (-1l) then self_locked t f ht_key ) ) (); unlock_page t t.dpage ;; let iter f t = let v = ref [] in let v_size = ref 0 in let reassemble key val_frag_opt = match val_frag_opt with | Some val_frag -> v := val_frag :: !v; v_size := !v_size + Bigarray.Array1.dim val_frag | None -> let v_total = Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout !v_size in List.iter (fun val_frag -> let len = Bigarray.Array1.dim val_frag in v_size := !v_size - len; Bigarray.Array1.blit val_frag (Bigarray.Array1.sub v_total !v_size len) ) !v; assert(!v_size = 0); v := []; f key v_total in lock_page t t.dpage Read; unlock_protect t [ t.dpage ] (fun () -> let total_pages = t.mem.{ t.dpage, 1 } in if Bigarray.Array2.dim1 t.mem <> (to_int total_pages) then remap t (to_int total_pages); iter_hash_table t (fun p q -> let ht_key = t.mem.{ p, q } in let ht_ptr = t.mem.{ p, q+1 } in if ht_ptr <> 0l && ht_ptr <> (-1l) then ( read_blocks_start t ht_key (reassemble ht_key) total_pages 0 (to_int ht_ptr) () ) ) ) (); unlock_page t t.dpage ;; let fold f t x0 = let acc = ref x0 in iter (fun key v -> acc := f key v !acc ) t; !acc ;; let length t = lock_page t t.dpage Read; let n = unlock_protect t [ t.dpage ] (fun () -> to_int t.mem.{ t.dpage, 4 } ) () in unlock_page t t.dpage; n ;; let get_page_from_free_list t = (* Assumes that there is a page! *) let p = t.mem.{ t.dpage, 5 } in if p = 0l then raise(Corrupt_file "Free list is empty when it should not be empty"); let p = to_int p in if t.mem.{ p, 0 } <> free_page_magic then raise(Corrupt_file "Bad free page magic"); let p' = t.mem.{ p, 1} in t.mem.{ t.dpage, 5 } <- p'; t.mem.{ t.dpage, 6 } <- Int32.pred t.mem.{ t.dpage, 6 }; p ;; let add t key v = if t.self_locked then failwith "Netshm: Cannot modify table locked by caller"; lock_page t t.dpage Write; unlock_protect t [ t.dpage ] (fun () -> let total_pages = t.mem.{ t.dpage, 1 } in if Bigarray.Array2.dim1 t.mem <> (to_int total_pages) then remap t (to_int total_pages); let (ht_page, ht_pos, ht_inc) = hash_lookup_for_addition t key in let old_cpage = t.mem.{ ht_page, ht_pos+1 } in let old_cpage = if old_cpage = (-1l) then 0l else old_cpage in (* How many pages do we need? *) let words = Bigarray.Array1.dim v in let pages = (words + 2 - 1) / (t.pagesize - 4) + 1 in (* How many pages do we need to allocate? *) let pages_in_free_list = to_int t.mem.{ t.dpage, 6 } in let pages_to_allocate = max 0 (pages - pages_in_free_list) in (* Allocate pages and enter into free list: *) if pages_to_allocate > 0 then ( let total_pages = to_int t.mem.{ t.dpage, 1 } in remap t (total_pages + pages_to_allocate); t.mem.{ t.dpage, 1 } <- of_int (total_pages + pages_to_allocate); for k = 0 to pages_to_allocate - 1 do let p = total_pages + k in t.mem.{ p, 0 } <- free_page_magic; t.mem.{ p, 1 } <- t.mem.{ t.dpage, 5 }; t.mem.{ t.dpage, 5 } <- of_int p; done; t.mem.{ t.dpage, 6 } <- of_int (pages_in_free_list + pages_to_allocate) ); (* MAYBE TODO: Unlock before writing to content pages *) (* Write content pages: *) let val_idx = ref 0 in let val_len = Bigarray.Array1.dim v in let cpage = get_page_from_free_list t in t.mem.{ cpage, 0 } <- content1_magic; t.mem.{ cpage, 1 } <- key; t.mem.{ cpage, 2 } <- 0l; (* later updated if necessary *) t.mem.{ cpage, 3 } <- old_cpage; t.mem.{ cpage, 4 } <- 0l; t.mem.{ cpage, 5 } <- of_int val_len; let cur_cpage = ref cpage in let pos = ref 6 in let seq = ref 0 in while !val_idx < val_len do if !pos >= t.pagesize then ( let cpage = get_page_from_free_list t in incr seq; t.mem.{ cpage, 0 } <- content2_magic; t.mem.{ cpage, 1 } <- key; t.mem.{ cpage, 2 } <- 0l; (* later updated if necessary *) t.mem.{ cpage, 3 } <- of_int !seq; t.mem.{ !cur_cpage, 2 } <- of_int cpage; cur_cpage := cpage; pos := 4 ); let len = val_len - !val_idx in let ca_len = t.pagesize - !pos in let words = min len ca_len in let mem_pg = Bigarray.Array2.slice_left t.mem !cur_cpage in Bigarray.Array1.blit (Bigarray.Array1.sub v !val_idx words) (Bigarray.Array1.sub mem_pg !pos words); val_idx := !val_idx + words; pos := !pos + words; done; (* Write hash table entry: *) t.mem.{ ht_page, ht_pos } <- key; t.mem.{ ht_page, ht_pos + 1 } <- of_int cpage; if ht_inc then t.mem.{ t.dpage, 3 } <- Int32.succ t.mem.{ t.dpage, 3 }; t.mem.{ t.dpage, 4 } <- Int32.succ t.mem.{ t.dpage, 4 }; ) (); (* Unlock: *) unlock_page t t.dpage ;; let rec unalloc_pages_of_binding t cpage = let cpage' = to_int t.mem.{ cpage, 2 } in t.mem.{ cpage, 0 } <- free_page_magic; t.mem.{ cpage, 1 } <- t.mem.{ t.dpage, 5 }; t.mem.{ t.dpage, 5 } <- of_int cpage; t.mem.{ t.dpage, 6 } <- Int32.succ t.mem.{ t.dpage, 6 }; if cpage' <> 0 then ( if t.mem.{ cpage', 0 } <> content2_magic then raise(Corrupt_file "Bad content2 magic"); unalloc_pages_of_binding t cpage' ) ;; (* the write_blocks implementation bases on iterators *) type write_op = [ `Remove_binding ] type ctrl_op = [ `Nop | write_op ] type op_announcement = { op_remove_binding : bool } type pointer_to_binding = [ `Prev_binding of int | `Hash_entry of int * int ] let remove_binding t key ptr pg = let next_cpage = t.mem.{ pg, 3 } in ( match ptr with | `Hash_entry(ht_page, ht_pos) -> t.mem.{ ht_page, ht_pos + 1 } <- (if next_cpage = 0l then (-1l) else next_cpage); | `Prev_binding pg' -> t.mem.{ pg', 3 } <- next_cpage; ); t.mem.{ t.dpage, 4 } <- Int32.pred t.mem.{ t.dpage, 4 }; (* Note: mem.{t.dpage, 3}, i.e. the number of used entries, does not change, * even if the hash cell is set to (-1). *) unalloc_pages_of_binding t pg; (* The new pointer to the next binding is the old after the deletion: *) ptr ;; let write_op it ops ptr op = match op with | `Nop -> `Prev_binding it.i_binding_pg | `Remove_binding -> if not ops.op_remove_binding then failwith "Netshm.write_blocks: Cannot do write operation unless announced"; remove_binding it.i_table it.i_key ptr it.i_binding_pg ;; let rec write_blocks_start t ops key f total_pages (ptr : pointer_to_binding) pg () = (* ptr: If [`Prev_binding pg], there is a previous binding that starts on * page pg. If [`Hash_entry(pg,pos)] this is the first binding, and the * hash entry on page [pg] and [pos] points to it. * * locking: the current, and if `Remove_binding is announced in ops, * the previous binding (if any) are write locked. * Additionally, t.dpage is locked over the whole time, too. *) lock_page t pg Write; let followup = unlock_protect t [ pg ] (fun () -> let it = create_iterator t key total_pages pg in write_blocks_extract it ops f ptr pg `Nop ) () in followup () and write_blocks_extract it ops f ptr pg old_op () = let locked = if ops.op_remove_binding then match ptr with | `Prev_binding pg' -> [ pg'; pg ] | `Hash_entry(_,_) -> [ pg ] else [ pg ] in let followup = unlock_protect it.i_table locked (fun () -> let val_frag = Bigarray.Array1.sub it.i_current it.i_start_val it.i_len_val in let op = ref old_op in try let new_op = self_locked it.i_table f (Some val_frag) in if new_op <> `Nop then op := new_op; if it.i_next_pg <> 0 then ( next_page it; write_blocks_extract it ops f ptr pg !op ) else ( let new_op = self_locked it.i_table f None in if new_op <> `Nop then op := new_op; raise Next ) with | Next -> let ptr' = write_op it ops ptr !op in write_blocks_next it ops f ptr pg ptr' | Break -> let _ptr' = write_op it ops ptr !op in (fun () -> unlock_page it.i_table pg) ) ()in followup() and write_blocks_next it ops f prev_ptr prev_pg ptr' () = let pg = it.i_next_binding_pg in if pg <> 0 then ( lock_page it.i_table pg Write; if ops.op_remove_binding then ( match prev_ptr with | `Prev_binding pg' -> unlock_page it.i_table pg' | `Hash_entry(_,_) -> () ) else unlock_page it.i_table prev_pg; next_binding it; write_blocks_extract it ops f ptr' pg `Nop () ) else ( if ops.op_remove_binding then ( match prev_ptr with | `Prev_binding pg' -> unlock_page it.i_table pg' | `Hash_entry(_,_) -> () ); unlock_page it.i_table prev_pg ) ;; let write_blocks t ops key f = let ops' = { op_remove_binding = List.mem `Remove_binding ops } in if t.self_locked then failwith "Netshm: Cannot modify table locked by caller"; lock_page t t.dpage Write; unlock_protect t [ t.dpage ] (fun () -> let total_pages = t.mem.{ t.dpage, 1 } in if Bigarray.Array2.dim1 t.mem <> (to_int total_pages) then remap t (to_int total_pages); let (ht_page, ht_pos, ht_found) = hash_lookup t key 0l false in if ht_found then ( let ht_ptr = t.mem.{ ht_page, ht_pos+1 } in if ht_ptr = (-1l) then ( (* key is unbound *) () ) else if ht_ptr > 0l && ht_ptr < total_pages then ( let ptr = `Hash_entry(ht_page,ht_pos) in write_blocks_start t ops' key f total_pages ptr (to_int ht_ptr) () ) else raise(Corrupt_file "Bad page number found") ) ) (); unlock_page t t.dpage; ;; let remove t key = let first = ref true in write_blocks t [`Remove_binding] key (fun _ -> if !first then ( first := false; `Remove_binding ) else raise Break) ;; let replace t key v = (* This is the trivial implementation... Not really what we want. Anything * better that reuses the pages of the old binding is a lot of work... *) group t (fun () -> remove t key; add t key v ) () ;; let manage ?(pagesize = 256) ?init lm sd = if pagesize < 160 then failwith "open_table: minimum pagesize is 160"; if pagesize mod 4 <> 0 then failwith "open_table: pagesize must be divisible by 4"; let pagesize = pagesize/4 in if size_of_shm sd = 0 || init <> None then ( (* re-initialize table *) let ld = create_gld sd pagesize lm in let t = { sd = sd; lm = ld; mem = dummy_int32matrix(); pagesize = pagesize; dpage = 0; self_locked = false; } in let n = match init with | None -> 1000 | Some n -> n in let n_ht = n * 2 in (* need 2 times more ht entries *) let q_ht = (pagesize-4) / 4 in (* entries per ht page *) let p_ht = (n_ht - 1) / q_ht + 1 in (* number of hash table pages *) remap t 2; t.mem.{ 0, 0 } <- file_magic1; t.mem.{ 0, 1 } <- file_magic2; t.mem.{ 0, 2 } <- file_magic3; t.mem.{ 0, 3 } <- file_magic4; t.mem.{ 0, 4 } <- 1l; t.mem.{ 1, 0 } <- descriptor_magic; t.mem.{ 1, 1 } <- 2l; t.mem.{ 1, 2 } <- 0l; t.mem.{ 1, 3 } <- 0l; t.mem.{ 1, 4 } <- 0l; t.mem.{ 1, 5 } <- 0l; t.mem.{ 1, 6 } <- 0l; t.mem.{ 1, 7 } <- 0l; for k = 0 to 15 do t.mem.{ 1, 8 + 2*k } <- 0l; t.mem.{ 1, 9 + 2*k } <- 0l; done; let t = { t with dpage = 1 } in let p = alloc_hash_extent t 0 p_ht in t.mem.{ 1, 8 } <- of_int p; t.mem.{ 1, 9 } <- of_int p_ht; t ) else ( (* manage existing table *) let ld = create_gld sd pagesize lm in let t = { sd = sd; lm = ld; mem = dummy_int32matrix(); pagesize = pagesize; dpage = 0; self_locked = false; } in remap t 1; if (t.mem.{ 0, 0 } <> file_magic1 || t.mem.{ 0, 1 } <> file_magic2 || t.mem.{ 0, 2 } <> file_magic3 || t.mem.{ 0, 3 } <> file_magic4) then raise(Corrupt_file "Bad file magic"); let dpage = to_int t.mem.{ 0, 4 } in remap t (dpage+1); if t.mem.{dpage, 0} <> descriptor_magic then raise(Corrupt_file "Bad descriptor magic"); let total_size = to_int t.mem.{ dpage, 1 } in remap t total_size; { t with dpage = dpage } ) (* Debug stuff: *) let dump t = printf " printf " %ld => [| " key; let l = Bigarray.Array1.dim v in for k = 0 to l - 1 do if k > 0 then printf "; "; printf "%ld" v.{ k } done; printf " |]\n"; ) t; printf ">\n%!" ;; let bigarray x = Bigarray.Array1.of_array Bigarray.int32 Bigarray.c_layout (Array.map Int32.of_int x) ;; let memory t = t.mem ocamlnet-4.1.2/src/netshm/netshm.mli0000644000175000017500000003222112731530350016031 0ustar gerdgerd(* $Id$ *) (** Shared memory for O'Caml programs using multi-processing *) (** {1 Shared Memory Descriptors} *) type shm_descr (** A shared memory descriptor refers to a shared memory object. * Such a descriptor must only be opened once for every process. *) type shm_type = [ `POSIX (** POSIX shared memory (system calls [shm_open] and [mmap]) *) | `File (** File-based, but not necessarily shared memory (system call [mmap]) *) ] val supported_types : shm_type list (** The types supported for this OS *) type shm_name = [ `POSIX of string * string (** The right name refers to a POSIX shared memory object. The name * must start with a slash, and must not contain further slashes, * e.g. ["/my_shm"]. The left name points to a file in the usual * file tree. {b Note that [`POSIX] does not work correctly on * OS X because it is not possible to resize memory objects.} *) | `File of string (** This is the name of an arbitrary file used to store the * data. Note that this is not shared memory unless the file * system is RAM-based. *) ] (** A [shm_name] is a name for a shared memory object. *) val shm_type_of_name : shm_name -> shm_type val open_shm : ?unique:bool -> shm_name -> Unix.open_flag list -> int -> shm_descr (** Opens the shared memory object. * * For [POSIX_shm] not all open flags can be specified. The flags * are limited to [O_RDONLY], [O_RDWR], [O_CREAT], [O_EXCL] and * [O_TRUNC]. * * [unique]: Unique file generation as in [create_unique_shm]. *) val create_unique_shm : shm_name -> int -> shm_descr (** Create a shared memory object under a name that is derived * from the passed [shm_name]. The actual name can be queried with * [name_of_shm] (below). * * For [POSIX] and [File] names, deriving works by replacing * the 'X' letters in the file name by random digits and letters. * For example, if the name is [File "/my/directory/ocaml.XXXXXX"] * six random characters are generated and replace the 'X' letters * such that the file is unique. * * The integer is the file permission. *) val name_of_shm : shm_descr -> shm_name (** Returns the name of an object *) val close_shm : shm_descr -> unit (** Closes the object. The object remains existent and can be * opened again. *) val unlink_shm : shm_name -> unit (** Removes the name permanently from the system *) val chmod_shm : shm_descr -> int -> unit val chown_shm : shm_descr -> int -> int -> unit (** Set file permission bits, user and group ownership of the object *) type locking_method = [ `No_locking (** Do not use locking at all *) | `Record_locking (** Use record locking as provided by [Unix.lockf]. This type of * locking is compatible with shared memory types [POSIX] and [File]. *) ] (** The locking method is used to ensure that parallel read and write * operations to the memory object do not interfer with each other. * If [No_locking] is selected, such protection is not done - this * is ok if only read accesses occur or if the user can ensure that * never a write access is done in parallel with another access. * The locking method must be compatible with the type of shared memory. *) val best_locking_method : shm_type -> locking_method (** Return the best locking method other than [No_locking] *) (** {1 Shared Memory Tables} *) (** This is a quite basic data structure implemented for shared memory: * hash tables with [int32] as key and one-dimensional [int32] * bigarray as values. *) (** The semantics resembles the [Hashtbl] of stdlib *) type shm_table type int32_array = (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array1.t exception Corrupt_file of string (** Raised when a violation of the object format is detected *) exception Deadlock (** Raised when a deadlock situation was detected. Deadlocks can occur * when the [group] function is used *) val manage : ?pagesize:int -> ?init:int -> locking_method -> shm_descr -> shm_table (** Starts managing an open shared memory object as [shm_table]. If * the object is empty, it is automatically enlarged to the * minimum size and initialized. If the object is non-empty it is * expected that it already contains a valid [shm_table] structure. * * The object automatically grows in size when new elements are * added to the object. By removing elements, however, the * object is never shrinked. Unused memory is held back for later * reallocation by the same [shm_table]. * * By default, the table uses a page size of 256 bytes. The page size is * the unit of memory allocation. The parameter [pagesize] overrides * this default. The page size must be at least 160 and divisible by 4. * The page size must be the same when the table was created. * * By passing [init] it is enforced that the table is re-initialized * (deleted and again created). The argument of [init] is a hint * for the number of elements the table will contain. The data * structure is then created such that this many elements can be added * without needing expensive data reorganization. * * Special note for using [shm_table] with multiple processes: Every * process must create its own [shm_descr], and every process must * call [manage] to manage it. It is not sufficient to just fork * a new process, and to keep using the already existing * [shm_descr] or [shm_table] in the subprocess. (This doesn't work * because the underlying file descriptor would be shared.) *) val group : shm_table -> ('a -> 'b ) -> 'a -> 'b (** Execute a sequence of operations in a group: * * {[ * let r = * group table * (fun arg -> * operation1; operation2; ...) * arg * ]} * * Operations can be any reading or writing functions from below. The * effect is that the locking requirements of the operations are merged, * so that no operation of another process can interfer with the grouped * sequence. Note, however, that this gives no real atomicity as there * is no way to roll back half-executed sequences. * * Groups can be nested. * * An example of [group] is to set a binding depending on the previous * value of the binding. Here, we add 1: * * {[ * let add_one table = * group table * (fun key -> * let ba = * try find table key * with Not_found -> * Bigarray.Array1.create Bigarray.int32 Bigarray.c_layout 1 in * ba.{ 0 } <- Int32.succ ba.{ 0 }; * replace table key ba * ) * ]} * * Grouping protects the update from modifications done by other processes * at the same time. In particular, without grouping it can happen that * another process also modifies the same value between [find] and * [replace]. *) val add : shm_table -> int32 -> int32_array -> unit (** [add tbl key value]: Adds the binding of [key] to [value] to the * table. Previous bindings are not removed, but simply hidden. *) val find : shm_table -> int32 -> int32_array (** [find tbl key]: Finds the current binding of [key] in [tbl] or * raises [Not_found] if no such binding exists. *) val find_all : shm_table -> int32 -> int32_array list (** [find_all tbl key] returns the list of all data * associated with [key] in [tbl]. * The current binding is returned first, then the previous * bindings, in reverse order of introduction in the table. *) val mem : shm_table -> int32 -> bool (** [mem tbl key] checks if [key] is bound in [tbl]. *) val remove : shm_table -> int32 -> unit (** [remove tbl key] removes the current binding of [key] in [tbl], * restoring the previous binding if it exists. * It does nothing if [key] is not bound in [tbl]. *) val replace : shm_table -> int32 -> int32_array -> unit (** [replace tbl key value] replaces the current binding of [key] * in [tbl] by a binding of [key] to [value]. If [key] is unbound in [tbl], * a binding of [key] to [value] is added to [tbl]. *) (* val rename : shm_table -> int32 -> int32 -> unit (** [rename tbl key1 key2]: Changes the key of the current binding of * [key1] such that it becomes the current binding of [key2]. Raises * [Not_found] if [key1] is unbound. *) *) (* val swap : shm_table -> int32 -> int32 -> unit (** [swap tbl key1 key2]: determins the current bindings of [key1] and * [key2], and renames them to [key2] and [key1], respectively. * Raises [Not_found] if [key1] or [key2] is unbound. *) *) val iter : (int32 -> int32_array -> unit) -> shm_table -> unit (** [iter f tbl] applies [f] to all bindings in table [tbl]. * [f] receives the key as first argument, and the associated value * as second argument. Each binding is presented exactly once to [f]. * The order in which the bindings are passed to [f] is unspecified. * However, if the table contains several bindings for the same key, * they are passed to [f] in reverse order of introduction, that is, * the most recent binding is passed first. * * While the iteration is in progress, the table is read-locked. * That means you cannot modify it during the iteration. *) val iter_keys : (int32 -> unit) -> shm_table -> unit (** [iter_keys f tbl] applies [f] to all keys in table [tbl]. If there * are several bindings for a key, [f] is only called once. * * While the iteration is in progress, the table is locked. * That means you cannot modify it during the iteration. *) val fold : (int32 -> int32_array -> 'a -> 'a) -> shm_table -> 'a -> 'a (** [fold f tbl init] computes * [(f kN dN ... (f k1 d1 init)...)], * where [k1 ... kN] are the keys of all bindings in [tbl], * and [d1 ... dN] are the associated values. * Each binding is presented exactly once to [f]. * The order in which the bindings are passed to [f] is unspecified. * However, if the table contains several bindings for the same key, * they are passed to [f] in reverse order of introduction, that is, * the most recent binding is passed first. * * While the iteration is in progress, the table is locked. * That means you cannot modify it during the iteration. *) val length : shm_table -> int (** [length tbl] returns the number of bindings in [tbl]. * Multiple bindings are counted multiply, so [length] * gives the number of times [iter] calls its first argument. *) (** {1 Enhanced API to shared memory tables} *) exception Next exception Break val read_blocks : shm_table -> int32 -> (int32_array option -> unit) -> unit (** [find_blocks tbl key f]: The values may be stored in several * disk blocks. This interface allows one to access the values block by * block. As [find_all], all bindings for [key] in [tbl] are determined * in reverse order, i.e. the newest binding first, the oldest last. * For every binding [value], the function [f] is invoked in a sequence * [f (Some v1)], [f (Some v2)], ..., [f (Some vN)], [f None] * where * [value] is the array concatenation of [v1], [v2], ..., [vN]. * The function [f] may raise the exception [Next] to go * directly to the start of the next binding of [key]. * The exception [Break] stops the iteration immediately. * * Note that the [int32_array] fragments [vK] point to shared memory. * Any assignment would modify the shared memory object directly! * The binding is at that time, however, only read-locked, so this * should be avoided. *) type write_op = [ `Remove_binding ] (* Future extensions: * - `Truncate_binding of int *) type ctrl_op = [ `Nop | write_op ] val write_blocks : shm_table -> write_op list -> int32 -> (int32_array option -> ctrl_op) -> unit (** [write_blocks tbl ops key f]: Like [read_blocks] this function iterates * over the blocks of all bindings for [key]. For every binding [value], * the function [f] is invoked in a sequence * [f (Some v1)], [f (Some v2)], ..., [f (Some vN)], [f None]. * Unlike [read_blocks] the function [f] returns a value. * The last non-[`Nop] result value in this sequence determines the * modification to carry out for the binding: * * - [`Remove_binding]: The whole binding is removed from the table. * * If all invocations of [f] just return [`Nop], no further modification * is done. * * The modifications must be announced in the [ops] argument. It is * not allowed that [f] returns a value not being a member of [ops] * (except [`Nop]). * * It is possible to raise the special exceptions [Next] and [Break] * just as for [read_blocks]. * * Note that the [int32_array] fragments [vK] point to shared memory. * Any assignment will modify the shared memory object directly! * The binding is at that time write-locked, so such assignments * are protected against concurrent writes. *) (* debug stuff *) val dump : shm_table -> unit val bigarray : int array -> int32_array val memory : shm_table -> (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array2.t ocamlnet-4.1.2/src/rpc-auth-local/0000755000175000017500000000000012731530351015346 5ustar gerdgerdocamlnet-4.1.2/src/rpc-auth-local/Makefile0000644000175000017500000000064312731530351017011 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PKGNAME = rpc-auth-local OBJECTS = rpc_auth_local.cmo COBJECTS = rpclocal.o DOBJECTS = rpc_auth_local.mli ARCHIVE = rpc_auth_local OCAMLC_OPTIONS += $(STRING_OPTS) OCAMLOPT_OPTIONS += $(STRING_OPTS) PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" DOC_IGNORABLE = true INCLUDES += $(INC_RPC) $(INC_NETSYS) include $(TOP_DIR)/Makefile.rules include depend ocamlnet-4.1.2/src/rpc-auth-local/configure0000755000175000017500000000276212731530351017264 0ustar gerdgerd#! /bin/sh have_getpeereid=0 have_getpeerucred=0 stdlib=`ocamlc -where` ###################################################################### printf "Checking for getpeereid... " getpeereid_compile=0 rm -f configtests/getpeereid.err if (cd configtests; ocamlc -o getpeereid getpeereid.c main.ml -custom ) \ >>configtests/getpeereid.err 2>&1 then getpeereid_compile=1 fi if [ $getpeereid_compile -gt 0 ]; then if configtests/getpeereid >>configtests/getpeereid.err 2>&1; then have_getpeereid=1 fi fi if [ $have_getpeereid -gt 0 ]; then echo "found" def_have_getpeereid="#define HAVE_GETPEEREID" else echo "not found" def_have_getpeereid="#undef HAVE_GETPEEREID" fi ###################################################################### printf "Checking for getpeerucred... " getpeerucred_compile=0 rm -f configtests/getpeerucred.err if (cd configtests; ocamlc -o getpeerucred getpeerucred.c main.ml -custom ) \ >>configtests/getpeerucred.err 2>&1 then getpeerucred_compile=1 fi if [ $getpeerucred_compile -gt 0 ]; then if configtests/getpeerucred >>configtests/getpeerucred.err 2>&1; then have_getpeerucred=1 fi fi if [ $have_getpeerucred -gt 0 ]; then echo "found" def_have_getpeerucred="#define HAVE_GETPEERUCRED" else echo "not found" def_have_getpeerucred="#undef HAVE_GETPEERUCRED" fi ###################################################################### cat <config.h $def_have_getpeereid $def_have_getpeerucred EOF exit 0 ocamlnet-4.1.2/src/rpc-auth-local/META.in0000644000175000017500000000036312731530351016426 0ustar gerdgerddescription = "Ocamlnet - RPC add-on for authentication of local connections" version = "@VERSION@" requires = "rpc" archive(byte) = "rpc_auth_local.cma" archive(native) = "rpc_auth_local.cmxa" archive(native,gprof) = "rpc_auth_local.p.cmxa" ocamlnet-4.1.2/src/rpc-auth-local/configtests/0000755000175000017500000000000012731530351017676 5ustar gerdgerdocamlnet-4.1.2/src/rpc-auth-local/configtests/getpeerucred.c0000644000175000017500000000047512731530351022526 0ustar gerdgerd#include #include #include #include #include #include "caml/mlvalues.h" #include "caml/alloc.h" /* reminder: we return the exit code, and 0 means success */ value check(value dummy) { ucred_t *ucred; getpeerucred(0, &ucred); return Val_int(0); } ocamlnet-4.1.2/src/rpc-auth-local/configtests/main.ml0000644000175000017500000000007112731530351021152 0ustar gerdgerdexternal check : unit -> int = "check";; exit (check()) ocamlnet-4.1.2/src/rpc-auth-local/configtests/getpeereid.c0000644000175000017500000000046612731530351022165 0ustar gerdgerd#include #include #include #include #include "caml/mlvalues.h" #include "caml/alloc.h" /* reminder: we return the exit code, and 0 means success */ value check(value dummy) { uid_t uid; gid_t gid; getpeereid(0, &uid, &gid); return Val_int(0); } ocamlnet-4.1.2/src/rpc-auth-local/rpc_auth_local.mli0000644000175000017500000000504012731530351021027 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (* Authentication for Unix domain sockets * * Some operating systems allow it to check the uid of the connecting user * of a Unix domain socket. This feature can be used for a very reliable * way of authentication. * * To use this method, connect with AUTH_NONE on the client side. On the * server side, put the following [server_auth_method] into the list of * permitted methods (in addition to {!Rpc_server.auth_none}). * * This method formats user names as strings * ".@localhost" * where is the effective user ID and is the effective group ID * of the calling user. * Note that you can parse this string with {!Rpc_auth_sys.parse_user_name}. * * If the file descriptor is not a Unix domain socket, this method generates * the error [Auth_too_weak]. * The same happens if the operating system does not provide a way to * get the credentials of the connecting user (or I have not yet implemented * it). * * {2 Supported OS} * * Currently this works {b only} on Linux. * * {2 Interface} *) val server_auth_method : unit -> Rpc_server.auth_method (** Return the authentication method [AUTH_LOCAL]. * * Note that you need another authentication method that operates at * message level (like AUTH_NONE, AUTH_SYS, AUTH_DH), otherwise you will * get an error [Auth_too_weak]. [AUTH_LOCAL] overrides the result of the * other authentication method. *) val get_peer_credentials : Unix.file_descr -> (int * int);; (** Return the pair (euid,egid) for a Unix domain socket. * The function raises [Invalid_argument] if it is not available for this * operating system. (Generally, this should work on Linux, BSD, and * Solaris, and OS with compatible system functions - supported methods are * [SO_PEERCRED], [getpeerucred], and [getpeereid]). * * Some OS support this only for named Unix domain sockets but not for * socketpairs. *) (* val peek_peer_credentials : Unix.file_descr -> (int * int);; (** Peeks at the next message and returns the pair (euid,egid) for a * Unix domain socket. This function must be called before data is * read from the socket (and it blocks until data is available). * The function raises [Invalid_argument] if it is not available for this * operating system. * The exception [Not_found] is raised if the credentials cannot be * extracted from the control block. * [peek_peer_credentials] seems to be more portable than * [get_peer_credentials]. *) *) ocamlnet-4.1.2/src/rpc-auth-local/Makefile.pre0000644000175000017500000000027612731530351017600 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PRE = 1 PKGNAME = rpc-auth-local GENERATE = META PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" include $(TOP_DIR)/Makefile.rules ocamlnet-4.1.2/src/rpc-auth-local/rpclocal.c0000644000175000017500000001336112731530351017315 0ustar gerdgerd/* $Id$ * ---------------------------------------------------------------------- * */ #define _GNU_SOURCE /* Required on some systems to enable struct ucred in sys/socket.h */ #include "config.h" #include "caml/mlvalues.h" #include "caml/alloc.h" #include "caml/memory.h" #include "caml/fail.h" #ifndef _WIN32 #include #include #include #include #include #include #include #include #endif #ifdef HAVE_GETPEERUCRED #include #endif /**********************************************************************/ /* From unixsupport.h */ /**********************************************************************/ #define Nothing ((value) 0) extern void unix_error (int errcode, char * cmdname, value arg) Noreturn; extern void uerror (char * cmdname, value arg) Noreturn; /**********************************************************************/ /* Inspired by PostgreSQL's fe-connect.c */ value netsys_get_peer_credentials(value fd) { CAMLparam1(fd); CAMLlocal1(result); #if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED) uid_t uid; gid_t gid; #else int uid; int gid; #endif #if defined(HAVE_GETPEEREID) /* BSD, AIX, Cygwin */ /* http://cr.yp.to/docs/secureipc.html */ if (getpeereid(Int_val(fd), &uid, &gid) != 0) { uerror("getpeereid", Nothing); } #elif defined(SO_PEERCRED) /* Linux */ { socklen_t len; struct ucred credentials; len = sizeof(struct ucred); if (getsockopt(Int_val(fd), SOL_SOCKET, SO_PEERCRED, &credentials, &len) == -1) { uerror("getsockopt",Nothing); }; uid = credentials.uid; /* Effective user ID */ gid = credentials.gid; /* Effective group ID */ } #elif defined(HAVE_GETPEERUCRED) /* Solaris */ { ucred_t *ucred; ucred = NULL; /* must be initialized to NULL */ if (getpeerucred(Int_val(fd), &ucred) == -1) { uerror("getpeerucred",Nothing); }; if ((uid = ucred_geteuid(ucred)) == -1) { uerror("ucred_geteuid",Nothing); ucred_free(ucred); }; if ((gid = ucred_getegid(ucred)) == -1) { uerror("ucred_getegid",Nothing); ucred_free(ucred); }; ucred_free(ucred); } #else invalid_argument("get_peer_credentials"); #endif /* Allocate a pair, and put the result into it: */ result = alloc_tuple(2); Store_field(result, 0, Val_int(uid)); Store_field(result, 1, Val_int(gid)); CAMLreturn(result); } /**********************************************************************/ /* * Another way of getting the credentials is too peek the next message * and look at the ancillary data. But this works only if the sender * has set the ancillary data, or if the operating system supports that * the receiver can request credentials. */ #if 0 value netsys_peek_peer_credentials(value fd) { CAMLparam1(fd); CAMLlocal1(result); int uid; int gid; #ifdef SO_PASSCRED /* Linux */ { int one = 1; struct msghdr msg; struct cmsghdr *cmp; struct ucred *sc; char buf[CMSG_SPACE(sizeof(*sc))]; struct iovec iov; char iovbuf[1]; if (setsockopt(Int_val(fd), SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) { uerror("setsockopt", Nothing); }; memset(&msg, 0, sizeof msg); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = buf; msg.msg_controllen = sizeof(buf); iov.iov_base = iovbuf; iov.iov_len = 1; /* Linux requires that at least one byte must be transferred. * So we initialize the iovector for exactly one byte. */ if (recvmsg(Int_val(fd), &msg, MSG_PEEK) < 0) { uerror("recvmsg", Nothing); }; if (msg.msg_controllen == 0 || (msg.msg_flags & MSG_CTRUNC) != 0) { raise_not_found(); }; cmp = CMSG_FIRSTHDR(&msg); if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_CREDENTIALS) { raise_not_found(); }; sc = (struct ucred *) CMSG_DATA(cmp); uid = sc->uid; gid = sc->gid; } #else #ifdef LOCAL_CREDS /* NetBSD */ /* The following code has been copied from libc: rpc/svc_vc.c * TODO: The following code does not work. No idea why. * msg_controllen is always 0. Maybe the socket option must be * set earlier (but that would be very strange). */ { int one = 1; struct msghdr msg; struct cmsghdr *cmp; void *crmsg = NULL; struct sockcred *sc; socklen_t crmsgsize; struct iovec iov; char buf; if (setsockopt(Int_val(fd), SOL_SOCKET, LOCAL_CREDS, &one, sizeof(one)) < 0) { uerror("setsockopt", Nothing); }; memset(&msg, 0, sizeof msg); crmsgsize = CMSG_SPACE(SOCKCREDSIZE(NGROUPS_MAX)); crmsg = stat_alloc(crmsgsize); memset(crmsg, 0, crmsgsize); msg.msg_control = crmsg; msg.msg_controllen = crmsgsize; msg.msg_iov = &iov; msg.msg_iovlen = 1; iov.iov_base = &buf; iov.iov_len = 1; if (recvmsg(Int_val(fd), &msg, MSG_PEEK) < 0) { stat_free(crmsg); uerror("recvmsg", Nothing); }; if (msg.msg_controllen == 0 || (msg.msg_flags & MSG_CTRUNC) != 0) { stat_free(crmsg); raise_not_found(); }; cmp = CMSG_FIRSTHDR(&msg); if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_CREDS) { stat_free(crmsg); raise_not_found(); }; sc = (struct sockcred *)(void *)CMSG_DATA(cmp); uid = sc->sc_euid; gid = sc->sc_egid; free(crmsg); } #else invalid_argument("peek_peer_credentials"); #endif #endif /* Allocate a pair, and put the result into it: */ result = alloc_tuple(2); Store_field(result, 0, Val_int(uid)); Store_field(result, 1, Val_int(gid)); CAMLreturn(result); } #endif ocamlnet-4.1.2/src/rpc-auth-local/rpc_auth_local.ml0000644000175000017500000000253012731530351020657 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) external get_peer_credentials : Unix.file_descr -> (int * int) = "netsys_get_peer_credentials" ;; (* external peek_peer_credentials : Unix.file_descr -> (int * int) = "netsys_peek_peer_credentials" ;; * *) class server_auth_method : Rpc_server.auth_method = object method name = "AUTH_LOCAL" method flavors = [ ] method peek = `Peek_descriptor (fun d -> match Netsys.getpeername d with Unix.ADDR_UNIX _ -> (* Try now peek_peer_credentials: *) begin try let uid, gid = get_peer_credentials d in let username = string_of_int uid ^ "." ^ string_of_int gid ^ "@localhost" in Some username with Invalid_argument _ -> (* peek_peer_credentials is not available for this OS *) None | Not_found -> (* Some other failure *) None | Unix.Unix_error(Unix.EAGAIN,_,_) -> (* peek_peer_credentials expects that there is a message * to read. EAGAIN is raised if we call it in the wrong * moment. *) None end | _ -> None ) method authenticate _ _ _ _ = () method invalidate() = () method invalidate_connection _ = () end let server_auth_method() = new server_auth_method ocamlnet-4.1.2/src/netcamlbox/0000755000175000017500000000000012731530351014667 5ustar gerdgerdocamlnet-4.1.2/src/netcamlbox/Makefile0000644000175000017500000000050512731530351016327 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PKGNAME = netcamlbox OBJECTS = netcamlbox.cmo DOBJECTS = netcamlbox.mli OCAMLC_OPTIONS += $(STRING_OPTS) OCAMLOPT_OPTIONS += $(STRING_OPTS) PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" INCLUDES = $(INC_NETSYS) include $(TOP_DIR)/Makefile.rules include depend ocamlnet-4.1.2/src/netcamlbox/netcamlbox.mli0000644000175000017500000003163712731530351017540 0ustar gerdgerd(* $Id$ *) (** Camlboxes are a fast IPC mechanism to send Ocaml values from one process to another. Source and destination processes must run on the same machine (no network). The Ocaml value is copied to a shared memory object where it can be directly accessed by the receiver without unmarshalling step. This means the sender writes the value into the shared memory in a format that can immediately interpreted by the receiver. A camlbox is owned by the single receiving process. Only this process (or a fork) can look for new messages and can read them. There can be any number of sending processes, i.e. we have a n:1 message passing scenario. The receiver process creates the camlbox, and is seen as the owner. The receiver is accountible for deleting the camlbox when it is no longer needed. The sender(s) can send messages to any existing camlbox. There is no notification whether the messages are actually read. The sender, however, blocks when the destination camlbox is full, and will only proceed when the receiver makes room for new messages. If there is space in the camlbox the sender does not need to synchronize with the receiver, i.e. it is possible to put a message into the box when the receiver is busy with something else (asynchronous send operation). Camlboxes have a fixed capacity of messages, and the message slots have a fixed maximum length. The messages can have any type with only a few restrictions (e.g. no functions and no custom blocks). There is no check whether the sender and the receiver assume the same type of the messages. This is left to the user. Breaking this assumption will lead to unpredictable effects, including program crashes. It is strongly advised to only communicate between processes that run the same executable. The user is also responsible for keeping only references to existing messages. It is possible to get a value pointer for a certain message via [camlbox_get] and then to delete the message. The user must no longer access the value - once the value is deleted it may be overwritten, and the program may crash. Another danger is that message values are modified so that pointers to heap values are put into the message. This may lead to delayed crashes when the heap value is moved to a different location or is even deleted by the garbage collector. There is nothing the camlbox implementation can do about that. If this is a problem, it is advised to use [camlbox_get_copy] instead which is not dangerous in this respect. On the system level, camlboxes are stored in POSIX shared memory objects. These objects have kernel persistence and continue to live after the process creating the camlbox has terminated without unlinking the box. This module requires Ocaml 3.11 or newer. The system must support POSIX shared memory and POSIX semaphores. Camlboxes may be used in multi-threaded programs as long as the values [camlbox] and [camlbox_sender] are not used by several threads at the same time. {b Examples.} There a few examples in the distribution tarball (examples/camlbox). {b Multi-core:} Camlboxes can be used to gain speed-ups on multi-cores. See examples/camlbox/README in the distribution tarball for an example how to accomplish this. {b Integration into event-based programs:} See the section below, {!Netcamlbox.events}. *) (** {b Since OCaml-4.01:} This OCaml version changed the semantics of the built-in primitives [caml_modify] and [caml_initialize]. Essentially, it is no longer possible to modify OCaml values residing outside the regular OCaml heap. As we do this inside Netcamlbox, this change affects this library. Fortunately, there is a workaround on systems supporting weak symbols (all ELF systems and OS X): Here, [caml_modify] and [caml_initialize] are overridden by Netcamlbox so that they are again compatible. Note that this is a global modification of the runtime system! Future versions of Ocamlnet may solve this problem differently. *) type camlbox_address = string (** The address of a camlbox is a string that does not contain slashes. Addresses are system-global. *) type 'a camlbox (** A [camlbox] may receive messages of type ['a] *) type 'a camlbox_sender (** An endpoint that may send messages of type ['a] to a camlbox *) exception Empty exception Message_too_big val create_camlbox : camlbox_address -> int -> int -> 'a camlbox (** [create_camlbox addr n size]: Creates a new camlbox for up to [n] messages of [size] bytes. The messages are numbered from 0 to [n-1]. The camlbox is only meaningful for the creating process, and must not be directly accessed by other processes. Other processes can only send using a [camlbox_sender]. It is an error if the camlbox already exists. It is suggested that the result of [create_camlbox] is immediately coerced to the right type [t], e.g. {[ let box = (create_camlbox addr n size : t camlbox) ]} as this ensures type safety for all following operations. {b Note that camlboxes have kernel persistence! They are not automatically deleted when the process finishes. Call [unlink_camlbox] to delete camlboxes.} *) val unlink_camlbox : camlbox_address -> unit (** Removes the global name of the camlbox. All functions requiring a [camlbox_address] as input will not find the box anymore. The box, however, continues to exist until the receiver and the senders are done with it. *) val format_camlbox : camlbox_address -> Unix.file_descr -> int -> int -> 'a camlbox (** [format_camlbox addr fd n size]: The file [fd] is mapped into memory, and formatted as camlbox. In Ocamlnet-3.6, the function got the extra [camlbox_address] argument. *) val camlbox_addr : 'a camlbox -> camlbox_address (** returns the address *) val camlbox_saddr : 'a camlbox_sender -> camlbox_address (** returns the address *) val camlbox_fd : camlbox_address -> Unix.file_descr (** Opens a new file descriptor to this address *) val camlbox_capacity : camlbox_address -> int (** Returns the maximum number of messages [n] *) val camlbox_bcapacity : 'a camlbox -> int (** same for an already opened box *) val camlbox_scapacity : 'a camlbox_sender -> int (** same for a box already opened for sending *) val camlbox_msg_size : camlbox_address -> int (** Returns the max size of a message in bytes *) val camlbox_bmsg_size : 'a camlbox -> int (** same for an already opened box *) val camlbox_smsg_size : 'a camlbox_sender -> int (** same for a box already opened for sending *) val camlbox_messages : camlbox_address -> int (** Returns the number of messages at the moment *) val camlbox_bmessages : 'a camlbox -> int (** same for an already opened box *) val camlbox_smessages : 'a camlbox_sender -> int (** same for a box already opened for sending *) val camlbox_get : 'a camlbox -> int -> 'a (** [camlbox_get box k]: Returns message number [k] from [box]. The returned value lives in the camlbox, and using it is only safe as long as the camlbox exists and the message is not deleted. If there is no message at [k] the exception [Empty] will be raised. The result value must have the same type as the sent value. This is not checked, however. Violating this rule is likely to crash the program. *) val camlbox_get_copy : 'a camlbox -> int -> 'a (** [camlbox_get box k]: Returns a deep copy of message number [k] from [box]. This is safer than [camlbox_get], because the returned value remains valid when the message is deleted from the box. If there is no message at [k] the exception [Empty] will be raised. The result value must have the same type as the sent value. This is not checked, however. Violating this rule is likely to crash the program. *) val camlbox_delete : 'a camlbox -> int -> unit (** [camlbox_delete box k]: Deletes the message number [k] from [box]. Any value obtained via [camlbox_get] for a message or a part of a message becomes invalid and must not be used anymore. There is no way to check this - violating this rule is likely to crash the program. (In doubt use [camlbox_get_copy] instead which cannot interfer with [camlbox_delete].) If there is no message at [k] the exception [Empty] will be raised. *) val camlbox_wait : 'a camlbox -> int list (** Waits until new messages arrive, and return the message numbers. A new message is only reported once by [camlbox_wait]. The order of the messages is not specified. Only one thread at a time must wait for new messages. It is allowed that this function returns the empty list. *) val camlbox_cancel_wait : 'a camlbox -> unit (** Cancels a [camlbox_wait] operation called by a different thread *) val camlbox_sender : camlbox_address -> 'a camlbox_sender (** Prepares for sending. It is suggested that the result of [camlbox_sender] is immediately coerced to the right type [t], e.g. {[ let box = (camlbox_sender addr : t camlbox_sender) ]} as this ensures type safety for all following operations. *) val camlbox_sender_of_fd : camlbox_address -> Unix.file_descr -> 'a camlbox_sender (** Gets a sender for a file descriptor from [camlbox_fd]. Ocamlnet-3.6: new arg [camlbox_address] *) val camlbox_send : ?prefer:int -> ?slot:int ref -> 'a camlbox_sender -> 'a -> unit (** Sends a message to a camlbox. The value must be boxed (neither [char], [bool], [int], nor a variant type), and a number of restrictions apply: - The size of the representation must not exceed the maximum message size of the camlbox, or the exception [Message_too_big] is raised. - Objects, closures, and lazy values are not supported - Abstract and custom block values are not supported except bigarrays, [int32], [int64], and [nativeint]. - Atoms (like empty arrays) may cause problems when the message is extracted by [camlbox_get] because atoms are duplicated, and no longer unique. For example, a test [if array=[||] then...] is likely not to work. Use [if Array.length array = 0 then...], or use [camlbox_get_copy] for extraction. The value is copied to the receiving camlbox. This function blocks until the receiving camlbox has free space. Several threads may try to send messages at the same time. [prefer]: suggests a slot for sending [slot]: the actual slot number is stored here *) val camlbox_wake : 'a camlbox_sender -> unit (** Sends an "empty message" - this only means that if the receiving thread is waiting for new messages it is interrupted and [camlbox_wait] will return the empty list. This function is non-blocking. *) (** {2:events Integration into event-based programs} The functions [camlbox_wait] and [camlbox_send] may both block the execution of the program when no message has arrived, and no space is available, respectively. This is a challenge for event-based programs where all waiting is bound to events on file descriptors. Generally, Camlboxes use semaphores for speed. The results are good, often only 4 microseconds for sending and receiving a short message. This is only possible because semaphores implement a fast path where the help of the kernel is not needed, i.e. no context switch happens. This is basically incompatible with the style of waiting implemented for file descriptors, because this kind of waiting for an event must always go through the kernel, and is thus slower by design. But anyway, what to do if Camlboxes need to be integrated into a program that bases already on file descriptor polling? Of course, speed will decrease, but maybe not dramatically. We assume here that the program uses {!Unixqueue}s as the basic data structure for organizing polling. If the program can use the Netmulticore library, there is a very simple solution. The condition variables provided by this library allow the integration into Unixqueues, see {!Netmcore_condition}. The condition variable is signalled whenever a new message is put into the Camlbox, and the receiver waits until this signal arrives. The function {!Netmcore_condition.wait_e} permits it to integrate waiting into a Unixqueue. Otherwise, if Netmulticore is no option (e.g. because the processes are unrelated that communicate via Camlboxes), the other workaround is to use threads. A special thread is set up which waits for new Camlbox messages. Whenever a message arrives, an engine is notified via a {!Uq_engines.signal_engine} (which is thread-safe). This engine can run in a different thread. *) module Debug : sig val enable : bool ref end ocamlnet-4.1.2/src/netcamlbox/META.in0000644000175000017500000000025412731530351015746 0ustar gerdgerdversion = "@VERSION@" requires = "netsys netsys.outofheap" archive(byte) = "netcamlbox.cma" archive(native) = "netcamlbox.cmxa" archive(native,gprof) = "netcamlbox.p.cmxa" ocamlnet-4.1.2/src/netcamlbox/netcamlbox.ml0000644000175000017500000004527012731530351017365 0ustar gerdgerd(* $Id$ *) (* Format of the shm object: - Const: CAPACITY Number of message slots - Const: MSG_SIZE Max size of messages - Sem: NOTIFICATIONS This semaphore is increased by the sender to wake up the receiver, and decreased by the receiver. - Sem: FREE_SLOTS Number of free slots. Increased by the receiver on [delete]. Decreased by the sender when waiting for space. - For each slot: SLOT_READABLE (one byte per slot). The number 1 if the slot is filled and has a readable message, or 0 if it is free or should be ignored by the receiver. - Array SLOT_LIST and number SPLIT_IDX: The array positions 0 .. SPLIT_IDX-1 contain the numbers of the filled slots. The array positions SPLIT_IDX .. CAPACITY-1 contain the numbers of the free slots. Sem SLOT_LOCK: mutex for SLOT_LIST and SPLIT_IDX. Sending: - sem_wait(FREE_SLOTS) - lock SLOT_LOCK - find a free slot, and move it to the part of the slot list with the filled slots - unlock SLOT_LOCK - copy the value to the chosen slot - SLOT_READABLE := 1 - sem_post(NOTIFICATIONS) Receiving: 1. Wait for message: - sem_wait(NOTIFICATIONS) - lock SLOT_LOCK - get the part of the slot list with the filled slots - unlock SLOT_LOCK - for each filled slot: - get the value of SLOT_READABLE. If it is 0 skip the slot. - if the slot was already reported to the user, skip the slot - otherwise include the slot in the result list 2. Get message: - test SLOT_READABLE. If it is 1 read the message 3. Delete the message: - Remove the message from the messages that "wait" already reported - SLOT_READABLE := 0 - lock SLOT_LOCK - move the slot to the part of the slot list with the empty slots - unlock SLOT_LOCK - sem_post(FREE_SLOTS) FORMAT OF THE SHARED MEMORY OBJECT: byte 0:
byte : byte : byte : first slot. Slots come one after the other, and are aligned at 128 byte boundaries
: the ocaml representation of type [header] : the semaphores one after the other : the ocaml representation of type [int array] *) module Debug = struct let enable = ref false end let dlog = Netlog.Debug.mk_dlog "Netcamlbox" Debug.enable let dlogr = Netlog.Debug.mk_dlogr "Netcamlbox" Debug.enable let () = Netlog.Debug.register_module "Netcamlbox" Debug.enable open Netsys_mem open Printf type camlbox_address = string (* The header must not contain pointers, so it is relocatable *) type header = { mutable address : int; (* address lsr 1 *) mutable sem_offset : int; (* offset to semaphore area *) mutable sl_offset : int; (* offset to slot_list *) mutable offset : int; (* offset to first slot *) capacity : int; msg_size : int; mutable free_slots : int; mutable split_idx : int; (* function pointers for custom operations: the header contains the pointers the receiver uses. *) bigarray_custom_ops : int; int32_custom_ops : int; int64_custom_ops : int; nativeint_custom_ops : int; } type semaphores = { s_notifications : Netsys_sem.anon_semaphore; s_free_slots : Netsys_sem.anon_semaphore; s_slot_lock : Netsys_sem.anon_semaphore ; slot_readable : int array; (* pointer to the byte *) } type 'a camlbox = { mem : memory; hdr : header; (* pointing into mem *) slot_list : int array; (* pointing into mem *) sem : semaphores; (* pointing into mem *) is_new : bool array; (* local *) addr : string; cont : Netsys_sem.container; (* local *) } type 'a camlbox_sender = 'a camlbox exception Empty exception Message_too_big let align = 128 (* header and slots are aligned by this *) let ws_bytes = (* word size in bytes *) Sys.word_size / 8 let this_bigarray_custom_ops = Netsys_mem.get_custom_ops (Bigarray.Array1.create Bigarray.char Bigarray.c_layout 1) let this_int32_custom_ops = Netsys_mem.get_custom_ops 0l let this_int64_custom_ops = Netsys_mem.get_custom_ops 0L let this_nativeint_custom_ops = Netsys_mem.get_custom_ops 0n let ntoi n = (* for addresses *) Nativeint.to_int(Nativeint.shift_right n 1) let iton i = (* for addresses *) Nativeint.shift_left (Nativeint.of_int i) 1 let create_header capacity msg_size = let dummy = Bigarray.Array1.create Bigarray.char Bigarray.c_layout 0 in let hdr = { address = 0; sem_offset = 0; sl_offset = 0; offset = 0; capacity = capacity; msg_size = msg_size; free_slots = capacity; split_idx = 0; bigarray_custom_ops = ntoi (snd this_bigarray_custom_ops); int32_custom_ops = ntoi (snd this_int32_custom_ops); int64_custom_ops = ntoi (snd this_int64_custom_ops); nativeint_custom_ops = ntoi (snd this_nativeint_custom_ops); } in let _, hdr_bytelen = init_value dummy 0 hdr [ Copy_simulate ] in hdr.sem_offset <- hdr_bytelen; let sem_bytelen = 3 * Netsys_sem.sem_size + capacity in let cap8 = sem_bytelen mod 8 in let sem_padding = if cap8 = 0 then 0 else 8 - cap8 in let slot_list = Array.init capacity (fun k -> k) in let _, sl_bytelen = init_value dummy 0 slot_list [ Copy_simulate ] in hdr.sl_offset <- hdr_bytelen + sem_bytelen + sem_padding; let bytelen = hdr_bytelen + sem_bytelen + sem_padding + sl_bytelen in hdr.offset <- (((bytelen-1) / align) + 1) * align; dlogr (fun () -> sprintf "create_header cap=%d msgsize=%d sem_offs=%d sl_offs=%d offs=%d" capacity msg_size hdr.sem_offset hdr.sl_offset hdr.offset ); (hdr, slot_list) let init_semaphores hdr mem cont = let offset = hdr.sem_offset in let init_sem k v = ignore( Netsys_sem.sem_init cont mem (offset+k*Netsys_sem.sem_size) true v) in init_sem 0 0; (* notifications *) init_sem 1 hdr.capacity; (* free_slots *) init_sem 2 1; (* slot_lock *) let b = 3 in let b_bytes = offset+b*Netsys_sem.sem_size in for k = 0 to hdr.capacity-1 do mem.{ b_bytes + k } <- '\000' done let destroy_semaphores hdr mem cont = (* Must be called before shm is unmapped (only in the receiver) *) let offset = hdr.sem_offset in for k = 0 to 2 do let s = Netsys_sem.as_sem cont mem (offset+k*Netsys_sem.sem_size) in Netsys_sem.sem_destroy cont s done let free_mem cont mem = let hdr = (as_value mem ws_bytes : header) in destroy_semaphores hdr mem cont let get_semaphores hdr mem cont = let offset = hdr.sem_offset in let get_sem k = Netsys_sem.as_sem cont mem (offset+k*Netsys_sem.sem_size) in let semrec = { s_notifications = get_sem 0; (* notifications *) s_free_slots = get_sem 1; (* free_slots *) s_slot_lock = get_sem 2; (* slot_lock *) slot_readable = Array.init hdr.capacity (fun k -> offset + 3*Netsys_sem.sem_size + k) } in dlog "get_semaphores"; semrec let mk_camlbox fn_name addr capacity msg_size cont f = if not (Netsys_sem.have_anon_semaphores()) then invalid_arg (sprintf "%s (no anonymous semaphores)" fn_name); if capacity < 1 || capacity > Sys.max_array_length || msg_size < 1 then invalid_arg (sprintf "%s (bad params)" fn_name); if capacity > Netsys_sem.sem_value_max then invalid_arg (sprintf "%s (capacity exceeds sem_value_max)" fn_name); let slot_size = (((msg_size-1) / align) + 1) * align in if slot_size < msg_size then (* overflow *) invalid_arg (sprintf "%s (too large)" fn_name); let (hdr0, slot_list0) = create_header capacity msg_size in let shm_size = hdr0.offset + capacity * slot_size in if shm_size < hdr0.offset then (* overflow *) invalid_arg (sprintf "%s (too large)" fn_name); if (shm_size - hdr0.offset) / slot_size <> capacity then (* overflow *) invalid_arg (sprintf "%s (too large)" fn_name); let mem = f shm_size in value_area mem; hdr0.address <- ntoi (memory_address mem); let hdr_voffs, _ = init_value mem 0 hdr0 [] in let hdr = (as_value mem hdr_voffs : header) in init_semaphores hdr mem cont; let sl_voffs, _ = init_value mem hdr.sl_offset slot_list0 [] in let slot_list = (as_value mem sl_voffs : int array) in Gc.finalise (free_mem cont) mem; let sem = get_semaphores hdr mem cont in dlogr (fun () -> sprintf "mk_camlbox fn_name=%s cap=%d msgsize=%d slot_size=%d shm_size=%d" fn_name capacity msg_size slot_size shm_size ); { mem = mem; hdr = hdr; slot_list = slot_list; sem = sem; is_new = Array.make capacity true; addr = addr; cont = cont } let format_camlbox addr fd capacity msg_size = if not (Netsys_posix.have_posix_shm()) then invalid_arg "format_camlbox (no POSIX shm)"; if String.contains addr '/' then invalid_arg "format_camlbox (bad name)"; let cont = Netsys_sem.container ("/" ^ addr) in mk_camlbox "format_camlbox" addr capacity msg_size cont (fun shm_size -> Unix.ftruncate fd shm_size; Netsys_mem.memory_map_file fd true shm_size ) let create_camlbox addr capacity msg_size = if not (Netsys_posix.have_posix_shm()) then invalid_arg "create_camlbox (no POSIX shm)"; if String.contains addr '/' then invalid_arg "create_camlbox (bad name)"; let cont = Netsys_sem.create_container ("/" ^ addr) in let box = mk_camlbox "create_camlbox" addr capacity msg_size cont (fun shm_size -> let shm = Netsys_posix.shm_open ("/" ^ addr) [ Netsys_posix.SHM_O_RDWR; Netsys_posix.SHM_O_CREAT; Netsys_posix.SHM_O_EXCL ] 0o600 in let mem = try Unix.ftruncate shm shm_size; let mem = Netsys_mem.memory_map_file shm true shm_size in Unix.close shm; mem with | error -> Unix.close shm; Netsys_sem.drop cont; raise error in mem ) in dlog "create_camlbox returning"; box let unlink_camlbox addr = Netsys_posix.shm_unlink ("/" ^ addr); Netsys_sem.unlink ("/" ^ addr) let camlbox_fd addr = Netsys_posix.shm_open ("/" ^ addr) [ Netsys_posix.SHM_O_RDWR ] 0o600 let with_fd fd f = try let r = f fd in Unix.close fd; r with | error -> Unix.close fd; raise error let dummy_header () = { address = 0; sem_offset = 0; sl_offset = 0; offset = 0; capacity = 0; msg_size = 0; split_idx = 0; free_slots = 0; bigarray_custom_ops = 0; int32_custom_ops = 0; int64_custom_ops = 0; nativeint_custom_ops = 0; } let header_size = lazy( let dummy = Bigarray.Array1.create Bigarray.char Bigarray.c_layout 0 in let hdr = dummy_header () in let voffset, bytelen = init_value dummy 0 hdr [ Copy_simulate ] in bytelen ) let camlbox_open cont addr fd = (* does not initialize is_new! *) let hdr_size = Lazy.force header_size in let mini_mem = Netsys_mem.memory_map_file fd true hdr_size in let hdr0 = (as_value mini_mem ws_bytes : header) in let offset = hdr0.offset in let slot_size = (((hdr0.msg_size-1) / align) + 1) * align in let shm_size = offset + hdr0.capacity * slot_size in let mem = Netsys_mem.memory_map_file fd true shm_size in let hdr = (as_value mem ws_bytes : header) in let sl = (as_value mem (hdr.sl_offset+ws_bytes) : int array) in dlogr (fun () -> sprintf "camlbox_open hdr_size=%d offset=%d slot_size=%d shm_size=%d" hdr_size offset slot_size shm_size ); { mem = mem; hdr = hdr; slot_list = sl; sem = get_semaphores hdr mem cont; is_new = [| |]; addr = addr; cont = cont; } let camlbox_addr box = box.addr let camlbox_saddr box = box.addr let camlbox_sender addr = let cont = Netsys_sem.container ("/" ^ addr) in with_fd (camlbox_fd addr) (camlbox_open cont addr) let camlbox_sender_of_fd addr = let cont = Netsys_sem.container ("/" ^ addr) in camlbox_open cont addr let camlbox_bcapacity box = box.hdr.capacity let camlbox_scapacity = camlbox_bcapacity let camlbox_capacity addr = let cont = Netsys_sem.container ("/" ^ addr) in with_fd (camlbox_fd addr) (fun fd -> let box = camlbox_open cont addr fd in camlbox_bcapacity box ) let camlbox_bmsg_size box = box.hdr.msg_size let camlbox_smsg_size = camlbox_bmsg_size let camlbox_msg_size addr = let cont = Netsys_sem.container ("/" ^ addr) in with_fd (camlbox_fd addr) (fun fd -> let box = camlbox_open cont addr fd in camlbox_bmsg_size box ) let camlbox_bmessages box = let free = try Netsys_sem.sem_getvalue box.sem.s_free_slots with Unix.Unix_error(Unix.ENOSYS,_,_) -> (* OS X *) Netsys_sem.sem_wait box.sem.s_slot_lock Netsys_sem.SEM_WAIT_BLOCK; let free = box.hdr.free_slots in Netsys_sem.sem_post box.sem.s_slot_lock; free in box.hdr.capacity - free let camlbox_smessages = camlbox_bmessages let camlbox_messages addr = let cont = Netsys_sem.container ("/" ^ addr) in with_fd (camlbox_fd addr) (fun fd -> let box = camlbox_open cont addr fd in camlbox_bmessages box ) let is_slot_readable_nolock fn_name box k = let p = box.sem.slot_readable.(k) in box.mem.{p} <> '\000' let is_slot_readable fn_name box k = let used = Netsys_sem.sem_wait box.sem.s_slot_lock Netsys_sem.SEM_WAIT_BLOCK; let p = box.sem.slot_readable.(k) in let used = box.mem.{p} <> '\000' in Netsys_sem.sem_post box.sem.s_slot_lock; used in dlogr (fun () -> sprintf "is_slot_readable fn_name=%s slot=%d used=%B p=%d p_used=%B" fn_name k used (box.sem.slot_readable.(k)) (box.mem.{box.sem.slot_readable.(k)} <> '\000') ); used let camlbox_get box k = if k < 0 || k >= box.hdr.capacity then invalid_arg "camlbox_get"; if not (is_slot_readable "camlbox_get" box k) then raise Empty; let slot_size = (((box.hdr.msg_size-1) / align) + 1) * align in let slot_offset = box.hdr.offset + k * slot_size in dlogr (fun () -> sprintf "camlbox_get slot=%d slot_offset=%d slot_size=%d" k slot_offset slot_size ); as_value box.mem (slot_offset + ws_bytes) let camlbox_get_copy box k = Netsys_mem.copy_value [Netsys_mem.Copy_custom_int; Netsys_mem.Copy_bigarray] (camlbox_get box k) let swap (x:int array) p q = let u = x.(p) in x.(p) <- x.(q); x.(q) <- u let camlbox_delete box k = if k < 0 || k >= box.hdr.capacity then invalid_arg "camlbox_delete"; if not (is_slot_readable "camlbox_delete" box k) then raise Empty; box.is_new.(k) <- true; Netsys_sem.sem_wait box.sem.s_slot_lock Netsys_sem.SEM_WAIT_BLOCK; let l = box.slot_list in let j = ref 0 in ( try for i = 0 to box.hdr.split_idx - 1 do if l.(i) = k then ( j := i; raise Exit ) done; assert false with | Exit -> () ); swap l !j (box.hdr.split_idx-1); box.hdr.split_idx <- box.hdr.split_idx - 1; box.hdr.free_slots <- box.hdr.free_slots + 1; let p = box.sem.slot_readable.(k) in box.mem.{p} <- '\000'; Netsys_sem.sem_post box.sem.s_slot_lock; Netsys_sem.sem_post box.sem.s_free_slots let camlbox_wait box = dlog "camlbox_wait "; Netsys_sem.sem_wait box.sem.s_notifications Netsys_sem.SEM_WAIT_BLOCK; let n = ref 0 in ( try while true do (* decrement to 0 *) Netsys_sem.sem_wait box.sem.s_notifications Netsys_sem.SEM_WAIT_NONBLOCK; incr n; done with | Unix.Unix_error(Unix.EAGAIN,_,_) -> () ); dlogr (fun () -> sprintf "camlbox_wait #notifications=%d" !n); Netsys_sem.sem_wait box.sem.s_slot_lock Netsys_sem.SEM_WAIT_BLOCK; let l = box.slot_list in let filled = ref [] in for i = 0 to box.hdr.split_idx - 1 do let k = l.(i) in if is_slot_readable_nolock "camlbox_wait" box k then filled := k :: !filled (* NB. Because of the 2-phase sending (first allocate, then fill the slot), it is possible to find a used slot that is not yet completely filled with a message *) done; dlogr (fun () -> sprintf "camlbox_wait slots=%s" (String.concat " " (List.map (fun i -> sprintf "%d<%s>" i (if box.is_new.(i) then "new" else "old") ) !filled )) ); let r = List.filter (fun i -> box.is_new.(i) ) !filled in Netsys_sem.sem_post box.sem.s_slot_lock; List.iter (fun k -> box.is_new.(k) <- false) r; r let camlbox_cancel_wait box = Netsys_sem.sem_post box.sem.s_notifications let camlbox_wake = camlbox_cancel_wait let find_free_slot box p = let rec loop i = if i < box.hdr.capacity then ( if box.slot_list.(i) = p then Some(p,i) else loop (i+1) ) else None in loop box.hdr.split_idx let camlbox_send ?prefer ?slot box value = (* First phase: find a free slot *) Netsys_sem.sem_wait box.sem.s_free_slots Netsys_sem.SEM_WAIT_BLOCK; Netsys_sem.sem_wait box.sem.s_slot_lock Netsys_sem.SEM_WAIT_BLOCK; assert(box.hdr.split_idx < box.hdr.capacity); let i_opt = match prefer with | None -> None | Some p -> find_free_slot box p in let k = match i_opt with | None -> box.slot_list.(box.hdr.split_idx) | Some(p,i) -> let save = box.slot_list.(box.hdr.split_idx) in box.slot_list.(box.hdr.split_idx) <- p; box.slot_list.(i) <- save; p in box.hdr.split_idx <- box.hdr.split_idx + 1; ( match slot with | None -> () | Some s -> s := k ); box.hdr.free_slots <- box.hdr.free_slots - 1; Netsys_sem.sem_post box.sem.s_slot_lock; (* Phase 2: Fill the slot. The slot_lock is released *) let slot_size = (((box.hdr.msg_size-1) / align) + 1) * align in let slot_offset = box.hdr.offset + k * slot_size in let target_custom_ops = [ fst this_bigarray_custom_ops, iton box.hdr.bigarray_custom_ops; fst this_int32_custom_ops, iton box.hdr.int32_custom_ops; fst this_int64_custom_ops, iton box.hdr.int64_custom_ops; fst this_nativeint_custom_ops, iton box.hdr.nativeint_custom_ops; ] in let (_, _) = try init_value ~targetaddr:(iton box.hdr.address) ~target_custom_ops box.mem slot_offset value [ Netsys_mem.Copy_bigarray; Netsys_mem.Copy_custom_int; Netsys_mem.Copy_atom ] with Out_of_space -> raise Message_too_big in (* Finally make the filled slot visible for the receiver *) Netsys_sem.sem_wait box.sem.s_slot_lock Netsys_sem.SEM_WAIT_BLOCK; let p = box.sem.slot_readable.(k) in dlogr (fun () -> sprintf "camlbox_send slot=%d p=%d" k p ); assert(box.mem.{p} = '\000'); box.mem.{p} <- '\001'; Netsys_sem.sem_post box.sem.s_slot_lock; Netsys_sem.sem_post box.sem.s_notifications ocamlnet-4.1.2/src/netcamlbox/Makefile.pre0000644000175000017500000000027212731530351017115 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PRE = 1 PKGNAME = netcamlbox GENERATE = META PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" include $(TOP_DIR)/Makefile.rules ocamlnet-4.1.2/src/nethttpd/0000755000175000017500000000000012731530350014364 5ustar gerdgerdocamlnet-4.1.2/src/nethttpd/nethttpd_kernel.mli0000644000175000017500000006356012731530350020273 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Nethttpd; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) (** {1 The protocol kernel of the HTTP daemon} * * This module mainly defines the [http_protocol] class which implements the * exchange of messages with a HTTP client. The request messages are represented * as sequence of [req_token] values. The response is encapsulated in a separate * [http_response] class. The contents of the response are represented as sequence * of [resp_token] values. *) (* HTTP protocol kernel for daemon *) open Nethttp open Nethttpd_types type fatal_error = [ `Broken_pipe | `Broken_pipe_ignore | `Message_too_long | `Timeout | `Unix_error of Unix.error | `TLS_error of string * string | `Server_error ] (** These are the serious protocol violations after that the daemon stops * any further processing. * * Note that [`Timeout] refers to a timeout in the middle of a request. * [`Broken_pipe_ignore] is the "harmless" version of [`Broken_pipe] * (see [config_suppress_broken_pipe]). * * Long messages are fatal because it is suspected that they are denial * of service attacks. The kernel generates [`Message_too_long] only for * long headers, not for long bodies. * * Fatal server errors can happen when exceptions are not properly handled. * As last resort the HTTP daemon closes the connection without notifying * the client. * * [`TLS_error] means any error on the TLS level. The two strings identify * the problem as for {!Netsys_tls.Error}. *) val string_of_fatal_error : fatal_error -> string (** Convert error to a string, for logging *) type bad_request_error = [ `Bad_header_field of string | `Bad_header | `Bad_trailer | `Bad_request_line | `Request_line_too_long | `Protocol_not_supported | `Unexpected_eof | `Format_error of string ] (** A bad request is a violation where the current request cannot be * decoded, and it is not possible to accept further requests over the * current connection. *) val string_of_bad_request_error : bad_request_error -> string (** Convert error to a string, for logging *) val status_of_bad_request_error : bad_request_error -> http_status (** Returns the best response code for the error *) type data_chunk = Bytes.t * int * int (** A [data_chunk] is a substring of a string. The substring is described by * the triple [(s, pos, len)] where [s] is the container, [pos] is the * position where the substring begins, and [len] its length. *) type status_line = int * string (** = (code, phrase) *) type transfer_coding = [ `Identity | `Chunked ] type resp_token = [ `Resp_info_line of (status_line * http_header) | `Resp_status_line of status_line | `Resp_header of http_header | `Resp_body of data_chunk | `Resp_trailer of http_trailer | `Resp_end | `Resp_action of (unit -> unit) ] (** The [resp_token] represents a textual part of the response to send: * - [`Resp_info_line] is an informational status line (code=100..199). There can * be several informational lines, and they can be accompanied with their own * headers. Such lines are only sent to HTTP/1.1 clients. * - [`Resp_status_line] is the final status line to send (code >= 200) * - [`Resp_header] is the whole response header to send * - [`Resp_body] is the next part of the response body to send. * - [`Resp_trailer] is the whole response trailer to send (currently ignored) * - [`Resp_action] is special because it does not directly represent a token * to send. The argument is a function which is called when the token is * the next token on the active event queue. The function is also called when * the event queue is dropped because of an error (the state of the * response object indicates this). The function must not raise exceptions * except [Unix_error], and it must not block. *) val resp_100_continue : resp_token (** The predefined token for the "100 Continue" response *) type resp_state = [ `Inhibited | `Queued | `Active | `Processed | `Error | `Dropped ] (** The response state: * - [`Inhibited] = it is not yet allowed to start the response * - [`Queued] = the response waits on the queue for activation * - [`Active] = the response is currently being transmitted * - [`Processed] = the response has been completely sent * - [`Error] = an error occurred during the transmission of this response * - [`Dropped] = an earlier response forced to close the connection, and * this response is dequeued *) type front_token = [ `Resp_wire_data of data_chunk | `Resp_end ] (** Tokens generated by [http_response]: * - [`Resp_wire_data] are data tokens. * - [`Resp_end] indicates the end of the response. *) exception Send_queue_empty type announcement = [`Ignore | `Ocamlnet | `Ocamlnet_and of string | `As of string ] (** See config *) (** Encapsultation of the HTTP response for a single request *) class type http_response = object (** Represents the action of sending the response * * This class has an internal * queue of response tokens that are not yet processed. One can easily add * new tokens to the end of the queue ([send]). * * The class is responsible for determining the transfer encoding: * - When the HTTP version is 1.0, the encoding is always "identity", and the * connection will be closed after the response. * - When the HTTP version is 1.1, and there is a Content-length header, * the encoding will be selected as "identity". It is checked whether the * body has really this length. If too short, it is suggested to close * the connection. If too long, the extra part of the message is silently * dropped. * - When the HTTP version is 1.1, and there is no Content-length header, * the encoding will be selected as "chunked". * * Currently, the [TE] request header is not taken into account. The trailer * is always empty. * * The following headers are set (or removed) by this class: * - [Transfer-Encoding] * - [Trailer] * - [Date] * - [Connection] * - [Upgrade] * - [Server] (it is appended to this field) * * Responses for HEAD requests have the special behaviour that the body is silently * dropped. The calculation of header fields is not affected by this. This means * that HEAD can be easily implemented by doing the same as for GET. * * Responses for other requests that must not include a body must set * [Content-Length] to 0. *) (** These methods can be called by the content provider: *) method state : resp_state (** Reports the state. The initial state is [`Inhibited] *) method bidirectional_phase : bool (** The bidrectional phase starts after "100 Continue" has been sent to the * client, and stops when the response body begins. The bidirectional phase * is special for the calculation of timeout values (input determines the timeout * although the response has started). *) method send : resp_token -> unit (** Add token to the end of the send queue *) method send_queue_empty : bool (** Return whether the send queue is empty. When the state is [`Inhibited], this * method fakes an empty queue. *) method protocol : protocol (** The HTTP version of the response. This is currently always HTTP/1.1, but maybe * we need to fake lower versions for buggy clients. Let's see what comes. *) method close_connection : bool (** Returns whether the connection should be closed after this response. * This flag should be evaluated when the [`Resp_end] front token has been * reached. *) method transfer_encoding : transfer_coding (** Returns the selected transfer encoding. This is valid after the header * has been passed to this object with [send]. *) method front_token : front_token (** The first token of the queue, represented as [data_chunk]. Raises * [Send_queue_empty] when there is currently no front token, or the state * is [`Inhibited]. * If there is a front token, it will never have length 0. * * Note that [Unix_error] exceptions can be raised when [`Resp_action] * tokens are processed. *) method set_callback : (unit -> unit) -> unit (** The function will be called when either [set_state] changes the state, * or when the send queue becomes empty. Note that the callback must never * fail, it is called in situations that make it hard to recover from errors. *) method body_size : int64 (** Accumulated size of the response body *) (** These methods must only be called by the HTTP protocol processor: *) method set_state : resp_state -> unit (** Sets the state *) method advance : int -> unit (** Tell this object that [n] bytes of the front token could be really * sent using [Unix.write]. If this means that the whole front token * has been sent, the next token is pulled from the queue and is made * the new front token. Otherwise, the data chunk representing the * front token is modified such that the position is advanced by * [n], and the length is reduced by [n]. *) end class http_response_impl : ?close:bool -> ?suppress_body:bool -> int64 -> protocol -> announcement -> http_response (** Exported for debugging and testing only *) val send_static_response : http_response -> http_status -> http_header option -> Bytes.t -> unit (** Sends the string argument as response body, together with the given status and * the header (optional). Response header fields are set as follows: * - The [Content-Length] is set to the length of the string. * - The [Content-Type] is set to "text/html" unless given by the header. * If the header object is passed in, these modifications are done * directly in this object as side effect. *) val send_file_response : http_response -> http_status -> http_header option -> Unix.file_descr -> int64 -> unit (** Sends the contents of a file as response body, together with the given status and * the header (optional). The descriptor must be a file descriptor (that cannot * block). The int64 number is the length * of the body. Response header fields are set as follows: * - The [Content-Length] is set to the length of the string. * - The [Content-Type] is set to "text/html" unless given by the header. * * Note that [Content-Range] is not set automatically, even if the file is only * partially transferred. * * If the header object is passed in, these modifications are done * directly in this object as side effect. * * The function does not send the file immediately, but rather sets the [http_response] * object up that the next chunk of the file is added when the send queue becomes * empty. This file will be closed when the transfer is done. *) type request_line = http_method * protocol (** The method (including the URI), and the HTTP version *) type req_token = [ `Req_header of request_line * http_header * http_response | `Req_expect_100_continue | `Req_body of data_chunk | `Req_trailer of http_trailer | `Req_end | `Eof | `Fatal_error of fatal_error | `Bad_request_error of bad_request_error * http_response | `Timeout ] (** A [req_token] represents a textual part of the received request: * - [`Req_header] is the full received header. Together with the header, * the corresponding [http_response] object is returned which must * be used to transmit the response. * - [`Req_expect_100_continue] is generated when the client expects that the * server sends a "100 Continue" response (or a final status code) now. * One should add [`Resp_info_line resp_100_continue] to the send queue * if the header is acceptable, or otherwise generate an error response. In any * case, the rest of the request must be read until [`Req_end]. * - [`Req_body] is a part of the request body. The transfer-coding, if any, * is already decoded. * - [`Req_trailer] is the received trailer * - [`Req_end] indicates the end of the request (the next request may begin * immediately). * - [`Eof] indicates the end of the stream * - [`Bad_request_error] indicates that the request violated the HTTP protocol * in a serious way and cannot be decoded. It is required to send a * "400 Bad Request" response. The following token will be [`Eof]. * - [`Fatal_error] indicates that the connection crashed. * The following token will be [`Eof]. * - [`Timeout] means that nothing has been received for a certain amount * of time, and the protocol is in a state that the next request can begin. * The following token will be [`Eof]. * * Note that it is always allowed to [send] tokens to the client. The protocol * implementation takes care that the response is transmitted at the right point * in time. *) val string_of_req_token : req_token -> string (** For debugging *) exception Recv_queue_empty (** Configuration values for the HTTP kernel *) class type http_protocol_config = object method config_max_reqline_length : int (** Maximum size of the request line. Longer lines are immediately replied with * a "Request URI too long" response. Suggestion: 32768. *) method config_max_header_length : int (** Maximum size of the header, {b including} the request line. Longer headers * are treated as attack, and cause the fatal error [`Message_too_long]. * Suggestion: 65536. *) method config_max_trailer_length : int (** Maximum size of the trailer *) method config_limit_pipeline_length : int (** Limits the length of the pipeline (= unreplied requests). A value of 0 * disables pipelining. A value of n allows that another request is * received although there are already n unreplied requests. *) method config_limit_pipeline_size : int (** Limits the size of the pipeline in bytes. If the buffered bytes in the * input queue exceed this value, the receiver temporarily stops reading * more data. The value 0 has the effect that even the read-ahead of * data of the current request is disabled. The value (-1) disables the * receiver completely (not recommended). *) method config_announce_server : announcement (** Whether to set the [Server] header: * - [`Ignore]: The kernel does not touch the [Server] header. * - [`Ocamlnet]: Announce this web server as "Ocamlnet/" * - [`Ocamlnet_and s]: Announce this web server as [s] and append * the Ocamlnet string. * - [`As s]: Announce this web server as [s] *) method config_suppress_broken_pipe : bool (** Whether to suppress [`Broken_pipe] errors. Instead * [`Broken_pipe_ignore] is reported. *) method config_tls : Netsys_crypto_types.tls_config option (** If set, the server enables TLS with the arugment config *) end val default_http_protocol_config : http_protocol_config (** Default config: - [config_max_reqline_length = 32768] - [config_max_header_length = 65536] - [config_max_trailer_length = 32768] - [config_limit_pipeline_length = 5] - [config_limit_pipeline_size = 65536] - [config_announce_server = `Ocamlnet] - [config_suppress_broken_pipe = false] - [config_tls = None] *) class modify_http_protocol_config : ?config_max_reqline_length:int -> ?config_max_header_length:int -> ?config_max_trailer_length:int -> ?config_limit_pipeline_length:int -> ?config_limit_pipeline_size:int -> ?config_announce_server:announcement -> ?config_suppress_broken_pipe:bool -> ?config_tls:Netsys_crypto_types.tls_config option -> http_protocol_config -> http_protocol_config (** Modifies the passed config object as specified by the optional arguments *) (** Allows it to set hooks for {!Nethttpd_kernel.http_protocol} *) class type http_protocol_hooks = object method tls_set_cache : store:(string -> string -> unit) -> remove:(string -> unit) -> retrieve:(string -> string) -> unit (** Sets the functions for accessing the session cache *) end (** The core event loop of the HTTP daemon *) class http_protocol : #http_protocol_config -> Unix.file_descr -> object (** Exchange of HTTP messages * * In [fd] one must pass the already connected socket. It must be in non- * blocking mode. * * How to use this class: Basically, one invokes [cycle] until the whole * message exchange on [fd] is processed. [cycle] receives data from the * socket and sends data to the socket. There are two internal queues: * * The receive queue stores parts of received requests as [req_token]. * One can take values from the front of this queue by calling [receive]. * * The response queue stores [http_response] objects. Each of the objects * corresponds to a request that was received before. This queue is handled * fully automatically, but one can watch its length to see whether all responses * are actually transmitted over the wire. * * The basic algorithm to process messages is: * * {[ * let rec next_token () = * if proto # recv_queue_len = 0 then ( * proto # cycle (); * next_token() * ) * else * proto # receive() * * let cur_token = ref (next_token()) in * while !cur_token <> `Eof do * (* Process first token of next request: *) * match !cur_token with * | `Req_header(req_line, header, resp) -> * (* Depending on [req_line], read further tokens until [`Req_end] *) * ... * (* Switch to the first token of the next message: *) * cur_token := next_token() * | `Timeout -> ... * | `Bad_request_error(e,resp) -> * (* Generate 400 error, send it to [resp] *) * ... * (* Switch to the first token of the next message: *) * cur_token := next_token() * | `Fatal_error e -> failwith "Crash" * | _ -> assert false * done; * while proto # resp_queue_len > 0 do * proto # cycle (); * done; * proto # shutdown() * ]} * * See the file [tests/easy_daemon.ml] for a complete implementation of this. * * As one can see, it is essential to watch the lengths of the queues in order * to figure out what has happened during [cycle]. * * When the body of the request is empty, [`Req_body] tokens are omitted. * Note that for requests like [GET] that always have an empty body, it is * still possible that an errorneous client sends a body, and that [`Req_body] * tokens arrive. One must accept and ignore these tokens. * * Error handling: For serious errors, the connection is immediately aborted. * In this case, [receive] returns a [`Fatal_error] token. Note that the * queued responses cannot be sent! An example of this is [`Broken_pipe]. * * There is a large class of non-serious errors, esp. format errors * in the header and body. It is typical of these errors that one cannot determine * the end of the request properly. For this reason, the daemon stops reading * further data from the request, but the response queue is still delivered. * For these errors, [receive] returns a [`Bad_request_error] token. * This token contains a [http_response] object that must be filled with a * 400 error response. *) method hooks : http_protocol_hooks (** Set hooks *) method cycle : ?block:float -> unit -> unit (** Looks at the file descriptor. If there is data to read from the descriptor, * and there is free space in the input buffer, additional data is read into * the buffer. It is also tried to interpret the new data as [req_token]s, * and if possible, new [req_token]s are appended to the receive queue. * * If the response queue has objects, and there is really data one can send, * and if the socket allows one to send data, it is tried to send as much * data as possible. * * The option [block] (default: 0) can be set to wait until data * can be exchanged with the socket. This avoids busy waiting. The number * is the duration in seconds to wait until the connection times out * (0 means not to wait at all, -1 means to wait infinitely). When a timeout * happens, and there is nothing to send, and the last request was fully * processed, [receive] will simply return [`Timeout] (i.e. when * [waiting_for_next_message] is [true]). Otherwise, the * fatal error [`Timeout] is generated. *) method receive : unit -> req_token (** Returns the first [req_token] from the receive queue. Raises * [Recv_queue_empty] when the queue is empty (= has no new data) *) method peek_recv : unit -> req_token (** Peeks the first token, but leaves it in the queue. * Raises [Recv_queue_empty] when the queue is empty. *) method recv_queue_len : int (** Returns the length of the receive queue (number of tokens) *) method resp_queue_len : int (** Returns the length of the internal response queue (number of [http_response] * objects that have not yet fully processed) *) method pipeline_len : int (** Returns the number of unanswered requests = Number of received [`Req_end] tokens * minus number of responses in state [`Processed]. Note that [pipeline_len] * can become [-1] when bad requests are responded. *) method recv_queue_byte_size : int (** Returns the (estimated) size of the input queue in bytes *) method waiting_for_next_message : bool (** Whether the kernel is currently waiting for the beginning of a new * arriving HTTP request. This is [false] while the request is being * received. *) method input_timeout_class : [ `Normal | `Next_message | `None ] (** Suggests the calculation of a timeout value for input: * - [`Normal]: The normal timeout value applies * - [`Next_message]: The timeout value applies while waiting for the next message * - [`None]: The connection is output-driven, no input timeout value *) method shutdown : unit -> unit (** Shuts the socket down. Note: the descriptor is not closed. TLS: You need to further [cycle] until XXX. *) method timeout : unit -> unit (** Process a timeout condition as [cycle] does *) method abort : fatal_error -> unit (** Stops the transmission of data. The receive queue is cleared and filled * with the two tokens [`Fatal_error] and [`Eof]. * The response queue is cleared. The [cycle] * method will return immediately without doing anything. *) method fd : Unix.file_descr (** Just returns the socket *) method do_input : bool (** Returns [true] iff the protocol engine is interested in new data from the * socket. Returns [false] after EOF and after errors. *) method do_output : bool (** Returns [true] iff the protocol engine has data to output to the socket *) method resp_queue_filled : bool (** Whether there is data to send in the internal output queue. If TLS is enabled, this is not always the same as [do_output]. *) method need_linger : bool (** Returns [true] when a lingering close operation is needed to reliably shut * down the socket. In many cases, this expensive operation is not necessary. * See the class [lingering_close] below. *) method tls_session_props : Nettls_support.tls_session_props option (** If TLS is enabled, this returns the session properties. These are first available after the TLS handshake. *) method config : http_protocol_config (** Just returns the configuration *) method test_coverage : string list (** For testing: returns a list of tokens indicating into which cases the program * ran. *) end (** Closes a file descriptor using the "lingering close" algorithm. The optional [preclose] function is called just before [Unix.close]. *) class lingering_close : ?preclose:(unit->unit) -> Unix.file_descr -> object (** Closes a file descriptor using the "lingering close" algorithm * * Usage: * {[ while lc # lingering do lc # cycle ~block:true () done ]} *) method cycle : ?block:bool -> unit -> unit (** Reads data from the file descriptor until EOF or until a fixed timeout * is over. Finally, the descriptor is closed. If [block] is set, the method * blocks until data is available. (Default: [false]) *) method lingering : bool (** Whether the socket is still lingering *) method fd : Unix.file_descr (** The file descriptor *) end (** {1 Debugging} *) module Debug : sig val enable : bool ref (** Enables {!Netlog}-style debugging of this module *) end ocamlnet-4.1.2/src/nethttpd/Makefile0000644000175000017500000000131512731530350016024 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PKGNAME = nethttpd OBJECTS = nethttpd_types.cmo nethttpd_util.cmo \ nethttpd_kernel.cmo nethttpd_reactor.cmo \ nethttpd_engine.cmo nethttpd_services.cmo nethttpd_plex.cmo DOBJECTS = nethttpd_types.mli nethttpd_kernel.mli nethttpd_reactor.mli \ nethttpd_engine.mli nethttpd_services.mli nethttpd_plex.mli \ nethttpd_util.mli nethttpd_intro.txt INCLUDES += $(INC_EQUEUE) $(INC_NETSTRING) $(INC_NETCGI2) $(INC_NETPLEX) \ $(INC_NETSYS) OCAMLC_OPTIONS += $(STRING_OPTS) OCAMLOPT_OPTIONS += $(STRING_OPTS) PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" DOC_IGNORABLE = true include $(TOP_DIR)/Makefile.rules include depend ocamlnet-4.1.2/src/nethttpd/nethttpd_util.mli0000644000175000017500000000077412731530350017766 0ustar gerdgerd(* $Id$ *) (** Utility functions *) open Nethttpd_types val std_error_response : error_response_params -> string (** Returns the HTML text of the standard error response *) val std_error_log_string : request_info -> string -> string (** Returns a log line for error logging *) val std_access_log_string : full_info -> string (** Returns a log line for access logging *) val std_debug_access_log_string : full_info -> string (** Returns a log string for extended access logging (multi-line) *) ocamlnet-4.1.2/src/nethttpd/nethttpd_types.mli0000644000175000017500000004371112731530350020153 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with WDialog; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) (** Type definitions for the HTTP daemon * * {b Contents} * * - {!Nethttpd_types.exceptions} * - {!Nethttpd_types.environment} * - {!Nethttpd_types.service} * - {!Nethttpd_types.helpers} *) (** Many types can also be found in the [Nethttp] module (part of netstring). * Furthermore, [Netcgi_env] and [Netcgi_types] are of interest (part of cgi). *) (** {1:exceptions Exceptions} *) open Nethttp exception Standard_response of http_status * http_header option * string option (** Some HTTP containers allow you to raise this exception. The standard * response corresponding to [http_status] is sent back to the client. * If the third argument exists, an entry into the error log * is written. *) (**********************************************************************) (** {1:environment Environment} *) type output_state = [ `Start | `Sending | `End ] val string_of_output_state : output_state -> string (** Debugging *) (** An extension of [cgi_environment] for use with the daemon. The methods * retrieving the socket addresses are virtual. *) class type virtual v_extended_environment = object inherit Netcgi.cgi_environment method virtual server_socket_addr : Unix.sockaddr method virtual remote_socket_addr : Unix.sockaddr (** These are always the physical IP addresses and ports of the two endpoints * of the current connection. *) method cgi_request_uri : string (** The full request URI. Identical to the CGI property "REQUEST_URI" *) method log_props : (string * string) list -> unit (** Remember this version of [cgi_properties] as the one sent to the [config_log_access] function *) method input_channel : Netchannels.in_obj_channel (** The input channel for reading the body of the request *) method input_body_size : int64 (** so far known, or 0L *) method request_body_rejected : bool (** so far known, or false *) method send_file : Unix.file_descr -> int64 -> unit (** Sends the output header with a file as body. The file must already be open, * and positioned where the transmission begins. The number is the length * of the transmission. * * This method may return immediately when it is possible to open the file, and * to set the kernel up for file transmission. Otherwise a [Unix_error] is * raised. It is also allowed that this method blocks until the file is actually * transmitted. * * It is not allowed to print to the output channel and to call [send_file]. * Only one transmission method must be invoked. *) method virtual output_state : output_state ref (** Reflects the state of the output generation: - [`Start]: Nothing is generated yet - [`Sending]: Output is already being sent - [`End]: The response (for a single request) has been fully sent *) method tls_session_props : Nettls_support.tls_session_props option (** The TLS session properties if TLS is active *) end (** Same as [v_extended_environment], but no virtual methods *) class type extended_environment = object inherit v_extended_environment method server_socket_addr : Unix.sockaddr method remote_socket_addr : Unix.sockaddr method output_state : output_state ref end (** {2 Construction of environments} *) class virtual empty_environment : object inherit v_extended_environment val mutable config : Netcgi.config val mutable protocol : Nethttp.protocol val mutable in_header : http_header val mutable out_header : http_header val mutable properties : (string * string) list val mutable in_channel : Netchannels.in_obj_channel val mutable out_channel : Netchannels.out_obj_channel val mutable tls_session_props : Nettls_support.tls_session_props option end (** This class implements an environment with defined internal containers. * These containers are empty, but fully functional. * The following methods are empty and should be redefined: * - [send_output_header] * - [send_file] * - [log_error] * - [log_props] * * The virtual methods, of course, must be defined! *) class redirected_environment : ?in_header : http_header -> ?properties : (string * string) list -> ?in_channel : Netchannels.in_obj_channel -> extended_environment -> extended_environment (** This class overlays the input-side containers of an existing environment. * The output-side containers ([out_header], and [out_channel]) * are physically identical with the existing environment. * * If one of the argument is not passed on class instantiation, the corresponding * overlay container is initialized with the current value of the passed * environment. As exception of this rule, the input channel is initialized with * an empty input channel. *) (** {2 Auxiliary Functions for Environments} *) val output_static_response : #extended_environment -> http_status -> http_header option -> string -> unit (** Outputs the string argument as response body, together with the given status and * the header (optional). Response header fields are set as follows: * - The [Content-Length] is set to the length of the string. * - The [Content-Type] is set to "text/html" unless given by the header. * * If the header is not passed, the header of the environment is taken. If the header * argument exists, however, it overrides the header of the environment. *) val output_file_response : #extended_environment -> http_status -> http_header option -> string -> int64 -> int64 -> unit (** Outputs the contents of a file as response body, together with the given status and * the header (optional). The string is the file name. The first int64 number is * the position in the file where to start, and the second number is the length * of the body. Response header fields are set as follows: * - The [Content-Length] is set to the length of the string. * - The [Content-Type] is set to "text/html" unless given by the header. * * Note that [Content-Range] is not set automatically, even if the file is only * partially transferred. * * If the header is not passed, the header of the environment is taken. If the header * argument exists, however, it overrides the header of the environment. * * The function raises [Sys_error] when the file cannot be read. *) (** {1 Generating error responses, logging} *) class type request_info = object method server_socket_addr : Unix.sockaddr (** The socket address of this server. May raise [Not_found] if there is no such address *) method remote_socket_addr : Unix.sockaddr (** The socket address of the client. May raise [Not_found] if there is no such address *) method request_method : string (** The method like [GET]. May raise [Not_found] *) method request_uri : string (** The URI of the client request. This is often without the server designation, i.e. just [/path?query]. May raise [Not_found] *) method input_header : Nethttp.http_header (** The request header. May raise [Not_found] *) method cgi_properties : (string * string) list (** The distilled CGI properties *) method input_body_size : int64 (** The size of the input body. May raise [Not_found] *) method tls_session_props : Nettls_support.tls_session_props option (** The TLS properties *) end class type full_info = object inherit request_info method response_status_code : int (** The HTTP status code to response *) method request_body_rejected : bool (** Whether the request body was rejected *) method output_header : Nethttp.http_header (** The response header *) method output_body_size : int64 (** The size of the output body. *) end class create_full_info : response_status_code:int -> request_body_rejected:bool -> output_header:Nethttp.http_header -> output_body_size:int64 -> request_info -> full_info (** Creates a [full_info] object by adding to a [request_info] object *) class type error_response_params = object inherit request_info method response_status_code : int (** The HTTP status code to response *) method error_message : string (** The error message explaining the detail that went wrong *) end class type min_config = object method config_error_response : error_response_params -> string method config_log_error : request_info -> string -> unit end (** Minimal configuration needed for [output_std_response] *) val output_std_response : #min_config -> #extended_environment -> http_status -> http_header option -> string option -> unit (** Outputs a "standard response" for the [http_status]. The string argument * is an optional entry into the error log. * * If the header is not passed, an empty header is taken. If the header argument * exists, this header is taken. The header of the environment is never taken. *) (**********************************************************************) (** {1:service Service Providers} * * Service providers are defined using the three class types: * - [http_service]: The service provider as such. When a HTTP header has been * received, and the service provider is invoked, it returns an object * fitting to the next class type, [http_service_receiver]. This object * is tagged with [`Accept_body]; at this point there are also alternate ways * of processing, see below. * - [http_service_receiver]: The task of this object is to receive the request * body. When the body has been completely received, the object is notified, * and returns a third object of type [http_service_generator]. * - [http_service_generator]: The task of this object is to generate the * response. * * An implementor is free to define only one class that satisfies all three * class types at once. However, this is only an option. * * The three objects reflect three stages of HTTP processing. The stages have * made explicit to allow the implementor of services to intercept the points * in time when the processing of the next stage begins. Furthermore, in multi-threaded * environments it is allowed that the stages are performed in the contexts of * different threads. * * In addition to the three-stage model there also several faster paths of * processing: * - [`Reject_body] can be used to refuse the acceptance of the request body when * it is already clear that an error response is sent back. This path skips * the stage [http_service_receiver]. * - [`Static] can be used to send a constant string back (only to be used * when the string needs not to be computed) * - [`File] can be used to send the contents of a file back (only to be used * when the file already exists) *) exception Redirect_request of string * http_header (** The "early" redirect is only allowed in stage 1 of HTTP processing. * The string argument is the new URI path of the request. The header can also * be exchanged except the fields that are needed to decode the request * body. It is not possible to change the method. *) exception Redirect_response of string * http_header (** The "late" redirect is only allowed in stage 3 of HTTP processing. * The string argument is the new URI path of the request. The header can also * be exchanged except the fields that are needed to decode the request * body. {b The method is always changed to [GET].} *) class type http_service_generator = object method generate_response : extended_environment -> unit (** Third stage of HTTP processing: * This method is called when the HTTP request has been completely received, * and the response is going to be generated. This method can again be called * from a different thread than the previous stages. It is allowed to spend * any necessary time to compute the response. * * When the method returns, the request processing is finished. No more data * is allowed to be written to the output channel past this moment. * * The method may raise [Standard_response] to generate one of the * standard messages. *) end class type http_service_receiver = object method process_body : extended_environment -> http_service_generator (** Second stage of HTTP processing: * This method is called when the body is expected to be arriving. Note that * the main difference to [process_header] is that this method can be * called from a different thread. It is allowed (and expected) that this method * blocks while reading the input. Of course, the input and output * channels of the environment are unlocked, and can be used. * * When the method returns, the request processing continues with stage 3. * Any body data not read is dropped. * * It is allowed that this method generates a response (or part of it), * although this should be better done in stage 3. * * The method may raise [Standard_response] to generate one of the * standard messages. * * One way of implementing this method is to instantiate [Netcgi.std_activation]. *) end type http_service_reaction = [ `Accept_body of http_service_receiver | `Reject_body of http_service_generator | `Static of http_status * http_header option * string | `File of http_status * http_header option * string * int64 * int64 | `Std_response of http_status * http_header option * string option ] (** Indicates the immediate reaction upon an arriving HTTP header: * - [`Accept_body] is the regular way of processing requests. If necessary, * the client is told to continue sending the rest of the request. * - [`Reject_body] can be used when the body of the request is not needed, * and the response will be negative. * - [`Static] means to send the header and a constant string back as response. * The header is taken from the environment if not explicitly passed, * Note: The [Content-Length] header is automatically added. The [Content-Type] * defaults to "text/html". * - [`File] is similar to this, but the data come from a file. The file * is specified by an absolute pathname. The range of the file is given * by the start position and the length of the range. * The header is taken from the environment if not explicitly passed, * Note: The [Content-Length] header is automatically added. The [Content-Type] * defaults to "text/html". * - [`Std_response] is similar to [`Static], however the body is the standard * text for the status code. If the header is omitted, it is taken as empty. * The third argument is an optional entry into the error log. * Note: The [Content-Length] header is automatically added. The [Content-Type] * defaults to "text/html". *) class type ['a] http_service = object method name : string (** The name of the type of the service provider *) method def_term :'a (** The definition term *) method print : Format.formatter -> unit (** Outputs the definition term to a formatter *) method process_header : extended_environment -> http_service_reaction (** First stage of HTTP processing: * This method is called when the HTTP header has been received. This method * must return quickly without blocking the thread how to go on. For example, * this could look as follows: * - Check whether the client is allowed to access this resource. If this * can be done immediately, it should be done now. (If an external service * must be queried, the check must not be done now, but deferred to the * second or third stage.) If the access is denied, an error response can * be sent back using [`Static], [`File], or, if computed, using [`Reject_body]. * - Check whether the request is delegated to another service provider * (e.g. lookup by hostname, by port number, or by URI). In this case, * the result of this [process_header] call is simply the result of the * [process_header] call of the other service provider. * - If this service provider generates the contents, there are mainly two * types of reaction. If the contents are stored in a file, one can simply * return [`File]. Otherwise, return [`Accept_body] to continue with the * second stage. Note that even if no body is expected to arrive, one must * go through the second stage, and drop any unexpected body. * * The argument of this function is the Netcgi environment. The header is * complete, including the request method. One cannot access the input and * output channels at this stage of processing. *) end (**********************************************************************) (** {1:helpers Helpers} *) val update_alist : ('a * 'b) list -> ('a * 'b) list -> ('a * 'b) list (** [update_alist updl l]: Returns the alist with all elements of [updl] * and all elements of [l] that are not member of [updl]. *) ocamlnet-4.1.2/src/nethttpd/nethttpd_plex.mli0000644000175000017500000003121512731530350017753 0ustar gerdgerd(* $Id$ *) (** {1 Netplex support} *) (** The important function is [nethttpd_factory], see below. The other functions are only needed for special effects. An example is explained here: {!Netplex_intro.webserver} *) type config_log_error = Nethttpd_types.request_info -> string -> unit type config_log_access = Nethttpd_types.full_info -> unit type config_error_response = Nethttpd_types.error_response_params -> string (** Three type abbreviations for logging functions *) val std_log_error : Netplex_types.container -> config_log_error (** Returns a function that logs errors using the [log_subch] method of the passed container *) val std_log_access : ?debug:bool -> Netplex_types.container -> config_log_access (** Returns a function that logs accesses using the [log_subch] method of the passed container If [debug] is set, additional debug log messages are printed that dump the whole access (incl. header and all available information) *) val std_error_response : config_error_response (** A sample error response function *) val restrict_file_service_config : Netplex_types.config_file -> Netplex_types.address -> unit (** Restricts the subsections and paremeters in the [service] configuration section of type "file" to the allowed ones. *) val read_file_service_config : Netplex_types.config_file -> Netplex_types.address -> string -> Nethttpd_services.file_service (** [read_file_service_config cfg addr uri_path]: Reads the [service] configuration section of type "file" from config file [cfg] at address [addr]. [uri_path] is the default value put into the [file_uri] component of the returned record if no "uri" configuration parameter exists. (In other words, this is the path of the enclosing "uri" section, or "/" if there is only a "host" section.) All other parameters are only taken from the configuration section. See below at [nethttpd_factory] how a file service needs to be configured. *) val restrict_dynamic_service_config : Netplex_types.config_file -> Netplex_types.address -> unit (** Restricts the subsections and paremeters in the [service] configuration section of type "dynamic" to the allowed ones. *) val read_dynamic_service_config : (string * (Netplex_types.config_file -> Netplex_types.address -> string -> 'a Nethttpd_services.dynamic_service ) ) list -> Netplex_types.config_file -> Netplex_types.address -> string -> 'a Nethttpd_services.dynamic_service (** [read_dynamic_service_config handlers cfg addr uri_path]: Reads the [service] configuration section of type "dynamic" from config file [cfg] at address [addr]. The alist [handlers] defines the available handlers. Every handler [h] is called like [h cfg addr uri_path]. [uri_path] is like in [read_file_service_config], i.e. the path of the enclosing "uri" section, or "/" by default. The [h] function has to return the dynamic service to use, which is also returned by [read_dynamic_service_config]. See below at [nethttpd_factory] how a dynamic service needs to be configured. *) type encap = [ `Reactor | `Engine ] val nethttpd_processor : ?hooks:Netplex_types.processor_hooks -> ?encap:encap -> (Netplex_types.container -> #Nethttpd_reactor.http_reactor_config) -> 'a Nethttpd_types.http_service -> Netplex_types.processor (** [netplex_processor mk_config http_service]: Creates a Netplex processor * for Nethttpd. * * [mk_config] determines the nethttpd config for a container. * This is especially useful for setting the logging functions. * * The resulting processor must be turned into a full Netplex service * by [Netplex_sockserv.create_socket_service] which can then be added * by calling the controller's method [add_service]. * * [hooks]: One can pass a Netplex hook object to set the hooks of the * processor. * * [encap]: Selects the encapsulation, [`Reactor] or [`Engine]. * The default is [`Reactor]. Each encapsulation has specific strengths * and weaknesses: * - [`Reactor] is simpler code. Also, the request and response bodies * need not to be buffered up, and are directly connected with the * underlying socket (low memory requirement). The disadvantage is * that a reactor processes TCP connections serially (important to know * when there is only a single Unix process) * - [`Engine]: The request body needs to be completely buffered up. * If pipelining is enabled, the response bodies are also buffered * (FIXME). * The advantage of this encapsulation is that the engine can * process multiple TCP connections simultaneously, even in a * single process/thread. *) type ('a,'b) service_factory = (string * 'a Nethttpd_services.dynamic_service) list -> Netplex_types.config_file -> Netplex_types.address -> string -> 'b Nethttpd_types.http_service constraint 'b = [ `Dynamic_service of 'a Nethttpd_services.dynamic_service | `File_service of Nethttpd_services.file_service ] (** The service factory function is called when a [service] configuration section of a certain type needs to be read. The function has args [handlers], [cfg], [addr], and [uri_path]. It needs to return the [http_service]. Such a function is usually [read_file_service_config], or [read_dynamic_service_config], or a derivative, whose return value is turned into a [http_service]. This can be done with {!Nethttpd_services.file_service} and {!Nethttpd_services.dynamic_service}. *) val default_services : (string * ('a,'b) service_factory) list (** The default services *) type httpd_factory = { httpd_factory : 'a . (Netplex_types.container -> Nethttpd_reactor.http_reactor_config) -> 'a Nethttpd_types.http_service -> Netplex_types.processor } (** The type of the [nethttpd_processor] function *) val nethttpd_factory : ?name:string -> ?hooks:Netplex_types.processor_hooks -> ?encap:encap -> ?config_cgi:Netcgi.config -> ?handlers:(string * 'a Nethttpd_services.dynamic_service) list -> ?services:(string * ('a,'b) service_factory) list -> ?log_error:(Netplex_types.container -> config_log_error) -> ?log_access:(?debug:bool -> Netplex_types.container -> config_log_access) -> ?error_response:config_error_response -> ?processor_factory:httpd_factory -> ?tls:(module Netsys_crypto_types.TLS_PROVIDER) -> unit -> Netplex_types.processor_factory (** Factory for a web server component. * * {b Configuration file.} See below. * * The [services] optional argument can be used to change the service * types understood. If not passed, it defaults to [default_services]. * The default includes "file" and "dynamic". * * {b Arguments.} * * - [name]: The processor name. Defaults to "nethttpd". This name can * be referenced by the "type" parameters in the [processor] section * of the config file. * - [hooks]: One can pass a Netplex hook object to set the hooks of the * processor. (This argument is ignored if a [processor_factory] is * passed to this function.) * - [encap]: See {!Nethttpd_plex.nethttpd_processor}. (This argument is * ignored if a [processor_factory] is * passed to this function.) * - [config_cgi]: The CGI configuration to use * - [handlers]: a list of handler function. These functions can be * referenced from a [service] section in the config file where * [type="dynamic"] (see example above). Defaults to the empty list. * - [services]: A list of service handlers that can be used * by [service] sections in the config files. Defaults to * {!Nethttpd_plex.default_services} which defines "file" and "dynamic". * - [log_error]: The error logger. Defaults to * {!Nethttpd_plex.std_log_error}. * - [log_access]: The access logger. Defaults to * {!Nethttpd_plex.std_log_access}. * - [error_response]: a handler which is invoked to generate error * responses. Defaults to {!Nethttpd_plex.std_error_response}. * - [processor_factory]: the function creating the processor. * Default is [nethttpd_processor]. * - [tls]: the TLS provider to use. By default, * {!Netsys_crypto.current_tls_opt} is used. *) (** {2 Configuration files} The configuration file understood by [nethttpd_factory] looks like: {[ processor { type = "nethttpd"; (* or what is passed as "name" arg *) timeout = 300.0; timeout_next_request = 15.0; access_log = "enabled"; suppress_broken_pipe = true; host { pref_name = "myhost"; (* optional *) pref_port = 80; (* optional *) names = "myhost:80 yourhost:81"; (* use *:0 for any name *) uri { path = "/the/path"; method { allow = "GET POST"; (* or: deny = "..." *) service { type = "..."; ... } } } uri { ... } } host { ... } } ]} The [access_log] parameter can be set to [off], [enabled], or [debug]. The default is [off]. Access messages go to the "access" subchannel of the component logger. If [enabled], one line is printed with the most important data. If [debug] is set, all access data are printed. If [suppress_broken_pipe] the error "Broken pipe" is not logged in the error log. This error occurs frequently, and may be regarded as a normal condition. The sections [host], [uri] and [method] can be nested to any depth. However, on every nesting level only one of these section types must be used. For example, if a [host] section already contains [uri] subsections, it is not allowed to add [method] subsections. Furthermore, the outermost section must be [host]. The [service] section may be one of (at least if the [services] parameter is not overridden): {[ service { type = "file"; docroot = "/a/path/in/the/filesystem"; uri = "/the/uri/prefix/corresponding/to/docroot"; media_types_file = "/etc/mime.types"; media_type { type = "application/foo"; suffix = "foo" } default_media_type = "text/plain"; enable_gzip = true; (* see doc in nethttpd_services.mli *) index_files = "index.html"; enable_listings = true; hide_from_listings = "README"; (* list of PCRE regexps *) } ]} Note that [uri] is taken from the surrounding [uri] section (or assumed to be "/" if there is none) if omitted. {[ service { type = "dynamic"; handler = "name_of_handler"; } ]} Binds the passed handler here. Any of [host], [uri], and [method] sections may contain one or several [access] sections (which are AND-connected): {[ access { type = "host"; allow = "host1 host2 ..."; (* or deny = "host1 host2 ..."; *) } ]} Other access control methods are not yet available. *) (** {2:tls Configuring TLS} First of all, there needs to be a TLS provider. See {!Tls} for more information how to get one. If the TLS provider is initialized, you can have a [tls] subsection inside [processor], like: {[ processor { ... tls { x509 { trust { crt_file = "ca.pem"; } key { crt_file = "server.crt"; key_file = "server.key"; } } } } ]} All of the files, [ca.pem], [server.crt] and [server.key] need to be PEM-encoded. You can have several [key] sub-sections when you want to do name-based virtual hosting. Note, however, that this relies on the SNI extension of the TLS protocol, and not all clients support this extension. Further parameters inside [tls]: - [algorithms]: This is a string describing the cipher suites and protocol options that are in effect. This string is provider-specific. (GnuTLS calls this string the "priority string".) Example: {[ tls { ... algorithms = "SECURE-128 !ARCFOUR-128"; } ]} - [dh_params]: This sub-section may set DH parameters. Example: {[ tls { ... dh_params { pkcs3_file = "/path/to/pkcs3_file"; } } ]} - [peer_auth]: This string parameter may enable client certificates. Set it to "required" to enforce such a certificate. {[ tls { ... peer_auth = "required"; } ]} *) ocamlnet-4.1.2/src/nethttpd/nethttpd_util.ml0000644000175000017500000000673612731530350017621 0ustar gerdgerd(* $Id$ *) open Nethttpd_types open Printf let std_error_response p = let b = Buffer.create 500 in bprintf b "\n"; bprintf b "\010\ \010\ \010\ \010\ \010\ \n"; let code = p # response_status_code in let text = try Nethttp.string_of_http_status(Nethttp.http_status_of_int code) with Not_found -> "Non-standard code" in bprintf b "

Error %i - %s

\n" code text; bprintf b "The server could not process your request.\n"; bprintf b "For additional information consult the error log of the\n"; bprintf b "server.\n"; bprintf b "
\n"; bprintf b "%s - Ocamlnet Nethttpd server\n" (Netdate.format "%c" (Netdate.create ~zone:Netdate.localzone (Unix.time()))); bprintf b "\n"; bprintf b "\n"; Buffer.contents b let std_error_log_string p msg = let peeraddr_opt = try Some(p # remote_socket_addr) with Not_found -> None in Printf.sprintf "[%s] [%s] %s" ( match peeraddr_opt with | Some addr -> Netsys.string_of_sockaddr ~norm:true addr | None -> "-" ) ( try let m = p # request_method in let u = p # request_uri in m ^ " " ^ u with Not_found -> "-" ) msg let std_access_log_string p = let code = p # response_status_code in let peerstr = try Netsys.string_of_sockaddr ~norm:true p#remote_socket_addr with Not_found -> "-" in let meth = try p#request_method with Not_found -> "-" in let uri = try p#request_uri with Not_found -> "-" in let user = try List.assoc "REMOTE_USER" p#cgi_properties with Not_found -> "-" in let respsize = p#output_body_size in let referrer = try p#input_header#field "Referer" with Not_found -> "-" in let user_agent = try p#input_header#field "User-agent" with Not_found -> "-" in Printf.sprintf "%s %s %s \"%s\" %d %Ld \"%s\" \"%s\"" peerstr user meth (String.escaped uri) code respsize (String.escaped referrer) (String.escaped user_agent) let std_debug_access_log_string p = let b = Buffer.create 500 in let b_ch = new Netchannels.output_buffer b in Printf.bprintf b "%s\n" (std_access_log_string p); Printf.bprintf b "Request header:\n"; ( try Netmime_string.write_header ~soft_eol:"\n" ~eol:"\n" b_ch p#input_header#fields with Not_found -> Printf.bprintf b "(missing)\n"; ); ( try Printf.bprintf b "Request body size: %Ld\n" p#input_body_size with Not_found -> Printf.bprintf b "Request body size: (missing)\n" ); Printf.bprintf b "Request body rejected: %b\n\n" p#request_body_rejected; Printf.bprintf b "CGI properties:\n"; ( try Netmime_string.write_header ~soft_eol:"\n" ~eol:"\n" b_ch p#cgi_properties with Not_found -> Printf.bprintf b "(missing)\n"; ); Printf.bprintf b "Response header (code %d):\n" p#response_status_code; Netmime_string.write_header ~soft_eol:"\n" ~eol:"\n" b_ch p#output_header#fields; Printf.bprintf b "Response body size: %Ld\n" p#output_body_size; Buffer.contents b ocamlnet-4.1.2/src/nethttpd/META.in0000644000175000017500000000033512731530350015443 0ustar gerdgerdversion = "@VERSION@" requires = "netstring,netcgi2,equeue,netplex,netsys" description = "Ocamlnet - HTTP daemon" archive(byte) = "nethttpd.cma" archive(native) = "nethttpd.cmxa" archive(native,gprof) = "nethttpd.p.cmxa" ocamlnet-4.1.2/src/nethttpd/nethttpd_types.ml0000644000175000017500000004044612731530350020004 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with WDialog; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) open Nethttp open Nethttp.Header open Printf exception Standard_response of http_status * http_header option * string option let exn_print_header b hdr = Buffer.add_string b "["; let first = ref true in List.iter (fun (n,v) -> if not !first then Buffer.add_string b ", "; bprintf b "%s: %S" n v; first := false ) hdr#fields; Buffer.add_string b "]" let () = Netexn.register_printer (Standard_response(`Continue, None, None)) (fun e -> match e with | Standard_response(status, hdr_opt, err_opt) -> let b = Buffer.create 200 in Buffer.add_string b "Nethttpd_types.Standard_response("; Buffer.add_string b (Nethttp.string_of_http_status status); Buffer.add_string b ", "; ( match hdr_opt with | None -> Buffer.add_string b "None" | Some hdr -> Buffer.add_string b "Some "; exn_print_header b hdr ); Buffer.add_string b ", "; ( match err_opt with | None -> Buffer.add_string b "None" | Some err -> bprintf b "Some %S" err ); Buffer.add_string b ")"; Buffer.contents b | _ -> assert false ) type output_state = [ `Start | `Sending | `End ] let string_of_output_state = function | `Start -> "Start" | `Sending -> "Sending" | `End -> "End" class type request_info = object method server_socket_addr : Unix.sockaddr method remote_socket_addr : Unix.sockaddr method request_method : string method request_uri : string method input_header : Nethttp.http_header method cgi_properties : (string * string) list method input_body_size : int64 method tls_session_props : Nettls_support.tls_session_props option end class type full_info = object inherit request_info method response_status_code : int method request_body_rejected : bool method output_header : Nethttp.http_header method output_body_size : int64 end class type error_response_params = object inherit request_info method response_status_code : int method error_message : string end class type virtual v_extended_environment = object inherit Netcgi.cgi_environment method virtual server_socket_addr : Unix.sockaddr method virtual remote_socket_addr : Unix.sockaddr method cgi_request_uri : string method log_props : (string * string) list -> unit method input_channel : Netchannels.in_obj_channel method input_body_size : int64 method request_body_rejected : bool method send_file : Unix.file_descr -> int64 -> unit method output_state : output_state ref method tls_session_props : Nettls_support.tls_session_props option end class type extended_environment = object inherit v_extended_environment method server_socket_addr : Unix.sockaddr method remote_socket_addr : Unix.sockaddr end class virtual empty_environment = object(self) val mutable config = Netcgi.default_config val mutable in_header = new Netmime.basic_mime_header [] val mutable out_header = new Netmime.basic_mime_header [] val mutable properties = [] val mutable in_channel = new Netchannels.input_string "" val mutable out_channel = new Netchannels.output_null() val mutable protocol = `Other val mutable cookies = lazy(assert false) val mutable tls_session_props = (None : Nettls_support.tls_session_props option) val output_state = ref (`Start : output_state) initializer ( cookies <- lazy(Nethttp.Header.get_cookie_ct self#input_header) ) method virtual server_socket_addr : Unix.sockaddr method virtual remote_socket_addr : Unix.sockaddr method output_state = output_state method config = config method cgi_properties = properties method cgi_property ?default name = try List.assoc name properties with Not_found -> ( match default with | None -> raise Not_found | Some d -> d ) method cgi_gateway_interface = self # cgi_property ~default:"" "GATEWAY_INTERFACE" method cgi_server_software = self # cgi_property ~default:"" "SERVER_SOFTWARE" method cgi_server_name = self # cgi_property ~default:"" "SERVER_NAME" method cgi_server_protocol = self # cgi_property ~default:"" "SERVER_PROTOCOL" method cgi_server_port = ( try Some(int_of_string(self # cgi_property "SERVER_PORT")) with Not_found -> None ) method cgi_request_method = self # cgi_property ~default:"" "REQUEST_METHOD" method cgi_path_info = self # cgi_property ~default:"" "PATH_INFO" method cgi_path_translated = self # cgi_property ~default:"" "PATH_TRANSLATED" method cgi_script_name = self # cgi_property ~default:"" "SCRIPT_NAME" method cgi_query_string = self # cgi_property ~default:"" "QUERY_STRING" method cgi_remote_host = self # cgi_property ~default:"" "REMOTE_HOST" method cgi_remote_addr = self # cgi_property ~default:"" "REMOTE_ADDR" method cgi_auth_type = self # cgi_property ~default:"" "AUTH_TYPE" method cgi_remote_user = self # cgi_property ~default:"" "REMOTE_USER" method cgi_remote_ident = self # cgi_property ~default:"" "REMOTE_IDENT" method cgi_https = match self # cgi_property ~default:"" "HTTPS" with | "" | "off" -> false | "on" -> true | _ -> failwith "Cannot interpret HTTPS property" method cgi_request_uri = self # cgi_property ~default:"" "REQUEST_URI" method protocol = (protocol : Nethttp.protocol) method send_output_header() = () method send_file (fd:Unix.file_descr) (n:int64) = () method log_error (s : string) = () method log_props (l : (string*string) list) = () method input_header = in_header method output_header = out_header method set_status ( st : http_status ) = out_header # update_field "Status" (string_of_int (int_of_http_status st)) method input_body_size = 0L method request_body_rejected = false (* ---- The following is copied from Netcgi_env: ---- *) (* method input_header = in_header *) method input_header_field ?default name = try in_header # field name with Not_found as nf -> match default with None -> raise nf | Some d -> d method multiple_input_header_field name = in_header # multiple_field name method input_header_fields = in_header # fields method user_agent = self # input_header_field ~default:"" "USER-AGENT" method cookies = Lazy.force cookies method cookie name = List.find (fun c -> Netcgi.Cookie.name c = name) self#cookies method input_channel = in_channel method input_content_length = int_of_string (self # input_header_field "CONTENT-LENGTH") method input_content_type_string = self # input_header_field ~default:"" "CONTENT-TYPE" method input_content_type() = Netmime_string.scan_mime_type_ep (self # input_header_field "CONTENT-TYPE") [] (* method output_header = out_header *) method output_header_field ?default name = try out_header # field name with Not_found as nf -> match default with None -> raise nf | Some d -> d method multiple_output_header_field name = out_header # multiple_field name method output_header_fields = out_header # fields method output_ch = out_channel method out_channel = out_channel method set_output_header_field name value = out_header # update_field name value method set_multiple_output_header_field name values = out_header # update_multiple_field name values method set_output_header_fields h = out_header # set_fields h method tls_session_props = tls_session_props end class redirected_environment ?in_header:new_in_header ?properties:new_properties ?in_channel:(new_in_channel = new Netchannels.input_string "") (env : extended_environment) = object(self) inherit empty_environment (* Inherits new containers for both input and output *) initializer ( config <- env # config; in_header <- ( match new_in_header with | Some h -> h | None -> new Netmime.basic_mime_header env#input_header_fields ); properties <- ( match new_properties with | Some p -> env#log_props p; p | None -> env # cgi_properties ); in_channel <- new_in_channel; ) (* The following methods are always delegated to [env]: *) method server_socket_addr = env # server_socket_addr method remote_socket_addr = env # remote_socket_addr method protocol = env # protocol method send_output_header = env # send_output_header method log_error = env # log_error method output_header = env # output_header method output_header_field = env # output_header_field method multiple_output_header_field = env # multiple_output_header_field method output_header_fields = env # output_header_fields method output_ch = env # output_ch method set_output_header_field = env # set_output_header_field method set_multiple_output_header_field = env # set_multiple_output_header_field method set_output_header_fields = env # set_output_header_fields method set_status = env # set_status method send_file = env # send_file method log_props = env # log_props method input_body_size = 0L method request_body_rejected = false method tls_session_props = env # tls_session_props method output_state = env # output_state (* The variable is shared! *) end class create_full_info ~response_status_code ~request_body_rejected ~output_header ~output_body_size (info : request_info) : full_info = object method server_socket_addr = info#server_socket_addr method remote_socket_addr = info#remote_socket_addr method request_method = info#request_method method request_uri = info#request_uri method input_header = info#input_header method cgi_properties = info#cgi_properties method input_body_size = info#input_body_size method tls_session_props = info#tls_session_props method response_status_code = response_status_code method request_body_rejected = request_body_rejected method output_header = output_header method output_body_size = output_body_size end let output_static_response (env : #extended_environment) status hdr_opt body = ( match hdr_opt with | Some hdr -> env # output_header # set_fields hdr#fields; (* Replaces any existing fields *) | None -> () ); ( match status with | `No_content | `Reset_content | `Not_modified -> () | _ -> ( try ignore(env # output_header_field "Content-Type") with Not_found -> env # set_output_header_field "Content-type" "text/html"; ); ); env # set_output_header_field "Content-Length" (string_of_int (String.length body)); env # set_status status; env # send_output_header(); env # output_ch # output_string body; env # output_ch # close_out(); ;; let rec output_channel_large (f_to : Netchannels.out_obj_channel) f_from length = if length > 0L then ( let n = min length (Int64.of_int max_int) in f_to # output_channel ~len:(Int64.to_int n) f_from; output_channel_large f_to f_from (Int64.sub length n) ) else () (* -- old implementation: let output_file_response (env : #extended_environment) status hdr_opt filename pos length = Netchannels.with_in_obj_channel ( let f = open_in_bin filename in (* or Sys_error *) LargeFile.seek_in f pos; new Netchannels.input_channel f) (fun f_ch -> ( match hdr_opt with | Some hdr -> env # output_header # set_fields hdr#fields; (* Replaces any existing fields *) | None -> () ); ( match status with | `No_content | `Reset_content | `Not_modified -> () | _ -> ( try ignore(env # output_header_field "Content-Type") with Not_found -> env # set_output_header_field "Content-type" "text/html"; ); ); env # set_output_header_field "Content-Length" (Int64.to_string length); env # send_output_header(); output_channel_large env # output_ch f_ch length; env # output_ch # close_out(); ) *) let output_file_response env status hdr_opt filename pos length = let fd = Unix.openfile filename [Unix.O_RDONLY] 0 in ignore(Unix.LargeFile.lseek fd pos Unix.SEEK_SET); ( match hdr_opt with | Some hdr -> env # output_header # set_fields hdr#fields; (* Replaces any existing fields *) | None -> () ); env # set_output_header_field "Status" (string_of_int (int_of_http_status status)); env # send_file fd length ;; class type min_config = object method config_error_response : error_response_params -> string method config_log_error : request_info -> string -> unit end let output_std_response config (env : #extended_environment) status hdr_opt msg_opt = let req_meth = env # cgi_request_method in let req_uri = env # cgi_request_uri in let req_hdr = new Netmime.basic_mime_header env#input_header_fields in let (msg, have_msg) = match msg_opt with | Some msg -> (msg,true) | None -> ("", false) in let code = int_of_http_status status in let info = ( object method server_socket_addr = env#server_socket_addr method remote_socket_addr = env#remote_socket_addr method tls_session_props = env#tls_session_props method request_method = req_meth method request_uri = req_uri method input_header = req_hdr method cgi_properties = env # cgi_properties method input_body_size = 0L (* don't know *) method response_status_code = code method error_message = msg end ) in if have_msg then config # config_log_error (info :> request_info) msg; let body = match status with | `No_content | `Reset_content | `Not_modified -> "" | _ -> config # config_error_response info in let hdr_opt' = match hdr_opt with | Some h -> Some h | None -> Some (new Netmime.basic_mime_header []) in output_static_response env status hdr_opt' body exception Redirect_request of string * http_header exception Redirect_response of string * http_header let () = Netexn.register_printer (Redirect_request("", new Netmime.basic_mime_header [])) (fun e -> match e with | Redirect_request(url, hdr) -> let b = Buffer.create 200 in bprintf b "Nethttpd_types.Redirect_request(%S, " url; exn_print_header b hdr; Buffer.add_string b ")"; Buffer.contents b | _ -> assert false ); Netexn.register_printer (Redirect_response("", new Netmime.basic_mime_header [])) (fun e -> match e with | Redirect_response(url, hdr) -> let b = Buffer.create 200 in bprintf b "Nethttpd_types.Redirect_response(%S, " url; exn_print_header b hdr; Buffer.add_string b ")"; Buffer.contents b | _ -> assert false ) class type http_service_generator = object method generate_response : extended_environment -> unit end class type http_service_receiver = object method process_body : extended_environment -> http_service_generator end type http_service_reaction = [ `Accept_body of http_service_receiver | `Reject_body of http_service_generator | `Static of http_status * http_header option * string | `File of http_status * http_header option * string * int64 * int64 | `Std_response of http_status * http_header option * string option ] class type ['a] http_service = object method name : string method def_term :'a method print : Format.formatter -> unit method process_header : extended_environment -> http_service_reaction end let update_alist updl l = updl @ (List.filter (fun (x,y) -> not (List.mem_assoc x updl)) l) ocamlnet-4.1.2/src/nethttpd/nethttpd_engine.mli0000644000175000017500000003711212731530350020252 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Nethttpd; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) (** {1 The event-based encapsulation of the HTTP daemon} * * This is a user-friendlier encapsulation of the HTTP daemon. It uses * the engine module defined in [Uq_engines]. *) (* Integration into event-based server design *) open Nethttpd_types type engine_req_state = [ `Received_header | `Receiving_body | `Received_request | `Finishing ] class type http_engine_config = object inherit Nethttpd_reactor.http_processor_config method config_input_flow_control : bool (** If [true], the engine stops reading input tokens from the HTTP kernel when * there is data in the input channel of the engine not yet read. If [false], * all available input tokens are fetched from the kernel and buffered up * in the input channel. * * In general, this {b should} be set to [true]. However, this is only possible * when the user of the engine is prepared for flow control. In particular, * all data contained in the input channel must be immediately read, or else * the engine blocks. By calling [input_ch_async # request_notification], the * user can be notified when there is data to read. * * When set to [false], the engine never blocks, but the price is that the * input channel may become as large as needed to store the whole request. * * The option [config_limit_pipeline_size] does not have any effect for engines. *) method config_output_flow_control : bool (** If [true], the engine signals the user when there is already enough data * to output, and no more output should be generated. The user can query * this state by calling [output_ch_async # can_output], and react * accordingly. The user can also ignore this signal, and the output channel * buffers all data. * * If [false], the mentioned method [can_output] returns always [true]. This * turns off flow control in the case it is implemented by the user of the * engine, but actually not wanted. * * The internal processing of data is not affected by this configuration option. * In doubt, set it to [true]. *) end val default_http_engine_config : http_engine_config (** The default config: - [config_input_flow_control=false] - [config_output_flow_control=true] *) class modify_http_engine_config : ?modify_http_protocol_config: (Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config) -> ?modify_http_processor_config: (Nethttpd_reactor.http_processor_config -> Nethttpd_reactor.http_processor_config) -> ?config_input_flow_control:bool -> ?config_output_flow_control:bool -> http_engine_config -> http_engine_config (** Modifies the passed config object as specified by the optional arguments. [modify_http_protocol_config] and [modify_http_processor_config]: These functions can be used to modify the parts of the config object that are inherited from [http_protocol_config] and [http_processor_config], respectively: For example: {[ let new_cfg = new modify_http_engine_config ~modify_http_protocol_config: (new Nethttpd_kernel.modify_http_protocol_config ~config_suppress_broken_pipe:true) ~modify_http_processor_config: (new Nethttpd_reactor.modify_http_processor_config ~config_timeout:15.0) old_cfg ]} *) class type extended_async_environment = object inherit extended_environment (** Environment also providing asynchronous views to I/O *) method input_ch_async : Uq_engines.async_in_channel (** This is the [input_ch] channel taken as asynchonous channel. This type of * channel indicates when data is available to read, and also sends notifications. * Note that this is only an alternate interface of the [input_ch] object. * * The method [can_input] returns true when there is at least one byte of * the body to read, or the EOF has been seen. The channel buffers any arriving * data (which can be limited in amount by [config_pipeline_size]). * * The behaviour of this channel is influenced by the configuration option * [config_input_flow_control]. *) method output_ch_async : Uq_engines.async_out_channel (** This is the [output_ch] channel taken as asynchronous channel. This type of * channel indicates when space is available for further output, and also sends * notifications. * Note that this is only an alternate interface of the [output_ch] object. * * The method [can_output] returns [true] only when the internal buffer is empty, * i.e. all data have been transmitted to the client. Independent of this, the * channel buffers all data written to it. * * The behaviour of this channel is influenced by the configuration option * [config_output_flow_control]. *) end class type http_request_header_notification = object (** Notification that a new request header has arrived * * This object notifies the user that a new request header has arrived. * The header is accessible by the [environment] object. The channels * also contained in this object are locked at this moment. The user must * now either call [schedule_accept_body] or [schedule_reject_body]. The * user will get a second notification (a [http_request_notification], below) * when the request body has completely arrived (in case of acceptance), or * immediately (in case of rejection). One can also call [schedule_finish] * at any time to drop the current request. *) method req_state : engine_req_state (** Returns the request processing state which is [`Received_header] at the * moment when this notification is delivered. *) method environment : extended_async_environment (** The request environment. Depending on the request processing state, parts * of the environment are already set up or still unaccessible ("locked"). * In the state [`Received_header] only the request header and the * derived fields are accessible, and the input and output channels are * locked. In the state [`Receiving_body] the input channel is unlocked, * but it is not yet filled (reading from it may cause the exception * [Buffer_underrun]). The output channel remains locked. * In the state [`Received_request], the input channel is unlocked and filled * with data, and the output channel is unlocked, too. * * This environment is not fully CGI-compatible. In particular, the following * differences exist: * - There is no [cgi_path_info] and no [cgi_path_translated]. * - The user is always unauthenticated. * - The [Status] response header works as in CGI. The [Location] header, however, * must be a full URL when set (only browser redirects) * - When the request body is transmitted by chunked encoding, the header * [Content-Length] is not set. In CGI this is interpreted as missing body. * It is unlikely that clients send requests with chunked encoding, as this * may cause interoperability problems anyway. * *) method schedule_accept_body : on_request:(http_request_notification -> unit) -> ?on_error:(unit -> unit) -> unit -> unit (** Schedules that the request body is accepted. In terms of HTTP, this sends the * "100 Continue" response when necessary. One can reply with a positive or * negative message. * * This method returns immediately, and sets callbacks for certain events. * When the body has completely arrived (or is empty), the function * [on_request] is called back. The argument is the full request notification * (see below). * * When the request is dropped for some reason, [on_error] is called back instead. * This can be used to free resources, for example. * * Neither of the callbacks must raise exceptions. *) method schedule_reject_body : on_request:(http_request_notification -> unit) -> ?on_error:(unit -> unit) -> unit -> unit (** Schedules that the request body is rejected. In terms of HTTP, this prevents * sending the "100 Continue" response. Any arriving request body is silently * discarded. One should immediately reply with an error mesage. * negative message. * * This method returns immediately, and sets callbacks for certain events. * When the body has completely arrived (or is empty), the function * [on_request] is called back. The argument is the full request notification * (see below). * * When the request is dropped for some reason, [on_error] is called back instead. * This can be used to free resources, for example. * * Neither of the callbacks must raise exceptions. *) method schedule_finish : unit -> unit (** Schedules that the request is finished. This method should be called after * the regular processing of the request to ensure that the HTTP protocol * is fulfilled. If the request body has not been * fully read, this is now done, and its data are dropped. If the response * is incomplete, it is completed. If the error is not recoverable, a "Server * Error" is generated. *) end and http_request_notification = object (** Notification that the whole request has arrived * * This object notifies the user that the request has fully arrived (including * the body if accepted), and can now be responded. The [environment] is the * same as in the request header notification, but the channels are now * unlocked. *) method req_state : engine_req_state (** Returns the request processing state which is [`Received_request] at the * moment when this notification is delivered. *) method environment : extended_async_environment (** The request environment. See above. *) method schedule_finish : unit -> unit (** Schedules that the request is finished. See above. *) end class http_engine : ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) -> on_request_header:(http_request_header_notification -> unit) -> unit -> #http_engine_config -> Unix.file_descr -> Unixqueue.unix_event_system -> [unit] Uq_engines.engine (** This engine processes the requests arriving on the file descriptor using * the Unix event system. Whenever a new request header arrives, the function * [on_request_header] is called back, and must handle the request. * * Unless aborted using the [abort] method, this engine is always successful. * Errors are logged, but not returned as result. * * The file descriptor is closed after processing all HTTP requests and * responses. It is also closed on error and when the engine is aborted. * * An aborted engine does not try to clean up resources external to the * engine, e.g. by calling the [on_error] functions. This is up to the user. *) class type http_engine_processing_config = object method config_synch_input : (Netchannels.in_obj_channel -> unit) -> Uq_engines.async_in_channel -> unit (** The "input synchronizer": It is called as [obj # config_synch_input f ch] * to create a synchronous input channel from an asynchronous one, [ch]. * The function [f] must be called back by the synchronizer when synchronisation * is established, and with the synchronous channel [ch'] as argument. * In particular, the task of the synchronizer is to turn blocking reads of * [ch'] into non-blocking reads of [ch]. In general there are two ways of * implementation: * - Buffer all input from [ch] until the end of the channel is reached, * then call [f] with a wrapper channel [ch'] that just reads from the * buffer. * - Run [f] in a different thread that blocks whenever there is nothing to * read from [ch]. * * Both implementations are allowed, i.e. {b it is allowed that [f] runs in * a different thread}. * * CHECK: How to handle exceptions raised from [f]? Idea: [f] is obliged to * close [ch'] in this case, even if [ch] is not yet at the end. The rest of * exception handling is up to the user. - The complementary must also be true: * When there is an error in the engine, [ch] must be closed to signal the * other thread that we have a problem. *) method config_synch_output : (Netchannels.out_obj_channel -> unit) -> Uq_engines.async_out_channel -> unit (** The "output synchronizer": It is called as [obj # config_synch_output f ch] * to create a synchronous output channel from an asynchronous one, [ch]. * The function [f] must be called back by the synchronizer when synchronisation * is established, and with the synchronous channel [ch'] as argument. * In particular, the task of the synchronizer is to turn blocking writes to * [ch'] into non-blocking writes to [ch]. In general there are two ways of * implementation: * - Call [f], then buffer all output to [ch'] until the end of the channel is * reached, and finally output the contents of the buffer in an asynchronous * way. * - Run [f] in a different thread that blocks whenever there is no space to * write to [ch]. * * Both implementations are allowed, i.e. {b it is allowed that [f] runs in * a different thread}. * * CHECK: Exceptions. *) end class buffering_engine_processing_config : http_engine_processing_config (** Implements the synchronisation by buffering *) class type http_engine_processing_context = object method engine : unit Uq_engines.engine (** The engine doing HTTP *) end val process_connection : ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) -> #Nethttpd_reactor.http_processor_config -> #http_engine_processing_config -> Unix.file_descr -> Unixqueue.unix_event_system -> 'a http_service -> http_engine_processing_context (** Sets up an engine that processes all requests using the service description. * This function returns immediately, one needs to [Unixqueue.run] the event * system to start the engine. * * The passed [http_engine_processing_config] is crucial for good performance. * XXX *) (** {1 Debugging} *) module Debug : sig val enable : bool ref (** Enables {!Netlog}-style debugging of this module *) end ocamlnet-4.1.2/src/nethttpd/Makefile.pre0000644000175000017500000000032212731530350016606 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PRE = 1 PKGNAME = nethttpd GENERATE = META INSTALL_EXTRA += LICENSE PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" include $(TOP_DIR)/Makefile.rules ocamlnet-4.1.2/src/nethttpd/nethttpd_reactor.mli0000644000175000017500000003304012731530350020440 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Nethttpd; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) (** {1 The reactive encapsulation of the HTTP daemon} * * This is a user-friendlier encapsulation of the HTTP daemon. It uses a * "pull model": One pulls HTTP requests from the "reactor" one after the * other. Request/response pairs have a common environment that represents * the input and output facilities. Input and output are realised by * [Netchannels], and the implementation details are completely hidden. * * This encapsulation can be easily used in a multi-threaded environment * when for every arriving HTTP connection a separate thread is used. *) open Nethttp open Nethttpd_types class type http_processor_config = object (* This config is also used for engines *) inherit Nethttpd_kernel.http_protocol_config method config_timeout_next_request : float (** Timeout in seconds to wait for the next request after the previous one * has been completely received. (-1) means no timeout. *) method config_timeout : float (** General timeout for network I/O (per I/O primitive). (-1) means no timeout. *) method config_cgi : Netcgi.config (** The CGI configuration to use in the Netcgi environment *) method config_error_response : error_response_params -> string (** Get HTML error text for the HTTP status code. Must return a generic * text for unknown codes. *) method config_log_error : request_info -> string -> unit (** [config_log_error info msg]: Log the message [msg]. Information about the request can be taken from [info]. The request may only be partially available - be prepared that [info] methods raise [Not_found]. *) method config_log_access : full_info -> unit (** Logs the access after the request/response cycle is complete. The [cgi_properties] are from the environment. As there is no automatic way of recording the last, finally used version of this list, it is required that users call [log_props] of the extended environment whenever the properties are updated. This is done by all [Nethttpd] modules. *) method config_tls_cert_props : bool (** Whether to include certificate properties in the cgi environment. (If set to false, the certificates needs not to be parsed again.) *) method config_tls_remote_user : bool (* Whether to set the REMOTE_USER variable to the subject of the client certificate. *) end val default_http_processor_config : http_processor_config (** Default configuration: Extends {!Nethttpd_kernel.default_http_protocol_config} with - [config_timeout_next_request = 15.0] - [config_timeout = 300.0] - [config_cgi = ]{!Netcgi.default_config} - [config_error_response =] {!Nethttpd_util.std_error_response} - [config_log_error]: Uses {!Nethttpd_util.std_error_log_string} to write a log message via {!Netlog}. - [config_log_access]: is a no-op - [config_tls_cert_props]: is true - [config_tls_remote_user]: is true *) class modify_http_processor_config : ?modify_http_protocol_config: (Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config) -> ?config_timeout_next_request:float -> ?config_timeout:float -> ?config_cgi:Netcgi.config -> ?config_error_response:(error_response_params -> string) -> ?config_log_error:(request_info -> string -> unit) -> ?config_log_access:(full_info -> unit) -> ?config_tls_cert_props:bool -> ?config_tls_remote_user:bool -> http_processor_config -> http_processor_config (** Modifies the passed config object as specified by the optional arguments. [modify_http_protocol_config]: This function can be used to modify the parts of the config object that are inherited from [http_protocol_config]. For example: {[ let new_cfg = new modify_http_processor_config ~modify_http_protocol_config: (new Nethttpd_kernel.modify_http_protocol_config ~config_suppress_broken_pipe:true) ~config_timeout:15.0 old_cfg ]} *) class type http_reactor_config = object inherit http_processor_config method config_reactor_synch : [ `Connection | `Close | `Flush | `Write ] (** Specifies when to synchronize output, i.e. force that all channel data are * actually transmitted to the client: * - [`Connection] means only at the end of the connection. This means that the * channels of all pending requests may be buffered - needs a huge amount of * memory * - [`Close] means only when closing the output channel (after every response). * This means that the whole response may be buffered - needs a lot of memory. * - [`Flush] means only when the [flush] method is called. This is a good idea * when one can control that. * - [`Write] means every time the internal output buffer overflows. This is the * recommended setting in general. *) end val default_http_reactor_config : http_reactor_config (** Default configuration: Extends {!Nethttpd_reactor.default_http_processor_config} with - [config_reactor_synch = `Write] *) class modify_http_reactor_config : ?modify_http_protocol_config: (Nethttpd_kernel.http_protocol_config -> Nethttpd_kernel.http_protocol_config) -> ?modify_http_processor_config: (http_processor_config -> http_processor_config) -> ?config_reactor_synch:[ `Connection | `Close | `Flush | `Write ] -> http_reactor_config -> http_reactor_config (** Modifies the passed config object as specified by the optional arguments. [modify_http_protocol_config] and [modify_http_processor_config]: These functions can be used to modify the parts of the config object that are inherited from [http_protocol_config] and [http_processor_config], respectively: For example: {[ let new_cfg = new modify_http_reactor_config ~modify_http_protocol_config: (new Nethttpd_kernel.modify_http_protocol_config ~config_suppress_broken_pipe:true) ~modify_http_processor_config: (new Nethttpd_reactor.modify_http_processor_config ~config_timeout:15.0) old_cfg ]} *) class type internal_environment = object inherit extended_environment method unlock : unit -> unit method req_method : http_method method response : Nethttpd_kernel.http_response method log_access : unit -> unit end (** For private use only *) class http_environment : #http_processor_config -> string -> string -> protocol -> http_header -> Unix.sockaddr -> Unix.sockaddr -> Netchannels.in_obj_channel -> int64 ref -> Netchannels.out_obj_channel -> output_state ref -> Nethttpd_kernel.http_response -> (unit -> unit) -> bool ref -> int64 -> Nettls_support.tls_session_props option -> internal_environment (** For private use only *) class type http_reactive_request = object method environment : extended_environment (** The Netcgi environment representing the request header, the response header, and * the channels to receive the request body and to send the response body. * The channels are locked until either [accept_body] or [reject_body] have been * called - using the channels before raises exceptions. * * This environment is not fully CGI-compatible. In particular, the following * differences exist: * - There is no [cgi_path_info] and no [cgi_path_translated]. * - The user is always unauthenticated. * - The [Status] response header works as in CGI. The [Location] header, however, * must be a full URL when set (only browser redirects) * - When the request body is transmitted by chunked encoding, the header * [Content-Length] is not set. In CGI this is interpreted as missing body. * It is unlikely that clients send requests with chunked encoding, as this * may cause interoperability problems anyway. * *) method accept_body : unit -> unit (** Call this method to unlock the body channels. In terms of HTTP, this sends the * "100 Continue" response when necessary. One can reply with a positive or * negative message. *) method reject_body : unit -> unit (** Call this method to unlock the body channels. In terms of HTTP, this prevents * sending the "100 Continue" response. Any arriving request body is silently * discarded. One should immediately reply with an error mesage. *) method finish_request : unit -> unit (** Reads the rest of the body (if any), and discards that data *) method finish : unit -> unit (** This method should be called after the request has been fully processed. * It takes care that the HTTP protocol is fulfilled, and the next request * can be properly detected and parsed. If the request body has not been * fully read, this is now done, and its data are dropped. If the response * is incomplete, it is completed. If the error is not recoverable, a "Server * Error" is generated. *) end (** The [http_reactor] allows one to pull the next request from a connected * client, and to deliver the response to the protocol engine. *) class http_reactor : ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) -> #http_reactor_config -> Unix.file_descr -> object method next_request : unit -> http_reactive_request option (** Tries to read the next request. When the header of the request is successfully * read, the method returns the request object (see above). It is connected * with the socket and can read the request body. * * After receiving the request, one must either call [accept_body] when the * request is acceptable and one want to reply afer evaluating the body, or * invoke [reject_body] when the request can be denied without looking at the * body. One must also call [accept_body] when there is not any body (it * is a no-op then). The HTTP protocol explicitly forbids to perform the request * when [reject_body] has been invoked ("[The origin server] MUST NOT * perform the requested method if it returns a final status code"). * * The response must be written to the Netcgi environment. Depending on * [config_reactor_synch] the response is immediately transmitted to the * client or at some specified time in the future (untransmitted data is buffered * in this case). * * While transmitting output, the reactor is able to read the next request * in the background when the limits for the pipeline size allows that. * * While receiving input, the reactor is able to write untransmitted response * data in the background. * * It is {b an error} to call [next_request] again before the previous request * is completely processed (you can ensure this by calling [finish]). * In this case the HTTP connection is immediately shut down. * * The method [next_request] returns [None] when all requests of the * connection are processed. *) method close : unit -> unit (** Closes the file descriptor with a reliable method. This method must be * called after [next_request] returned [None]. It can also be called at any * time to shut down the connection prematurely (this means a lingering close, * and may cost some time). *) end val process_connection : ?config_hooks:(Nethttpd_kernel.http_protocol_hooks -> unit) -> #http_reactor_config -> Unix.file_descr -> 'a http_service -> unit (** Processes all HTTP requests in turn arriving at the file descriptor, and * calls the service provider for every request. Finally, the descriptor is * closed. * * All stages of HTTP processing, as defined by the service provider, are * executed in the current thread. * * Any exceptions are caught and logged. The connection is immediately closed * in this case. *) (** {1 Debugging} *) module Debug : sig val enable : bool ref (** Enables {!Netlog}-style debugging of this module *) end (**/**) (* Internal: *) val logged_error_response : Unix.sockaddr -> Unix.sockaddr -> (string*string) option -> int64 -> bool -> http_status -> http_header option -> string option -> extended_environment option -> Nethttpd_kernel.http_response option -> http_processor_config -> unit ocamlnet-4.1.2/src/nethttpd/nethttpd_plex.ml0000644000175000017500000004006012731530350017600 0ustar gerdgerd(* $Id$ *) open Nethttpd_services open Netplex_types open Printf type config_log_error = Nethttpd_types.request_info -> string -> unit type config_log_access = Nethttpd_types.full_info -> unit type config_error_response = Nethttpd_types.error_response_params -> string type ('a,'b) service_factory = (string * 'a Nethttpd_services.dynamic_service) list -> Netplex_types.config_file -> Netplex_types.address -> string -> 'b Nethttpd_types.http_service constraint 'b = [ `Dynamic_service of 'a Nethttpd_services.dynamic_service | `File_service of Nethttpd_services.file_service ] type httpd_factory = { httpd_factory : 'a . (Netplex_types.container -> Nethttpd_reactor.http_reactor_config) -> 'a Nethttpd_types.http_service -> Netplex_types.processor } let std_log_error container info msg = let s = Nethttpd_util.std_error_log_string info msg in container # log_subch "" `Err s let std_log_access ?(debug=false) container info = let s_info = Nethttpd_util.std_access_log_string info in container # log_subch "access" `Info s_info; if debug then ( let s_debug = Nethttpd_util.std_debug_access_log_string info in container # log_subch "access" `Debug s_debug ) type encap = [ `Reactor | `Engine ] class nethttpd_processor ?(hooks = new Netplex_kit.empty_processor_hooks()) ?(encap = `Reactor) mk_config srv : Netplex_types.processor = object(self) inherit Netplex_kit.processor_hooks_delegation hooks method post_add_hook sockserv ctrl = ctrl # add_plugin Netplex_sharedvar.plugin; hooks # post_add_hook sockserv ctrl method process ~when_done (container : Netplex_types.container) fd proto = let config = mk_config container in let config_hooks hooks = let store key value = let name = "nethttpd.tls_cache." ^ Netencoding.to_hex key in let _ex = Netplex_sharedvar.create_var ~own:true ~timeout:300.0 name in ignore(Netplex_sharedvar.set_value name value) in let remove key = let name = "nethttpd.tls_cache." ^ Netencoding.to_hex key in ignore(Netplex_sharedvar.delete_var name) in let retrieve key = let name = "nethttpd.tls_cache." ^ Netencoding.to_hex key in match Netplex_sharedvar.get_value name with | Some value -> value | None -> raise Not_found in hooks # tls_set_cache ~store ~remove ~retrieve in match encap with | `Reactor -> ( try Nethttpd_reactor.process_connection ~config_hooks config fd srv with | err -> container # log `Err ("Exception caught by HTTP server: " ^ Netexn.to_string err) ); when_done() | `Engine -> let engine_config = new Nethttpd_engine.buffering_engine_processing_config in let ctx = Nethttpd_engine.process_connection ~config_hooks config engine_config fd container#event_system srv in Uq_engines.when_state ~is_done:(fun () -> when_done()) ~is_error:(fun e -> container#log `Err ("Exception caught by HTTP server: " ^ Printexc.to_string e); when_done()) ctx#engine method supported_ptypes = [ `Multi_processing ; `Multi_threading ] end let nethttpd_processor ?hooks ?encap mk_config srv = new nethttpd_processor ?hooks ?encap mk_config srv let is_options_request env = env # cgi_request_method = "OPTIONS" && env # cgi_request_uri = "*" let is_any_request env = true let ws_re = Netstring_str.regexp "[ \r\t\n]+" let split_ws s = Netstring_str.split ws_re s let name_port_re = Netstring_str.regexp "^\\([^:]+\\):\\([0-9]+\\)$" let split_name_port s = match Netstring_str.string_match name_port_re s 0 with | Some m -> let name = Netstring_str.matched_group m 1 s in let port = Netstring_str.matched_group m 2 s in (name, int_of_string port) | None -> failwith "Bad name:port specifier" let cfg_req_str_param cfg addr name = try cfg#string_param (cfg # resolve_parameter addr name) with | Not_found -> failwith ("Missing parameter: " ^ cfg#print addr ^ "." ^ name) let cfg_opt_str_param cfg addr name = try Some(cfg#string_param (cfg # resolve_parameter addr name)) with | Not_found -> None let cfg_float_param cfg default addr name = try cfg#float_param (cfg # resolve_parameter addr name) with | Not_found -> default let cfg_bool_param cfg addr name = try cfg#bool_param (cfg # resolve_parameter addr name) with | Not_found -> false let restrict_file_service_config cfg addr = cfg # restrict_subsections addr [ "media_type" ]; cfg # restrict_parameters addr [ "type"; "media_types_file"; "docroot"; "default_media_type"; "enable_gzip"; "index_files"; "enable_listings"; "hide_from_listings" ] let read_file_service_config cfg addr uri_path = let req_str_param = cfg_req_str_param cfg in let opt_str_param = cfg_opt_str_param cfg in let bool_param = cfg_bool_param cfg in let suffix_types = ( List.map (fun addr -> cfg # restrict_subsections addr []; cfg # restrict_parameters addr [ "suffix"; "type" ]; (req_str_param addr "suffix", req_str_param addr "type") ) (cfg # resolve_section addr "media_type") ) @ ( match opt_str_param addr "media_types_file" with | None -> [] | Some f -> read_media_types_file f ) in let spec = { file_docroot = req_str_param addr "docroot"; file_uri = ( match opt_str_param addr "uri" with | None -> uri_path | Some uri -> uri ); file_suffix_types = suffix_types; file_default_type = ( match opt_str_param addr "default_media_type" with | None -> "text/plain" | Some t -> t); file_options = ( if bool_param addr "enable_gzip" then [ `Enable_gzip ] else [] ) @ ( match opt_str_param addr "index_files" with | None -> [] | Some s -> [ `Enable_index_file (split_ws s) ] ) @ ( if bool_param addr "enable_listings" then let hide = match opt_str_param addr "hide_from_listings" with | None -> [] | Some s -> split_ws s in let l = simple_listing ~hide in [ `Enable_listings l ] else [] ) @ [ `Override_compression_suffixes[] ] (* disable that for the time being *) } in spec let std_error_response = Nethttpd_util.std_error_response let default_file_service : ('a,'b) service_factory = fun handlers cfg addr uri_path -> restrict_file_service_config cfg addr; let spec = read_file_service_config cfg addr uri_path in Nethttpd_services.file_service spec let restrict_dynamic_service_config cfg addr = cfg # restrict_subsections addr []; cfg # restrict_parameters addr [ "type"; "handler" ] let read_dynamic_service_config xhandlers cfg addr uri_path = let handler_name = cfg_req_str_param cfg addr "handler" in let xhandler = try List.assoc handler_name xhandlers with | Not_found -> failwith ("Unknown handler `" ^ handler_name ^ "' in param " ^ cfg#print addr ^ ".handler") in let srv = xhandler cfg addr uri_path in srv let default_dynamic_service handlers cfg addr uri_path = restrict_dynamic_service_config cfg addr; let xhandlers = List.map (fun (name,h) -> (name, (fun _ _ _ -> h)) ) handlers in let spec = read_dynamic_service_config xhandlers cfg addr uri_path in Nethttpd_services.dynamic_service spec let default_services = [ "file", default_file_service; "dynamic", default_dynamic_service ] let create_processor hooks config_cgi handlers services log_error log_access error_response processor_factory encap tls_provider ctrl_cfg cfg addr = let req_str_param = cfg_req_str_param cfg in let opt_str_param = cfg_opt_str_param cfg in let float_param = cfg_float_param cfg in let bool_param = cfg_bool_param cfg in let rec sub_service outermost_flag uri_path addr = let host_sects = cfg # resolve_section addr "host" in let uri_sects = cfg # resolve_section addr "uri" in let method_sects = cfg # resolve_section addr "method" in let service_sects = cfg # resolve_section addr "service" in match (host_sects, uri_sects, method_sects, service_sects) with | [], [], [], [] -> linear_distributor [] (* Forces a 404 response *) | _, [], [], [] -> let hosts = List.map (host_sub_service uri_path) host_sects in host_distributor hosts | [], _, [], [] -> if outermost_flag then failwith ("Outermost subsection must be 'host': " ^ cfg#print addr); let uris = List.map (uri_sub_service uri_path) uri_sects in uri_distributor uris | [], [], _, [] -> if outermost_flag then failwith ("Outermost subsection must be 'host': " ^ cfg#print addr); let methods = List.map (method_sub_service uri_path) method_sects in method_distributor methods | [], [], [], _ -> if outermost_flag then failwith ("Outermost subsection must be 'host': " ^ cfg#print addr); ( match service_sects with | [] -> assert false | [service_sect] -> service uri_path service_sect | _ -> failwith ("Only one 'service' subsection is permitted: " ^ cfg#print addr); ) | _ -> failwith("Only one type of subsections host/uri/method/service is allowed: " ^ cfg#print addr) and sub_service_ac uri_path addr = (* With access control *) let srv = sub_service false uri_path addr in let access_sects = cfg # resolve_section addr "access" in List.fold_left (fun srv access_sect -> access_control access_sect srv) srv access_sects and host_sub_service uri_path addr = cfg # restrict_subsections addr [ "host"; "uri"; "method"; "service"; "access" ]; cfg # restrict_parameters addr [ "names"; "pref_name"; "pref_port" ]; let names_str = req_str_param addr "names" in let names = List.map (fun s -> try split_name_port s with | Failure m -> failwith (m ^ ": " ^ cfg#print addr ^ ".names") ) (split_ws names_str) in let host_def = { server_pref_name = opt_str_param addr "pref_name"; server_pref_port = ( try Some(cfg # int_param (cfg # resolve_parameter addr "pref_port")) with Not_found -> None ); server_names = names; server_addresses = ( List.map (fun (_, port) -> (Unix.inet_addr_any, port)) (List.filter (fun (name, _) -> name = "*") names) ) } in let srv = sub_service_ac uri_path addr in (host_def, srv) and uri_sub_service _ addr = cfg # restrict_subsections addr [ "host"; "uri"; "method"; "service"; "access" ]; cfg # restrict_parameters addr [ "path" ]; let path = req_str_param addr "path" in let srv = sub_service_ac path (* sic! *) addr in (path, srv) and method_sub_service uri_path addr = cfg # restrict_subsections addr [ "host"; "uri"; "method"; "service"; "access" ]; cfg # restrict_parameters addr [ "allow"; "deny" ]; let allow_opt = opt_str_param addr "allow" in let deny_opt = opt_str_param addr "deny" in let filter = match (allow_opt, deny_opt) with | (Some host_list), None -> `Limit (split_ws host_list) | None, (Some host_list) -> `Limit_except (split_ws host_list) | None, None -> failwith ("Missing parameter 'allow' or 'deny': " ^ cfg#print addr) | _, _ -> failwith ("It is forbidden to specify both 'allow' and 'deny': " ^ cfg#print addr) in let srv = sub_service_ac uri_path addr in (filter, srv) and access_control addr srv = let typ = req_str_param addr "type" in match typ with | "host" -> host_access_control addr srv | _ -> failwith ("Unknown access control type: " ^ cfg#print addr ^ ".type") and host_access_control addr srv = cfg # restrict_subsections addr [ ]; cfg # restrict_parameters addr [ "type"; "allow"; "deny" ]; let allow_opt = opt_str_param addr "allow" in let deny_opt = opt_str_param addr "deny" in let filter = match (allow_opt, deny_opt) with | (Some host_list), None -> `Allow (split_ws host_list) | None, (Some host_list) -> `Deny (split_ws host_list) | None, None -> failwith ("Missing parameter 'allow' or 'deny': " ^ cfg#print addr) | _, _ -> failwith ("It is forbidden to specify both 'allow' and 'deny': " ^ cfg#print addr) in ac_by_host (filter, srv) and service uri_path addr = let typ = req_str_param addr "type" in let get_serv = try List.assoc typ services with | Not_found -> failwith ("Unknown service type: " ^ cfg#print addr ^ ".type") in let serv = get_serv handlers cfg addr (uri_path:string) in (serv : ( [ `Dynamic_service of 'a Nethttpd_services.dynamic_service | `File_service of Nethttpd_services.file_service ] Nethttpd_types.http_service ) :> ( [> `Dynamic_service of 'a Nethttpd_services.dynamic_service | `File_service of Nethttpd_services.file_service ] Nethttpd_types.http_service ) ) in cfg # restrict_subsections addr [ "host"; "uri"; "method"; "service"; "tls" ]; cfg # restrict_parameters addr [ "type"; "timeout"; "timeout_next_request"; "access_log"; "suppress_broken_pipe"; "tls_cert_props"; "tls_remote_user"; ]; let srv = linear_distributor [ is_options_request, options_service(); is_any_request, sub_service true "/" addr ] in let timeout = float_param 300.0 addr "timeout" in let timeout_next_request = float_param 15.0 addr "timeout_next_request" in let access_enabled, access_debug = match opt_str_param addr "access_log" with | None -> (false,false) | Some "off" -> (false,false) | Some "enabled" -> (true,false) | Some "debug" -> (true,true) | _ -> failwith "Bad parameter 'access_log'" in let suppress_broken_pipe = bool_param addr "suppress_broken_pipe" in let tls_cert_props = not(bool_param addr "tls_no_cert_props") in let tls_remote_user = not(bool_param addr "tls_no_remote_user") in let config_tls = Netplex_config.read_tls_config cfg addr tls_provider in let mk_config container = let cle = log_error container in let cla = if access_enabled then log_access ?debug:(Some access_debug) container else (fun _ -> ()) in (object method config_reactor_synch = `Write method config_timeout_next_request = timeout_next_request method config_timeout = timeout method config_cgi = config_cgi method config_error_response = error_response method config_log_error = cle method config_log_access = cla method config_max_reqline_length = 32768 method config_max_header_length = 65536 method config_max_trailer_length = 65536 method config_limit_pipeline_length = 1 method config_limit_pipeline_size = 65536 method config_announce_server = `Ocamlnet (* TODO *) method config_suppress_broken_pipe = suppress_broken_pipe method config_tls = config_tls method config_tls_cert_props = tls_cert_props method config_tls_remote_user = tls_remote_user end ) in match processor_factory with | None -> nethttpd_processor ~hooks ?encap mk_config srv | Some fr -> fr.httpd_factory mk_config srv ;; let nethttpd_factory ?(name = "nethttpd") ?(hooks = new Netplex_kit.empty_processor_hooks()) ?encap ?(config_cgi = Netcgi.default_config) ?(handlers=[]) ?(services=default_services) ?(log_error = std_log_error) ?(log_access = std_log_access) ?(error_response = std_error_response) ?processor_factory ?tls () : processor_factory = object method name = name method create_processor ctrl_cfg cfg addr = let tls_provider = match tls with | Some t -> Some t | None -> Netsys_crypto.current_tls_opt() in create_processor hooks config_cgi handlers services log_error log_access error_response processor_factory encap tls_provider ctrl_cfg cfg addr end ocamlnet-4.1.2/src/nethttpd/nethttpd_reactor.ml0000644000175000017500000011474512731530350020303 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Nethttpd; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) module Debug = struct let enable = ref false end let dlog = Netlog.Debug.mk_dlog "Nethttpd_reactor" Debug.enable let dlogr = Netlog.Debug.mk_dlogr "Nethttpd_reactor" Debug.enable let () = Netlog.Debug.register_module "Nethttpd_reactor" Debug.enable open Nethttp open Nethttp.Header open Nethttpd_types open Nethttpd_kernel open Netchannels open Printf class type http_processor_config = object inherit Nethttpd_kernel.http_protocol_config method config_timeout_next_request : float method config_timeout : float method config_cgi : Netcgi.config method config_error_response : error_response_params -> string method config_log_error : request_info -> string -> unit method config_log_access : full_info -> unit method config_tls_cert_props : bool method config_tls_remote_user : bool end class type http_reactor_config = object inherit http_processor_config method config_reactor_synch : [ `Connection | `Close | `Flush | `Write ] end class type internal_environment = object inherit extended_environment method unlock : unit -> unit method req_method : http_method method response : http_response method log_access : unit -> unit end class type http_reactive_request = object method environment : extended_environment method accept_body : unit -> unit method reject_body : unit -> unit method finish : unit -> unit method finish_request : unit -> unit end let get_this_host addr = match addr with | Unix.ADDR_UNIX path -> ("", None) (* questionable *) | Unix.ADDR_INET(ia,port) -> (Unix.string_of_inet_addr ia, Some port) let logged_error_response fd_addr peer_addr req_meth_uri_opt in_cnt req_rej status hdr_opt msg_opt env_opt resp_opt config = let unopt = function Some x -> x | None -> raise Not_found in let msg, have_msg = match msg_opt with | Some msg -> msg, true | None -> "", false in let code = int_of_http_status status in let info = ( object method server_socket_addr = fd_addr method remote_socket_addr = peer_addr method tls_session_props = match env_opt with | None -> None | Some env -> env # tls_session_props method request_method = fst(unopt req_meth_uri_opt) method request_uri = snd(unopt req_meth_uri_opt) method input_header = (unopt env_opt) # input_header method cgi_properties = (unopt env_opt) # cgi_properties method input_body_size = in_cnt method response_status_code = code method error_message = msg end ) in if have_msg then config # config_log_error (info:>request_info) msg; match resp_opt with | None -> () | Some resp -> let body = Bytes.of_string(config # config_error_response info) in let eff_header = match hdr_opt with | None -> new Netmime.basic_mime_header [] | Some hdr -> hdr in Nethttpd_kernel.send_static_response resp status (Some eff_header) body; let full = new create_full_info ~response_status_code:code ~request_body_rejected:req_rej ~output_header:eff_header ~output_body_size:(Int64.of_int (Bytes.length body)) (info:>request_info) in config # config_log_access full let no_info = ( object method server_socket_addr = raise Not_found method remote_socket_addr = raise Not_found method tls_session_props = None method request_method = raise Not_found method request_uri = raise Not_found method input_header = raise Not_found method cgi_properties = raise Not_found method input_body_size = raise Not_found end ) let cert_atts = [ Netx509.DN_attributes.at_commonName, "_CN"; Netx509.DN_attributes.at_emailAddress, "_Email"; Netx509.DN_attributes.at_organizationName, "_O"; Netx509.DN_attributes.at_organizationalUnitName, "_OU"; Netx509.DN_attributes.at_countryName, "_C"; Netx509.DN_attributes.at_stateOrProvinceName, "_SP"; Netx509.DN_attributes.at_localityName, "_L"; ] let gen_dn_props dn prefix = let p = prefix ^ "_DN" in (p, dn#string) :: List.flatten (List.map (fun (oid, suffix) -> try let s = Netx509.lookup_dn_ava_utf8 dn oid in [ p ^ suffix, s ] with Not_found -> [] ) cert_atts ) let gen_cert_props cert prefix = [ prefix ^ "_M_SERIAL", Netencoding.to_hex (cert#serial_number); prefix ^ "_V_START", Netdate.mk_internet_date ~zone:0 cert#valid_not_before; prefix ^ "_V_END", Netdate.mk_internet_date ~zone:0 cert#valid_not_after; ] class http_environment (proc_config : #http_processor_config) req_meth req_uri req_version req_hdr fd_addr peer_addr in_ch in_cnt out_ch output_state resp after_send_file reqrej fdi tls_props : internal_environment = (* Decode important input header fields: *) let (in_host, in_port_opt) = (* Host and port of the [Host] header *) try get_host req_hdr with | Not_found -> (* For HTTP/1.1 and later this is not allowed. For earlier protocols, we * just fill in the IP address that accepted the request. *) ( match req_version with | `Http((1,n),_) when n>= 1 -> raise(Standard_response(`Bad_request, None, Some "Nethttpd: Bad request: [Host] header is missing")) | _ -> get_this_host fd_addr ) | Bad_header_field _ -> raise(Standard_response(`Bad_request, None, Some "Nethttpd: Bad request: Cannot decode [Host] header")) in let (script_name, query_string) = decode_query req_uri in (* let full_uri = "http://" ^ in_host ^ (match in_port with Some n -> ":" ^ string_of_int n | None -> "") ^ req_uri *) object(self) inherit empty_environment val mutable locked = true val mutable logged_props = [] val out_state = (output_state : output_state ref) initializer ( config <- proc_config # config_cgi; in_header <- req_hdr; in_channel <- in_ch; out_channel <- out_ch; protocol <- req_version; properties <- [ "GATEWAY_INTERFACE", "Nethttpd/0.0"; "SERVER_SOFTWARE", "Nethttpd/0.0"; "SERVER_NAME", in_host; "SERVER_PROTOCOL", string_of_protocol req_version; "REQUEST_METHOD", req_meth; "SCRIPT_NAME", script_name; (* "PATH_INFO", ""; *) (* "PATH_TRANSLATED", ""; *) "QUERY_STRING", query_string; (* "REMOTE_HOST", ""; *) "REMOTE_ADDR", fst(get_this_host peer_addr); (* "AUTH_TYPE", ""; *) (* "REMOTE_USER", ""; *) (* "REMOTE_IDENT", ""; *) "HTTPS", (if tls_props = None then "off" else "on"); "REQUEST_URI", req_uri; ] @ ( match in_port_opt with | Some p -> [ "SERVER_PORT", string_of_int p ] | None -> [] ) @ ( match tls_props with | None -> [] | Some (p:Nettls_support.tls_session_props) -> (* see http://httpd.apache.org/docs/2.4/mod/mod_ssl.html for a reference. Not everything is supported here, though. *) [ "SSL_PROTOCOL", p#protocol; "SSL_VERSION_LIBRARY", "Nethttpd/0.0"; "SSL_CIPHER", p#kx_algo ^ "-" ^ p#cipher_algo ^ "-" ^ p#mac_algo; "SSL_SESSION_ID", Netencoding.to_hex p#id ] @ (if proc_config # config_tls_remote_user then match p # peer_credentials with | `X509 cert -> ( try let name = Nettls_support.get_tls_user_name p in [ "REMOTE_USER", name ] with Not_found -> [] ) | _ -> [] else [] ) @ (if proc_config # config_tls_cert_props then ( match p # endpoint_credentials with | `X509 cert -> gen_dn_props cert#subject "SSL_SERVER_S" @ gen_dn_props cert#issuer "SSL_SERVER_I" @ gen_cert_props cert "SSL_SERVER" | _ -> [] ) @ ( match p # peer_credentials with | `X509 cert -> gen_dn_props cert#subject "SSL_CLIENT_S" @ gen_dn_props cert#issuer "SSL_CLIENT_I" @ gen_cert_props cert "SSL_CLIENT" | _ -> [] ) else [] ) ); logged_props <- properties; tls_session_props <- tls_props; ) method unlock() = dlogr (fun () -> sprintf "FD=%Ld: env.unlock" fdi); locked <- false method server_socket_addr = fd_addr method remote_socket_addr = peer_addr method response = resp method req_method = (req_meth, req_uri) val mutable sent_status = 0 val mutable sent_resp_hdr = new Netmime.basic_mime_header [] method send_output_header() = dlogr (fun () -> sprintf "FD=%Ld: env.send_output_header out_state=%s" fdi (string_of_output_state !out_state)); if locked then failwith "Nethttpd_reactor: channel is locked"; if !out_state = `Start then ( (* The response status is encoded in the [Status] pseudo header *) let (code, phrase) = status_of_cgi_header out_header in resp # send (`Resp_status_line(code, phrase)); (* Create a copy of the header without [Status]: *) let h = new Netmime.basic_mime_header out_header#fields in h # delete_field "Status"; sent_status <- code; (* remember what has been sent for access logging *) sent_resp_hdr <- h; resp # send (`Resp_header h); out_state := `Sending; ) (* netcgi2 may call send_output_header several times, so we have to ignore the later calls after the first one *) method send_file fd length = dlogr (fun () -> sprintf "FD=%Ld: env.send_file out_state=%s" fdi (string_of_output_state !out_state)); if locked then failwith "Nethttpd_reactor: channel is locked"; if !out_state <> `Start then failwith "send_file"; (* The response status is encoded in the [Status] pseudo header *) let (code, phrase) = status_of_cgi_header out_header in let status = http_status_of_int code in (* Create a copy of the header without [Status]: *) let h = new Netmime.basic_mime_header out_header#fields in h # delete_field "Status"; sent_status <- code; (* remember what has been sent for access logging *) sent_resp_hdr <- h; send_file_response resp status (Some h) fd length; out_state := `Sending; after_send_file() method log_error s = let info = ( object method server_socket_addr = fd_addr method remote_socket_addr = peer_addr method request_method = req_meth method request_uri = req_uri method input_header = req_hdr method cgi_properties = logged_props method input_body_size = !in_cnt method tls_session_props = tls_props end ) in proc_config # config_log_error info s method log_props l = logged_props <- l val mutable access_logged = false method log_access () = (* Called when the whole response is written. Do now access logging *) if not access_logged then ( let full_info = ( object method server_socket_addr = fd_addr method remote_socket_addr = peer_addr method request_method = req_meth method request_uri = req_uri method input_header = req_hdr method cgi_properties = logged_props method input_body_size = !in_cnt method response_status_code = sent_status method request_body_rejected = !reqrej method output_header = sent_resp_hdr method output_body_size = resp#body_size method tls_session_props = tls_props end ) in proc_config # config_log_access full_info; access_logged <- true ) method input_body_size = !in_cnt method request_body_rejected = !reqrej method output_state = out_state end class http_reactor_input next_token in_cnt fdi = (* an extension of rec_in_channel *) object(self) val mutable current_chunk = None val mutable eof = false val mutable closed = false val mutable locked = true method private refill() = dlogr (fun () -> sprintf "FD=%Ld: input.refill" fdi); match next_token() with | `Req_body(s,pos,len) -> assert(len > 0); in_cnt := Int64.add !in_cnt (Int64.of_int len); current_chunk <- Some(s,pos,len) | `Req_trailer _ -> self # refill () (* ignore *) | `Req_end -> current_chunk <- None; eof <- true; raise End_of_file; | _ -> (* Something else... Handle this as `Req_end! *) current_chunk <- None; eof <- true; raise End_of_file; method input s spos slen = dlogr (fun () -> sprintf "FD=%Ld: input.input" fdi); if closed then raise Closed_channel; if locked then failwith "Nethttpd_reactor: channel is locked"; if eof then raise End_of_file; if current_chunk = None then self#refill(); (* may raise End_of_file *) match current_chunk with | Some(u,upos,ulen) -> (* We have [ulen] data, copy that to [s] *) let len = min slen ulen in Bytes.blit u upos s spos len; let ulen' = ulen - len in if ulen' = 0 then current_chunk <- None else current_chunk <- Some(u,upos+len,ulen'); len | None -> (* After [refill] this is not possible *) assert false method close_in() = dlogr (fun () -> sprintf "FD=%Ld: input.close_in" fdi); if not closed then ( if locked then failwith "Nethttpd_reactor: channel is locked"; (* It is no problem to ignore further arriving tokens. These will be "eaten" by * [finish_request] later. (Of course, we could call [finish_request] here, * but that would probably defer the generation of responses.) *) closed <- true; ) method unlock() = dlogr (fun () -> sprintf "FD=%Ld: input.unlock" fdi); locked <- false; method drop() = dlogr (fun () -> sprintf "FD=%Ld: input.drop" fdi); locked <- false; eof <- true end class http_reactor_output config resp synch out_state (f_access : unit -> unit) fdi = (* an extension of rec_out_channel *) object val mutable closed = false val mutable locked = true val mutable access_logged = false method output s spos slen = dlogr (fun () -> sprintf "FD=%Ld: output.output" fdi); if closed then raise Closed_channel; if locked then failwith "Nethttpd_reactor: channel is locked"; if !out_state <> `Sending then failwith "output channel: Cannot output now"; let u = Bytes.sub s spos slen in resp # send (`Resp_body(u, 0, Bytes.length u)); ( match config#config_reactor_synch with | `Write -> synch() | _ -> () ); slen method flush() = dlogr (fun () -> sprintf "FD=%Ld: output.flush" fdi); if closed then raise Closed_channel; if locked then failwith "Nethttpd_reactor: channel is locked"; if !out_state = `Sending then match config#config_reactor_synch with | `Write | `Flush -> synch() | _ -> () method close_out() = dlogr (fun () -> sprintf "FD=%Ld: output.close_out" fdi); if not closed then ( if locked then failwith "Nethttpd_reactor: channel is locked"; closed <- true; if !out_state = `Sending then resp # send `Resp_end; out_state := `End; ( match config#config_reactor_synch with | `Write | `Flush | `Close -> synch() | _ -> () ); (* This is the right time for writing the access log entry: *) if not access_logged then ( f_access(); access_logged <- true ) ) method after_send_file() = (* Flush after send_file. This method does not count as close_out, though. It is possible that more flushes follow. *) dlogr (fun () -> sprintf "FD=%Ld: output.after_send_file" fdi); out_state := `End; ( match config#config_reactor_synch with | `Write | `Flush | `Close -> synch() | _ -> () ); (* This is the right time for writing the access log entry: *) if not access_logged then ( f_access(); access_logged <- true ) method unlock() = dlogr (fun () -> sprintf "FD=%Ld: output.unlock" fdi); locked <- false end class http_reactive_request_impl config env inch outch resp expect_100_continue finish_request reqrej : http_reactive_request = (* NB. inch and outch must only be used here to control the locks in these channels, not for doing real I/O *) object(self) initializer ( let (m,u) = env # req_method in dlogr (fun () -> sprintf "req-%d: %s %s" (Oo.id self) m u ); ) method environment = (env : internal_environment :> extended_environment) method accept_body() = dlogr (fun () -> sprintf "req-%d: accept_body" (Oo.id self)); if expect_100_continue then resp # send resp_100_continue; (* We need not to synch here! The attempt to read the body will synchronize * implicitly. * We should keep in mind, however, that when the existing body isn't read * the "100 Continue" might be transmitted very late. This is no disadvantage, * I think. *) inch # unlock(); outch # unlock(); env # unlock() method reject_body() = dlogr (fun () -> sprintf "req-%d: reject_body" (Oo.id self)); inch # drop(); outch # unlock(); env # unlock(); reqrej := true (* for access logging only *) val mutable fin_req = false method finish_request() = if not fin_req then ( (* Do this only once *) dlogr (fun () -> sprintf "req-%d: finish_request" (Oo.id self)); fin_req <- true; inch # drop(); outch # unlock(); env # unlock(); finish_request(); (* Read the rest of the request until `Req_end *) ) method finish() = self # finish_request(); dlogr (fun () -> sprintf "req-%d: finish" (Oo.id self)); match !(env#output_state) with | `Start -> (* The whole response is missing! Generate a "Server Error": *) dlogr (fun () -> sprintf "req-%d: no response, generating server error" (Oo.id self)); output_std_response config env `Internal_server_error None (Some "Nethttpd: Missing response, replying 'Server Error'"); (env#output_state) := `End | `Sending -> (* The response body is probably incomplete or missing. Try to close * the channel. *) dlogr (fun () -> sprintf "req-%d: incomplete response, trying to fix" (Oo.id self)); ( try env # output_ch # close_out() with Closed_channel -> () ); (env#output_state) := `End; | `End -> (* Everything ok, just to be sure... *) ( try env # output_ch # close_out() with Closed_channel -> () ); end class http_reactor ?(config_hooks = fun _ -> ()) (config : #http_reactor_config) fd = (* note that "new http_reactor" can already raise exceptions, e.g. Unix.ENOTCONN *) object(self) val proto = new http_protocol config fd val fd_addr = Unix.getsockname fd val peer_addr = Netsys.getpeername fd initializer ( Netlog.Debug.track_fd ~owner:"Nethttpd_reactor" ~descr:(sprintf "HTTP %s->%s" (Netsys.string_of_sockaddr peer_addr) (Netsys.string_of_sockaddr fd_addr)) fd; config_hooks proto#hooks ) method private cycle() = let block = if proto # waiting_for_next_message then config#config_timeout_next_request else config#config_timeout in dlogr (fun () -> sprintf "FD %Ld: cycle block_tmo=%f" (Netsys.int64_of_file_descr fd) block); proto # cycle ~block (); method private next_token() = if proto # recv_queue_len = 0 then ( self # cycle(); self # next_token() ) else ( let tok = proto # receive() in dlogr (fun () -> sprintf "FD %Ld: next_token=%s" (Netsys.int64_of_file_descr fd) (Nethttpd_kernel.string_of_req_token tok)); tok ) method private peek_token() = if proto # recv_queue_len = 0 then ( self # cycle(); self # peek_token() ) else ( let tok = proto # peek_recv() in dlogr (fun () -> sprintf "FD %Ld: peek_token=%s" (Netsys.int64_of_file_descr fd) (Nethttpd_kernel.string_of_req_token tok)); tok ) method private finish_request() = (* Read the rest of the previous request, ignoring it *) dlogr (fun () -> sprintf "FD %Ld: reactor_finish_request" (Netsys.int64_of_file_descr fd)); match self # peek_token() with | `Req_header _ | `Eof | `Fatal_error _ | `Bad_request_error _ | `Timeout -> (* Everything ok, do nothing *) () | `Req_end -> (* Just drop this token, the next token starts the new request *) ignore(proto # receive ()) | `Req_expect_100_continue | `Req_body _ | `Req_trailer _ -> (* Continue to read this request until its end *) while match self # peek_token () with | `Req_header _ | `Eof | `Fatal_error _ | `Bad_request_error _ | `Timeout -> false (* Do not read further *) | _ -> ignore(self # next_token()); true (* Continue *) do () done method private synch() = (* Ensure that all written data are actually transmitted: *) dlogr (fun () -> sprintf "FD %Ld: synch loop" (Netsys.int64_of_file_descr fd)); while proto # resp_queue_filled do self # cycle(); done; dlogr (fun () -> sprintf "FD %Ld: leaving synch loop" (Netsys.int64_of_file_descr fd)); (* CHECK: Maybe we have to throw away the remaining tokens of the current request! *) method next_request () = let tok = self # next_token() in match tok with | `Req_header (req, req_hdr, resp) -> (* Ok, we have a new request. Initialize the new environment processing * it *) dlogr (fun () -> sprintf "FD %Ld: reactor_next_request: got header" (Netsys.int64_of_file_descr fd)); let expect_100_continue = try proto # peek_recv() = `Req_expect_100_continue with Recv_queue_empty -> false in if expect_100_continue then ignore(proto # receive()); let ((req_meth, req_uri), req_version) = req in let env_opt = ref None in (* set below *) let in_cnt = ref 0L in let input_ch = new http_reactor_input self#next_token in_cnt (Netsys.int64_of_file_descr fd) in let output_state = ref `Start in let output_ch = new http_reactor_output config resp self#synch output_state (fun () -> match !env_opt with | None -> () | Some env -> env#log_access() ) (Netsys.int64_of_file_descr fd) in let lifted_input_ch = lift_in ~buffered:false (`Rec (input_ch :> rec_in_channel)) in let lifted_output_ch = lift_out (`Rec (output_ch :> rec_out_channel)) in (* The input channel needs no additional buffer here. The httpd kernel * already implements a good buffer. * * The output channel profits from a buffer. The effect is that the * kernel is driven with output chunks of uniform size. Furthermore, * `Write synchronization is only performed after every of these chunks, * and not after every output method invocation. *) let after_send_file() = output_ch # after_send_file(); lifted_output_ch # close_out() in let reqrej = ref false in ( try let env = new http_environment config req_meth req_uri req_version req_hdr fd_addr peer_addr lifted_input_ch in_cnt lifted_output_ch output_state resp after_send_file reqrej (Netsys.int64_of_file_descr fd) proto#tls_session_props in env_opt := Some env; let req_obj = new http_reactive_request_impl config env input_ch output_ch resp expect_100_continue self#finish_request reqrej in dlogr (fun () -> sprintf "FD %Ld: reactor_next_request: returning req-%d" (Netsys.int64_of_file_descr fd) (Oo.id req_obj)); Some req_obj with Standard_response(status, hdr_opt, msg_opt) -> (* Probably a problem when decoding a header field! *) dlogr (fun () -> sprintf "FD %Ld: reactor_next_request: standard response" (Netsys.int64_of_file_descr fd)); logged_error_response fd_addr peer_addr (Some(req_meth,req_uri)) !in_cnt !reqrej status hdr_opt msg_opt !env_opt (Some resp) config; self # synch(); self # finish_request(); self # next_request() ) | `Eof -> dlogr (fun () -> sprintf "FD %Ld: reactor_next_request: got eof" (Netsys.int64_of_file_descr fd)); self # synch(); None | `Fatal_error e -> (* The connection is already down. Just log the incident: *) dlogr (fun () -> sprintf "FD %Ld: reactor_next_request: got fatal error" (Netsys.int64_of_file_descr fd)); if e <> `Broken_pipe_ignore then ( let msg = Nethttpd_kernel.string_of_fatal_error e in let status = `Internal_server_error in logged_error_response fd_addr peer_addr None 0L false status None (Some msg) None None config; ); None | `Bad_request_error (e, resp) -> (* Log the incident, and reply with a 400 response: *) dlogr (fun () -> sprintf "FD %Ld: reactor_next_request: got bad request" (Netsys.int64_of_file_descr fd)); let msg = string_of_bad_request_error e in let status = status_of_bad_request_error e in logged_error_response fd_addr peer_addr None 0L false status None (Some msg) None (Some resp) config; self # next_request() | `Timeout -> (* Just ignore. The next token will be `Eof *) dlogr (fun () -> sprintf "FD %Ld: reactor_next_request: got timeout" (Netsys.int64_of_file_descr fd)); self # next_request() | _ -> (* Everything else means that we lost synchronization, and this is a * fatal error! *) dlogr (fun () -> sprintf "FD %Ld: reactor_next_request: out of sync" (Netsys.int64_of_file_descr fd)); logged_error_response fd_addr peer_addr None 0L false `Internal_server_error None (Some "Nethttpd: Reactor out of synchronization") None None config; proto # abort `Server_error; self # next_request() method close () = dlogr (fun () -> sprintf "FD %Ld: reactor close" (Netsys.int64_of_file_descr fd)); ( try self # synch(); with | err -> Netlog.Debug.release_fd fd; Unix.close fd; raise err ); proto # shutdown(); if proto # need_linger then ( dlogr (fun () -> sprintf "FD %Ld: lingering" (Netsys.int64_of_file_descr fd)); let lc = new Nethttpd_kernel.lingering_close ~preclose:(fun () -> Netlog.Debug.release_fd fd) fd in while lc # lingering do lc # cycle ~block:true () done ) else ( Netlog.Debug.release_fd fd; Unix.close fd ) end exception Redirect_response_legal of string * http_header type x_reaction = [ http_service_reaction | `Redirect_request of string * http_header ] let process_connection ?config_hooks config fd (stage1 : 'a http_service) = let fd_addr_str = try Netsys.string_of_sockaddr (Unix.getsockname fd) with _ -> "(noaddr)" in let peer_addr_str = try Netsys.string_of_sockaddr (Netsys.getpeername fd) with _ -> "(noaddr)" in dlogr (fun () -> sprintf "FD %Ld (%s -> %s) processing connection" (Netsys.int64_of_file_descr fd) peer_addr_str fd_addr_str ); let protect env f arg = try f arg with | Redirect_response_legal(_,_) as e -> raise e | Standard_response(status, hdr_opt, errmsg_opt) when !(env#output_state) = `Start -> ( output_std_response config env status hdr_opt errmsg_opt ) | err when !(env#output_state) = `Start -> output_std_response config env `Internal_server_error None (Some("Nethttpd: Handler exception: " ^ Netexn.to_string err)); in let do_stage3 req env stage3 = dlogr (fun () -> sprintf "req-%d: stage3" (Oo.id req)); try stage3 # generate_response env; dlogr (fun () -> sprintf "req-%d: stage3 done" (Oo.id req)); with | Redirect_request(_,_) -> failwith "Caught Redirect_request in stage 3, \ but it is only allowed in stage 1" | Redirect_response(uri,hdr) -> if !(env#output_state) <> `Start then failwith "Caught Redirect_response, \ but it is too late for redirections"; dlogr (fun () -> sprintf "req-%d: stage3 redirect_response" (Oo.id req)); raise (Redirect_response_legal(uri,hdr)) in let do_stage2 req env stage2 = dlogr (fun () -> sprintf "req-%d: stage2" (Oo.id req)); let stage3 = try stage2 # process_body env with | Redirect_request(_,_) -> failwith "Caught Redirect_request in stage 2, \ but it is only allowed in stage 1" | Redirect_response(_,_) -> failwith "Caught Redirect_response in stage 2, \ but it is only allowed in stage 3" in dlogr (fun () -> sprintf "req-%d: stage2 done" (Oo.id req)); req # finish_request(); do_stage3 req env stage3 in let rec process_request req (redir_env:extended_environment) redir_count = (* [redir_env]: The environment of the request, possibly rewritten by redirects. * [redir_count]: The number of already performed redirections * [req]: Contains always the original environment *) dlogr (fun () -> sprintf "req-%d: process_request redir_count=%d" (Oo.id req) redir_count); if redir_count > 10 then failwith "Too many redirections"; dlogr (fun () -> sprintf "req-%d: stage1" (Oo.id req)); let reaction = try (stage1 # process_header (redir_env :> extended_environment) :> x_reaction) with | Redirect_request(new_uri, new_hdr) -> `Redirect_request(new_uri, new_hdr) | Redirect_response(_,_) -> failwith "Caught Redirect_response in stage 1, \ but it is only allowed in stage 3" in dlogr (fun () -> let s_reaction = match reaction with | `Accept_body stage2 -> "Accept_body (next stage: stage2)" | `Reject_body stage3 -> "Reject_body (next stage: stage3)" | `Static _ -> "Static" | `File _ -> "File" | `Std_response _ -> "Std_response" | `Redirect_request _ -> "Redirect_request" in sprintf "req-%d: stage1 results in: %s" (Oo.id req) s_reaction ); ( try ( match reaction with | `Accept_body stage2 -> req # accept_body(); protect redir_env (do_stage2 req redir_env) stage2 | `Reject_body stage3 -> req # reject_body(); protect redir_env (do_stage3 req redir_env) stage3 | `Static(status, resp_hdr_opt, resp_str) -> req # reject_body(); output_static_response redir_env status resp_hdr_opt resp_str | `File(status, resp_hdr_opt, resp_filename, pos, length) -> req # accept_body(); protect redir_env (output_file_response redir_env status resp_hdr_opt resp_filename pos) length | `Std_response(status, resp_hdr_opt, errlog_opt) -> req # reject_body(); output_std_response config redir_env status resp_hdr_opt errlog_opt | `Redirect_request(new_uri, new_hdr) -> dlogr (fun () -> sprintf "req-%d: redirect_request to: %s" (Oo.id req) new_uri); let (new_script_name, new_query_string) = decode_query new_uri in new_hdr # update_multiple_field "Content-length" (redir_env # multiple_input_header_field "Content-length"); let new_properties = update_alist [ "REQUEST_URI", new_uri; "SCRIPT_NAME", new_script_name; "QUERY_STRING", new_query_string ] redir_env#cgi_properties in let new_env = new redirected_environment ~properties:new_properties ~in_header:new_hdr ~in_channel:req#environment#input_channel redir_env in process_request req new_env (redir_count+1) ) with | Redirect_response_legal(new_uri, new_hdr) -> dlogr (fun () -> sprintf "req-%d: redirect_response to: %s" (Oo.id req) new_uri); if !(redir_env#output_state) <> `Start then failwith "Redirect_response is not allowed after \ output has started"; let (new_script_name, new_query_string) = decode_query new_uri in new_hdr # update_field "Content-length" "0"; let new_properties = update_alist [ "REQUEST_URI", new_uri; "SCRIPT_NAME", new_script_name; "QUERY_STRING", new_query_string; "REQUEST_METHOD", "GET" ] redir_env#cgi_properties in let new_env = new redirected_environment ~properties:new_properties ~in_header:new_hdr redir_env in process_request req new_env (redir_count+1) ); dlogr (fun () -> sprintf "req-%d: finish" (Oo.id req)); req # finish(); dlogr (fun () -> sprintf "req-%d: done" (Oo.id req)); in let rec fetch_requests reactor = match reactor # next_request() with | None -> dlogr (fun () -> sprintf "FD %Ld - no next request" (Netsys.int64_of_file_descr fd)); () | Some req -> dlogr (fun () -> sprintf "FD %Ld - next request req-%d" (Netsys.int64_of_file_descr fd) (Oo.id req) ); process_request req req#environment 0; fetch_requests reactor in let reactor = try new http_reactor ?config_hooks config fd with err -> (* An exception means here that getsockname or getpeername failed. We can only close the descriptor! *) Unix.close fd; (* No need for release_fd - the descriptor has not yet been tracked! *) raise err in ( try fetch_requests reactor with err -> let bt = Printexc.get_backtrace() in let msg1 = Netexn.to_string err in let msg = msg1 ^ (if Printexc.backtrace_status() then " (backtrace: " ^ bt ^ ")" else "") in dlogr (fun () -> sprintf "Exception forwarding to error log: %s" msg); config # config_log_error no_info ("Nethttpd: Protocol exception: " ^ msg); ); ( try reactor # close() with err -> let bt = Printexc.get_backtrace() in let msg1 = Netexn.to_string err in let msg = msg1 ^ (if Printexc.backtrace_status() then " (backtrace: " ^ bt ^ ")" else "") in dlogr (fun () -> sprintf "Exception forwarding to error log: %s" msg); config # config_log_error no_info ("Nethttpd: Protocol exception: " ^ msg) ) ;; let default_http_processor_config = ( object inherit Nethttpd_kernel.modify_http_protocol_config Nethttpd_kernel.default_http_protocol_config method config_timeout_next_request = 15.0 method config_timeout = 300.0 method config_cgi = Netcgi.default_config method config_error_response = Nethttpd_util.std_error_response method config_log_error p msg = let s = Nethttpd_util.std_error_log_string p msg in Netlog.log `Err s method config_log_access p = () method config_tls_cert_props = true method config_tls_remote_user = true end ) let override v opt = match opt with | None -> v | Some x -> x class modify_http_processor_config ?modify_http_protocol_config:(m1 = fun cfg -> cfg) ?config_timeout_next_request ?config_timeout ?config_cgi ?config_error_response ?config_log_error ?config_log_access ?config_tls_cert_props ?config_tls_remote_user (config : http_processor_config) : http_processor_config = let config_timeout_next_request = override config#config_timeout_next_request config_timeout_next_request in let config_timeout = override config#config_timeout config_timeout in let config_cgi = override config#config_cgi config_cgi in let config_error_response = override config#config_error_response config_error_response in let config_log_error = override config#config_log_error config_log_error in let config_log_access = override config#config_log_access config_log_access in let config_tls_cert_props = override config#config_tls_cert_props config_tls_cert_props in let config_tls_remote_user = override config#config_tls_remote_user config_tls_remote_user in object inherit modify_http_protocol_config (m1 (config:>http_protocol_config)) method config_timeout_next_request = config_timeout_next_request method config_timeout = config_timeout method config_cgi = config_cgi method config_error_response = config_error_response method config_log_error = config_log_error method config_log_access = config_log_access method config_tls_cert_props = config_tls_cert_props method config_tls_remote_user = config_tls_remote_user end let default_http_reactor_config = ( object inherit modify_http_processor_config default_http_processor_config method config_reactor_synch = `Write end ) class modify_http_reactor_config ?modify_http_protocol_config ?modify_http_processor_config:(m2 = fun cfg -> cfg) ?config_reactor_synch (config : http_reactor_config) : http_reactor_config = let config_reactor_synch = override config#config_reactor_synch config_reactor_synch in object inherit modify_http_processor_config ?modify_http_protocol_config (m2 (config:>http_processor_config)) method config_reactor_synch = config_reactor_synch end ocamlnet-4.1.2/src/nethttpd/nethttpd_intro.txt0000644000175000017500000001750212731530350020177 0ustar gerdgerd{2:overview Overview over the HTTP daemon} This library implements an HTTP 1.1 server. Because it is a library and not a stand-alone server like Apache, it can be used in very flexible ways. The disadvantage is that the user of the library must do more to get a running program than just configuring the daemon. The daemon has five modules: - {!Nethttpd_types} is just a module with common type definitions used by the other modules - {!Nethttpd_kernel} is the implementation of the HTTP protocol. If we talk about the "kernel" we mean this module. The kernel has two interface sides: There is the "socket side" and the "message side" that are connected by bidirectional data flow. The task of the kernel is to decode input received by the socket side and to deliver it to a consumer on the message side, and conversely to encode input coming in through the message side and to send it to the socket. The kernel is a quite low-level module; the socket is accessed in a multiplexing-compatible style, and the messages are sequences of tokens like "status line", "header", "body chunk" and so on. Normally a user of the daemon does not program the kernel directly. It is, however, possible to pass certain configuration options to the kernel even if an encapsulation is used. - {!Nethttpd_reactor} is an encapsulation of the kernel with a nicer interface. An instance of the reactor processes, like the kernel, only a single HTTP connection. It is used as follows: The user of the reactor pulls the arriving HTTP requests from the reactor, processes them, and writes the responses back to the reactor. This means that the requests are processed in a strictly sequential way. The reactor hides the details of the HTTP protocol. The reactor is able to perform socket input and output at the same time, i.e. when the response is sent to the client the next request(s) can already be read (pipelining). The reactor can be configured such that buffering of requests and responses is avoided, even if large messages are transferred. As mentioned, the reactor can only deal with one connection at the same time. In order to serve several connections, one must use multi-threading. - {!Nethttpd_engine} is another encapsulation of the kernel. It is event-based, and this makes it possible that several instances can work at the same time without using multi-threading. The user of the engine is called back when the beginning of the next HTTP request arrives and at certain other events. The user processes the event, and generates the response. The engine is a highly efficient implementation of an HTTP server, but there are also drawbacks, so user may feel more comfortable with the reactor. Especially, the engine needs large buffers for input and output (there is an idea to use helper threads to avoid these buffers, but this has not been implemented yet). Of course, the engine also supports pipelining. - {!Nethttpd_services} has functions to compose complex service functions from simpler ones. In particular, one can configure name- or IP-based virtual hosting, one can bind services to URLs, and one can define static file serving, directory listings, and dynamic services. It is quite easy to turn a Netcgi program into a dynamic service for Nethttpd. - {!Nethttpd_plex} provides nice integration into [netplex]. Most features provided by {!Nethttpd_services} can be activated by simply referencing them in the netplex configuration file. It is also important to mention what Nethttpd does not include: - There is no function to create the socket, and to accept connections. - There is no function to manage threads or subprocesses Ocamlnet provides this in the [netplex] library. {2 Suggested strategy} First, look at {!Nethttpd_services}. This module allows the user to define the services of the web server. For example, the following code defines a single host with an URL space: {[ let fs_spec = { file_docroot = "/data/docroot"; file_uri = "/"; file_suffix_types = [ "txt", "text/plain"; "html", "text/html" ]; file_default_type = "application/octet-stream"; file_options = [ `Enable_gzip; `Enable_listings simple_listing ] } let srv = host_distributor [ default_host ~pref_name:"localhost" ~pref_port:8765 (), uri_distributor [ "*", (options_service()); "/files", (file_service fs_spec); "/service", (dynamic_service { dyn_handler = process_request; dyn_activation = std_activation `Std_activation_buffered; dyn_uri = Some "/service"; dyn_translator = file_translator fs_spec; dyn_accept_all_conditionals = false }) ] ] ]} The [/files] path is bound to a static service, i.e. the files found in the directory [/data/docroot] can be accessed over the web. The record [fs_spec] configures the static service. The [/service] path is bound to a dynamic service, i.e. the requests are processed by the user-defined function [process_request]. This function is very similar to the request processors used in Netcgi. The symbolic [*] path is only bound for the [OPTIONS] method. This is recommended, because clients can use this method to find out the capabilities of the server. Second, select an encapsulation. As mentioned, the reactor is much simpler to use, but you must take a multi-threaded approach to serve multiple connections simultaneously. The engine is more efficient, but may use more memory (unless it is only used for static pages). Third, write the code to create the socket and to accept connections. For the reactor, you should do this in a multi-threaded way (but multi-processing is also possible). For the engine, you should do this in an event-based way. Now, just call {!Nethttpd_reactor.process_connection} or {!Nethttpd_engine.process_connection}, and pass the socket descriptor as argument. These functions do all the rest. The Ocamlnet source tarball includes examples for several approaches. Especially look at [file_reactor.ml], [file_mt_reactor.ml], and [file_engine.ml]. {2 Configuration} One of the remaining questions is: How to set all these configuration options. The user configures the daemon by passing a configuration object. This object has a number of methods that usually return constants, but there are also a few functions, e.g. {[ let config : http_reactor_config = object method config_timeout_next_request = 15.0 method config_timeout = 300.0 method config_reactor_synch = `Write method config_cgi = Netcgi_env.default_config method config_error_response n = "Error " ^ string_of_int n ^ "" method config_log_error _ _ _ _ msg = printf "Error log: %s\n" msg method config_max_reqline_length = 256 method config_max_header_length = 32768 method config_max_trailer_length = 32768 method config_limit_pipeline_length = 5 method config_limit_pipeline_size = 250000 end ]} Some of the options are interpreted by the encapsulation, and some by the kernel. The object approach has been taken, because it can be arranged that the layers of the daemon correspond to a hierarchy of class types. The options are documented in the modules where the class types are defined. Some of them are difficult to understand. In doubt, it is recommended to just copy the values found in the examples, because these are quite reasonable for typical usage scenarios. {2 Linking} In Ocamlnet 3 the nethttpd library can be both referenced as [-package nethttpd] or [-package nethttpd-for-netcgi2] (the latter being an alias). As the [netcgi1] library was dropped, there is no reason for [nethttpd-for-netcgi1] anymore - this name is now unavailable. ocamlnet-4.1.2/src/nethttpd/nethttpd_engine.ml0000644000175000017500000014454412731530350020111 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Nethttpd; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) module Debug = struct let enable = ref false end let dlog = Netlog.Debug.mk_dlog "Nethttpd_engine" Debug.enable let dlogr = Netlog.Debug.mk_dlogr "Nethttpd_engine" Debug.enable let () = Netlog.Debug.register_module "Nethttpd_engine" Debug.enable open Nethttp open Nethttp.Header open Nethttpd_types open Nethttpd_kernel open Printf type engine_req_state = [ `Received_header | `Receiving_body | `Received_request | `Finishing ] class type http_engine_config = object inherit Nethttpd_reactor.http_processor_config method config_input_flow_control : bool method config_output_flow_control : bool end class type extended_async_environment = object inherit extended_environment method input_ch_async : Uq_engines.async_in_channel method output_ch_async : Uq_engines.async_out_channel end class type http_request_header_notification = object method req_state : engine_req_state method environment : extended_async_environment method schedule_accept_body : on_request:(http_request_notification -> unit) -> ?on_error:(unit -> unit) -> unit -> unit method schedule_reject_body : on_request:(http_request_notification -> unit) -> ?on_error:(unit -> unit) -> unit -> unit method schedule_finish : unit -> unit end and http_request_notification = object method req_state : engine_req_state method environment : extended_async_environment method schedule_finish : unit -> unit end type conn_state = [ `Active of http_protocol | `Closing of lingering_close | `Closed ] type reset_cond = unit -> unit exception Ev_output_filled of Unixqueue.group * reset_cond (** condition: The output channel filled data into the [http_response] object, and * notifies now the [http_engine] *) (* FIXME: This event is also sent for response objects that are still buffering but not yet writing to the output descriptor. This is not harmful, because it means this event is sent too often. This is inelegant, though, and might be a performance problem. *) exception Ev_input_empty of Unixqueue.group * reset_cond (** condition: The input channel became empty, and the engine must be notified * (used for input flow control) *) class condition ues mk_ev = object(self) val mutable signaled = false (* Records whether there is [ev] on the event queue. As [ev] is used only for expressing a condition, it is nonsense to add [ev] twice to the queue. *) val mutable ev = lazy(assert false) initializer ( let ev0 = mk_ev self#reset in ev <- lazy ev0 ) method signal() = if not signaled then ( Unixqueue.add_event ues (Lazy.force ev); signaled <- true ) method reset() = (* To be called when [ev] is consumed by the event handler *) signaled <- false end class http_engine_input config ues group in_cnt fdi rqid = let cond_input_empty = new condition ues (fun reset -> Unixqueue.Extra(Ev_input_empty(group,reset))) in object(self) (* The input channel is fed with data by the main event handler that invokes * [add_data] and [add_eof] to forward new input data to this channel. *) val mutable front = None val mutable data_queue = Queue.create() val mutable eof = false val mutable pos_in = 0 val mutable closed = false val mutable locked = true val mutable aborted = false val mutable notify_list = [] val mutable notify_list_new = [] method cond_input_empty = cond_input_empty method input s spos slen = dlogr (fun () -> sprintf "FD %Ld req-%d: input.input" fdi !rqid); if closed then raise Netchannels.Closed_channel; if locked then failwith "Nethttpd_engine: channel is locked"; if aborted then failwith "Nethttpd_engine: channel aborted"; (match front with | None -> ( try front <- Some(Queue.take data_queue) with Queue.Empty -> () ) | Some _ -> () ); (match front with | None -> if eof then raise End_of_file else 0 (* buffer underrun *) | Some (u,upos,ulen) -> let len = min slen ulen in Bytes.blit u upos s spos len; if len = ulen then front <- None else front <- Some(u,upos+len,ulen-len); pos_in <- pos_in + len; if not (self # can_input) then ( if config#config_input_flow_control then cond_input_empty # signal(); self # notify(); ); len ) method pos_in = pos_in method close_in() = dlogr (fun () -> sprintf "FD %Ld req-%d: input.close_in" fdi !rqid); if not closed then ( if locked then failwith "Nethttpd_engine: channel is locked"; front <- None; Queue.clear data_queue; closed <- true ) method can_input = not closed && (front <> None || not(Queue.is_empty data_queue) || eof) method request_notification f = notify_list_new <- f :: notify_list_new method private notify() = notify_list <- notify_list @ notify_list_new; notify_list_new <- []; notify_list <- List.filter (fun f -> f()) notify_list method add_data ((_,_,len) as data_chunk) = dlogr (fun () -> sprintf "FD %Ld req-%d: input.add_data" fdi !rqid); assert(len > 0); if not eof then ( let old_can_input = self # can_input in Queue.push data_chunk data_queue; in_cnt := Int64.add !in_cnt (Int64.of_int len); if not old_can_input && not closed then self # notify() ) (* else: we are probably dropping all data! *) method add_eof() = dlogr (fun () -> sprintf "FD %Ld req-%d: input.add_eof" fdi !rqid); if not eof then ( let old_can_input = self # can_input in eof <- true; if not old_can_input && not closed then self # notify() ) method unlock() = dlogr (fun () -> sprintf "FD %Ld req-%d: input.unlock" fdi !rqid); locked <- false method drop() = dlogr (fun () -> sprintf "FD %Ld req-%d: input.drop" fdi !rqid); locked <- false; eof <- true method abort() = dlogr (fun () -> sprintf "FD %Ld req-%d: input.abort" fdi !rqid); aborted <- true end class http_engine_output config ues group resp output_state (f_access : unit->unit) fdi = let cond_output_filled = new condition ues (fun reset -> Unixqueue.Extra(Ev_output_filled(group,reset))) in object(self) (* The output channel adds the incoming data to the [http_response] object * [resp]. The main [http_engine] is notified about new data by a * [Ev_output_filled] event. This gives the [http_engine] has the chance to * check whether it again enables output because new data is to be output. * * Note that [resp] is setup such that it calls [resp_notify] whenever the state * of [resp] changes, or the [resp] queue becomes empty. We do not immediately * forward this notification, but delay it a bit by pusing the invocation * onto the event queue. This indirection * is necessary because the moment of the [resp_notify] invocation is quite * hairy, and failures must not be risked. *) val mutable pos_out = 0 val mutable closed = false val mutable locked = true val mutable aborted = false val mutable notify_list = [] val mutable notify_list_new = [] initializer ( resp # set_callback self#resp_notify ) method cond_output_filled = cond_output_filled method output s spos slen = (* In principle we always accept any amount of output data. For practical reasons, * the length of an individual chunk is limited to 8K - it just prevents * some dumb programming errors. *) dlogr (fun () -> sprintf "FD %Ld resp-%d: output.output" fdi (Oo.id resp)); if closed then raise Netchannels.Closed_channel; if locked then failwith "Nethttpd_engine: channel is locked"; if aborted then failwith "Nethttpd_engine: channel aborted"; if !output_state <> `Sending then failwith "output channel: cannot output now"; let len = min slen 8192 in if len > 0 then ( let old_can_output = self # can_output in let u = Bytes.sub s spos len in resp # send (`Resp_body(u,0,Bytes.length u)); cond_output_filled # signal(); pos_out <- pos_out + len; if old_can_output <> self # can_output then self # notify(); ); len method pos_out = pos_out method flush() = dlogr (fun () -> sprintf "FD %Ld resp-%d: output.flush" fdi (Oo.id resp)); () method close_out() = dlogr (fun () -> sprintf "FD %Ld resp-%d: output.close_out" fdi (Oo.id resp)); if not closed then ( if locked then failwith "Nethttpd_engine: channel is locked"; let old_can_output = self # can_output in resp # send `Resp_end; closed <- true; output_state := `End; f_access(); cond_output_filled # signal(); if old_can_output <> self # can_output then self # notify(); ) method close_after_send_file() = dlogr (fun () -> sprintf "FD %Ld resp-%d: output.close_after_send_file" fdi (Oo.id resp)); closed <- true; f_access(); method can_output = (not config#config_output_flow_control) || ((resp # state = `Active) && resp # send_queue_empty) method unlock() = dlogr (fun () -> sprintf "FD %Ld resp-%d: output.unlock" fdi (Oo.id resp)); locked <- false method resp_notify() = Unixqueue.once ues group 0.0 self#notify (* CHECK: It is assumed that self#notify is called before the condition * is again invalid. * If this turns out to be wrong, we have to implement a quicker way of * notification. It is known that [resp_notify] is called back from the * current [cycle]. One could check after every [cycle] whether the * notification is still valid. *) method request_notification f = notify_list_new <- f :: notify_list_new method private notify() = notify_list <- notify_list @ notify_list_new; notify_list_new <- []; notify_list <- List.filter (fun f -> f()) notify_list method abort() = dlogr (fun () -> sprintf "FD %Ld resp-%d: output.abort" fdi (Oo.id resp)); aborted <- true end class http_async_environment config ues group ((req_meth, req_uri), req_version) req_hdr fd_addr peer_addr in_ch_async in_cnt out_ch_async output_state resp reqrej fdi tls_props = let in_ch = Netchannels.lift_in ~buffered:false (`Raw (in_ch_async :> Netchannels.raw_in_channel)) in let out_ch = Netchannels.lift_out ~buffered:false (`Raw (out_ch_async :> Netchannels.raw_out_channel)) in (* [in_ch] and [out_ch] are standard channels corresponding to [in_ch_async] and * [out_ch_async]. Note that there is no buffering. A buffer would introduce * a delay between the standard and the asynchronous channels - a very surprising * effect. Furthermore, there is already a lot of buffering in [http_protocol], * so buffers are probably not needed here. *) object (self) inherit Nethttpd_reactor.http_environment config req_meth req_uri req_version req_hdr fd_addr peer_addr in_ch in_cnt out_ch output_state resp out_ch_async#close_after_send_file reqrej fdi tls_props as super method input_ch_async = (in_ch_async :> Uq_engines.async_in_channel) method output_ch_async = (out_ch_async :> Uq_engines.async_out_channel) method send_output_header() = let ok = !output_state = `Start in super # send_output_header(); if ok then out_ch_async # cond_output_filled # signal() method send_file fd length = super # send_file fd length; (* does not block, because [synch] is now [ fun () -> () ] *) out_ch_async # cond_output_filled # signal() end class http_request_manager config ues group req_line req_hdr expect_100_continue fd_addr peer_addr resp fdi tls_props = let f_access = ref (fun () -> ()) in (* set below *) let in_cnt = ref 0L in let reqrej = ref false in let rqid = ref (-1) in let output_state = ref `Start in let in_ch = new http_engine_input config ues group in_cnt fdi rqid in let out_ch = new http_engine_output config ues group resp output_state (fun () -> !f_access()) fdi in let env = new http_async_environment config ues group req_line req_hdr fd_addr peer_addr in_ch in_cnt out_ch output_state resp reqrej fdi tls_props in (* may raise Standard_response! *) let () = f_access := env # log_access in object(self) (* This class also satisfies the types [http_request_notification] and * [http_request_header_notification] *) initializer ( dlogr (fun () -> sprintf "FD=%Ld: new request_manager req-%d resp-%d" fdi (Oo.id self) (Oo.id resp)); rqid := (Oo.id self) ) val mutable req_state = ( `Received_header : engine_req_state ) (* When this object is created, the header has just been received *) val mutable req_handler = (fun _ -> failwith "Nethttpd_engine: No [on_request] function") val mutable error_handler = (fun () -> ()) method real_input_ch = in_ch (* full type! *) method real_output_ch = out_ch (* full type! *) method environment = (env :> extended_async_environment) method req_state = req_state method set_req_state s = req_state <- s method req_handler = (req_handler : http_request_notification -> unit) method error_handler = error_handler method log_access = env#log_access method abort() = dlogr (fun () -> sprintf "FD %Ld req-%d: abort" fdi (Oo.id self)); in_ch # abort(); out_ch # abort(); method schedule_accept_body ~on_request ?(on_error = fun ()->()) () = dlogr (fun () -> sprintf "FD %Ld req-%d: accept_body" fdi (Oo.id self)); (* Send the "100 Continue" response if requested: *) if expect_100_continue then ( resp # send resp_100_continue; out_ch # cond_output_filled # signal(); ); (* Unlock everything: *) in_ch # unlock(); out_ch # unlock(); env # unlock(); (* Remember the callback functions: *) req_handler <- on_request; error_handler <- on_error method schedule_reject_body ~on_request ?(on_error = fun ()->()) () = dlogr (fun () -> sprintf "FD %Ld req-%d: reject_body" fdi (Oo.id self)); (* Unlock everything: *) in_ch # drop(); out_ch # unlock(); env # unlock(); reqrej := true; (* Remember the callback functions: *) req_handler <- on_request; error_handler <- on_error method schedule_finish() = (* This is quite tricky: * - Any remaining data in the input channel is dropped. The [drop] method * does this. This has also the effect that any additional data still * arriving is thrown away. * - We have to check the output state for the response. If it is still `Start, * the whole response is missing. We generate a "Server Error" in this case. * Otherwise we just close the output channel and hope we are done. * - We also set [req_state] to `Finishing to inform all other parts of the * engine what is going on. *) dlogr (fun () -> sprintf "FD %Ld req-%d: schedule_finish" fdi (Oo.id self)); in_ch # drop(); out_ch # unlock(); env # unlock(); req_state <- `Finishing; match !(env # output_state) with | `Start -> (* The whole response is missing! Generate a "Server Error": *) dlogr (fun () -> sprintf "FD %Ld req-%d: missing response error" fdi (Oo.id self)); output_std_response config env `Internal_server_error None (Some "Nethttpd: Missing response, replying 'Server Error'"); (env # output_state) := `End; | `Sending -> (* The response body is probably incomplete or missing. Try to close * the channel. *) ( try env # output_ch # close_out() with Netchannels.Closed_channel -> () ); (env # output_state) := `End; | `End -> (* Everything ok, just to be sure... *) ( try env # output_ch # close_out() with Netchannels.Closed_channel -> () ) end let ensure_not_reentrant name lock f arg = if !lock then ( prerr_endline ("Illegal reentrancy: " ^ name); assert false ); lock := true; try let r = f arg in lock := false; r with err -> lock := false; raise err class http_engine ?(config_hooks = fun _ -> ()) ~on_request_header () config fd ues = (* note that "new http_engine" can already raise exceptions, e.g. Unix.ENOTCONN *) let _proto = new http_protocol config fd in let () = config_hooks _proto#hooks in let handle_event_lock = ref false in let fdi = Netsys.int64_of_file_descr fd in object(self) inherit [unit] Uq_engines.engine_mixin (`Working 0) ues val fd_addr = Unix.getsockname fd val peer_addr = Netsys.getpeername fd val mutable conn_state = (`Active _proto : conn_state) val mutable group = Unixqueue.new_group ues val mutable enable_in = false val mutable in_timeout = 0.0 val mutable enable_out = false (* - When to listen for input events? In principle, when [proto # do_input] * indicates this. This flag can only change after every [proto # cycle]. * - When to listen for output events? In principle, when [proto # do_output] * indicates this. This flag can change after [proto # cycle], but also * after new data have been output. Our output channel will tell us, and * sends [Ev_output_filled] events to us. *) val mutable cur_request_manager = None val mutable eof_seen = false initializer ( self # start(); Netlog.Debug.track_fd (* configure tracking as last step of init *) ~owner:"Nethttpd_engine" ~descr:(sprintf "HTTP %s->%s" (Netsys.string_of_sockaddr peer_addr) (Netsys.string_of_sockaddr fd_addr)) fd ) method private start() = Unixqueue.add_handler ues group (fun _ _ -> self # handle_event); Unixqueue.add_abort_action ues group (fun _ -> self # handle_exception); self # enable_input true method private enable_input flag = let timeout = match conn_state with | `Active proto -> ( match proto # input_timeout_class with | `None -> (-1.0) | `Normal -> config#config_timeout | `Next_message -> config#config_timeout_next_request ) | `Closing lc -> 1.0 (* i.e. check every second whether the lingering phase is over *) | `Closed -> assert false in ( match (flag, enable_in) with | (true, false) -> Unixqueue.add_resource ues group (Unixqueue.Wait_in fd, timeout); | (false, true) -> Unixqueue.remove_resource ues group (Unixqueue.Wait_in fd); | (true, true) when timeout <> in_timeout -> Unixqueue.remove_resource ues group (Unixqueue.Wait_in fd); Unixqueue.add_resource ues group (Unixqueue.Wait_in fd, timeout); | _ -> () ); enable_in <- flag; in_timeout <- timeout; method private enable_output flag = if flag && not enable_out then Unixqueue.add_resource ues group (Unixqueue.Wait_out fd, config#config_timeout); if not flag && enable_out then Unixqueue.remove_resource ues group (Unixqueue.Wait_out fd); enable_out <- flag method private handle_event ev = ensure_not_reentrant "Nethttpd_engine.http_engine#handle_event" handle_event_lock (fun () -> match ev with | Unixqueue.Input_arrived(g,_) when g = group -> (* Input data from the HTTP client *) ( match conn_state with | `Active proto -> self # cycle_proto proto | `Closing lc -> self # cycle_lc lc | `Closed -> () (* drop this event *) ); self # count() | Unixqueue.Output_readiness(g,_) when g = group -> (* The HTTP client accepts new data *) ( match conn_state with | `Active proto -> self # cycle_proto proto | `Closing lc -> () (* Strange. Ignore for now. *) | `Closed -> () (* drop this event *) ); self # count() | Unixqueue.Timeout(g,_) when g = group -> (* Register a timeout *) ( match conn_state with | `Active proto -> self # timeout_proto proto | `Closing lc -> self # cycle_lc lc | `Closed -> () (* drop this event *) ) | Unixqueue.Extra (Ev_output_filled(g,reset)) when g = group -> (* The output channel is filled with fresh data *) reset(); ( match conn_state with | `Active proto -> (* Check whether to enable output now: *) self # enable_output proto#do_output | `Closing lc -> () (* drop this event *) | `Closed -> () (* drop this event *) ) | Unixqueue.Extra (Ev_input_empty(g,reset)) when g = group -> (* The input channel is empty. CHECK: why is this a no-op? *) reset(); ( match conn_state with | `Active proto -> () | `Closing lc -> () (* drop this event *) | `Closed -> () (* drop this event *) ) | _ -> raise Equeue.Reject (* Other engines may want to see this event *) ) () method private count() = match self#state with | `Working n -> self # set_state(`Working(n+1)) | _ -> () method private cycle_proto proto = (* Do a HTTP protocol cycle, and check whether I/O is still enabled *) dlogr (fun () -> sprintf "FD %Ld: cycle" (Netsys.int64_of_file_descr fd)); proto # cycle(); (* do not block! *) self # goon_proto proto method private timeout_proto proto = (* Either input or output has timed out. *) dlogr (fun () -> sprintf "FD %Ld: timeout" (Netsys.int64_of_file_descr fd)); proto # timeout(); self # goon_proto proto method private goon_proto proto = dlogr (fun () -> sprintf "FD %Ld: go on" (Netsys.int64_of_file_descr fd)); let enabled_input_flow = (not config#config_input_flow_control) || ( (* Input flow control: We stop reading from the descriptor when there are * unprocessed request tokens. *) match cur_request_manager with | None -> true (* CHECK: This might be nonsense. It is possible that in the * last request manager the input channel has unprocessed data. * Don't know how to handle this. (I don't think it is possible * to attack the server because of this issue, because the * pipeline length option limits the number of unresponded * requests anyway.) *) | Some rm -> (* If the input channel is empty, we enable input, and vice versa: *) not(rm # environment # input_ch_async # can_input) ) in self # forward_input_tokens proto; self # enable_input (enabled_input_flow && proto#do_input); self # enable_output proto#do_output; (* Check whether the HTTP connection is processed and can be closed: *) if eof_seen && not proto#resp_queue_filled then ( if proto # need_linger then ( (* FIXME: It is strange to check here for a lingering close. This should never be necessary after getting an EOF from the client *) dlogr (fun () -> sprintf "FD %Ld: lingering" (Netsys.int64_of_file_descr fd)); let lc = new lingering_close ~preclose:(fun () -> Netlog.Debug.release_fd fd) fd in conn_state <- `Closing lc; self # enable_input true; self # enable_output false; ) else ( (* Just close the descriptor and shut down the engine: *) dlogr (fun () -> sprintf "FD %Ld: closing" (Netsys.int64_of_file_descr fd)); Netlog.Debug.release_fd fd; conn_state <- `Closed; Unix.close fd; Unixqueue.clear ues group; (* Stop in Unixqueue terms *) self # set_state (`Done()); (* Report the new state *) ) ) method private receive proto = let tok = proto # receive() in dlogr (fun () -> sprintf "FD %Ld: next token: %s" (Netsys.int64_of_file_descr fd) (Nethttpd_kernel.string_of_req_token tok) ); tok method private forward_input_tokens proto = (* Interpret all available input tokens: *) dlogr (fun () -> sprintf "FD %Ld: forward_input_tokens" (Netsys.int64_of_file_descr fd)); while proto # recv_queue_len > 0 do match self # receive proto with | `Req_header(req_line, req_hdr, resp) -> (* The next request starts. *) assert(cur_request_manager = None); let expect_100_continue = try proto # peek_recv() = `Req_expect_100_continue with Recv_queue_empty -> false in if expect_100_continue then ignore(self # receive proto); let f_access = ref (fun () -> ()) in let tls_props = proto # tls_session_props in ( try let rm = new http_request_manager (* or Standard_response *) config ues group req_line req_hdr expect_100_continue fd_addr peer_addr resp fdi tls_props in f_access := rm # log_access; cur_request_manager <- Some rm; dlogr (fun () -> sprintf "FD %Ld: got request req-%d, notifying user" (Netsys.int64_of_file_descr fd) (Oo.id rm)); (* Notify the user that we have received the header: *) let () = on_request_header (rm :> http_request_header_notification) in (* Note: the callback may raise an arbitrary exception *) dlogr (fun () -> sprintf "FD %Ld: back from user for req-%d" (Netsys.int64_of_file_descr fd) (Oo.id rm)) with | Standard_response(status, hdr_opt, msg_opt) -> (* Probably a problem when decoding a header field! *) dlogr (fun () -> sprintf "FD %Ld: got request -> std response" (Netsys.int64_of_file_descr fd)); let (req_meth, req_uri) = fst req_line in let (in_cnt,reqrej,env_opt) = match cur_request_manager with | Some rm -> let env = (rm # environment :> extended_environment) in (env#input_body_size, env#request_body_rejected, Some env) | None -> (0L, false, None) in Nethttpd_reactor.logged_error_response fd_addr peer_addr (Some(req_meth,req_uri)) in_cnt reqrej status (Some req_hdr) msg_opt env_opt (Some resp) (config :> Nethttpd_reactor.http_processor_config); Unixqueue.add_event ues (Unixqueue.Extra(Ev_output_filled(group,(fun () -> ())))); (* Now [cur_request_manager = None]. This has the effect that * all further input tokens for this request are silently * dropped. *) ) | `Req_expect_100_continue -> assert false (* already processed *) | `Req_body data_chunk -> (* Just forward data to the current request manager: *) dlogr (fun () -> sprintf "FD %Ld: got body data" (Netsys.int64_of_file_descr fd)); ( match cur_request_manager with | Some rm -> if rm # req_state <> `Finishing then rm # set_req_state `Receiving_body; rm # real_input_ch # add_data data_chunk | None -> () (* drop it *) ) | `Req_trailer _ -> (* Don't know what to do with the trailer. *) dlogr (fun () -> sprintf "FD %Ld: got trailer" (Netsys.int64_of_file_descr fd)); () | `Req_end -> (* Just forward this event to the current request manager: *) dlogr (fun () -> sprintf "FD %Ld: got request end" (Netsys.int64_of_file_descr fd)); ( match cur_request_manager with | Some rm -> dlogr (fun () -> sprintf "FD %Ld: req end for req-%d" (Netsys.int64_of_file_descr fd) (Oo.id rm)); cur_request_manager <- None; ( match rm # req_state with | `Finishing -> (* The request has been dropped, so call the error * handler. *) rm # error_handler() | _ -> (* Normal end of request: *) rm # set_req_state `Received_request; rm # real_input_ch # add_eof (); (* Now call the function given by the [on_request] argument: *) rm # req_handler (rm :> http_request_notification); (* Note: the callback may raise an arbitrary exception *) ) | None -> () (* drop *) ); | `Eof -> (* If there is still a request manager, finish the current request. *) dlogr (fun () -> sprintf "FD %Ld: got eof" (Netsys.int64_of_file_descr fd)); ( match cur_request_manager with | Some rm -> cur_request_manager <- None; ( match rm # req_state with | `Received_request -> (* This is impossible! *) assert false | `Finishing -> (* The current request has not been arrived completely. * It has been dropped, so call the error handler. *) rm # error_handler() | _ -> (* Same as before, but the request was not yet properly * finished. *) rm # schedule_finish(); rm # error_handler() ); | None -> () ); (* Record this event. Will be checked in [cylce_proto] *) eof_seen <- true | `Fatal_error e -> (* The connection is already down. Just log the incident: *) dlogr (fun () -> sprintf "FD %Ld: got fatal error" (Netsys.int64_of_file_descr fd)); if e <> `Broken_pipe_ignore then ( let msg = Nethttpd_kernel.string_of_fatal_error e in Nethttpd_reactor.logged_error_response fd_addr peer_addr None 0L false `Internal_server_error None (Some msg) None None (config :> Nethttpd_reactor.http_processor_config) (* Note: The kernel ensures that the following token will be [`Eof]. * Any necessary cleanup will be done when [`Eof] is processed. *) ) | `Bad_request_error (e, resp) -> (* Log the incident, and reply with a 400 response. There isn't any * request manager, because `Bad_request_error replaces `Req_header * when bad requests arrive. *) dlogr (fun () -> sprintf "FD %Ld: got bad request" (Netsys.int64_of_file_descr fd)); assert(cur_request_manager = None); let msg = string_of_bad_request_error e in let status = status_of_bad_request_error e in Nethttpd_reactor.logged_error_response fd_addr peer_addr None 0L false status None (Some msg) None (Some resp) (config :> Nethttpd_reactor.http_processor_config); Unixqueue.add_event ues (Unixqueue.Extra(Ev_output_filled(group,(fun () -> ())))); (* Note: The kernel ensures that the following token will be [`Eof]. * Any necessary cleanup will be done when [`Eof] is processed. *) | `Timeout -> (* A non-fatal timeout. Always followed by [`Eof] *) dlogr (fun () -> sprintf "FD %Ld: got timeout" (Netsys.int64_of_file_descr fd)); () done method private cycle_lc lc = (* Do a cycle of the [lc] engine. *) dlogr (fun () -> sprintf "FD %Ld: cycle_lc" (Netsys.int64_of_file_descr fd)); lc # cycle(); (* do not block! *) let cont = lc # lingering in self # enable_output false; self # enable_input cont; if not cont then ( (* Now stop the whole engine! *) dlogr (fun () -> sprintf "FD %Ld: cycle_lc transitioning to Done" (Netsys.int64_of_file_descr fd)); conn_state <- `Closed; Unixqueue.clear ues group; (* Stop in Unixqueue terms *) self # set_state (`Done()); (* Report the new state *) ) method private handle_exception err = (* In general this should not happen. The HTTP kernel already handles all kinds * of I/O errors. This means all remaining exceptions are programming errors. *) assert false method event_system = ues method abort() = (* The hard way to stop everything: *) dlogr (fun () -> sprintf "FD %Ld: abort" (Netsys.int64_of_file_descr fd)); match self#state with | `Working _ -> Unixqueue.clear ues group; (* Stop the queue immediately *) if conn_state <> `Closed then ( Netlog.Debug.release_fd fd; try Unix.close fd with _ -> () ); ( match conn_state with | `Active proto -> proto # abort `Broken_pipe (* This closes the file descriptors of all files currently * being sent by [send_file_response]. *) | _ -> () ); ( match cur_request_manager with | Some rm -> rm # abort() (* The input and output channels are forced to fail when data * is input/output. *) | None -> () ); self # set_state `Aborted | _ -> () (* already in a final state *) end class type http_engine_processing_config = object method config_synch_input : (Netchannels.in_obj_channel -> unit) -> Uq_engines.async_in_channel -> unit method config_synch_output : (Netchannels.out_obj_channel -> unit) -> Uq_engines.async_out_channel -> unit end class buffering_engine_processing_config : http_engine_processing_config = object method config_synch_input f (ch : Uq_engines.async_in_channel) = let queue = Queue.create() in let ch' = object(self) val mutable closed = false val mutable token = None val mutable pos_in = 0 method input u up ul = if closed then raise Netchannels.Closed_channel; try let (s,sp,sl) = self # next_token in let n = min ul sl in Bytes.blit s sp u up n; token <- if n = sl then None else Some(s,sp+n,sl-n); pos_in <- pos_in + n; n with Queue.Empty -> raise End_of_file method close_in() = closed <- true method pos_in = pos_in method private next_token = match token with | None -> let tok = Queue.take queue in token <- Some tok; tok | Some(s,p,l) -> (s,p,l) end in let s = Bytes.create 8192 in let on_data() = try while ch # can_input do let n = ch # input s 0 8192 in Queue.push (Bytes.sub s 0 n, 0, n) queue done; true (* notify again *) with End_of_file -> let ch' = Netchannels.lift_in ~buffered:false (`Raw ch') in f ch'; false (* don't notify any longer *) in ch # request_notification on_data; if ch # can_input then ignore(on_data()); method config_synch_output f (ch : Uq_engines.async_out_channel) = let ch' = Netchannels.lift_out ~buffered:false (`Raw (ch :> Netchannels.raw_out_channel)) in f ch' (* The output channel of the engine buffers anyway! *) end class type http_engine_processing_context = object method engine : unit Uq_engines.engine end type x_reaction = [ http_service_reaction | `Redirect_request of string * http_header ] exception Ev_stage2_processed of (http_service_generator option * http_request_header_notification * Unixqueue.group) (* Event: Stage 2 has been processed. The argument is the follow-up action: * - None: Finish request immediately * - Some g: Proceed with generator g * The other args only allow identification of the event. *) exception Ev_stage3_processed of ((string * http_header) option * http_request_notification * Unixqueue.group) (* Event: Stage 2 has been processed. The argument is the follow-up action: * - None: Finish request * - Some(uri,hdr): Redirect response to this location *) class redrained_environment ~out_channel (env : extended_environment) = object(self) inherit redirected_environment env method output_ch = out_channel method out_channel = out_channel (* CHECK: send_file? maybe it needs also to be overridden *) end class fake_rhn (req:http_request_notification) : http_request_header_notification = object method req_state = `Received_header method environment = req # environment method schedule_accept_body ~on_request ?(on_error = fun () -> ()) () = on_request req method schedule_reject_body ~on_request ?(on_error = fun () -> ()) () = on_request req method schedule_finish() = req # schedule_finish() end let process_connection ?config_hooks config pconfig fd ues (stage1 : _ http_service) : http_engine_processing_context = let fd_addr = Unix.getsockname fd in let peer_addr = Netsys.getpeername fd in dlogr (fun () -> sprintf "FD %Ld (%s -> %s) processing connection" (Netsys.int64_of_file_descr fd) (Netsys.string_of_sockaddr peer_addr) (Netsys.string_of_sockaddr fd_addr) ); let on_req_hdr = ref (fun _ -> ()) in let eng_config = object inherit Nethttpd_reactor.modify_http_processor_config (config :> Nethttpd_reactor.http_processor_config) method config_input_flow_control = true method config_output_flow_control = true end in let log_error req msg = let env = (req # environment :> extended_environment) in let meth = env # cgi_request_method in let uri = env # cgi_request_uri in Nethttpd_reactor.logged_error_response fd_addr peer_addr (Some(meth,uri)) 0L false `Internal_server_error (Some env#input_header) (Some msg) (Some env) None (config :> Nethttpd_reactor.http_processor_config) in let group = Unixqueue.new_group ues in (* for the extra events *) let fdi = Netsys.int64_of_file_descr fd in (* debug msg *) object(self) val mutable watched_groups = [] val mutable engine = lazy (assert false) initializer ( on_req_hdr := self # on_request_header; (* Create the http_engine, but be careful in case of errors: *) ( try let eng = new http_engine ?config_hooks ~on_request_header:(fun req -> !on_req_hdr req) () eng_config fd ues in Uq_engines.when_state ~is_aborted:(fun _ -> List.iter (Unixqueue.clear ues) watched_groups; watched_groups <- [] ) eng; engine <- lazy eng; with | error -> Unix.close fd; (* fd is not yet tracked here *) let eng = new Uq_engines.epsilon_engine (`Error error) ues in engine <- lazy eng ) ) method private do_stage3 req_id (req : http_request_notification) env redir_count stage3 = (* We call the response generator with a synchronized output channel. By sending * the [Ev_stage3_processed] event, we catch the point in time when the whole * request is over, and can be finished. *) dlogr (fun () -> sprintf "FD %Ld req-%d: preparing stage3 env=%d" fdi req_id (Oo.id env)); (* This construction just catches the [Ev_stage3_processed] event: *) let pe = new Uq_engines.poll_engine ~extra_match:(function | Ev_stage3_processed (_,r,g) -> r=req && g=group | _ -> false) [] ues in watched_groups <- pe#group :: watched_groups; Uq_engines.when_state ~is_done:(function | Unixqueue.Extra(Ev_stage3_processed(redirect_opt,_,_)) -> (* Maybe we have to perform a redirection: *) ( match redirect_opt with | Some (new_uri,new_hdr) -> dlogr (fun () -> sprintf "FD %Ld req-%d: redirect_response \ to %s" fdi req_id new_uri); if !(env # output_state) <> `Start then log_error req "Nethttpd: Redirect_response is not allowed \ after output has started" else ( let (new_script_name, new_query_string) = decode_query new_uri in new_hdr # update_field "Content-length" "0"; let new_properties = update_alist [ "REQUEST_URI", new_uri; "SCRIPT_NAME", new_script_name; "QUERY_STRING", new_query_string; "REQUEST_METHOD", "GET" ] env#cgi_properties in let new_env = new redirected_environment ~properties:new_properties ~in_header:new_hdr env in let new_req = new fake_rhn req in (* The fake_rhn accepts/rejects the body immediately. * In reality this is already done, but when we * redirect the response we must fake a fresh * request header object *) self # process_request new_req new_env (redir_count+1) ) | None -> dlogr (fun () -> sprintf "FD %Ld req-%d: stage3 done" fdi req_id); req # schedule_finish()) | _ -> assert false) pe; pconfig # config_synch_output (fun out_ch -> let env' = new redrained_environment ~out_channel:out_ch env in dlogr (fun () -> sprintf "FD %Ld req-%d: stage3 reqenv=%d env=%d" fdi req_id (Oo.id req#environment) (Oo.id env')); let redirect_opt = try stage3 # generate_response env'; None with | Redirect_request(_,_) -> log_error req "Nethttpd: Caught Redirect_request in stage 3, but it is only allowed in stage 1"; None | Redirect_response(new_uri, new_hdr) -> Some(new_uri, new_hdr) | Standard_response(status, hdr_opt, errmsg_opt) when !(env'#output_state) = `Start -> output_std_response config env' status hdr_opt errmsg_opt; None | err when !(env#output_state) = `Start -> output_std_response config env' `Internal_server_error None (Some("Nethttpd: Exception (sending server error): " ^ Netexn.to_string err)); None | err -> log_error req ("Nethttpd: Exception: " ^ Netexn.to_string err); (* Better do an abort here. We probably cannot finish the cycle regularly *) self # engine # abort(); None in dlogr (fun () -> sprintf "FD %Ld req-%d: stage3 postprocessing" fdi req_id); (* Send the event that we are done here: *) ues # add_event (Unixqueue.Extra(Ev_stage3_processed(redirect_opt,req,group))) ) req # environment # output_ch_async method private do_stage2 (req : http_request_header_notification) env redir_count stage2 = (* This is quite complicated. First, we schedule the body acceptance. Second, * we call the synchronized stage2 processor. In an MT environment, both * processes may run in parallel, so we have to synchronize them again (i.e. * determine the point in time when the body has accepted due to * [schedule_accept_body], and when the stage2 processor is done). To do so, * we send a [Ev_stage2_processed] event, and catch that by the main event loop. * (NB. We could also use a Uq_engines.signal_engine for this purpose, * but signal engines are not thread-safe (the signal function cannot be * called from other threads). Thread-safety is announced in the API, * though.) *) dlogr (fun () -> sprintf "FD %Ld req-%d: preparing stage2 env=%d" fdi (Oo.id req) (Oo.id env)); let accepted_request = ref None in let stage3_opt = ref None in (* When both variables are [Some], we are in synch again. *) let check_synch() = match (!accepted_request, !stage3_opt) with | (Some req', Some(Some stage3)) -> (* Synch + stage2 was successful. Continue with stage3: *) dlogr (fun () -> sprintf "FD %Ld synch req-%d req'-%d" fdi (Oo.id req) (Oo.id req')); (* assertion: req = req' *) self # do_stage3 (Oo.id req) req' env redir_count stage3 | (Some req', Some None) -> (* Synch, but stage2 was not successful. Finish the request immediately. *) dlogr (fun () -> sprintf "FD %Ld synch-err req-%d req'-%d" fdi (Oo.id req) (Oo.id req')); (* assertion: req = req' *) req' # schedule_finish() | _ -> (* All other cases: not yet in synch. Do nothing. *) () in req # schedule_accept_body ~on_request:(fun req' -> accepted_request := Some req'; check_synch()) (* ~on_error:XXX *) (* CHECK: close async in channel? *) (); (* This construction just catches the [Ev_stage2_processed] event: *) let pe = new Uq_engines.poll_engine ~extra_match:(function | Ev_stage2_processed(_,r,g) -> r=req && g=group | _ -> false) [] ues in watched_groups <- pe#group :: watched_groups; Uq_engines.when_state ~is_done:(function | Unixqueue.Extra(Ev_stage2_processed(st3_opt,_,_)) -> stage3_opt := Some st3_opt; check_synch() | _ -> assert false) pe; pconfig # config_synch_input (fun in_ch -> let env' = new redirected_environment ~in_channel:in_ch env in dlogr (fun () -> sprintf "FD %Ld req-%d: stage2 reqenv=%d env=%d" fdi (Oo.id req) (Oo.id req#environment) (Oo.id env')); let stage3_opt = try Some(stage2 # process_body env') with | Redirect_request(_,_) -> log_error req "Nethttpd: Caught Redirect_request in stage 2, \ but it is only allowed in stage 1"; None | Redirect_response(_,_) -> log_error req "Nethttpd: Caught Redirect_response in stage 2, \ but it is only allowed in stage 3"; None | Standard_response(status, hdr_opt, errmsg_opt) when !(env'#output_state) = `Start -> output_std_response config env' status hdr_opt errmsg_opt; None | err when !(env#output_state) = `Start -> output_std_response config env' `Internal_server_error None (Some("Nethttpd: Exception (sending server error): " ^ Netexn.to_string err)); None | err -> (* Unlikely case *) log_error req ("Nethttpd: Exception: " ^ Netexn.to_string err); (* Better do an abort here. We probably cannot finish the cycle regularly *) self # engine # abort(); None in (* Send the event that we are done here: *) dlogr (fun () -> sprintf "FD %Ld req-%d: stage2 done" fdi (Oo.id req)); ues # add_event (Unixqueue.Extra(Ev_stage2_processed(stage3_opt,req,group))) ) req # environment # input_ch_async method private process_request (req:http_request_header_notification) redir_env redir_count = (* [redir_env]: The environment of the request, possibly rewritten by redirects. * [redir_count]: The number of already performed redirections * [req]: Contains always the original environment *) dlogr (fun () -> sprintf "FD %Ld req-%d: process_request FD=%Ld env=%d redir_count=%d" fdi (Oo.id req) (Netsys.int64_of_file_descr fd) (Oo.id redir_env) redir_count); if redir_count > 10 then failwith "Too many redirections"; dlogr (fun () -> sprintf "FD %Ld req-%d: stage1" fdi (Oo.id req)); let reaction = try (stage1 # process_header redir_env :> x_reaction) with | Redirect_request(new_uri, new_hdr) -> `Redirect_request(new_uri, new_hdr) | Redirect_response(_,_) -> failwith "Caught Redirect_response in stage 1, but it is only allowed in stage 3" in dlogr (fun () -> let s_reaction = match reaction with | `Accept_body stage2 -> "Accept_body (next stage: stage2)" | `Reject_body stage3 -> "Reject_body (next stage: stage3)" | `Static _ -> "Static" | `File _ -> "File" | `Std_response _ -> "Std_response" | `Redirect_request _ -> "Redirect_request" in sprintf "FD %Ld req-%d: stage1 results in: %s" fdi (Oo.id req) s_reaction ); ( match reaction with | `Accept_body stage2 -> self # do_stage2 req redir_env redir_count stage2 | `Reject_body stage3 -> req # schedule_reject_body ~on_request:(fun req' -> self # do_stage3 (Oo.id req) req' redir_env redir_count stage3) (); | `Static(status, resp_hdr_opt, resp_str) -> req # schedule_reject_body ~on_request:(fun req' -> output_static_response redir_env status resp_hdr_opt resp_str; req' # schedule_finish()) (); | `File(status, resp_hdr_opt, resp_filename, pos, length) -> req # schedule_reject_body ~on_request:(fun req' -> output_file_response redir_env status resp_hdr_opt resp_filename pos length; req' # schedule_finish()) (); | `Std_response(status, resp_hdr_opt, errlog_opt) -> req # schedule_reject_body ~on_request:(fun req' -> output_std_response config redir_env status resp_hdr_opt errlog_opt; req' # schedule_finish()) (); | `Redirect_request(new_uri, new_hdr) -> dlogr (fun () -> sprintf "FD %Ld req-%d: redirect_request to: %s" fdi (Oo.id req) new_uri); let (new_script_name, new_query_string) = decode_query new_uri in new_hdr # update_multiple_field "Content-length" (redir_env # multiple_input_header_field "Content-length"); let new_properties = update_alist [ "REQUEST_URI", new_uri; "SCRIPT_NAME", new_script_name; "QUERY_STRING", new_query_string ] redir_env#cgi_properties in let new_env = new redirected_environment ~properties:new_properties ~in_header:new_hdr ~in_channel:(redir_env # input_channel) redir_env in self # process_request req new_env (redir_count+1) ) method private on_request_header req = try self # process_request req (req#environment :> extended_environment) 0 with | err -> log_error req ("Nethttpd: Exception: " ^ Netexn.to_string err); (* Better do an abort here. We probably cannot finish the cycle regularly *) self # engine # abort() method engine = Lazy.force engine end let override v opt = match opt with | None -> v | Some x -> x let default_http_engine_config = ( object inherit Nethttpd_reactor.modify_http_processor_config Nethttpd_reactor.default_http_processor_config method config_input_flow_control = false method config_output_flow_control = true end ) class modify_http_engine_config ?modify_http_protocol_config ?modify_http_processor_config:(m2 = fun cfg -> cfg) ?config_input_flow_control ?config_output_flow_control (config : http_engine_config) : http_engine_config = let config_input_flow_control = override config#config_input_flow_control config_input_flow_control in let config_output_flow_control = override config#config_output_flow_control config_output_flow_control in object inherit Nethttpd_reactor.modify_http_processor_config ?modify_http_protocol_config (m2 (config:>Nethttpd_reactor.http_processor_config)) method config_input_flow_control = config_input_flow_control method config_output_flow_control = config_output_flow_control end ocamlnet-4.1.2/src/nethttpd/nethttpd_kernel.ml0000644000175000017500000017316412731530350020124 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Nethttpd; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) module Debug = struct let enable = ref false end let dlog = Netlog.Debug.mk_dlog "Nethttpd_kernel" Debug.enable let dlogr = Netlog.Debug.mk_dlogr "Nethttpd_kernel" Debug.enable let () = Netlog.Debug.register_module "Nethttpd_kernel" Debug.enable open Nethttpd_types open Nethttp open Nethttp.Header open Printf type fatal_error = [ `Broken_pipe | `Broken_pipe_ignore | `Message_too_long | `Timeout | `Unix_error of Unix.error | `TLS_error of string * string | `Server_error ] let string_of_fatal_error = function | `Broken_pipe -> "Nethttpd: Broken pipe" | `Broken_pipe_ignore -> "Nethttpd: Ignorable broken pipe" | `Message_too_long -> "Nethttpd: Message too long, dropping it" | `Timeout -> "Nethttpd: Connection timed out" | `Unix_error ue -> ("Nethttpd: System error: " ^ Unix.error_message ue) | `TLS_error(code,msg) -> ("Nethttpd: TLS error code " ^ code ^ ": " ^ msg) | `Server_error -> "Nethttpd: Terminating connection because of internal error" type bad_request_error = [ `Bad_header_field of string | `Bad_header | `Bad_trailer | `Bad_request_line | `Request_line_too_long | `Protocol_not_supported | `Unexpected_eof | `Format_error of string ] let string_of_bad_request_error = function | `Bad_header_field s -> "Nethttpd: Bad request header field: " ^ s | `Bad_header -> "Nethttpd: Bad request header" | `Bad_trailer -> "Nethttpd: Bad request trailer" | `Bad_request_line -> "Nethttpd: Bad request line" | `Request_line_too_long -> "Nethttpd: Request line too long" | `Protocol_not_supported -> "Nethttpd: Prototol not supported" | `Unexpected_eof -> "Nethttpd: Bad request: unexpected EOF" | `Format_error s -> "Nethttpd: Bad request: " ^ s let status_of_bad_request_error = function | `Request_line_too_long -> `Request_uri_too_long | `Protocol_not_supported -> `Http_version_not_supported | _ -> `Bad_request type data_chunk = Bytes.t * int * int type status_line = int * string type transfer_coding = [ `Identity | `Chunked ] type resp_token = [ `Resp_info_line of (status_line * http_header) | `Resp_status_line of status_line | `Resp_header of http_header | `Resp_body of data_chunk | `Resp_trailer of http_trailer | `Resp_end | `Resp_action of (unit -> unit) ] let resp_100_continue = `Resp_info_line((100, "Continue"), new Netmime.basic_mime_header []) exception Send_queue_empty type front_token = [ `Resp_wire_data of data_chunk (* everything else *) | `Resp_end ] type front_token_x = [ front_token | `Resp_wire_action of (unit->unit) ] type front_token_opt = [ `None | front_token_x ] type resp_state = [ `Inhibited | `Queued | `Active | `Processed | `Error | `Dropped ] type announcement = [`Ignore | `Ocamlnet | `Ocamlnet_and of string | `As of string ] let string_of_front_token_x = function | `Resp_wire_data(s,pos,len) -> let n = min len 20 in sprintf "Resp_wire_data(%s%s)" (String.escaped (Bytes.sub_string s pos n)) (if len > n then "..." else "") | `Resp_end -> "Resp_end" | `Resp_wire_action _ -> "Resp_wire_action" class type http_response = object method state : resp_state method set_state : resp_state -> unit method bidirectional_phase : bool method set_callback : (unit -> unit) -> unit method send : resp_token -> unit method send_queue_empty : bool method protocol : protocol method close_connection : bool method transfer_encoding : transfer_coding method front_token : front_token method advance : int -> unit method body_size : int64 end let string_of_state = function | `Inhibited -> "Inhibited" | `Queued -> "Queued" | `Active -> "Active" | `Processed -> "Processed" | `Error -> "Error" | `Dropped -> "Dropped" (* TODO: * - make http_repsonse_impl thread-safe * - implement trailers *) class http_response_impl ?(close=false) ?(suppress_body=false) fdi (req_version : protocol) (ann_server : announcement) : http_response = (* - [close]: If true, the connection will be closed after this response * - [suppress_body]: If true, the body will not be transmitted (e.g. in response * to a HEAD request) * - [req_version]: The version of the request. Used to limit features in the * response to what the client understands. *) object(self) val resp_version = `Http((1,1),[]) val mutable state = `Queued val mutable accept = (`Status : [ `Status | `Header | `Body | `End | `None] ) val mutable suppress_body = suppress_body val mutable front_token = (`None : front_token_opt) val mutable queue = (Queue.create() : front_token_x Queue.t) val mutable close_connection = close val mutable transfer_encoding = `Identity val mutable announced_content_length = None val mutable real_length = 0L (* int64 *) val mutable callback = (fun () -> ()) val mutable bidirectional_phase = false method state = state method bidirectional_phase = bidirectional_phase method set_state s = let old_state = state in state <- s; dlogr (fun () -> sprintf "FD %Ld resp-%d: response state: %s" fdi (Oo.id self) (string_of_state s)); if s <> old_state && (s = `Processed || s = `Error || s = `Dropped) then ( (* do all actions on the queue *) try while true do match Queue.take queue with | `Resp_wire_action f -> ( try f() with _ -> () ) | _ -> () done with Queue.Empty -> () ); if s <> old_state then callback(); method set_callback f = callback <- f method send tok = match tok with | `Resp_info_line((code, phrase), info_header) -> if code < 100 || code > 199 then failwith "Nethttpd_kernel.http_response: Bad informational status code"; if accept <> `Status then failwith "Nethttpd_kernel.http_response: Cannot send status line now"; ( match req_version with | `Http((1,n),_) when n >= 1 -> let s = Printf.sprintf "%s %3d %s\r\n" (string_of_protocol resp_version) code phrase in let s = Bytes.of_string s in Queue.push (`Resp_wire_data (s, 0, Bytes.length s)) queue; (* Convert the header to a data chunk: *) let b = Netbuffer.create 256 in (* Expect a short/empty header in most cases *) let ch = new Netchannels.output_netbuffer b in Netmime_string.write_header ch info_header#fields; Queue.push (`Resp_wire_data (Netbuffer.unsafe_buffer b, 0, Netbuffer.length b)) queue; Queue.push (`Resp_wire_action (fun () -> bidirectional_phase <- true)) queue | _ -> () (* Suppress this for HTTP 1.0 and lower *) ) | `Resp_status_line (code, phrase) -> if code < 200 || code > 999 then failwith "Nethttpd_kernel.http_response: Bad final status code"; if accept <> `Status then failwith "Nethttpd_kernel.http_response: Cannot send status line now"; let s = Printf.sprintf "%s %03d %s\r\n" (string_of_protocol resp_version) code phrase in let s = Bytes.of_string s in Queue.push (`Resp_wire_action (fun () -> bidirectional_phase <- false)) queue; Queue.push (`Resp_wire_data (s, 0, Bytes.length s)) queue; accept <- `Header | `Resp_header resp_header -> if accept <> `Header then failwith "Nethttpd_kernel.http_response: Cannot send header now"; (* Set [announced_content_length]: *) ( try let len = get_content_length resp_header in (* or Not_found *) announced_content_length <- Some len; dlogr (fun () -> sprintf "FD %Ld resp-%d: response anncounced_content_length=%Ld" fdi (Oo.id self) len) with Not_found -> announced_content_length <- None ); (* Update the values for [close_connection] and [transfer_encoding]: *) ( match req_version with | `Http((1,n),_) when n >= 1 -> transfer_encoding <- ( match announced_content_length with | Some _ -> `Identity | None -> `Chunked ); dlogr (fun () -> sprintf "FD %Ld resp-%d: response transfer_encoding=%s" fdi (Oo.id self) (match transfer_encoding with | `Identity -> "identity" | `Chunked -> "chunked" )) | _ -> (* Other protocol version: fall back to conservative defaults *) close_connection <- true; transfer_encoding <- `Identity; dlogr (fun () -> sprintf "FD %Ld resp-%d: response \ transfer_encoding=identity; close_connection=true" fdi (Oo.id self)) ); (* Update the header: *) ( match transfer_encoding, suppress_body with | (`Identity, false) | (_, true) -> resp_header # delete_field "Transfer-Encoding" | (`Chunked, false) -> set_transfer_encoding resp_header ["chunked", []] ); resp_header # delete_field "Trailer"; set_date resp_header (Unix.time()); ( match close_connection with | false -> resp_header # delete_field "Connection" | true -> set_connection resp_header ["close"] ); resp_header # delete_field "Upgrade"; ( match ann_server with | `Ignore -> () | `Ocamlnet -> let sh = "Ocamlnet/" ^ Netconst.ocamlnet_version in set_server resp_header sh | `Ocamlnet_and s -> let sh = s ^ " Ocamlnet/" ^ Netconst.ocamlnet_version in set_server resp_header sh | `As sh -> set_server resp_header sh ); (* Convert the header to a data chunk: *) let b = Netbuffer.create 4096 in let ch = new Netchannels.output_netbuffer b in Netmime_string.write_header ch resp_header#fields; Queue.push (`Resp_wire_data (Netbuffer.unsafe_buffer b, 0, Netbuffer.length b)) queue; (* What is accepted next: *) accept <- `Body | `Resp_body ((s,pos,len) as data) -> if accept <> `Body then failwith "Nethttpd_kernel.http_response: Cannot send body now"; if pos < 0 || len < 0 || pos + len > Bytes.length s then invalid_arg "Nethttpd_kernel.http_response#send"; if not suppress_body then ( match transfer_encoding with | `Identity -> (* Check whether the length fits to the announced length: *) let len' = match announced_content_length with | None -> len | Some ann_len -> Int64.to_int (min (Int64.of_int len) (Int64.sub ann_len real_length)) in if len' > 0 then Queue.push (`Resp_wire_data (s,pos,len')) queue; if len > 0 && len' = 0 then dlogr (fun () -> sprintf "FD %Ld resp-%d: response warning: \ response is longer than announced" fdi (Oo.id self)) | `Chunked -> if len > 0 then ( (* Generate the chunk header: *) let u = Printf.sprintf "%x\r\n" len in let u = Bytes.of_string u in Queue.push (`Resp_wire_data(u,0,Bytes.length u)) queue; (* Output the chunk: *) Queue.push (`Resp_wire_data data) queue; (* Framing: *) let v = Bytes.of_string "\r\n" in Queue.push (`Resp_wire_data (v, 0, 2)) queue; ) ); real_length <- Int64.add real_length (Int64.of_int len); if real_length < 0L then (* Check for wrap around *) failwith "Nethttpd_kernel: response too long"; | `Resp_trailer resp_trailer -> if accept <> `Body then failwith "Nethttpd_kernel.http_response: Cannot send trailer now"; accept <- `End; (* trailers are ignored for now *) | `Resp_end -> if accept <> `Body && accept <> `End then failwith "Nethttpd_kernel.http_response: Cannot finish response now"; if not suppress_body then ( match transfer_encoding with | `Identity -> (* Check whether the length fits to the announced length: *) ( match announced_content_length with | None -> () | Some ann_len -> if ann_len > real_length then close_connection <- true ); Queue.push `Resp_end queue | `Chunked -> (* Add the last-chunk: *) let s = Bytes.of_string "0\r\n\r\n" in Queue.push (`Resp_wire_data(s,0,Bytes.length s)) queue; Queue.push `Resp_end queue; ); accept <- `None | `Resp_action f -> Queue.push (`Resp_wire_action f) queue method send_queue_empty = (state = `Inhibited) || ( (front_token = `None) && (Queue.is_empty queue) ) method protocol = resp_version method close_connection = close_connection method transfer_encoding = transfer_encoding method body_size = real_length method front_token : front_token = if state = `Inhibited then raise Send_queue_empty; match front_token with | `None -> ( try let tok = Queue.take queue in front_token <- (tok :> front_token_opt); dlogr (fun () -> sprintf "FD %Ld resp-%d: response new front_token: %s" fdi (Oo.id self) (string_of_front_token_x tok)); self # front_token with Queue.Empty -> raise Send_queue_empty ) | `Resp_wire_action f -> front_token <- `None; dlogr (fun () -> sprintf "FD %Ld resp-%d: response Resp_wire_action" fdi (Oo.id self)); f(); self # front_token | #front_token as other -> other method advance n = if n > 0 then ( ignore(self # front_token); (* such that we can assert front_token <> `None *) match front_token with | `Resp_wire_data (s,pos,len) -> if n > len then invalid_arg "Nethttpd_kernel#http_response: Cannot advance past the current data chunk"; let len' = len - n in front_token <- if len'=0 then `None else `Resp_wire_data(s,pos+n,len'); if front_token = `None && Queue.is_empty queue then callback() | `Resp_end -> failwith "Nethttpd_kernel#http_response: Cannot advance past the end of the response" | `Resp_wire_action _ -> assert false | `None -> assert false ) end let send_static_response resp status hdr_opt body = let code = int_of_http_status status in let text = string_of_http_status status in let h = ( match hdr_opt with | None -> new Netmime.basic_mime_header [] | Some h -> h ) in ( try ignore(h # field "Content-Type") with Not_found -> h # update_field "Content-type" "text/html"; ); h # update_field "Content-Length" (string_of_int (Bytes.length body)); resp # send (`Resp_status_line(code, text)); resp # send (`Resp_header h); resp # send (`Resp_body(body, 0, Bytes.length body)); resp # send `Resp_end ;; let send_file_response resp status hdr_opt fd length = Netlog.Debug.track_fd ~owner:"Nethttpd_kernel" ~descr:"file response" fd; let hdr = match hdr_opt with | None -> new Netmime.basic_mime_header [] | Some h -> h in ( match status with | `No_content | `Reset_content | `Not_modified -> () | _ -> ( try ignore(hdr # field "Content-Type") with Not_found -> hdr # update_field "Content-type" "text/html"; ); ); hdr # update_field "Content-Length" (Int64.to_string length); let code = int_of_http_status status in let phrase = string_of_http_status status in resp # send (`Resp_status_line (code, phrase)); resp # send (`Resp_header hdr); let fd_open = ref true in let buf = Bytes.create 8192 in let len = ref length in let rec feed() = match resp # state with | `Inhibited | `Queued -> assert false | `Active -> ( try let m = min 8192L !len in let n = Unix.read fd buf 0 (Int64.to_int m) in (* or Unix_error *) if n > 0 then ( len := Int64.sub !len (Int64.of_int n); resp # send (`Resp_body(buf, 0, n)); (* no copy of [buf]! *) resp # send (`Resp_action feed) (* loop *) ) else ( resp # send `Resp_end; fd_open := false; Netlog.Debug.release_fd fd; Unix.close fd; ) with | Unix.Unix_error((Unix.EAGAIN | Unix.EWOULDBLOCK),_,_) -> assert false (* Cannot happen when [fd] is a file! *) | Unix.Unix_error(Unix.EINTR, _, _) -> feed() ) | `Processed | `Error | `Dropped -> if !fd_open then ( Netlog.Debug.release_fd fd; Unix.close fd; ); fd_open := false in resp # send (`Resp_action feed) ;; type request_line = http_method * protocol type req_token = [ `Req_header of request_line * http_header * http_response | `Req_expect_100_continue | `Req_body of data_chunk | `Req_trailer of http_trailer | `Req_end | `Eof | `Fatal_error of fatal_error | `Bad_request_error of bad_request_error * http_response | `Timeout ] let string_of_req_token = function | `Req_header(((req_method, req_uri), req_proto), hd, resp) -> sprintf "Req_header(%s %s)" req_method req_uri | `Req_expect_100_continue -> "Req_expect_100_continue" | `Req_body(s,pos,len) -> let n = min len 20 in sprintf "Req_body_data(%s%s)" (String.escaped (Bytes.sub_string s pos n)) (if len > n then "..." else "") | `Req_trailer tr -> "Req_trailer" | `Req_end -> "Req_end" | `Eof -> "Eof" | `Fatal_error e -> sprintf "Fatal_error(%s)" (string_of_fatal_error e) | `Bad_request_error (e, resp) -> sprintf "Bad_request_error(%s)" (string_of_bad_request_error e) | `Timeout -> "Timeout" exception Recv_queue_empty exception Buffer_exceeded (* Internally used by HTTP implementation: The buffer was not large enough for the * current token *) exception Timeout (* Internally used by HTTP implementation: socket blocks for too long *) exception Fatal_error of fatal_error (* Internally used by HTTP implementation: Indicate fatal error *) exception Bad_request of bad_request_error (* Internally used by HTTP implementation: Indicate bad request *) class type http_protocol_config = object method config_max_reqline_length : int method config_max_header_length : int method config_max_trailer_length : int method config_limit_pipeline_length : int method config_limit_pipeline_size : int method config_announce_server : announcement method config_suppress_broken_pipe : bool method config_tls : Netsys_crypto_types.tls_config option end class type http_protocol_hooks = object method tls_set_cache : store:(string -> string -> unit) -> remove:(string -> unit) -> retrieve:(string -> string) -> unit end let http_find_line_start s pos len = let ops = Netstring_tstring.bytes_ops in try Netmime_string.find_line_start_poly ops s pos len with Not_found -> raise Buffer_exceeded let http_find_double_line_start s pos len = let ops = Netstring_tstring.bytes_ops in try Netmime_string.find_double_line_start_poly ops s pos len with Not_found -> raise Buffer_exceeded let parse_req_line s pos len = (* Parses a request line: "WORD WORD WORD\r\n", where \r is optional. The words are separated by spaces or TABs. Once we did this with a regexp, but this caused stack overflows in the regexp interpreter for long request lines. Raises Not_found if not parseable. We don't support HTTP/0.9. One could recognize it easily because the third word is missing. *) let e = pos+len in let rec next_sep p = if p >= e then raise Not_found else let c = Bytes.get s p in if c = ' ' || c = '\t' then p else if c = '\r' || c = '\n' then raise Not_found else next_sep(p+1) in let rec next_end p = if p >= e then raise Not_found else let c = Bytes.get s p in if c = '\r' || c = '\n' then p else next_end(p+1) in let rec skip_sep p = if p >= e then raise Not_found else let c = Bytes.get s p in if c = ' ' || c = '\t' then skip_sep(p+1) else p in let p1 = next_sep pos in let q1 = skip_sep p1 in let p2 = next_sep q1 in let q2 = skip_sep p2 in let p3 = next_end q2 in if Bytes.get s p3 = '\n' then ( if p3+1 <> e then raise Not_found ) else ( if Bytes.get s p3 <> '\r' then raise Not_found; if p3+2 <> e then raise Not_found; if Bytes.get s (p3+1) <> '\n' then raise Not_found; ); let w1 = Bytes.sub_string s pos (p1-pos) in let w2 = Bytes.sub_string s q1 (p2-q1) in let w3 = Bytes.sub_string s q2 (p3-q2) in (w1, w2, w3) let is_hex = function | '0'..'9' | 'a'..'f' | 'A'..'F' -> true | _ -> false let parse_chunk_header s pos len = (* Parses "HEXNUMBER OPTIONAL_SEMI_AND_IGNORED_EXTENSION CRLF", or raises Not_found. *) let ops = Netstring_tstring.bytes_ops in let e = pos+len in let rec skip_hex_number p = if p >= e then raise Not_found else let c = Bytes.get s p in if is_hex c then skip_hex_number(p+1) else p in let p1 = skip_hex_number pos in if p1 = pos || p1 >= e then raise Not_found; let c1 = Bytes.get s p1 in if c1=';' then ( let p2 = Netmime_string.find_line_start_poly ops s p1 (e - p1) in if p2 <> e then raise Not_found ) else ( if c1 = '\n' then ( if p1+1 <> e then raise Not_found ) else ( if p1+2 <> e then raise Not_found; if Bytes.get s (p1+1) <> '\n' then raise Not_found ) ); Bytes.sub_string s pos (p1-pos) type cont = [ `Continue of unit -> cont | `Restart | `Restart_with of unit -> cont ] module StrSet = Set.Make(String) class http_protocol (config : #http_protocol_config) (fd : Unix.file_descr) = let pa = Netsys_posix.create_poll_array 1 in let fdi = Netsys.int64_of_file_descr fd in let tls = match config # config_tls with | None -> None | Some tc -> Some(Netsys_tls.endpoint (Netsys_tls.create_file_endpoint ~role:`Server ~rd:fd ~wr:fd ~peer_name:None tc)) in let tls_message code = match config # config_tls with | None -> code | Some tc -> let module Config = (val tc : Netsys_crypto_types.TLS_CONFIG) in Config.TLS.error_message code in let hooks = ( object method tls_set_cache ~store ~remove ~retrieve = match tls with | None -> () | Some ep -> let module Endpoint = (val ep : Netsys_crypto_types.TLS_ENDPOINT) in Endpoint.TLS.set_session_cache ~store ~remove ~retrieve Endpoint.endpoint end ) in object(self) val mutable override_dir = None (* For TLS: can be set to [Some `R] or [Some `W] if the descriptor needs to be read or written *) val mutable tls_handshake = (tls <> None) (* Whether the handshake is not yet complete *) val mutable tls_shutdown = false (* Whether a TLS shutdown (for sending) needs to be done *) val mutable tls_shutdown_done = false (* Whether the TLS shutdown (for sending) is over *) val mutable tls_session_props = None (* Session properties (available after handshake) *) val mutable resp_queue = Queue.create() (* The queue of [http_response] objects. The first is currently being transmitted *) val mutable recv_buf = Netbuffer.create 8192 (* The buffer of received data that have not yet been tokenized *) val mutable recv_eof = false (* Whether EOF has been seen. This is also set if the protocol engine is no * longer interested in any input because of processing errors *) val mutable recv_fd_eof = false (* Whether the descriptor is at EOF. This can be different from recv_eof if TLS is active. *) val mutable recv_queue = (Queue.create() : (req_token * int) Queue.t) (* The queue of received tokens. The integer is the estimated buffer size *) val mutable recv_cont = (fun () -> `Restart) (* The continuation processing the beginning of [recv_buf] *) val mutable test_coverage = StrSet.empty (* Only used for certain tests: This set contains tokens for cases the program * ran into. *) val mutable pipeline_len = 0 val mutable recv_queue_byte_size = 0 val mutable waiting_for_next_message = true (* Updated by the input acceptor as side effect *) val mutable need_linger = true (* Whether we need a lingering close to reliable close the connection from the * server side. *) val linger_buf = Bytes.create 256 (* A small buffer for data thrown away *) initializer ( recv_cont <- self # accept_header 0; Unix.set_nonblock fd ) method hooks = hooks method cycle ?(block=0.0) () = override_dir <- None; try (* Block until we have something to read or write *) if block <> 0.0 then self # block block; (* Maybe the TLS handshake is in progress: *) if tls_handshake then self # do_tls_handshake() else if tls_shutdown && not tls_shutdown_done then self # do_tls_shutdown() else ( (* Accept any arriving data, and process that *) self # accept_data(); (* Transmit any outgoing data *) self # transmit_response(); ) with | Fatal_error e -> dlog (sprintf "FD %Ld: fatal error" fdi); self # abort e; | Timeout -> dlog (sprintf "FD %Ld: timeout" fdi); self # timeout() | Bad_request e -> (* Stop only the input side of the engine! *) dlog (sprintf "FD %Ld: bad request" fdi); self # stop_input_acceptor(); let resp = new http_response_impl ~close:true fdi (`Http((1,0),[])) config#config_announce_server in self # push_recv (`Bad_request_error(e, resp), 0); self # push_recv (`Eof, 0); resp # set_state `Queued; (* allow response from now on *) Queue.push resp resp_queue method private block d = (* If d < 0 wait for undefinite time. If d >= 0 wait for a maximum of d seconds. * On expiration, raise [Timeout]. *) dlogr (fun () -> sprintf "FD %Ld: block %f" fdi d); let f_input = self#do_input in let f_output = self#do_output in if not f_input && not f_output then raise Timeout; Netsys_posix.set_poll_cell pa 0 { Netsys_posix.poll_fd = fd; poll_req_events = Netsys_posix.poll_req_events f_input f_output false; poll_act_events = Netsys_posix.poll_null_events() }; let t = Unix.gettimeofday() in try let n = Netsys_posix.poll pa 1 d in if n = 0 then raise Timeout; (* Check for error: *) let c = Netsys_posix.get_poll_cell pa 0 in let have_error = Netsys_posix.poll_err_result c.Netsys_posix.poll_act_events in if have_error then ( (* Now find out which error. Unfortunately, a simple Unix.read on the socket seems not to work. *) (* -- interpreting POLL_HUP here is difficult. Generally, POLL_HUP can also be set when the other side sends EOF, i.e. a harmless condition if Netsys_posix.poll_hup_result c.Netsys_posix.poll_act_events then raise(Fatal_error `Broken_pipe); *) let code = Unix.getsockopt_int fd Unix.SO_ERROR in let error = Netsys.unix_error_of_code code in let exn_arg = match error with | Unix.EPIPE | Unix.ECONNRESET -> `Broken_pipe | _ -> `Unix_error error in raise(Fatal_error exn_arg) ) with Unix.Unix_error(Unix.EINTR,_,_) -> dlog (sprintf "FD %Ld: block: EINTR" fdi); if d < 0.0 then self # block d else ( let t' = Unix.gettimeofday() in self # block (max 0.0 (t' -. t)) ) method private case name = test_coverage <- StrSet.add name test_coverage method test_coverage = StrSet.elements test_coverage (* ---- TLS ---- *) method private do_tls_handshake() = try ( match tls with | None -> () | Some t -> Netsys_tls.handshake t; tls_handshake <- false; ) with | Netsys_types.EAGAIN_RD -> dlogr (fun () -> sprintf "FD %Ld: handshake EAGAIN_RD" fdi); override_dir <- Some `R | Netsys_types.EAGAIN_WR -> dlogr (fun () -> sprintf "FD %Ld: handshake EAGAIN_WR" fdi); override_dir <- Some `W | Unix.Unix_error(Unix.EINTR,_,_) -> dlogr (fun () -> sprintf "FD %Ld: handshake EINTR" fdi) | Netsys_types.TLS_error code as e -> dlogr (fun () -> sprintf "FD %Ld: handshake TLS_ERROR %s" fdi (Netexn.to_string e)); self # abort(`TLS_error(code,tls_message code)) method private do_tls_shutdown() = try ( match tls with | None -> () | Some t -> Netsys_tls.shutdown t Unix.SHUTDOWN_SEND ); tls_shutdown_done <- true with | Netsys_types.EAGAIN_RD -> dlogr (fun () -> sprintf "FD %Ld: handshake EAGAIN_RD" fdi); override_dir <- Some `R | Netsys_types.EAGAIN_WR -> dlogr (fun () -> sprintf "FD %Ld: handshake EAGAIN_WR" fdi); override_dir <- Some `W | Unix.Unix_error(Unix.EINTR,_,_) -> dlogr (fun () -> sprintf "FD %Ld: handshake EINTR" fdi) | Netsys_types.TLS_error code as e -> dlogr (fun () -> sprintf "FD %Ld: handshake TLS_ERROR %s" fdi (Netexn.to_string e)); self # abort (`TLS_error(code,tls_message code)) (* ---- Process received data ---- *) method private stop_input_acceptor() = recv_cont <- (fun () -> `Restart); recv_eof <- true method private accept_data () = (* Check whether the socket is ready and we can receive input data. New data * are appended to [recv_buf]. Continue with the next acceptor *) let continue = try if recv_eof then ( if need_linger then ( (* Try to linger in the background... *) dlogr (fun () -> sprintf "FD %Ld: lingering for remaining input" fdi); let n = Unix.recv fd linger_buf 0 (Bytes.length linger_buf) [] in (* or Unix_error *) if n=0 then need_linger <- false (* that's it! *) ); false (* no new data *) ) else ( if self # do_input then ( dlogr (fun () -> sprintf "FD %Ld: recv" fdi); let n = Netbuffer.add_inplace (* or Unix_error *) recv_buf (fun s pos len -> match tls with | None -> Unix.recv fd s pos len [] | Some t -> Netsys_tls.recv t s pos len ) in if n=0 then ( recv_eof <- true; ( match tls with | None -> recv_fd_eof <- true; need_linger <- false | Some t -> recv_fd_eof <- Netsys_tls.at_transport_eof t; tls_shutdown <- true; ); dlog (sprintf "FD %Ld: got EOF (fd_eof=%B)" fdi recv_fd_eof); ) else dlogr (fun () -> sprintf "FD %Ld: got %d bytes" fdi n); true ) else false (* no new data *) ) with | Unix.Unix_error((Unix.EAGAIN | Unix.EWOULDBLOCK), _,_) | Netsys_types.EAGAIN_RD -> dlogr (fun () -> sprintf "FD %Ld: recv EWOULDBLOCK" fdi); false (* socket not ready *) | Unix.Unix_error(Unix.EINTR,_,_) -> dlogr (fun () -> sprintf "FD %Ld: recv EINTR" fdi); false (* got signal *) | Unix.Unix_error(Unix.ECONNRESET, _,_) -> dlogr (fun () -> sprintf "FD %Ld: recv ECONNRESET" fdi); self # abort `Broken_pipe; false | Unix.Unix_error(e, _, _) -> dlogr (fun () -> sprintf "FD %Ld: recv ERROR" fdi); self # abort (`Unix_error e); false | Netsys_types.EAGAIN_WR -> (* Currently impossible *) assert false | Netsys_types.TLS_error code as e -> dlogr (fun () -> sprintf "FD %Ld: rev TLS_ERROR %s" fdi (Netexn.to_string e)); self # abort(`TLS_error(code,tls_message code)); false in if continue then self # accept_loop() method private accept_loop () = let next_cont_opt = recv_cont() in ( match next_cont_opt with | `Continue next_cont -> recv_cont <- next_cont; self # accept_loop() | `Restart -> () (* Stop here for now, restart the last function the next time *) | `Restart_with next_cont -> recv_cont <- next_cont (* Stop here, too, but use [next_cont] the next time *) ) (* The following methods are only called by [accept_loop] when [recv_cont] * is set to one of the methods. They return [`Continue] when another method * should continue to parse the message. They return [`Restart] when they could not * finish parsing, and they want to be called again the next time [cycle] is * invoked. They return [`Restart_with] when they could not finish parsing, * but another method is scheduled for the next time. * * Programming rules: * - When the buffer boundary is hit (often indicated by [Buffer_exceeded]), * check on EOF. Furthermore, delete processed parts from the input buffer. * * - After parts of the buffer have been deleted, [`Restart] must not be returned * (the position would be wrong) *) method private accept_header pos () : cont = (* Check whether the beginning of [recv_buf] contains the full request line and * the full header. If so, process that. If not, still check on premature EOF. *) (* (1) Skip any CRLF sequences at the beginning * (2) Check there is at least one character * (2a) Try to parse the request line * (3) Search the next occurence of CRLF CRLF * CHECK: Maybe use a faster algorithm, e.g. Knuth-Morris-Pratt * (4) Try to parse this block * (5) Create the corresponding response object, and put the token onto the queue * (6) Go on with body parsing * * If we ever hit the bounding of the buffer, raise Buffer_exceeded. This means * we don't have the header block yet. *) #ifdef Testing self # case "accept_header"; #endif waiting_for_next_message <- true; let l = Netbuffer.length recv_buf in let ops = Netstring_tstring.bytes_ops in let s = Netbuffer.unsafe_buffer recv_buf in let block_start = Netmime_string.skip_line_ends_poly ops s pos (l - pos) in (* (1) *) try (* (2) *) if block_start = l || (block_start+1 = l && Bytes.get s block_start = '\013') then ( #ifdef Testing self # case "accept_header/1"; #endif raise Buffer_exceeded; ); (* (2a) *) let reqline_end = try http_find_line_start s block_start (l - block_start) with Buffer_exceeded -> #ifdef Testing self # case "accept_header/reqline_ex"; #endif waiting_for_next_message <- false; if l-block_start > config#config_max_reqline_length then raise (Bad_request `Request_line_too_long); raise Buffer_exceeded in if reqline_end-block_start > config#config_max_reqline_length then raise (Bad_request `Request_line_too_long); waiting_for_next_message <- false; let ((meth,uri),req_version) as request_line = try let (meth, uri, proto_s) = parse_req_line s block_start (reqline_end - block_start) in (* or Not_found *) #ifdef Testing self # case "accept_header/4"; #endif let proto = protocol_of_string proto_s in ( match proto with | `Http((1,_),_) -> () | _ -> raise (Bad_request `Protocol_not_supported) ); ((meth, uri), proto) with | Not_found -> (* This is a bad request. Response should be "Bad Request" *) #ifdef Testing self # case "accept_header/3"; #endif raise (Bad_request `Bad_request_line) in (* (3) *) let config_max_header_length = config # config_max_header_length in let block_end = try http_find_double_line_start s block_start (l - block_start) with Buffer_exceeded -> #ifdef Testing self # case "accept_header/2"; #endif if l-block_start > config_max_header_length then raise (Fatal_error `Message_too_long); raise Buffer_exceeded in if block_end - block_start > config_max_header_length then raise (Fatal_error `Message_too_long); (* (4) *) (* For simplicity, we create an in_obj_channel reading the portion of the * buffer. *) let ch = new Netchannels.input_bytes ~pos:reqline_end ~len:(block_end - reqline_end) s in let str = new Netstream.input_stream ch in (* TODO: This is quite expensive. Create a new netstream class for cheaper access * in this case where we only read from a constant string. *) let req_h = try Netmime_channels.read_mime_header str with Failure _ -> #ifdef Testing self # case "accept_header/5"; #endif raise(Bad_request `Bad_header) in (* TLS: check whether Host header (if set) equals the SNI host name *) ( match self#tls_session_props with | None -> () | Some props -> ( try let host_hdr = match req_h # multiple_field "host" with | [ host_hdr ] -> host_hdr | [] -> raise Not_found | _ -> raise(Bad_request (`Bad_header_field "Host")) in let host_name, _ = try Nethttp.split_host_port host_hdr with _ -> host_hdr, None in if not (Nettls_support.is_endpoint_host host_name props) then raise(Bad_request (`Bad_header_field "Host")) with Not_found -> (* No "Host" header => no checks *) () ) ); (* (5) *) let close = match req_version with | `Http((1,0),_) -> false (* Ignore "Connection" header *) | `Http((1,n),_) when n >= 1 -> (try List.mem "close" (get_connection req_h) with Not_found -> false) | _ -> false in let suppress_body = (meth = "HEAD") in let resp = new http_response_impl ~close ~suppress_body fdi (snd request_line) config#config_announce_server in self # push_recv (`Req_header (request_line, req_h, resp), block_end-block_start); Queue.push resp resp_queue; (* (6) *) `Continue(self # accept_body_start meth req_version req_h resp block_end) with | Buffer_exceeded -> #ifdef Testing self # case "accept_header/exceeded"; #endif if recv_eof then ( if l = block_start then ( (* Regular EOF *) #ifdef Testing self # case "accept_header/regeof"; #endif self # push_recv (`Eof, 0); `Restart_with (fun () -> `Restart) ) else ( #ifdef Testing self # case "accept_header/eof"; #endif raise(Bad_request `Unexpected_eof) ) ) else ( #ifdef Testing self # case "accept_header/restart"; #endif Netbuffer.delete recv_buf 0 block_start; `Restart_with (self # accept_header 0) ) method private accept_body_start meth req_version req_h resp pos () : cont = (* Parse the start of the body at byte [pos] of [recv_buf]. This function * only checks the transfer encoding, and passes over to * [accept_body_identity] or [accept_body_chunked]. *) #ifdef Testing self # case "accept_body_start"; #endif let is_http_1_1 = function | `Http((1,1),_) -> true | _ -> false in try ( match req_version with | `Http((1,n),_) when n>=1 -> let expect_list = try get_expect req_h with Not_found -> [] in let rfc2068_expect = (is_http_1_1 req_version && (meth = "POST" || meth = "PUT")) in let rfc2616_expect = List.exists (fun (tok,_,_) -> tok = "100-continue") expect_list in if rfc2068_expect || rfc2616_expect then ( #ifdef Testing self # case "accept_body_start/100-continue"; #endif self # push_recv (`Req_expect_100_continue, 0); if resp#state = `Inhibited then resp # set_state `Queued (* allow response from now on *) ) | _ -> () ); let enc_list = try get_transfer_encoding req_h with Not_found -> [] in let chunked_encoding = (* The RFC talks about "non-identity transfer encoding"... *) match enc_list with [] | ["identity",_] -> false | _ -> true in if chunked_encoding then ( #ifdef Testing self # case "accept_body_start/chunked"; #endif `Continue (self # accept_body_chunked req_h resp pos) ) else ( let remaining_length = try Some(get_content_length req_h) with Not_found -> None in #ifdef Testing if remaining_length = None then self # case "accept_body_start/empty" else self # case "accept_body_start/identity"; #endif `Continue (self # accept_body_identity req_h resp pos remaining_length) ) with Bad_header_field name -> #ifdef Testing self # case "accept_body_start/bad_header_field"; #endif raise(Bad_request (`Bad_header_field name)) method private accept_body_identity req_h resp pos remaining_length () : cont = (* Accept a body with no transfer encoding. The body continues at byte [pos]. * In [remaining_length], the number of missing bytes is remembered until * the body is complete. [None] means there was neither [Content-length] nor * [Transfer-Encoding], so the body is empty (e.g. for GET). *) #ifdef Testing self # case "accept_body_identity"; #endif let l = Netbuffer.length recv_buf in match remaining_length with | Some rl -> let have_length = Int64.of_int (l - pos) in let take_length = min rl have_length in let n = Int64.to_int take_length in if n > 0 then self # push_recv (`Req_body(Netbuffer.sub_bytes recv_buf pos n, 0, n), n); let rl' = Int64.sub rl take_length in if rl' > 0L then ( #ifdef Testing self # case "accept_body_identity/exceeded"; #endif (* We hit the buffer boundary *) if recv_eof then ( (* This request was prematurely terminated by EOF. Simply drop it. *) #ifdef Testing self # case "accept_body_identity/eof"; #endif raise(Bad_request `Unexpected_eof) ) else ( (* Need to read the remaining part of the request: *) #ifdef Testing self # case "accept_body_identity/restart"; #endif Netbuffer.clear recv_buf; `Restart_with(self # accept_body_identity req_h resp 0 (Some rl')) ) ) else ( (* This was the last part of the message. *) #ifdef Testing self # case "accept_body_identity/last"; #endif self # push_recv (`Req_end, 0); pipeline_len <- pipeline_len + 1; if resp#state = `Inhibited then resp # set_state `Queued; (* allow response from now on *) `Continue(self # accept_header (pos+n)) ) | None -> self # push_recv (`Req_end, 0); pipeline_len <- pipeline_len + 1; if resp#state = `Inhibited then resp # set_state `Queued; (* allow response from now on *) `Continue(self # accept_header pos) method private accept_body_chunked req_h resp pos () : cont = (* Check for a chunk header at byte position [pos]. If complete, parse the number of * bytes the chunk will consist of, and continue with [accept_body_chunked_contents]. *) #ifdef Testing self # case "accept_body_chunked"; #endif let l = Netbuffer.length recv_buf in let s = Netbuffer.unsafe_buffer recv_buf in try let p = http_find_line_start s pos (l - pos) (* or Buffer_exceeded *) in ( try let hex_digits = parse_chunk_header s pos (p-pos) in (* or Not_found *) let chunk_length = try int_of_string("0x" ^ hex_digits) with Failure _ -> #ifdef Testing self # case "accept_body_chunked/ch_large"; #endif raise(Bad_request (`Format_error "Chunk too large")) in (* Continue with chunk data or chunk end *) if chunk_length > 0 then ( #ifdef Testing self # case "accept_body_chunked/go_on"; #endif `Continue(self # accept_body_chunked_contents req_h resp p chunk_length) ) else ( #ifdef Testing self # case "accept_body_chunked/end"; #endif `Continue(self # accept_body_chunked_end req_h resp p) ) with Not_found -> #ifdef Testing self # case "accept_body_chunked/invalid_ch"; #endif raise(Bad_request (`Format_error "Invalid chunk")) ) with | Buffer_exceeded -> #ifdef Testing self # case "accept_body_chunked/exceeded"; #endif if recv_eof then ( #ifdef Testing self # case "accept_body_chunked/eof"; #endif raise(Bad_request `Unexpected_eof); ); if pos > 0 then Netbuffer.delete recv_buf 0 pos; if Netbuffer.length recv_buf > 500 then ( #ifdef Testing self # case "accept_body_chunked/ch_hdr_large"; #endif raise(Bad_request (`Format_error "Chunk header too large")); ); #ifdef Testing self # case "accept_body_chunked/restart"; #endif `Restart_with(self # accept_body_chunked req_h resp 0) method private accept_body_chunked_contents req_h resp pos remaining_length () : cont = (* Read the chunk body at [pos], at most [remaining_length] bytes *) #ifdef Testing self # case "accept_body_chunked_contents"; #endif let l = Netbuffer.length recv_buf in let s = Netbuffer.unsafe_buffer recv_buf in if remaining_length > 0 then ( #ifdef Testing self # case "accept_body_chunked_contents/data"; #endif (* There are still data to read *) let have_length = l - pos in let take_length = min have_length remaining_length in let rem_length' = remaining_length - take_length in if take_length > 0 then self # push_recv (`Req_body(Netbuffer.sub_bytes recv_buf pos take_length, 0, take_length), take_length); if take_length = remaining_length then `Continue (self # accept_body_chunked_contents req_h resp (pos+take_length) 0) else ( #ifdef Testing self # case "accept_body_chunked_contents/exceeded"; #endif (* We hit the buffer boundary. Delete the buffer *) if recv_eof then ( #ifdef Testing self # case "accept_body_chunked_contents/eof"; #endif raise(Bad_request `Unexpected_eof); ); Netbuffer.clear recv_buf; #ifdef Testing self # case "accept_body_chunked_contents/restart"; #endif `Restart_with (self # accept_body_chunked_contents req_h resp 0 rem_length') ) ) else ( #ifdef Testing self # case "accept_body_chunked_contents/end"; #endif (* End of chunk reached. There must a (single) line end at the end of the chunk *) if (l > pos && Bytes.get s pos = '\010') then ( #ifdef Testing self # case "accept_body_chunked_contents/lf"; #endif `Continue(self # accept_body_chunked req_h resp (pos+1)) ) else if (l > pos+1 && Bytes.get s pos = '\013' && Bytes.get s (pos+1) = '\010') then ( #ifdef Testing self # case "accept_body_chunked_contents/crlf"; #endif `Continue(self # accept_body_chunked req_h resp (pos+2)) ) else if l > pos+1 then ( #ifdef Testing self # case "accept_body_chunked_contents/no_eol"; #endif raise (Bad_request (`Format_error "Chunk not followed by line terminator")) ) else ( #ifdef Testing self # case "accept_body_chunked_contents/e_exceeded"; #endif (* We hit the buffer boundary *) if recv_eof then ( #ifdef Testing self # case "accept_body_chunked_contents/e_eof"; #endif raise(Bad_request `Unexpected_eof); ); Netbuffer.delete recv_buf 0 pos; #ifdef Testing self # case "accept_body_chunked_contents/e_restart"; #endif `Restart_with (self # accept_body_chunked_contents req_h resp 0 0) ) ) method private accept_body_chunked_end req_h resp pos () : cont = (* Read the trailer *) #ifdef Testing self # case "accept_body_chunked_end"; #endif let l = Netbuffer.length recv_buf in let s = Netbuffer.unsafe_buffer recv_buf in let config_max_trailer_length = max 2 (config # config_max_trailer_length) in try (* Check if there is a trailer *) if l > pos && Bytes.get s pos = '\010' then ( #ifdef Testing self # case "accept_body_chunked_end/lf"; #endif self # push_recv (`Req_end, 0); pipeline_len <- pipeline_len + 1; if resp#state = `Inhibited then resp # set_state `Queued; (* allow response from now on *) `Continue(self # accept_header (pos+1)) ) else if l > pos+1 && Bytes.get s pos = '\013' && Bytes.get s (pos+1) = '\010' then ( #ifdef Testing self # case "accept_body_chunked_end/crlf"; #endif self # push_recv (`Req_end, 0); pipeline_len <- pipeline_len + 1; if resp#state = `Inhibited then resp # set_state `Queued; (* allow response from now on *) `Continue(self # accept_header (pos+2)) ) else ( #ifdef Testing self # case "accept_body_chunked_end/trailer"; #endif (* Assume there is a trailer. *) let trailer_end = http_find_double_line_start s pos (l-pos) in (* or Buf_exceeded *) #ifdef Testing self # case "accept_body_chunked_end/tr_found"; #endif (* Now we are sure there is a trailer! *) if trailer_end - pos > config_max_trailer_length then ( #ifdef Testing self # case "accept_body_chunked_end/tr_long"; #endif raise(Bad_request (`Format_error "Trailer too long")); ); let ch = new Netchannels.input_bytes ~pos:pos ~len:(trailer_end - pos) s in let str = new Netstream.input_stream ch in let req_tr = try Netmime_channels.read_mime_header str with Failure _ -> #ifdef Testing self # case "accept_body_chunked_end/bad_tr"; #endif raise(Bad_request `Bad_trailer) in self # push_recv (`Req_trailer req_tr, trailer_end-pos); self # push_recv (`Req_end, 0); pipeline_len <- pipeline_len + 1; if resp#state = `Inhibited then resp # set_state `Queued; (* allow response from now on *) `Continue(self # accept_header trailer_end) ) with Buffer_exceeded -> #ifdef Testing self # case "accept_body_chunked_end/exceeded"; #endif if recv_eof then ( #ifdef Testing self # case "accept_body_chunked_end/eof"; #endif raise(Bad_request `Unexpected_eof); ); if l-pos > config_max_trailer_length then ( #ifdef Testing self # case "accept_body_chunked_end/tr_long"; #endif raise(Bad_request (`Format_error "Trailer too long")); ); Netbuffer.delete recv_buf 0 pos; #ifdef Testing self # case "accept_body_chunked_end/restart"; #endif `Restart_with (self # accept_body_chunked_end req_h resp 0) (* ---- Process responses ---- *) method resp_queue_len = Queue.length resp_queue method private transmit_response() = (* Try to transmit the response. Do nothing if the socket is not ready for * transmission. If a fatal error happens, the connection is aborted. *) if not (Queue.is_empty resp_queue) then let resp = Queue.peek resp_queue in try resp # set_state `Active; match resp # front_token with (* or Send_queue_empty, Unix_error *) | `Resp_wire_data (s,pos,len) -> (* Try to write: *) dlogr (fun () -> sprintf "FD %Ld: send" fdi); let n = match tls with | None -> Unix.send fd s pos len [] (* or Unix.error *) | Some t -> Netsys_tls.send t s pos len in dlogr (fun () -> sprintf "FD %Ld: sent %d bytes" fdi n); (* Successful. Advance by [n] *) resp # advance n; | `Resp_end -> dlogr (fun () -> sprintf "FD %Ld: found Resp_end in the queue" fdi); pipeline_len <- pipeline_len - 1; resp # set_state `Processed; (* Check if we have to close the connection: *) if resp # close_connection then ( match tls with | None -> self # shutdown_sending() | Some _ -> tls_shutdown <- true ); (* Continue with the next response, if any, and if possible: *) let next_resp = Queue.take resp_queue in next_resp # set_state `Active; (* ... unless dropped *) (* If the queue is still non-empty, and if the connection is closed, * the remaining, already computed responses, cannot be sent at all. * Drop the responses in this case. *) if resp # close_connection then self # drop_remaining_responses() with | Send_queue_empty -> () (* nothing to do *) | Unix.Unix_error((Unix.EAGAIN | Unix.EWOULDBLOCK),_,_) | Netsys_types.EAGAIN_WR -> () (* socket not ready *) | Unix.Unix_error(Unix.EINTR,_,_) -> () (* Signal happened, try later again *) | Unix.Unix_error((Unix.EPIPE | Unix.ECONNRESET), _,_) -> resp # set_state `Error; ignore(Queue.take resp_queue); self # abort `Broken_pipe | Unix.Unix_error(e, _, _) -> resp # set_state `Error; ignore(Queue.take resp_queue); self # abort (`Unix_error e) | Netsys_types.EAGAIN_RD -> assert false (* not possible here *) | Netsys_types.TLS_error code as e -> dlogr (fun () -> sprintf "FD %Ld: rev TLS_ERROR %s" fdi (Netexn.to_string e)); self # abort (`TLS_error(code,tls_message code)) method private drop_remaining_responses() = (* Set the state to [`Dropped] for all responses in the [resp_queue]: *) Queue.iter (fun resp -> resp # set_state `Dropped) resp_queue; Queue.clear resp_queue (* ---- Queue management ---- *) method receive () = try let (tok, size) = Queue.take recv_queue in recv_queue_byte_size <- recv_queue_byte_size - size; tok with Queue.Empty -> raise Recv_queue_empty method peek_recv () = try fst(Queue.peek recv_queue) with Queue.Empty -> raise Recv_queue_empty method private push_recv ( (token,size) as qelem ) = Queue.push qelem recv_queue; recv_queue_byte_size <- recv_queue_byte_size + size method recv_queue_len = Queue.length recv_queue method recv_queue_byte_size = recv_queue_byte_size (* ---- Socket stuff ---- *) val mutable fd_down = false method shutdown () = (* The shutdown issue is discussed here: * http://ftp.ics.uci.edu/pub/ietf/http/draft-ietf-http-connection-00.txt * * Recommendation: * - Only shutdown for sending * - Keep receiving data for a while ("lingering"). In principle, until the client has * seen the half shutdown, but we do not know when. Apache lingers for 30 seconds. *) dlogr (fun () -> sprintf "FD %Ld: shutdown" fdi); self # stop_input_acceptor(); self # drop_remaining_responses(); tls_shutdown <- true; if tls = None then self # shutdown_sending() method private shutdown_sending() = dlogr (fun () -> sprintf "FD %Ld: shutdown_sending" fdi); if not fd_down then ( try Unix.shutdown fd Unix.SHUTDOWN_SEND; with Unix.Unix_error(Unix.ENOTCONN,_,_) -> need_linger <- false (* the peer has already shut down in the meantime *) ); fd_down <- true method waiting_for_next_message = waiting_for_next_message method input_timeout_class : [ `Normal | `Next_message | `None ] = (* Do we have an active response object? In this case, it might be the case the * connection is output-driven, and no timeout applies: *) try let first = Queue.peek resp_queue in (* or Queue.Empty *) if first#state <> `Active then raise Queue.Empty; (* If the response object is in the bidirectional phase, the normal input * timeout applies nevertheless. *) if first#bidirectional_phase then `Normal else `None with Queue.Empty -> if waiting_for_next_message then `Next_message else `Normal method timeout () = if waiting_for_next_message then ( (* Indicate a "soft" timeout. Processing is nevertheless similar to [abort]: *) dlogr (fun () -> sprintf "FD %Ld: soft timeout" fdi); need_linger <- false; self # shutdown(); self # push_recv (`Timeout, 0); self # push_recv (`Eof, 0); ) else self # abort `Timeout (* "hard" timeout *) method abort (err : fatal_error) = dlogr (fun () -> sprintf "FD %Ld: abort %s" fdi (string_of_fatal_error err)); need_linger <- false; self # shutdown(); tls_shutdown_done <- true; (* don't do the TLS shutdown protocol *) let err' = if err=`Broken_pipe && config#config_suppress_broken_pipe then `Broken_pipe_ignore else err in self # push_recv (`Fatal_error err', 0); self # push_recv (`Eof, 0) method fd = fd method config = (config :> http_protocol_config) method pipeline_len = pipeline_len method do_input = match override_dir with | None -> not recv_fd_eof && (* CHECK: can we get further alerts after TLS END ? *) (pipeline_len <= config#config_limit_pipeline_length) && (recv_queue_byte_size <= config#config_limit_pipeline_size) | Some `R -> true | Some `W -> false method do_output = match override_dir with | None -> self # resp_queue_filled | Some `R -> false | Some `W -> true method resp_queue_filled = ( not (Queue.is_empty resp_queue) && not ((Queue.peek resp_queue) # send_queue_empty) ) || ( tls_shutdown && not tls_shutdown_done ) method need_linger = (* TLS: never need lingering close, as TLS alerts indicate the end of the data stream *) tls = None && need_linger method tls_session_props = if not tls_handshake && tls_session_props = None then ( match tls with | Some t -> tls_session_props <- Some (Nettls_support.get_tls_session_props t) | None -> () ); tls_session_props end class lingering_close ?(preclose = fun () -> ()) fd = let fd_style = Netsys.get_fd_style fd in object(self) val start_time = Unix.gettimeofday() val timeout = 60.0 val junk_buffer = Bytes.create 256 val mutable lingering = true method cycle ?(block=false) () = try if block then ( let now = Unix.gettimeofday() in let sel_time = max (timeout -. (now -. start_time)) 0.0 in if sel_time = 0.0 then raise Not_found; ignore(Netsys.wait_until_readable fd_style fd sel_time); () ); let n = Unix.recv fd junk_buffer 0 (Bytes.length junk_buffer) [] in if n = 0 then ( lingering <- false; preclose(); Unix.close fd ) with | Unix.Unix_error((Unix.EAGAIN | Unix.EWOULDBLOCK), _,_)-> () (* socket not ready *) | Unix.Unix_error(Unix.EINTR,_,_) -> () (* got signal *) | Unix.Unix_error(_, _,_) | Not_found -> (* Any other error means we are done! *) lingering <- false; preclose(); Unix.close fd method lingering = lingering method fd = fd end let default_http_protocol_config = ( object method config_max_reqline_length = 32768 method config_max_header_length = 65536 method config_max_trailer_length = 32768 method config_limit_pipeline_length = 5 method config_limit_pipeline_size = 65536 method config_announce_server = `Ocamlnet method config_suppress_broken_pipe = false method config_tls = None end ) let override v opt = match opt with | None -> v | Some x -> x class modify_http_protocol_config ?config_max_reqline_length ?config_max_header_length ?config_max_trailer_length ?config_limit_pipeline_length ?config_limit_pipeline_size ?config_announce_server ?config_suppress_broken_pipe ?config_tls (config : http_protocol_config) : http_protocol_config = let config_max_reqline_length = override config#config_max_reqline_length config_max_reqline_length in let config_max_header_length = override config#config_max_header_length config_max_header_length in let config_max_trailer_length = override config#config_max_trailer_length config_max_trailer_length in let config_limit_pipeline_length = override config#config_limit_pipeline_length config_limit_pipeline_length in let config_limit_pipeline_size = override config#config_limit_pipeline_size config_limit_pipeline_size in let config_announce_server = override config#config_announce_server config_announce_server in let config_suppress_broken_pipe = override config#config_suppress_broken_pipe config_suppress_broken_pipe in let config_tls = override config#config_tls config_tls in object method config_max_reqline_length = config_max_reqline_length method config_max_header_length = config_max_header_length method config_max_trailer_length = config_max_trailer_length method config_limit_pipeline_length = config_limit_pipeline_length method config_limit_pipeline_size = config_limit_pipeline_size method config_announce_server = config_announce_server method config_suppress_broken_pipe = config_suppress_broken_pipe method config_tls = config_tls end ocamlnet-4.1.2/src/nethttpd/LICENSE0000644000175000017500000004337712731530350015407 0ustar gerdgerdThe library Nethttpd is distributed under the terms of the GNU General Public License (GPL). ====================================================================== GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ocamlnet-4.1.2/src/nethttpd/nethttpd_services.mli0000644000175000017500000003125312731530350020630 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Nethttpd; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) (** {1 Service Providers for HTTP daemon} * * This module defines the basic service providers that handle requests and * generate responses. The service providers can be used with both the * reactive and the event-based daemon encapsulations. *) (* Predefined service providers: *) open Nethttpd_types type host = { server_pref_name : string option; (** The preferred name of the host. This can be a DNS name or an IP address. *) server_pref_port : int option; (** The preferred port of the host *) server_names : (string * int) list; (** Names and ports that match this host definition, for * name-based virtual hosting. The name ["*"] matches any name, and the port * 0 matches any port. *) server_addresses : (Unix.inet_addr * int) list; (** IP addresses and ports that also match this host definition, for * IP-based virtual hosting. The address [Unix.inet_addr_any] matches any * address, and the port 0 matches any port. *) } (** For name- and IP-based virtual hosting this record describes the individual * host. An incoming request matches this host if: * - The [Host] header is mentioned in [server_names], or if * - The request has been accepted on the port contained in [server_addresses] * * If [server_pref_name] is set, the name of the host is set to this string for * further processing (esp. [cgi_server_name]). If not set, the name of the * host is set to the name corresponding to the matching entry of [server_names] * or [server_addresses], or if this does not succeed, to the real IP address. * * If [server_pref_port] is set, the port of the host is set to this string for * further processing (esp. [cgi_server_port]). If not set, the port of the * host is set to the port corresponding to the matching entry of [server_names] * or [server_addresses], or if this does not succeed, to the real port number. *) type 'a host_distributor = ( host * 'a http_service ) list (** Describes virtual hosting by pairs [(host,service)]: If [host] matches the * incoming request, the corresponding [service] is performed to generate the * response. *) val host_distributor : 'a host_distributor -> [> `Host_distributor of 'a host_distributor ] http_service (** Configures virtual hosting *) val default_host : ?pref_name:string -> ?pref_port:int -> unit -> host (** Creates a [host] record that matches any request. [pref_name] and [pref_port] * can be used to specify preferred names. *) val options_service : unit -> [> `Options_service ] http_service (** This service responds to "OPTIONS *" requests, and nothing else *) type 'a uri_distributor = ( string * 'a http_service ) list (** Describes that services are bound to URI prefixes. The strings are URI paths * (without URI escaping). * For an incoming request URI, the longest matching prefix is selected, and * the corresponding service is carried out. * * If the URI path in the list ends with a slash, it can only be selected if the * incoming request URI also includes the slash. * * If the URI path in the list does not end with a slash, it can only be selected * if the incoming request URI is exactly identical, or continues the path with * a slash. *) val uri_distributor : 'a uri_distributor -> [> `Uri_distributor of 'a uri_distributor ] http_service (** Configures URI distribution. The incoming request URI is normalized before * being matched, and the request is rewritten to the normalized URI. * * Normalization includes: * - Removal of [.] path components * - Resolution of [..] path components * * If the path starts with [..] after normalization, the request is rejected. *) type 'a linear_distributor = ( (extended_environment -> bool) * 'a http_service ) list (** Services are selected by calling the selector function. The first service * for which the function returns [true] is selected. *) val linear_distributor : 'a linear_distributor -> [> `Linear_distributor of 'a linear_distributor ] http_service (** Configures linear distribution *) type method_filter = [ `Limit of string list | `Limit_except of string list ] (** The request is only accepted if listed (for [`Limit]), or if not listed * (for [`Limit_except]). *) type 'a method_distributor = ( method_filter * 'a http_service ) list (** The first service is selected for which the method filter accepts the request *) val method_distributor : 'a method_distributor -> [> `Method_distributor of 'a method_distributor ] http_service (** Configures method distribution *) type file_option = [ `Enable_gzip | `Enable_cooked_compression | `Override_compression_suffixes of (string * string) list | `Enable_index_file of string list | `Enable_listings of extended_environment -> Netcgi.cgi_activation -> file_service -> unit ] (** Add-on features for file services: * - [`Enable_gzip]: Deprecated. Same as [`Enable_cooked_compression]. * - [`Enable_cooked_compression]: Modifies the way compressed files * are handled. Normally it is required that one accesses the compressed * file (with suffix such as "gz") directly to get it in compressed form. * If this option is enabled, though, the server also compresses * the base file (without suffix such as "gz"), but only if the * base file is accompanied by a compressed version (with suffix). * E.g. if there is "foo" and "foo.gz", this enables that the accesses * to "foo" can make use of compression. * - [`Enable_index_file]: If enabled, accesses to directories are redirected * to index files. The possible file names are given in the string list. * E.g. [`Enable_index_file ["index.html"; "index.htm"]]. It is redirected to * these files, so these can be handled by different services if neccessary. * - [`Enable_listings]: If enabled, directory listings are generated by calling * the argument function. The [PATH_TRANSLATED] property of the environment * contains the absolute name of the directory to list. The [PATH_INFO] property * is the corresponding URI path. [SCRIPT_NAME] is meaningless. * - [`Override_compression_suffixes l]: Tags the file suffixes in * [l] as compression schemes. A pair [(suffix,ce)] sets that the * [suffix] means the content encoding [ce]. Knowing this is important * for determining the media type of the file. *) and file_service = { file_docroot : string; (** The document root for this file service *) file_uri : string; (** The URI prefix corresponding to the document root. Escapes are not allowed *) file_suffix_types : (string * string) list; (** Maps the file suffixes (after the dot) to media types *) file_default_type : string; (** The media type to use if suffix mapping fails *) file_options : file_option list; (** Further options for files *) } (** Describes a file service *) val file_service : file_service -> [> `File_service of file_service ] http_service (** Configures a file service *) val file_translator : file_service -> string -> string (** Translates an URI path to a file name. Raises [Not_found] if not possible. It is not checked whether the resulting file exists. This function removes a trailing slash of the translated path, if any, and if resulting from appending the path info component. Trailing slashes must not be used to deduce that directories are accessed. *) val simple_listing : ?hide:string list -> extended_environment -> Netcgi.cgi_activation -> file_service -> unit (** Simple listing generator for [`Enable_listings] * * [hide]: An optional list of Str regular expressions. File names matching one * of the regexps are hidden in the listing. Defaults to hiding files starting with * a dot, and files ending in a tilde character. (Changed in Ocamlnet-3.3: * [hide] uses now Str regexps, and no longer PCRE regexps.) *) type std_activation_options = { stdactv_processing : Netcgi.arg_store option; stdactv_operating_type : Netcgi.output_type option; } (** These are options for [`Std_activation]. For explanations, see the [Netcgi] * module. *) type std_activation = [ `Std_activation of std_activation_options | `Std_activation_unbuffered (* Shortcut for common case *) | `Std_activation_buffered (* Shortcut for common case *) | `Std_activation_tempfile (* Shortcut for common case *) ] (** The way the [Netcgi_types.cgi_activation] object is created. For typical * usage, just take: * - [`Std_activation_unbuffered]: Creates a [Netcgi.std_activation] without * output buffer (type [`Direct ""]) and memory-based argument processing * - [`Std_activation_buffered]: Creates a [Netcgi.std_activation] * with a transactions buffer in memory, and memory-based argument processing * - [`Std_activation_tempfile]: Creates a [Netcgi.std_activation] * with a file as transactions buffer, and memory-based argument processing * * The following option is provided for detailed control: * - [`Std_activation opt]: Creates a [Netcgi.std_activation] with the given * options *) type 'a dynamic_service = { dyn_handler : extended_environment -> 'a -> unit; (** A dynamic service is carried out by calling this function with the environment * and the CGI activation. The function can use all CGI features, including * setting the [Location] handler to redirect responses. *) dyn_activation : extended_environment -> 'a; (** The way the [Netcgi_types.cgi_activation] is created. Look below * for [std_activation]. *) dyn_uri : string option; (** The URI prefix corresponding to this service. This is only used to * compute [cgi_path]. Leave it to [None] if not needed. *) dyn_translator : string -> string; (** The function computing [cgi_path_translated] from [cgi_path]. Set it * to [(fun _ -> "")] if not needed. *) dyn_accept_all_conditionals : bool; (** Whether to pass requests with [If-Match] and [If-Unmodified-Since] headers * to this service. If set to [true], the service can optimize the caching * behaviour by interpreting these fields. It is even obliged to interpret * them. If [false], requests containing these headers are rejected. * * The other condition fields [If-None-Match], [If-Modified-Since], and * [If-Ranges] are not affected by this option. One can safely ignore these * headers. *) } constraint 'a = # Netcgi.cgi_activation ;; val std_activation : std_activation -> extended_environment -> Netcgi.cgi_activation (** Create the function for [dyn_activation] from a [std_activation] tag. * Example: * [ let dyn_actv = std_activation `Std_activation_unbuffered ] *) val dynamic_service : 'a dynamic_service -> [> `Dynamic_service of 'a dynamic_service ] http_service (** Configures the dynamic service. *) type ac_by_host_rule = [ `Allow of string list | `Deny of string list ] (** Access control by host: * - [`Allow]: Only the listed hosts are allowed; all other are denied * - [`Deny]: The listed hosts are denied; all other are allowed *) type 'a ac_by_host = ac_by_host_rule * 'a http_service (** The service is protected by the access control rule *) val ac_by_host : 'a ac_by_host -> [> `Ac_by_host of 'a ac_by_host ] http_service (** Configures host-based access control *) val read_media_types_file : string -> (string * string) list (** Reads a text file with two columns where the left column is the * media type and the right column the corresponding suffix. * Returns the contents as pairs [ (suffix, type) ]. *) module Debug : sig val enable : bool ref end ocamlnet-4.1.2/src/nethttpd/nethttpd_services.ml0000644000175000017500000013203612731530350020460 0ustar gerdgerd(* $Id$ * *) (* * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann * * This file is part of Nethttpd. * * Nethttpd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nethttpd 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with WDialog; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) module Debug = struct let enable = ref false end let dlog = Netlog.Debug.mk_dlog "Nethttpd_services" Debug.enable let dlogr = Netlog.Debug.mk_dlogr "Nethttpd_services" Debug.enable let () = Netlog.Debug.register_module "Nethttpd_services" Debug.enable open Nethttp open Nethttp.Header open Nethttpd_types open Printf type host = { server_pref_name : string option; server_pref_port : int option; server_names : (string * int) list; server_addresses : (Unix.inet_addr * int) list; } type 'a host_distributor = ( host * 'a http_service ) list (* Note: For all objects below we cannot define classes (i.e. "class xy = ..."), * but we _must_ fall back to ad-hoc objects (i.e. "let xy = object ... end"). * The reason is a subtle typing difference: classes must not have open types, * but ad-hoc objects can have them. Here, the method [def_term] is usually * something like [> `Foo], i.e. an _open_ variant. This is not possible with * classes. We need open variants, however, otherwise one could not put * several service objects into the same list, i.e. [ service1; service2 ]. * * Ad-hoc objects are available since O'Caml 3.08. This means this module cannot * be type-checked in any earlier version of O'Caml, i.e. this is * "bleeding-edge typing". *) let host_distributor (spec : 'a host_distributor) = object(self) method name = "host_distributor" method def_term = `Host_distributor spec method print fmt = Format.fprintf fmt "@[host_distributor("; List.iter (fun (host,service) -> Format.fprintf fmt "@,@[host("; ( match host.server_pref_name with | Some n -> Format.fprintf fmt "@ pref_name(%s)" n | None -> () ); ( match host.server_pref_port with | Some p -> Format.fprintf fmt "@ pref_port(%d)" p | None -> () ); List.iter (fun (n,p) -> Format.fprintf fmt "@ name(%s:%d)" n p ) host.server_names; List.iter (fun (addr,p) -> let n = Unix.string_of_inet_addr addr in Format.fprintf fmt "@ addr(%s:%d)" n p ) host.server_addresses; Format.fprintf fmt "@ "; service # print fmt; Format.fprintf fmt "@]@,)"; ) spec; Format.fprintf fmt "@]@,)" method process_header (env : extended_environment) = (* For simplicity, just iterate over spec and take the first matching host * definition. *) let def_matches host = (* Check server_names first, then server_addresses. Returns (name,port) on * success, Not_found otherwise *) try let req_name = env # input_header_field "Host" in let (req_host, req_port_opt) = split_host_port req_name in let req_host = String.lowercase req_host in let req_port = match req_port_opt with Some p -> p | None -> 80 in (* CHECK *) List.find (fun (n,p) -> (n = "*" || String.lowercase n = req_host) && (p = 0 || p = req_port)) host.server_names with Not_found -> ( let (req_sockaddr, req_sockport) = match env # server_socket_addr with | Unix.ADDR_INET(inet,port) -> (inet,port) | _ -> failwith "Not an Internet socket" in if List.exists (fun (n,p) -> (n = Unix.inet_addr_any || n = req_sockaddr) && (p = 0 || p = req_sockport)) host.server_addresses then (Unix.string_of_inet_addr req_sockaddr, req_sockport) else raise Not_found ) in let rec find_host hosts = match hosts with | (host, service) :: hosts' -> ( try (host, service, def_matches host) with Not_found -> find_host hosts' ) | [] -> raise Not_found in try let (m_host, m_service, (m_name, m_port)) = find_host spec in (* or Not_found *) (* Finally, we have found the host [m_host] served by [m_service]. * We must now set the virtual names in [env]. *) let any_name = Unix.string_of_inet_addr Unix.inet_addr_any in let (sock_addr, sock_port) = match env # server_socket_addr with | Unix.ADDR_INET(inet,port) -> (inet,port) | _ -> failwith "Not an Internet socket" in let new_server_name = match m_host.server_pref_name with | Some n -> n | None -> (* No preferred name: Use [m_name] if possible *) if m_name = "*" || m_name = any_name then Unix.string_of_inet_addr sock_addr (* fallback *) else m_name in let new_server_port = match m_host.server_pref_port with | Some p -> string_of_int p | None -> (* No preferred port: Use [m_port] if possible *) if m_port = 0 then string_of_int sock_port (* fallback *) else string_of_int m_port in let new_properties = update_alist [ "SERVER_NAME", new_server_name; "SERVER_PORT", new_server_port ] env#cgi_properties in let new_env = new redirected_environment ~properties:new_properties ~in_channel:(env # input_channel) env in (* Pass control over to the corresponding service: *) m_service # process_header new_env with Not_found -> `Std_response(`Not_found, None, (Some "Nethttpd: no matching host definition")) end let default_host ?pref_name ?pref_port () = { server_pref_name = pref_name; server_pref_port = pref_port; server_names = []; server_addresses = [ Unix.inet_addr_any, 0 ] } let options_service () = object(self) method name = "options_service" method def_term = `Options_service method print fmt = Format.fprintf fmt "options_service()" method process_header env = if env # cgi_request_method = "OPTIONS" && env # cgi_request_uri = "*" then `Static(`Ok, None, "") else `Std_response(`Not_found, None, (Some "Nethttpd: This OPTIONS service works only for *")) end type 'a uri_distributor = ( string * 'a http_service ) list module StrMap = Map.Make(String) type 'leaf uri_tree = 'leaf uri_node StrMap.t and 'leaf uri_node = { leaf : 'leaf option; tree : 'leaf uri_tree; } let rec make_uri_tree ( spec : 'a uri_distributor ) : 'a http_service uri_tree = match spec with | (uri, service) :: spec' -> let uri_list = Neturl.norm_path (Neturl.split_path uri) in let tree' = make_uri_tree spec' in if uri_list <> [] then merged_uri_tree uri_list tree' service else tree' (* i.e. uri = "" is silently ignored *) | [] -> StrMap.empty and merged_uri_tree l t service = (* merge l into t *) match l with | [x] -> let t_node_at_x = try StrMap.find x t with Not_found -> { leaf = None; tree = StrMap.empty } in let new_t_node_at_x = { leaf = Some service; tree = t_node_at_x.tree; } in StrMap.add x new_t_node_at_x t (* replaces old binding, if any *) | x :: l' -> let t_node_at_x = try StrMap.find x t with Not_found -> { leaf = None; tree = StrMap.empty } in let new_t_node_at_x = { leaf = t_node_at_x.leaf; tree = merged_uri_tree l' t_node_at_x.tree service; } in StrMap.add x new_t_node_at_x t (* replaces old binding, if any *) | [] -> assert false let rec find_uri_service uri_list uri_tree = (* Finds the prefix of [uri_list] in [uri_tree] serving the request *) match uri_list with | [] -> raise Not_found | directory :: uri_list' -> let node = try (* Search ..../: *) StrMap.find directory uri_tree (* or Not_found *) with Not_found -> (* Search ..../: (i.e. trailing slash) *) let node' = StrMap.find "" uri_tree in if not (StrMap.is_empty node'.tree) then raise Not_found; node' in ( match node.leaf with | Some service -> (* Try to find a more specific service *) ( try find_uri_service uri_list' node.tree with Not_found -> service ) | None -> find_uri_service uri_list' node.tree ) exception Bad_uri_escaping let uri_distributor ( spec : 'a uri_distributor ) = let uri_tree = make_uri_tree spec in object(self) method name = "uri_distributor" method def_term = `Uri_distributor spec method print fmt = Format.fprintf fmt "@[uri_distributor("; List.iter (fun (uri,service) -> Format.fprintf fmt "@ @[uri(%s =>@ " uri; service # print fmt; Format.fprintf fmt "@]@ )"; ) spec; Format.fprintf fmt "@]@ )" method process_header env = (* Do path normalization, and if there is something to do, redirect: *) try let req_path_esc = env # cgi_script_name in let req_path = try uripath_decode req_path_esc with Failure _ -> raise Bad_uri_escaping in let req_uri_list = Neturl.split_path req_path in let req_uri_list_norm = Neturl.norm_path req_uri_list in let req_uri_norm = Neturl.join_path req_uri_list_norm in (* Safety checks *) ( match req_uri_list_norm with | [] -> (* i.e. "." - but empty URIs are generally forbidden *) `Std_response(`Not_found, None, (Some "Nethttpd: Non-absolute URI")) | [ ".." ] -> (* i.e. URI begins with ".." *) `Std_response(`Not_found, None, (Some "Nethttpd: Non-absolute URI")) | [ ""; ".." ] -> (* i.e. URI begins with "/.." *) `Std_response(`Not_found, None, (Some "Nethttpd: URI begins with /..")) | _ -> (* Everything else is acceptable. Now perform the redirection if * the URI changed by normalization: * CHECK: Maybe it is better not to redirect, but to derive a new * environment. *) if req_uri_norm <> req_path then ( let qs = env#cgi_query_string in let qm_qs = if qs = "" then "" else "?" ^ qs in let req_uri_esc = uripath_encode req_uri_norm ^ qm_qs in raise(Redirect_request(req_uri_esc, env # input_header))); (* Search the URI to match: *) ( match ( try Some(find_uri_service req_uri_list_norm uri_tree) with Not_found -> None ) with | Some service -> service # process_header env | None -> `Std_response(`Not_found, None, (Some "Nethttpd: No service bound to URI")) ) ) with | Bad_uri_escaping -> `Std_response(`Not_found, None, (Some "Nethttpd: Bad URI escape sequences")) end type 'a linear_distributor = ( (extended_environment -> bool) * 'a http_service ) list let linear_distributor ( spec : 'a linear_distributor ) = object(self) method name = "linear_distributor" method def_term = `Linear_distributor spec method print fmt = Format.fprintf fmt "@[linear_distributor("; List.iter (fun (_,service) -> Format.fprintf fmt "@ @[conditional(??? =>@ "; service # print fmt; Format.fprintf fmt "@]@ )"; ) spec; Format.fprintf fmt "@]@ )" method process_header env = match ( try Some (List.find (fun (cond, service) -> cond env) spec) with Not_found -> None ) with | Some(_, service) -> service # process_header env | None -> `Std_response(`Not_found, None, (Some "Nethttpd: No service matches in linear distribution")) end type method_filter = [ `Limit of string list | `Limit_except of string list ] type 'a method_distributor = ( method_filter * 'a http_service ) list let method_distributor ( spec : 'a method_distributor ) = object(self) method name = "method_distributor" method def_term = `Method_distributor spec method print fmt = Format.fprintf fmt "@[method_distributor("; List.iter (fun (rule,service) -> Format.fprintf fmt "@ @[method(%s =>@ " (match rule with | `Limit l -> "+" ^ String.concat "," l | `Limit_except l -> "-" ^ String.concat "," l); service # print fmt; Format.fprintf fmt "@]@ )"; ) spec; Format.fprintf fmt "@]@ )" method process_header env = let rule_matches = function | `Limit l -> let req_method = env # cgi_request_method in List.mem req_method l | `Limit_except l -> let req_method = env # cgi_request_method in not(List.mem req_method l) in match ( try Some (List.find (fun (rule, _) -> rule_matches rule) spec) with Not_found -> None ) with | Some(_, service) -> service # process_header env | None -> `Std_response(`Not_found, None, (Some "Nethttpd: Method not bound")) end type std_activation_options = { stdactv_processing : Netcgi.arg_store option; stdactv_operating_type : Netcgi.output_type option; } type std_activation = [ `Std_activation of std_activation_options | `Std_activation_unbuffered | `Std_activation_buffered | `Std_activation_tempfile ] type 'a dynamic_service = { dyn_handler : extended_environment -> 'a -> unit; dyn_activation : extended_environment -> 'a; dyn_uri : string option; dyn_translator : string -> string; dyn_accept_all_conditionals : bool; } constraint 'a = # Netcgi.cgi_activation let rec strip_prefix ~prefix l = match prefix, l with | [], l -> l | (p :: prefix'), (x :: l') -> if p = x then strip_prefix ~prefix:prefix' l' else raise Not_found | _, [] -> raise Not_found let std_activation tag = match tag with | `Std_activation opts -> (fun env -> let out_type = match opts.stdactv_operating_type with | None -> `Direct "" | Some p -> p in let arg_store = match opts.stdactv_processing with | None -> (fun _ _ _ -> `Automatic) | Some f -> f in Netcgi_common.cgi_with_args (new Netcgi_common.cgi) (env :> Netcgi.cgi_environment) out_type env#input_channel arg_store ) | `Std_activation_unbuffered -> (fun env -> Netcgi_common.cgi_with_args (new Netcgi_common.cgi) (env :> Netcgi.cgi_environment) (`Direct "") env#input_channel (fun _ _ _ -> `Automatic) ) | `Std_activation_buffered -> (fun env -> Netcgi_common.cgi_with_args (new Netcgi_common.cgi) (env :> Netcgi.cgi_environment) Netcgi.buffered_transactional_outtype env#input_channel (fun _ _ _ -> `Automatic) ) | `Std_activation_tempfile -> (fun env -> Netcgi_common.cgi_with_args (new Netcgi_common.cgi) (env :> Netcgi.cgi_environment) Netcgi.tempfile_transactional_outtype env#input_channel (fun _ _ _ -> `Automatic) ) class dynamic_out_channel enabled out_ch : Netchannels.out_obj_channel = (* if enabled is set to false, output is suppressed *) object(self) method output s p len = if !enabled then out_ch # output s p len else len method flush() = if !enabled then out_ch # flush() method close_out() = if !enabled then out_ch # close_out() method pos_out = out_ch # pos_out method really_output s p len = if !enabled then out_ch # really_output s p len method really_output_string s p len = if !enabled then out_ch # really_output_string s p len method output_char c = if !enabled then out_ch # output_char c method output_string s = if !enabled then out_ch # output_string s method output_byte b = if !enabled then out_ch # output_byte b method output_bytes b = if !enabled then out_ch # output_bytes b method output_buffer b = if !enabled then out_ch # output_buffer b method output_channel ?len ch = if !enabled then out_ch # output_channel ?len ch end class dynamic_env_wrapper (env:extended_environment) properties = let in_channel = env#input_channel in let out_enabled = ref true in let out_channel = new dynamic_out_channel out_enabled env#output_ch in object(self) inherit redirected_environment ~in_channel ~properties env as super method send_output_header() = (* Check for CGI-type redirection. In this case we have to suppress any output. (see also below) *) ( try let loc = self # output_header_field "Location" in (* or Not_found *) if loc = "" || loc.[0] <> '/' then raise Not_found; dlogr (fun () -> sprintf "env-%d dynamic_env_wrapper suppressing output" (Oo.id env)); out_enabled := false; (* suppress output *) with Not_found -> super # send_output_header() ) method output_ch = out_channel method out_channel = out_channel end let dynamic_service_impl spec = object(self) method name = "dynamic_service" method def_term = `Dynamic_service spec method print fmt = Format.fprintf fmt "@[dynamic_service("; ( match spec.dyn_uri with | None -> () | Some uri -> Format.fprintf fmt "@ uri(%s)" uri ); Format.fprintf fmt "@ accept_all_conditionals(%b)" spec.dyn_accept_all_conditionals; Format.fprintf fmt "@]@ )" method process_header (env : extended_environment) = dlogr (fun () -> sprintf "env-%d process_header dynamic_service" (Oo.id env)); try let req_path_esc = env#cgi_script_name in let _req_path = try uripath_decode req_path_esc with Failure _ -> raise Not_found in let req_method = env # cgi_request_method in let allowed = List.map Netcgi_common.string_of_http_method (env # config).Netcgi.permitted_http_methods in if not (List.mem req_method allowed) then ( let h = new Netmime.basic_mime_header [] in set_allow h allowed; raise (Standard_response(`Method_not_allowed,Some h,(Some "Nethttpd: Method not allowed for dynamic service"))); ); if not spec.dyn_accept_all_conditionals then ( if env # multiple_input_header_field "If-match" <> [] then raise(Standard_response(`Precondition_failed,None,None)); if env # multiple_input_header_field "If-unmodified-since" <> [] then raise(Standard_response(`Precondition_failed,None,None)); ); dlogr (fun () -> sprintf "env-%d process_header dynamic_service accepts %s %s" (Oo.id env) req_method req_path_esc); (`Accept_body(self :> http_service_receiver) : http_service_reaction) with | Not_found -> `Std_response(`Not_found, None,(Some "Nethttpd: Cannot decode request")) | Standard_response(status,hdr_opt,errmsg_opt) -> `Std_response(status,hdr_opt,errmsg_opt) val response_param = None method process_body env = dlogr (fun () -> sprintf "env-%d process_body dynamic_service" (Oo.id env)); (* Set PATH_INFO and PATH_TRANSLATED: *) let props = match spec.dyn_uri with | Some dyn_uri -> let req_path_esc = env#cgi_script_name in let req_path = uripath_decode req_path_esc in let req_path_list = Neturl.split_path req_path in let dyn_path_list = Neturl.split_path dyn_uri in let path_list = try "" :: (strip_prefix ~prefix:dyn_path_list req_path_list) with Not_found -> [] in let path = Neturl.join_path path_list in let path_esc = uripath_encode path in let path_translated = spec.dyn_translator path in let properties = update_alist [ "PATH_INFO", path_esc; "PATH_TRANSLATED", path_translated; "SCRIPT_NAME", uripath_encode dyn_uri ] env#cgi_properties in properties | None -> env#cgi_properties in let fenv = new dynamic_env_wrapper env props in let cgi = spec.dyn_activation fenv in dlogr (fun () -> sprintf "env-%d process_body dynamic_service cgi=%d fixed_env=%d" (Oo.id env) (Oo.id cgi) (Oo.id fenv)); (* We cannot set here response_param directly because this object is globally used by all incoming requests *) let self' = {< response_param = Some (cgi,fenv) >} in (self' :> http_service_generator) method generate_response env = dlogr (fun () -> sprintf "env-%d generate_response dynamic_service" (Oo.id env)); match response_param with | Some (cgi,fenv) -> dlogr (fun () -> sprintf "env-%d generate_response dynamic_service calling handler with cgi=%d fixed_env=%d" (Oo.id env) (Oo.id cgi) (Oo.id fenv)); spec.dyn_handler fenv cgi; dlogr (fun () -> sprintf "env-%d generate_response dynamic_service \ back from handler" (Oo.id env)); (* Check for CGI-type redirection. In this case we have to do the actual redirection (see also dynamic_env_wrapper) *) ( try let loc = fenv # output_header_field "Location" in (* or Not_found *) if loc = "" || loc.[0] <> '/' then raise Not_found; fenv # output_header # set_fields []; (* Reset output *) raise(Redirect_response(loc, fenv # input_header)) with Not_found -> () ) | _ -> failwith "Activation object is missing" end let dynamic_service spec = (dynamic_service_impl spec :> 'a http_service) type file_option = [ `Enable_gzip | `Enable_cooked_compression | `Override_compression_suffixes of (string * string) list | `Enable_index_file of string list | `Enable_listings of extended_environment -> Netcgi.cgi_activation -> file_service -> unit ] and file_service = { file_docroot : string; file_uri : string; file_suffix_types : (string * string) list; file_default_type : string; file_options : file_option list; } let file_translator spec uri = let rem_slash s = let s1 = if s<>"" && s.[0] = '/' then String.sub s 1 (String.length s - 1) else s in let s2 = if s1 <> "" && s1.[String.length s1-1] = '/' then String.sub s1 0 (String.length s1-1) else s1 in s2 in let concat p1 p2 = if p2="" then p1 else Filename.concat p1 p2 in let rec translate pat_l l = match (pat_l, l) with | ([], [""]) -> spec.file_docroot | ([], path) -> concat spec.file_docroot (rem_slash(Neturl.join_path path)) | ([""], path) -> concat spec.file_docroot (rem_slash(Neturl.join_path path)) | (pat_dir :: pat_l', dir :: l') when pat_dir = dir -> translate pat_l' l' | _ -> raise Not_found in let uri_list = Neturl.norm_path (Neturl.split_path uri) in match uri_list with | [] -> (* i.e. "." - but empty URIs are generally forbidden *) raise Not_found | [ ".." ] -> (* i.e. URI begins with ".." *) raise Not_found | [ ""; ".." ] -> (* i.e. URI begins with "/.." *) raise Not_found | s :: _ when s <> "" -> (* i.e. URI does not begin with "/" *) raise Not_found | _ -> (* ok, translate that *) let spec_uri_list = Neturl.norm_path (Neturl.split_path spec.file_uri) in translate spec_uri_list uri_list let ext_re = Netstring_str.regexp ".*\\.\\([^.]+\\)$";; let get_extension s = match Netstring_str.string_match ext_re s 0 with | None -> None | Some m -> Some(Netstring_str.matched_group m 1 s) let merge_byte_ranges st ranges = (* Merge the byte [ranges] into a single range. Returns [Some (first,last)] if * the range is satisfiable, else [None]. *) let size = st.Unix.LargeFile.st_size in let max_pos = Int64.pred size in let rec merge ranges = match ranges with | (first_pos_opt, last_pos_opt) :: ranges' -> let (first_pos, last_pos) = match (first_pos_opt, last_pos_opt) with | (Some fp, Some lp) -> (fp, lp) | (Some fp, None) -> (fp, max_pos) | (None, Some lp) -> (Int64.sub size lp, max_pos) | (None, None) -> assert false in let first_pos' = max 0L (min first_pos max_pos) in let last_pos' = max 0L (min last_pos max_pos) in if first_pos' <= last_pos' then ( match merge ranges' with | None -> Some(first_pos', last_pos') | Some(first_pos'', last_pos'') -> Some(min first_pos' first_pos'', max last_pos' last_pos'') ) else (* This range is void, try next range *) merge ranges' | [] -> None in merge ranges let w32_fix_trailing_slash s = (* background: Win32 dislikes Unix.stat "directory/". It is unclear whether this function is still required - file_translator is now changed so that trailing slashes are normally not returned. *) if Sys.os_type = "Win32" then ( if s <> "" && s <> "/" && s.[ String.length s - 1 ] = '/' then s ^ "." else s ) else s let get_compression_suffixes file_options = let rec find opts = match opts with | `Override_compression_suffixes l :: _ -> l | _ :: opts' -> find opts' | [] -> [ "gz", "gzip"; "bz2", "bzip2"; "Z", "compress" ] in find file_options let rec search_cooked_file filename compression_suffixes = match compression_suffixes with | [] -> [ "identity", filename ] | (suffix, ce) :: suffixes' -> try let filename_ext = filename ^ "." ^ suffix in let fd = Unix.openfile filename_ext [ Unix.O_RDONLY] 0 in (* or Unix_error *) Unix.close fd; (ce, filename_ext) :: search_cooked_file filename suffixes' with | Unix.Unix_error(_,_,_) -> search_cooked_file filename suffixes' let file_service (spec : file_service) = object(self) method name = "file_service" method def_term = `File_service spec method print fmt = Format.fprintf fmt "@[file_service("; Format.fprintf fmt "@ docroot(%s)" spec.file_docroot; Format.fprintf fmt "@ uri(%s)" spec.file_uri; Format.fprintf fmt "@ @[suffix_types("; List.iter (fun (suff,t) -> Format.fprintf fmt "@ %s => %s" suff t) spec.file_suffix_types; Format.fprintf fmt "@]@ )"; Format.fprintf fmt "@ default_type(%s)" spec.file_default_type; Format.fprintf fmt "@ @[options("; List.iter (function | `Enable_gzip -> Format.fprintf fmt "@ enable_gzip" | `Enable_cooked_compression -> Format.fprintf fmt "@ enable_cooked_compression" | `Enable_index_file _ -> Format.fprintf fmt "@ enable_index_file" | `Enable_listings _ -> Format.fprintf fmt "@ enable_listings" | `Override_compression_suffixes _ -> Format.fprintf fmt "@ override_compression_suffixes" ) spec.file_options; Format.fprintf fmt "@]@ )"; Format.fprintf fmt "@]@ )"; method process_header env = try let req_path_esc = env#cgi_script_name in let req_path = try uripath_decode req_path_esc with Failure _ -> raise Not_found in let filename = file_translator spec req_path in (* or Not_found *) let s = Unix.LargeFile.stat (w32_fix_trailing_slash filename) in (* or Unix_error *) ( match s.Unix.LargeFile.st_kind with | Unix.S_REG -> self # serve_regular_file env filename s | Unix.S_DIR -> self # serve_directory env filename s | _ -> (* other types are illegal *) raise Not_found ) with | Not_found -> `Std_response(`Not_found, None,(Some "Nethttpd: Can neither translate to regular file nor to directory") ) | Unix.Unix_error(Unix.ENOENT,_,_) -> `Std_response(`Not_found, None, (Some "Nethttpd: No such file or directory")) | Unix.Unix_error((Unix.EACCES | Unix.EPERM),_,_) -> `Std_response(`Forbidden, None, (Some "Nethttpd: File access denied")) | Unix.Unix_error(e,_,_) -> `Std_response(`Internal_server_error, None, (Some ("Nethttpd: Unix error: " ^ Unix.error_message e))) | Standard_response(status,hdr_opt,errmsg_opt) -> if status = `Ok then `Static(`Ok,hdr_opt,"") else `Std_response(status,hdr_opt,errmsg_opt) method private serve_regular_file env filename s = (* Regular file: Check if we can open for reading *) let fd = Unix.openfile filename [Unix.O_RDONLY] 0 in (* or Unix_error *) Unix.close fd; (* If OPTIONS: Respond now *) let req_method = env # cgi_request_method in if req_method = "OPTIONS" then ( env # set_output_header_field "Accept-ranges" "bytes"; raise(Standard_response(`Ok, None, None)); ); (* Check request method: Only GET and HEAD are supported *) if req_method <> "GET" && req_method <> "HEAD" then ( let h = new Netmime.basic_mime_header [] in set_allow h [ "GET"; "HEAD"; "OPTIONS" ]; raise(Standard_response(`Method_not_allowed,Some h, (Some "Nethttpd: Method not allowed for file")))); (* Set [Accept-ranges] header: *) env # set_output_header_field "Accept-ranges" "bytes"; (* Figure out file extension, content encoding (compression type) and media type *) let media_type_of_ext ext = try List.assoc ext spec.file_suffix_types with Not_found -> spec.file_default_type in let compression_suffixes = get_compression_suffixes spec.file_options in let ext_opt = get_extension filename in let content_encoding, media_type = match ext_opt with | Some ext when List.mem_assoc ext compression_suffixes -> let ce = List.assoc ext compression_suffixes in let filename1 = Filename.chop_extension filename in let ext1_opt = get_extension filename1 in ( match ext1_opt with | None -> (ce, spec.file_default_type) | Some ext1 -> (ce, media_type_of_ext ext1) ) | Some ext -> "identity", media_type_of_ext ext | None -> "identity", spec.file_default_type in env # set_output_header_field "Content-type" media_type; if content_encoding <> "identity" then env # set_output_header_field "Content-Encoding" content_encoding; (* Generate the (weak) validator from the file statistics: *) let etag = `Weak (sprintf "%d-%Lu-%.0f" s.Unix.LargeFile.st_ino s.Unix.LargeFile.st_size s.Unix.LargeFile.st_mtime) in set_etag env#output_header etag; set_last_modified env#output_header s.Unix.LargeFile.st_mtime; (* Check for conditional and partial GET *) (* In order of decreasing priority: * If-Match: If present, we always respond with code 412. This condition * requires the availablity of strong validators. * If-Unmodified-Since: If present, we check the dates, and if passing * the GET will be carried out. * If-Modified-Since and If-None-Match: The results of the individual * tests are ORed (accept when either of the tests accepts): * +--------------+---------------+-----------+ * | If-Mod-Since | If-None-Match | Behaviour | * +--------------+---------------+-----------+ * | modified | none | accept | * | unmodified | none | code 304 | * | modified | match | accept | * | unmodified | match | code 304 | * | none | match | code 304 | * | modified | no match | accept | * | unmodified | no match | accept | * | none | no match | accept | * +--------------+---------------+-----------+ * (my interpretation of 14.26 of RFC 2616) * * If accepted, the second question is whether to return the whole * file or only a fragment: * If-Range + Range: (only if both headers are present) * If the condition is fulfilled, return only the range, else the * whole document. * Only Range: The range is satisfied whenever possible. * No Range: Return whole file. `Enable_gzip is only interpreted in this * case. * *) if env # multiple_input_header_field "If-match" <> [] then ( raise(Standard_response(`Precondition_failed,None,None)); ); ( try let d = get_if_unmodified_since env#input_header in (* or Not_found *) if s.Unix.LargeFile.st_mtime > d then raise(Standard_response(`Precondition_failed,None,None)); with | Not_found -> () | Bad_header_field _ -> () ); let accept_if_modified, have_if_modified = try let d = get_if_modified_since env#input_header in (* or Not_found *) s.Unix.LargeFile.st_mtime > d, true with | Not_found -> false, false | Bad_header_field _ -> false, false in let accept_if_none_match, have_if_none_match = try let if_etags = get_if_none_match env#input_header in (* or Not_found *) ( match if_etags with | None -> (* case: If-None-Match: * *) false, true | Some l -> not (List.exists (weak_validator_match etag) l), true ) with | Not_found -> false, false | Bad_header_field _ -> false, false in if (have_if_modified || have_if_none_match) && not (accept_if_modified || accept_if_none_match) then raise(Standard_response(`Not_modified,None,None)); (* Now the GET request is accepted! *) let partial_GET = try let ranges = get_range env#input_header in (* or Not_found *) (* Ok, we can do a partial GET. Now check if this is not needed * because of If-Range: *) ( try match get_if_range env#input_header with (* or Not_found *) | `Etag e -> None (* Because we do not have strong validators *) | `Date d -> if s.Unix.LargeFile.st_mtime <= d then Some ranges else None with | Not_found -> Some ranges | Bad_header_field _ -> Some ranges ) with | Not_found -> None | Bad_header_field _ -> None in (* So either serve partially or fully: *) ( match partial_GET with | Some(`Bytes ranges) -> (* Partial GET: We do not support multipart/byteranges. Instead, * all requested ranges are implicitly merged into a single one. *) let eff_range_opt = merge_byte_ranges s ranges in (* TODO *) ( match eff_range_opt with | Some ((first_pos,last_pos) as eff_range) -> (* Serve the file fragment: *) let h = env # output_header in set_content_range h (`Bytes(Some eff_range, Some s.Unix.LargeFile.st_size)); let length = Int64.succ(Int64.sub last_pos first_pos) in `File(`Partial_content, Some h, filename, first_pos, length) | None -> (* The range is not satisfiable *) let h = env # output_header in set_content_range h (`Bytes(None, (Some s.Unix.LargeFile.st_size) )); `Std_response(`Requested_range_not_satisfiable, Some h, (Some "Nethttpd: Requested range is not satisfiable")) ) | None -> (* Full GET *) (* Check whether there is a gzip-encoded complementary file *) let encodings_and_files = if (List.mem `Enable_gzip spec.file_options || List.mem `Enable_cooked_compression spec.file_options) then search_cooked_file filename compression_suffixes else [ "identity", filename ] in let supported_encodings = List.map fst encodings_and_files in let encoding = best_encoding env#input_header supported_encodings in let h = env # output_header in ( match encoding with | "identity" -> `File(`Ok, None, filename, 0L, s.Unix.LargeFile.st_size) | _ -> let fn = List.assoc encoding encodings_and_files in let st_gzip = Unix.LargeFile.stat fn in h # update_field "Content-Encoding" encoding; `File(`Ok, Some h, fn, 0L, st_gzip.Unix.LargeFile.st_size) ) ) method private serve_directory env filename s = let index_files = (try List.flatten (List.map (function `Enable_index_file l -> l | _ -> []) spec.file_options) with Not_found -> []) in let abs_index_file_opt = try Some (List.find (fun n -> Sys.file_exists(Filename.concat filename n)) index_files) with Not_found -> None in let gen_listings = try Some(List.find (fun opt -> match opt with `Enable_listings _ -> true|_ -> false) spec.file_options) with Not_found -> None in if abs_index_file_opt <> None || gen_listings <> None then ( let req_path_esc = env#cgi_script_name in let req_path = uripath_decode req_path_esc in (* If [req_path] does not end with a slash, perform a redirection: *) if req_path <> "" && req_path.[ String.length req_path - 1 ] <> '/' then ( let h = new Netmime.basic_mime_header [ "Location", sprintf "%s://%s%s%s/" (if env#cgi_https then "https" else "http") env#cgi_server_name ( match env#cgi_server_port with | Some p -> ":" ^ string_of_int p | None -> "") env#cgi_request_uri ] in raise(Standard_response(`Found, Some h, None)); ) ); match (abs_index_file_opt, gen_listings) with | Some name, _ -> (* Ok, redirect to the file *) let req_path_esc = Neturl.split_path env#cgi_script_name in let name_esc = [ uripath_encode name ] in raise(Redirect_request(Neturl.join_path (req_path_esc @ name_esc), env # input_header)) | None, Some (`Enable_listings generator) -> (* If OPTIONS: Respond now *) let req_method = env # cgi_request_method in if req_method = "OPTIONS" then ( raise(Standard_response(`Ok, None, None)); ); (* Check request method: Only GET and HEAD are supported *) let req_method = env # cgi_request_method in if req_method <> "GET" && req_method <> "HEAD" then ( let h = new Netmime.basic_mime_header [] in set_allow h [ "GET"; "HEAD" ]; raise (Standard_response(`Method_not_allowed,Some h,(Some "Nethttpd: Method not allowed for directory listing")))); (* Generate contents: *) let dyn_spec = { dyn_handler = (fun env cgi -> generator env cgi spec); dyn_activation = std_activation `Std_activation_unbuffered; dyn_uri = Some "/"; dyn_translator = (fun _ -> filename); dyn_accept_all_conditionals = false; } in let dyn_srv = dynamic_service dyn_spec in dyn_srv # process_header env (* let (listing, listing_hdr) = generator env spec filename in (* Generate the (weak) validator from the file statistics: *) let etag = `Weak (sprintf "%d-%Lu-%.0f" s.Unix.LargeFile.st_ino s.Unix.LargeFile.st_size s.Unix.LargeFile.st_mtime) in set_etag listing_hdr etag; (* Refuse If-match and If-unmodified-since: *) if env # multiple_input_header_field "If-match" <> [] then raise(Standard_response(`Precondition_failed, None, None)); if env # multiple_input_header_field "If-unmodified-since" <> [] then raise(Standard_response(`Precondition_failed, None, None)); (* Return contents: *) `Static(`Ok, Some listing_hdr, listing) *) | _ -> (* Listings are forbidden: *) `Std_response(`Forbidden, None, (Some "Nethttpd: Access to directories not configured") ) end let simple_listing ?(hide=[ "\\."; ".*~$" ]) env (cgi :Netcgi.cgi_activation) fs = let dirname = env # cgi_path_translated in let col_name = 30 in let col_mtime = 20 in let col_size = 10 in let regexps = List.map (fun re -> Netstring_str.regexp re) hide in let req_path_esc = env#cgi_path_info in let req_path = uripath_decode req_path_esc in let files = Sys.readdir (w32_fix_trailing_slash dirname) in let xfiles = Array.map (fun name -> if List.exists (fun re -> Netstring_str.string_match re name 0 <> None) regexps then `None else try let st = Unix.LargeFile.stat (Filename.concat dirname name) in match st.Unix.LargeFile.st_kind with | Unix.S_REG -> `Reg(name, st.Unix.LargeFile.st_mtime, st.Unix.LargeFile.st_size) | Unix.S_DIR -> `Dir(name, st.Unix.LargeFile.st_mtime) | _ -> `None with Unix.Unix_error(_,_,_) -> `None ) files in let params = try Netencoding.Url.dest_url_encoded_parameters env#cgi_query_string with _ -> [] in let sort_param = try List.assoc "sort" params with Not_found -> "name" in let direction_param = try List.assoc "direction" params with Not_found -> "ascending" in let direction_factor = match direction_param with | "ascending" -> 1 | "descending" -> (-1) | _ -> 0 in let rev_direction = match direction_param with | "ascending" -> "descending" | "descending" -> "ascending" | _ -> "" in let query_sort_name = if sort_param = "name" then "?sort=name&direction=" ^ rev_direction else "?sort=name&direction=ascending" in let query_sort_mtime = if sort_param = "mtime" then "?sort=mtime&direction=" ^ rev_direction else "?sort=mtime&direction=ascending" in let query_sort_size = if sort_param = "size" then "?sort=size&direction=" ^ rev_direction else "?sort=size&direction=ascending" in let cmp x y = match (x,y) with | `None, `None -> 0 | `None, _ -> (-1) | _, `None -> 1 | `Dir _, `Reg _ -> (-1) | `Reg _, `Dir _ -> 1 | `Reg(xname,xmtime,xsize), `Reg(yname,ymtime,ysize) -> direction_factor * ( match sort_param with | "name" -> compare xname yname | "mtime" -> compare xmtime ymtime | "size" -> compare xsize ysize | _ -> 0 ) | `Dir(xname,xmtime), `Dir(yname,ymtime) -> direction_factor * ( match sort_param with | "name" -> compare xname yname | "mtime" -> compare xmtime ymtime | _ -> 0 ) in Array.stable_sort cmp xfiles; let esc_html = Netencoding.Html.encode_from_latin1 in let link_to href n s = let s' = if String.length s > n then String.sub s 0 n else s in sprintf "%s%s" (esc_html href) s' (String.make (n-String.length s') ' ') in let nolink n s = let s' = if String.length s > n then String.sub s 0 n else s in s' ^ (String.make (n-String.length s') ' ') in let mkdate f = Netdate.format ~fmt:"%Y-%m-%d %H:%M" (Netdate.create f) in let mksize n = if n >= 1099511627776L then sprintf "%8.1fT" (Int64.to_float n /. 1099511627776.0) else if n >= 1073741824L then sprintf "%8.1fG" (Int64.to_float n /. 1073741824.0) else if n >= 1048576L then sprintf "%8.1fM" (Int64.to_float n /. 1048576.0) else if n >= 1024L then sprintf "%8.1fk" (Int64.to_float n /. 1024.0) else if n >= 0L then sprintf "%8.1f" (Int64.to_float n) else "-" in let out = cgi # output # output_string in cgi # set_header (); out "\n"; out (sprintf "Index of %s\n" (esc_html req_path)); out "\n"; out (sprintf "

Index of %s

\n" (esc_html req_path)); out "
";
  out (sprintf "      %s %s %s\n\n"
    (link_to query_sort_name  col_name  "Name")
    (link_to query_sort_mtime col_mtime "Last Modified")
    (link_to query_sort_size  col_size  "Size"));
  if req_path <> "/" then
    out (sprintf "[DIR] %s %s %s\n"
      (link_to ".." col_name "Parent Directory")
      (nolink col_mtime "")
      (nolink col_size ""));
  Array.iter
    (function
       | `Reg(name, mtime, size) ->
	   let mtime_str = mkdate mtime in
	   let size_str = mksize size in
	   out (sprintf "[   ] %s %s %s\n"
	     (link_to name col_name name)
	     (nolink col_mtime mtime_str)
	     (nolink col_size size_str));
       | `Dir(name, mtime) ->
	   let mtime_str = mkdate mtime in
	   out (sprintf "[DIR] %s %s %s\n"
	     (link_to name col_name (name ^ "/"))
	     (nolink col_mtime mtime_str)
	     (nolink col_size "-"))
       | `None ->
	   ()
    )
    xfiles;
  out "
\n"; cgi # output # commit_work() type ac_by_host_rule = [ `Allow of string list | `Deny of string list ] type 'a ac_by_host = ac_by_host_rule * 'a http_service let prepare_ac_by_host spec = let resolve host = try [ Unix.inet_addr_of_string host ] with | _ -> ( try let h = Uq_resolver.get_host_by_name host in Array.to_list h.Unix.h_addr_list with | Uq_resolver.Host_not_found _ -> [] ) in match spec with | `Allow hosts -> let ipaddrs = List.flatten (List.map resolve hosts) in `Allow_ip ipaddrs | `Deny hosts -> let ipaddrs = List.flatten (List.map resolve hosts) in `Deny_ip ipaddrs let ac_by_host (spec, (srv : 'a http_service)) = let spec' = prepare_ac_by_host spec in ( object(self) method name = "ac_by_host" method def_term = `Ac_by_host (spec,srv) method print fmt = Format.fprintf fmt "ac_by_host(...)" method process_header env = let addr = env # remote_socket_addr in let allowed = match spec' with | `Allow_ip ipaddrs -> ( match addr with | Unix.ADDR_INET(ia,_) -> List.mem ia ipaddrs | _ -> true ) | `Deny_ip ipaddrs -> ( match addr with | Unix.ADDR_INET(ia,_) -> not(List.mem ia ipaddrs) | _ -> true ) in if allowed then srv # process_header env else `Std_response(`Forbidden, None, (Some "Nethttpd: Access denied by host rule")) end ) let ws_re = Netstring_str.regexp "[ \r\t\n]+" let split_ws s = Netstring_str.split ws_re s let read_media_types_file fname = let f = open_in fname in let l = ref [] in try while true do let line = input_line f in if line = "" || line.[0] <> '#' then ( let words = split_ws line in match words with | [] -> () | [ mtype ] -> () | mtype :: suffixes -> l := (List.map (fun s -> (s,mtype)) (List.rev suffixes)) @ !l ) done; assert false with | End_of_file -> close_in f; List.rev !l | error -> close_in f; raise error ;; ocamlnet-4.1.2/src/netcgi2-apache/0000755000175000017500000000000012731530350015304 5ustar gerdgerdocamlnet-4.1.2/src/netcgi2-apache/handler.c0000644000175000017500000004103512731530350017070 0ustar gerdgerd/* handler.c * Copyright (C) 2003 Merjis Ltd. * Copyright (C) 2007 Christophe Troestler * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This is a fork from mod_caml cleaned up and tailored to Netcgi2. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #if APACHE2 #include #include #include #endif #include "wrappers.h" #if !(APACHE2) #define apr_pool_t pool #define apr_palloc ap_palloc #endif #define VERSION_STRING "Netcgi_apache/" VERSION extern module netcgi_module; /* The module_init hook isn't called until after configuration. Duh! * So we need something which really _will_ be called early, to * initialize the OCaml runtime. */ static void init (void) __attribute__((constructor)); #pragma init(init) static void init (void) { /* The doc says that argv[0] and argv[1] are consulted to find the * file containing the bytecode. */ static char *argv[] = { APACHE_LIBDIR "/mod_netcgi_apache.so", APACHE_LIBDIR "/mod_netcgi_apache.so", NULL }; /* Remove a possible source of error by bailing if argv[0] doesn't exist. */ if (access (argv[0], R_OK) == -1) { perror(argv[0]); fprintf(stderr, "This probably means one of the following things:\n" "- Program has not been installed.\n" "- File has been moved/removed since installation.\n" "- APACHE_LIBDIR wasn't set correctly by ./configure\n" "In any case you must fix this before Netcgi_apache can run.\n"); abort(); } /* Start the OCaml bytecode interpreter. */ /* caml_main(argv); */ caml_startup(argv); /* embed the bytecode in the C code */ } #if APACHE2 static int post_config (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *s) { ap_add_version_component (pPool, VERSION_STRING); /* FIXME: should we protect against apache threads? */ return OK; } #else static void module_init (server_rec *s, pool *p) { ap_add_version_component (VERSION_STRING); /* No interesting Caml callback to execute */ } #endif /* * Configuration */ /* Notes on per-server and per-directory configuration. * * The actual OCaml data that we store here is defined in the * immutable structs Netcgi_apache.Handler.server_config_t and * Netcgi_apache.Handler.dir_config_t. You are advised to go and look * at those now... * * Apache lets us store a pointer (void *) and leaves it up to us * what this actually points to. In our case the pointer (v in the * diagram) points to an OCaml value. The OCaml value is presumed * to be a pointer to the structure itself. * * 4/8 bytes * in pool allocated on OCaml heap * +----------+ +-- the structure ---------+ * v ----> | value -------> | either server_config_t | * +----------+ | or dir_config_t | * | ... | * | ... | * | ... | * +--------------------------+ * * The value is allocated in the pool which Apache gives us. This * pool should usually last for the lifetime of the server, but it's * up to Apache to sort that out. * * In addition, we make the value be an OCaml GC global root. This * means that the GC won't free up the structure prematurely. * * Also we register a cleanup function in the pool. When Apache does * finally deallocate the pool, our cleanup function will remove the * global root. * * Note that the structure is immutable, so, for example, * cmd_translate_handler and friends actually create a new structure * and update the value to point to the new structure. */ /* [alloc_root_value(p)]: allocate a global root value in the pool * [p], and register a cleanup which will be called when the pool dies * to unregister the global root. */ #if APACHE2 static int remove_root_value (void *vp) { remove_global_root ((value *) vp); return OK; } #endif static value * alloc_root_value (apr_pool_t *p) { value *v = (value *) apr_palloc(p, sizeof (value)); *v = Val_unit; register_global_root (v); #if APACHE2 apr_pool_cleanup_register (p, v, remove_root_value, apr_pool_cleanup_null); #else ap_register_cleanup (p, v, (void (*)(void *)) remove_global_root, ap_null_cleanup); #endif return v; } static void * create_dir_config (apr_pool_t *p, char *dirname) { value arg = Val_optstring (dirname); value *v = alloc_root_value (p); static value *f = NULL; if(f == NULL) f = caml_named_value("netcgi2_apache_create_dir_config"); *v = callback(*f, arg); return v; } static void * merge_dir_config (apr_pool_t *p, void *base, void *add) { value *v = alloc_root_value (p); static value *f = NULL; if(f == NULL) f = caml_named_value("netcgi2_apache_merge_dir_config"); *v = callback2(*f, *(value *) base, *(value *) add); return v; } static void * create_server_config (apr_pool_t *p, server_rec *s) { value arg = Val_server_rec (s); value *v = alloc_root_value (p); static value *f = NULL; if(f == NULL) f = caml_named_value("netcgi2_apache_create_server_config"); *v = callback(*f, arg); return v; } static void * merge_server_config (apr_pool_t *p, void *base, void *add) { value *v = alloc_root_value (p); static value *f = NULL; if(f == NULL) f = caml_named_value("netcgi2_apache_merge_server_config"); *v = callback2(*f, *(value *) base, *(value *) add); return v; } /* * Handlers -- call the corresponding functions on the Caml side that * execute the handler in the configuration structure. */ /* Handlers are not supposed to raise exceptions (these should be * caught on the Caml side) but leave this anyway for security. */ static int exception_in_handler (value exn, const char *function_name) { char strtime[26]; time_t secs; /* Uncaught exception: log it and return internal server error. */ strtime[0] = '\0'; time(&secs); ctime_r(&secs, strtime); strtime[24] = '\0'; /* Remove the '\n' put by ctime */ fprintf(stderr, "[%s] [netcgi2_apache] %s: Uncaught exception \"%s\".\n", strtime, function_name, caml_format_exception(exn)); return HTTP_INTERNAL_SERVER_ERROR; } #define MAKE_HANDLER(name) \ static int name (request_rec *r) \ { \ static value *f = NULL; \ value rv, arg; \ if (f == NULL) f = caml_named_value("netcgi2_apache_" #name); \ assert(f); \ arg = Val_request_rec(r); \ rv = callback_exn(*f, arg); \ if (Is_exception_result(rv)) \ return exception_in_handler(Extract_exception(rv), __func__); \ return(Int_val(rv)); \ } MAKE_HANDLER(translate_handler) MAKE_HANDLER(check_user_id) MAKE_HANDLER(auth_checker) MAKE_HANDLER(access_checker) MAKE_HANDLER(type_checker) MAKE_HANDLER(fixer_upper) MAKE_HANDLER(logger) MAKE_HANDLER(header_parser) MAKE_HANDLER(post_read_request) MAKE_HANDLER(ocaml_bytecode_handler) /* * Commands */ #define MAKE_SIMPLE_CMD(name) \ static const char * \ name (cmd_parms *parms, void *dummy, const char *strarg) \ { \ static value *f = NULL; \ value arg = copy_string (strarg); \ value exn; \ if (f == NULL) f = caml_named_value("netcgi2_apache_" #name); \ exn = callback_exn(*f, arg); \ if (Is_exception_result (exn)) \ /* FIXME: ap_pstrdup into pool? */ \ return caml_format_exception (Extract_exception (exn)); \ return NULL; \ } MAKE_SIMPLE_CMD(cmd_load) MAKE_SIMPLE_CMD(cmd_require) MAKE_SIMPLE_CMD(cmd_thread) MAKE_SIMPLE_CMD(cmd_predicates) static const char * cmd_translate_handler (cmd_parms *parms, void *dummy, const char *name) { value *sconfig = (value *) ap_get_module_config (parms->server->module_config, &netcgi_module); static value *f = NULL; value arg = copy_string(name); value exn; if (f == NULL) f = caml_named_value("netcgi2_apache_cmd_translate_handler"); exn = callback2_exn(*f, *sconfig, arg); if (Is_exception_result (exn)) /* FIXME: ap_pstrdup into pool? */ return caml_format_exception (Extract_exception (exn)); *sconfig = exn; /* Update server config. */ return NULL; } #define MAKE_CMD(name) \ static const char * \ name (cmd_parms *parms, void *dconfig, const char *name) \ { \ value *f = NULL; \ value arg = copy_string(name); \ value exn; \ if (f == NULL) f = caml_named_value("netcgi2_apache_" #name); \ exn = callback2_exn(*f, *(value *) dconfig, arg); \ if (Is_exception_result (exn)) \ /* FIXME: ap_pstrdup into pool? */ \ return caml_format_exception (Extract_exception (exn)); \ *(value *)dconfig = exn; /* Update dir config. */ \ return NULL; \ } MAKE_CMD(cmd_check_user_id_handler) MAKE_CMD(cmd_auth_checker_handler) MAKE_CMD(cmd_access_checker_handler) MAKE_CMD(cmd_type_checker_handler) MAKE_CMD(cmd_fixer_upper_handler) MAKE_CMD(cmd_logger_handler) MAKE_CMD(cmd_header_parser_handler) MAKE_CMD(cmd_post_read_request_handler) MAKE_CMD(cmd_handler) #if APACHE2 /* * Set up an Apache 2 module for Netcgi_apache */ static command_rec cmds[] = { AP_INIT_TAKE1 ("NetcgiLoad", cmd_load, NULL, RSRC_CONF, "load OCaml module"), AP_INIT_TAKE1 ("NetcgiRequire", cmd_require, NULL, RSRC_CONF, "load OCaml package (findlib)"), AP_INIT_TAKE1 ("NetcgiThread", cmd_thread, NULL, RSRC_CONF, "load OCaml threading support"), AP_INIT_TAKE1 ("NetcgiPredicates", cmd_predicates, NULL, RSRC_CONF, "set findlib predicates for NetcgiRequire"), AP_INIT_TAKE1 ("NetcgiTranslateHandler", cmd_translate_handler, NULL, RSRC_CONF, "set module as translate handler"), AP_INIT_TAKE1 ("NetcgiCheckUserIDHandler", cmd_check_user_id_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, "set module as check user ID handler"), AP_INIT_TAKE1 ("NetcgiAuthCheckerHandler", cmd_auth_checker_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, "set module as auth checker handler"), AP_INIT_TAKE1 ("NetcgiAccessCheckerHandler", cmd_access_checker_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, "set module as access checker handler"), AP_INIT_TAKE1 ("NetcgiTypeCheckerHandler", cmd_type_checker_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, "set module as type checker handler"), AP_INIT_TAKE1 ("NetcgiFixerUpperHandler", cmd_fixer_upper_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, "set module as fixer upper handler"), AP_INIT_TAKE1 ("NetcgiLoggerHandler", cmd_logger_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, "set module as logger handler"), AP_INIT_TAKE1 ("NetcgiHeaderParserHandler", cmd_header_parser_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, "set module as header parser handler"), AP_INIT_TAKE1 ("NetcgiPostReadRequestHandler", cmd_post_read_request_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, "set module as post read request handler"), AP_INIT_TAKE1 ("NetcgiHandler", cmd_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, "set module as output handler"), { NULL } }; static void register_hooks (apr_pool_t *p) { ap_hook_post_config (post_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_translate_name (translate_handler, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_check_user_id (check_user_id, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_auth_checker (auth_checker, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_access_checker (access_checker, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_type_checker (type_checker, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_fixups (fixer_upper, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_log_transaction (logger, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_header_parser (header_parser, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_read_request (post_read_request, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_handler (ocaml_bytecode_handler, NULL, NULL, APR_HOOK_MIDDLE); } module netcgi_module = { STANDARD20_MODULE_STUFF, create_dir_config, /* per-directory config creator */ merge_dir_config, /* dir config merger */ create_server_config, /* server config creator */ merge_server_config, /* server config merger */ cmds, /* command table */ register_hooks, /* register hooks */ }; #else /* * Set up an Apache 1 module for Netcgi_apache */ static command_rec cmds[] = { { "NetcgiLoad", cmd_load, NULL, RSRC_CONF, TAKE1, "load OCaml module" }, { "NetcgiTranslateHandler", cmd_translate_handler, NULL, RSRC_CONF, TAKE1, "set module as translate handler" }, { "NetcgiCheckUserIDHandler", cmd_check_user_id_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, "set module as check user ID handler" }, { "NetcgiAuthCheckerHandler", cmd_auth_checker_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, "set module as auth checker handler" }, { "NetcgiAccessCheckerHandler", cmd_access_checker_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, "set module as access checker handler" }, { "NetcgiTypeCheckerHandler", cmd_type_checker_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, "set module as type checker handler" }, { "NetcgiFixerUpperHandler", cmd_fixer_upper_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, "set module as fixer upper handler" }, { "NetcgiLoggerHandler", cmd_logger_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, "set module as logger handler" }, { "NetcgiHeaderParserHandler", cmd_header_parser_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, "set module as header parser handler" }, { "NetcgiPostReadRequestHandler", cmd_post_read_request_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, "set module as post read request handler" }, { "NetcgiHandler", cmd_handler, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, "set module as output handler" }, { NULL } }; static handler_rec handlers[] = { { "ocaml-bytecode", ocaml_bytecode_handler }, { NULL } }; module netcgi_module = { STANDARD_MODULE_STUFF, module_init, /* initializer */ create_dir_config, /* create per-directory config */ merge_dir_config, /* merge per-directory config */ create_server_config, /* create per-server config */ merge_server_config, /* merge per-server config */ cmds, /* command table */ handlers, /* handlers */ translate_handler, /* translate handler */ check_user_id, /* check user id */ auth_checker, /* check authorization */ access_checker, /* check access */ type_checker, /* type mapping */ fixer_upper, /* pre-run fixups */ logger, /* logging */ header_parser, /* header parsing */ NULL, /* child initialization */ NULL, /* child exit */ post_read_request, /* post-read request */ }; #endif /* not APACHE2 */ ocamlnet-4.1.2/src/netcgi2-apache/Makefile0000644000175000017500000000461712731530350016754 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PKGNAME = netcgi2-apache # Keep the name in sync with the one on handler.c : BUILD_EXTRA = mod_netcgi_apache.so INCLUDES += $(INC_NETSTRING) $(INC_NETSYS) $(INC_NETCGI2) REQUIRES += findlib OBJECTS = netcgi_apache.cmo netcgi_modtpl.cmo DOBJECTS = netcgi_apache.mli netcgi_modtpl.mli ALL_EXTRA = mod_netcgi_apache.so INSTALL_EXTRA = mod_netcgi_apache.so 500netcgi_apache.info OCAMLC_OPTIONS += $(STRING_OPTS) OCAMLOPT_OPTIONS += $(STRING_OPTS) PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" DOC_IGNORABLE = true include $(TOP_DIR)/Makefile.rules ifeq ($(APACHE_MAJOR),2) APACHE_LDFLAGS_SHLIB += -lapr-1 -laprutil-1 endif # mod_netcgi_apache.so: apache.lo handler.lo wrappers.lo netcgi_apache_mod.cmo # $(OCAMLC) -verbose -custom -linkall -o $@ \ # -cc "$(APXS) -c $(filter %.lo,$^)" \ # dynlink.cma unix.cma $(filter-out %.lo,$^) \ # -cclib '$(APACHE_CFLAGS) $(APACHE_LDFLAGS_SHLIB) $(APACHE_OCAMLLIBS)' # $(patsubst %.o,.libs/%.o,$^) \ # %.o: %.c # $(APACHE_CC) $(APACHE_CFLAGS) -I $(APACHE_OCAMLLIBDIR) -c $< # -Wl,-bI:$(APACHE_LIBDIR)/httpd.exp # mod_netcgi_apache.so: netcgi_apache_mod.cmo apache.o handler.o wrappers.o # $(OCAMLC) -o $@ -verbose -linkall -custom \ # -ccopt -Wl,--warn-unresolved-symbols \ # dynlink.cma unix.cma $(patsubst %.o, ./.libs/%.o, $^) \ # -cclib "$(APACHE_CFLAGS) $(APACHE_LDFLAGS_SHLIB) $(APACHE_OCAMLLIBS)" MOD_OBJECTS := wrappers.o handler.o apache.o netcgi_apache_mod.o # must be after the `include' for APACHE_MAJOR to be defined ifeq ($(APACHE_MAJOR),2) MOD_OBJECTS := $(patsubst %.o,%.lo,$(MOD_OBJECTS)) else MOD_OBJECTS := $(MOD_OBJECTS) endif ### Embed Caml code into the C code. ### Requires `caml_startup' instead of `caml_main' in handler.c ### Only works with OCaml >= 3.11 on plafforms where PIC differs from non-PIC ### See http://caml.inria.fr/mantis/view.php?id=3866 mod_netcgi_apache.so: $(MOD_OBJECTS) $(APXS) -c -o $@ $^ -L$(APACHE_OCAMLLIBDIR) -Wl,-R,$(APACHE_OCAMLLIBDIR) $(APACHE_OCAMLLIBS) test -f .libs/$@ && cp .libs/$@ . netcgi_apache_mod.lo: netcgi_apache_mod.o echo "$@ generated by the rule for $^" netcgi_apache_mod.o: netcgi_apache_mod.ml $(OCAMLC) -verbose -output-obj -linkall -o $@ \ -cc "./drive-apxs $(APXS)" \ -package "dynlink bytes unix findlib" -linkpkg $^ %.o: %.c $(APXS) -I$(APACHE_OCAMLLIBDIR) -c $< %.lo: %.c $(APXS) -I$(APACHE_OCAMLLIBDIR) -c $< include depend ocamlnet-4.1.2/src/netcgi2-apache/wrappers.h0000644000175000017500000000413512731530350017323 0ustar gerdgerd/* Wrappers around data structures. * Copyright (C) 2003 Merjis Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: wrappers.h,v 1.1 2003/09/07 19:41:14 rwmj Exp $ */ #ifndef _mod_caml_wrappers_ #define _mod_caml_wrappers_ #include "config.h" #include #include #include #include #include #if APACHE2 #define table apr_table_t #endif /* Wrap up an arbitrary void pointer in an opaque OCaml object. */ extern value Val_voidptr (void *ptr); /* Unwrap an arbitrary void pointer from an opaque OCaml object. */ #define Voidptr_val(type,rv) ((type *) Field ((rv), 0)) /* Hide the Apache types in opaque OCaml objects. */ #define Val_table(r) (Val_voidptr ((r))) #define Table_val(rv) (Voidptr_val (table, (rv))) #define Val_request_rec(r) (Val_voidptr ((r))) #define Request_rec_val(rv) (Voidptr_val (request_rec, (rv))) #define Val_server_rec(r) (Val_voidptr ((r))) #define Server_rec_val(rv) (Voidptr_val (server_rec, (rv))) #define Val_conn_rec(r) (Val_voidptr ((r))) #define Conn_rec_val(rv) (Voidptr_val (conn_rec, (rv))) #define Val_module_struct(r) (Val_voidptr ((r))) #define Module_struct_val(rv) (Voidptr_val (struct module_struct, (rv))) #define Val_cmd_parms(r) (Val_voidptr ((r))) #define Cmd_parms_val(rv) (Voidptr_val (cmd_parms, (rv))) /* Wrap up a char * as a string option. */ extern value Val_optstring (const char *); #endif /* _mod_caml_wrappers_ */ ocamlnet-4.1.2/src/netcgi2-apache/500netcgi_apache.info.in0000644000175000017500000000022312731530350021562 0ustar gerdgerdLoadModule: caml_module @APACHE_LIBDIR@/netcgi_apache.so Directives: CamlLoad CamlHandler Description: Cgi scripts, apache handlers,... in OCaml ocamlnet-4.1.2/src/netcgi2-apache/META.in0000644000175000017500000000062712731530350016367 0ustar gerdgerd# Specifications for the Netcgi_apache module -*-conf-*- #name = "netcgi_apache" version = "@VERSION@" description = "Apache mod connector" requires = "unix netstring netsys netcgi2 str" archive(byte) = "netcgi_apache.cma" archive(native) = "netcgi_apache.cmxa" archive(native,gprof) = "netcgi_apache.p.cmxa" error(pkg_netcgi1) = "The packages netcgi1 and netcgi2 cannot be used together" ocamlnet-4.1.2/src/netcgi2-apache/netcgi_apache_mod.ml.in0000644000175000017500000005730012731530350021661 0ustar gerdgerd(* netcgi_apache_mod.ml Copyright (C) 2005-2007 Christophe Troestler email: Christophe.Troestler@umh.ac.be WWW: http://math.umh.ac.be/an/ This library is free software; see the file LICENSE for more information. 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 file LICENSE for more details. *) (* This is a module with minimal dependencies to embed the ocaml runtime into Apache. Together with some C bindings it will make the mod_netcgi.so Apache module. The Netcgi_apache will then be loaded (with ist dependencies) using Apache directives. *) (** Configuration settings. *) module Conf = struct let ocaml_libdir = "@APACHE_OCAMLLIBDIR@" let package = "@PKGNAME@" let version = "@VERSION@" let apache_libdir = "@APACHE_LIBDIR@" let apache_major = @APACHE_MAJOR@ let gateway_interface = "Netcgi_apache" let server_software = String.concat "" ["Apache/"; Filename.basename apache_libdir; " "; gateway_interface; "/"; version] end (* We do not want to use the Netcgi_apache one because we want minimal dependencies. *) let log_error msg = let t = Unix.localtime(Unix.time()) in let dow = [| "Sun"; "Mon"; "Tue"; "Wed"; "Thu"; "Fri"; "Sat" |].(t.Unix.tm_wday) and month = [| "Jan"; "Feb"; "Mar"; "Apr"; "May"; "Jun"; "Jul"; "Aug"; "Sep"; "Oct"; "Nov"; "Dec" |].(t.Unix.tm_mon) in Printf.eprintf "[%s %s %d %02d:%02d:%02d %d] [Netcgi_apache_mod] %s\n%!" dow month t.Unix.tm_mday t.Unix.tm_hour t.Unix.tm_min t.Unix.tm_sec (t.Unix.tm_year + 1900) msg (* One has at least to use the apache.c functions here so they are part of the dynamic library. *) module Raw_Apache = struct (* Forked from mod_caml on May 29, 2006. *) module Table = struct (* Table functions. *) type t external clear : t -> unit = "netcgi2_apache_table_clear" external get : t -> string -> string = "netcgi2_apache_table_get" external get_all : t -> string -> string list = "netcgi2_apache_table_get_all" external fields : t -> (string * string) list = "netcgi2_apache_table_fields" external set : t -> string -> string -> unit = "netcgi2_apache_table_set" external add : t -> string -> string -> unit = "netcgi2_apache_table_add" external unset : t -> string -> unit = "netcgi2_apache_table_unset" (* Non-copying version. Not a great idea to allow access to this. external setn : t -> string -> string -> unit = "netcgi2_apache_table_setn" *) (* ... etc ... *) end module Server = struct (* Server_rec functions. *) type t (* Actual server_rec structure. *) external hostname : t -> string = "netcgi2_apache_server_hostname" external admin : t -> string = "netcgi2_apache_server_admin" external is_virtual : t -> bool = "netcgi2_apache_server_is_virtual" (* ... etc ... *) end module Connection = (* Conn_rec functions. *) struct type t (* Actual conn_rec structure. *) external remote_ip : t -> string = "netcgi2_apache_connection_remote_ip" external remote_host : t -> string = "netcgi2_apache_connection_remote_host" (* ... etc ... *) end module Request = struct (* Request_rec functions. *) type t (* request_rec structure. *) external connection : t -> Connection.t = "netcgi2_apache_request_connection" external server : t -> Server.t = "netcgi2_apache_request_server" external next : t -> t = "netcgi2_apache_request_next" external prev : t -> t = "netcgi2_apache_request_prev" external main : t -> t = "netcgi2_apache_request_main" external the_request : t -> string = "netcgi2_apache_request_the_request" external assbackwards : t -> bool = "netcgi2_apache_request_assbackwards" external header_only : t -> bool = "netcgi2_apache_request_header_only" external protocol : t -> string = "netcgi2_apache_request_protocol" external proto_num : t -> int = "netcgi2_apache_request_proto_num" external hostname : t -> string = "netcgi2_apache_request_hostname" external request_time : t -> float = "netcgi2_apache_request_request_time" external status_line : t -> string = "netcgi2_apache_request_status_line" external set_status_line : t -> string -> unit = "netcgi2_apache_request_set_status_line" external status : t -> int = "netcgi2_apache_request_status" external set_status : t -> int -> unit = "netcgi2_apache_request_set_status" external method_name : t -> string = "netcgi2_apache_request_method" external method_number : t -> int = "netcgi2_apache_request_method_number" let request_methods = [| `GET; `PUT; `POST; `DELETE; `CONNECT; `OPTIONS; `TRACE; `PATCH; `PROPFIND; `PROPPATCH; `MKCOL; `COPY; `MOVE; `LOCK; `UNLOCK; `INVALID |] let method_number r = let n = method_number r in if n < 0 || n >= Array.length request_methods then assert false; Array.unsafe_get request_methods n external headers_in : t -> Table.t = "netcgi2_apache_request_headers_in" external headers_out : t -> Table.t = "netcgi2_apache_request_headers_out" external err_headers_out : t -> Table.t = "netcgi2_apache_request_err_headers_out" external subprocess_env : t -> Table.t = "netcgi2_apache_request_subprocess_env" external notes : t -> Table.t = "netcgi2_apache_request_notes" external content_type : t -> string = "netcgi2_apache_request_content_type" external set_content_type : t -> string -> unit = "netcgi2_apache_request_set_content_type" external uri : t -> string = "netcgi2_apache_request_uri" external port : t -> int = "netcgi2_apache_request_port" external set_uri : t -> string -> unit = "netcgi2_apache_request_set_uri" external filename : t -> string = "netcgi2_apache_request_filename" external set_filename : t -> string -> unit = "netcgi2_apache_request_set_filename" external path_info : t -> string = "netcgi2_apache_request_path_info" external set_path_info : t -> string -> unit = "netcgi2_apache_request_set_path_info" external args : t -> string = "netcgi2_apache_request_args" external set_args : t -> string -> unit = "netcgi2_apache_request_set_args" external finfo : t -> Unix.stats option = "netcgi2_apache_request_finfo" type read_policy = NO_BODY | CHUNKED_ERROR | CHUNKED_DECHUNK | CHUNKED_PASS external setup_client_block : t -> read_policy -> int = "netcgi2_apache_request_setup_client_block" external should_client_block : t -> bool = "netcgi2_apache_request_should_client_block" external get_client_block : t -> string = "netcgi2_apache_request_get_client_block" external get_client_block_buffer : t -> Bytes.t -> int -> int -> int = "netcgi2_apache_request_get_client_block_buffered" external discard_request_body : t -> int = "netcgi2_apache_request_discard_request_body" external user : t -> string = "netcgi2_apache_request_user" (* In Apache 1.3 this field is actually in the [conn_rec] structure, and was moved here in Apache 2.0. We transparently hide this detail for you. *) external auth_type : t -> string = "netcgi2_apache_auth_type" external note_auth_failure : t -> unit = "netcgi2_apache_request_note_auth_failure" external note_basic_auth_failure : t -> unit = "netcgi2_apache_request_note_basic_auth_failure" external note_digest_auth_failure : t -> unit = "netcgi2_apache_request_note_digest_auth_failure" external get_basic_auth_pw : t -> int * string option = "netcgi2_apache_request_get_basic_auth_pw" external send_http_header : t -> unit = "netcgi2_apache_request_send_http_header" external rflush : t -> int = "netcgi2_apache_request_rflush" external internal_redirect : string -> t -> unit = "netcgi2_apache_request_internal_redirect" external internal_redirect_handler : string -> t -> unit = "netcgi2_apache_request_internal_redirect_handler" external print_char : t -> char -> unit = "netcgi2_apache_request_print_char" external unsafe_output : t -> Bytes.t -> int -> int -> int = "netcgi2_apache_request_output" let output r s ofs len = if ofs < 0 || len < 0 || ofs + len > Bytes.length s then invalid_arg "Netcgi_apache.Apache.Request.output"; unsafe_output r s ofs len let print_string r s = let s = Bytes.unsafe_of_string s in let n = Bytes.length s in let i = ref 0 in while !i < n do let w = unsafe_output r s !i (n - !i) in if w <= 0 then failwith "print_string: end of file or error"; i := !i + w; done let print_int r i = print_string r (string_of_int i) let print_float r f = print_string r (string_of_float f) let print_newline r = print_string r "\r\n" let print_endline r s = print_string r s; print_newline r (* ... etc ... *) external register_cleanup : t -> (unit -> unit) -> unit = "netcgi2_apache_request_register_cleanup" end (* Unless we actually reference the external C functions, OCaml doesn't load them into the primitive table and we won't be able to access them! *) let _table_clear = Table.clear let _table_get = Table.get let _table_get_all = Table.get_all let _table_fields = Table.fields let _table_set = Table.set let _table_add = Table.add let _table_unset = Table.unset let _server_hostname = Server.hostname let _server_admin = Server.admin let _server_is_virtual = Server.is_virtual let _connection_remote_ip = Connection.remote_ip let _connection_remote_host = Connection.remote_host let _request_connection = Request.connection let _request_server = Request.server let _request_next = Request.next let _request_prev = Request.prev let _request_main = Request.main let _request_the_request = Request.the_request let _request_assbackwards = Request.assbackwards let _request_header_only = Request.header_only let _request_protocol = Request.protocol let _request_proto_num = Request.proto_num let _request_hostname = Request.hostname let _request_request_time = Request.request_time let _request_status_line = Request.status_line let _request_set_status_line = Request.set_status_line let _request_status = Request.status let _request_set_status = Request.set_status let _request_method_name = Request.method_name let _request_method_number = Request.method_number let _request_headers_in = Request.headers_in let _request_headers_out = Request.headers_out let _request_err_headers_out = Request.err_headers_out let _request_subprocess_env = Request.subprocess_env let _request_notes = Request.notes let _request_content_type = Request.content_type let _request_set_content_type = Request.set_content_type let _request_uri = Request.uri let _request_port = Request.port let _request_set_uri = Request.set_uri let _request_filename = Request.filename let _request_set_filename = Request.set_filename let _request_path_info = Request.path_info let _request_set_path_info = Request.set_path_info let _request_args = Request.args let _request_set_args = Request.set_args let _request_finfo = Request.finfo let _request_setup_client_block = Request.setup_client_block let _request_should_client_block = Request.should_client_block let _request_get_client_block = Request.get_client_block let _request_get_client_block_buffer = Request.get_client_block_buffer let _request_discard_request_body = Request.discard_request_body let _request_user = Request.user let _request_auth_type = Request.auth_type let _request_note_auth_failure = Request.note_auth_failure let _request_note_basic_auth_failure = Request.note_basic_auth_failure let _request_note_digest_auth_failure = Request.note_digest_auth_failure let _request_get_basic_auth_pw = Request.get_basic_auth_pw let _request_send_http_header = Request.send_http_header let _request_rflush = Request.rflush let _request_internal_redirect = Request.internal_redirect let _request_internal_redirect_handler = Request.internal_redirect_handler let _request_print_char = Request.print_char let _request_unsafe_output = Request.unsafe_output let _request_register_cleanup = Request.register_cleanup end (* module Raw_Apache ------------------------------------------------- *) module Handler = struct (* Forked from mod_caml.ml but streamlined and adapted to Netcgi2 style. *) type result = OK | DECLINED | DONE | HTTP of int type t = Raw_Apache.Request.t -> result (* Handler on the Caml side. May also exit through an exception. *) (*----- Initialize Dynlink library. -----*) let () = try Dynlink.init (); Dynlink.allow_unsafe_modules true with Dynlink.Error(e) -> failwith(Dynlink.error_message e) (*----- Configuration. -----*) type dir_config_t = { location : string option; check_user_id : t option; auth_checker : t option; access_checker : t option; type_checker : t option; fixer_upper : t option; logger : t option; header_parser : t option; post_read_request : t option; ocaml_bytecode_handler : t option; } type server_config_t = { translate_handler : t option; } let create_dir_config dirname = { location = dirname; check_user_id = None; auth_checker = None; access_checker = None; type_checker = None; fixer_upper = None; logger = None; header_parser = None; post_read_request = None; ocaml_bytecode_handler = None } let update b a = if a = None then b else a let merge_dir_config base add = { location = update base.location add.location; check_user_id = update base.check_user_id add.check_user_id; auth_checker = update base.auth_checker add.auth_checker; access_checker = update base.access_checker add.access_checker; type_checker = update base.type_checker add.type_checker; fixer_upper = update base.fixer_upper add.fixer_upper; logger = update base.logger add.logger; header_parser = update base.header_parser add.header_parser; post_read_request = update base.post_read_request add.post_read_request; ocaml_bytecode_handler = update base.ocaml_bytecode_handler add.ocaml_bytecode_handler; } external get_dir_config : Raw_Apache.Request.t -> dir_config_t = "netcgi2_apache_get_dir_config" (* in apache.c *) let create_server_config s = { translate_handler = None; } let merge_server_config base add = { translate_handler = update base.translate_handler add.translate_handler } external get_server_config : Raw_Apache.Request.t -> server_config_t = "netcgi2_apache_get_server_config" (* in apache.c *) let () = Callback.register "netcgi2_apache_create_dir_config" create_dir_config; Callback.register "netcgi2_apache_merge_dir_config" merge_dir_config; Callback.register "netcgi2_apache_create_server_config" create_server_config; Callback.register "netcgi2_apache_merge_server_config" merge_server_config (*----- Handlers. -----*) (** [make_handler name conf_member] register a function that, when executed (on the C side), will run the handler set in the configuration if any is present. *) let make_handler name conf = (* This function returns an integer (DECLINED -1, DONE -2, OK 0 or an HTTP status) so we can deal with exceptions on the Caml side. *) let handler r = try match conf r with | Some handler -> (try match handler r with | OK -> 0 | DECLINED -> -1 | DONE -> -2 | HTTP i -> i with | Exit -> 0 (* = OK; considered a correct way to terminate *) | exn -> log_error(name ^ ": Uncaught exception: " ^ Printexc.to_string exn); 500 (* Internal Server Error *) ) | None -> -1 (* DECLINED; no handler *) with Not_found -> -1 (* DECLINED; no server config *) in Callback.register name (handler:Raw_Apache.Request.t -> int) let () = make_handler "netcgi2_apache_translate_handler" (fun r -> (get_server_config r).translate_handler); make_handler "netcgi2_apache_check_user_id" (fun r -> (get_dir_config r).check_user_id); make_handler "netcgi2_apache_auth_checker" (fun r -> (get_dir_config r).auth_checker); make_handler "netcgi2_apache_access_checker" (fun r -> (get_dir_config r).access_checker); make_handler "netcgi2_apache_type_checker" (fun r -> (get_dir_config r).type_checker); make_handler "netcgi2_apache_fixer_upper" (fun r -> (get_dir_config r).fixer_upper); make_handler "netcgi2_apache_logger" (fun r -> (get_dir_config r).logger); make_handler "netcgi2_apache_header_parser" (fun r -> (get_dir_config r).header_parser); make_handler "netcgi2_apache_post_read_request" (fun r -> (get_dir_config r).post_read_request); make_handler "netcgi2_apache_ocaml_bytecode_handler" (fun r -> (get_dir_config r).ocaml_bytecode_handler) (*----- Handler registration. -----*) let reg_table = Hashtbl.create 16 let reg_module_name = ref None let register_module handler full_name = Hashtbl.replace reg_table full_name handler (* Register the module's handler. *) let register (handler:t) name = match !reg_module_name with | None -> failwith("Netcgi_apache.Handler.register: \ call outside module initialization") | Some module_name -> register_module handler (module_name ^ "." ^ name) (*----- Commands. -----*) (* NetcgiLoad [filename]. Preprend the ocaml standard library path (ocamlc -where) if [filename] is relative. *) let cmd_load filename = let filename = if Filename.is_relative filename then Filename.concat Conf.ocaml_libdir filename else filename in reg_module_name := Some(String.capitalize(Filename.chop_extension (Filename.basename filename))); try Dynlink.loadfile filename; with Dynlink.Error(e) -> log_error(Dynlink.error_message e) let skip_findlib = [ "unix"; "dynlink"; "findlib" ] let predicates = ref [ "byte" ] let loaded = ref [] let init_findlib_var = ref false let init_findlib() = if not !init_findlib_var then ( Findlib.init(); init_findlib_var := true ) let split_in_words s = (* Copy of Fl_split.in_words. splits s in words separated by commas and/or whitespace *) let l = String.length s in let rec split i j = if j < l then match s.[j] with (' '|'\t'|'\n'|'\r'|',') -> if i split i (j+1) else if i if not (List.mem pkg !loaded) then begin (* Determine the package directory: *) let d = Findlib.package_directory pkg in if not (List.mem pkg skip_findlib) then begin (* Determine the 'archive' property: *) let archive = try Findlib.package_property !predicates pkg "archive" with Not_found -> "" in (* Split the 'archive' property and load the files: *) let archives = split_in_words archive in List.iter (fun arch -> let arch' = Findlib.resolve_path ~base:d arch in reg_module_name := Some(String.capitalize(Filename.chop_extension (Filename.basename arch'))); try Dynlink.loadfile arch'; with Dynlink.Error(e) -> log_error(Dynlink.error_message e) ) archives; end; (* The package is loaded: *) loaded := pkg :: !loaded end ) eff_pkglist with | Findlib.No_such_package(name,_) -> log_error ("No such ocaml package: " ^ name) | Findlib.Package_loop name -> log_error ("Ocaml package loop: " ^ name) | Failure msg -> log_error ("Failure: " ^ msg) let cmd_thread _ = init_findlib(); let have_mt_support() = Findlib.package_property [] "threads" "type_of_threads" = "posix" in if not(List.mem "threads" !loaded) then ( (* This works only for POSIX threads. *) if have_mt_support() then ( predicates := ["mt"; "mt_posix"] @ !predicates; cmd_require "threads" ) else ( log_error "NetcgiThread: No support for threads" ) ) let cmd_predicates s = init_findlib(); let preds = split_in_words s in predicates := preds @ !predicates let cmd_translate_handler sconfig name = { sconfig with translate_handler = Some (Hashtbl.find reg_table name) } let cmd_check_user_id_handler dconfig name = { dconfig with check_user_id = Some (Hashtbl.find reg_table name) } let cmd_auth_checker_handler dconfig name = { dconfig with auth_checker = Some (Hashtbl.find reg_table name) } let cmd_access_checker_handler dconfig name = { dconfig with access_checker = Some (Hashtbl.find reg_table name) } let cmd_type_checker_handler dconfig name = { dconfig with type_checker = Some (Hashtbl.find reg_table name) } let cmd_fixer_upper_handler dconfig name = { dconfig with fixer_upper = Some (Hashtbl.find reg_table name) } let cmd_logger_handler dconfig name = { dconfig with logger = Some (Hashtbl.find reg_table name) } let cmd_header_parser_handler dconfig name = { dconfig with header_parser = Some (Hashtbl.find reg_table name) } let cmd_post_read_request_handler dconfig name = { dconfig with post_read_request = Some (Hashtbl.find reg_table name) } let cmd_handler dconfig name = { dconfig with ocaml_bytecode_handler = Some (Hashtbl.find reg_table name) } let () = let cb = Callback.register in cb "netcgi2_apache_cmd_load" cmd_load; cb "netcgi2_apache_cmd_require" cmd_require; cb "netcgi2_apache_cmd_thread" cmd_thread; cb "netcgi2_apache_cmd_predicates" cmd_predicates; cb "netcgi2_apache_cmd_translate_handler" cmd_translate_handler; cb "netcgi2_apache_cmd_check_user_id_handler" cmd_check_user_id_handler; cb "netcgi2_apache_cmd_auth_checker_handler" cmd_auth_checker_handler; cb "netcgi2_apache_cmd_access_checker_handler" cmd_access_checker_handler; cb "netcgi2_apache_cmd_type_checker_handler" cmd_type_checker_handler; cb "netcgi2_apache_cmd_fixer_upper_handler" cmd_fixer_upper_handler; cb "netcgi2_apache_cmd_logger_handler" cmd_logger_handler; cb "netcgi2_apache_cmd_header_parser_handler" cmd_header_parser_handler; cb "netcgi2_apache_cmd_post_read_request_handler" cmd_post_read_request_handler; cb "netcgi2_apache_cmd_handler" cmd_handler end (* module Handler ------------------------------------------------- *) (** Support for classes. Unless we use classes here, the support for classes will not be embedded in apache and loading Netcgi will fail. *) class _support__classes_ = object end (** There is no lazy.cma, lexing.cma, stream.cma,... to load. Reference these modules here to make sure they are included in the module hence the mod .so *) let _arg_parse_ = Arg.parse let _lazy_force_ = Lazy.force let _lexing_lexeme_ = Lexing.lexeme let _queue_create_ = Queue.create let _stack_create_ = Stack.create let _stream_sempty_ = Stream.sempty ocamlnet-4.1.2/src/netcgi2-apache/netcgi_modtpl.mli0000644000175000017500000001020712731530350020637 0ustar gerdgerd(* netcgi_modtpl.mli (C) 2005 Christophe Troestler This code may be used under either, the GNU GPL, or the same license as ocamlnet (see the file LICENSE). 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 file LICENSE for more details. *) (** @deprecated Mod_caml style of templates. This template module is * simple to use. It is here to provide a simple upgrade path from * mod_caml. It should not be considered as the default template * system of Netcgi. *) type var = | VarString of string (** ::tag:: *) | VarTable of table_row list (** ::table(tag):: *) | VarConditional of bool (** ::if(tag):: *) | VarCallback of (string list -> string) (** ::call(f, x1,...):: *) and table_row = (string * var) list (** Variables are either simple string, tables, conditionals or callbacks. A simple string is set with [template#set "name" s] where [s] will be automatically escaped depending on the declaration in the template: - [::name::] does no escaping; - [::name_url::] escapes for URL encoding, make it suitable in a link []; - [::name_html::] escapes for HTML display of the string; - [::name_html_tag::] escapes the string to make it suitable to be placed between quotes in an HTML tag, e.g. []; - [::name_html_textarea::] escapes the string to make it suitable to be placed between []. Tables are declared in the template by [::table(name)::] {i row template} [::end::]. The {i row template} can contain other variables. Calling [template#table "name" rows], where [rows] is a list [[row1, row2,...,rowN]], will insert [N] {i row templates} with each template having its variables set thanks to [row1],... each of which is an associative list name -> value (of type {!Template.table_row}). Conditionals are declared in the template by [::if(name) .. ::else:: .. ::end::] with the "else" clause being optional. Calling [template#conditional] sets up a conditional value. Calling [template#callback "fname" f] sets up the callback function declared by [::call(fname,arg1,...,argN)::] replacing the call by the value of [f] applied to the list [[arg1,...,argN]]. The string returned by [f] can be escaped by using suffices in the template as for simple tags: [::call(fname,arg1,...,argN)_html::],... A template may also include other templates with [::include(filename)::]. *) (** [new template ?filename tpl] computes a new template from the string [tpl]. Once the object has been created, it can be used in a single thread. @param filename if set, it is used to determine the base path for [::include()::] tags in the template (default: current directory) and to reuse the templates of already compiled files (e.g. headers, footers,...). *) class template : ?filename:string -> string -> object method set : string -> string -> unit (** Set a variable in the template. *) method table : string -> table_row list -> unit (** Set a table in the template. *) method conditional : string -> bool -> unit (** Set a conditional in the template. *) method callback : string -> (string list -> string) -> unit (** Set a callback in the template. *) method to_string : string (** Return the template as a string. *) method to_channel : out_channel -> unit (** Write the template to a channel. *) method output : Netcgi.cgi -> unit (** [output cgi] outputs the template to the CGI session [cgi]. *) method source : string (** Return the original source code for the template. *) end val template : string -> template (** Compile the template from a named file. Not thread safe. *) val template_from_string : ?filename:string -> string -> template (** Compile the template from a literal string. Not thread safe. *) val template_from_channel : ?filename:string -> in_channel -> template (** Compile the template from a channel. Not thread safe. *) ocamlnet-4.1.2/src/netcgi2-apache/drive-apxs0000755000175000017500000000102412731530350017311 0ustar gerdgerd#! /bin/sh # apxs is not fully compatible with the C compiler. In particular, -g # does not work as intended apxs="$1" shift options="" while [ $# -gt 0 ]; do case "$1" in -c|-W*|-I*|-L*,-l*) options="$options $1" shift ;; -o) options="$options -o $2" shift 2 ;; -*) options="$options -Wc,$1" shift ;; *) options="$options $1" shift ;; esac done echo "+ $apxs $options" exec "$apxs" $options ocamlnet-4.1.2/src/netcgi2-apache/Makefile.pre0000644000175000017500000000210012731530350017522 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PRE = 1 PKGNAME = netcgi2-apache GENERATE = config.h netcgi_apache_mod.ml META 500netcgi_apache.info INSTALL_EXTRA = netcgi_modtpl.cma 500netcgi_apache.info \ mod_netcgi_apache.so PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" config.h: config.h.in sed -e 's,@APACHE_LIBDIR@,$(APACHE_LIBDIR),g' \ -e 's,@PACKAGE@,$(PACKAGE),g' \ -e 's,@VERSION@,$(VERSION),g' \ -e 's,@APACHE_MAJOR@,$(APACHE_MAJOR),g' \ < $< > $@ netcgi_apache_mod.ml: netcgi_apache_mod.ml.in sed -e 's,@APACHE_OCAMLLIBDIR@,$(APACHE_OCAMLLIBDIR),g' \ -e 's,@PKGNAME@,$(PKGNAME),g' \ -e 's,@VERSION@,$(VERSION),g' \ -e 's,@APACHE_MAJOR@,$(APACHE_MAJOR),g' \ -e 's,@APACHE_LIBDIR@,$(APACHE_LIBDIR),g' \ < $< > $@ 500netcgi_apache.info: 500netcgi_apache.info.in sed -e 's,@APACHE_LIBDIR@,$(APACHE_LIBDIR),g' < $< > $@ include $(TOP_DIR)/Makefile.rules CLEAN_LIST += $(wildcard *.so) $(wildcard *.lo) $(wildcard *.slo) \ $(wildcard *.la) config.h netcgi_apache_mod.ml 500netcgi_apache.info clean:: test -d .libs && $(RM) -rf .libs/ ocamlnet-4.1.2/src/netcgi2-apache/netcgi_modtpl.ml0000644000175000017500000002656012731530350020477 0ustar gerdgerd(* netcgi_modtpl.ml (C) 2005 Christophe Troestler This code may be used under either, the GNU GPL, or the same license as ocamlnet (see the file LICENSE). 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 file LICENSE for more details. *) (* $Id: netcgi_modtpl.ml,v 1.4 2005/10/19 20:24:58 chris_77 Exp $ *) module Url = Netencoding.Url module Html = Netencoding.Html (* Escaping ***********************************************************************) type escape = EscapeNone | EscapeUrl | EscapeHtml | EscapeHtmlTag | EscapeHtmlTextarea let escape_html_textarea = Html.encode ~in_enc:`Enc_iso88591 ~unsafe_chars:Html.unsafe_chars_html4 () (* FIXME: The escaping functions below are limited -- they do not escape everything well. (?) *) let eol_re = Str.regexp "\r?\n" let escape_html str = let str = escape_html_textarea str in let str = Str.global_replace eol_re "
" str in str let escape_html_tag str = let str = escape_html_textarea str in let str = Str.global_replace eol_re " " str in str let escape = function | EscapeNone -> (fun str -> str) | EscapeUrl -> (fun s -> Url.encode s) (* XXX http://... are not well escaped *) | EscapeHtml -> escape_html | EscapeHtmlTag -> escape_html_tag | EscapeHtmlTextarea -> escape_html_textarea (* Inputting files ***********************************************************************) let input_whole_chan chan = let buf = Buffer.create 4096 in try while true do Buffer.add_string buf (input_line chan); Buffer.add_char buf '\n'; done; assert false with End_of_file -> Buffer.contents buf let input_whole_file filename = let fh = open_in filename in let contents = input_whole_chan fh in close_in fh; contents (* Compile templates ***********************************************************************) type compiled = node list and node = | Plain of string (* Just some text. *) | Var of escape * string (* ::tag:: *) | If of string * compiled * compiled (* ::if(..):: .. ::else:: .. ::end:: *) | Table of string * compiled (* ::table(..):: .. ::end:: *) | Call of escape * string * string list (* [prepend_rev l1 l2] = [List.rev l1 @ l2] *) let rec prepend_rev l1 l2 = match l1, l2 with | [], _ -> l2 | a :: tl, _ -> prepend_rev tl (a :: l2) (* If name has the form "_html" (or one of the similar cases), return bare name and the form of the escaping that needs to be applied. *) let get_var = let string_ends_with s sfx = let ls = String.length s and lsfx = String.length sfx in ls >= lsfx && String.sub s (ls - lsfx) lsfx = sfx in let suppress s sfx = String.sub s 0 (String.length s - String.length sfx) in fun name -> if string_ends_with name "_url" then Var(EscapeUrl, suppress name "_url") else if string_ends_with name "_html" then Var(EscapeHtml, suppress name "_html") else if string_ends_with name "_html_tag" then Var(EscapeHtmlTag, suppress name "_html_tag") else if string_ends_with name "_html_textarea" then Var(EscapeHtmlTextarea, suppress name "_html_textarea") else Var(EscapeNone, name) let delim_re = Str.regexp_string "::" let ident = "[ \t]*\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)[ \t]*" let var_re = Str.regexp("::" ^ ident ^"::") let if_re = Str.regexp("::if(" ^ ident ^ ")::") let else_re = Str.regexp_string "::else::" let end_re = Str.regexp_string "::end::" let table_re = Str.regexp("::table(" ^ ident ^ ")::") let include_re = (* We do not allow white space in filenames because it is too easy to get mistaken. *) Str.regexp("::include([ \t\r\n]*\\([^(): \t\r\n]+\\)[ \t\r\n]*)::") let call_re = Str.regexp("::call(" ^ ident ^ "\\(\\([ \t]*,[ \t]*[a-zA-Z_]+[a-zA-Z0-9_]*\\)*\\)[ \t]*)" ^ "\\([_a-z]*\\)::") let comma_re = Str.regexp "[ \t]*,[ \t]*" (* The compiled templates are not mutable. We keep a list of templates associated to filenames to reuse them if necessary (e.g. when including headers and footers). *) let compiled_templates = Hashtbl.create 5 (* Type of delimiters that ends the current level of recursion. *) type closing = | Else (* ::else:: *) | End (* ::end:: *) | Eos (* End of string *) let rec compile_template ~filename source = match filename with | None -> let ct, _, _ = compile (Sys.getcwd()) Sys.executable_name source (String.length source) 0 [] in ct | Some f -> try Hashtbl.find compiled_templates f with Not_found -> let ct, _, _ = compile (Filename.dirname f) (Filename.basename f) source (String.length source) 0 [] in Hashtbl.add compiled_templates f ct; ct (* [compile basename source len i0 ct] returns [(ct', closing, i)] where [ct'] is the compiled template, [closing] is the "token" closing that part and [i] is the position right after that token. [ct] is the compiled template SO FAR in REVERSE order. *) and compile basename filename source len i0 ct = try if i0 >= len then raise Not_found; let i = Str.search_forward delim_re source i0 in let ct = if i > i0 then Plain(String.sub source i0 (i - i0)) :: ct else ct in (* Check if any of the recognized constructs follows *) if Str.string_match end_re source i then (List.rev ct, End, Str.match_end()) else if Str.string_match else_re source i then (List.rev ct, Else, Str.match_end()) else if Str.string_match var_re source i then let ct = get_var(Str.matched_group 1 source) :: ct in compile basename filename source len (Str.match_end()) ct else if Str.string_match if_re source i then let cond = Str.matched_group 1 source in let i_end = Str.match_end() in let (ct_then, cl, i) = compile basename filename source len i_end [] in match cl with | Else -> let (ct_else, cl, i) = compile basename filename source len i [] in begin match cl with | End -> compile basename filename source len i (If(cond, ct_then, ct_else) :: ct) | _ -> failwith(filename ^ ": Missing ::end:: for ::if(" ^ cond ^ "):: ... ::else::") end | End -> compile basename filename source len i (If(cond, ct_then, []) :: ct) | Eos -> failwith(filename ^ ": Missing ::end:: for ::if(" ^ cond ^ ")::") else if Str.string_match table_re source i then let table = Str.matched_group 1 source in let i_end = Str.match_end() in let (ct_rows, cl, i) = compile basename filename source len i_end [] in match cl with | End -> compile basename filename source len i (Table(table, ct_rows) :: ct) | _ -> failwith(filename ^ ": Missing ::end:: for ::table(" ^ table ^ ")::") else if Str.string_match call_re source i then let fname = Str.matched_group 1 source in let args = Str.matched_group 2 source in let esc = match Str.matched_group 4 source with | "_url" -> EscapeUrl | "_html" -> EscapeHtml | "_html_tag" -> EscapeHtmlTag | "_html_textarea" -> EscapeHtmlTextarea | _ -> EscapeNone in let i_end = Str.match_end() in let ct = Call(esc, fname, Str.split comma_re args) :: ct in compile basename filename source len i_end ct else if Str.string_match include_re source i then let i_filename = Str.matched_group 1 source in let i_end = Str.match_end() in let i_filename = if Filename.is_relative i_filename then Filename.concat basename i_filename else i_filename in let i_source = input_whole_file i_filename in let i_ct = compile_template ~filename:(Some i_filename) i_source in compile basename filename source len i_end (prepend_rev i_ct ct) else (* Skip "::" and look for the next one *) (* compile basename filename source len (i + 2) (Plain "::" :: ct) *) (* Error! *) failwith("Netcgi_modtpl (" ^ filename ^ "): Unrecognized " ^ (if i + 20 < String.length source then String.sub source i 20 ^ "..." else String.sub source i (String.length source - i))) with Not_found -> let ct = if len > i0 then Plain(String.sub source i0 (len - i0)) :: ct else ct in (List.rev ct, Eos, len) (* Set variables and output the template ***********************************************************************) type var = | VarString of string (* ::tag:: *) | VarTable of table_row list (* ::table(tag):: *) | VarConditional of bool (* ::if(tag):: *) | VarCallback of (string list -> string) (* ::call(f, x1,...):: *) and table_row = (string * var) list let find fname bindings k = try Hashtbl.find bindings k with Not_found -> failwith("Netcgi_modtpl (" ^ fname ^ "): tag/table ::" ^ k ^ ":: was not assigned any value.") class template ?filename source = let bindings = Hashtbl.create 5 in let fname = match filename with | None -> Sys.executable_name | Some f -> Filename.basename f in let resolve_variable name = match find fname bindings name with | VarString str -> str | _ -> failwith ("Netcgi_modtpl (" ^ fname ^ "): ::" ^ name ^ ":: should be a simple string tag.") and eval_condition name = match find fname bindings name with | VarConditional b -> b | _ -> failwith ("Netcgi_modtpl (" ^ fname ^ "): ::if(" ^ name ^ "):: should be a conditional tag.") and resolve_table name = match find fname bindings name with | VarTable tbl -> tbl | _ -> failwith ("Netcgi_modtpl (" ^ fname ^ "): ::table(" ^ name ^ "):: should be a table tag.") and resolve_callback name = match find fname bindings name with | VarCallback f -> f | _ -> failwith ("Netcgi_modtpl (" ^ fname ^ "): ::call(" ^ name ^ "[,...]):: should be a callback function.") in let rec substitute ct (out:string -> unit) = let out_node = function | Plain text -> out text | Var(esc, name) -> out(escape esc (resolve_variable name)) | If(cond, then_clause, else_clause) -> substitute (if eval_condition cond then then_clause else else_clause) out | Table(name, body) -> (* For each table [row], add the corresponding bindings, process the table body and then remove them. *) let process_row row = List.iter (fun (k, v) -> Hashtbl.add bindings k v) row; substitute body out; List.iter (fun (k, v) -> Hashtbl.remove bindings k) row; in List.iter process_row (resolve_table name); | Call(esc, fname, args) -> out(escape esc (resolve_callback fname args)) in List.iter out_node ct in let output = substitute (compile_template ?filename source) in object(self) method set name value = Hashtbl.add bindings name (VarString value) method table name tbl = Hashtbl.add bindings name (VarTable tbl) method conditional name cond = Hashtbl.add bindings name (VarConditional cond) method callback name f = Hashtbl.add bindings name (VarCallback f) method to_string = let buffer = Buffer.create 4096 in output (Buffer.add_string buffer); Buffer.contents buffer method to_channel chan = output (output_string chan) method source = source method output (cgi:Netcgi.cgi) = output (cgi#out_channel#output_string) end let template_from_string ?filename source = new template ?filename source let template_from_channel ?filename chan = template_from_string ?filename (input_whole_chan chan) let template filename = template_from_string ~filename (input_whole_file filename) ocamlnet-4.1.2/src/netcgi2-apache/config.h.in0000644000175000017500000000221112731530350017323 0ustar gerdgerd/* Configuration file. -*-c-*- * Copyright (C) 2003 Merjis Ltd. * Copyright (C) 2007 Troestler Ch. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: config.h.in,v 1.1 2003/09/07 19:41:14 rwmj Exp $ */ #ifndef mod_caml_config_h #define mod_caml_config_h #define APACHE_LIBDIR "@APACHE_LIBDIR@" #define PACKAGE "@PACKAGE@" #define VERSION "@VERSION@" #define APACHE_MAJOR @APACHE_MAJOR@ #if APACHE_MAJOR == 2 #define APACHE2 1 #endif #endif /* mod_caml_config_h */ ocamlnet-4.1.2/src/netcgi2-apache/netcgi_apache_mod.mli0000644000175000017500000001737112731530350021431 0ustar gerdgerd(* netcgi_apache.mli Copyright (C) 2005-2006 Christophe Troestler email: Christophe.Troestler@umh.ac.be WWW: http://math.umh.ac.be/an/ This library is free software; see the file LICENSE for more information. 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 file LICENSE for more details. *) module Conf : sig val package : string val version : string val apache_libdir : string val apache_major : int val gateway_interface : string val server_software : string end module Raw_Apache : sig (** See {!Netcgi_apache.Apache.Table} *) module Table : sig type t (** Apache [table] structure. *) external get : t -> string -> string = "netcgi2_apache_table_get" external get_all : t -> string -> string list = "netcgi2_apache_table_get_all" external fields : t -> (string * string) list = "netcgi2_apache_table_fields" external clear : t -> unit = "netcgi2_apache_table_clear" external set : t -> string -> string -> unit = "netcgi2_apache_table_set" external add : t -> string -> string -> unit = "netcgi2_apache_table_add" external unset : t -> string -> unit = "netcgi2_apache_table_unset" end (** See {!Netcgi_apache.Apache.Server} *) module Server : sig type t (** Apache [server_rec] structure. *) external hostname : t -> string = "netcgi2_apache_server_hostname" external admin : t -> string = "netcgi2_apache_server_admin" external is_virtual : t -> bool = "netcgi2_apache_server_is_virtual" end (** See {!Netcgi_apache.Apache.Connection} *) module Connection : sig type t (** Apache [conn_rec] structure. *) external remote_ip : t -> string = "netcgi2_apache_connection_remote_ip" external remote_host : t -> string = "netcgi2_apache_connection_remote_host" end (** See {!Netcgi_apache.Apache.Request} *) module Request : sig type t (** Apache [request_rec] structure. *) external connection : t -> Connection.t = "netcgi2_apache_request_connection" external server : t -> Server.t = "netcgi2_apache_request_server" external next : t -> t = "netcgi2_apache_request_next" external prev : t -> t = "netcgi2_apache_request_prev" external main : t -> t = "netcgi2_apache_request_main" external the_request : t -> string = "netcgi2_apache_request_the_request" external assbackwards : t -> bool = "netcgi2_apache_request_assbackwards" external header_only : t -> bool = "netcgi2_apache_request_header_only" external protocol : t -> string = "netcgi2_apache_request_protocol" external proto_num : t -> int = "netcgi2_apache_request_proto_num" external hostname : t -> string = "netcgi2_apache_request_hostname" external request_time : t -> float = "netcgi2_apache_request_request_time" external status_line : t -> string = "netcgi2_apache_request_status_line" external set_status_line : t -> string -> unit = "netcgi2_apache_request_set_status_line" external status : t -> int = "netcgi2_apache_request_status" external set_status : t -> int -> unit = "netcgi2_apache_request_set_status" external method_name : t -> string = "netcgi2_apache_request_method" val method_number : t -> [ `GET | `PUT | `POST | `DELETE | `CONNECT | `OPTIONS | `TRACE | `PATCH | `PROPFIND | `PROPPATCH | `MKCOL | `COPY | `MOVE | `LOCK | `UNLOCK | `INVALID ] external headers_in : t -> Table.t = "netcgi2_apache_request_headers_in" external headers_out : t -> Table.t = "netcgi2_apache_request_headers_out" external err_headers_out : t -> Table.t = "netcgi2_apache_request_err_headers_out" external subprocess_env : t -> Table.t = "netcgi2_apache_request_subprocess_env" external notes : t -> Table.t = "netcgi2_apache_request_notes" external content_type : t -> string = "netcgi2_apache_request_content_type" external set_content_type : t -> string -> unit = "netcgi2_apache_request_set_content_type" external uri : t -> string = "netcgi2_apache_request_uri" external port : t -> int = "netcgi2_apache_request_port" external set_uri : t -> string -> unit = "netcgi2_apache_request_set_uri" external filename : t -> string = "netcgi2_apache_request_filename" external set_filename : t -> string -> unit = "netcgi2_apache_request_set_filename" external path_info : t -> string = "netcgi2_apache_request_path_info" external set_path_info : t -> string -> unit = "netcgi2_apache_request_set_path_info" external args : t -> string = "netcgi2_apache_request_args" external set_args : t -> string -> unit = "netcgi2_apache_request_set_args" external finfo : t -> Unix.stats option = "netcgi2_apache_request_finfo" type read_policy = | NO_BODY | CHUNKED_ERROR | CHUNKED_DECHUNK | CHUNKED_PASS external setup_client_block : t -> read_policy -> int = "netcgi2_apache_request_setup_client_block" external should_client_block : t -> bool = "netcgi2_apache_request_should_client_block" external get_client_block : t -> string = "netcgi2_apache_request_get_client_block" external get_client_block_buffer : t -> Bytes.t -> int -> int -> int = "netcgi2_apache_request_get_client_block_buffered" external discard_request_body : t -> int = "netcgi2_apache_request_discard_request_body" external user : t -> string = "netcgi2_apache_request_user" external auth_type : t -> string = "netcgi2_apache_auth_type" external note_auth_failure : t -> unit = "netcgi2_apache_request_note_auth_failure" external note_basic_auth_failure : t -> unit = "netcgi2_apache_request_note_basic_auth_failure" external note_digest_auth_failure : t -> unit = "netcgi2_apache_request_note_digest_auth_failure" external get_basic_auth_pw : t -> int * string option = "netcgi2_apache_request_get_basic_auth_pw" external send_http_header : t -> unit = "netcgi2_apache_request_send_http_header" external rflush : t -> int = "netcgi2_apache_request_rflush" external internal_redirect : string -> t -> unit = "netcgi2_apache_request_internal_redirect" external internal_redirect_handler : string -> t -> unit = "netcgi2_apache_request_internal_redirect_handler" external print_char : t -> char -> unit = "netcgi2_apache_request_print_char" val print_string : t -> string -> unit (** Send a string back to the client. *) val output : t -> Bytes.t -> int -> int -> int (** [output r s ofs len] send [s[ofs .. len-1]] back to the client. Returns the number of bytes actually written, which is smaller than the number of bytes in the string if there was a failure. *) val print_int : t -> int -> unit (** Send a decimal number back to the client. *) val print_float : t -> float -> unit (** Send a floating-point number back to the client. *) val print_newline : t -> unit (** Send a CR LF back to the client. *) val print_endline : t -> string -> unit (** Send a string followed by CR LF back to the client. *) external register_cleanup : t -> (unit -> unit) -> unit = "netcgi2_apache_request_register_cleanup" (** Register a cleanup function which is called when the current request cycle ends. *) end end module Handler : sig (** See {!Netcgi_apache.Handler.result}. *) type result = | OK | DECLINED | DONE | HTTP of int type t = Raw_Apache.Request.t -> result (** See {!Netcgi_apache.Handler.t}. *) val register : t -> string -> unit (** See {!Netcgi_apache.Handler.register}. *) end ocamlnet-4.1.2/src/netcgi2-apache/netcgi_apache.mli0000644000175000017500000004313712731530350020571 0ustar gerdgerd(* netcgi_apache.mli Copyright (C) 2005-2006 Christophe Troestler email: Christophe.Troestler@umh.ac.be WWW: http://math.umh.ac.be/an/ This library is free software; see the file LICENSE for more information. 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 file LICENSE for more details. *) (** Netcgi Apache "mod" connector. * * See the {!Netcgi_mod.setup} section at the end of this file to know * how to configure Apache. *) (** Interface to Apache API. *) module Apache : sig module Table : sig type t (** Apache [table] structure. *) external get : t -> string -> string = "netcgi2_apache_table_get" (** [Table.get tbl key] returns the corresponding entry in the table. The [key] is matched case-insensitively. The first key will retrieved in case there are more than one entry in the table for the key. @raise Not_found otherwise. *) external get_all : t -> string -> string list = "netcgi2_apache_table_get_all" (** [Table.get_all tbl key] same as [Table.get tbl key] except it returns all values corresponding to the [key]. *) external fields : t -> (string * string) list = "netcgi2_apache_table_fields" (** [Table.fields tbl] returns a list of [(key, value)] pairs consisting of all entries of the table [tbl]. *) external clear : t -> unit = "netcgi2_apache_table_clear" (** [Table.clear tbl] removes all key/value pairs from the table [tbl]. *) external set : t -> string -> string -> unit = "netcgi2_apache_table_set" (** [Table.set tbl key value] sets the [(key, value)] pair in the table [tbl]. If one or more key/value pairs already exists with the same key they will be deleted and replaced with [(key, value)]. *) external add : t -> string -> string -> unit = "netcgi2_apache_table_add" (** [Table.add tbl key value] adds the [(key, value)] pair in the table [tbl]. This does not erase any existing pairs. *) external unset : t -> string -> unit = "netcgi2_apache_table_unset" (** [Table.unset tbl key] delete every key/value pair associated with the [key] from the table [tbl]. *) end module Server : sig type t (** Apache [server_rec] structure. *) external hostname : t -> string = "netcgi2_apache_server_hostname" (** [server_hostname] field (as declared in Apache configuration file). @raise Not_found if NULL. *) external admin : t -> string = "netcgi2_apache_server_admin" (** [server_admin] field. @raise Not_found if NULL. *) external is_virtual : t -> bool = "netcgi2_apache_server_is_virtual" (** [is_virtual] field. @raise Not_found if NULL. *) end module Connection : sig type t (** Apache [conn_rec] structure. *) external remote_ip : t -> string = "netcgi2_apache_connection_remote_ip" (** [conn_rec] [remote_ip] field. @raise Not_found if NULL. *) external remote_host : t -> string = "netcgi2_apache_connection_remote_host" (** [conn_rec] [remote_host] field. @raise Not_found if NULL. *) end module Request : sig type t (** Apache [request_rec] structure. *) external connection : t -> Connection.t = "netcgi2_apache_request_connection" (** [request_rec] [connection] field. *) external server : t -> Server.t = "netcgi2_apache_request_server" (** [request_rec] [server] field. *) external next : t -> t = "netcgi2_apache_request_next" (** [request_rec] [next] field. @raise Not_found if NULL. *) external prev : t -> t = "netcgi2_apache_request_prev" (** [request_rec] [prev] field. @raise Not_found if NULL. *) external main : t -> t = "netcgi2_apache_request_main" (** [request_rec] [main] field. @raise Not_found if NULL. *) external the_request : t -> string = "netcgi2_apache_request_the_request" (** [request_rec] [the_request] field. @raise Not_found if NULL. *) external assbackwards : t -> bool = "netcgi2_apache_request_assbackwards" (** [request_rec] [assbackwards] field; [true] if HTTP/0.9, "simple" request. *) external header_only : t -> bool = "netcgi2_apache_request_header_only" (** [request_rec] [header_only] field. It is [true] when the request method is HEAD. *) external protocol : t -> string = "netcgi2_apache_request_protocol" (** [request_rec] [protocol] field. @raise Not_found if NULL. *) external proto_num : t -> int = "netcgi2_apache_request_proto_num" (** [request_rec] [proto_num] field. Number version of protocol; 1.1 = 1001 *) external hostname : t -> string = "netcgi2_apache_request_hostname" (** [request_rec] [hostname] field -- hostname to which the request was made. @raise Not_found if NULL. *) external request_time : t -> float = "netcgi2_apache_request_request_time" (** [request_rec] [request_time] field. *) external status_line : t -> string = "netcgi2_apache_request_status_line" (** [request_rec] [status_line] field. @raise Not_found if NULL. *) external set_status_line : t -> string -> unit = "netcgi2_apache_request_set_status_line" (** Set [request_rec] [status_line] field. *) external status : t -> int = "netcgi2_apache_request_status" (** [request_rec] [status] field. *) external set_status : t -> int -> unit = "netcgi2_apache_request_set_status" (** Set [request_rec] [status] field. *) external method_name : t -> string = "netcgi2_apache_request_method" (** [request_rec] [method] field. *) val method_number : t -> [ `GET | `PUT | `POST | `DELETE | `CONNECT | `OPTIONS | `TRACE | `PATCH | `PROPFIND | `PROPPATCH | `MKCOL | `COPY | `MOVE | `LOCK | `UNLOCK | `INVALID ] (** [request_rec] [method_number] field (given symbolically instead of a number). *) external headers_in : t -> Table.t = "netcgi2_apache_request_headers_in" (** [request_rec] [headers_in] field. *) external headers_out : t -> Table.t = "netcgi2_apache_request_headers_out" (** [request_rec] [headers_out] field. *) external err_headers_out : t -> Table.t = "netcgi2_apache_request_err_headers_out" (** [request_rec] [err_headers_out] field. *) external subprocess_env : t -> Table.t = "netcgi2_apache_request_subprocess_env" (** [request_rec] [subprocess_env] field. *) external notes : t -> Table.t = "netcgi2_apache_request_notes" (** [request_rec] [notes] field. *) external content_type : t -> string = "netcgi2_apache_request_content_type" (** [request_rec] [content_type] field. @raise Not_found if NULL. *) external set_content_type : t -> string -> unit = "netcgi2_apache_request_set_content_type" (** Set [request_rec] [content_type] field. *) external uri : t -> string = "netcgi2_apache_request_uri" (** [request_rec] [uri] field. @raise Not_found if NULL. *) external port : t -> int = "netcgi2_apache_request_port" (** Server port. *) external set_uri : t -> string -> unit = "netcgi2_apache_request_set_uri" (** Set [request_rec] [uri] field. *) external filename : t -> string = "netcgi2_apache_request_filename" (** [request_rec] [filename] field. @raise Not_found if NULL. *) external set_filename : t -> string -> unit = "netcgi2_apache_request_set_filename" (** Set [request_rec] [filename] field. *) external path_info : t -> string = "netcgi2_apache_request_path_info" (** [request_rec] [path_info] field. @raise Not_found if NULL. *) external set_path_info : t -> string -> unit = "netcgi2_apache_request_set_path_info" (** Set [request_rec] [path_info] field. *) external args : t -> string = "netcgi2_apache_request_args" (** [request_rec] [args] field. @raise Not_found if NULL. *) external set_args : t -> string -> unit = "netcgi2_apache_request_set_args" (** Set [request_rec] [args] field. *) external finfo : t -> Unix.stats option = "netcgi2_apache_request_finfo" (** [request_rec] [finfo] field. *) (** Policy to apply by [setup_client_block] if the request message indicates a body. *) type read_policy = | NO_BODY (** Send 413 error if message has any body *) | CHUNKED_ERROR (** Send 411 error if body without Content-Length *) | CHUNKED_DECHUNK (** If chunked, remove the chunks for me. *) | CHUNKED_PASS (** Pass the chunks to me without removal. *) val setup_client_block : t -> read_policy -> unit (** Setup for reading client request. @raise Netcgi_common.HTTP in case of problems. *) external should_client_block : t -> bool = "netcgi2_apache_request_should_client_block" (** Returns true if there is any client request data. *) val get_client_block : t -> string (** Get client request data. @raise Netcgi_common.HTTP in case of reading error. *) val get_client_block_buf : t -> Bytes.t -> int -> int -> int (** [get_client_block_buf r buf ofs len] read a chunk of data and puts it in [buf.[ofs .. ofs+len-1]]. The return value [i] is the number of bytes actually read -- thus only [buf.[ofs .. ofs+i-1]] is meaningful. @raise Netcgi_common.HTTP in case of reading error. *) val discard_request_body : t -> unit (** Discard client request body. @raise Netcgi_common.HTTP in case of problems. *) external user : t -> string = "netcgi2_apache_request_user" (** The authenticated user. @raise Not_found if NULL. *) external auth_type : t -> string = "netcgi2_apache_auth_type" external note_auth_failure : t -> unit = "netcgi2_apache_request_note_auth_failure" (** Set headers to tell browser that authentication failed. *) external note_basic_auth_failure : t -> unit = "netcgi2_apache_request_note_basic_auth_failure" (** Set headers to tell browser that basic authentication failed. *) external note_digest_auth_failure : t -> unit = "netcgi2_apache_request_note_digest_auth_failure" (** Set headers to tell browser that digest authentication failed. *) val get_basic_auth_pw : t -> string option (** Get the password sent in basic authentication. @raise Netcgi_common.HTTP in case of problems. *) external internal_redirect : string -> t -> unit = "netcgi2_apache_request_internal_redirect" (** Internally redirects immediately to [uri]. *) external internal_redirect_handler : string -> t -> unit = "netcgi2_apache_request_internal_redirect_handler" (** Internally redirects immediately to [uri] using handler specified by [r]. *) external send_http_header : t -> unit = "netcgi2_apache_request_send_http_header" (** Send the HTTP headers. Note that you must set the Status and Content-Type with [set_status] and [set_content_type] respectively. *) val rflush : t -> unit (** Flush any buffered data waiting to be written to the client. @raise End_of_file if it is not possible. *) external print_char : t -> char -> unit = "netcgi2_apache_request_print_char" (** Send a character back to the client. *) val print_string : t -> string -> unit (** Send a string back to the client. *) val output : t -> Bytes.t -> int -> int -> int (** [output r s ofs len] send [s[ofs .. len-1]] back to the client. Returns the number of bytes actually written, which is smaller than the number of bytes in the string if there was a failure. *) val print_int : t -> int -> unit (** Send a decimal number back to the client. *) val print_float : t -> float -> unit (** Send a floating-point number back to the client. *) val print_newline : t -> unit (** Send a CR LF back to the client. *) val print_endline : t -> string -> unit (** Send a string followed by CR LF back to the client. *) external register_cleanup : t -> (unit -> unit) -> unit = "netcgi2_apache_request_register_cleanup" (** Register a cleanup function which is called when the current request cycle ends. *) end end (* ---------------------------------------------------------------------- *) (** Registering Apache handlers. *) module Handler : sig type result = | OK (** This stage of request processing was handled successfully. *) | DECLINED (** No erroneous condition exists, but the module declines to handle the phase; the server tries to find another. *) | DONE (** The request is completely satisfied. *) | HTTP of int (** The request returns the HTTP status code given as argument. *) type t = Apache.Request.t -> result (** The type of handler functions. The exception [Exit] is considered as a normal way of terminating early. All other exceptions are logged and result in an Internal_server_error response by Apache. *) val register : t -> string -> unit (** Modules may call [register fn name] to register one or more handler functions. The handler functions are then referred to in the [Netcgi*Handler] configuration commands as [Module_name.name] where [Module_name] is derived from the filename (given to the [NetcgiLoad] directive) and [name] is the string passed here. *) end (* ---------------------------------------------------------------------- *) open Netcgi (** The usual [cgi] class with an additional method to access Apache specificities. *) class type cgi = object inherit Netcgi.cgi method request : Apache.Request.t (** The underlying apache request structure. *) end val run : ?config:config -> ?output_type:output_type -> ?arg_store:arg_store -> ?exn_handler:exn_handler -> (cgi -> unit) -> unit (** [run f] register the function [f] as a main function of the script. Each call to the script will execute [f cgi]. The code outside [f] will be executed only once (when the script is loaded into memory) which allows to cache database connections, etc. (The code stays in memory unless you restart the server or the file changes on disk.) @param config Default: {!Netcgi.default_config} @param output_type Default: [`Direct ""] @param arg_store Default: [`Automatic] for all arguments. @param exn_handler See {!Netcgi.exn_handler}. Default: delegate all exceptions to the default handler. *) (* ---------------------------------------------------------------------- *) (** {2:setup Setup} {3 Apache 1.3} You need to put in an Apache configuration file (we recommend /etc/apache/conf.d/netcgi_apache.conf) the following lines: {v LoadModule netcgi_module /usr/lib/apache/1.3/mod_netcgi_apache.so NetcgiRequire netcgi2-apache v} {3 Apache 2.2 or later} You need to put in an Apache configuration file (we recommend /etc/apache2/mods-available/netcgi_apache.load) the following line: {v LoadModule netcgi_module /usr/lib/apache2/modules/mod_netcgi_apache.so NetcgiRequire netcgi2-apache v} and make a symbolic link from /etc/apache2/mods-enabled/ to it to actually enable it. Subsequent configuration is recommended to be in /etc/apache2/mods-available/netcgi_apache.conf (also to be linked to /etc/apache2/mods-enabled/). {3 Loading libraries} If your scripts depend on other libraries, you need to load them using [NetcgiLoad]. More specifically, if your library is x.cma and is in the subdirectory y of standard OCaml directory (given by `ocamlc -where`), use {v NetcgiLoad y/x.cma v} If x.cma is not in a subdirectory of `ocamlc -where`, you need to specify the full path. {3 Interaction with findlib} Libraries managed with findlib are specially supported. In order to load a library "lib" just use {v NetcgiRequire lib v} Findlib-managed libraries are automatically found. For special configurations one can also set Findlib predicates: {v NetcgiPredicates p1,p2,p3,... v} {3 Multi-threading} If you need multi-threading call {v NetcgiThread v} as the very first directive after [LoadModule], even before [NetcgiRequire netcgi2-apache] (otherwise a number of critical sections remain unprotected in Ocamlnet, and you'll experience crashes). {3 Installing scripts} You need also to tell Apache how to detect whether a script is to be handled by netcgi_apache, either by putting them in a special directory (here /caml-bin/): {v Alias /caml-bin/ /path/to/your/scripts/ SetHandler ocaml-bytecode NetcgiHandler Netcgi_apache.bytecode Options ExecCGI Allow from all v} or by distinguishing them by their extension (here [.cma]): {v NetcgiHandler Netcgi_apache.bytecode AddHandler ocaml-bytecode .cma v} {3 Compiling scripts} If your script reside in the file [x.ml], compile it to [x.cmo] or [x.cma]. If your script depends on other libraries, you may either load them with [NetcgiLoad] (see above) or include them in [x.cma]. You need not include the [netcgi_apache.cma], [netcgi.cma], [netstring.cma], [netsys.cma], or [pcre.cma] modules as these are already loaded into Apache (see above). *) ocamlnet-4.1.2/src/netcgi2-apache/wrappers.c0000644000175000017500000000256212731530350017320 0ustar gerdgerd/* Wrappers around data structures. * Copyright (C) 2003 Merjis Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: wrappers.c,v 1.1 2003/09/07 19:41:14 rwmj Exp $ */ #include #include #include #include "wrappers.h" value Val_voidptr (void *ptr) { value rv = alloc (1, Abstract_tag); /* XXX Is this correct? */ Field(rv, 0) = (value) ptr; return rv; } value Val_optstring (const char *str) { if (str) /* Return "Some str". */ { CAMLparam0(); CAMLlocal2(rv, s); s = copy_string (str); rv = alloc_small (1, 0); Field(rv, 0) = s; CAMLreturn(rv); } else /* Return "None". */ return Val_int (0); } ocamlnet-4.1.2/src/netcgi2-apache/apache.c0000644000175000017500000005304312731530350016676 0ustar gerdgerd/* Apache "mod" interface. * Copyright (C) 2003 Merjis Ltd. * Copyright (C) 2007 Christophe Troestler * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This is a fork from mod_caml cleaned up and tailored to Netcgi2. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #if APACHE2 #include #include #include #endif #include "wrappers.h" #if !(APACHE2) /* Apache 1 */ #define apr_pstrdup ap_pstrdup #define apr_palloc ap_palloc #define apr_table_clear ap_clear_table #define apr_table_get ap_table_get #define apr_table_set ap_table_set #define apr_table_unset ap_table_unset #define apr_table_add ap_table_add #define apr_table_do ap_table_do #endif extern module netcgi_module; /*----- Tables. -----*/ CAMLprim value netcgi2_apache_table_clear(value tv) { CAMLparam1(tv); table *t = Table_val(tv); apr_table_clear(t); CAMLreturn(Val_unit); } CAMLprim value netcgi2_apache_table_get (value tv, value str) { CAMLparam2(tv, str); table *t = Table_val (tv); const char *res = apr_table_get(t, String_val (str)); if (res) CAMLreturn (copy_string (res)); else raise_not_found (); } static int netcgi2_apache_table_get_loop(void *res, const char *key, const char *val) { CAMLparam0(); CAMLlocal1(cons); /* head cell of new list */ cons = alloc(2, 0); /* :: */ Store_field(cons, 0, copy_string(val)); /* value :: */ Store_field(cons, 1, *((value *) res)); /* :: previous list */ *((value *) res) = cons; CAMLreturn(1); } CAMLprim value netcgi2_apache_table_get_all(value tv, value str) { CAMLparam2(tv, str); CAMLlocal1(res); /* list */ table *t = Table_val(tv); char *key = String_val(str); res = Val_int(0); /* empty list [] */ /* Only iterates over values associated with [key]. */ apr_table_do(&netcgi2_apache_table_get_loop, &res, t, key, NULL); CAMLreturn(res); } static int netcgi2_apache_table_fields_loop(void *res, const char *key, const char *val) { CAMLparam0(); CAMLlocal2(cons, pair); pair = alloc_tuple(2); /* (,) */ Store_field(pair, 0, copy_string(key)); Store_field(pair, 1, copy_string(val)); /* fprintf(stderr, "(%s, %s)\n", key, val); /\* DEBUG *\/ */ cons = alloc(2, 0); /* :: */ Store_field(cons, 0, pair); /* pair :: */ Store_field(cons, 1, *((value *) res)); /* :: list */ *((value *) res) = cons; CAMLreturn(1); } CAMLprim value netcgi2_apache_table_fields(value tv) { CAMLparam1(tv); CAMLlocal1(res); /* list */ table *t = Table_val(tv); res = Val_int(0); /* empty list [] */ /* Only iterates over *all* values of the table. */ apr_table_do(&netcgi2_apache_table_fields_loop, &res, t, NULL); CAMLreturn(res); } CAMLprim value netcgi2_apache_table_set (value tv, value key, value val) { CAMLparam3 (tv, key, val); table *t = Table_val (tv); apr_table_set(t, String_val (key), String_val (val)); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_table_add (value tv, value key, value val) { CAMLparam3 (tv, key, val); table *t = Table_val (tv); apr_table_add (t, String_val (key), String_val (val)); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_table_unset (value tv, value key) { CAMLparam2 (tv, key); table *t = Table_val (tv); apr_table_unset (t, String_val (key)); CAMLreturn (Val_unit); } /*----- Server structure. -----*/ CAMLprim value netcgi2_apache_server_hostname (value sv) { CAMLparam1(sv); server_rec *s = Server_rec_val(sv); if (s->server_hostname) CAMLreturn(copy_string(s->server_hostname)); else raise_not_found (); } CAMLprim value netcgi2_apache_server_admin(value sv) { CAMLparam1(sv); server_rec *s = Server_rec_val(sv); if (s->server_admin) CAMLreturn(copy_string(s->server_admin)); else raise_not_found(); } CAMLprim value netcgi2_apache_server_is_virtual(value sv) { CAMLparam1(sv); server_rec *s = Server_rec_val(sv); CAMLreturn(Val_bool(s->is_virtual)); } /*----- Connection structure. -----*/ #define CONNECTION(suffix,field) \ CAMLprim value \ netcgi2_apache_connection_ ## suffix (value cv) \ { \ CAMLparam1 (cv); \ conn_rec *c = Conn_rec_val (cv); \ if (c->field) \ CAMLreturn (copy_string (c->field)); \ else \ raise_not_found (); \ } #if AP_SERVER_MAJORVERSION_NUMBER == 1 CONNECTION(remote_ip, remote_ip) #else #if AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER < 3 CONNECTION(remote_ip, remote_ip) #else /* Apache-2.4 and up: remote_ip is now available in two variants: client_ip is the IP of the client (possibly a proxy), and useragent_ip is the IP of the user agent (by trusting an http field that was added by the proxy if there is a proxy) */ CONNECTION(remote_ip, client_ip) #endif #endif CONNECTION(remote_host, remote_host) /*----- Request structure. -----*/ CAMLprim value netcgi2_apache_request_connection (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_conn_rec (r->connection)); } CAMLprim value netcgi2_apache_request_server (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_server_rec (r->server)); } CAMLprim value netcgi2_apache_request_next (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv), *rr = r->next; if (rr) CAMLreturn (Val_request_rec (rr)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_prev (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv), *rr = r->prev; if (rr) CAMLreturn (Val_request_rec (rr)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_main (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv), *rr = r->main; if (rr) CAMLreturn (Val_request_rec (rr)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_the_request (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); if (r->the_request) CAMLreturn (copy_string (r->the_request)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_assbackwards (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_bool (r->assbackwards)); } CAMLprim value netcgi2_apache_request_header_only (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_bool (r->header_only)); } CAMLprim value netcgi2_apache_request_protocol (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); if (r->protocol) CAMLreturn (copy_string (r->protocol)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_proto_num (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_int (r->proto_num)); } CAMLprim value netcgi2_apache_request_hostname (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); if (r->hostname) CAMLreturn (copy_string (r->hostname)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_request_time (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (copy_double ((double) r->request_time)); } CAMLprim value netcgi2_apache_request_status_line (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); if (r->status_line) CAMLreturn (copy_string (r->status_line)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_set_status_line (value rv, value str) { CAMLparam2 (rv, str); request_rec *r = Request_rec_val (rv); r->status_line = apr_pstrdup (r->pool, String_val (str)); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_status (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_int (r->status)); } CAMLprim value netcgi2_apache_request_set_status (value rv, value i) { CAMLparam2 (rv, i); request_rec *r = Request_rec_val (rv); r->status = Int_val (i); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_method (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (copy_string (r->method)); } CAMLprim value netcgi2_apache_request_method_number (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_int (r->method_number)); } CAMLprim value netcgi2_apache_request_headers_in (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_table (r->headers_in)); } CAMLprim value netcgi2_apache_request_headers_out (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_table (r->headers_out)); } CAMLprim value netcgi2_apache_request_err_headers_out (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_table (r->err_headers_out)); } CAMLprim value netcgi2_apache_request_subprocess_env (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_table (r->subprocess_env)); } CAMLprim value netcgi2_apache_request_notes (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_table (r->notes)); } CAMLprim value netcgi2_apache_request_content_type (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); if (r->content_type) CAMLreturn (copy_string (r->content_type)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_set_content_type (value rv, value str) { CAMLparam2 (rv, str); request_rec *r = Request_rec_val (rv); r->content_type = apr_pstrdup (r->pool, String_val (str)); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_user (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); #if APACHE2 if (r->user) CAMLreturn (copy_string (r->user)); #else if (r->connection->user) CAMLreturn (copy_string (r->connection->user)); #endif else raise_not_found (); } CAMLprim value netcgi2_apache_request_uri (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); if (r->uri) CAMLreturn (copy_string (r->uri)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_port(value rv) { CAMLparam1(rv); request_rec *r = Request_rec_val (rv); CAMLreturn(Val_int(ap_get_server_port(r))); } CAMLprim value netcgi2_apache_request_set_uri (value rv, value str) { CAMLparam2 (rv, str); request_rec *r = Request_rec_val (rv); r->uri = apr_pstrdup (r->pool, String_val (str)); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_filename (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); if (r->filename) CAMLreturn (copy_string (r->filename)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_set_filename (value rv, value str) { CAMLparam2 (rv, str); request_rec *r = Request_rec_val (rv); r->filename = apr_pstrdup (r->pool, String_val (str)); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_path_info (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); if (r->path_info) CAMLreturn (copy_string (r->path_info)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_set_path_info (value rv, value str) { CAMLparam2 (rv, str); request_rec *r = Request_rec_val (rv); r->path_info = apr_pstrdup (r->pool, String_val (str)); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_args (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); if (r->args) CAMLreturn (copy_string (r->args)); else raise_not_found (); } CAMLprim value netcgi2_apache_request_set_args (value rv, value str) { CAMLparam2 (rv, str); request_rec *r = Request_rec_val (rv); r->args = apr_pstrdup (r->pool, String_val (str)); CAMLreturn (Val_unit); } #if APACHE2 static int file_kind_table[] = { APR_REG, APR_DIR, APR_CHR, APR_BLK, APR_LNK, APR_PIPE, APR_SOCK }; #else static int file_kind_table[] = { S_IFREG, S_IFDIR, S_IFCHR, S_IFBLK, S_IFLNK, S_IFIFO, S_IFSOCK }; #endif static value cst_to_constr (int n, int *tbl, int size, int deflt) { int i; for (i = 0; i < size; i++) if (n == tbl[i]) return Val_int(i); return Val_int(deflt); } CAMLprim value netcgi2_apache_request_finfo (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLlocal5 (v, sb, atime, mtime, ctime); #if APACHE2 if (r->finfo.filetype != APR_NOFILE) /* Some statbuf */ { atime = (r->finfo.valid & APR_FINFO_ATIME) ? copy_double ((double) apr_time_sec (r->finfo.atime)) : copy_double (0.); mtime = (r->finfo.valid & APR_FINFO_MTIME) ? copy_double ((double) apr_time_sec (r->finfo.mtime)) : copy_double (0.); ctime = (r->finfo.valid & APR_FINFO_CTIME) ? copy_double ((double) apr_time_sec (r->finfo.ctime)) : copy_double (0.); sb = alloc_small (12, 0); Field (sb, 0) = Val_int (r->finfo.device); Field (sb, 1) = Val_int (r->finfo.inode); Field (sb, 2) = cst_to_constr (r->finfo.filetype, file_kind_table, sizeof (file_kind_table) / sizeof (int), 0); Field (sb, 3) = Val_int (r->finfo.protection); Field (sb, 4) = Val_int (r->finfo.nlink); Field (sb, 5) = Val_int (r->finfo.user); Field (sb, 6) = Val_int (r->finfo.group); Field (sb, 7) = Val_int (0); /* FIXME rdev? */ Field (sb, 8) = Val_int (r->finfo.size); /* FIXME 64 bit file offsets */ Field (sb, 9) = atime; Field (sb, 10) = mtime; Field (sb, 11) = ctime; v = alloc (1, 0); /* The "Some" block. */ Field (v, 0) = sb; } else v = Val_int (0); /* None. */ #else /* not APACHE2 */ if (r->finfo.st_mode) /* Some statbuf */ { /* This code copied and modified from otherlibs/unix/stat.c. */ atime = copy_double ((double) r->finfo.st_atime); mtime = copy_double ((double) r->finfo.st_mtime); ctime = copy_double ((double) r->finfo.st_ctime); sb = alloc_small (12, 0); Field (sb, 0) = Val_int (r->finfo.st_dev); Field (sb, 1) = Val_int (r->finfo.st_ino); Field (sb, 2) = cst_to_constr (r->finfo.st_mode & S_IFMT, file_kind_table, sizeof (file_kind_table) / sizeof (int), 0); Field (sb, 3) = Val_int (r->finfo.st_mode & 07777); Field (sb, 4) = Val_int (r->finfo.st_nlink); Field (sb, 5) = Val_int (r->finfo.st_uid); Field (sb, 6) = Val_int (r->finfo.st_gid); Field (sb, 7) = Val_int (r->finfo.st_rdev); Field (sb, 8) = Val_int (r->finfo.st_size); /* FIXME: 64 bit file offsets */ Field (sb, 9) = atime; Field (sb, 10) = mtime; Field (sb, 11) = ctime; v = alloc (1, 0); /* The "Some" block. */ Field (v, 0) = sb; } else v = Val_int (0); /* None. */ #endif /* not APACHE2 */ CAMLreturn (v); } CAMLprim value netcgi2_apache_request_send_http_header (value rv) { CAMLparam1 (rv); #if APACHE2 /* FIXME do nothing in Apache 2.x? */ #else request_rec *r = Request_rec_val (rv); ap_send_http_header (r); #endif CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_rflush (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); int i = ap_rflush (r); CAMLreturn (Val_int (i)); } CAMLprim value netcgi2_apache_request_setup_client_block (value rv, value rp) { CAMLparam2 (rv, rp); request_rec *r = Request_rec_val (rv); int i = ap_setup_client_block (r, Int_val (rp)); CAMLreturn (Val_int(i)); /* possible error dealt with on the Caml side */ } CAMLprim value netcgi2_apache_request_should_client_block (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_bool (ap_should_client_block (r))); } CAMLprim value netcgi2_apache_request_get_client_block (value rv) { CAMLparam1 (rv); CAMLlocal1 (str); request_rec *r = Request_rec_val (rv); const int huge_string_len = 8192; /* Same as Apache's HUGE_STRING_LEN. */ char buffer [huge_string_len]; int i; str = Val_unit; i = ap_get_client_block (r, buffer, huge_string_len); if (i == -1) { /* FIXME: It seems there is now way to get more info about the error. */ caml_failwith("ap_get_client_block"); } str = alloc_string (i); memcpy (String_val (str), buffer, i); CAMLreturn (str); } CAMLprim value netcgi2_apache_request_get_client_block_buffered(value rv, value bufv, value ofsv, value lenv) { CAMLparam4(rv, bufv, ofsv, lenv); request_rec *r = Request_rec_val(rv); int ofs = Int_val(ofsv); int len = Int_val(lenv); int i; i = ap_get_client_block (r, String_val(bufv) + ofs, len); /* Error dealt with on the Caml side. */ CAMLreturn(Val_int(i)); } CAMLprim value netcgi2_apache_request_discard_request_body (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); int i = ap_discard_request_body (r); CAMLreturn (Val_int(i)); /* possible error dealt with on the Caml side */ } CAMLprim value netcgi2_apache_auth_type(value rv) { CAMLparam1(rv); request_rec *r = Request_rec_val(rv); #if APACHE2 if (r->ap_auth_type) CAMLreturn(copy_string(r->ap_auth_type)); #else if (r->connection->ap_auth_type) CAMLreturn(copy_string(r->connection->ap_auth_type)); #endif else raise_not_found(); } CAMLprim value netcgi2_apache_request_note_auth_failure (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); ap_note_auth_failure (r); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_note_basic_auth_failure (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); ap_note_basic_auth_failure (r); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_note_digest_auth_failure (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); ap_note_digest_auth_failure (r); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_get_basic_auth_pw (value rv) { CAMLparam1 (rv); CAMLlocal1 (c); request_rec *r = Request_rec_val (rv); const char *pw = 0; int i = ap_get_basic_auth_pw (r, &pw); /* no need to free(pw) */ /* Return [i] as the first component of a couple so we can deal with * the possible errors on the Caml side. */ if (i == DECLINED) pw = NULL; /* FIXME */ c = alloc_tuple (2); Store_field(c, 0, Val_int(i)); Store_field(c, 1, Val_optstring(pw)); CAMLreturn (c); } CAMLprim value netcgi2_apache_request_internal_redirect (value new_uri, value rv) { CAMLparam2 (new_uri, rv); request_rec *r = Request_rec_val (rv); ap_internal_redirect (String_val (new_uri), r); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_internal_redirect_handler (value new_uri, value rv) { CAMLparam2 (new_uri, rv); request_rec *r = Request_rec_val (rv); ap_internal_redirect_handler (String_val (new_uri), r); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_print_char (value rv, value cv) { CAMLparam2 (rv, cv); request_rec *r = Request_rec_val (rv); int c = Int_val (cv); if (ap_rputc (c, r) == EOF) raise_sys_error(copy_string("Netcgi_mod#out_channel#output_char")); CAMLreturn (Val_unit); } CAMLprim value netcgi2_apache_request_output(value rv, value bufv, value ofsv, value lenv) { CAMLparam4(rv, bufv, ofsv, lenv); request_rec *r = Request_rec_val(rv); int ofs = Int_val(ofsv); int len = Int_val(lenv); int i = ap_rwrite(String_val(bufv) + ofs, len, r); CAMLreturn(Val_int (i)); } static int run_cleanup (void *fv) { value f = *(value *) fv; callback (f, Val_unit); remove_global_root ((value *) fv); return OK; } CAMLprim value netcgi2_apache_request_register_cleanup (value rv, value f) { CAMLparam2 (rv, f); request_rec *r = Request_rec_val (rv); value *v = (value *) apr_palloc (r->pool, sizeof (value)); *v = f; register_global_root (v); #if APACHE2 apr_pool_cleanup_register (r->pool, v, run_cleanup, apr_pool_cleanup_null); #else ap_register_cleanup (r->pool, v, (void (*)(void *)) run_cleanup, ap_null_cleanup); #endif CAMLreturn (Val_unit); } /*----- Miscellaneous functions. -----*/ CAMLprim value netcgi2_apache_get_server_config (value rv) { CAMLparam1 (rv); CAMLlocal1 (config); request_rec *r = Request_rec_val (rv); if (r->server && r->server->module_config) { void *c = ap_get_module_config (r->server->module_config, &netcgi_module); if (c) config = *(value *) c; else goto not_found; } else not_found: raise_not_found (); CAMLreturn (config); } CAMLprim value netcgi2_apache_get_dir_config (value rv) { CAMLparam1 (rv); CAMLlocal1 (config); request_rec *r = Request_rec_val (rv); if (r->per_dir_config) { void *c = ap_get_module_config (r->per_dir_config, &netcgi_module); if (c) config = *(value *) c; else goto not_found; } else not_found: raise_not_found (); CAMLreturn (config); } ocamlnet-4.1.2/src/netcgi2-apache/netcgi_apache.ml0000644000175000017500000005717112731530350020423 0ustar gerdgerd(* netcgi_apache.ml Copyright (C) 2005-2007 Christophe Troestler email: Christophe.Troestler@umh.ac.be WWW: http://math.umh.ac.be/an/ This library is free software; see the file LICENSE for more information. 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 file LICENSE for more details. *) open Netcgi_common open Printf let log_error msg = let zone = Netdate.localzone in prerr_endline ("[" ^ Netdate.format "%c" (Netdate.create ~zone (Unix.gettimeofday())) ^ "] [Netcgi_apache] " ^ msg) module Conf = Netcgi_apache_mod.Conf module Handler = Netcgi_apache_mod.Handler module Apache = struct (* Here we shadow some external functions of the Apache stub to make them safer or respecting Netcgi conventions. *) module Table = Netcgi_apache_mod.Raw_Apache.Table module Server = Netcgi_apache_mod.Raw_Apache.Server module Connection = Netcgi_apache_mod.Raw_Apache.Connection module Request = struct (* Request_rec functions. *) include Netcgi_apache_mod.Raw_Apache.Request (* If the return code [i] is an error, raise HTTP with the message [msg]. *) let possible_error msg i : unit = (* DECLINED -1, DONE -2, OK 0 *) if i > 0 then raise(HTTP(Nethttp.http_status_of_int i, msg)) let setup_client_block r p = possible_error "Netcgi_apache.Apache.Request.setup_client_block" (setup_client_block r p) let get_client_block r = try get_client_block r with Failure msg -> raise(HTTP(`Internal_server_error, msg)) let get_client_block_buf r buf ofs len = if ofs < 0 || ofs + len > Bytes.length buf then invalid_arg "Netcgi_apache.Apache.Request.get_client_block_buf"; let r = get_client_block_buffer r buf ofs len in if r < 0 then raise(HTTP(`Internal_server_error, "Netcgi_apache.Apache.Request.get_client_block_buf")) else r let discard_request_body r = possible_error "Netcgi_apache.Apache.Request.discard_request_body" (discard_request_body r) let get_basic_auth_pw r = let i, pw = get_basic_auth_pw r in possible_error "Netcgi_apache.Apache.Request.get_basic_auth_pw" i; pw let rflush r = if rflush r < 0 then raise End_of_file end end (* module Apache -------------------------------------------------- *) (* CGI and Environment objects ---------------------------------------- *) open Apache (** Useful functions *) (* [rm_htspace s] removes heading and trailing spaces of [s]. *) let rm_htspace = let is_space c = c = ' ' || c = '\t' || c = '\n' || c = '\r' in fun s -> rm_htspace is_space s 0 (String.length s) (* Monomorphic version *) let min (i:int) j = if i <= j then i else j (* [index_in_range s i0 i1 c] returns the index [j] of the first occurrence of [c] in s.[i0 .. i1-1]. If no occurence of [c] is found, it will return [i1]. It is assumed that 0 <= i0 and i1 <= String.length s. *) let index_in_range s i0 i1 c = let rec examine i = if i < i1 then if Bytes.unsafe_get s i = c then i else examine (i+1) else i1 in examine i0 (************************************************************************) (** Input channel *) (* The "stdin" data is here accessible through the "get_client_block" function of the [Request.t] type. We wrap it into a in_object to use Netstring parsing functions. WARNING: You should NOT create this object if one is not ready to read content. Never create several [in_obj] on the same request. *) (* http://www.auburn.edu/docs/apache/misc/client_block_api.html *) class in_obj (r:Apache.Request.t) : Netchannels.in_obj_channel = object(self) val r = r val in_buf = Bytes.create 8192 (* valid: buf.[in0 .. in1-1] *) val mutable in0 = 0 val mutable in1 = 0 (* in1 < 0 indicates the channel is closed *) val mutable read = 0 (* number of byte delivered to the user *) initializer Request.setup_client_block r Request.CHUNKED_ERROR; if not(Request.should_client_block r) then ( (* e.g. for GET request -- should not happen if used correctly *) (* XXX Do not terminate the process. *) log_error "Netcgi_apache.in_obj: should_client_block returned false \ for a POST request (ignored)"; (* failwith "Netcgi_apache.in_obj: should_client_block" *) ) (* [#fill_in_buf] refills [in_buf] if needed (when empty). After this [in0 < in1] or [End_of_file] is raised. *) method private fill_in_buf = if in0 >= in1 then ( in0 <- 0; in1 <- Request.get_client_block_buf r in_buf 0 8192; if in1 = 0 then raise End_of_file; ) method private unsafe_input buf ofs len = self#fill_in_buf; let r = min len (in1 - in0) in Bytes.blit in_buf in0 buf ofs r; in0 <- in0 + r; read <- read + r; r (* rec_in_channel *) method input buf ofs len = if in1 < 0 then raise Netchannels.Closed_channel; if ofs < 0 || len < 0 || ofs + len > Bytes.length buf then invalid_arg "Netcgi_apache.in_obj#input"; self#unsafe_input buf ofs len method close_in () = if in1 < 0 then raise Netchannels.Closed_channel; in0 <- 0; in1 <- -1 (* raw_in_channel *) method pos_in = read (* Convenience methods *) method really_input buf ofs len = if in1 < 0 then raise Netchannels.Closed_channel; if ofs < 0 || len < 0 || ofs + len > Bytes.length buf then invalid_arg "Netcgi_apache.in_obj#really_input"; let ofs = ref ofs and len = ref len in while !len > 0 do let r = self#unsafe_input buf !ofs !len in ofs := !ofs + r; len := !len - r done method really_input_string len = let b = Bytes.create len in self # really_input b 0 len; Bytes.unsafe_to_string b method input_char () = if in1 < 0 then raise Netchannels.Closed_channel; self#fill_in_buf; let c = Bytes.unsafe_get in_buf in0 in in0 <- in0 + 1; read <- read + 1; c method input_byte () = Char.code(self#input_char()) method input_line () = if in1 < 0 then raise Netchannels.Closed_channel; let line = ref "" and i = ref in1 (* to enter the loop *) in while !i = in1 (* '\n' not found *) do self#fill_in_buf; (* => in0 < in1 *) i := index_in_range in_buf in0 in1 '\n'; let r = !i - in0 in line := !line ^ (Bytes.sub_string in_buf in0 r); read <- read + r + 1; (* +1 for '\n' *) in0 <- !i + 1; (* skip '\n' *) done; !line end (* When no input is required, we need a dummy object to play the input channel role. The following one will give us appropriate information in case of misuse. *) class dummy_in_obj : Netchannels.in_obj_channel = object method input (_:Bytes.t) (_:int) (_:int) = invalid_arg "dummy_in_obj" method close_in () = invalid_arg "dummy_in_obj" method pos_in = invalid_arg "dummy_in_obj" method really_input (_:Bytes.t) (_:int) (_:int) = invalid_arg "dummy_in_obj" method really_input_string (_:int) = invalid_arg "dummy_in_obj" method input_char () = invalid_arg "dummy_in_obj" method input_byte () = invalid_arg "dummy_in_obj" method input_line () = invalid_arg "dummy_in_obj" end (************************************************************************) (** Output channel: though output functions of the request *) class out_obj (r:Apache.Request.t) : Netchannels.out_obj_channel = object(self) val r = r val mutable sent = 0 val mutable closed = false (* At the moment, all buffering is left to Apache. *) (* rec_out_channel *) method output s ofs len = if closed then raise Netchannels.Closed_channel; let w = Request.output r s ofs len in sent <- sent + w; w method flush () = if closed then raise Netchannels.Closed_channel; try Request.rflush r with _ -> raise(Sys_error "Netcgi_apache#out_channel#flush: EOF") method close_out () = (* Apache closes the channel itself *) if not closed then ( closed <- true; try self#flush(); with | error -> Netlog.logf `Err "Netcgi_apache: Suppressed error in close_out: %s" (Netexn.to_string error); ) (* raw_out_channel *) method pos_out = sent (* convenience methods *) method output_char c = if closed then raise Netchannels.Closed_channel; Request.print_char r c; sent <- sent + 1 method output_byte i = self#output_char(Char.unsafe_chr(i land 0xFF)) method private unsafe_really_output s ofs len = let len = ref len and ntries = ref 0 (* avoid infinite loop *) in while !len > 0 && !ntries < 100 do let w = Request.output r s ofs !len (* checks bounds *) in sent <- sent + w; len := !len - w; (* if not = 0, try again *) incr ntries; done; if !len > 0 then failwith "Netcgi_apache#out_channel#really_output" method output_string s = if closed then raise Netchannels.Closed_channel; self#unsafe_really_output (Bytes.unsafe_of_string s) 0 (String.length s) method output_bytes s = if closed then raise Netchannels.Closed_channel; self#unsafe_really_output s 0 (Bytes.length s) method output_buffer b = self#output_string(Buffer.contents b) method really_output s ofs len = if closed then raise Netchannels.Closed_channel; if ofs < 0 || len < 0 || ofs + len > Bytes.length s then invalid_arg "Netcgi_apache#out_channel#really_output"; self#unsafe_really_output s ofs len method really_output_string s ofs len = if closed then raise Netchannels.Closed_channel; if ofs < 0 || len < 0 || ofs + len > String.length s then invalid_arg "Netcgi_apache#out_channel#really_output_string"; self#unsafe_really_output (Bytes.unsafe_of_string s) ofs len method output_channel ?len in_obj = if closed then raise Netchannels.Closed_channel; let buf = Bytes.create 8192 in match len with | None -> (* read till the end *) (try while true do let r = in_obj#input buf 0 8192 in if r = 0 then raise Sys_blocked_io; self#unsafe_really_output buf 0 r; done with End_of_file -> ()) | Some len -> (* read at most that many bytes *) (try let len = ref len in while !len > 0 do let r = in_obj#input buf 0 (min 8192 !len) in if r = 0 then raise Sys_blocked_io; self#unsafe_really_output buf 0 r; len := !len - r done with End_of_file -> ()) end (************************************************************************) (** Header classes bound to Apache table *) (* Apache already has a representation for MIME headers so we bind directly to them instead of using OcamlNet [Netmime] module. The Apache functions already treat keys case-insensitively as we want. *) class mime_header ?(ro=false) table : Netmime.mime_header = object (self) val ro = ro val t = table (* Get *) method ro = ro method fields = Apache.Table.fields t method field name = Apache.Table.get t name method multiple_field name = Apache.Table.get_all t name (* Set *) method private immutable = raise (Netmime.Immutable "Netcgi_apache.mime_header"); method set_fields h = if ro then self#immutable; Apache.Table.clear t; List.iter (fun (k,v) -> Apache.Table.add t k v) h method update_field name v = if ro then self#immutable; Apache.Table.set t name v method update_multiple_field name vl = if ro then self#immutable; match vl with | [] -> Apache.Table.unset t name | v :: tl -> Apache.Table.set t name v; List.iter (fun v -> Apache.Table.add t name v) tl method delete_field name = if ro then self#immutable; Apache.Table.unset t name (* Access methods for frequent standard fields *) (* method content_length() = int_of_string(rm_htspace(self#field "content-length")) method content_type() = Netmime_string.scan_mime_type_ep (self#field "content-type") [] method content_disposition() = Netmime_string.scan_mime_type_ep (self#field "content-disposition") [] method content_transfer_encoding() = String.lowercase(self#field "content-transfer-encoding") *) end (************************************************************************) (** Environment *) (* The environment properties does not come from a list that we have to parse. Rather, properties come from various entries in the [request_rec] structure, i.e. various functions in the [Apache.Request] module. *) class cgi_environment ~config r : Netcgi.cgi_environment = let path_info = try Request.path_info r with Not_found -> "" in object(self) inherit Netcgi_common.cgi_environment ~config ~properties:[] ~input_header:[] (new out_obj r) (* Properties settable by Request functions. Store their initial value. *) val script_name = let s = try Request.uri r with Not_found -> "" in if Filename.check_suffix s path_info then Filename.chop_suffix s path_info (* suppress path_info *) else s val path_info = path_info val r_filename = try Request.filename r with Not_found -> "" val query_string = try Request.args r with Not_found -> "" val input_header = new mime_header ~ro:true (Request.headers_in r) val output_header = new mime_header ~ro:false (Request.headers_out r) (* XXX Should we use [err_headers_out] because they persist on errors and across internal redirect? What about other connectors? *) val r = r (* must be last for the above [r] to be the arg. *) val mutable properties_list = lazy(assert false) val mutable input_content_type = lazy(assert false) initializer (* Content-type MSIE bug fix has not been applied; do it now. *) input_content_type <- lazy( let work_around = List.mem `MSIE_Content_type_bug self#config.workarounds && (try is_MSIE(self#user_agent) with Not_found -> false) in let ct = self#input_header_field "content-type" in let ct = if work_around then fix_MSIE_Content_type_bug ct else ct in Netmime_string.scan_mime_type_ep ct [] ); (* We probably do not want the list of all properties, so compute it on demand only. *) properties_list <- lazy ( let l = [ ("GATEWAY_INTERFACE", self#cgi_gateway_interface); ("SERVER_NAME", self#cgi_server_name); ("SERVER_PROTOCOL", self#cgi_server_protocol); ("SERVER_SOFTWARE", self#cgi_server_software); ("SERVER_ADMIN", Server.admin(Request.server r)); ("REQUEST_METHOD", self#cgi_request_method); ("SCRIPT_NAME", self#cgi_script_name); ("PATH_INFO", self#cgi_path_info); ("PATH_TRANSLATED", self#cgi_path_translated); ("AUTH_TYPE", self#cgi_auth_type); ("REMOTE_ADDR", self#cgi_remote_addr); ("REMOTE_HOST", self#cgi_remote_host); ("REMOTE_USER", self#cgi_remote_user); ("REMOTE_IDENT", self#cgi_remote_ident); ("QUERY_STRING", self#cgi_query_string); ("SCRIPT_FILENAME", r_filename); ] in let l = match self#cgi_server_port with | None -> l | Some p -> ("SERVER_PORT", string_of_int(p)) :: l in l ) (* CGI properties *) method cgi_properties = Lazy.force properties_list method cgi_property ?default name = try List.assoc name (Lazy.force properties_list) with Not_found -> (match default with | None -> raise Not_found | Some d -> d) (* None of the following methods should raise [Not_found]. Return "" instead. *) method cgi_gateway_interface = Conf.gateway_interface method cgi_server_name = try Request.hostname r with Not_found -> "" method cgi_server_port = Some(Request.port r) method cgi_server_protocol = try Request.protocol r with Not_found -> "" method cgi_server_software = Conf.server_software method cgi_request_method = try Request.method_name r with Not_found -> "" (* Beware that it is used by the [Netcgi_common.cgi_with_args] to pass a it to [[Netcgi_common.cgi] to set the [out_channel] to an appropriate value. *) method cgi_script_name = script_name method cgi_path_info = path_info method cgi_path_translated = "" (* FIXME: don't know how to get it *) method cgi_auth_type = try Request.auth_type r with Not_found -> "" method cgi_remote_addr = try Connection.remote_ip(Request.connection r) with Not_found -> "" method cgi_remote_host = try Connection.remote_host(Request.connection r) with Not_found -> "" method cgi_remote_user = try Request.user r with Not_found -> "" method cgi_remote_ident = "" (* FIXME: is it only supported? *) method cgi_query_string = query_string (* method protocol is inherited and use [server_protocol]; OK *) method cgi_https = false (* FIXME: don't know how to get it *) (* Input -- other methods are defined in terms of [input_header], so no nedd to override them. *) method input_header = input_header (* Output -- again other methods are defined in terms of [output_header] and do not need to be overridden. *) method output_header = output_header method send_output_header () = if header_not_sent then ( (* Must treat Status specially *) (try let st = int_of_string(self#output_header#field "Status") in Request.set_status r st with Not_found | Failure _ -> ()); (* Must treat Content-Type specially *) Request.set_content_type r (try self#output_header#field "Content-Type" with Not_found -> "text/html" (* In [Netcgi_common.environment], it was decided to have a default Content-type. *) ); Request.send_http_header r; header_not_sent <- false ) (* method out_channel is fine as inherited *) (* method log_error: funny as it is, printing on stderr is fine for Apache modules. *) end (************************************************************************) (** CGI abstraction *) (* Enriched CGI class *) class type cgi = object inherit Netcgi.cgi method request : Apache.Request.t end class cgi_mod (r:Request.t) env op request_method args : cgi = object inherit Netcgi_common.cgi env op request_method args as super val r = r method request = r end exception Error of Nethttp.http_status * string * string (* [Error(status, log-msg, user-msg)]: errors raised before the handler is created. *) (* This will be used by the script to set its entry point (function to be run) when loaded with [Dynlink]. *) let script_run = ref None (* Load a file and return the function to run. *) let load_file filename = script_run := None; (try Dynlink.loadfile_private filename; with | Dynlink.Error e -> raise(Error(`Internal_server_error, filename ^ ": Dynlink.Error: " ^ Dynlink.error_message e, "Couldn't load the script.")) | e -> raise(Error(`Internal_server_error, filename ^ ": " ^ Netexn.to_string e, "Couldn't load the script."))); (* If the file was loaded and thus the toplevel code executed, [current_script] should now be [Some handler]. *) match !script_run with | None -> raise(Error(`Not_found, "You must register your main function with Netcgi_apache.run!", "No entry point in the script.")) | Some script -> script (* Tells wich function of the script is the one to run on each request. This is to be only called 1 time per script. Exceptions will be dealt with in the handler (see below). *) let run ?(config=Netcgi.default_config) ?(output_type=(`Direct "" : Netcgi.output_type)) ?(arg_store=(fun _ _ _ -> `Automatic : Netcgi.arg_store)) ?(exn_handler=(fun _ f -> f())) f = if !script_run <> None then raise(Error(`Internal_server_error, "Netcgi_apache.run should only be called once!", "Multiple entry points in the script.")); let script r = (* Netcgi_apache specific environment -- including output object *) let env = new cgi_environment ~config r in exn_handler_default env ~exn_handler (fun () -> let in_obj = match env#cgi_request_method with | "POST" | "PUT" -> new in_obj r (* => only created if necessary *) | _ -> Request.discard_request_body r; new dummy_in_obj (* raise an exception if used *) in let cgi = cgi_with_args (new cgi_mod r) env output_type in_obj arg_store in (try f cgi; cgi#out_channel#commit_work(); cgi#finalize() with e when config.default_exn_handler -> cgi#finalize(); raise e); None (* no "special" internal exception *) ) ~finally:(fun () -> (try env#out_channel#close_out() with _ -> ()); (* flush *) ); Handler.OK in (* Register the main function *) script_run := Some script (************************************************************************) (** Registry *) (* This part is loosely based on mod_caml Registry *) (* This is an error page for the exceptions launched before the environment object can be created. *) let error_page r status log_msg user_msg = (* Log the error *) let code = Nethttp.int_of_http_status status in log_error(Printf.sprintf "%s (Status %i)" log_msg code); (* Display an error page *) Request.set_status r code; Request.set_content_type r "text/html"; let t = Request.headers_out r in Apache.Table.set t "Cache-control" "max-age=3600"; Apache.Table.add t "Cache-control" "must-revalidate"; let secs = Netdate.mk_mail_date(Unix.time() +. 3600.) in Apache.Table.set t "Expires" secs; Request.send_http_header r; if not(Request.header_only r) then ( let out s = ignore(Request.print_string r s) in out "\n"; out " \n"; let info = Nethttp.string_of_http_status status in out ("

Netcgi_apache — " ^ info ^ "

\n"); out "

"; out user_msg; out "

\n"; out "

Additional information is available in the web server \ error log file.

\n"; out "\n\n"; ignore(Request.rflush r) ) (* Table of scripts we have already loaded. Maps filename -> (handler, mtime) so we can reload the file if the mtime has changed. *) let loaded_scripts = Hashtbl.create 32 (* Handler for requests. *) let handler r = try (* Without [filename] or [mtime] we cannot do anything so we decline the request. *) let filename = try Apache.Request.filename r with Not_found -> raise(Error(`Not_found, "Request.filename not found!", "No such script.")) in let mtime = match Apache.Request.finfo r with | Some finfo -> finfo.Unix.st_mtime | None -> raise(Error(`Not_found, sprintf "Request.finfo not found. It probably means \ that the file %S does not exist." filename, "No such script.")) in (* Get the script main function for this file. *) let script = try let (old_handler, old_mtime) = Hashtbl.find loaded_scripts filename in if old_mtime < mtime then ( (* Reload the file. *) let handler = load_file filename in Hashtbl.replace loaded_scripts filename (handler, mtime); handler ) else old_handler with Not_found -> (* Load the file for the first time. *) let handler = load_file filename in Hashtbl.add loaded_scripts filename (handler, mtime); handler in (* Run the script. *) script r with Error(status, log_msg, user_msg) -> error_page r status log_msg user_msg; (* Returning [Handler.DECLINED] is not fine. Indeed, Apache then tries his own handler and then propose to download the script -- this is a security problem! *) Handler.DONE let () = (* We are in the same module than the Handler (no bytecode to load), so specify the full module name to use. *) Handler.register handler "bytecode" ocamlnet-4.1.2/src/equeue-tcl/0000755000175000017500000000000012731530351014604 5ustar gerdgerdocamlnet-4.1.2/src/equeue-tcl/Makefile0000644000175000017500000000073612731530351016252 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PKGNAME = equeue-tcl ARCHIVE = equeue_tcl OBJECTS = uq_tcl.cmo DOBJECTS = uq_tcl.mli COBJECTS = tclqueue.o LINK_OPTIONS = $(EQUEUE_TCL_LIBS) CC_OPTIONS = $(EQUEUE_TCL_DEFS) OCAMLC_OPTIONS += $(STRING_OPTS) OCAMLOPT_OPTIONS += $(STRING_OPTS) PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" DOC_IGNORABLE = true INCLUDES += $(INC_EQUEUE) INCLUDES += $(INC_NETSYS) include $(TOP_DIR)/Makefile.rules include depend ocamlnet-4.1.2/src/equeue-tcl/META.in0000644000175000017500000000031012731530351015654 0ustar gerdgerdversion = "@VERSION@" description = "Ocamlnet - Event queues" requires = "unix equeue" archive(byte) = "equeue_tcl.cma" archive(native) = "equeue_tcl.cmxa" archive(native,gprof) = "equeue_tcl.p.cmxa" ocamlnet-4.1.2/src/equeue-tcl/uq_tcl.mli0000644000175000017500000000310012731530351016570 0ustar gerdgerd(* $Id$ *) open Equeue open Unixqueue (** Integration with the labltk event system *) (** This module provides integration of Unixqueue event systems with the * TCL event queue (and, as a consequence, with the labltk event queue). *) (** OPAM users: Note that this library is currently unavailable. *) type runner = event_system -> (unit -> unit) -> unit class tcl_event_system : ?run:runner -> unit -> event_system (** This class is an alternate implementation of the Unixqueue event systems * for the TCL event loop. Use this class instead of [unix_event_system]. * * Both Unixqueue and TCL provide event queues for system events, * and it is possible to merge both queues such that events may happen and * be processed on one queue while the other queue blocks. * * To achieve this, just use this class instead of [unix_event_system]. * It automatically creates handlers for the TCL loop when necessary. * However, you must not invoke the method [run], as this class does not * provide its own event loop. Instead, ensure that [Tk.mainLoop] is * called. * * Of course, this is all intended to help writing applications which have * a graphical user interface (GUI) built with labltk, and some network * functionality which is designed to work in the background. Simply create * your GUI with labltk, and after the button is pressed which starts the * network I/O, you add resources to this event queue, and the I/O will be * processed concurrently with any user input coming from the GUI. * * Note: The implementation is not thread-safe (and neither TCL). *) ocamlnet-4.1.2/src/equeue-tcl/Makefile.pre0000644000175000017500000000027212731530351017032 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PRE = 1 PKGNAME = equeue-tcl GENERATE = META PP_OPTIONS = -pp "$(CPPO) $(PP_BYTES) $(PP_DEPRECATED)" include $(TOP_DIR)/Makefile.rules ocamlnet-4.1.2/src/equeue-tcl/tclqueue.c0000644000175000017500000000533512731530351016605 0ustar gerdgerd/* $Id$ * ---------------------------------------------------------------------- * */ #include #include "caml/mlvalues.h" #include "caml/memory.h" #include "caml/alloc.h" #include "caml/fail.h" #include "caml/callback.h" #include "tclqueue.h" typedef struct _filehandler { value callback_fn; int fd; } filehandler; typedef struct _timerhandler { value callback_fn; Tcl_TimerToken token; } timerhandler; static void file_proc(ClientData cdata, int mask) { filehandler *h; value r; h = (filehandler *) cdata; r = callback_exn(h->callback_fn, Val_int(0)); if (Is_exception_result(r)) { fprintf(stderr, "In file_proc: Uncaught Ocaml exception\n"); }; } value caml_Tcl_CreateFileHandler(value callback_fn, value file_descriptor, value mask) { filehandler *h; int m, tcl_m; CAMLparam3(callback_fn, file_descriptor, mask); h = (filehandler *) (stat_alloc(sizeof(filehandler))); /* This must be a malloc'ed data block. */ register_global_root(&(h->callback_fn)); h->callback_fn = callback_fn; h->fd = Int_val(file_descriptor); m = Int_val(mask); tcl_m = 0; if (m & 1) tcl_m |= TCL_READABLE; if (m & 2) tcl_m |= TCL_WRITABLE; if (m & 4) tcl_m |= TCL_EXCEPTION; Tcl_CreateFileHandler(Int_val(file_descriptor), tcl_m, file_proc, (ClientData) h); CAMLreturn((value) h); } value caml_Tcl_DeleteFileHandler(value descriptor) { filehandler *h; CAMLparam1(descriptor); h = (filehandler *) descriptor; Tcl_DeleteFileHandler(h->fd); remove_global_root(&(h->callback_fn)); free(h); CAMLreturn(Val_int(0)); } static void timer_proc(ClientData cdata) { timerhandler *h; value r; h = (timerhandler *) cdata; r = callback_exn(h->callback_fn, Val_int(0)); if (Is_exception_result(r)) { fprintf(stderr, "In timer_proc: Uncaught Ocaml exception\n"); }; } value caml_Tcl_CreateTimerHandler(value callback_fn, value milliseconds) { timerhandler *h; CAMLparam2(callback_fn, milliseconds); h = (timerhandler *) (stat_alloc(sizeof(timerhandler))); /* This must be a malloc'ed data block. */ register_global_root(&(h->callback_fn)); h->callback_fn = callback_fn; h->token = Tcl_CreateTimerHandler(Int_val(milliseconds), timer_proc, (ClientData) h); CAMLreturn((value) h); } value caml_Tcl_DeleteTimerHandler(value descriptor) { timerhandler *h; CAMLparam1(descriptor); h = (timerhandler *) descriptor; Tcl_DeleteTimerHandler(h->token); remove_global_root(&(h->callback_fn)); free(h); CAMLreturn(Val_int(0)); } value caml_return_null (value dummy) { return (value) NULL; } ocamlnet-4.1.2/src/equeue-tcl/tclqueue.h0000644000175000017500000000177512731530351016616 0ustar gerdgerd/* $Id$ * ---------------------------------------------------------------------- * */ #ifndef TCLQUEUE_H #define TCLQUEUE_H value caml_Tcl_CreateFileHandler(value callback_fn, value file_descriptor, value mask); /* callback_fn: Caml closure. * file_descriptor: a Unix.file_descr. * mask: the condition to wait for * Returns: A descriptor describing the handler. * Note that the closure is registered as global roots until * DeleteFileHandler is called. */ value caml_Tcl_DeleteFileHandler(value descriptor); /* descriptor: the descriptor returned by CreateFileHandler. * returns: () */ value caml_return_null(value dummy); /* Returns a Null pointer */ value caml_Tcl_CreateTimerHandler(value callback_fn, value milliseconds); /* callback_fn: Caml closure * milliseconds: How long to wait. * retunrs: A descriptor describing the handler */ value caml_Tcl_DeleteTimerHandler(value descriptor); /* descriptor: the descriptor returned by CreateTimerHandler. * returns: () */ #endif ocamlnet-4.1.2/src/equeue-tcl/uq_tcl.ml0000644000175000017500000002000012731530351016415 0ustar gerdgerd(* $Id$ *) open Equeue open Unixqueue type tcl_timer_handler type tcl_file_handler type tcl_file_handler_rec = { mutable tcl_fh : tcl_file_handler; mutable tcl_fd : Unix.file_descr; mutable tcl_mask : int; } external tcl_CreateFileHandler : (unit -> unit) -> Unix.file_descr -> int -> tcl_file_handler = "caml_Tcl_CreateFileHandler";; external tcl_DeleteFileHandler : tcl_file_handler -> unit = "caml_Tcl_DeleteFileHandler";; external tcl_CreateTimerHandler : (unit -> unit) -> int -> tcl_timer_handler = "caml_Tcl_CreateTimerHandler";; external tcl_DeleteTimerHandler : tcl_timer_handler -> unit = "caml_Tcl_DeleteTimerHandler";; external tcl_null_file_handler : unit -> tcl_file_handler = "caml_return_null";; external tcl_null_timer_handler : unit -> tcl_timer_handler = "caml_return_null";; let null_fh = tcl_null_file_handler();; let null_th = tcl_null_timer_handler();; let dummy_fh = { tcl_fh = tcl_null_file_handler(); tcl_fd = Unix.stdin; tcl_mask = -1; } ;; let create_timer callback ms = (* prerr_endline ("create_timer ms=" ^ string_of_int ms); *) ref (tcl_CreateTimerHandler callback ms) ;; let delete_timer t = (* prerr_endline ("delete_timer"); *) let old = !t in t := null_th; tcl_DeleteTimerHandler old ;; type runner = event_system -> (unit -> unit) -> unit class tcl_event_system ?(run : runner option) () = object (self) inherit Unixqueue_select.select_based_event_system() as super val mutable tcl_attaching = false val mutable tcl_run_soon = false val mutable tcl_is_running = false val mutable tcl_last_timer = (None : tcl_timer_handler ref option) val mutable tcl_last_file_handlers = (Hashtbl.create 1 : (Unix.file_descr, tcl_file_handler_rec) Hashtbl.t) method private tcl_attach ?(run_soon=false) () = (* Creates an idle callback to reschedule events the next time the * event loop is entered. This step can be omitted when this method * is called from a Unixqueue callback (it is ensured tcl_setup * will be invoked soon). * * run_soon: if true, the Unixqueue is run once from the idle * callback. This can be used to process additional, non-file events. *) if not tcl_is_running then ( (* prerr_endline "ATTACH!"; *) if not tcl_attaching then ( tcl_attaching <- true; ( match tcl_last_timer with Some th -> delete_timer th; tcl_last_timer <- None | None -> () ); tcl_last_timer <- Some (create_timer (fun () -> self#tcl_setup(); if tcl_run_soon then ( tcl_run_soon <- false; self#tcl_safe_handler ([],[],[],0.0) () ) ) 0); ); tcl_run_soon <- tcl_run_soon || run_soon; ) (* else prerr_endline "(no attach)"; *) method private tcl_setup() = let (infiles, outfiles, oobfiles, time) as watch_tuple = super#setup() in let ht = Hashtbl.create 50 (* n *) in (* 50 should be enough *) (* Fill ht, the new hash table of file handlers: *) List.iter (fun fd -> let r = try Hashtbl.find ht fd with Not_found -> let r' = { tcl_fh = null_fh; tcl_fd = fd; tcl_mask = 0 } in Hashtbl.add ht fd r'; r' in r.tcl_mask <- r.tcl_mask lor 1) infiles; List.iter (fun fd -> let r = try Hashtbl.find ht fd with Not_found -> let r' = { tcl_fh = null_fh; tcl_fd = fd; tcl_mask = 0 } in Hashtbl.add ht fd r'; r' in r.tcl_mask <- r.tcl_mask lor 2) outfiles; List.iter (fun fd -> let r = try Hashtbl.find ht fd with Not_found -> let r' = { tcl_fh = null_fh; tcl_fd = fd; tcl_mask = 0 } in Hashtbl.add ht fd r'; r' in r.tcl_mask <- r.tcl_mask lor 4) oobfiles; (* Remove all TCL file handlers *) Hashtbl.iter (fun fd r -> (* Only delete if the new condition is different: *) if try let r' = Hashtbl.find ht fd in r'.tcl_mask <> r.tcl_mask with Not_found -> true then begin let fh = r.tcl_fh in r.tcl_fh <- null_fh; (* to avoid race condition with GC *) (* prerr_endline "DeleteFileHandler"; *) tcl_DeleteFileHandler fh end ) tcl_last_file_handlers; (* Create the new file handlers *) Hashtbl.iter (fun fd r -> (* Only create if the new condition is different: *) let r' = try Hashtbl.find tcl_last_file_handlers fd with Not_found -> dummy_fh (* dummy_fh.tcl_mask <> r.tcl_mask *) in if r'.tcl_mask <> r.tcl_mask then ( (* prerr_endline ("CreateFileHandler mask=" ^ string_of_int r.tcl_mask); *) r.tcl_fh <- tcl_CreateFileHandler (self#tcl_safe_handler watch_tuple) fd r.tcl_mask ) else r.tcl_fh <- r'.tcl_fh; ) ht; (* Remember [ht] for next round: *) tcl_last_file_handlers <- ht; (* let watching_files = infiles <> [] || outfiles <> [] || oobfiles <> [] in *) (* Remove the old timer, if any. *) begin match tcl_last_timer with None -> () | Some th -> delete_timer th; tcl_last_timer <- None; end; tcl_attaching <- false; (* Set the new timer, if necessary *) if time >= 0.0 then begin (* prerr_endline ("Timeout: " ^ string_of_float time); *) tcl_last_timer <- Some (create_timer (self#tcl_safe_handler watch_tuple) (int_of_float (((*min*) time (*1.0*)) *. 1E3 +. 0.5))); end; (* If no handler is active, detach. *) (* if tcl_last_timer = None && not watching_files then begin tcl_attached <- false; (* prerr_endline "Detached!"; *) end; *) method private tcl_safe_handler watch_tuple () = try self#tcl_handler watch_tuple () with any -> prerr_endline("Uq_tcl: Internal uncaught exception: " ^ Netexn.to_string any); method private tcl_handler (infiles, outfiles, oobfiles, time) () = (* IMPORTANT: * It is possible that this is a "ghost event". We need to test whether * there is a resource for the event or not. *) (* Do now a 'select' with zero timeout to test the file descriptors. *) let (infiles', outfiles', oobfiles') as actual_tuple = (* (infiles', outfiles', oobfiles'): Lists of file descriptors that * can be handled *) Unix.select infiles outfiles oobfiles 0.0 (* Because of the timeout value 0.0, this "select" call cannot block, * and it cannot raise EINTR. *) in (* Now we have in infiles', outfiles', oobfiles' the actually happened * file descriptor events. * Furthermore, pure timeout events may have happened, but this is not * indicated specially. *) ignore(self#queue_events actual_tuple); (* Now run the queue (without source). *) begin try tcl_is_running <- true; match run with None -> super#run() | Some r -> r (self : #event_system :> event_system) super#run; with any -> prerr_endline ("Uq_tcl: Uncaught exception: " ^ Netexn.to_string any ); end; tcl_is_running <- false; (* Set up for the next round. *) self#tcl_setup (); (**********************************************************************) (* Overriden methods *) (**********************************************************************) method private source _ = (* Override this method: All events are coming from the tcl loop, * so disable this source of events *) () (* After certain method invocations, we must ensure we are attached: *) method add_resource g (op,t) = super # add_resource g (op,t); self # tcl_attach() method remove_resource g op = super # remove_resource g op; self # tcl_attach() method add_event e = super # add_event e; self # tcl_attach ~run_soon:true () method run() = (* Calling this method is an error! *) failwith "tcl_event_system#run: This method is disabled. Run the TCL event loop instead!" end ;; ocamlnet-4.1.2/src/netstring/0000755000175000017500000000000012731530350014547 5ustar gerdgerdocamlnet-4.1.2/src/netstring/netaux.ml0000644000175000017500000000723112731530350016410 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) module KMP = struct type pattern = { len : int; p : string; fail : int array; rex : Netstring_str.regexp; } let rec delta pat state c = if pat.p.[state] = c then state + 1 else if state = 0 then 0 else delta pat pat.fail.(state - 1) c let make_pattern p = let l = String.length p in if l = 0 then invalid_arg "Netaux.KMP.make_pattern"; let rex = Netstring_str.regexp (Netstring_str.quote (String.make 1 p.[0])) in let pat = { len = l; p = p; fail = Array.make l 0; rex = rex } in for n = 0 to l - 2 do pat.fail.(n + 1) <- delta pat pat.fail.(n) p.[n] done; pat let run rex len p fail s endpos state pos = let rec run_loop state pos = if (state = len) || (pos = endpos) then (state,pos) else if p.[state] = (Bytes.get s pos) then run_loop (state+1) (pos+1) else if state = 0 then (* run_loop 0 (pos+1) *) run_regexp (pos+1) else let state' = fail.(state-1) in run_delta p.[state'] state' pos and run_delta c state pos = if c = Bytes.get s pos then run_loop (state+1) (pos+1) else if state = 0 then run_loop 0 (pos+1) else let state' = fail.(state-1) in run_delta p.[state'] state' pos and run_regexp pos = (* Does the same as [run_loop 0 pos], but uses regexps to skip all the * non-matching characters. Improves the speed of bytecode dramatically, * but does not cost very much for native code. *) let pos' = try (* Note: setting s.[endpos] <- p.[0] would be a working guard, * but this might lead to problems in multi-threaded programs. * So we don't do it here. Better fix Pcre someday... *) let p, _ = Netstring_str.search_forward_bytes rex s pos in (* FIXME: no ~len *) p with Not_found -> endpos in if pos' < endpos then run_loop 0 pos' else run_loop 0 endpos in run_loop state pos let find_pattern pat ?(pos=0) ?len s = let endpos = match len with None -> Bytes.length s | Some l -> pos+l in if pos < 0 || endpos > Bytes.length s || pos > endpos then invalid_arg "Netaux.KMP.find_pattern"; let (state,pos) = run pat.rex pat.len pat.p pat.fail s endpos 0 pos in pos - state end module ArrayAux = struct let int_blit_ref = ref (fun (src:int array) srcpos dest destpos len -> (* A specialised version of Array.blit for int arrays. * Faster than the polymorphic Array.blit for * various reasons. *) if (len < 0 || srcpos < 0 || srcpos+len > Array.length src || destpos < 0 || destpos+len > Array.length dest) then invalid_arg "Netaux.ArrayAux.int_blit"; if src != dest || destpos <= srcpos then ( for i = 0 to len-1 do Array.unsafe_set dest (destpos+i) (Array.unsafe_get src (srcpos+i)) done ) else ( for i = len-1 downto 0 do Array.unsafe_set dest (destpos+i) (Array.unsafe_get src (srcpos+i)) done ) ) let int_blit src srcpos dest destpos len = !int_blit_ref src srcpos dest destpos len let int_series_ref = ref (fun src srcpos dst dstpos len n -> if (len < 0 || srcpos < 0 || dstpos < 0 || srcpos+len > Array.length src || dstpos+len > Array.length dst) then invalid_arg "Netaux.ArrayAux.int_series"; let s = ref n in for i = 0 to len-1 do Array.unsafe_set dst (dstpos+i) !s; s := !s + Array.unsafe_get src (srcpos+i) done ) let int_series src srcpos dst dstpos len n = !int_series_ref src srcpos dst dstpos len n end ocamlnet-4.1.2/src/netstring/neturl_ldap.ml0000644000175000017500000001134412731530350017415 0ustar gerdgerdopen Neturl open Printf let make_ldap_url ?(encoded=false) ?host ?addr ?port ?socksymbol ?dn ?attributes ?scope ?filter ?extensions () = let enc = Netencoding.Url.encode ~plus:false in let path = if dn=None && attributes=None && scope=None && filter=None && extensions=None then [] else match dn with | None -> [ ""; "" ] | Some s -> [ ""; s ] in let q4 = match extensions with | None -> "" | Some l -> "?" ^ String.concat "," (List.map (fun (crit,name,valopt) -> sprintf "%s%s%s" (if crit then "!" else "") (enc name) (match valopt with | None -> "" | Some v -> "=" ^ enc v ) ) l ) in let q3 = match filter with | None -> if q4 = "" then "" else "?" ^ q4 | Some s -> "?" ^ enc s ^ q4 in let q2 = match scope with | None -> if q3 = "" then "" else "?" ^ q3 | Some `Base -> "?base" ^ q3 | Some `Sub -> "?sub" ^ q3 | Some `One -> "?one" ^ q3 in let q1 = match attributes with | None -> if q2 = "" then "" else q2 | Some l -> String.concat "," (List.map enc l) ^ q2 in let query = if q1 = "" then None else Some q1 in let u1 = make_url ~encoded ~scheme:"ldap" ?host ?addr ?port ?socksymbol ~path Neturl.ldap_url_syntax in modify_url ~encoded:true ?query u1 let nth_query_part q n = let l = String.length q in let rec extract start n k = if n=0 then if k >= l || q.[k] = '?' then String.sub q start (k-start) else extract start n (k+1) else if k >= l then raise Not_found else if q.[k] = '?' then extract (k+1) (n-1) (k+1) else extract start n (k+1) in assert(n>=0); extract 0 n 0 let ldap_url_dn ?(encoded=false) u = match url_path ~encoded u with | [ ""; dn ] -> dn | [] -> raise Not_found | _ -> raise Malformed_URL let comma_re = Netstring_str.regexp "," let ldap_url_attributes ?(encoded=false) u = let query = url_query ~encoded:true u in let q_atts = nth_query_part query 0 in let atts = Netstring_str.split comma_re q_atts in if encoded then atts else List.map (Netencoding.Url.decode ~plus:false) atts let ldap_url_scope u = let query = url_query ~encoded:true u in let q_scope = nth_query_part query 1 in match String.lowercase q_scope with | "" | "base" -> `Base | "one" -> `One | "sub" -> `Sub | _ -> raise Malformed_URL let ldap_url_filter ?(encoded=false) u = let query = url_query ~encoded:true u in let q_flt = nth_query_part query 2 in if encoded then q_flt else Netencoding.Url.decode ~plus:false q_flt let ext_re = Netstring_str.regexp "!?\\([0-9a-zA-Z.%-]+\\)\\(=\\(.*\\)\\)$" let ldap_url_extensions ?(encoded=false) u = let query = url_query ~encoded:true u in let q_exts = nth_query_part query 3 in let exts1 = Netstring_str.split comma_re q_exts in List.map (fun ext1 -> match Netstring_str.string_match ext_re ext1 0 with | None -> raise Malformed_URL | Some m -> let crit = ext1.[0] = '!' in let name1 = Netstring_str.matched_group m 1 ext1 in let value1 = try Some(Netstring_str.matched_group m 3 ext1) with Not_found -> None in let name = if encoded then name1 else Netencoding.Url.decode ~plus:false name1 in let value = if encoded then value1 else match value1 with | None -> None | Some s -> Some(Netencoding.Url.decode ~plus:false s) in (crit,name,value) ) exts1 let ldap_url_provides ?(dn=false) ?(attributes=false) ?(scope=false) ?(filter=false) ?(extensions=false) u = let query_comp_present n = try let query = url_query ~encoded:true u in ignore(nth_query_part query n); true with Not_found -> false in let dn_ok = not dn || Neturl.url_path u <> [] in let attributes_ok = not attributes || query_comp_present 0 in let scope_ok = not scope || query_comp_present 1 in let filter_ok = not filter || query_comp_present 2 in let exts_ok = not extensions || query_comp_present 3 in dn_ok && attributes_ok && scope_ok && filter_ok && exts_ok ocamlnet-4.1.2/src/netstring/netx509_rsa.ml0000644000175000017500000000265712731530350017174 0ustar gerdgerd(* details in RFC-3447 *) (* type private_key_v0 = { modulus : XXX; public_exponent : int; private_exponent : int; prime1 : XXX; prime2 : XXX; exponent1 : XXX; exponent2 : XXX; coefficient : XXX; } type other_prime_info = { opi_prime : XXX; opi_exponent : XXX; opi_coefficient : XXX } type private_key = | V0 of private_key_v0 | V1 of private_key_v0 * other_prime_info list val decode_der : string -> private_key (* val v : Netasn1.Value.value = Netasn1.Value.Seq [Netasn1.Value.Integer ; Netasn1.Value.Integer ; Netasn1.Value.Integer ; Netasn1.Value.Integer ; Netasn1.Value.Integer ; Netasn1.Value.Integer ; Netasn1.Value.Integer ; Netasn1.Value.Integer ; Netasn1.Value.Integer ] *) type public_key = { modulus : XXX; exponent : int; } (* val v : Netasn1.Value.value = Netasn1.Value.Seq [Netasn1.Value.Seq [Netasn1.Value.OID [|1; 2; 840; 113549; 1; 1; 1|]; Netasn1.Value.Null]; Netasn1.Value.Bitstring ] let Netasn1.Value.Seq[_; Netasn1.Value.Bitstring bs] = v;; let pubkey = Netasn1.Value.get_bitstring_data bs;; let n,pubkey_der = Netasn1.decode_ber pubkey;; val n : int = 270 val pubkey_der : Netasn1.Value.value = Netasn1.Value.Seq [Netasn1.Value.Integer ; Netasn1.Value.Integer ] *) *) ocamlnet-4.1.2/src/netstring/netdn.ml0000644000175000017500000002107512731530350016216 0ustar gerdgerd(* $Id$ *) open Printf type oid = Netoid.t type dn = (oid * Netasn1.Value.value) list list module type AT_LOOKUP = sig val attribute_types : (oid * string * string list) list val lookup_attribute_type_by_oid : oid -> string * string list val lookup_attribute_type_by_name : string -> oid * string * string list end module type DN_string = sig val parse : string -> dn val print : dn -> string end let () = Netmappings_asn1.init() (* ensure that asn1 tables are linked in *) let directory_string_from_ASN1 value = let fail_enc() = failwith "Netx509.directory_string_from_ASN1: bad input encoding" in match value with | Netasn1.Value.UTF8String s -> ( try Netconversion.verify `Enc_utf8 s with Netconversion.Malformed_code_at _ -> fail_enc() ); s | Netasn1.Value.PrintableString s -> ( try Netconversion.convert ~in_enc:`Enc_asn1_printable ~out_enc:`Enc_utf8 s with Netconversion.Malformed_code -> fail_enc() ) | Netasn1.Value.IA5String s -> ( try Netconversion.convert ~in_enc:`Enc_usascii ~out_enc:`Enc_utf8 s with Netconversion.Malformed_code -> fail_enc() ) | Netasn1.Value.TeletexString s -> ( try Netconversion.convert ~in_enc:`Enc_asn1_T61 ~out_enc:`Enc_utf8 s with Netconversion.Malformed_code -> fail_enc() ) | Netasn1.Value.BMPString s -> ( try Netconversion.convert ~in_enc:`Enc_utf16_be ~out_enc:`Enc_utf8 s with Netconversion.Malformed_code -> fail_enc() ) | Netasn1.Value.UniversalString s -> ( try Netconversion.convert ~in_enc:`Enc_utf32_be ~out_enc:`Enc_utf8 s with Netconversion.Malformed_code -> fail_enc() ) | _ -> failwith "Netx509.directory_string_from_ASN1: \ unsupported ASN.1 value type" module DN_string_generic(L : AT_LOOKUP) = struct type token = | Space | Quote | Hash | Plus | Comma | Semi | Less | Equal | Greater | Text of (string * bool) (* bool: whether there were escaped chars when decoding the text *) let illegal_esc() = failwith "Netdn.DN_string.parse: illegal escape sequence" let syntax_error() = failwith "Netdn.DN_string.parse: syntax error" let hex_val s = int_of_string ("0x" ^ s) let tokenize s = let l = String.length s in let b = Buffer.create 80 in let b_esc = ref false in let rec next k = if k < l then ( match s.[k] with | ' ' -> special Space (k+1) | '"' -> special Quote (k+1) | '#' -> special Hash (k+1) | '+' -> special Plus (k+1) | ',' -> special Comma (k+1) | ';' -> special Semi (k+1) | '<' -> special Less (k+1) | '=' -> special Equal (k+1) | '>' -> special Greater (k+1) | '\\' -> if k+1 < l then match s.[k+1] with | ( ' ' | '"' | '#' | '+' | ',' | ';' | '<' | '=' | '>' | '\\' ) as c -> Buffer.add_char b c; b_esc := true; next (k+2) | ( '0' .. '9' | 'A' .. 'F' | 'a' .. 'f' ) as c1 -> if k+2 < l then match s.[k+2] with | ( '0' .. '9' | 'A' .. 'F' | 'a' .. 'f' ) as c2 -> let h = Bytes.create 2 in Bytes.set h 0 c1; Bytes.set h 1 c2; let v = hex_val (Bytes.to_string h) in Buffer.add_char b (Char.chr v); b_esc := true; next (k+3) | _ -> illegal_esc() else illegal_esc() | _ -> illegal_esc() else illegal_esc() | c -> Buffer.add_char b c; next (k+1) ) else if Buffer.length b > 0 then [ Text (Buffer.contents b, !b_esc) ] else [] and special token k = if Buffer.length b > 0 then ( let u = Buffer.contents b in let e = !b_esc in Buffer.clear b; b_esc := false; Text(u,e) :: token :: next k ) else token :: next k in next 0 let rec skip_spaces toks = (* until the next Equal token *) match toks with | Space :: toks' -> skip_spaces toks' | Equal :: toks' -> toks | other :: toks' -> other :: skip_spaces toks' | [] -> [] let descr_re = Netstring_str.regexp "^[A-Za-z][A-Za-z0-9-]*$" let parse s = let rec parse_rdn cur toks = let toks = skip_spaces toks in match toks with | Text(name,esc) :: Equal :: toks1 -> if esc then illegal_esc(); if Netstring_str.string_match descr_re name 0 <> None then ( (* it's a descr *) let name_uc = String.uppercase name in let (oid, _, _) = try L.lookup_attribute_type_by_name name_uc with Not_found -> failwith ("Netdn.DN_string.parse: unknown attribute '" ^ name ^ "'") in parse_value cur oid toks1 ) else ( try let oid = Netoid.of_string name in parse_value cur oid toks1 with | _ -> syntax_error() ) | _ -> syntax_error() and parse_value cur oid toks = match toks with | Hash :: _ -> failwith "Netdn.DN_string.parse: hex-encoded values are not \ supported by this parser" | Space :: toks1 -> (* CHECK *) parse_value cur oid toks1 | _ -> parse_value_rest cur oid [] toks and parse_value_rest cur oid value toks = match toks with | Plus :: toks1 -> let ava = (oid, utf8 (String.concat "" (List.rev value))) in parse_rdn (ava :: cur) toks1 | Comma :: toks1 -> let ava = (oid, utf8 (String.concat "" (List.rev value))) in let rdn = List.rev (ava :: cur) in rdn :: parse_rdn [] toks1 | Text(s,_) :: toks1 -> parse_value_rest cur oid (s :: value) toks1 | Hash :: toks1 -> parse_value_rest cur oid ("#" :: value) toks1 | Equal :: toks1 -> parse_value_rest cur oid ("=" :: value) toks1 | Space :: toks1 -> parse_value_rest cur oid (" " :: value) toks1 | (Quote | Semi | Less | Greater) :: toks1 -> syntax_error() | [] -> let ava = (oid, utf8 (String.concat "" (List.rev value))) in let rdn = List.rev (ava :: cur) in [ rdn ] and utf8 s = try Netconversion.verify `Enc_utf8 s; Netasn1.Value.UTF8String s with | Netconversion.Malformed_code_at _ -> failwith "Netdn.DN_string.parse: not in UTF-8" in parse_rdn [] (tokenize s) let string_of_ava (oid, value) = let oid_str = try let (_, l) = L.lookup_attribute_type_by_oid oid in if l = [] then raise Not_found; List.hd l with Not_found -> Netoid.to_string oid in let u = directory_string_from_ASN1 value in let b = Buffer.create 80 in Buffer.add_string b oid_str; Buffer.add_char b '='; let l = String.length u in for k = 0 to l - 1 do match String.unsafe_get u k with | ' ' -> if k=0 || k=l-1 then Buffer.add_string b "\\20" else Buffer.add_char b ' ' | '#' -> if k=0 then Buffer.add_string b "\\23" else Buffer.add_char b '#' | ('"' | '+' | ',' | ';' | '<' | '>' | '\\') as c -> Buffer.add_string b (sprintf "\\%02x" (Char.code c)) | c -> Buffer.add_char b c done; Buffer.contents b let print dn = String.concat "," (List.map (fun rdn -> String.concat "+" (List.map string_of_ava rdn) ) dn ) end ocamlnet-4.1.2/src/netstring/netmech_spnego_http.ml0000644000175000017500000003451212731530350021143 0ustar gerdgerd(* $Id$ *) (* see RFC 4559 for SPNEGO for HTTP *) (* SPNEGO authenticates the whole TCP connection, and not the individual request. Our design how to handle this: - There is a new transport_layer_id: spnego_trans_id. This implies SPNEGO with "default configuration" and https. - If we get a www-authenticate: negotiate header from a server, and the current connection isn't for spnego_trans_id, we return a special code so that the request is re-routed to a new connection which is then bound to spnego_trans_id. - Type changes: * client_match may return a new tag for re-routing to a different trans_id: `Reroute. - Changes in Nethttp_client: * pass trans_id as part of client_match call * what to do for `Reroute: we always follow this. Check whether a connection with the new trans_id exists. If yes, use it. If not, create a new one. Trace for `Reroute: - new case for auth_state: `Resubmit of trans_id - generic_auth_session_for_challenge: test for `Reroute condition in initializer. If so, we still create the session, but [authenticate] immediately returns `Reroute. If the user has set the trans_id we MUST reject this auth method. - postprocess_complete_message_e: check whether content_response=`Reroute. set_auth_state `Resubmit. - From that point on, the request is handled as a special redirect - add_with_callback: check whether auth_state=`Resubmit. In this case, set the trans_id of the request and re-add *) (* Re-auth: Better: SPNEGO indicates `Accept on client_match, and reroutes the second request New auth_status: - `Continue_reroute. Returned for the first request. client_domain: return [ "/" ] *) open Printf let spnego_oid = [| 1;3;6;1;5;5;2 |] let spnego_trans_id = Nethttp.spnego_trans_id let map_opt f = function | None -> None | Some x -> Some(f x) module type PROFILE = sig val acceptable_transports_http : Nethttp.transport_layer_id list val acceptable_transports_https : Nethttp.transport_layer_id list val enable_delegation : bool val deleg_credential : exn option (* future: configure SPNEGO *) end module Default : PROFILE = struct let acceptable_transports_http = [ ] let acceptable_transports_https = [ spnego_trans_id ] let enable_delegation = true let deleg_credential = None end module SPNEGO(P:PROFILE)(G:Netsys_gssapi.GSSAPI) : Nethttp.HTTP_CLIENT_MECHANISM = struct module M = Netgssapi_auth.Manage(G) module C = struct let raise_error = failwith end module A = Netgssapi_auth.Auth(G)(C) let mechanism_name = "Negotiate" let available() = true (* FIXME: check whether spnego supported *) let restart_supported = true type credentials = unit let init_credentials _ = () let realm = "SPNEGO" let client_match ~params (challenge : Nethttp.Header.auth_challenge) = let param name = let (_, v, _) = List.find (fun (n, _, _) -> n = name) params in v in try let (ch_name, ch_params) = challenge in if String.lowercase ch_name <> "negotiate" then raise Not_found; let trans_id = int_of_string (param "trans_id") in let https = bool_of_string (param "https") in let acceptable_transports = if https then P.acceptable_transports_https else P.acceptable_transports_http in let is_acceptable_trans = List.mem trans_id acceptable_transports in if is_acceptable_trans then `Accept(realm, None) else match acceptable_transports with | [] -> raise Not_found | pref_id :: _ -> `Accept_reroute(realm, None, pref_id) with | Not_found -> `Reject type client_sub_state = [ `Pre_init_context | `Init_context | `Established | `Restart ] type client_session = { mutable ccontext : G.context option; cstate : Netsys_sasl_types.client_state; csubstate : client_sub_state; ctoken : string; cconn : int; cconf : Netsys_gssapi.client_config; ctarget_name : G.name; ccred : G.credential; cprops : Netsys_gssapi.client_props option; } let client_state cs = cs.cstate let client_del_ctx cs = match cs.ccontext with | None -> cs | Some ctx -> M.delete_context cs.ccontext (); { cs with ccontext = None } let cvalidity cs0 = let cs1 = {cs0 with ccontext = cs0.ccontext} in cs0.ccontext <- None; cs1 let check_gssapi_status fn_name ((calling_error,routine_error,_) as major_status) minor_status = if calling_error <> `None || routine_error <> `None then ( let msg = M.format_status ~fn:fn_name ~minor_status major_status in failwith msg ) let client_check_gssapi_status cs fn_name major_status minor_status = try check_gssapi_status fn_name major_status minor_status with | error -> ignore(client_del_ctx cs); raise error let call_init_sec_context cs input_token = let (out_context, out_token, ret_flags, props_opt) = A.init_sec_context ~initiator_cred:cs.ccred ~context:cs.ccontext ~target_name:cs.ctarget_name ~req_flags:(A.get_client_flags cs.cconf) ~chan_bindings:None ~input_token cs.cconf in let cs = { cs with ccontext = Some out_context; ctoken = out_token; cprops = props_opt; } in let auth_done = (props_opt <> None) in if auth_done then ( let cs = { cs with cstate = if out_token = "" then `OK else `Emit; csubstate = `Established; } in client_del_ctx cs; (* no longer needed *) ) else { cs with cstate = `Emit; csubstate = `Init_context } let create_client_session ~user ~creds ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_krb5_sasl.create_client_session:" [ "realm"; "id"; "target-host"; "trans_id"; "conn_id"; "https" ] params in let conn_id = try int_of_string (List.assoc "conn_id" params) with Not_found -> failwith "missing parameter: conn_id" in let acceptor_name = try "HTTP@" ^ List.assoc "target-host" params with | Not_found -> failwith "missing parameter 'target-host'" in let acceptor_name_type = Netsys_gssapi.nt_hostbased_service in let cconf = Netsys_gssapi.create_client_config ~mech_type:spnego_oid ~target_name:(acceptor_name, acceptor_name_type) ~privacy:`If_possible ~integrity:`Required ~flags:( [ `Mutual_flag, `Required ] @ ( if P.enable_delegation then [`Deleg_flag, `Required] else [] ) ) () in let ctarget_name = A.get_target_name cconf in let ccred = match P.deleg_credential with | Some (G.Credential c) -> c | _ -> G.interface # no_credential in let cstate = `Wait (* HTTP auth is always "server-first" *) in let cs = { ccontext = None; cstate; csubstate = `Pre_init_context; ctoken = ""; ctarget_name; cconf; cconn = conn_id; ccred; cprops = None; } in cs let client_configure_channel_binding cs cb = if cb <> `None then failwith "Netmech_spnego_http.client_configure_channel_binding: \ not supported" else cs let client_state cs = cs.cstate let client_channel_binding cs = `None let client_restart ~params cs = (* There is actually no restart protocol. As we authenticate the TCP connection, we just claim we can restart. *) if cs.cstate <> `OK then failwith "Netmech_spnego_http.client_restart: unfinished auth"; let cs = cvalidity cs in let params = Netsys_sasl_util.preprocess_params "Netmech_krb5_sasl.create_client_session:" [ "realm"; "id"; "target-host"; "trans_id"; "conn_id"; "https" ] params in let conn_id = try int_of_string (List.assoc "conn_id" params) with Not_found -> failwith "missing parameter: conn_id" in let cs = { cs with ccontext = None; cstate = `Emit; ctoken = ""; csubstate = `Pre_init_context; cconn = conn_id; } in call_init_sec_context cs None let client_context cs = match cs.ccontext with | None -> failwith "client_context" | Some c -> c let client_process_challenge cs meth uri hdr challenge = let cs = cvalidity cs in try if cs.cstate <> `Wait then failwith "protocol error"; let (ch_name, ch_params) = challenge in if String.lowercase ch_name <> "negotiate" then failwith "bad auth scheme"; let msg = match ch_params with | [ "credentials", `V msg ] -> msg | [] -> "" | _ -> failwith "bad www-authenticate header" in let msg = try Netencoding.Base64.decode msg with | Invalid_argument _ -> failwith "Base64 error" in match cs.csubstate with | `Pre_init_context -> if msg <> "" then failwith "unexpected token"; call_init_sec_context cs None (* sets cs.cstate to `Emit *) | `Init_context -> call_init_sec_context cs (Some msg) | `Restart -> (* THIS PATH IS CURRENTLY NOT TAKEN: on restart, we directly enter `Pre_init_context state, and generate the token *) (* As SPNEGO authenticates the connection and not the message, we are done when the server responds with a non-401 message, and there is no www-authenticate (here: ch_params=[]). Otherwise, handle it like `Pre_init_context, and re-run the protocol. *) if ch_params = [] then ( { cs with cstate = `OK; csubstate = `Established } ) else call_init_sec_context cs None (* sets cs.cstate to `Emit *) | `Established -> failwith "unexpected token" with | Failure msg -> let cs = client_del_ctx cs in { cs with cstate = `Auth_error msg } let client_emit_response cs meth uri hdr = if cs.cstate <> `Emit then failwith "Netmech_spnego_http.client_emit_response: bad state"; let cs = match cs.csubstate with | `Pre_init_context -> assert false | `Established -> let cs = client_del_ctx cs in { cs with cstate = `OK } | _ -> { cs with cstate = `Wait } in let b64 = Netencoding.Base64.encode cs.ctoken in let creds = ( "Negotiate", if cs.ctoken="" then [] else [ "credentials", `Q b64 ] ) in (* NB. The case creds=(something,[]) is special-cased in the http client, so that no auth header is added at all *) (cs, creds, []) let client_session_id cs = None let client_prop cs key = raise Not_found let client_gssapi_props cs = match cs.cprops with | None -> raise Not_found | Some p -> p let client_user_name cs = "" let client_authz_name cs = "" let client_stash_session cs = (* GSSAPI does not support that unfinished contexts are exported. We do not need the context anyway after session establishment, so we don't save it at all. *) if cs.cstate <> `OK then failwith "Netmech_spnego_http.client_stash_session: the session \ must be established (implementation restriction)"; "client,t=SPNEGO;" ^ Marshal.to_string (map_opt Netsys_gssapi.marshal_client_props cs.cprops) [] let cs_re = Netstring_str.regexp "client,t=SPNEGO;" let client_resume_session s = match Netstring_str.string_match cs_re s 0 with | None -> failwith "Netmech_spnego_http.client_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let (mprops) = Marshal.from_string data 0 in { ccontext = None; cstate = `OK; csubstate = `Established; ctoken = ""; ctarget_name = G.interface # no_name; cconn = 0; (* FIXME *) cconf = Netsys_gssapi.create_client_config(); ccred = G.interface # no_credential; cprops = map_opt Netsys_gssapi.unmarshal_client_props mprops; } let client_domain s = [ "/" ] (* This way the auth sessions get cached *) end (* #use "topfind";; #require "netclient,netgss-system,nettls-gnutls";; module D = Netmech_spnego_http.Default;; module D = struct include Netmech_spnego_http.Default let enable_delegation=true end;; module A = Netmech_spnego_http.SPNEGO(D)(Netgss.System);; open Nethttp_client;; Debug.enable := true;; let keys = new key_ring ~no_invalidation:true ();; keys # add_key (key ~user:"krb" ~password:"" ~realm:"SPNEGO" ~domain:[]);; let a = new generic_auth_handler keys [ (module A : Nethttp.HTTP_CLIENT_MECHANISM) ];; let p = new pipeline;; p # add_auth_handler a;; let c1 = new get "https://gps.dynxs.de/krb/";; let c2 = new get "https://gps.dynxs.de/krb/index.html";; p # add c1;; p # add c2;; p # run();; p # add_with_callback c1 (fun _ -> p # add c2);; p # run();; c2 # set_transport_layer Nethttp_client.spnego_trans_id;; p # add_with_callback c1 (fun _ -> p # add c2);; p # run();; *) ocamlnet-4.1.2/src/netstring/neturl.ml0000644000175000017500000014650312731530350016423 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) open Printf exception Malformed_URL type url_syntax_option = Url_part_not_recognized | Url_part_allowed | Url_part_required type url_syntax = { url_enable_scheme : url_syntax_option; url_enable_user : url_syntax_option; url_enable_user_param : url_syntax_option; url_enable_password : url_syntax_option; url_enable_host : url_syntax_option; url_enable_port : url_syntax_option; url_enable_path : url_syntax_option; url_enable_param : url_syntax_option; url_enable_query : url_syntax_option; url_enable_fragment : url_syntax_option; url_enable_other : url_syntax_option; url_accepts_8bits : bool; url_is_valid : url -> bool; url_enable_relative : bool; } and url = { url_syntax : url_syntax; mutable url_validity : bool; url_scheme : string option; url_user : string option; url_user_param : string list; url_password : string option; url_host : string option; url_port : int option; url_path : string list; url_param : string list; url_query : string option; url_fragment : string option; url_other : string option; } ;; type char_category = Accepted | Rejected | Separator let scan_url_part s k_from k_to cats accept_8bits = (* Scans the longest word of accepted characters from position 'k_from' * in 's' until at most position 'k_to'. The character following the * word (if any) must be a separator character. * On success, the function returns the position of the last character * of the word + 1. * If there is any rejected character before the separator or the end * of the string (i.e. position 'k_to') is reached, the exception * Malformed_URL is raised. * Furthermore, if the character '%' is accepted it is checked whether * two hexadecimal digits follow (which must be accepted, too). If this * is not true, the exception Malformed_URL is raised, too. * 'cats': contains for every character code (0 to 255) the category * of the character. *) let check_hex c = if cats.( Char.code c ) <> Accepted then raise Malformed_URL; match c with ('0'..'9'|'A'..'F'|'a'..'f') -> () | _ -> raise Malformed_URL in let rec scan k = if k >= k_to then k else begin let c = s.[k] in let cat = cats.(Char.code c) in match cat with Accepted -> if c = '%' then begin if k+2 >= k_to then raise Malformed_URL; let c1 = s.[k+1] in let c2 = s.[k+2] in check_hex c1; check_hex c2; scan (k+3) end else scan (k+1) | Separator -> k | Rejected -> if accept_8bits && c >= '\128' then scan (k+1) else raise Malformed_URL end in assert (Array.length cats = 256); assert (k_from >= 0); assert (k_from <= k_to); assert (k_to <= String.length s); scan k_from ;; (* Create a categorization: *) let lalpha = [ 'a'; 'b'; 'c'; 'd'; 'e'; 'f'; 'g'; 'h'; 'i'; 'j'; 'k'; 'l'; 'm'; 'n'; 'o'; 'p'; 'q'; 'r'; 's'; 't'; 'u'; 'v'; 'w'; 'x'; 'y'; 'z' ] let ualpha = [ 'A'; 'B'; 'C'; 'D'; 'E'; 'F'; 'G'; 'H'; 'I'; 'J'; 'K'; 'L'; 'M'; 'N'; 'O'; 'P'; 'Q'; 'R'; 'S'; 'T'; 'U'; 'V'; 'W'; 'X'; 'Y'; 'Z' ] let digit = [ '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9' ] let hex_digit = [ 'a'; 'b'; 'c'; 'd'; 'e'; 'f'; 'A'; 'B'; 'C'; 'D'; 'E'; 'F'; ] @ digit let safe = [ '$'; '-'; '_'; '.'; '+' ] let extra = [ '!'; '*'; '\''; '('; ')'; ',' ] let make_cats accepted separators = (* create a categorization: * - All characters listed in 'separators' are separators. * - All characters listed in 'accepted' and which do not occur in * 'separators' are accepted characters. * - All other characters are rejected. *) let cats = Array.make 256 Rejected in List.iter (fun c -> cats.(Char.code c) <- Accepted ) accepted; List.iter (fun c -> cats.(Char.code c) <- Separator ) separators; cats ;; let scheme_cats = make_cats (lalpha @ ualpha @ ['+'; '-'; '.']) [':'] ;; (* scheme_cats: character categorization to _extract_ the URL scheme *) let login_cats = make_cats (lalpha @ ualpha @ digit @ safe @ extra @ [';'; '&'; '='; '%']) [':'; '@'; '/'; '#'; '?' ] ;; (* login_cats: character categorization to _extract_ user name, password, * host name, and port. * * Note: user_params are extracted in a second step. * * Note: '?' is now a separator, as described in RFC 2396. *) let host_cats = make_cats (lalpha @ ualpha @ digit @ ['.'; '-']) [] ;; (* host_cats: character categorization to _check_ whether the host name * is formed only by legal characters. * Especially '%' is not allowed here! * IPv6 addresses are checked separately. *) let ipv6_cats = make_cats (hex_digit @ [ ':' ]) [ ] let ipv6_sep_cats = make_cats (hex_digit @ [ ':' ]) [ ']' ] let port_cats = make_cats digit [] ;; (* port_cats: character categorization to _check_ whether the port number * is formed only by legal characters. * Especially '%' is not allowed here! *) let path_cats separators = make_cats (lalpha @ ualpha @ digit @ safe @ extra @ ['?'; ':'; '@'; '&'; '='; ';'; '%'; '/'; '~']) separators ;; let separators_from_syntax syn = let include_if syn_option clist = if syn_option <> Url_part_not_recognized then clist else [] in (include_if syn.url_enable_param [';']) @ (include_if syn.url_enable_query ['?']) @ (include_if syn.url_enable_fragment ['#']) ;; let path_cats_from_syntax syn extraseps = let separators = separators_from_syntax syn in path_cats (separators @ extraseps) ;; (* path_cats_from_syntax: * Computes a character categorization to extract the path from an URL. * This depends on the syntax because the list of possible separators * contains the characters that may begin the next URL clause. * * Notes: * - The '#' is rejected unless fragments are enabled. * - The '~' is accepted although this violates RFC 1738 (but it is ok * according to RFC 2396) *) let other_cats_from_syntax syn = let include_if syn_option clist = if syn_option <> Url_part_not_recognized then clist else [] in let separators = (include_if syn.url_enable_param [';']) @ (include_if syn.url_enable_query ['?']) @ (include_if syn.url_enable_fragment ['#']) in make_cats (lalpha @ ualpha @ digit @ safe @ extra @ (separators @ ['?'; ':'; '@'; '&'; '='; ';'; '%'; '/'])) [] ;; (* other_cats: character categorization to extract or check the * "other" part of the URL. *) let extract_url_scheme s = let l = String.length s in let k = scan_url_part s 0 l scheme_cats false in (* or raise Malformed_URL *) if k = l then raise Malformed_URL; assert (s.[k] = ':'); String.lowercase(String.sub s 0 k) ;; let ( => ) a b = not a || b;; (* implication *) let ( <=> ) (a:bool) b = ( a = b );; (* equivalence *) let url_syntax_is_valid syn = let recognized x = x <> Url_part_not_recognized in let _not_recognized x = x = Url_part_not_recognized in (recognized syn.url_enable_password => recognized syn.url_enable_user) && (recognized syn.url_enable_user_param => recognized syn.url_enable_user) && (recognized syn.url_enable_port => recognized syn.url_enable_host) && (recognized syn.url_enable_user => recognized syn.url_enable_host) && not ( (recognized syn.url_enable_user || recognized syn.url_enable_password || recognized syn.url_enable_host || recognized syn.url_enable_port || recognized syn.url_enable_path) && (recognized syn.url_enable_other)) ;; let partial_url_syntax syn = let weaken = function Url_part_not_recognized -> Url_part_not_recognized | Url_part_allowed -> Url_part_allowed | Url_part_required -> Url_part_allowed in if not syn.url_enable_relative then failwith "Neturl.partial_url_syntax: This syntax does not support relative URLs"; { url_enable_scheme = weaken syn.url_enable_scheme; url_enable_user = weaken syn.url_enable_user; url_enable_user_param= weaken syn.url_enable_user_param; url_enable_password = weaken syn.url_enable_password; url_enable_host = weaken syn.url_enable_host; url_enable_port = weaken syn.url_enable_port; url_enable_path = weaken syn.url_enable_path; url_enable_param = weaken syn.url_enable_param; url_enable_query = weaken syn.url_enable_query; url_enable_fragment = weaken syn.url_enable_fragment; url_enable_other = weaken syn.url_enable_other; url_accepts_8bits = syn.url_accepts_8bits; url_is_valid = syn.url_is_valid; url_enable_relative = true; } ;; let file_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_not_recognized; url_enable_user_param= Url_part_not_recognized; url_enable_password = Url_part_not_recognized; url_enable_host = Url_part_allowed; url_enable_port = Url_part_not_recognized; url_enable_path = Url_part_required; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_not_recognized; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = true; } ;; let ftp_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_allowed; url_enable_user_param= Url_part_not_recognized; url_enable_password = Url_part_allowed; url_enable_host = Url_part_required; url_enable_port = Url_part_allowed; url_enable_path = Url_part_allowed; url_enable_param = Url_part_allowed; url_enable_query = Url_part_not_recognized; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = true; } ;; let http_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_allowed; url_enable_user_param= Url_part_not_recognized; url_enable_password = Url_part_allowed; url_enable_host = Url_part_required; url_enable_port = Url_part_allowed; url_enable_path = Url_part_allowed; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_allowed; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = true; } ;; let pop_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_allowed; url_enable_user_param= Url_part_allowed; url_enable_password = Url_part_allowed; url_enable_host = Url_part_required; url_enable_port = Url_part_allowed; url_enable_path = Url_part_not_recognized; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_not_recognized; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = false; } ;; let imap_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_allowed; url_enable_user_param= Url_part_allowed; url_enable_password = Url_part_allowed; url_enable_host = Url_part_required; url_enable_port = Url_part_allowed; url_enable_path = Url_part_allowed; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_allowed; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = true; } ;; let mailto_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_not_recognized; url_enable_user_param= Url_part_not_recognized; url_enable_password = Url_part_not_recognized; url_enable_host = Url_part_not_recognized; url_enable_port = Url_part_not_recognized; url_enable_path = Url_part_not_recognized; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_allowed; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_required; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = false; } ;; let news_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_not_recognized; url_enable_user_param= Url_part_not_recognized; url_enable_password = Url_part_not_recognized; url_enable_host = Url_part_not_recognized; url_enable_port = Url_part_not_recognized; url_enable_path = Url_part_not_recognized; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_not_recognized; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_required; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = false; } ;; let cid_url_syntax = news_url_syntax;; let data_url_syntax = news_url_syntax;; let nntp_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_not_recognized; url_enable_user_param= Url_part_not_recognized; url_enable_password = Url_part_not_recognized; url_enable_host = Url_part_required; url_enable_port = Url_part_allowed; url_enable_path = Url_part_required; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_not_recognized; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun url -> List.length url.url_path = 3 ); url_enable_relative = true; } ;; let ipp_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_not_recognized; url_enable_user_param= Url_part_not_recognized; url_enable_password = Url_part_not_recognized; url_enable_host = Url_part_required; url_enable_port = Url_part_allowed; url_enable_path = Url_part_allowed; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_allowed; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = true; } ;; let null_url_syntax = { url_enable_scheme = Url_part_not_recognized; url_enable_user = Url_part_not_recognized; url_enable_user_param= Url_part_not_recognized; url_enable_password = Url_part_not_recognized; url_enable_host = Url_part_not_recognized; url_enable_port = Url_part_not_recognized; url_enable_path = Url_part_not_recognized; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_not_recognized; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = false; } ;; let ip_url_syntax = { url_enable_scheme = Url_part_allowed; url_enable_user = Url_part_allowed; url_enable_user_param= Url_part_not_recognized; (* so user parameters are parsed as part * of the user string! (Most generic.) *) url_enable_password = Url_part_allowed; url_enable_host = Url_part_allowed; url_enable_port = Url_part_allowed; url_enable_path = Url_part_allowed; url_enable_param = Url_part_allowed; url_enable_query = Url_part_allowed; url_enable_fragment = Url_part_allowed; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = true; } ;; let ldap_url_syntax = { url_enable_scheme = Url_part_required; url_enable_user = Url_part_not_recognized; url_enable_user_param= Url_part_not_recognized; url_enable_password = Url_part_not_recognized; url_enable_host = Url_part_allowed; url_enable_port = Url_part_allowed; url_enable_path = Url_part_allowed; url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_allowed; url_enable_fragment = Url_part_not_recognized; url_enable_other = Url_part_not_recognized; url_accepts_8bits = false; url_is_valid = (fun _ -> true); url_enable_relative = true; } ;; let common_url_syntax = let h = Hashtbl.create 10 in Hashtbl.add h "file" file_url_syntax; Hashtbl.add h "ftp" ftp_url_syntax; Hashtbl.add h "http" http_url_syntax; Hashtbl.add h "https" http_url_syntax; Hashtbl.add h "pop" pop_url_syntax; Hashtbl.add h "pops" pop_url_syntax; Hashtbl.add h "imap" imap_url_syntax; Hashtbl.add h "imaps" imap_url_syntax; Hashtbl.add h "mailto" mailto_url_syntax; Hashtbl.add h "news" news_url_syntax; Hashtbl.add h "nntp" nntp_url_syntax; Hashtbl.add h "nntps" nntp_url_syntax; Hashtbl.add h "cid" cid_url_syntax; Hashtbl.add h "mid" cid_url_syntax; Hashtbl.add h "data" data_url_syntax; Hashtbl.add h "ipp" ipp_url_syntax; Hashtbl.add h "ipps" ipp_url_syntax; Hashtbl.add h "ldap" ldap_url_syntax; Hashtbl.add h "ldaps" ldap_url_syntax; h ;; let url_conforms_to_syntax url = let recognized x = x <> Url_part_not_recognized in let required x = x = Url_part_required in let present x = x <> None in let syn = url.url_syntax in (present url.url_scheme => recognized syn.url_enable_scheme) && (present url.url_user => recognized syn.url_enable_user) && ((url.url_user_param <> []) => recognized syn.url_enable_user_param) && (present url.url_password => recognized syn.url_enable_password) && (present url.url_host => recognized syn.url_enable_host) && (present url.url_port => recognized syn.url_enable_port) && ((url.url_path <> []) => recognized syn.url_enable_path) && ((url.url_param <> []) => recognized syn.url_enable_param) && (present url.url_query => recognized syn.url_enable_query) && (present url.url_fragment => recognized syn.url_enable_fragment) && (present url.url_other => recognized syn.url_enable_other) && (required syn.url_enable_scheme => present url.url_scheme) && (required syn.url_enable_user => present url.url_user) && (required syn.url_enable_user_param => (url.url_user_param <> [])) && (required syn.url_enable_password => present url.url_password) && (required syn.url_enable_host => present url.url_host) && (required syn.url_enable_port => present url.url_port) && (required syn.url_enable_path => (url.url_path <> [])) && (required syn.url_enable_param => (url.url_param <> [])) && (required syn.url_enable_query => present url.url_query) && (required syn.url_enable_fragment => present url.url_fragment) && (required syn.url_enable_other => present url.url_other) && (url.url_validity || syn.url_is_valid url) ;; let url_syntax_of_url url = url.url_syntax ;; let host_of_addr ip = match Netsys.domain_of_inet_addr ip with | Unix.PF_INET -> Unix.string_of_inet_addr ip | Unix.PF_INET6 -> "[" ^ Unix.string_of_inet_addr ip ^ "]" | _ -> assert false let modify_url ?syntax ?(encoded = false) ?scheme ?user ?user_param ?password ?host ?addr ?port ?socksymbol ?path ?param ?query ?fragment ?other url = let enc ?(plus=false) x = if encoded then x else match x with None -> None | Some x' -> Some (Netencoding.Url.encode ~plus x') in let enc_list ?(plus=false) l = if encoded then l else List.map (Netencoding.Url.encode ~plus) l in let new_syntax = match syntax with None -> url.url_syntax | Some syn -> syn in let check_string s_opt cats = match s_opt with None -> () | Some s -> let l = String.length s in let k = scan_url_part s 0 l cats new_syntax.url_accepts_8bits in (* or raise Malformed_URL *) if k <> l then raise Malformed_URL in let check_string_list p cats sep = List.iter (fun p_component -> let l = String.length p_component in let k = scan_url_part p_component 0 l cats new_syntax.url_accepts_8bits in (* or raise Malformed_URL *) if k <> l then raise Malformed_URL; if String.contains p_component sep then raise Malformed_URL; ) p in let check_host s = let l = String.length s in if String.length s >= 2 && s.[0] = '[' then ( if s.[l-1] <> ']' then raise Malformed_URL; let ipv6 = String.sub s 1 (l-2) in check_string (Some ipv6) ipv6_cats ) else check_string (Some s) host_cats in (* Create the modified record: *) let url_host_0 = match addr with | Some a -> Some(host_of_addr a) | None -> ( match host with | Some h -> Some h | None -> url.url_host ) in let url_port_0 = match port with | Some p -> Some p | None -> url.url_port in let (url_host, url_port) = match (socksymbol : Netsockaddr.socksymbol option) with | Some(`Inet(ip,p)) -> (Some(host_of_addr ip), Some p) | Some(`Inet_byname(h,p)) -> (Some h, Some p) | Some _ -> failwith "Neturl: Unacceptable socksymbol" | None -> (url_host_0, url_port_0) in let url' = { url_syntax = new_syntax; url_validity = false; url_scheme = if scheme = None then url.url_scheme else scheme; url_user = if user = None then url.url_user else enc user; url_user_param = ( match user_param with None -> url.url_user_param | Some p -> enc_list p); url_password = if password = None then url.url_password else enc password; url_host = url_host; url_port = url_port; url_path = (match path with None -> url.url_path | Some p -> enc_list p); url_param = (match param with None -> url.url_param | Some p -> enc_list p); url_query = if query = None then url.url_query else enc ~plus:true query; url_fragment = if fragment = None then url.url_fragment else enc fragment; url_other = if other = None then url.url_other else enc other; } in (* Check whether the URL conforms to the syntax: *) if not (url_conforms_to_syntax url') then raise Malformed_URL; if url'.url_password <> None && url'.url_user = None then raise Malformed_URL; if url'.url_user_param <> [] && url'.url_user = None then raise Malformed_URL; if url'.url_user <> None && url'.url_host = None then raise Malformed_URL; if url'.url_port <> None && url'.url_host = None then raise Malformed_URL; (* Check every part: *) check_string url'.url_scheme scheme_cats; check_string url'.url_user login_cats; check_string_list url'.url_user_param login_cats ';'; check_string url'.url_password login_cats; ( match url'.url_host with | None -> () | Some s -> check_host s ); (match url'.url_port with None -> () | Some p -> if p < 0 || p > 65535 then raise Malformed_URL ); let path_cats = path_cats_from_syntax new_syntax [] in let other_cats = other_cats_from_syntax new_syntax in let query_cats = let syn = { new_syntax with url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_not_recognized } in path_cats_from_syntax syn [] in check_string url'.url_query query_cats; check_string url'.url_fragment path_cats; check_string url'.url_other other_cats; (* Check the lists: *) check_string_list url'.url_param path_cats ';'; check_string_list url'.url_path path_cats '/'; (* Further path checks: *) begin match url'.url_path with [] -> (* The path is empty: There must not be 'param' *) if url'.url_host <> None then begin if url'.url_param <> [] then raise Malformed_URL; (* if url'.url_query <> None then raise Malformed_URL; * Allowed since RFC 2396 *) end | ["";""] -> (* This is illegal. *) raise Malformed_URL; | "" :: p' -> (* The path is absolute: ensure there is no double slash with host *) ( match url'.url_path with | "" :: "" :: _ -> (* Double slash at beginning of path: Only allowed we have * a host name! *) if host = None then raise Malformed_URL | _ -> () ) | _ -> (* The path is relative: there must not be a host *) if url'.url_host <> None then raise Malformed_URL; end; (* Cache that the URL is valid: *) url'.url_validity <- true; url' ;; let null_url = { url_syntax = null_url_syntax; url_validity = true; url_scheme = None; url_user = None; url_user_param = []; url_password = None; url_host = None; url_port = None; url_path = []; url_param = []; url_query = None; url_fragment = None; url_other = None; } ;; let make_url ?(encoded = false) ?scheme ?user ?user_param ?password ?host ?addr ?port ?socksymbol ?path ?param ?query ?fragment ?other syntax = if not (url_syntax_is_valid syntax) then invalid_arg "Neturl.make_url"; modify_url ~encoded ~syntax ?scheme ?user ?user_param ?password ?host ?addr ?port ?socksymbol ?path ?param ?query ?fragment ?other null_url ;; let remove_from_url ?(scheme = false) ?(user = false) ?(user_param = false) ?(password = false) ?(host = false) ?(port = false) ?(path = false) ?(param = false) ?(query = false) ?(fragment = false) ?(other = false) url = make_url ~encoded: true ?scheme: (if scheme then None else url.url_scheme) ?user: (if user then None else url.url_user) ?user_param:(if user_param then None else Some url.url_user_param) ?password: (if password then None else url.url_password) ?host: (if host then None else url.url_host) ?port: (if port then None else url.url_port) ?path: (if path then None else Some url.url_path) ?param: (if param then None else Some url.url_param) ?query: (if query then None else url.url_query) ?fragment: (if fragment then None else url.url_fragment) ?other: (if other then None else url.url_other) url.url_syntax ;; let default_url ?(encoded = false) ?scheme ?user ?(user_param = []) ?password ?host ?port ?(path = []) ?(param = []) ?query ?fragment ?other url = let encode = Netencoding.Url.encode ~plus:true in let enc x = if encoded then x else match x with None -> None | Some x' -> Some (encode x') in let enc_list l = if encoded then l else List.map encode l in let pass_if_missing current arg = match current with None -> arg | _ -> current in make_url ~encoded: true ?scheme: (pass_if_missing url.url_scheme scheme) ?user: (pass_if_missing url.url_user (enc user)) ~user_param:(if url.url_user_param = [] then enc_list user_param else url.url_user_param) ?password: (pass_if_missing url.url_password (enc password)) ?host: (pass_if_missing url.url_host host) ?port: (pass_if_missing url.url_port port) ~path: (if url.url_path = [] then enc_list path else url.url_path) ~param: (if url.url_param = [] then enc_list param else url.url_param) ?query: (pass_if_missing url.url_query (enc query)) ?fragment: (pass_if_missing url.url_fragment (enc fragment)) ?other: (pass_if_missing url.url_other (enc other)) url.url_syntax ;; let undefault_url ?scheme ?user ?user_param ?password ?host ?port ?path ?param ?query ?fragment ?other url = let remove_if_matching current arg = match current with None -> None | Some x -> (match arg with None -> current | Some x' -> if x=x' then None else current) in let remove_list_if_matching current arg = match arg with None -> current | Some x -> if x = current then [] else current in make_url ~encoded: true ?scheme: (remove_if_matching url.url_scheme scheme) ?user: (remove_if_matching url.url_user user) ~user_param:(remove_list_if_matching url.url_user_param user_param) ?password: (remove_if_matching url.url_password password) ?host: (remove_if_matching url.url_host host) ?port: (remove_if_matching url.url_port port) ~path: (remove_list_if_matching url.url_path path) ~param: (remove_list_if_matching url.url_param param) ?query: (remove_if_matching url.url_query query) ?fragment: (remove_if_matching url.url_fragment fragment) ?other: (remove_if_matching url.url_other other) url.url_syntax ;; let url_provides ?(scheme = false) ?(user = false) ?(user_param = false) ?(password = false) ?(host = false) ?(port = false) ?(path = false) ?(param = false) ?(query = false) ?(fragment = false) ?(other = false) url = (scheme => (url.url_scheme <> None)) && (user => (url.url_user <> None)) && (user_param => (url.url_param <> [])) && (password => (url.url_password <> None)) && (host => (url.url_host <> None)) && (port => (url.url_port <> None)) && (path => (url.url_path <> [])) && (param => (url.url_param <> [])) && (query => (url.url_query <> None)) && (fragment => (url.url_fragment <> None)) && (other => (url.url_other <> None)) ;; let return_if value = match value with None -> raise Not_found | Some x -> x ;; let decode_if ?(plus=false) want_encoded value = let value' = return_if value in if want_encoded then value' else Netencoding.Url.decode ~plus value' ;; let decode_path_if ?(plus=false) want_encoded value = if want_encoded then value else List.map (Netencoding.Url.decode ~plus) value ;; let url_scheme url = return_if url.url_scheme;; let url_user ?(encoded=false) url = decode_if encoded url.url_user;; let url_user_param ?(encoded=false) url = decode_path_if encoded url.url_user_param;; let url_password ?(encoded=false) url = decode_if encoded url.url_password;; let url_host url = return_if url.url_host;; let url_port url = return_if url.url_port;; let url_path ?(encoded=false) url = decode_path_if encoded url.url_path;; let url_param ?(encoded=false) url = decode_path_if encoded url.url_param;; let url_query ?(encoded=false) url = decode_if ~plus:true encoded url.url_query;; let url_fragment ?(encoded=false) url = decode_if encoded url.url_fragment;; let url_other ?(encoded=false) url = decode_if encoded url.url_other;; let url_addr url = match url.url_host with | None -> raise Not_found | Some h -> let l = String.length h in if l >= 2 && h.[0] = '[' && h.[l-1] = ']' then let a = String.sub h 1 (l-2) in try Unix.inet_addr_of_string a with _ -> raise Not_found else ( try Unix.inet_addr_of_string h with _ -> raise Not_found ) let url_socksymbol url dp = let p = match url.url_port with | None -> dp | Some p -> p in try let a = url_addr url in `Inet(a, p) with | Not_found -> (match url.url_host with | None -> raise Not_found | Some h -> `Inet_byname(h, p) ) let string_of_url url = if not (url.url_validity) then failwith "Neturl.string_of_url: URL not flagged as valid"; (match url.url_scheme with None -> "" | Some s -> s ^ ":") ^ (match url.url_host with None -> "" | Some host -> "//" ^ (match url.url_user with None -> "" | Some user -> user ^ (String.concat "" (List.map (fun p -> ";" ^ p) url.url_user_param)) ^ (match url.url_password with None -> "" | Some password -> ":" ^ password ) ^ "@") ^ host ^ (match url.url_port with None -> "" | Some port -> ":" ^ string_of_int port)) ^ (match url.url_path with | [""] -> "/" | x :: p when url.url_scheme = None && url.url_host = None && String.contains x ':' -> (* Really a special case: The colon contained in 'x' may cause * that a prefix of 'x' is interpreted as URL scheme. In this * case, "./" is prepended (as recommended in RFC 1808, 5.3). *) "./" | _ -> "" ) ^ String.concat "/" url.url_path ^ (match url.url_other with None -> "" | Some other -> other) ^ String.concat "" (List.map (fun s -> ";" ^ s) url.url_param) ^ (match url.url_query with None -> "" | Some query -> "?" ^ query) ^ (match url.url_fragment with None -> "" | Some fragment -> "#" ^ fragment) ;; let semi_re = Netstring_str.regexp ";";; let url_of_string url_syntax s = let l = String.length s in let recognized x = x <> Url_part_not_recognized in let rec collect_words ?(ipv6=false) terminators eof_char cats k = (* Collect words as recognized by 'cats', starting at position 'k' in * 's'. Collection stops if one the characters listed in 'terminators' * is found. If the end of the string is reached, it is treated as * 'eof_char'. * * if ipv6: words "[ipv6addr]" are also recognized. *) let word, sep, k_end = if ipv6 && k < l && s.[k] = '[' then ( let k' = scan_url_part s (k+1) l ipv6_sep_cats false in if k' >= l then raise Malformed_URL; if s.[k'] <> ']' then raise Malformed_URL; let word, sep = String.sub s k (k'+1-k), (if k'+1 eof_char then ( if cats.(Char.code sep) <> Separator then raise Malformed_URL ); (word, sep, k'+1) ) else ( let k' = scan_url_part s k l cats url_syntax.url_accepts_8bits in (* or raise Malformed_URL *) let word, sep = String.sub s k (k'-k), (if k' None, 0 else None, 0 in (* If there is a "//", a host will follow: *) let host, port, userinfo, password, k2 = if recognized url_syntax.url_enable_host && k1 + 2 <= l && s.[k1]='/' && s.[k1+1]='/' then begin let word_sep_list, k' = collect_words ~ipv6:true [ '/'; '?'; '#' ] '/' login_cats (k1+2) in (* or raise Malformed_URL *) let int x = try int_of_string x with _ -> raise Malformed_URL in match word_sep_list with [ host, ('/'|'?'|'#') ] -> Some host, None, None, None, k' | [ host, ':'; port, ('/'|'?'|'#') ] -> Some host, Some (int port), None, None, k' | [ user, '@'; host, ('/'|'?'|'#') ] -> Some host, None, Some user, None, k' | [ user, '@'; host, ':'; port, ('/'|'?'|'#') ] -> Some host, Some (int port), Some user, None, k' | [ user, ':'; password, '@'; host, ('/'|'?'|'#') ] -> Some host, None, Some user, Some password, k' | [ user, ':'; password, '@'; host, ':'; port, ('/'|'?'|'#') ] -> Some host, Some (int port), Some user, Some password, k' | _ -> raise Malformed_URL end else None, None, None, None, k1 in (* Separate user from user_param: *) let user, user_param = match userinfo with None -> (None, []) | Some u -> if recognized url_syntax.url_enable_user_param then ( let l = Netstring_str.split_delim semi_re u in match l with [] -> (Some "", []) | user :: user_param -> (Some user, user_param) ) else (Some u, []) in let path, k3 = if recognized url_syntax.url_enable_path && k2 < l (* && s.[k2]='/' *) then begin let cats = path_cats_from_syntax url_syntax [ '/' ] in let seps = separators_from_syntax url_syntax in (* Note: '>' is not allowed within URLs; because of this we can use * it as end-of-string character. *) let word_sep_list, k' = collect_words ('>'::seps) '>' cats k2 in (* or raise Malformed_URL *) match word_sep_list with [ "", '/'; "", _ ] -> [ "" ], k' | [ "", _ ] -> [], k' | _ -> List.map fst word_sep_list, k' end else begin (* If there is a single '/': skip it *) if not (recognized url_syntax.url_enable_other) && k2 < l && s.[k2]='/' then [], (k2+1) else [], k2 end in let other, k4 = if recognized url_syntax.url_enable_other && k3 < l then begin let cats = other_cats_from_syntax url_syntax in (* Note: '>' is not allowed within URLs; because of this we can use * it as end-of-string character. *) let word_sep_list, k' = collect_words ['>';'#'] '>' cats k3 in (* or raise Malformed_URL *) match word_sep_list with [ other, _ ] -> Some other, k' | _ -> assert false end else None, k3 in let param, k5 = if recognized url_syntax.url_enable_param && k4 < l && s.[k4]=';' then begin let cats = path_cats_from_syntax url_syntax [] in let seps = separators_from_syntax url_syntax in let seps' = List.filter (fun c -> c <> ';') seps in (* Note: '>' is not allowed within URLs; because of this we can use * it as end-of-string character. *) let word_sep_list, k' = collect_words ('>'::seps') '>' cats (k4+1) in (* or raise Malformed_URL *) List.map fst word_sep_list, k' end else [], k4 in let query, k6 = if recognized url_syntax.url_enable_query && k5 < l && s.[k5]='?' then begin let syn = { url_syntax with url_enable_param = Url_part_not_recognized; url_enable_query = Url_part_not_recognized } in let cats = path_cats_from_syntax syn [] in let seps = separators_from_syntax syn in (* Note: '>' is not allowed within URLs; because of this we can use * it as end-of-string character. *) let word_sep_list, k' = collect_words ('>'::seps) '>' cats (k5+1) in (* or raise Malformed_URL *) match word_sep_list with [ query, _ ] -> Some query, k' | _ -> assert false end else None, k5 in let fragment, k7 = if recognized url_syntax.url_enable_fragment && k6 < l && s.[k6]='#' then begin let cats = path_cats_from_syntax url_syntax [] in let seps = separators_from_syntax url_syntax in (* Note: '>' is not allowed within URLs; because of this we can use * it as end-of-string character. *) let word_sep_list, k' = collect_words ('>'::seps) '>' cats (k6+1) in (* or raise Malformed_URL *) match word_sep_list with [ fragment, _ ] -> Some fragment, k' | _ -> assert false end else None, k6 in if k7 <> l then raise Malformed_URL; make_url ~encoded:true ?scheme ?user ~user_param ?password ?host ?port ~path ~param ?query ?fragment ?other url_syntax ;; let problem_re = Netstring_str.regexp "[ <>\"{}|\\^`]" let problem_hash_re = Netstring_str.regexp "[ <>\"{}|\\^`#]" let fixup_url_string ?(escape_hash=false) = Netstring_str.global_substitute (if escape_hash then problem_hash_re else problem_re) (fun m s -> sprintf "%%%02x" (Char.code s.[Netstring_str.match_beginning m])) ;; let parse_url ?(schemes = common_url_syntax) ?base_syntax ?(accept_8bits = false) ?(enable_fragment = false) s = let scheme = try Some (extract_url_scheme s) with Malformed_URL -> None in let syntax = match scheme with None -> ( match base_syntax with None -> raise Malformed_URL | Some syn -> partial_url_syntax syn ) | Some sch -> try Hashtbl.find schemes sch with Not_found -> raise Malformed_URL in let syntax' = if accept_8bits then { syntax with url_accepts_8bits = true } else syntax in let syntax'' = if enable_fragment && syntax.url_enable_fragment = Url_part_not_recognized then { syntax' with url_enable_fragment = Url_part_allowed } else syntax' in url_of_string syntax'' s ;; let split_path s = let l = String.length s in let rec collect_words k = let k' = try String.index_from s k '/' with Not_found -> l in let word = String.sub s k (k'-k) in if k' >= l then [word] else word :: collect_words (k'+1) in match collect_words 0 with [ "" ] -> [] | [ "";"" ] -> [ "" ] | other -> other ;; let join_path l = match l with [ "" ] -> "/" | _ -> String.concat "/" l;; let norm_path l = let rec remove_slash_slash l first = match l with | [ "" ] -> [ "" ] | [ ""; "" ] when first -> [ "" ] | "" :: l' when not first -> remove_slash_slash l' false | x :: l' -> x :: remove_slash_slash l' false | [] -> [] in let rec remove_dot l first = match l with | ([ "." ] | ["."; ""]) -> if first then [] else [ "" ] | "." :: x :: l' -> remove_dot (x :: l') false | x :: l' -> x :: remove_dot l' false | [] -> [] in let rec remove_dot_dot_once l first = match l with x :: ".." :: [] when x <> "" && x <> ".." && not first -> [ "" ] | x :: ".." :: l' when x <> "" && x <> ".." -> l' | x :: l' -> x :: remove_dot_dot_once l' false | [] -> raise Not_found in let rec remove_dot_dot l = try let l' = remove_dot_dot_once l true in remove_dot_dot l' with Not_found -> l in let l' = remove_dot_dot (remove_dot (remove_slash_slash l true) true) in match l' with [".."] -> [".."; ""] | ["";""] -> [ "" ] | _ -> l' ;; let apply_relative_url baseurl relurl = if not (baseurl.url_validity) || not (relurl.url_validity) then failwith "Neturl.apply_relative_url: URL not flagged as valid"; if relurl.url_scheme <> None then modify_url ~syntax:baseurl.url_syntax (* inherit syntax *) relurl else if relurl.url_host <> None then modify_url ~syntax:baseurl.url_syntax (* inherit syntax and scheme *) ?scheme:baseurl.url_scheme relurl else match relurl.url_path with "" :: other -> (* An absolute path *) modify_url ~syntax:baseurl.url_syntax (* inherit syntax, scheme, and *) ~encoded:true ?scheme:baseurl.url_scheme (* login info *) ?host:baseurl.url_host ?port:baseurl.url_port ?user:baseurl.url_user ~user_param:baseurl.url_user_param ?password:baseurl.url_password relurl | [] -> (* Empty: Inherit also path, params, query, and fragment *) let new_params, new_query, new_fragment = match relurl.url_param, relurl.url_query, relurl.url_fragment with [], None, None -> (* Inherit all three *) baseurl.url_param, baseurl.url_query, baseurl.url_fragment | [], None, f -> (* Inherit params and query *) baseurl.url_param, baseurl.url_query, f | [], q, f -> (* Inherit params *) baseurl.url_param, q, f | p, q, f -> (* Inherit none of them *) p, q, f in modify_url ~syntax:baseurl.url_syntax ~encoded:true ?scheme:baseurl.url_scheme ?host:baseurl.url_host ?port:baseurl.url_port ?user:baseurl.url_user ~user_param:baseurl.url_user_param ?password:baseurl.url_password ~path:baseurl.url_path ~param:new_params ?query:new_query ?fragment:new_fragment relurl | relpath -> (* A relative path *) let rec change_path basepath = match basepath with | [] -> if baseurl.url_host = None then relpath else "" :: relpath | [ "" ] -> "" :: relpath | [ x ] -> relpath | x :: basepath' -> x :: change_path basepath' in let new_path = norm_path (change_path baseurl.url_path) in modify_url ~syntax:baseurl.url_syntax (* inherit syntax, scheme, and *) ~encoded:true ?scheme:baseurl.url_scheme (* login info *) ?host:baseurl.url_host ?port:baseurl.url_port ?user:baseurl.url_user ~user_param:baseurl.url_user_param ?password:baseurl.url_password ~path:new_path (* and change path *) relurl ;; let ensure_absolute_url ?base u = if u.url_scheme = None then ( match base with None -> raise Malformed_URL | Some b -> apply_relative_url b u ) else u ;; let print_url url = Format.print_string ("") ;; let backslash_re = Netstring_str.regexp "\\\\";; let drive_letter_re = Netstring_str.regexp "^\\([A-Za-z]\\):/";; let drive_letter_re' = Netstring_str.regexp "^/\\([A-Za-z]\\):/";; let unc_path_re = Netstring_str.regexp "^//\\([^/]+\\)\\(/|$\\)";; let os_type = Sys.os_type;; let classify_path p = match os_type with "Unix" -> if p <> "" && p.[0] = '/' then `Absolute_local p else `Relative p | "Win32" -> let p' = Netstring_str.global_replace backslash_re "/" p in ( match Netstring_str.string_match drive_letter_re p' 0 with Some m -> `Absolute_local ("/" ^ p') | None -> ( match Netstring_str.string_match unc_path_re p' 0 with Some m -> let host = Netstring_str.matched_group m 1 p' in let host_e = Netstring_str.group_end m 1 in let path = String.sub p' host_e (String.length p' - host_e) in let path = if path = "" then "/" else path in `Absolute_remote(host,path) | None -> if p' <> "" && p'.[0] = '/' then `Relative_drive p' else `Relative p' ) ) | "Cygwin" -> let p' = Netstring_str.global_replace backslash_re "/" p in ( match Netstring_str.string_match drive_letter_re p' 0 with Some m -> let letter = Netstring_str.matched_group m 1 p' in let rest = String.sub p' 2 (String.length p' - 2) in `Absolute_local("/cygdrive/" ^ letter ^ rest) | None -> ( match Netstring_str.string_match unc_path_re p' 0 with Some m -> let host = Netstring_str.matched_group m 1 p' in let host_e = Netstring_str.group_end m 1 in let path = String.sub p' host_e (String.length p' - host_e) in let path = if path = "" then "/" else path in `Absolute_remote(host,path) | None -> if p' <> "" && p'.[0] = '/' then `Absolute_local p' else `Relative p' ) ) | _ -> assert false ;; let file_url_of_local_path ?(getcwd = Sys.getcwd) p = (* Classify p, and make it absolute: *) let p_class = classify_path p in let p_abs_class = match p_class with `Relative r -> ( match classify_path (getcwd()) with `Absolute_local l -> if l = "/" then `Absolute_local("/" ^ r) else `Absolute_local(l ^ "/" ^ r) | `Absolute_remote(h,l) -> if l = "/" then `Absolute_remote(h,"/" ^ r) else `Absolute_remote(h,l ^ "/" ^ r) | _ -> failwith "Neturl.file_url_of_local_path: cwd is not absolute" ) | `Relative_drive r -> ( match classify_path (getcwd()) with `Absolute_local l -> ( match Netstring_str.string_match drive_letter_re' l 0 with Some m -> let letter = Netstring_str.matched_group m 1 l in `Absolute_local("/" ^ letter ^ ":" ^ r) | None -> assert false ) | `Absolute_remote(h,l) -> `Absolute_remote(h,r) | _ -> failwith "Neturl.file_url_of_local_path: cwd is not absolute" ) | other -> other in (* Generate the URL: *) let syntax = { file_url_syntax with url_accepts_8bits = true } in match p_abs_class with `Absolute_local l -> let path = split_path l in make_url ~scheme:"file" ~host:"localhost" ~path syntax | `Absolute_remote(host,l) -> let path = split_path l in make_url ~scheme:"file" ~host ~path syntax | _ -> assert false ;; let drive_letter_comp_re = Netstring_str.regexp "^\\([A-Za-z]\\)\\(:|\\|\\)";; let local_path_of_file_url u = let local_path p = if p = [] || List.hd p <> "" then failwith "Neturl.local_path_of_file_url: URL is not absolute"; match os_type with "Unix" -> join_path p | "Win32" -> (* There must be a drive letter: *) ( match p with ("" :: drive :: rest) -> (match Netstring_str.string_match drive_letter_comp_re drive 0 with Some m -> let letter = Netstring_str.matched_group m 1 drive in let rest = if rest = [] then [""] else rest in join_path((letter ^ ":") :: rest) | None -> failwith "Neturl.local_path_of_file_url: URL is not absolute"; ) | _ -> failwith "Neturl.local_path_of_file_url: URL is not absolute"; ) | "Cygwin" -> (* Recognize drive letters: *) ( match p with ("" :: drive :: rest) -> (match Netstring_str.string_match drive_letter_comp_re drive 0 with Some m -> let letter = Netstring_str.matched_group m 1 drive in join_path("" :: "cygdrive" :: letter :: rest) | None -> join_path p ) | _ -> join_path p ) | _ -> assert false in let remote_path host p = if p = [] || List.hd p <> "" then failwith "Neturl.local_path_of_file_url: URL is not absolute"; match os_type with "Unix" -> failwith "Neturl.local_path_of_file_url: Cannot process non-local file URLs" | "Win32" | "Cygwin" -> join_path( "" :: "" :: host :: List.tl p) | _ -> assert false in let opt f = try Some(f u) with Not_found -> None in match (opt url_scheme), (opt url_host), (url_path u) with (Some "file", (Some("localhost"|"")|None), []) -> local_path [""] | (Some "file", (Some("localhost"|"")|None), p) -> local_path p | (Some "file", Some host, []) -> remote_path host [""] | (Some "file", Some host, p) -> remote_path host p | (Some _, _, _) -> failwith "Neturl.local_path_of_file_url: Unexpected scheme" | (None, _, _) -> failwith "Neturl.local_path_of_file_url: Missing scheme (relative URL?)" ;; ocamlnet-4.1.2/src/netstring/netulex.ml0000644000175000017500000002615212731530350016573 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * PXP: The polymorphic XML parser for Objective Caml. * Copyright by Gerd Stolpmann. See LICENSE for details. *) module ULB = struct open Netaux.ArrayAux open Netconversion type unicode_lexbuf = { mutable ulb_encoding : encoding; mutable ulb_encoding_start : int; mutable ulb_rawbuf : Bytes.t; mutable ulb_rawbuf_len : int; mutable ulb_rawbuf_end : int; mutable ulb_rawbuf_const : bool; mutable ulb_chars : int array; mutable ulb_chars_pos : int array; mutable ulb_chars_len : int; mutable ulb_eof : bool; mutable ulb_refill : Bytes.t -> int -> int -> int; mutable ulb_enc_change_hook : unicode_lexbuf -> unit; mutable ulb_cursor : Bytes.t poly_cursor } let empty = Bytes.create 0 let from_function ?(raw_size = 512) ?(char_size = 250) ?(enc_change_hook = fun _ -> ()) ~refill enc = { ulb_encoding = enc; ulb_encoding_start = 0; ulb_rawbuf = Bytes.create raw_size; ulb_rawbuf_len = 0; ulb_rawbuf_end = 0; ulb_rawbuf_const = false; ulb_chars = Array.make char_size (-1); ulb_chars_pos = ( let cp = Array.make (char_size+1) (-1) in cp.(0) <- 0; cp ); ulb_chars_len = 0; ulb_eof = false; ulb_refill = refill; ulb_enc_change_hook = enc_change_hook; ulb_cursor = create_poly_cursor enc Netstring_tstring.bytes_ops empty; } let from_in_obj_channel ?raw_size ?char_size ?enc_change_hook enc inch = let refill s k l = try let n = inch # input s k l in if n=0 then failwith "Netulex.ULB.from_in_obj_channel: non-blocking channel"; n with End_of_file -> 0 in from_function ?raw_size ?char_size ?enc_change_hook ~refill enc let from_bytes_inplace ?(enc_change_hook = fun _ -> ()) enc s = let char_size = 250 in { ulb_encoding = enc; ulb_encoding_start = 0; ulb_rawbuf = s; ulb_rawbuf_len = Bytes.length s; ulb_rawbuf_end = 0; ulb_rawbuf_const = true; ulb_chars = Array.make char_size (-1); ulb_chars_pos = ( let cp = Array.make (char_size+1) (-1) in cp.(0) <- 0; cp ); ulb_chars_len = 0; ulb_eof = true; ulb_refill = (fun _ _ _ -> assert false); ulb_enc_change_hook = enc_change_hook; ulb_cursor = create_poly_cursor enc Netstring_tstring.bytes_ops empty; } let from_bytes ?enc_change_hook enc s = from_bytes_inplace ?enc_change_hook enc (Bytes.copy s) let from_string ?enc_change_hook enc s = from_bytes_inplace ?enc_change_hook enc (Bytes.of_string s) let delete n ulb = if n < 0 || n > ulb.ulb_chars_len then invalid_arg "Netulex.ULB.delete"; let m = ulb.ulb_chars_len - n in int_blit ulb.ulb_chars n ulb.ulb_chars 0 m; int_blit ulb.ulb_chars_pos n ulb.ulb_chars_pos 0 (m+1); if not ulb.ulb_rawbuf_const then ( let k = ulb.ulb_chars_pos.(0) in assert (ulb.ulb_rawbuf_end >= k); let m' = ulb.ulb_rawbuf_len - k in Bytes.blit ulb.ulb_rawbuf k ulb.ulb_rawbuf 0 m'; let cp = ulb.ulb_chars_pos in for i = 0 to m do cp.(i) <- cp.(i) - k done; ulb.ulb_rawbuf_len <- m'; ulb.ulb_rawbuf_end <- ulb.ulb_rawbuf_end - k; ); ulb.ulb_chars_len <- m; ulb.ulb_encoding_start <- max 0 (ulb.ulb_encoding_start - n) let set_encoding enc ulb = if enc <> ulb.ulb_encoding then ( ulb.ulb_encoding <- enc; ulb.ulb_encoding_start <- ulb.ulb_chars_len; ulb.ulb_enc_change_hook ulb ) let close ulb = ulb.ulb_eof <- true let utf8_sub_string k n ulb = if k < 0 || k > ulb.ulb_chars_len || n < 0 || k+n > ulb.ulb_chars_len then invalid_arg "Netulex.ULB.utf8_sub_string"; if ulb.ulb_encoding = `Enc_utf8 && k >= ulb.ulb_encoding_start then ( (* Extract the substring from [ulb_rawbuf] ! *) let k' = ulb.ulb_chars_pos.(k) in let n' = ulb.ulb_chars_pos.(k+n) - k' in Bytes.sub_string ulb.ulb_rawbuf k' n' ) else ( (* Create the UTF-8 string from [ulb_chars] *) ustring_of_uarray `Enc_utf8 ~pos:k ~len:n ulb.ulb_chars ) let utf8_sub_string_length k n ulb = if k < 0 || k > ulb.ulb_chars_len || n < 0 || k+n > ulb.ulb_chars_len then invalid_arg "Netulex.ULB.utf8_sub_string_length"; if ulb.ulb_encoding = `Enc_utf8 && k >= ulb.ulb_encoding_start then ( (* Extract the substring from [ulb_rawbuf] ! *) let k' = ulb.ulb_chars_pos.(k) in let n' = ulb.ulb_chars_pos.(k+n) - k' in n' ) else ( (* Count the UTF-8 string from [ulb_chars] *) (* Maybe better algorithm: divide into several slices, and call * ustring_of_uarray for them. Goal: Reduction of memory allocation *) let conv = ustring_of_uchar `Enc_utf8 in let n' = ref 0 in for i = k to k+n-1 do n' := !n' + String.length (conv ulb.ulb_chars.(i)) done; !n' ) let rec refill_aux ulb = (* Check whether we cannot add at least one byte to [ulb_chars] because * of EOF: *) if ulb.ulb_eof && ulb.ulb_rawbuf_len = ulb.ulb_rawbuf_end then 0 else ( (* Enlarge [ulb_chars] if necessary (need at least space for one character) *) if ulb.ulb_chars_len >= Array.length ulb.ulb_chars then ( let n = min (Sys.max_array_length-1) (2 * (Array.length ulb.ulb_chars)) in if n = Array.length ulb.ulb_chars then failwith "Netulex.ULB.refill: array too large"; let c = Array.make n (-1) in let cp = Array.make (n+1) (-1) in int_blit ulb.ulb_chars 0 c 0 ulb.ulb_chars_len; int_blit ulb.ulb_chars_pos 0 cp 0 (ulb.ulb_chars_len+1); ulb.ulb_chars <- c; ulb.ulb_chars_pos <- cp; ); (* If there is unanalysed material in [ulb_rawbuf], try to convert it. * It may happen, however, that there is only the beginning of a * multi-byte character, so this may not add any new character. *) let new_chars = if ulb.ulb_rawbuf_end < ulb.ulb_rawbuf_len then ( let cs = ulb.ulb_cursor in reinit_cursor ~range_pos:ulb.ulb_rawbuf_end ~range_len:(ulb.ulb_rawbuf_len - ulb.ulb_rawbuf_end) ~enc:ulb.ulb_encoding ulb.ulb_rawbuf cs; let counter = ref 0 in ( try while ulb.ulb_chars_len < Array.length ulb.ulb_chars do let space = Array.length ulb.ulb_chars - ulb.ulb_chars_len in (* cursor_blit may raise End_of_string, too *) let n = cursor_blit cs ulb.ulb_chars ulb.ulb_chars_len space in let n' = cursor_blit_positions cs ulb.ulb_chars_pos ulb.ulb_chars_len space in assert(n=n'); if n>0 then ( ulb.ulb_chars_len <- ulb.ulb_chars_len+n; counter := !counter + n; move ~num:n cs; (* may raise Malformed_code *) ) else ( (* We are at a special position in the string! *) try ignore(uchar_at cs); assert false with Byte_order_mark -> (* Skip the BOM: *) move cs (* may raise Malformed_code *) (* Note: this [move] does not count *) | Partial_character -> (* Stop here *) raise Exit (* End_of_string: already handled *) ) done with Exit -> () | End_of_string -> () ); let e = cursor_pos cs; in ulb.ulb_chars_pos.(ulb.ulb_chars_len) <- e; ulb.ulb_rawbuf_end <- e; (* Encoding might have changed: *) set_encoding (cursor_encoding cs) ulb; !counter ) else 0 in (* In the case we still did not add any char: Check if we are near * EOF (the last multi-byte character is not complete). *) if new_chars = 0 then ( if ulb.ulb_eof then raise Malformed_code; assert(not ulb.ulb_rawbuf_const); (* Now try to get new data into [ulb_rawbuf]. First, we check whether * we have enough free space in this buffer. We insist on at least * 50 bytes (quite arbitrary...). Then call the [ulb_refill] function * to get the data. *) if ulb.ulb_rawbuf_len + 50 >= Bytes.length ulb.ulb_rawbuf then ( let n = min Sys.max_string_length (2 * (Bytes.length ulb.ulb_rawbuf)) in if n = Bytes.length ulb.ulb_rawbuf then failwith "Netulex.ULB.refill: string too large"; let s = Bytes.create n in Bytes.blit ulb.ulb_rawbuf 0 s 0 ulb.ulb_rawbuf_len; ulb.ulb_rawbuf <- s; ); (* Call now [ulb_refill]. If we detect EOF, record this. Anyway, * start over. *) let space = (Bytes.length ulb.ulb_rawbuf) - ulb.ulb_rawbuf_len in let n = ulb.ulb_refill ulb.ulb_rawbuf ulb.ulb_rawbuf_len space in assert(n>=0); if n=0 then ( (* EOF *) ulb.ulb_eof <- true; ) else ( ulb.ulb_rawbuf_len <- ulb.ulb_rawbuf_len + n ); refill_aux ulb ) else new_chars ) let refill ulb = let n = refill_aux ulb in assert(n>=0); if n=0 then ( assert(ulb.ulb_eof); assert(ulb.ulb_rawbuf_len = ulb.ulb_rawbuf_end); raise End_of_file ) end module Ulexing = struct type lexbuf = { ulb : ULB.unicode_lexbuf; mutable offset : int; mutable pos : int; mutable start : int; mutable marked_pos : int; mutable marked_val : int; } exception Error let from_ulb_lexbuf ulb = { ulb = ulb; offset = 0; pos = 0; start = 0; marked_pos = 0; marked_val = 0; } let lexeme_start lexbuf = lexbuf.start + lexbuf.offset let lexeme_end lexbuf = lexbuf.pos + lexbuf.offset let lexeme_length lexbuf = lexbuf.pos - lexbuf.start let lexeme lexbuf = let buf = lexbuf.ulb.ULB.ulb_chars in Array.sub buf lexbuf.start (lexbuf.pos - lexbuf.start) let sub_lexeme lexbuf pos len = let buf = lexbuf.ulb.ULB.ulb_chars in Array.sub buf (lexbuf.start + pos) len let lexeme_char lexbuf pos = let buf = lexbuf.ulb.ULB.ulb_chars in buf.(lexbuf.start + pos) let utf8_lexeme lexbuf = ULB.utf8_sub_string lexbuf.start (lexbuf.pos - lexbuf.start) lexbuf.ulb let utf8_sub_lexeme lexbuf pos len = ULB.utf8_sub_string (lexbuf.start + pos) len lexbuf.ulb let utf8_sub_lexeme_length lexbuf pos len = ULB.utf8_sub_string_length (lexbuf.start + pos) len lexbuf.ulb (* "Internal" interface *) let start lexbuf = lexbuf.start <- lexbuf.pos; lexbuf.marked_pos <- lexbuf.pos; lexbuf.marked_val <- (-1) let mark lexbuf i = lexbuf.marked_pos <- lexbuf.pos; lexbuf.marked_val <- i let backtrack lexbuf = lexbuf.pos <- lexbuf.marked_pos; lexbuf.marked_val let rollback lexbuf = lexbuf.pos <- lexbuf.start let eof = (-1) let refill lexbuf = try (* Delete all characters in ulexbuf before the current lexeme: *) if lexbuf.start > 0 then ( let n = lexbuf.start in ULB.delete n lexbuf.ulb; lexbuf.offset <- lexbuf.offset + n; lexbuf.pos <- lexbuf.pos - n; lexbuf.marked_pos <- lexbuf.marked_pos - n; lexbuf.start <- 0; ); ULB.refill lexbuf.ulb; (* raises either End_of_file, or ensures there is one char in ulb *) lexbuf.ulb.ULB.ulb_chars.(lexbuf.pos) with End_of_file -> (* We cannot modify the buffer as the original Ulexing implementation *) eof let next lexbuf = let ulb = lexbuf.ulb in let i = if lexbuf.pos = ulb.ULB.ulb_chars_len then refill lexbuf else ulb.ULB.ulb_chars.(lexbuf.pos) in if i <> eof then lexbuf.pos <- lexbuf.pos + 1; i end ocamlnet-4.1.2/src/netstring/nettls_support.mli0000644000175000017500000000767012731530350020371 0ustar gerdgerd(* $Id$ *) (** Support types and functions for TLS *) type credentials = [ `X509 of Netx509.x509_certificate | `Anonymous ] (** The types of credentials *) (* Later: `OpenPGP of XXX | `Username of string *) type raw_credentials = [ `X509 of string | `Anonymous ] (** The encoded credentials: - [`X509 s]: The X509 certificate in DER encoding - [`Anonymous]: no certificate or other key is available *) type cred_type = [ `X509 | `Anonymous ] (** The type of credential types *) (** Direct access to TLS properties of a session *) class type tls_session_props = object method id : string (** The ID of the session (non-printable string) *) method addressed_server : string option (** The name of the server (for name-based virtual servers). This may be unavailable, because this information is exchanged via a TLS extension. *) method cipher_suite_type : string (** A string describing the authentication and privacy mechanism that is in effect: - "X509": X509 certificates are used - "OPENPGP": OpenPGP certificates are used - "ANON": anonymous credentials - "SRP": SRP credentials - "PSK": PSK credentials *) method endpoint_credentials : credentials (** Returns the decoded credentials of this endpoint *) method endpoint_credentials_type : cred_type (** The type of credentials *) method endpoint_credentials_raw : raw_credentials (** Returns the credentials in the raw form. For X509 certicates, this is the DER encoding *) method peer_credentials : credentials (** Returns the decoded peer credentials *) method peer_credentials_type : cred_type (** The type of credentials *) method peer_credentials_raw : raw_credentials (** Returns the peer credentials in the raw form. For X509 certicates, this is the DER encoding *) method cipher_algo : string (** The name of the algorithm for encrypting the data stream, e.g. "AES-128-CBC". *) method kx_algo : string (** The name of the key exchange algorithm, e.g. "RSA" *) method mac_algo : string (** The name of the data integrity algorithm (actually only the digest algorithm for HMAC), e.g. "SHA1" *) method compression_algo : string (** The name of the compression algorithm (or "NULL"), on the TLS layer. E.g. "DEFLATE". *) method protocol : string (** The name of the TLS protocol version, e.g. "TLS1.0" *) end val get_tls_session_props : Netsys_crypto_types.tls_endpoint -> tls_session_props (** Get the session properties for an endpoint for which the handshake is already done *) val get_tls_user_name : tls_session_props -> string (** Get the "user name" of client certificates. It is determined as follows: - if there is a subjectAltName with an email address (i.e. rfc822 type), this address is returned - if there is a subjectAltName using the directory name format, it is checked whether there is a "uid", "email", or "cn" name component - otherwise, it is checked whether there is a "uid", "email", or "cn" name component in the subject Raises [Not_found] if nothing approriate is found. *) val squash_file_tls_endpoint : (module Netsys_crypto_types.FILE_TLS_ENDPOINT) -> (module Netsys_crypto_types.TLS_ENDPOINT) (** Coerce a file endpoint to a normal endpoint *) val is_endpoint_host : string -> tls_session_props -> bool (** [is_endpoint_host name props]: checks whether [name] matches the certificate of the endpoint in [props]. In particular, this function checks the DNS alternate name, and the common name of the subject. The certificate name can use wildcards. Returns true if [name] could be verified this way. NB. This doesn't check SNI ([addressed_server]), because this is the peer's task. *) ocamlnet-4.1.2/src/netstring/netsendmail.mli0000644000175000017500000003470512731530350017566 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Functions to compose and send electronic mails * * {b Contents} * * - {!Netsendmail.composing} * - {!Netsendmail.sending} * * The tutorial has been moved to {!Netsendmail_tut}. *) (** {1:composing Composing Messages} * * The core function is {!Netsendmail.compose} generating a MIME mail. * The mail can be sent with {!Netsendmail.sendmail}, written to an * object channel with {!Netmime.write_mime_message}, or postprocessed * by a user function. * * The call to [compose] can be as easy as * * {[ compose ~from_addr:("me", "me\@domain.net") * ~to_addrs:["you", "you\@domain.com"] * ~subject:"I have a message for you" * "Hello, this is my message!\n" * ]} * * This call generates the message as {!Netmime.complex_mime_message}, * and can be directly sent with {!Netsendmail.sendmail}. * * The [compose] function is the simplified interface; alternatively one * can also generate the mail by calling {!Netsendmail.wrap_mail}, * {!Netsendmail.wrap_parts}, and {!Netsendmail.wrap_attachment}, getting * more fine-grained control of certain options. *) val compose : ?in_charset:Netconversion.encoding -> ?out_charset:Netconversion.encoding -> ?from_addr:(string * string) -> ?cc_addrs:(string * string) list -> ?bcc_addrs:(string * string) list -> ?content_type:(string * (string * Netmime_string.s_param) list) -> ?container_type:(string * (string * Netmime_string.s_param) list) -> ?attachments:Netmime.complex_mime_message list -> to_addrs:(string * string) list -> subject:string -> (* text:*) string -> Netmime.complex_mime_message (** Composes a mail message with a main text, and optionally * a number of attachments. * * The addresses [from_addr], [to_addrs], [cc_addrs], and [bcc_addrs] are * passed as pairs [(human_readable,formal)] where * [human_readable] is an arbitrary printable string identifying the * sender/receiver, and where [formal] is the RFC-822 mailbox specification. * An example is [("Stolpmann, Gerd", "gerd\@gerd-stolpmann.de")]. * * The [subject] can be any text. * * The anonymous [string] argument is the main text of the mail. * * The resulting message is always a correct MIME message. * * @param in_charset All passed texts (except the formal addresses) must * be encoded in [in_charset]. Default: [`Enc_iso88591]. * As another exception, setting [content_type] explicitly prevents * the main text from being converted, and [in_charset] does not * have a meaning for the main text. * @param out_charset The encoded words in the generated header fields, * if necessary, and the main text are encoded in [out_charset]. * Default: [`Enc_iso88591]. * It is required that [out_charset] is ASCII-compatible. * As a special rule, setting [content_type] explicitly prevents * the main text from being converted to [out_charset]. * @param content_type The content type of the main text. The list is * the list of parameters attached * to the type, e.g. [("text/plain", ["charset", mk_param "ISO-8859-1"])] * (see {!Netmime_string.mk_param}). When this argument is set, * the main text is no longer converted to [out_charset]. * By default, when this argument is missing, the main text is * converted from [in_charset] to [out_charset], and the * content type becomes ["text/plain; charset="]. * @param container_type The content type of the container wrapping the * main text and the attachment into one entity * (only used if [attachments] are present). This * defaults to [("multipart/mixed", [])]. This must be either a * "multipart" or "message" type. * @param attachments An optional list of attachments. Should be generated * with [wrap_attachment]. *) (** {b Character Set Conversion} * * The impact of [in_charset] and [out_charset] on the generated mail * is not very obvious. The charset arguments may have an effect on * the mail header and the mail body. * * The mail header can only be composed of ASCII characters (7 bit). * To circumvent this restriction the MIME standard specifies a special * format, the so-called encoded words. These may only be used in some * places, and [compose] knows where: In the subject, and the non-formal * part of mail addresses. The [out_charset] is the character set * used in the generated mail. The [in_charset] is the character set * the strings are encoded you pass to [compose]. It is a good idea * to have [in_charset = out_charset], or at least choose [out_charset] * as a superset of [in_charset], because this ensures that the character * set conversion succeeds. * * If the mail header does not make use of the additional non-ASCII * characters, the encoded words will be avoided. * * The mail body is only subject of character set conversion if * the [content_type] is {b not} passed to [compose]. In this case, * the function sets it to [text/plain], and converts the message * from [in_charset] to [out_charset]. * * {b Adding Attachments} * * To generate the attachments, call {!Netsendmail.wrap_attachment}, e.g. * * {[ compose ... * ~attachments:[ wrap_attachment * ~content_type:("application/octet-stream", []) * (new Netmime.file_mime_body "file.tar.gz") ] * ]} * * There * are a number of kinds of attaching files, identified by [container_type]. * The default is [multipart/mixed], meaning that the parts of the mail are * mixed messages and files. One can give a hint whether to display * the parts directly in the mailer program (so-called inline attachments), * or whether to suggest that the file is saved to disk ("real" * attachments). This hint is contained in the [Content-disposition] * header, see [wrap_attachment] how to set it. * * For a discusion of the other [container_type]s see the * {!Netsendmail.tutorial} at the end of this document. *) val wrap_attachment : ?in_charset:Netconversion.encoding -> ?out_charset:Netconversion.encoding -> ?content_id:string -> ?content_description:string -> ?content_location:string -> ?content_disposition:(string * (string * Netmime_string.s_param) list) -> content_type:(string * (string * Netmime_string.s_param) list) -> Netmime.mime_body -> Netmime.complex_mime_message (** Generates a header for the [mime_body]. The returned value * is intended to be used as input for the [attachments] argument * of the [compose] function: * * {[ * compose ... * ~attachments:[ wrap_attachment * ~content_type:("audio/wav", []) * (new file_mime_body "music.wav") ] * ]} * * The header contains at least the [Content-type] and the * [Content-transfer-encoding] fields. The latter is currently * always ["base64"], but it is possible that the function is * changed in the future to also generate ["quoted-printable"] * when applicable. * * @param in_charset The encoding of the [content_description] argument. * Default: [`Enc_iso88591]. * @param out_charset The encoding of the generated [Content-Description] * header. Default: [`Enc_iso88591]. * @param content_type Specifies the content type with main * type and list of parameters. Example: * [ ("text/plain", ["charset", Netmime_string.mk_param "ISO-8859-1" ]) ] * (see {!Netmime_string.mk_param}) * @param content_disposition Optionally sets the [Content-disposition] * header. Frequent values are * - [ ("inline", []) ]: Indicates that the attachment is displayed * together with the main text * - [ ("attachment", ["filename", Netmime_string.mk_param fn]) ]: Indicates * that the attachment should be stored onto the disk. The * parameter [fn] is the suggested file name. Note that [fn] * should only consist of ASCII characters unless the [charset] * argument of [mk_param] is set to a different character encoding. * @param content_id Optionally sets the [Content-ID] header field. * The passed string is the ID value without the embracing angle * brackets. The [Content-ID] can be used to refer to the attachment * from other parts of the mail, e.g. in [multipart/related] mails * HTML documents can include hyperlinks to attachments using the * URL syntax [cid:ID] where [ID] is the ID value. * @param content_description The [Content-Description] header * @param content_location The [Content-Location] header. This must be * a valid URL, only composed of 7 bit characters, and with escaped * unsafe characters *) val wrap_mail : ?in_charset:Netconversion.encoding -> ?out_charset:Netconversion.encoding -> ?from_addr:(string * string) -> ?cc_addrs:(string * string) list -> ?bcc_addrs:(string * string) list -> to_addrs:(string * string) list -> subject:string -> Netmime.complex_mime_message -> Netmime.complex_mime_message (** Sets the mail-related header fields in the input message, and * returns a message ready for delivery. Transfer- and delivery-related * header fields are removed from the message first, and the new fields * are set to the values passed to this function. * * The arguments are like in {!Netsendmail.compose}. * * The input message should have at least a [Content-type] header, * but this is not enforced. * * Use this function as an alternative to {!Netsendmail.compose}, * if the message is already available as [complex_mime_message], * e.g. to re-send a parsed mail message to a new destination. *) (** {b Note: Resending Messages} * * Note that mails generated by [wrap_mail] always appear as new mails, * not as forwarded or replied mails. In order to do the latter a different * way of processing the message is needed. *) val wrap_parts : ?in_charset:Netconversion.encoding -> ?out_charset:Netconversion.encoding -> ?content_type:(string * (string * Netmime_string.s_param) list) -> ?content_id:string -> ?content_description:string -> ?content_location:string -> ?content_disposition:(string * (string * Netmime_string.s_param) list) -> Netmime.complex_mime_message list -> Netmime.complex_mime_message (** Generates an intermediate container for multipart attachments. * Use this if you want to bundle a set of attachments as a single * attachment. * * @param in_charset The encoding of the [content_description] argument. * Default: [`Enc_iso88591]. * @param out_charset The encoding of the generated [Content-Description] * header. Default: [`Enc_iso88591]. * @param content_type The [Content-Type] header. Default: multipart/mixed * @param content_id The [Content-ID] header, without the angle brackets * @param content_description The [Content-Description] header * @param content_location The [Content-Location] header. This must be * a valid URL, only composed of 7 bit characters, and with escaped * unsafe characters * @param content_disposition The [Content-Disposition] header *) (** {b Low-level} *) val create_address_list_tokens : ?in_charset:Netconversion.encoding -> ?out_charset:Netconversion.encoding -> (string * string) list -> Netmime_string.s_token list (** Returns the list of [s_token]s representing email addresses as * structured value. The addresses are passed as list of pairs * [(human_readable, formal)] as in the [compose] function above. * The returned structured field value can be formatted and filled * into a mail header. For example, to set the "To" header to * ["Stolpmann, Gerd" ] use * {[ * let sval = create_address_list_tokens ["Stolpmann, Gerd", * "gerd\@gerd-stolpmann.de"] in * header # update_field "to" (format_field_value "to" sval) * ]} * This ensures that the field is correctly quoted, that appropriate * encodings are applied and that long values are folded into several * lines. * * @param in_charset The character encoding used for [human_readable]. * Defaults to [`Enc_iso88591]. * @param out_charset The character encoding used in the generated * encoded word. This encoding must be ASCII-compatible. Defaults to * [`Enc_iso88591]. *) val create_text_tokens : ?in_charset:Netconversion.encoding -> ?out_charset:Netconversion.encoding -> string -> Netmime_string.s_token list (** Returns the list of [s_token]s representing an informal text * as structured value. The text is passed as simple string. * The returned structured field value can be formatted and filled * into a mail header. For example, to set the "Subject" header to * ["I have to say something"], use * {[ * let sval = create_text_tokens "I have to say something" in * header # update_field "subject" (format_field_value "subject" sval) * ]} * This ensures that the field is correctly quoted, that appropriate * encodings are applied and that long values are folded into several * lines. * * @param in_charset The character encoding used for the input string. * Defaults to [`Enc_iso88591]. * @param out_charset The character encoding used in the generated * encoded words. This encoding must be ASCII-compatible. Defaults to * [`Enc_iso88591]. *) val format_field_value : string -> Netmime_string.s_token list -> string (** To put [sval], an [s_token list], into the header field [name], * call * * [ header # update_field name (format_field_value name sval) ] * * The field value is folded into several lines, if necessary. *) (** {1:sending Sending Messages} *) val sendmail : ?mailer:string -> ?crlf:bool -> Netmime.complex_mime_message -> unit (** Sends the passed message. The mailer program must be sendmail-compatible * (this can be assumed on all Unix systems, even if a non-sendmail * mailer is installed). * * The mailer program is the command passed as [mailer], which is by * default a reasonable compile-time setting. * * With [crlf] one can determine the EOL convention for the message piped to * the mailer program: If [crlf], CR/LF is used, if [not crlf], only LF is * used. The default is [false] for Unix systems. * * See also {!Netsmtp.sendmail} for a way to send emails via SMTP. *) ocamlnet-4.1.2/src/netstring/netgssapi_support.mli0000644000175000017500000001072212731530350021045 0ustar gerdgerd(* $Id$ *) (** Support functions for GSS-API *) open Netsys_gssapi (** {2 Encodings} *) val oid_to_der : oid -> string val der_to_oid : string -> int ref -> oid (** Convert OID's to/from DER. [der_to_oid] takes a cursor as second arg. *) val oid_to_der_value : oid -> string val der_value_to_oid : string -> int ref -> int -> oid (** Convert OID's to/from DER. This variant does not include the header (hex 06 plus length). [der_value_to_oid] takes a cursor and the length in bytes. *) val wire_encode_token : oid -> token -> string val wire_decode_token : string -> int ref -> oid * token (** Encode tokens as described in section 3.1 of RFC 2078. This is usually only done for the initiating token. *) val encode_exported_name : oid -> string -> string val decode_exported_name : string -> int ref -> oid * string (** Encode names as described in section 3.2 of RFC 2078 *) val gs2_encode_saslname : string -> string val gs2_decode_saslname : string -> string (** Encodes "," and "=" characters, and forbids null bytes, and checks whether the names are UTF-8-encoded (as required for the "saslname" production in section 4 of RFC 5801). Fails if something is wrong. *) val parse_kerberos_name : string -> string list * string option (** [let (name_components, realm_opt) = parse_kerberos_name s]: Returns the slash-separated name components as [name_components], and the realm following "@" as [realm_opt]. Fails on parse error. *) (** {2 Create tokens} *) (** Format of the tokens: see RFC 4121 *) val create_mic_token : sent_by_acceptor:bool -> acceptor_subkey:bool -> sequence_number:int64 -> get_mic:(message -> string) -> message:message -> string (** Create a MIC token: - [sent_by_acceptor]: whether this token comes from the acceptor - [acceptor_subkey]: see RFC - [sequence_number]: a sequence number - [get_mic]: the checksum function (e.g. {!Netmech_scram.Cryptosystem.get_mic}) - [message]: the message to be signed The function returns the MIC token *) val parse_mic_token_header : string -> (bool * bool * int64) (** Returns the triple ([sent_by_acceptor], [acceptor_subkey], [sequence_number]) from the header of a MIC token that is passed to this function as string. Fails if not parsable *) val verify_mic_token : get_mic:(message -> string) -> message:message -> token:string -> bool (** Verifies the MIC [token] with [get_mic], and returns true if the verification is successful *) val create_wrap_token_conf : sent_by_acceptor:bool -> acceptor_subkey:bool -> sequence_number:int64 -> get_ec:(int -> int) -> encrypt_and_sign:(message -> message) -> message:message -> message (** Wraps a [message] so that it is encrypted and signed (confidential). - [sent_by_acceptor]: whether this token comes from the acceptor - [acceptor_subkey]: see RFC - [sequence_number]: a sequence number - [get_ec]: This function returns the "extra count" number for the size of the plaintext w/o filler (e.g. use {!Netmech_scram.Cryptosystem.get_ec}). - [encrypt_and_sign]: the encryption function from the cryptosystem. The plaintext is passed to this function, and the ciphertext with the appended signature must be returned in the string. - [message]: the payload message The function returns the token wrapping the message. *) val parse_wrap_token_header : message -> (bool * bool * bool * int64) (** [let (sent_by_acceptor, sealed, acceptor_subkey, sequence_number) = parse_wrap_token_header token] Fails if the [token] cannot be parsed. *) val unwrap_wrap_token_conf : decrypt_and_verify:(message -> message) -> token:message -> message (** Unwraps the [token] using the decryption function [decrypt_and_verify] from the cryptosystem. The functions fails if there is a format error, or the integrity check fails. Non-confidential messages cannot be unwrapped with this function. *) (** Token functions for non-confidential messages are still missing *) ocamlnet-4.1.2/src/netstring/Makefile0000644000175000017500000000676312731530350016223 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf OBJECTS = netconst.cmo netstring_str.cmo netbuffer.cmo netunichar.cmo \ netaux.cmo netstring_tstring.cmo \ netchannels.cmo netchannels_crypto.cmo netsockaddr.cmo \ netdb.cmo netmappings_asn1.cmo netmappings.cmo netconversion.cmo \ netulex.cmo netencoding.cmo netstream.cmo netdate.cmo \ netmime_string.cmo \ nethtml_scanner.cmo nethtml.cmo \ neturl.cmo neturl_ldap.cmo netsaslprep_data.cmo netsaslprep.cmo \ netaddress.cmo netcompression.cmo \ netmime.cmo netmime_header.cmo netmime_channels.cmo \ netsendmail.cmo nethttp.cmo \ netpagebuffer.cmo netfs.cmo netglob_lex.cmo netglob.cmo \ netauth.cmo netnumber.cmo netxdr_mstring.cmo netxdr.cmo \ netasn1.cmo netasn1_encode.cmo netoid.cmo netdn.cmo netx509.cmo \ netascii_armor.cmo netx509_pubkey.cmo netx509_pubkey_crypto.cmo \ nettls_support.cmo \ netgssapi_support.cmo netgssapi_auth.cmo \ netmech_scram.cmo netmech_scram_gssapi.cmo netmech_scram_sasl.cmo \ netmech_scram_http.cmo \ netmech_plain_sasl.cmo netmech_crammd5_sasl.cmo \ netmech_digest.cmo netmech_digest_sasl.cmo \ netmech_digest_http.cmo netmech_gs2_sasl.cmo netmech_krb5_sasl.cmo \ netmech_spnego_http.cmo PKGNAME = netstring REQUIRES += $(REGEXP_PROVIDER_MAKE) bigarray INCLUDES += $(INC_NETSYS) INCLUDES += -I ../netstring-pcre INSTALL_EXTRA_CMO = netstring_top \ netaccel_link INSTALL_EXTRA_CMX = netconversion \ netbuffer netnumber netxdr INSTALL_EXTRA = $(INSTALL_EXTRA_CMO:=.cmo) \ $(INSTALL_EXTRA_CMX:=.cmx) $(INSTALL_EXTRA_CMX:=.p.cmx) \ $(INSTALL_EXTRA_CMX:=.o) $(INSTALL_EXTRA_CMX:=.p.o) \ dllnetaccel_c.* DOBJECTS = netconversion.mli netchannels.mli netstream.mli netmime_string.mli \ netmime.mli netsendmail.mli neturl.mli netaddress.mli netbuffer.mli \ netmime_header.mli netmime_channels.mli neturl_ldap.mli \ netdate.mli netencoding.mli netulex.mli netaccel.mli \ netaccel_link.mli nethtml.mli netstring_str.mli \ netmappings.mli netaux.mli nethttp.mli netpagebuffer.mli \ netfs.mli netglob.mli netauth.mli netsockaddr.mli \ netnumber.mli netxdr_mstring.mli netxdr.mli \ netcompression.mli netunichar.mli netasn1.mli netasn1_encode.mli \ netoid.mli netstring_tstring.mli \ netdn.mli netx509.mli netascii_armor.mli nettls_support.mli \ netmech_scram.mli netmech_scram_gssapi.mli netmech_scram_sasl.mli \ netmech_scram_http.mli \ netgssapi_support.mli netgssapi_auth.mli netchannels_crypto.mli \ netx509_pubkey.mli netx509_pubkey_crypto.mli netsaslprep.mli \ netmech_plain_sasl.mli netmech_crammd5_sasl.mli \ netmech_digest_sasl.mli netmech_digest_http.mli \ netmech_krb5_sasl.mli netmech_gs2_sasl.mli netmech_spnego_http.mli \ netchannels_tut.txt netmime_tut.txt netsendmail_tut.txt \ netulex_tut.txt neturl_tut.txt OCAMLC_OPTIONS += $(STRING_OPTS) OCAMLOPT_OPTIONS += $(STRING_OPTS) PP_OPTIONS = -pp "$(CPPO) $(NETNUMBER_DEFS) $(REGEXP_DEFS) $(PP_BYTES) $(PP_DEPRECATED)" ALL_EXTRA = netaccel.cma netaccel_link.cmo netstring_top.cmo netaccel.cma: netaccel_c.o netaccel.cmo $(OCAMLMKLIB) -o netaccel -oc netaccel_c netaccel_c.o netaccel.cmo NETNUMBER_DEFS = -D WORDSIZE_$(WORD_SIZE) -D HOST_IS_$(ENDIANESS) \ -D USE_NETSYS_XDR OCAMLOPT_OPTIONS_FOR_netbuffer.ml = -inline 10 OCAMLOPT_OPTIONS_FOR_netnumber.ml = -inline 10 OCAMLOPT_OPTIONS_FOR_xdr.ml = -inline 5 OCAMLC_OPTIONS_FOR_netstring_top.ml = -I +compiler-libs include $(TOP_DIR)/Makefile.rules distclean:: $(MAKE) clean include depend ocamlnet-4.1.2/src/netstring/netstream.mli0000644000175000017500000001171112731530350017255 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** A netstream is an input channel that is read block by block. The * fragment of the channel currently loaded into memory is called the * current window of the netstream. The window can be thought as * look-ahead buffer. * * {b Picture:} * * {[ * 0 pos_in pos_in + window_length EOF * +------------------+-------------------+--------------------------+ * ==================== * The current window * ]} * * You can use a netstream like an [in_obj_channel], and read characters * and strings from the stream. The bytes come first from the look-ahead * buffer, and if there are not enough bytes, they are loaded from the * underlying channel. After every read operation it is tried to enlarge * the window such that it contains at least one block. * * If you want that the window becomes larger, you can call [want] (to * enlarge the window to a certain size) or [want_another_block] (to load * just another block from the underlying channel). Note that this affects only * the current window and not the future size of the window. * * Note [Buffer_underrun]: netstreams can cope with underruns of underlying * channels. An underrun happens when it is not possible to ensure the * minimum window size. However, it is possible that the window size * sinks under the minimum, but the [Buffer_underrun] is deferred until the * next call of an input method. Furthermore, there is a problem in the [skip] * method which may only be partially executed, i.e. the method skips some * bytes and then raises [Buffer_underrun]. *) (** An [in_obj_stream] extends [in_obj_channel] by look-ahead methods *) class type in_obj_stream = object inherit Netchannels.in_obj_channel (** The normal input operations work as usual. The window is moved after * every read sequence of bytes by exactly the number of bytes, and * if the window length becomes smaller than the block size, it will * be ensured that the window will be enlarged to the block size (or * to the rest of the stream until EOF, whatever is smaller). *) method block_size : int (** The block size of the stream *) method window : Netbuffer.t (** The look-ahead window. The first byte of the window is the byte that * would be read next by [input_char]. The length of the window is returned * by the method [window_length]. This length may be smaller than the * current length of the netbuffer, i.e. the netbuffer may contain * additional data that must be ignored. *) method want : int -> unit (** Increases the length of the window such that the length is at least * the passed number of bytes or that the window reaches EOF (whatever * happens first). *) method want_another_block : unit -> unit (** The same as: [want block_size] *) method window_length : int (** Returns the length of the window *) method window_at_eof : bool (** Whether the window is at eof *) method skip : int -> unit (** Skip the n bytes of the stream. It is not an error to skip more bytes * than available in the remaining stream. *) end class input_stream : ?len:int -> ?block_size:int -> Netchannels.in_obj_channel -> in_obj_stream (** Make an [in_obj_stream] on top of an [in_obj_channel]. The [block_size] * can be specified; it defaults to 4096. * * If [len] is passed, this parameter limits the length of the channel: * Only the first [len] bytes are read from the input channel, then an EOF * is simulated even if the input channel is longer. *) class sub_stream : ?len:int -> (* default: no maximum length *) ?delimiter:string -> (* default: no delimiter *) in_obj_stream -> in_obj_stream (** A sub stream is the part of the whole stream from the current position * to an arbitrary other position that is determined by [len] and * [delimiter]. [len] specifies the maximum length of the sub stream. * [delimiter] is an arbitrary string that indicates the end of the * sub stream (the delimiter is not part of the sub stream; i.e. the * sub stream ends immediately before the delimiter). * * While reading from the sub stream, not only the current position of * the sub stream moves, but also the current position of the main * stream. This means that it must be avoided to read data from the * main stream while the sub stream is in use. The typical pattern * is: * - Read from the main stream until the beginning of a section is * recognized * - Create a sub stream at this point * - Read from the sub stream until EOF * - Continue reading the main stream. The next character of the main * stream is exactly the character following the EOF of the sub stream *) val print_in_obj_stream : Format.formatter -> in_obj_stream -> unit (** A top-loop printer for streams *) ocamlnet-4.1.2/src/netstring/netauth.ml0000644000175000017500000000777212731530350016566 0ustar gerdgerd(* $Id$ *) let xor_s s u = let s_len = String.length s in let u_len = String.length u in assert(s_len = u_len); let x = Bytes.create s_len in for k = 0 to s_len-1 do Bytes.set x k (Char.chr ((Char.code s.[k]) lxor (Char.code u.[k]))) done; Bytes.unsafe_to_string x let hmac ~h ~b ~l ~k ~message = if String.length k > b then failwith "Netauth.hmac: key too long"; let k_padded = k ^ String.make (b - String.length k) '\000' in let ipad = String.make b '\x36' in let opad = String.make b '\x5c' in h((xor_s k_padded opad) ^ (h ((xor_s k_padded ipad) ^ message))) let add_1_complement s1 s2 = (* Add two bitstrings s1 and s2 (in big-endian order) with one's complement addition *) let l1 = String.length s1 in let l2 = String.length s2 in if l1 <> l2 then invalid_arg "Netauth.add_1_complement"; let r = Bytes.make l1 '\000' in let carry = ref 0 in for k = l1-1 downto 0 do let i1 = Char.code s1.[k] in let i2 = Char.code s2.[k] in let sum = i1 + i2 + !carry in Bytes.set r k (Char.chr (sum land 0xff)); carry := if sum > 0xff then 1 else 0; done; if !carry > 0 then ( for k = l1-1 downto 0 do let i = Char.code (Bytes.get r k) in let sum = i + !carry in Bytes.set r k (Char.chr (sum land 0xff)); carry := if sum > 0xff then 1 else 0; done ); Bytes.unsafe_to_string r let rotate_right n s = (* Rotate the (big-endian) bitstring s to the right by n bits *) let l = String.length s in let b = 8 * l in (* bit length of s *) let n' = n mod b in let n' = if n' < 0 then b+n' else n' in let u = Bytes.create l in (* First byte-shift the string, then bit-shift the remaining 0-7 bits *) let bytes = n' lsr 3 in let bits = n' land 7 in Bytes.blit_string s 0 u bytes (l-bytes); if bytes > 0 then Bytes.blit_string s (l-bytes) u 0 bytes; let mask = match bits with | 0 -> 0 | 1 -> 1 | 2 -> 3 | 3 -> 7 | 4 -> 15 | 5 -> 31 | 6 -> 63 | 7 -> 127 | _ -> assert false in let carry = ref 0 in if bits > 0 && l > 0 then ( for k = 0 to l-1 do let x = Char.code (Bytes.get u k) in Bytes.set u k (Char.chr ((x lsr bits) lor (!carry lsl (8-bits)))); carry := x land mask; done; let u0 = Bytes.get u 0 in Bytes.set u 0 (Char.chr((Char.code u0) lor (!carry lsl (8-bits)))); ); Bytes.unsafe_to_string u let n_fold n s = (** n-fold the number given by the bitstring s. The length of the number is taken as the byte-length of s. n must be divisible by 8. *) if n=0 || n mod 8 <> 0 then invalid_arg "Netauth.n_fold"; let p = n / 8 in let buf = Buffer.create (String.length s) in let rec add_rot u len = if len > 0 && len mod p = 0 then () else ( Buffer.add_string buf u; add_rot (rotate_right 13 u) (len+String.length u) ) in add_rot s 0; let blen = Buffer.length buf in let s = ref (Buffer.sub buf 0 p) in for k = 1 to (blen / p) - 1 do s := add_1_complement !s (Buffer.sub buf (k*p) p) done; !s type key_type = [ `Kc | `Ke | `Ki ] let k_truncate k s = let b = k/8 in String.sub s 0 b let derive_key_rfc3961_simplified ~encrypt ~random_to_key ~block_size ~k ~usage ~key_type = if block_size < 40 then invalid_arg "Netauth.derive_key_rfc3961: bad block_size"; if k <= 0 || k mod 8 <> 0 then invalid_arg "Netauth.derive_key_rfc3961: bad k"; if usage < 0 || usage > 255 then invalid_arg "Netauth.derive_key_rfc3961: bad usage (only 0-255 allowed)"; let usage_s = String.make 3 '\000' ^ String.make 1 (Char.chr usage) ^ (match key_type with | `Kc -> "\x99" | `Ke -> "\xaa" | `Ki -> "\x55" ) in let usage_exp = n_fold block_size usage_s in let kbuf = Buffer.create 80 in let ki = ref (encrypt usage_exp) in Buffer.add_string kbuf !ki; while 8*(Buffer.length kbuf) < k do ki := encrypt !ki; Buffer.add_string kbuf !ki done; let derived_random = k_truncate k (Buffer.contents kbuf) in random_to_key derived_random ocamlnet-4.1.2/src/netstring/netmech_digest_sasl.ml0000644000175000017500000002042412731530350021107 0ustar gerdgerd(* $Id$ *) (* Unit tests: tests/netstring/bench/test_netmech.ml *) open Netmech_digest open Printf (* For parsing the messages, we just reuse the Nethttp function for the www-authenticate HTTP header. *) let parse_message = Nethttp.Header.parse_quoted_parameters module DIGEST_MD5 : Netsys_sasl_types.SASL_MECHANISM = struct let mechanism_name = "DIGEST-MD5" let client_first = `No let server_sends_final_data = true let supports_authz = true let available() = true let profile = { ptype = `SASL; hash_functions = [ `MD5 ]; mutual = true; } type credentials = (string * string * (string * string) list) list type client_session = Netmech_digest.client_session type server_session = Netmech_digest.server_session let init_credentials l = (l:credentials) let server_state ss = ss.sstate let create_server_session ~lookup ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_digestmd5_sasl.create_server_session:" [ "realm"; "nonce"; "mutual"; "secure" ] params in let srealm = try Some(List.assoc "realm" params) with Not_found -> None in let nonce = try List.assoc "nonce" params with Not_found -> create_nonce() in (* NB. "mutual" is enabled anyway, so no check here *) { sstate = `Emit; srealm; snonce = nonce; sresponse = None; snextnc = 1; sstale = false; sprofile = profile; sutf8 = true; snosess = false; lookup } let server_configure_channel_binding ss cb_list = failwith "Netmech_digest_sasl.server_configure_channel_binding: \ not supported" let format_kv l = String.concat "," (List.map (fun (k,v) -> k ^ "=" ^ v) l) let server_emit_challenge ss = if ss.sstate <> `Emit then failwith "Netmech_digestmd5_sasl.server_emit_challenge: bad state"; match ss.sresponse with | None -> let ss, l = server_emit_initial_challenge_kv ~quote:true ss in (ss, format_kv l) | Some _ -> let ss, l = server_emit_final_challenge_kv ~quote:true ss in (ss, format_kv l) let server_process_response ss msg = try let msg_params = parse_message msg in server_process_response_kv ss msg_params "AUTHENTICATE" with | Failure _ -> (* from parse_message *) { ss with sstate = `Auth_error "parse error" } let server_process_response_restart ss msg set_stale = if ss.sstate <> `OK then failwith "Netmech_digestmd5_sasl.server_process_response_restart: \ bad state"; try let msg_params = parse_message msg in server_process_response_restart_kv ss msg_params set_stale "AUTHENTICATE" with | Failure _ -> (* from parse_message *) ( { ss with sstate = `Auth_error "parse error" }, false ) let server_channel_binding ss = `None let server_stash_session ss = server_stash_session_i ss let server_resume_session ~lookup s = server_resume_session_i ~lookup s let server_session_id ss = Some ss.snonce let server_prop ss key = server_prop_i ss key let server_gssapi_props ss = raise Not_found let server_user_name ss = match ss.sresponse with | None -> raise Not_found | Some(rp,_,_) -> to_utf8 rp.r_utf8 rp.r_user let server_authz_name ss = match ss.sresponse with | None -> raise Not_found | Some(rp,_,_) -> match rp.r_authz with | None -> raise Not_found | Some authz -> authz let create_client_session ~user ~authz ~creds ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_digestmd5_sasl.create_client_session:" [ "digest-uri"; "realm"; "cnonce"; "mutual"; "secure" ] params in let pw = try Netsys_sasl_util.extract_password creds with Not_found -> failwith "Netmech_digestmd5_sasl.create_client_session: no password \ found in credentials" in (* NB. mutual auth is enabled anyway *) { cstate = `Wait; cresp = None; cprofile = profile; cmethod = "AUTHENTICATE"; cdigest_uri = (try List.assoc "digest-uri" params with Not_found -> "generic/generic"); crealm = (try Some(List.assoc "realm" params) with Not_found -> None); cuser = user; cauthz = authz; cpasswd = pw; cnonce = (try List.assoc "cnonce" params with Not_found -> create_nonce()); } let client_configure_channel_binding cs cb = if cb <> `None then failwith "Netmech_digestmd5_sasl.client_configure_channel_binding: \ not supported" else cs let client_state cs = cs.cstate let client_channel_binding cs = `None let client_restart cs = if cs.cstate <> `OK then failwith "Netmech_digestmd5_sasl.client_restart: unfinished auth"; client_restart_i cs let client_process_challenge cs msg = (* This can either be the initial challenge or the final server message *) try let msg_params = parse_message msg in if List.exists (fun (k,_) -> String.lowercase k = "rspauth") msg_params then client_process_final_challenge_kv cs msg_params else client_process_initial_challenge_kv cs msg_params with | Failure _ -> (* from parse_message *) { cs with cstate = `Auth_error "parse error" } let client_emit_response cs = if cs.cstate <> `Emit && cs.cstate <> `Stale then failwith "Netmech_digestmd5_sasl.client_emit_response: bad state"; let cs, l = client_emit_response_kv ~quote:true cs in (cs, format_kv l) let client_stash_session cs = client_stash_session_i cs let client_resume_session s = client_resume_session_i s let client_session_id cs = None let client_prop cs key = client_prop_i cs key let client_gssapi_props cs = raise Not_found let client_user_name cs = cs.cuser let client_authz_name cs = cs.cauthz end (* #use "topfind";; #require "netstring";; open Netmech_digest_sasl.DIGEST_MD5;; let creds = init_credentials ["password", "secret", []];; let lookup _ _ = Some creds;; let s = create_server_session ~lookup ~params:["realm", "elwood.innosoft.com", false; "nonce", "OA6MG9tEQGm2hh",false] ();; let s, s1 = server_emit_challenge s;; let c = create_client_session ~user:"chris" ~authz:"" ~creds ~params:["digest-uri", "imap/elwood.innosoft.com", false; "cnonce", "OA6MHXh6VqTrRk", false ] ();; let c = client_process_challenge c s1;; let c, c1 = client_emit_response c;; (* response=d388dad90d4bbd760a152321f2143af7 *) let s = server_process_response s c1;; let s, s2 = server_emit_challenge s;; assert(server_state s = `OK);; assert(s2 = "rspauth=\"ea40f60335c427b5527b84dbabcdfffd\"");; let c = client_process_challenge c s2;; assert(client_state c = `OK);; let crestart = c;; (* Reauth, short path: *) let c = client_restart crestart;; let c, c2 = client_emit_response c;; (* nc=2 *) let stoo = create_server_session ~lookup ~params:["realm", "elwood.innosoft.com", false; ] ();; let stoo = server_process_response stoo c2;; assert(server_state stoo = `Restart "OA6MG9tEQGm2hh");; (* Now the server looks into the cache, and finds s under this ID *) let s, _ = server_process_response_restart s c2 false;; assert(server_state s = `Emit);; let s, s3 = server_emit_challenge s;; assert(s3 = "rspauth=\"73dd7feae8e84a22b0ad1f92666954d0\"");; assert(server_state s = `OK);; let c = client_process_challenge c s3;; assert(client_state c = `OK);; (* Reauth, long path: *) let c = client_restart crestart;; let c, c2 = client_emit_response c;; (* nc=2 *) let stoo = create_server_session ~lookup ~params:["realm", "elwood.innosoft.com", false; ] ();; let stoo = server_process_response stoo c2;; assert(server_state stoo = `Restart "OA6MG9tEQGm2hh");; let s, _ = server_process_response_restart s c2 true;; (* stale *) let s, s4 = server_emit_challenge s;; (* s4: new nonce, stale=true *) let c = client_process_challenge c s4;; assert(client_state c = `Stale);; let c, c3 = client_emit_response c;; (* c3: new cnonce *) let s = server_process_response s c3;; let s, s5 = server_emit_challenge s;; assert(server_state s = `OK);; let c = client_process_challenge c s5;; assert(client_state c = `OK);; *) ocamlnet-4.1.2/src/netstring/netmech_krb5_sasl.mli0000644000175000017500000000644512731530350020653 0ustar gerdgerd(* $Id$ *) (** Kerberos 5 as SASL mechanism *) module Krb5_gs1(GSS:Netsys_gssapi.GSSAPI) : Netsys_sasl_types.SASL_MECHANISM (** This is an adapter turning the Kerberos 5 GSSAPI mechanism into a SASL mechanism. Note that there are two ways of doing this, RFC 4752 and RFC 5801, and this is the former way ("gs1"). The SASL name is "GSSAPI". Although this name may suggest that all GSSAPI mechanisms are understood, the RFC requires that this protocol is only used for Kerberos 5. Create the final module like {[ module K = Netmech_krb5_sasl.Krb5_gs1(Netgss.System) ]} {b Remarks for clients:} This adapter doesn't need any credentials for [create_client_session]. You can pass the empty list. [user] is ignored (or better, the user is taken from the current Kerberos ticket). [authz] can be passed, though. The client needs to know the service name (e.g. "imap") and the fully qualified domain name of the server. These must be passed in the "gssapi-acceptor" parameter in the form "service\@fully.qualified.domain.name", e.g. {[ let cs = S.create_client_session ~user:"" ~authz:"" ~creds:(S.init_credentials []) ~params:[ "gssapi-acceptor", "imap\@mailprovider.com", false ] () ]} {b Remarks for servers:} Usually the "realm" parameter is set to the name of the realm. In this case the realm is stripped off the principal before the [lookup] callback is invoked (e.g. "tim\@REALM.NET" is shortened to just "tim"). If the "realm" parameter is not set, the full principal name is passed to [lookup]. If [lookup] returns [Some c] for any [c] the user is accepted. If it returns [None] the user is declined. The "gssapi-acceptor-service" parameter must be set to the name of the service. E.g. {[ let ss = S.create_server_session ~lookup:(fun user _ -> if user_ok user then Some(S.init_credentials []) else None ) ~params:[ "gssapi-acceptor-service", "imap", false; "realm", "SAMPLE.NET", false; ] () ]} {b Parameters:} - The parameter [mutual] is forwarded to the GSSAPI. Authentication fails if mutual authentication cannot be granted. - The parameter [secure] is understood but ignored (Kerberos is considered as secure method) {b Statefulness:} The GSSAPI is stateful. Our SASL interface is stateless. We cannot hide the statefulness of the GSSAPI, and because of this old versions of sessions are invalidated. E.g. this does not work {[ let s1 = S.server_process_response s0 "some message" let s2 = S.server_process_response s0 "another message" ]} and the second attempt to continue with the old session [s0] will fail. *) module Krb5_gs2(GSS:Netsys_gssapi.GSSAPI) : Netsys_sasl_types.SASL_MECHANISM (** This is the other adapter turning the Kerberos 5 GSSAPI mechanism into a SASL mechanism. This follows the specification in RFC 5801 ("gs2"). The usage is the same as {!Netmech_krb5_sasl.Krb5_gs1}. This adapter doesn't announce channel bindings. *) module Krb5_gs2_profile : Netmech_gs2_sasl.PROFILE (** This is the profile used for {!Netmech_krb5_sasl.Krb5_gs2} *) ocamlnet-4.1.2/src/netstring/netmech_digest_sasl.mli0000644000175000017500000000353312731530350021262 0ustar gerdgerd(* $Id$ *) module DIGEST_MD5 : Netsys_sasl_types.SASL_MECHANISM (** The DIGEST-MD5 SASL mechanism (RFC 2831). This mechanism is only provided to connect to old services; it shouldn't be used otherwise. Key facts: - The password is not sent in the clear - Not only authenticates the client to the server, but the client can also find out whether the server knew the password, i.e. the server is also authenticated. - DIGEST-MD5 is vulnerable to man-in-the-middle attacks. - The MD5 hash is broken (too weak) Only "auth" mode is supported (no integrity or privacy protection). This implementation rejects servers that offer multiple realms. This implementation supports both [server_session_id] (which is the nonce) and the [client_session_id] (the cnonce). Parameters: - [create_server_session] understands: "realm" (optional), "nonce" (optional) - [server_prop] will return: "realm" (the realm selected by the client), "nonce", "digest-uri" (once known), "cnonce" (once known), "nc" (once known). - [create_client_session] understands: "realm" (optional), "cnonce" (optional), "digest-uri" (optional). If the digest-uri is not set, it defaults to "generic/generic". - [client_prop] will return: "cnonce", "realm" (once known; this is always the server realm), "nonce" (once known), "nc" (after sending the response). - The parameters [mutual] and [secure] are understood but ignored (there is mutual authentication anyway, and DIGEST is considered as secure method) As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of DIGEST-MD5 should pass user names and passwords through {!Netsaslprep.saslprep}. *) ocamlnet-4.1.2/src/netstring/netxdr.mli0000644000175000017500000005274412731530350016572 0ustar gerdgerd(* $Id$ *) (** External Data Representation *) (** This module supports the "external data representation", or XDR * for short. XDR is a means to pack structured values as strings and * it serves to transport such values across character streams even * between computers with different architectures. * * XDR values must be formed according to an XDR type. Such types are * usually written in a notation that is close to the C notation of * structured types. There are some important details where XDR is * better than C: * - direct support for strings * - arrays may have fixed or variable length * - unions must have a discriminator * - no pointers. The notation [*t] is allowed, but means something * different, namely "t option" in O'Caml notation. * - recursive types are possible and behave like recursive types in * O'Caml. For example, * {[ * struct *list { * int value; * next list; * } * ]} * is a list of integer values and equivalent to * {[ * type intlist = intlist_el option * and intlist_el = { value : int; next : intlist } * ]} * * See RFC 1014 for details about XDR. * * This module defines: * - XDR types * - XDR type terms * - XDR type systems * - XDR type term systems * * In "type terms" you can see the components from which the type has been * formed, while a "type" is an opaque representation that has been checked * and for that some preprocessing has been done. * * A "type system" is a collection of several types that have names and that * can refer to previously defined types (i.e. a sequence of "typedef"s). * As with simple types, there is an extensive and an opaque representation. * * A typical way of using this module is to define an "XDR type term system" * by simply writing an O'Caml expression. After that, this system is validated * and you get the "type system". From now on, you can refer to the types * defined in the system by name and get the corresponding "XDR types". * Once you have an XDR type you can use it to pack or unpack an XDR value. *) open Netnumber;; (** Values possible for XDR types. This is straight-forward, except the * "_fast" variants: *) type xdr_value = | XV_int of int4 | XV_uint of uint4 | XV_hyper of int8 | XV_uhyper of uint8 | XV_enum of string | XV_float of fp4 | XV_double of fp8 | XV_opaque of string | XV_string of string | XV_array of xdr_value array | XV_struct of (string * xdr_value) list | XV_union_over_int of (int4 * xdr_value) | XV_union_over_uint of (uint4 * xdr_value) | XV_union_over_enum of (string * xdr_value) | XV_void (* New in 0.4: *) | XV_enum_fast of int (** The integer is the _position_ in the [X_enum] list, sorted by * enum values (ascending). For example, if we have * [X_enum [ "A", 4; "B", 2; "C", 6 ]] * the element "B" has the position 0, because 2 is the lowest * number *) | XV_struct_fast of xdr_value array (** The array elements are in the same order as declared in [X_struct] *) | XV_union_over_enum_fast of (int * xdr_value) (** The integer is the _position_ in the [X_enum] list. "position" * means the same as for [XV_enum_fast] *) (* New in 3.0: *) | XV_array_of_string_fast of string array (** To be used with an [X_array] or [X_array_fixed] with an inner type of [X_string] *) | XV_mstring of Netxdr_mstring.mstring (* New in 3.5: *) | XV_direct of exn * int * (exn -> xdr_value) (* The variant [XV_direct(exn,size,expand)] should only be used by code generated with ocamlrpcgen. It is only allowed at positions in the term with type [X_direct]. It is assumed that the value is available as exception [exn] (in any form). [size] is the number of bytes in XDR format. [expand] is a function that can convert the exception to a normal [xdr_value]. *) (* TODO: arrays of int, uint, hyper, uhyper, opaque, float, double *) val xv_true : xdr_value val xv_false : xdr_value (** See [x_bool] *) val xv_none : xdr_value val xv_some : xdr_value -> xdr_value (** See [x_optional] *) (** Terms that describe possible XDR types: * * - [X_int]: integer (32 bit) * - [X_uint]: unsigned integer * - [X_hyper]: hyper (64 bit signed integer) * - [X_uhyper]: unsigned hyper * - [X_enum [x1,i1; ...]]: [enum { x1 = i1, ... }] * - [X_float]: float (32 bit fp number) * - [X_double]: double (64 bit fp number) * - [X_opaque_fixed n]: [opaque[n]] * - [X_opaque n]: [opaque] * - [X_string n]: [string] * - [X_mstring(name,n)]: [_managed string] (see below) * - [X_array_fixed (t,n)]: [t[n]] * - [X_array (t,n)]: [t] * - [X_struct [x1,t1;...]]: [struct { t1 x1; ...}] * - [X_union_over_int * ([n1,t1;...], None)]: [union switch(int) {case n1: t1; ...}] * - [X_union_over_int * ([n1,t1;...], Some t)]: [union switch(int) {case n1: t1; ...; default t}] * - [X_union_over_uint * ([n1,t1;...], None)]: [union switch(unsigned int) {case n1: t1; ...}] * - [X_union_over_uint * ([n1,t1;...], Some t)]: [union switch(unsigned int) * {case n1: t1; ...; default t}] * - [X_union_over_enum * (e, [n1,t1;...], None)]: [union switch(e) {case n1:t1; ...}] * where e is an enumeration type * - [X_union_over_enum * (e, [n1,t1;...], Some t)]: [union switch(e) {case n1:t1; ...; default t}] * where e is an enumeration type * - [X_void]: void * * * The [X_type] constructor is only useful for types interpreted relative to * a type system. Then it refers to a named type in this system. * * The [X_param] constructor includes a reference to an arbitrary type * which must first be given when packing or unpacking values. * (A "lazy" type reference.) Additionally, the values for parameters * may be encrypted or decrypted. * * Example how to define a recursive type: * * [X_rec ("a", X_array ( X_struct ["value", X_int; "next", X_refer "a"], 1))] * * {b Managed strings} are represented as [X_mstring(name,n)]. The [name] refers * to the preferred factory for managed strings (needs to be passed to the * XDR unpacker). Values for managed strings are objects of type * {!Netxdr_mstring.mstring}. * * The term [X_direct(t,read,write,size,expand)] is generated by ocamlrpcgen at * positions * suitable for direct mapping. In this case, the XDR byte representation is * directly mapped to the final Ocaml value bypassing the intermediate * representation defined in this module. [t] is the mapped type. The * function [read] is called as [read s cursor len] in order to map the * XDR bytes at [!cursor] in [s]. The [cursor] must be advanced to the * end position. [len] is the number of valid bytes in [s] (i.e. [s.(len-1)] * is the last one). The result of [read] is an arbitrary exception which * needs to be postprocessed by ocamlrpcgen-generated code. The function * [write] is called as [write x s cursor]: The value encapsulated in * exception [x] is written to string [s] at position [cursor]. Like for * [read] the cursor is advanced by the number of written bytes. There * must be enough space in [s]. The function [size] can be used to determine * the number of written bytes beforehand. *) type xdr_type_term = | X_int | X_uint | X_hyper | X_uhyper | X_enum of (string * int4) list | X_float | X_double | X_opaque_fixed of uint4 | X_opaque of uint4 | X_string of uint4 | X_mstring of string * uint4 | X_array_fixed of xdr_type_term * uint4 | X_array of xdr_type_term * uint4 | X_struct of (string * xdr_type_term) list | X_union_over_int of (int4 * xdr_type_term) list * xdr_type_term option | X_union_over_uint of (uint4 * xdr_type_term) list * xdr_type_term option | X_union_over_enum of xdr_type_term * (string * xdr_type_term) list * xdr_type_term option | X_void | X_type of string | X_param of string | X_rec of (string * xdr_type_term) (* define a recursive type *) | X_refer of string (* refer to a recursive type *) | X_direct of xdr_type_term * (Bytes.t -> int ref -> int -> exn) * (exn -> Bytes.t -> int ref -> unit) * (exn -> int) * (exn -> xdr_value) ;; type xdr_type;; (** This is the validated version of [xdr_type_term]. Note that it does not * contain [X_type] constructors, i.e. is completely expanded. * It is allowed that an [xdr_type] contains [X_param] constructors (parameters). * The set of occurring parameters can be determined very quickly for an * [xdr_type]. *) type xdr_type_term_system = (string * xdr_type_term) list;; (** Bind names to types. In a correct system you can only refer to * previously defined types, i.e. the type called [n] must be defined * in the list before it can be used via [X_type n]. * It is possible to use this module without the means of type * systems, but often code is more readable if types are defined * in an environment allowing bindings to names. *) type xdr_type_system;; (** A validated type system. *) val x_bool : xdr_type_term;; (** Common abbreviation for boolean types. Has values [xv_true] and [xv_false]. *) val x_optional : xdr_type_term -> xdr_type_term (** Common abbreviation for optional types. Has values [xv_none] and * [xv_some v]. *) val x_opaque_max : xdr_type_term (** Common abbreviation for opaque data of arbitrary length *) val x_string_max : xdr_type_term (** Common abbreviation for strings of arbitrary length *) val x_mstring_max : string -> xdr_type_term (** Common abbreviation for mstrings of arbitrary length *) val x_array_max : xdr_type_term -> xdr_type_term (** Common abbreviation for arrays of arbitrary length *) (* Destructors. *) exception Dest_failure (** raised if the dest_* function are applied to non-matching xdr_value *) val dest_xv_int : xdr_value -> int4 val dest_xv_uint : xdr_value -> uint4 val dest_xv_hyper : xdr_value -> int8 val dest_xv_uhyper : xdr_value -> uint8 val dest_xv_enum : xdr_value -> string val dest_xv_enum_fast : xdr_value -> int val dest_xv_float : xdr_value -> fp4 val dest_xv_double : xdr_value -> fp8 val dest_xv_opaque : xdr_value -> string val dest_xv_string : xdr_value -> string val dest_xv_mstring : xdr_value -> Netxdr_mstring.mstring val dest_xv_array : xdr_value -> xdr_value array val dest_xv_array_of_string_fast : xdr_value -> string array val dest_xv_struct : xdr_value -> (string * xdr_value) list val dest_xv_struct_fast : xdr_value -> xdr_value array val dest_xv_union_over_int : xdr_value -> int4 * xdr_value val dest_xv_union_over_uint : xdr_value -> uint4 * xdr_value val dest_xv_union_over_enum : xdr_value -> string * xdr_value val dest_xv_union_over_enum_fast : xdr_value -> int * xdr_value val dest_xv_void : xdr_value -> unit val map_xv_enum_fast : xdr_type -> xdr_value -> int32 (** Works for both [XV_enum] and [XV_enum_fast] *) val map_xv_struct_fast : xdr_type -> xdr_value -> xdr_value array (** Works for both [XV_struct] and [XV_struct_fast] *) val map_xv_union_over_enum_fast : xdr_type -> xdr_value -> int * int32 * xdr_value (** Works for both [XV_union_over_enum] and [XV_union_over_enum_fast]. * Returns the triple [(k,i,x)]: * - [k]: Position of the selected value in the [T_enum] array * - [i]: value of the enum * - [x]: selected arm of the union *) (* This exception is used in unpack_xdr_value. *) exception Xdr_format of string (** Format error found during unpacking a string *) exception Xdr_format_message_too_long of xdr_value (** The message is too long and cannot be packed into a string *) exception Xdr_failure of string (** Usually a problem during packing *) (** You must use these two functions to obtain validated types and * type systems. They fail with "validate_xdr_type" resp. * "validate_xdr_type_system" if the parameters are incorrect. *) val validate_xdr_type : xdr_type_term -> xdr_type val validate_xdr_type_system : xdr_type_term_system -> xdr_type_system val params : xdr_type -> string list (** return the [X_param] parameters contained in the type *) (** Get the unvalidated version back: * * - Note that [X_type] constructions are always resolved *) val xdr_type_term : xdr_type -> xdr_type_term val xdr_type_term_system : xdr_type_system -> xdr_type_term_system (** You can expand any type term relative to a (validated) type system. * For example: * [expanded_xdr_type sys1 (X_type "xy")] * extracts the type called "xy" defined in sys1. * Expansion removes all X_type constructions in a type term. *) val expanded_xdr_type : xdr_type_system -> xdr_type_term -> xdr_type val expanded_xdr_type_term : xdr_type_term_system -> xdr_type_term -> xdr_type_term val are_compatible : xdr_type -> xdr_type -> bool (** [are_compatible]: currently not implemented *) val value_matches_type : xdr_value -> xdr_type -> (string*xdr_type) list -> bool (** Is the value properly formed with respect to this type? The third * argument of this function is a list of parameter instances. Note that * all parameters must be instantiated to compare a value with a type * and that the parameters instances are not allowed to have parameters * themselves. * * Encrypted parameters are not supported here. *) (** {2 Packing and unpacking} *) (** [pack_xdr_value v t p print]: Serialize v into a string conforming to * the XDR standard where v matches t. In p the parameter instances are * given. All parameters must be given, and the parameters must not contain * parameters themselves. The fourth argument, print, is a function * which is evaluated for the pieces of the resultant string. You can use * pack_xdr_value_as_string to get the whole string at once. * * [unpack_xdr_value s t p]: Unserialize a string to a value * matching t. If this operation fails you get an Xdr_format * exception explaining what the reason for the failure is. * Mostly the cause for failures is that t isn't the type * of the value. * Note that there are some implementation restrictions limiting * the number of elements in array, strings and opaque fields. * If you get such an error this normally still means that * the value is not of the expected type, because these limits * have no practical meaning (they are still higher than the * usable address space). *) (** {b Encryption:} The [encode] and [decode] functions can be used * to encrypt/decrypt parameters (placeholders in the type marked with * [X_param pname] for a parameter name [pname]). The [encode] argument * may list for each parameter an encoding function: * * {[ encode = [ pname1, encoder1; pname2, encoder2; ... ] ]} * * The functions [encoder] are called with the XDR-packed parameter value, * and return the encrypted value. * * Likewise, the [decode] argument may list for each parameter a decoding * function: * * {[ decode = [ pname1, decoder1; pname2, decoder2; ... ] ]} * * The call style of the decoder functions is a bit more complicated, though. * They are called as * * {[ let (xdr_s, n) = decoder s pos len ]} * * meaning that the [decoder] starts decoding at position [pos] of string [s], * and that at most [len] bytes can be decoded. It returns the decoded * string [xdr_s] (which is then unpacked), and in [n] the number of * consumed input bytes is returned. * * Exceptions raised in encoders or decoders fall through unmodified. *) type encoder = Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list (** see text above *) type decoder = Bytes.t -> int -> int -> (Bytes.t * int) (** see text above *) val pack_xdr_value : ?encode:(string * encoder) list -> xdr_value -> xdr_type -> (string*xdr_type) list -> (Bytes.t -> unit) -> unit val pack_xdr_value_as_bytes : ?rm:bool -> ?encode:(string * encoder) list -> xdr_value -> xdr_type -> (string*xdr_type) list -> Bytes.t val pack_xdr_value_as_string : ?rm:bool -> ?encode:(string * encoder) list -> xdr_value -> xdr_type -> (string*xdr_type) list -> string (** rm: If true, four null bytes are prepended to the string for the record mark Changed in Ocamlnet-3.3: these functions raise [Xdr_failure] in case of errors. *) val pack_xdr_value_as_mstrings : ?rm:bool -> ?encode:(string * encoder) list -> xdr_value -> xdr_type -> (string*xdr_type) list -> Netxdr_mstring.mstring list (** The concatanated mstrings are the packed representation Changed in Ocamlnet-3.3: this function raises [Xdr_failure] in case of errors. *) type xdr_value_version = [ `V1 | `V2 | `V3 | `V4 | `Ocamlrpcgen ] (** Selects which version of [xdr_value] is returned by [unpack_xdr_value]. During the development of Ocamlnet several incompatible changes were made, but by selecting a certain version these changes can be hidden from the caller. - [`V1]: This version refers to the original [xdr_value] definition, which only included [XV_int], [XV_uint], [XV_hyper], [XV_uhyper], [XV_enum], [XV_float], [XV_double], [XV_opaque], [XV_string], [XV_array], [XV_struct], [XV_union_over_int], [XV_union_over_uint], [XV_union_over_enum], and [XV_void]. - [`V2]: This version is available since the [rpc-0.4] distribution, and added the tags [XV_enum_fast], [XV_struct_fast], and [XV_union_over_enum_fast]. - [`V3]: In Ocamlnet-3.0 the tag [XV_array_of_string_fast] was added. - [`V4]: In Ocamlnet-3.5 the tag [XV_direct] was added. - [`Ocamlrpcgen]: This refers to the version that must be used if the returned [xdr_value] is processed by code generated with [ocamlrpcgen]. The default is still [`V1], for ultimate backward compatibility. The switch [fast=true] selects [`Ocamlrpcgen] (it was always used for this purpose, despite its name). *) val unpack_xdr_value : ?pos:int -> ?len:int -> ?fast:bool -> ?prefix:bool -> ?mstring_factories:Netxdr_mstring.named_mstring_factories-> ?xv_version:xdr_value_version -> ?decode:(string * decoder) list -> Bytes.t -> xdr_type -> (string * xdr_type) list -> xdr_value val unpack_xdr_value_l : ?pos:int -> ?len:int -> ?fast:bool -> ?prefix:bool -> ?mstring_factories:Netxdr_mstring.named_mstring_factories-> ?xv_version:xdr_value_version -> ?decode:(string * decoder) list -> Bytes.t -> xdr_type -> (string * xdr_type) list -> (xdr_value * int) (** [prefix]: whether it is ok that the string is longer than the message * (default: false) * * [mstring_factories]: when a [T_mstring(name,_)] type is found, the * factory is looked up in this hash table under [name], and if this * fails under the name ["*"]. If there is no such * factory, unpacking fails! (Default: empty table.) * * [xv_version]: Selects a certain version of the returned [xdr_value] * terms. See {!Netxdr.xdr_value_version} for details. Set this to * [`Ocamlrpcgen] if you decode the [xdr_value] with ocamlrpcgen-generated * decoders. * * [fast]: Setting this to true is a deprecated way to set * [xv_version=`Ocamlrpcgen]. * * The variant [unpack_xdr_value_l] returns not only the decoded value, * but also the actual length in bytes. * * The exceptions [Xdr_format] and [Xdr_format_message_too_long] may * be raised. *) val unpack_xdr_value_str : ?pos:int -> ?len:int -> ?fast:bool -> ?prefix:bool -> ?mstring_factories:Netxdr_mstring.named_mstring_factories-> ?xv_version:xdr_value_version -> ?decode:(string * decoder) list -> string -> xdr_type -> (string * xdr_type) list -> (xdr_value * int) (** Same for strings *) (**/**) (* Low-level *) val get_string_decoration_size : int -> Netnumber.uint4 -> int (* Returns the size of the "string decoration", i.e. the size of the header (always 4 bytes) plus the size of the padding. *) val sizefn_string : Netnumber.uint4 -> string -> int (* Return the packed size of a string *) val sizefn_mstring : Netnumber.uint4 -> Netxdr_mstring.mstring -> int (* Return the packed size of an mstring *) val write_string_fixed : int -> string -> Bytes.t -> int ref -> unit val write_string : string -> Bytes.t -> int ref -> unit (* [write_* s1 s2 p]: write the string s1 as XDR to s2 at position p *) val read_string_fixed : int -> Bytes.t -> int ref -> int -> string val read_string : Netnumber.uint4 -> Bytes.t -> int ref -> int -> string val raise_xdr_format_too_short : unit -> 'a val raise_xdr_format_value_not_included : unit -> 'a val raise_xdr_format_maximum_length : unit -> 'a val raise_xdr_format_undefined_descriminator : unit -> 'a val safe_add : int -> int -> int val safe_mul : int -> int -> int type ctx = { ctx_direct : bool; ctx_direct_sub : bool; ctx_copy_string : string -> string } val default_ctx : ctx val expand_ctx : ctx val direct_ctx : ctx ocamlnet-4.1.2/src/netstring/netxdr_mstring.mli0000644000175000017500000002540712731530350020331 0ustar gerdgerd(* $Id$ *) (** Managed Strings *) (** Managed strings are used in XDR context for constant strings that are stored either as string or as memory (bigarray of char). A managed string [ms] is declared in the XDR file as in {[ typedef _managed string ms<>; ]} In the encoded XDR stream there is no difference between strings and managed strings, i.e. the wire representation is identical. Only the Ocaml type differs to which the managed string is mapped. This type is {!Netxdr_mstring.mstring} (below). In the RPC context there is often the problem that the I/O backend would profit from a different string representation than the user of the RPC layer. To bridge this gap, managed strings have been invented. Generally, the user can determine how to represent strings (usually either as an Ocaml string, or as memory), and the I/O backend can request to transform to a different representation when this leads to an improvement (i.e. copy operations can be saved). Only large managed strings result in a speedup of the program (at least several K). {2 How to practically use managed strings} There are two cases: The encoding case, and the decoding case. In the encoding case the [mstring] object is created by the user and passed to the RPC library. This happens when a client prepares an argument for calling a remote procedure, or when the server sends a response back to the caller. In the decoding case the client analyzes the response from an RPC call, or the server looks at the arguments of an RPC invocation. The difference here is that in the encoding case user code can directly create [mstring] objects by calling functions of this module, whereas in the decoding case the RPC library creates the [mstring] objects. For simplicity, let us only look at this problem from the perspective of an RPC client. {b Encoding.} Image a client wants to call an RPC, and one of the arguments is a managed string. This means we finally need an [mstring] object that can be put into the argument list of the call. This library supports two string representation specially: The normal Ocaml [string] type, and {!Netsys_mem.memory} which is actually just a bigarray of char's. There are two factories [fac], - {!Netxdr_mstring.string_based_mstrings}, and - {!Netxdr_mstring.memory_based_mstrings}, and both can be used to create the [mstring] to pass to the RPC layer. It should be noted that this layer can process the [memory] representation a bit better. So, if the original [data] value is a string, the factory for [string] should be used, and if it is a char bigarray, the factory for [memory] should be used. Now, the [mstring] object is created by - [let mstring = fac # create_from_string data pos len copy_flag], or by - [let mstring = fac # create_from_memory data pos len copy_flag]. Of course, if [fac] is the factory for strings, the [create_from_string] method works better, and if [fac] is for [memory], the [create_from_memory] method works better. [pos] and [len] can select a substring of [data]. If [copy_flag] is [false], the [mstring] object does not copy the data if possible, but just keeps a reference to [data] until it is accessed; otherwise if [copy_flag] is [true], a copy is made immediately. Of couse, delaying the copy is better, but this requires that [data] is not modified until the RPC call is completed. {b Decoding.} Now, the call is done, and the client looks at the result. There is also an [mstring] object in the result. As noted above, this [mstring] object was already created by the RPC library (and currently this library prefers string-based objects if not told otherwise). The user code can now access this [mstring] object with the access methods of the [mstring] class (see below). As these methods are quite limited, it makes normally only sense to output the [mstring] contents to a file descriptor. The user can request a different factory for managed strings. The function {!Rpc_client.set_mstring_factories} can be used for this purpose. (Similar ways exist for managed clients, and for RPC servers.) {b Potential.} Before introducing managed strings, a clean analysis was done how many copy operations can be avoided by using this technique. Example: The first N bytes of a file are taken as argument of an RPC call. Instead of reading these bytes into a normal Ocaml string, an optimal implementation uses now a [memory] buffer for this purpose. This gives: - Old implementation with strings and ocamlnet-2: Data is copied {b six} times from reading it from the file until writing it to the socket. - New implementation with memory-based mstrings: Data is copied only {b twice}! The first copy reads it from the file into the input buffer (a [memory] value), and the second copy writes the data into the socket. Part of the optimization is that [Unix.read] and [Unix.write] do a completely avoidable copy of the data which is prevented by switching to {!Netsys_mem.mem_read} and {!Netsys_mem.mem_write}, respectively. The latter two functions exploit an optimization that is only possible when the data is [memory]-typed. The possible optimizations for the decoding side of the problem are slightly less impressive, but still worth doing it. *) (** {2 Interface} *) open Netsys_mem (** The object holding the string value *) class type mstring = object method length : int (** The length of the managed string *) method blit_to_bytes : int -> Bytes.t -> int -> int -> unit (** [blit_to_bytes mpos s spos len]: Copies the substring of the managed string from [mpos] to [mpos+len-1] to the substring of [s] from [spos] to [spos+len-1] *) method blit_to_string : int -> Bytes.t -> int -> int -> unit (* DEPRECATED("Use blit_to_bytes instead.") *) method blit_to_memory : int -> memory -> int -> int -> unit (** [blit_to_string mpos mem mempos len]: Copies the substring of the managed string from [mpos] to [mpos+len-1] to the substring of [mem] from [mempos] to [mempos+len-1] *) method as_bytes : Bytes.t * int (** Returns the contents as bytes. It is undefined whether the returned string is a copy or the underlying buffer. The int is the position where the contents start *) method as_string : string * int (** Returns the contents as string (this is always a copy) *) method as_memory : memory * int (** Returns the contents as memory. It is undefined whether the returned memory is a copy or the underlying buffer. The int is the position where the contents start *) method preferred : [ `Memory | `Bytes ] (** Whether [as_memory] or [as_bytes] is cheaper *) end (** The object creating new [mstring] objects *) class type mstring_factory = object method create_from_string : string -> int -> int -> bool -> mstring (** [create_from_string s pos len must_copy]: Creates the [mstring] from the sub string of s starting at [pos] with length [len] The [must_copy] flag is ignored (and exists for backwards compatibility). *) method create_from_bytes : Bytes.t -> int -> int -> bool -> mstring (** [create_from_string s pos len must_copy]: Creates the [mstring] from the sub string of s starting at [pos] with length [len] If [must_copy] the mstring object must create a copy. Otherwise it can just keep the string passed in. *) method create_from_memory : memory -> int -> int -> bool -> mstring (** [create_from_memory m pos len must_copy]: Creates the [mstring] from the sub string of m starting at [pos] with length [len] If [must_copy] the mstring object must create a copy. Otherwise it can just keep the memory passed in. *) end val bytes_based_mstrings : mstring_factory (** Uses bytes to represent mstrings *) val string_based_mstrings : mstring_factory DEPRECATED("Use bytes_based_mstrings instead.") val string_to_mstring : ?pos:int -> ?len:int -> string -> mstring (** Represent a string as mstring (no copy) *) val bytes_to_mstring : ?pos:int -> ?len:int -> Bytes.t -> mstring (** Represent bytes as mstring (no copy) *) val memory_based_mstrings : mstring_factory (** Uses memory to represent mstrings. The memory bigarrays are allocated with [Bigarray.Array1.create] *) val memory_to_mstring : ?pos:int -> ?len:int -> memory -> mstring (** Represent memory as mstring (no copy) *) val paligned_memory_based_mstrings : mstring_factory (** Uses memory to represent mstrings. The memory bigarrays are allocated with {!Netsys_mem.alloc_memory_pages} if available, and [Bigarray.Array1.create] if not. *) val memory_pool_based_mstrings : Netsys_mem.memory_pool -> mstring_factory (** Uses memory to represent mstrings. The memory bigarrays are obtained from the pool. The length of these mstrings is limited by the blocksize of the pool. *) val length_mstrings : mstring list -> int (** returns the sum of the lengths of the mstrings *) val concat_mstrings : mstring list -> string (** concatenates the mstrings and return them as single string. The returned string may be shared with one of the mstrings passed in. *) val concat_mstrings_bytes : mstring list -> Bytes.t (** Same, returning bytes *) val prefix_mstrings : mstring list -> int -> string (** [prefix_mstrings l n]: returns the first [n] chars of the concatenated mstrings [l] as single string *) val prefix_mstrings_bytes : mstring list -> int -> Bytes.t (** Same, returning bytes *) val blit_mstrings_to_memory : mstring list -> memory -> unit (** blits the mstrings one after the other to the memory, so that they appear there concatenated *) val shared_sub_mstring : mstring -> int -> int -> mstring (** [shared_sub_mstring ms pos len]: returns an mstring that includes a substring of [ms], starting at [pos], and with [len] bytes. The returned mstring shares the buffer with the original mstring [ms] *) val shared_sub_mstrings : mstring list -> int -> int -> mstring list (** Same for a list of mstrings *) val copy_mstring : mstring -> mstring (** Create a copy *) val copy_mstrings : mstring list -> mstring list (** Create a copy *) val in_channel_of_mstrings : mstring list -> Netchannels.in_obj_channel (** Returns a channel reading from the sequence of mstrings *) val mstrings_of_in_channel : Netchannels.in_obj_channel -> mstring list (** Returns the data of a channel as a sequence of mstrings *) (** See also {!Netsys_digests.digest_mstrings} for a utiliy function to compute cryptographic digests on mstrings *) type named_mstring_factories = (string, mstring_factory) Hashtbl.t ocamlnet-4.1.2/src/netstring/netmech_scram_gssapi.mli0000644000175000017500000000463212731530350021435 0ustar gerdgerd(* $Id$ *) (** The SCRAM security mechanism for GSS-API {b This module needs the SHA-1 hash function. In order to use it, initialize crypto support, e.g. by including the [nettls-gnutls] packages and calling {!Nettls_gnutls.init}.} *) (** See RFC 5802 *) open Netsys_gssapi val scram_mech : oid (** The OID of SCRAM *) (** A [client_key_ring] identifies the user on the client side *) class type client_key_ring = object method password_of_user_name : string -> string (** Returns the cleartext password for a user name, or raises [Not_found] if the user is unknown *) method default_user_name : string option (** This method may return a default user name *) end (** A [server_key_verifier] verifies on the server side that the users exist and have the right authentication credentials *) class type server_key_verifier = object method scram_credentials : string -> Netmech_scram.credentials (** Returns the credentials for a user, or raises [Not_found]. See {!Netmech_scram.create_server_session} for the meaning of this triple. *) end val scram_gss_api : ?client_key_ring:client_key_ring -> ?server_key_verifier:server_key_verifier -> Netmech_scram.profile -> (module Netsys_gssapi.GSSAPI) (** Returns a standard-compliant GSS-API object for the passed SCRAM profile. The object can be used on the client side for all users whose passwords are available via [client_key_ring]. By default, the key ring is empty. On the server side, the object authenticates all users whose credentials are available via [server_key_verifier]. By default, no user can be verified. SCRAM only allows usernames of type [NT_USER_NAME] for identifying users. For principals (servers), this SCRAM implementation allows identifiers of type [NT_HOSTBASED_SERVICE] and [NT_USER_NAME]. Any such name can be used, because the SCRAM protocol does not use principal names. The contexts will always return the hostbased service "@" as name of the principals. This implementation checks whether the messages are verified and unwrapped in the same order than generated, and reports this via the [`Unseq_token] and [`Gap_token] flags. Support for true replay detection ([`Duplicate_token]) is not implemented, though. Replayed tokens will also be marked as [`Unseq_token]. *) ocamlnet-4.1.2/src/netstring/netcompression.ml0000644000175000017500000000175412731530350020160 0ustar gerdgerd(* $Id$ *) type algo = { iana_name : string; encoder : (unit -> Netchannels.io_obj_channel) option; decoder : (unit -> Netchannels.io_obj_channel) option; } let registry = Hashtbl.create 5 let register ~iana_name ?encoder ?decoder () = let algo = { iana_name = iana_name; encoder = encoder; decoder = decoder } in Hashtbl.replace registry iana_name algo let lookup_encoder ~iana_name = let algo = Hashtbl.find registry iana_name in match algo.encoder with | None -> raise Not_found | Some f -> f let lookup_decoder ~iana_name = let algo = Hashtbl.find registry iana_name in match algo.decoder with | None -> raise Not_found | Some f -> f let all_encoders() = Hashtbl.fold (fun name algo acc -> if algo.encoder <> None then name :: acc else acc ) registry [] let all_decoders() = Hashtbl.fold (fun name algo acc -> if algo.decoder <> None then name :: acc else acc ) registry [] ocamlnet-4.1.2/src/netstring/netmech_scram_http.ml0000644000175000017500000002222512731530350020753 0ustar gerdgerd(* There isn't an RFC yet ... *) open Printf module type PROFILE = sig val mutual : bool val hash_function : Netsys_digests.iana_hash_fn val test_nonce : string option end module Make_SCRAM(P:PROFILE) : Nethttp.HTTP_CLIENT_MECHANISM = struct let profile = { Netmech_scram.ptype = `SASL; hash_function = P.hash_function; return_unknown_user = false; iteration_count_limit = 65536; } let hash_available iana_name = iana_name = `MD5 || ( try ignore(Netsys_digests.iana_find iana_name); true with Not_found -> false ) let mechanism_name = "SCRAM" let available() = hash_available P.hash_function let restart_supported = false (* TODO *) type credentials = (string * string * (string * string) list) list type client_session = { sid : string option; data : Netmech_scram.client_session; initflag : bool; realm_accepted : string option; realm_actual : string option; realm_tosend : string option; error : bool; } let init_credentials l = (l:credentials) let client_state cs = if cs.error then `Auth_error "SCRAM protocol error" else if not P.mutual && Netmech_scram.client_semifinish_flag cs.data then `OK else if Netmech_scram.client_finish_flag cs.data then `OK else match Netmech_scram.client_error_flag cs.data with | Some error -> `Auth_error (Netmech_scram.error_of_exn error) | None -> if cs.realm_actual = None then `Wait else if Netmech_scram.client_emit_flag cs.data then `Emit else if Netmech_scram.client_recv_flag cs.data then `Wait else assert false let create_client_session ~user ~creds ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_scram_http.create_client_session:" [ "realm" ] params in let pw = try Netsys_sasl_util.extract_password creds with Not_found -> failwith "Netmech_scram_http.create_client_session: no password \ found in credentials" in let data = Netmech_scram.create_client_session ?nonce:P.test_nonce profile user pw in { sid = None; data; initflag = true; realm_accepted = (try Some(List.assoc "realm" params) with Not_found -> None); realm_actual = None; realm_tosend = None; error = false } let client_configure_channel_binding cs cb = if cb <> `None then failwith "Netmech_scram_http.client_configure_channel_binding: \ not supported" else cs let client_channel_binding cs = `None let client_restart ~params cs = failwith "Netmech_scram_http.client_restart: not supported" let decode_params l = (* params are always already decoded *) List.map (function | (n, `Q _) -> assert false | (n, `V v) -> (n,v) ) l let base64_decode s = let s1 = Netencoding.Base64.decode s in let l1 = String.length s1 in if s1 <> "" && s1.[l1-1] = '\n' then String.sub s1 0 (l1-1) else s1 let client_match ~params (ch_name, ch_params) = try let params = Netsys_sasl_util.preprocess_params "Netmech_scram_http.client_match:" [ "realm" ] params in let ch_params = decode_params ch_params in if String.lowercase ch_name <> Netmech_scram.mechanism_name profile then raise Not_found; let ac_realm_opt = try Some(List.assoc "realm" params) with Not_found -> None in let ch_realm_opt = try Some(List.assoc "realm" ch_params) with Not_found -> None in ( match ac_realm_opt, ch_realm_opt with | Some ac_realm, Some ch_realm -> if ac_realm <> ch_realm then raise Not_found | _ -> () ); let realm_name = match ch_realm_opt with | None -> "default" | Some r -> r in `Accept(realm_name, None) with | Not_found | Failure _ -> `Reject let client_process_authinfo cs hdr = (* There must be an Authentication-Info header *) try let info = hdr # field "authentication-info" in let info_params = Nethttp.Header.parse_quoted_parameters info in let sid_opt = try Some(List.assoc "sid" info_params) with Not_found -> None in let data_b64 = List.assoc "data" info_params in let data = try base64_decode data_b64 with Failure _ -> raise Not_found in ( match sid_opt, cs.sid with | None, None -> () | Some sid, None -> () | Some sid1, Some sid2 -> if sid1 <> sid2 then raise Not_found | None, Some _ -> raise Not_found ); { cs with data = Netmech_scram.client_recv_message cs.data data; sid = sid_opt } with | Not_found -> { cs with error = true } let client_process_challenge cs method_name uri hdr challenge = if Netmech_scram.client_semifinish_flag cs.data then client_process_authinfo cs hdr else try let (_, ch_params) = challenge in let ch_params = decode_params ch_params in if cs.initflag then (* initial challenge *) let realm = try Some(List.assoc "realm" ch_params) with Not_found -> None in { cs with initflag = false; realm_actual = realm; realm_tosend = realm; } else let sid_opt = try Some(List.assoc "sid" ch_params) with Not_found -> None in let data_b64 = List.assoc "data" ch_params in let data = try base64_decode data_b64 with Failure _ -> raise Not_found in ( match sid_opt, cs.sid with | None, None -> () | Some sid, None -> () | Some sid1, Some sid2 -> if sid1 <> sid2 then raise Not_found | None, Some _ -> raise Not_found ); { cs with data = Netmech_scram.client_recv_message cs.data data; sid = sid_opt } with | Not_found -> { cs with error = true } let client_emit_response cs method_name uri hdr = let ds, data = Netmech_scram.client_emit_message cs.data in let data_b64 = Netencoding.Base64.encode data in let data_l = [ "data", `V data_b64 ] in let realm_l = match cs.realm_tosend with | Some r -> ["realm", `V r] | None -> [] in let sid_l = match cs.sid with | Some sid -> ["sid", `V sid] | None -> [] in let cs = { cs with data = ds; realm_tosend = None } in ( cs, (Netmech_scram.mechanism_name profile, (realm_l @ sid_l @ data_l) ), [] ) let client_user_name cs = Netmech_scram.client_user_name cs.data let client_stash_session cs = assert false (* TODO *) let client_resume_session s = assert false (* TODO *) let client_session_id cs = cs.sid let client_domain cs = (* CHECK *) [ "/" ] let client_prop cs name = Netmech_scram.client_prop cs.data name let client_gssapi_props cs = raise Not_found end (* #use "topfind";; #require "netstring,nettls-gnutls";; module P = struct let mutual = true let hash_function = `SHA_256 let test_nonce = Some "rOprNGfwEbeRWgbNEkqO" end;; module M = Netmech_scram_http.Make_SCRAM(P);; Netmech_scram.Debug.enable := true;; let creds = M.init_credentials [ "password", "pencil", [] ];; let s = M.create_client_session ~user:"user" ~creds ~params:["realm", "testrealm@example.com", true ] ();; let empty_hdr = new Netmime.basic_mime_header [];; let s = M.client_process_challenge s "GET" "/resource" empty_hdr ("SCRAM-SHA-256", ["realm", `V "testrealm@example.com"]);; let s, msg1, new_hdr = M.client_emit_response s "GET" "/resource" empty_hdr;; let s = M.client_process_challenge s "GET" "/resource" empty_hdr ("SCRAM-SHA-256", ["realm", `V "testrealm@example.com"; "sid", `V "AAAABBBBCCCCDDDD"; "data", `V "cj1yT3ByTkdmd0ViZVJXZ2JORWtxTyVodllEcFdVYTJSYVRDQWZ1eEZJbGopaE5sRixzPVcyMlphSjBTTlk3c29Fc1VFamI2Z1E9PSxpPTQwOTYK"; ] );; let s, msg2, new_hdr = M.client_emit_response s "GET" "/resource" empty_hdr;; let s = M.client_process_challenge s "GET" "/resource" empty_hdr ("SCRAM-SHA-256", ["realm", `V "testrealm@example.com"; "sid", `V "AAAABBBBCCCCDDDD"; "data", `V "dj02cnJpVFJCaTIzV3BSUi93dHVwK21NaFVaVW4vZEI1bkxUSlJzamw5NUc0PQo=" ] );; *) ocamlnet-4.1.2/src/netstring/netfs.ml0000644000175000017500000004667312731530350016240 0ustar gerdgerd(* $Id$ *) type read_flag = [ `Skip of int64 | `Binary | `Streaming | `Dummy ] type read_file_flag = [ `Binary | `Dummy ] type write_flag = [ `Create | `Exclusive | `Truncate | `Binary | `Streaming | `Dummy ] type write_file_flag = [ `Create | `Exclusive | `Truncate | `Binary | `Link | `Dummy ] type write_common = [ `Create | `Exclusive | `Truncate | `Binary | `Dummy ] (* The intersection of write_flag and write_file_flag *) type size_flag = [ `Dummy ] type test_flag = [ `Link | `Dummy ] type remove_flag = [ `Recursive | `Dummy ] type rename_flag = [ `Dummy ] type symlink_flag = [ `Dummy ] type readdir_flag = [ `Dummy ] type readlink_flag = [ `Dummy ] type mkdir_flag = [ `Path | `Nonexcl | `Dummy ] type rmdir_flag = [ `Dummy ] type copy_flag = [ `Dummy ] type test_type = [ `N | `E | `D | `F | `H | `R | `W | `X | `S ] class type local_file = object method filename : string method close : unit -> unit end class type stream_fs = object method path_encoding : Netconversion.encoding option method path_exclusions : (int * int) list method nominal_dot_dot : bool method read : read_flag list -> string -> Netchannels.in_obj_channel method read_file : read_file_flag list -> string -> local_file method write : write_flag list -> string -> Netchannels.out_obj_channel method write_file : write_file_flag list -> string -> local_file -> unit method size : size_flag list -> string -> int64 method test : test_flag list -> string -> test_type -> bool method test_list : test_flag list -> string -> test_type list -> bool list method remove : remove_flag list -> string -> unit method rename : rename_flag list -> string -> string -> unit method symlink : symlink_flag list -> string -> string -> unit method readdir : readdir_flag list -> string -> string list method readlink : readlink_flag list -> string -> string method mkdir : mkdir_flag list -> string -> unit method rmdir : rmdir_flag list -> string -> unit method copy : copy_flag list -> string -> string -> unit method cancel : unit -> unit end class empty_fs detail : stream_fs = let enosys path = raise (Unix.Unix_error(Unix.ENOSYS, path, detail)) in object method path_encoding = enosys "" method path_exclusions = enosys "" method nominal_dot_dot = enosys "" method read _ p = enosys p method read_file _ p = enosys p method write _ p = enosys p method write_file _ p _ = enosys p method size _ p = enosys p method test _ p _ = enosys p method test_list _ p _ = enosys p method remove _ p = enosys p method rename _ p _ = enosys p method symlink _ p _ = enosys p method readdir _ p = enosys p method readlink _ p = enosys p method mkdir _ p = enosys p method rmdir _ p = enosys p method copy _ p _ = enosys p method cancel () = enosys "" end let slash_re = Netstring_str.regexp "/+" let drive_re = Netstring_str.regexp "^[a-zA-Z]:$" exception Not_absolute exception Unavailable let list_isect_empty l1 l2 = (* whether intersection is empty *) List.for_all (fun x1 -> not (List.mem x1 l2)) l1 let readdir d = try let l = ref [] in ( try while true do l := (Unix.readdir d) :: !l done; assert false with End_of_file -> () ); Unix.closedir d; List.rev !l with | error -> Unix.closedir d; raise error let copy_prim ~streaming orig_fs orig_name dest_fs dest_name = let sflags = if streaming then [`Streaming] else [] in Netchannels.with_in_obj_channel (orig_fs#read (sflags @ [`Binary]) orig_name) (fun r_ch -> Netchannels.with_out_obj_channel (dest_fs#write (sflags @ [`Binary; `Truncate; `Create]) dest_name) (fun w_ch -> w_ch # output_channel r_ch ) ) let local_fs ?encoding ?root ?(enable_relative_paths=false) () : stream_fs = let enc = match encoding with | None -> ( match Sys.os_type with | "Win32" -> Netconversion.user_encoding() | _ -> None ) | Some e -> Some e in ( match enc with | None -> () | Some e -> if not (Netconversion.is_ascii_compatible e) then failwith "Netfs.local_fs: the encoding is not ASCII-compatible"; ); let excl = match Sys.os_type with | "Win32" | "Cygwin" -> (* http://msdn.microsoft.com/en-us/library/aa365247%28v=VS.85%29.aspx *) [ 0, 31; (* control chars *) 42, 42; (* <, >, :, quotation mark, /, backslash, |, ?, * *) 47, 47; 58, 58; 60, 60; 62, 63; 92, 92; 124, 124 ] | _ -> [ 0, 0; 47, 47 ] in let excl_array_size = List.fold_left (fun mx (from,upto) -> max mx upto) 0 excl + 1 in let excl_array = ( let a = Array.make excl_array_size false in List.iter (fun (from,upto) -> for k = from to upto do a.(k) <- true done ) excl; a) in let check_component path c = let iter f s = match enc with | None -> String.iter (fun c -> f (Char.code c)) s | Some e -> Netconversion.ustring_iter e f s in try iter (fun code -> if code < excl_array_size && excl_array.(code) then raise (Unix.Unix_error(Unix.EINVAL, "Netfs: invalid char in path", path)) ) c with Netconversion.Malformed_code -> raise (Unix.Unix_error(Unix.EINVAL, "Netfs: path does not comply to charset encoding", path)) in let win32_root = root = None && Sys.os_type = "Win32" in let is_drive_letter s = Netstring_str.string_match drive_re s 0 <> None in let is_unc s = String.length s >= 3 && s.[0] = '/' && s.[1] = '/' && s.[2] <> '/' in let check_and_norm_path p = let l = Netstring_str.split_delim slash_re p in List.iter (check_component p) l; try ( match l with | [] -> raise (Unix.Unix_error(Unix.EINVAL, "Netfs: empty path", p)) | "" :: first :: rest -> if win32_root then ( if ((not (is_drive_letter first) || rest=[]) && not (is_unc p)) then raise Not_absolute ) | first :: rest -> if win32_root then ( if not(is_drive_letter first) || rest=[] then raise Not_absolute ) else raise Not_absolute ); let np = String.concat "/" l in if win32_root then ( if is_unc p then "/" ^ np else if np.[0] = '/' then String.sub np 1 (String.length np - 1) (* remove leading / *) else np ) else np with | Not_absolute -> if enable_relative_paths then String.concat "/" l else raise (Unix.Unix_error(Unix.EINVAL, "Netfs: path not absolute", p)) in let real_root = match root with | None -> "" | Some r -> if (Unix.stat r).Unix.st_kind <> Unix.S_DIR then failwith "Netfs.local_fs: root is not a directory"; r in ( object(self) method path_encoding = enc method path_exclusions = excl method nominal_dot_dot = false method read flags filename = let fn = real_root ^ check_and_norm_path filename in let binary = List.mem `Binary flags in let skip_d = try List.find (fun flag -> match flag with | `Skip _ -> true | _ -> false ) flags with Not_found -> `Skip 0L in let skip = match skip_d with | `Skip n -> n | _ -> assert false in (* Use Unix.openfile to open so we get Unix_errors on error *) let fd = Unix.openfile fn [Unix.O_RDONLY] 0 in let st = Unix.fstat fd in if st.Unix.st_kind = Unix.S_DIR then raise(Unix.Unix_error(Unix.EISDIR,"Netfs.read","")); if skip > 0L then ignore(Unix.LargeFile.lseek fd skip Unix.SEEK_SET); let ch = Unix.in_channel_of_descr fd in set_binary_mode_in ch binary; new Netchannels.input_channel ch method read_file flags filename = let fn = real_root ^ check_and_norm_path filename in let st = Unix.stat fn in if st.Unix.st_kind = Unix.S_DIR then raise(Unix.Unix_error(Unix.EISDIR,"Netfs.read_file","")); ( object method filename = fn method close() = () end ) method write flags filename = let fn = real_root ^ check_and_norm_path filename in let binary = List.mem `Binary flags in let create = List.mem `Create flags in let truncate = List.mem `Truncate flags in let exclusive = List.mem `Exclusive flags in let mode = List.flatten [ [Unix.O_WRONLY]; if create then [ Unix.O_CREAT ] else []; if truncate then [ Unix.O_TRUNC ] else []; if exclusive then [ Unix.O_EXCL ] else []; ] in (* Use Unix.openfile to open so we get Unix_errors on error *) let fd = Unix.openfile fn mode 0o666 in let ch = Unix.out_channel_of_descr fd in set_binary_mode_out ch binary; new Netchannels.output_channel ch method write_file flags filename local = (* This is just a copy operation *) let fn = real_root ^ check_and_norm_path filename in let binary = List.mem `Binary flags in let link = List.mem `Link flags in let local_filename = local#filename in let wflags = List.map (function | #write_common as x -> (x :> write_flag) | _ -> `Dummy ) flags in try let do_copy = try not link || ( Unix.link local_filename fn; false ) with | Unix.Unix_error( ( Unix.EACCES | Unix.ELOOP | Unix.ENAMETOOLONG | Unix.ENOENT | Unix.ENOTDIR | Unix.EPERM | Unix.EROFS ), _, _) as e -> (* These errors cannot be fixed by doing copies instead *) raise e | Unix.Unix_error(_,_,_) -> true in if do_copy then ( let fd_local = Unix.openfile local_filename [Unix.O_RDONLY] 0 in let ch_local = Unix.in_channel_of_descr fd_local in set_binary_mode_in ch_local binary; Netchannels.with_in_obj_channel (new Netchannels.input_channel ch_local) (fun obj_local -> Netchannels.with_out_obj_channel (self # write wflags filename) (fun out -> out # output_channel obj_local ) ); ); local#close() with | error -> local#close(); raise error method size flags filename = let fn = real_root ^ check_and_norm_path filename in let fd = Unix.openfile fn [Unix.O_RDONLY] 0 in try let n = Unix.LargeFile.lseek fd 0L Unix.SEEK_END in Unix.close fd; n with | error -> Unix.close fd; raise error (* esp. non-seekable *) method private test_list_NH flags fn = try let st = Unix.LargeFile.lstat fn in if st.Unix.LargeFile.st_kind = Unix.S_LNK then [ `N; `H ] else [ `N ] with | Unix.Unix_error(Unix.ENOENT,_,_) -> [] method private test_list_EDFS flags fn = try let st = if List.mem `Link flags then Unix.LargeFile.lstat fn else Unix.LargeFile.stat fn in let non_empty = st.Unix.LargeFile.st_size <> 0L in let kind_l = match st.Unix.LargeFile.st_kind with | Unix.S_REG -> [ `F ] | Unix.S_DIR -> [ `D ] | _ -> [] in [ `E ] @ kind_l @ (if non_empty then [`S] else []) with | Unix.Unix_error(Unix.ENOENT,_,_) -> [] method private test_list_RWX flags fn = let r_ok = try Unix.access fn [Unix.R_OK]; true with _ -> false in let w_ok = try Unix.access fn [Unix.W_OK]; true with _ -> false in let x_ok = try Unix.access fn [Unix.X_OK]; true with _ -> false in List.flatten [ if r_ok then [`R] else []; if w_ok then [`W] else []; if x_ok then [`X] else [] ] method test flags filename ttype = let fn = real_root ^ check_and_norm_path filename in let l = match ttype with | `N | `H -> self#test_list_NH flags fn | `E | `D | `F | `S -> self#test_list_EDFS flags fn | `R | `W | `X -> self#test_list_RWX flags fn in List.mem ttype l method test_list flags filename tests = let fn = real_root ^ check_and_norm_path filename in let nh = if not(list_isect_empty tests [`N;`H]) then self#test_list_NH flags fn else [] in let edfs = if not(list_isect_empty tests [`E;`D;`F;`S]) then self#test_list_EDFS flags fn else [] in let rwx = if not(list_isect_empty tests [`R;`W;`X]) then self#test_list_RWX flags fn else [] in List.map (fun t -> match t with | `N | `H -> List.mem t nh | `E | `D | `F | `S -> List.mem t edfs | `R | `W | `X -> List.mem t rwx ) tests method remove flags filename = let fn = real_root ^ check_and_norm_path filename in if List.mem `Recursive flags then ( try self#rm_r_safe fn with Unavailable -> self#rm_r_trad fn ) else Unix.unlink fn (* A rename race: while the recursive removal progresses, a second process renames the directory. The removal function suddenly does not find the directory anymore. Even worse, the second process could move a different directory into the place of the old directory being deleted. In this case, the wrong data would be deleted. We can avoid this in the style of rm_r_safe, or by chdir-ing into the directory hierarchy. The latter is incompatible with multi-threading, so we don't do it here. *) method private rm_r_trad fn = (* "traditional" implemenation w/o protection against rename races *) let is_dir fn = try (Unix.stat fn).Unix.st_kind = Unix.S_DIR with _ -> false in let rec recurse fn = if is_dir fn then ( let files = readdir (Unix.opendir fn) in List.iter (fun file -> if file <> "." && file <> ".." then ( recurse (fn ^ "/" ^ file) ) ) files; Unix.rmdir fn; ) else Unix.unlink fn in recurse fn method private rm_r_safe fn = (* safer implemention using openat and fdopendir *) let rec rm_dir_entries fd = let files = readdir (Netsys_posix.fdopendir (Unix.dup fd)) in List.iter (fun file -> if file <> "." && file <> ".." then rm_dir_or_file fd file ) files and rm_dir_or_file fd file = let file_fd = Netsys_posix.openat fd file [Unix.O_RDONLY] 0 in let file_is_dir = try (Unix.fstat file_fd).Unix.st_kind = Unix.S_DIR with _ -> false in if file_is_dir then ( ( try rm_dir_entries file_fd with error -> Unix.close file_fd; raise error ); Unix.close file_fd; Netsys_posix.unlinkat fd file [Netsys_posix.AT_REMOVEDIR] ) else ( Unix.close file_fd; Netsys_posix.unlinkat fd file [] ) in let test_availability() = if not (Netsys_posix.have_at()) then raise Unavailable; try let dir = Netsys_posix.fdopendir(Unix.openfile "." [Unix.O_RDONLY] 0) in Unix.closedir dir with _ -> raise Unavailable in test_availability(); rm_dir_or_file Netsys_posix.at_fdcwd fn method rename flags oldname newname = let oldfn = real_root ^ check_and_norm_path oldname in let newfn = real_root ^ check_and_norm_path newname in Unix.rename oldfn newfn method symlink flags oldpath newpath = let oldfn = real_root ^ check_and_norm_path oldpath in let newfn = real_root ^ check_and_norm_path newpath in Unix.symlink oldfn newfn method readdir flags filename = let fn = real_root ^ check_and_norm_path filename in readdir (Unix.opendir fn) method readlink flags filename = let fn = real_root ^ check_and_norm_path filename in Unix.readlink fn method mkdir flags filename = if List.mem `Path flags then self#mkdir_p filename else ( let fn = real_root ^ check_and_norm_path filename in try Unix.mkdir fn 0o777 with | Unix.Unix_error(Unix.EEXIST,_,_) when List.mem `Nonexcl flags -> () ) method private mkdir_p filename = let rec traverse curdir todo = match todo with | [] -> () | d :: todo' -> let curdir' = curdir @ [d] in let p = String.concat "/" curdir' in let fn = real_root ^ p in ( try Unix.mkdir fn 0o777 with Unix.Unix_error(Unix.EEXIST,_,_) -> () ); traverse curdir' todo' in let fn1 = check_and_norm_path filename in let l = Netstring_str.split_delim slash_re fn1 in traverse [List.hd l] (List.tl l) method rmdir flags filename = let fn = real_root ^ check_and_norm_path filename in Unix.rmdir fn method copy flags srcfilename destfilename = copy_prim ~streaming:false self srcfilename self destfilename method cancel () = () (* This is totally legal here - the user has to invoke close_out anyway as part of the cancellation protocol. *) end ) let convert_path ?subst oldfs newfs oldpath = match oldfs#path_encoding, newfs#path_encoding with | Some oldenc, Some newenc -> Netconversion.convert ?subst ~in_enc:oldenc ~out_enc:newenc oldpath | _ -> oldpath let copy ?(replace=false) ?(streaming=false) orig_fs0 orig_name dest_fs0 dest_name = let orig_fs = (orig_fs0 :> stream_fs) in let dest_fs = (dest_fs0 :> stream_fs) in if replace then dest_fs # remove [] dest_name; try if orig_fs = dest_fs then orig_fs # copy [] orig_name dest_name else raise(Unix.Unix_error(Unix.ENOSYS,"","")) with | Unix.Unix_error(Unix.ENOSYS,_,_) | Unix.Unix_error(Unix.EXDEV,_,_) -> copy_prim ~streaming orig_fs orig_name dest_fs dest_name type file_kind = [ `Regular | `Directory | `Symlink | `Other | `None ] let iter ~pre ?(post=fun _ -> ()) fs0 start = let fs = (fs0 :> stream_fs) in let rec iter_members dir rdir = let files = fs # readdir [] dir in List.iter (fun file -> if file <> "." && file <> ".." then ( let absfile = dir ^ "/" ^ file in let relfile = if rdir="" then file else rdir ^ "/" ^ file in let l0 = fs#test_list [] absfile [`D; `F; `E] in let l1 = fs#test_list [`Link] absfile [`D; `F; `H] in let (is_dir0, is_reg0, is_existing) = match l0 with | [is_dir; is_reg; is_ex] -> (is_dir, is_reg, is_ex) | _ -> assert false in let (is_dir1, is_reg1, is_link) = match l1 with | [is_dir; is_reg; is_link] -> (is_dir, is_reg, is_link) | _ -> assert false in if is_dir1 then ( pre relfile `Directory `Directory; iter_members absfile relfile; post relfile ) else ( let t0 = if is_reg0 then `Regular else if is_dir0 then `Directory else if is_existing then `Other else `None in let t1 = if is_reg1 then `Regular else if is_dir1 then `Directory else if is_link then `Symlink else `Other in pre relfile t0 t1 ) ) ) files in iter_members start "" let copy_into ?(replace=false) ?subst ?streaming orig_fs0 orig_name dest_fs0 dest_name = let orig_fs = (orig_fs0 :> stream_fs) in let dest_fs = (dest_fs0 :> stream_fs) in let orig_base = Filename.basename orig_name in let dest_start = dest_name ^ "/" ^ convert_path ?subst orig_fs dest_fs orig_base in if not(dest_fs # test [] dest_name `D) then raise(Unix.Unix_error (Unix.ENOENT, "Netfs.copy_into: destination directory does not exist", dest_name)); if orig_fs # test [] orig_name `D then ( if replace then dest_fs # remove [ `Recursive ] dest_start; dest_fs # mkdir [ `Nonexcl ] dest_start; iter ~pre:(fun rpath typ link_typ -> let dest_rpath = convert_path ?subst orig_fs dest_fs rpath in match link_typ with | `Regular -> copy ?streaming orig_fs (orig_name ^ "/" ^ rpath) dest_fs (dest_start ^ "/" ^ dest_rpath) | `Directory -> dest_fs # mkdir [ `Nonexcl ] (dest_start ^ "/" ^ dest_rpath) | `Symlink -> dest_fs # symlink [] (orig_fs # readlink [] (orig_name ^ "/" ^ rpath)) (dest_start ^ "/" ^ dest_rpath) | `Other -> () ) orig_fs orig_name ) else copy ~replace ?streaming orig_fs orig_name dest_fs dest_start ocamlnet-4.1.2/src/netstring/netmime.mli0000644000175000017500000003120012731530350016704 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Netmime contains high-level classes and functions to process * mail and MIME messages. * * {b Contents} * * - {!Netmime.types} * - {!Netmime.classes} * * The tutorial has been moved to {!Netmime_tut}. Parsers for MIME * headers are now in {!Netmime_header}. Parser and printers for MIME * channels are now in {!Netmime_channels}. *) (* ***************************** Types ******************************** *) (** {1:types Types} *) open Netchannels type store = [ `Memory | `File of string (* The string is the filename of a file containing the (decoded) value * of the body *) ] (** Specifies where to store the body of a mail message. [`Memory] * means in-memory, [`File name] means in the file [name]. The body * is stored in decoded form (i.e. without transfer encoding). *) exception Immutable of string (** Raised if it is tried to modify a read-only value. The string denotes * the function or method where the incident happened. *) (** MIME headers and bodies are defined in two steps. First the subtype * describing read access is defined ([mime_header_ro], and [mime_body_ro]), * and after that the full class type including write access is defined * ([mime_header], and [mime_body]). * * The idea is that you can write functions that take an ro value as * input to indicate that they do not modify the value. For example: * * {[ * let number_of_fields (h:#mime_header_ro) = * List.length (h#fields) ]} * * This function accepts both [mime_header], and [mime_header_ro] values as * input, but the typing ensures that the function cannot mutate anything. * * There is another way to ensure that a header or body is not modified. * The read-only flag can be set when creating the object, and this flag * causes that all trials to modify the value will raise the exception * [Immutable]. Of course, such trials of mutation are only detected at * run-time. * * The advantage of the read-only flag is that it even works if * mutation depends on a condition, but it can be ensured that this * condition is never true. Furthermore, typing is much simpler (getting * subtyping correct can be annoying). *) (** This is the read-only version of a MIME header. There are only methods * to read the header fields. *) class type mime_header_ro = object (* read-only view of a mime_header *) method fields : (string * string) list method field : string -> string method multiple_field : string -> string list (** The current fields of the header. [fields] returns the complete * header. [field name] returns the value of the field, or raises * [Not_found]. [multiple_field name] returns all fields with the same * name. * * Note that field names are case-insensitive; [field "content-length"], * and [field "CONTENT-LENGTH"] will return the same field. However, * the method [fields] returns the original field names, without * adjustment of the case. * * The order of the fields is preserved. *) (** Since OCamlnet-4 the methods [content_length], [content_type], [content_dispositions] and [content_transfer_encoding] have been moved to {!Netmime_header}. *) end (** A MIME header with both read and write method. It is still possible, * however, to set the read-only flag to make this kind of header * immutable, too. *) class type mime_header = object (* A mutable or immutable mime_header *) inherit mime_header_ro (** Supports all these read access method, too *) method ro : bool (** whether the header is read-only or not *) method set_fields : (string * string) list -> unit method update_field : string -> string -> unit method update_multiple_field : string -> string list -> unit method delete_field : string -> unit (** These methods modify the fields of the header. If the header is * read-only, the exception [Immutable] will be raised. * * [set_fields] replaces the current fields with a new list of * (name,value) pairs. [update_field name value] replaces all fields * of the passed name with the single setting (name,value), or * adds this setting to the list. [update_multiple_field name values] * replaces all fields of the passed name with the list of values, * or adds this list. Finally, [delete_field name] deletes all * fields of the passed name. Nothing happens if there is no such * field. * * Both [update_field] and [update_multiple_field] first replace * existing values by the new ones without changing the order * of the fields in the header. Additional values are inserted * after the last existing value, or at the end of the header. *) end (** This is the read-only version of a MIME body. There are only methods * to read the body contents. * * The value of the body can be returned either as [string], or as * object channel. Both ways are possible independently of where * the value is stored, in-memory, or as external file. *) class type mime_body_ro = object (* a read-only view of a mime_body *) method value : string (** The [value] method returns the _decoded_ body, * i.e. transfer encodings are removed before the value is passed * back. * * When the body is stored in an external file, this method * reads the complete file into memory. *) method store : store (** Where the body is actually stored. *) method open_value_rd : unit -> in_obj_channel (** Opens the value for reading. This works independently of where * the body is stored. For example, to read the body line by line: * {[ * let ch = body # open_value_rd () in * try * while true do * let line = ch # input_line() in * ... (* do something *) * done; * assert false; (* never reached *) * with * End_of_file -> * ch # close_in() * ]} * * As [value], this method returns the value in decoded form. * This method is quite economical with the resources, and takes * only as much memory as needed for the channel operations. *) method finalize : unit -> unit (** After the body has been finalized, it cannot be accessed any longer. * External resources (files) are deallocated, if they are seen as * temporary. *) end (** A MIME body with both read and write method. It is still possible, * however, to set the read-only flag to make this kind of body * immutable, too. * * The value of the body can be set either by a [string], or by writing * to an object channel. Both ways are possible independently of where * the value is stored, in-memory, or as external file. *) class type mime_body = object (* A mutable or immutable mime_body *) inherit mime_body_ro (** Supports all these read access method, too *) method ro : bool (** whether this body is read-only or not *) method set_value : string -> unit (** Sets the value. If the value is immutable, the exception * [Immutable] will be raised. * * The passed string must be in decoded form. When the body is * stored in an external file, the file is overwritten. *) method open_value_wr : unit -> out_obj_channel (** Opens the value for writing. The current value is overwritten. * If the value is immutable, the exception [Immutable] will be raised. * * For example, to copy the file [f] into the value: * {[ * let ch = body # open_value_wr() in * let f_ch = new Netchannels.input_file f in * ch # output_channel f_ch; * f_ch # close_in(); * ch # close_out(); * ]} * *) end (** One can consider the pair [(mime_header, mime_body)] as simple MIME * message with one header and one body. Of course, this simple representation * does not support multi-part messages (attachments). For that reason, * the [complex_mime_message] was invented: The body can be further * structured as a sequence of parts that are complex messages themselves. * * For example, a mail message with an attachment is usually * represented as * {[ * (mail_header, `Parts [ (main_header, `Body main_body); * (att_header, `Body att_body) ] ) ]} * * Here, [mail_header] is the real header of the mail message. * [main_header] is the header of the main message, usually * only containing the content type of [main_body], the body * of the main message. The attachment has also its own * [att_header], again usually only containing the content type, * and the data of the attachment can be found in [att_body]. * * Nowadays, mails have often even a more complicated structure * with [`Parts] containing nested [`Parts]. As [complex_mime_message] * is recursive, any kind of nesting can be easily represented. *) type complex_mime_message = mime_header * complex_mime_body and complex_mime_body = [ `Body of mime_body | `Parts of complex_mime_message list ] (* A complex_mime_message can have (nested) multipart structure. *) type complex_mime_message_ro = mime_header_ro * complex_mime_body_ro and complex_mime_body_ro = [ `Body of mime_body_ro | `Parts of complex_mime_message_ro list ] (** The read-only view of a complex_mime_message *) (** Note: [`Parts []], i.e. [`Parts] together with an empty list, is * considered as illegal. Such a value cannot be transformed into * printable text. *) type mime_message = mime_header * [ `Body of mime_body ] (** Simple MIME message, in a form that is compatible with complex * ones. *) type mime_message_ro = mime_header_ro * [ `Body of mime_body_ro ] (** Read-only variant of simple messages *) (* ************************* Representations ************************** *) (** {1:classes Classes} *) class basic_mime_header : (string * string) list -> mime_header (** An implementation of [mime_header]. * * The argument is the list of (name,value) pairs of the header. * * Example: Create a MIME header with only the field "Content-type": * {[ let h = new basic_mime_header ["content-type", "text/plain"] ]} * * Example: Set the field "Subject": * {[ h # update_field "subject" "The value of this field" ]} * * This [mime_header] implementation bases on a mixture of a [Map] data * structure and a doubly linked list. The efficiency of the operations * (n=number of fields; m=average number of values per field; * n*m=total number of values): * - [new], [set_fields]: O(m * n * log n), but the construction of the dictionary * is deferred until the first real access * - [field]: O(log n) * - [multiple_field]: O(log n + m) * - [fields]: O(n * m) * - [update_field], [update_multiple_field]: O(log n + m) * - [delete_field]: O(n + m) *) val basic_mime_header : (string * string) list -> mime_header (** Same as function *) class wrap_mime_header : #mime_header -> mime_header (** Wraps the inner header *) class wrap_mime_header_ro : #mime_header_ro -> mime_header (** Wraps the inner header but disallows modifications. In this case, [Immutable] is raised. *) val wrap_mime_header_ro : #mime_header_ro -> mime_header (** Same as function *) class memory_mime_body : string -> mime_body (** An implementation of [mime_body] where the value is stored * in-memory. * * The argument is the initial (decoded) value of the body. * The method [store] returns [`Memory]. * * Example: To create a body from a string, call * {[ new memory_mime_body "The value as string" ]} *) val memory_mime_body : string -> mime_body (** Same as function *) class file_mime_body : ?fin:bool -> string -> mime_body (** An implementation of [mime_body] where the value is stored * in an external file. * * The argument is the name of the file containing the (decoded) value. * The method [store] returns [`File filename]. * The method [value] loads the contents of the file and returns them * as string. * * Example: To create a body from the file "f", call * {[ new file_mime_body "f" ]} * * @param fin whether to delete the file when the [finalize] method is called * (default: false) *) val file_mime_body : ?fin:bool -> string -> mime_body (** Same as function *) class wrap_mime_body : #mime_body -> mime_body (** Wraps the inner body *) class wrap_mime_body_ro : #mime_body_ro -> mime_body (** Wraps the inner body but disallows modifications. In this case, [Immutable] is raised. *) val wrap_mime_body_ro : #mime_body_ro -> mime_body (** Same as function *) val wrap_complex_mime_message_ro : complex_mime_message_ro -> complex_mime_message ocamlnet-4.1.2/src/netstring/netbuffer.ml0000644000175000017500000002442212731530350017065 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) open Netsys_types type t = { mutable buffer : Bytes.t; mutable buffer_length : int; (* = String.length buffer *) mutable length : int; create_length : int; } (* To help the garbage collector: * The 'buffer' has a minimum length of 31 bytes. This minimum can still * be stored in the minor heap. * The 'buffer' has a length which is always near a multiple of two. This * limits the number of different bucket sizes, and simplifies reallocation * of freed memory. *) (* Optimal string length: * Every string takes: 1 word for the header, enough words for the * contents + 1 Null byte (for C compatibility). * If the buffer grows, it is best to use a new string length such * that the number of words is exactly twice as large as for the previous * string. * n: length of the previous string in bytes * w: storage size of the previous string in words * n': length of the new string in bytes * w' = 2*w: storage size of the new string in words * * w = (n+1) / word_length + 1 * [it is assumed that (n+1) is always a multiple of word_length] * * n' = (2*w - 1) * word_length - 1 * * n' = [2 * ( [n+1] / word_length + 1) - 1] * word_length - 1 * = ... * = (2*n + 2) + word_length - 1 * = 2 * n + word_length + 1 * * n'+1 is again a multiple of word_length: * n'+1 = 2*n + 2 + word_length * = 2*(n+1) + word_length * = a multiple of word_length because n+1 is a multiple of word_length *) let word_length = Sys.word_size / 8 (* in bytes *) let create n = let bl = max n 31 in { buffer = Bytes.create bl; buffer_length = bl; length = 0; create_length = n } let reset b = let n = b.create_length in let bl = max n 31 in b.buffer <- Bytes.create bl; b.buffer_length <- bl; b.length <- 0 let contents b = Bytes.sub_string b.buffer 0 b.length let to_bytes b = Bytes.sub b.buffer 0 b.length let to_tstring_poly : type s . t -> s Netstring_tstring.tstring_kind -> s = fun b kind -> match kind with | Netstring_tstring.String_kind -> contents b | Netstring_tstring.Bytes_kind -> to_bytes b | Netstring_tstring.Memory_kind -> let m = Bigarray.Array1.create Bigarray.char Bigarray.c_layout b.length in Netsys_mem.blit_bytes_to_memory b.buffer 0 m 0 b.length; m let to_tstring : type s . t -> s Netstring_tstring.tstring_kind -> tstring = fun b kind -> let s = to_tstring_poly b kind in match kind with | Netstring_tstring.String_kind -> `String s | Netstring_tstring.Bytes_kind -> `Bytes s | Netstring_tstring.Memory_kind -> `Memory s let e_get() = invalid_arg "Netbuffer.get" let get b k = if k < 0 || k >= b.length then e_get(); Bytes.unsafe_get b.buffer k let nth = get let sub_invalid() = raise (Invalid_argument "Netbuffer.sub") let sub_bytes b k n = if k < 0 || n < 0 || k > b.length-n then sub_invalid(); Bytes.sub b.buffer k n let sub b k n = if k < 0 || n < 0 || k > b.length-n then sub_invalid(); Bytes.sub_string b.buffer k n let blit_to_bytes_invalid() = raise (Invalid_argument "Netbuffer.blit_to_bytes") let blit_to_bytes b srcpos dest destpos n = if srcpos < 0 || n < 0 || srcpos > b.length-n then blit_to_bytes_invalid(); Bytes.blit b.buffer srcpos dest destpos n let blit = blit_to_bytes let blit_to_string = blit_to_bytes let blit_to_memory b srcpos dest destpos n = if srcpos < 0 || n < 0 || srcpos > b.length-n then raise (Invalid_argument "Netbuffer.blit_to_memory"); Netsys_mem.blit_bytes_to_memory b.buffer srcpos dest destpos n let blit_to_tbuffer b srcpos dest destpos n = match dest with | `Bytes s | `String s -> blit_to_bytes b srcpos s destpos n | `Memory m -> blit_to_memory b srcpos m destpos n let unsafe_buffer b = b.buffer let length b = b.length let alloc_space b n = let rec new_size s = if s >= n then s else new_size(2*s + word_length + 1) in let size = min (new_size b.buffer_length) Sys.max_string_length in if size < n then failwith "Netbuffer: string too large"; let buffer' = Bytes.create size in Bytes.blit b.buffer 0 buffer' 0 b.length; b.buffer <- buffer'; b.buffer_length <- size let ensure_space b n = (* Ensure that there are n bytes space in b *) if n > b.buffer_length then alloc_space b n let add_internal blit b s k l = ensure_space b (l + b.length); blit s k b.buffer b.length l; b.length <- b.length + l let add_substring b s k l = if k < 0 || l < 0 || k > String.length s-l then invalid_arg "Netbuffer.add_substring"; add_internal Bytes.blit_string b s k l let add_sub_string = add_substring let add_string b s = add_substring b s 0 (String.length s) let add_subbytes b s k l = if k < 0 || l < 0 || k > Bytes.length s-l then invalid_arg "Netbuffer.add_subbytes"; add_internal Bytes.blit b s k l let add_bytes b s = add_subbytes b s 0 (Bytes.length s) let add_submemory b s k l = if k < 0 || l < 0 || k > Bigarray.Array1.dim s-l then invalid_arg "Netbuffer.add_submemory"; add_internal Netsys_mem.blit_memory_to_bytes b s k l let add_sub_memory = add_submemory let add_subtstring b ts k l = match ts with | `String s -> add_substring b s k l | `Bytes s -> add_subbytes b s k l | `Memory s -> add_submemory b s k l let add_tstring b ts = add_subtstring b ts 0 (Netsys_impl_util.tstring_length ts) let add_subtstring_poly b ops s k l = let open Netstring_tstring in add_internal ops.blit_to_bytes b s k l let add_tstring_poly b ops s = let open Netstring_tstring in add_subtstring_poly b ops s 0 (ops.length s) let add_buffer b1 b2 = add_internal Bytes.blit b1 b2.buffer 0 b2.length let add_char b c = let l = b.length in ensure_space b (l+1); Bytes.unsafe_set b.buffer l c; b.length <- l + 1 let add_char_2 b c1 c2 = let l = b.length in ensure_space b (l+2); Bytes.unsafe_set b.buffer l c1; Bytes.unsafe_set b.buffer (l+1) c2; b.length <- l + 2 let add_char_4 b c1 c2 c3 c4 = let l = b.length in ensure_space b (l+4); Bytes.unsafe_set b.buffer l c1; Bytes.unsafe_set b.buffer (l+1) c2; Bytes.unsafe_set b.buffer (l+2) c3; Bytes.unsafe_set b.buffer (l+3) c4; b.length <- l + 4 let space_for_additions ?len b = match len with Some l -> ensure_space b (b.length + l); l | None -> ensure_space b (b.length + 1); b.buffer_length - b.length let advance b n = let l = b.length + n in if n < 0 || l > b.buffer_length then invalid_arg "Netbuffer.advance"; b.length <- l let add_inplace ?len b f = let len' = space_for_additions ?len b in let n = f b.buffer b.length len' in advance b n; n let area_for_additions ?len b = let len' = space_for_additions ?len b in (b.buffer, b.length, len') let insert_internal name blit length b p s k l = if p < 0 || p > b.length || k < 0 || l < 0 || k > length s - l then invalid_arg ("Netbuffer." ^ name); ensure_space b (l + b.length); Bytes.unsafe_blit b.buffer p b.buffer (p+l) (b.length - p); blit s k b.buffer p l; b.length <- b.length + l let insert_substring = insert_internal "insert_substring" Bytes.blit_string String.length let insert_sub_string = insert_substring let insert_string b p s = insert_internal "insert_string" Bytes.blit_string String.length b p s 0 (String.length s) let insert_subbytes = insert_internal "insert_subbytes" Bytes.blit Bytes.length let insert_submemory = insert_internal "inser_submemory" Netsys_mem.blit_memory_to_bytes Bigarray.Array1.dim let insert_subtstring b p ts k l = match ts with | `String s -> insert_substring b p s k l | `Bytes s -> insert_subbytes b p s k l | `Memory s -> insert_submemory b p s k l let insert_char_invalid() = invalid_arg "Netbuffer.insert_char" let insert_char b p c = if p < 0 || p > b.length then insert_char_invalid(); ensure_space b (1 + b.length); Bytes.unsafe_blit b.buffer p b.buffer (p+1) (b.length - p); Bytes.set b.buffer p c; b.length <- b.length + 1 let e_set() = invalid_arg "Netbuffer.set" let set b k c = if k < 0 || k >= b.length then e_set(); Bytes.unsafe_set b.buffer k c let put_string_invalid() = invalid_arg "Netbuffer.put_string" let put_string b p s = if p < 0 || p > b.length then put_string_invalid(); let len = max b.length (p + String.length s) in ensure_space b len; String.unsafe_blit s 0 b.buffer p (String.length s); b.length <- len let blit_from_internal name blit length src srcpos b p n = if p < 0 || p > b.length || srcpos < 0 || n < 0 || srcpos > length src - n then invalid_arg ("Netbuffer." ^ name); let len = max b.length (p + n) in ensure_space b len; blit src srcpos b.buffer p n; b.length <- len let blit_from_string = blit_from_internal "blit_from_string" Bytes.blit_string String.length let blit_from_bytes = blit_from_internal "blit_from_bytes" Bytes.blit Bytes.length let blit_from_memory = blit_from_internal "blit_from_memory" Netsys_mem.blit_memory_to_bytes Bigarray.Array1.dim let blit_from_tstring ts p1 b p2 n = match ts with | `String s -> blit_from_string s p1 b p2 n | `Bytes s -> blit_from_bytes s p1 b p2 n | `Memory s -> blit_from_memory s p1 b p2 n let delete b k l = (* deletes l bytes at position k in b *) let n = b.buffer_length in if k+l <> n && k <> n then Bytes.blit b.buffer (k+l) b.buffer k (n-l-k); b.length <- b.length - l; () let try_shrinking b = (* If the buffer size decreases drastically, reallocate the buffer *) if b.length < (b.buffer_length / 2) then begin let rec new_size s = if s >= b.length then s else new_size(2*s + word_length + 1) in let size = new_size 31 in let buffer' = Bytes.create size in Bytes.blit b.buffer 0 buffer' 0 b.length; b.buffer <- buffer'; b.buffer_length <- size end let clear b = delete b 0 (b.length) let index_from_invalid() = raise (Invalid_argument "Netbuffer.index_from") let index_from b k c = if k > b.length then index_from_invalid(); let p = Bytes.index_from b.buffer k c in if p >= b.length then raise Not_found; p let print_buffer b = Format.printf "" b.length b.buffer_length ;; ocamlnet-4.1.2/src/netstring/netchannels_crypto.ml0000644000175000017500000002351612731530350021012 0ustar gerdgerd(* $Id$ *) class type tls_channel = object inherit Netchannels.raw_io_channel method tls_endpoint : Netsys_crypto_types.tls_endpoint end class type crypto_out_filter = object inherit Netchannels.out_obj_channel method supports_aead : bool method mac : unit -> string end class type crypto_in_filter = object inherit Netchannels.in_obj_channel method supports_aead : bool method mac : unit -> string end (************************** TLS *****************************) class tls_layer ?(start_pos_in=0) ?(start_pos_out=0) ?resume ~role ~rd ~wr ~peer_name config = let sbuf = Bytes.create 65536 in let recv buf = try let buf_len = min (Bigarray.Array1.dim buf) (Bytes.length sbuf) in let n = rd # input sbuf 0 buf_len in if n = 0 then raise(Unix.Unix_error(Unix.EAGAIN, "", "")); Netsys_mem.blit_bytes_to_memory sbuf 0 buf 0 n; n with | Sys_blocked_io -> raise(Unix.Unix_error(Unix.EAGAIN, "", "")) | End_of_file -> 0 in let send buf size = try let send_len = min size (Bytes.length sbuf) in Netsys_mem.blit_memory_to_bytes buf 0 sbuf 0 send_len; let n = ref 0 in while !n < send_len do let p = wr # output sbuf !n (send_len - !n) in n := !n + p done; wr # flush(); send_len with | Sys_blocked_io -> raise(Unix.Unix_error(Unix.EAGAIN, "", "")) in let endpoint = let module Config = (val config : Netsys_crypto_types.TLS_CONFIG) in let module P = Config.TLS in let ep = match resume with | None -> P.create_endpoint ~role ~recv ~send ~peer_name Config.config | Some data -> if role <> `Client then failwith "Netchannels.tls_layer: can only resume clients"; P.resume_client ~recv ~send ~peer_name Config.config data in let module Endpoint = struct module TLS = P let endpoint = ep end in (module Endpoint : Netsys_crypto_types.TLS_ENDPOINT) in ( object(self) val mutable in_closed = false val mutable out_closed = false val mutable pos_in = start_pos_in val mutable pos_out = start_pos_out method input buf pos len = if in_closed then raise Netchannels.Closed_channel; try if len=0 then raise Sys_blocked_io; let n = Netsys_tls.recv endpoint buf pos len in pos_in <- pos_in + n; if n=0 then raise End_of_file else n with | Sys_blocked_io -> 0 | Netsys_types.EAGAIN_RD -> 0 | Netsys_types.EAGAIN_WR -> 0 | Unix.Unix_error(Unix.EINTR,_,_) -> 0 method close_in () = if not in_closed then ( in_closed <- true; if out_closed then ( Netsys_tls.shutdown endpoint Unix.SHUTDOWN_ALL; wr # close_out(); rd # close_in(); ) ) method pos_in = pos_in method output buf pos len = if out_closed then raise Netchannels.Closed_channel; try if len=0 then raise Sys_blocked_io; let n = Netsys_tls.send endpoint buf pos len in pos_out <- pos_out + n; n with | Sys_blocked_io -> 0 | Netsys_types.EAGAIN_RD -> 0 | Netsys_types.EAGAIN_WR -> 0 | Unix.Unix_error(Unix.EINTR,_,_) -> 0 method flush () = if out_closed then raise Netchannels.Closed_channel; Netsys_tls.handshake endpoint method close_out() = if not out_closed then ( out_closed <- true; if in_closed then ( Netsys_tls.shutdown endpoint Unix.SHUTDOWN_ALL; wr # close_out(); rd # close_in(); ) else Netsys_tls.shutdown endpoint Unix.SHUTDOWN_SEND ) method pos_out = pos_out method tls_endpoint = endpoint end ) class tls_endpoint ?(start_pos_in=0) ?(start_pos_out=0) ?resume ~role ~peer_name fd config = let endpoint = Netsys_tls.create_file_endpoint ?resume ~role ~rd:fd ~wr:fd ~peer_name config in let fd_style = `TLS endpoint in ( object (self) inherit Netchannels.socket_descr ~fd_style fd as super method flush() = Netsys_tls.handshake (Netsys_tls.endpoint endpoint); super # flush() method tls_endpoint = (Netsys_tls.endpoint endpoint) end ) (*************** SYMM CRYPTO ************) let process_out proc ctx ch = let buf, free_buf = Netsys_mem.pool_alloc_memory2 Netsys_mem.small_pool in let out_buf, free_out_buf = Netsys_mem.pool_alloc_memory2 Netsys_mem.small_pool in let str_buf = Bytes.create (Bigarray.Array1.dim out_buf) in let buf_pos = ref 0 in let buf_len = Bigarray.Array1.dim buf in let closed = ref false in let pos_out = ref 0 in ( object(self) inherit Netchannels.augment_raw_out_channel method output s pos len = if !closed then raise Netchannels.Closed_channel; let n = min len (buf_len - !buf_pos) in Netsys_mem.blit_bytes_to_memory s pos buf !buf_pos n; buf_pos := !buf_pos + n; if !buf_pos = buf_len then self#flush(); pos_out := !pos_out + n; n method flush() = if !closed then raise Netchannels.Closed_channel; if !buf_pos > 0 then ( let buf1 = Bigarray.Array1.sub buf 0 !buf_pos in let consumed, generated = proc ~last:false buf1 out_buf in Netsys_mem.blit_memory_to_bytes out_buf 0 str_buf 0 generated; ch # really_output str_buf 0 generated; let remaining = buf_len - consumed in if remaining > 0 then Bigarray.Array1.blit (Bigarray.Array1.sub buf consumed remaining) (Bigarray.Array1.sub buf 0 remaining); buf_pos := remaining; ) method private final_flush() = (* tricky: call [proc ~last:true] at least once. Call it again if there is not enough space in out_buf (the encrypted msg can get longer), which is indicated by not consuming all data *) if !closed then raise Netchannels.Closed_channel; while !buf_pos >= 0 do let buf_sub = Bigarray.Array1.sub buf 0 !buf_pos in let consumed, generated = proc ~last:true buf_sub out_buf in Netsys_mem.blit_memory_to_bytes out_buf 0 str_buf 0 generated; ch # really_output str_buf 0 generated; let remaining = !buf_pos - consumed in if remaining > 0 then Bigarray.Array1.blit (Bigarray.Array1.sub buf consumed remaining) (Bigarray.Array1.sub buf 0 remaining); buf_pos := remaining; if !buf_pos = 0 then buf_pos := (-1) done; buf_pos := 0; () method close_out() = if not !closed then ( self # final_flush(); closed := true; free_buf(); free_out_buf(); ch # close_out() ) method pos_out = !pos_out method supports_aead = ctx # supports_aead method mac() = ctx # mac() end ) let encrypt_out ctx ch = let proc = ctx # encrypt in process_out proc ctx ch let decrypt_out ctx ch = let proc = ctx # decrypt in process_out proc ctx ch let process_in proc ctx ch = let buf, free_buf = Netsys_mem.pool_alloc_memory2 Netsys_mem.small_pool in let in_buf, free_in_buf = Netsys_mem.pool_alloc_memory2 Netsys_mem.small_pool in let str_buf = Bytes.create (Bigarray.Array1.dim in_buf) in let buf_pos = ref 0 in let buf_len = ref 0 in let in_buf_len = ref 0 in let closed = ref false in let eof = ref false in let pos_in = ref 0 in ( object(self) inherit Netchannels.augment_raw_in_channel method input s pos len = if !closed then raise Netchannels.Closed_channel; if !buf_pos = !buf_len && not !eof then ( try let l = Bigarray.Array1.dim in_buf - !in_buf_len in let n = ch # input str_buf 0 l in Netsys_mem.blit_bytes_to_memory str_buf 0 in_buf !in_buf_len n; in_buf_len := !in_buf_len + n; let consumed, generated = proc ~last:false (Bigarray.Array1.sub in_buf 0 !in_buf_len) buf in buf_pos := 0; buf_len := generated; let remaining = !in_buf_len - consumed in if remaining > 0 then Bigarray.Array1.blit (Bigarray.Array1.sub in_buf consumed remaining) (Bigarray.Array1.sub in_buf 0 remaining); in_buf_len := remaining; with | End_of_file -> eof := true; buf_pos := 0; buf_len := 0; while !in_buf_len >= 0 do let consumed, generated = proc ~last:true (Bigarray.Array1.sub in_buf 0 !in_buf_len) buf in buf_len := generated; in_buf_len := !in_buf_len - consumed; if !in_buf_len = 0 then in_buf_len := (-1) done; in_buf_len := 0; ); let n = min len (!buf_len - !buf_pos) in if !eof && n=0 && len>0 then raise End_of_file; Netsys_mem.blit_memory_to_bytes buf !buf_pos s pos n; buf_pos := !buf_pos + n; pos_in := !pos_in + n; n method close_in() = if not !closed then ( closed := true; free_buf(); free_in_buf(); ch # close_in() ) method pos_in = !pos_in method supports_aead = ctx # supports_aead method mac() = ctx # mac() end ) let encrypt_in ctx ch = let proc = ctx # encrypt in process_in proc ctx ch let decrypt_in ctx ch = let proc = ctx # decrypt in process_in proc ctx ch ocamlnet-4.1.2/src/netstring/netstream.ml0000644000175000017500000002552212731530350017111 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) open Netchannels;; class type in_obj_stream = object inherit Netchannels.in_obj_channel method block_size : int method window : Netbuffer.t method want : int -> unit method want_another_block : unit -> unit method window_length : int method window_at_eof : bool method skip : int -> unit end class virtual input_methods init_s_netbuf = object(self) val mutable s_pos = 0 val mutable s_at_eof = false val s_netbuf = init_s_netbuf val mutable s_closed = false method virtual want : int -> unit method virtual want_another_block : unit -> unit method virtual window_length : int method virtual input : Bytes.t -> int -> int -> int (* The following input methods base all on [input] *) method really_input buf pos len = if s_closed then raise Netchannels.Closed_channel; let rec read p = let l = self # input buf (pos+p) (len-p) in let p' = p + l in if p' = len then () else ( if l=0 then raise Sys_blocked_io; read p' ) in self # want len; (* may raise Buffer_underrun *) read 0 method really_input_string len = let buf = Bytes.create len in self # really_input buf 0 len; Bytes.unsafe_to_string buf method input_char () = let s = Bytes.create 1 in self # really_input s 0 1; Bytes.get s 0 method input_byte () = let s = Bytes.create 1 in self # really_input s 0 1; int_of_char (Bytes.get s 0) method input_line () = (* CHECK: Are the different end of line conventions important here? *) let rec find_eol() = try Netbuffer.index_from s_netbuf 0 '\n' (* or Not_found *) with Not_found -> if not s_at_eof then begin self # want_another_block(); (* may raise Buffer_underrun *) find_eol() end else self#window_length in if s_closed then raise Netchannels.Closed_channel; let n = find_eol() in if n >= self#window_length then begin if n = 0 then raise End_of_file; self#really_input_string n end else begin let s = self#really_input_string n in ignore(self#input_char()); (* '\n' *) s end method pos_in = if s_closed then raise Netchannels.Closed_channel; s_pos end class input_stream ?len ?(block_size = 4096) in_ch : in_obj_stream = object (self) val s_channel = (in_ch : in_obj_channel) val s_maxlength = len val s_blocksize = block_size val mutable s_underrun = false inherit input_methods (Netbuffer.create block_size) (* Note: This implementation must even work if [in_ch] is a pipe, * and raises Buffer_underrun from time to time. This may happen * at inconvenient situations. In this case the flag s_underrun stores * whether an underrun happened, and should be reported later. *) initializer try self # want_minimum() (* may raise Buffer_underrun *) with Buffer_underrun -> s_underrun <- true method private debug msg = prerr_endline (msg ^ ": s_pos=" ^ string_of_int s_pos ^ " s_at_eof=" ^ string_of_bool s_at_eof ^ " buflen=" ^ string_of_int (Netbuffer.length s_netbuf) ^ " s_closed=" ^ string_of_bool s_closed); method block_size = s_blocksize (* The block size is a static property, so never raise Closed_channel *) method window = if s_closed then raise Netchannels.Closed_channel; s_netbuf method window_length = if s_closed then raise Netchannels.Closed_channel; Netbuffer.length s_netbuf method window_at_eof = if s_closed then raise Netchannels.Closed_channel; s_at_eof method want_another_block() = if s_closed then raise Netchannels.Closed_channel; if not s_at_eof then begin (* How much are we allowed to read? *) let m = match s_maxlength with None -> s_blocksize | Some l -> min (l - s_pos - Netbuffer.length s_netbuf) s_blocksize in assert(m >= 0); (* Try to read m bytes: *) let rec read_block k = if k < m then let n = Netbuffer.add_inplace ~len:(m-k) s_netbuf (s_channel # input) (* may raise End_of_file, Buffer_underrun *) in ( if n > 0 then read_block (k+n) else raise Sys_blocked_io ) else () in try if m=0 then (* Artificial EOF because len is reached *) s_at_eof <- true else read_block 0 with End_of_file -> s_at_eof <- true end; (* self # debug "after stream#want_another_block"; *) (* Unix.sleep 1; *) method want n = if s_closed then raise Netchannels.Closed_channel; while not s_at_eof && Netbuffer.length s_netbuf < n do self # want_another_block() done method private want_minimum() = self # want s_blocksize method skip len = if s_closed then raise Netchannels.Closed_channel; let rec read len = if len > 0 then begin let k = min (Netbuffer.length s_netbuf) len in Netbuffer.delete s_netbuf 0 k; s_pos <- s_pos + k; self # want_minimum(); (* may raise Buffer_underrun *) if k > 0 then read (len - k) end in read len method input buf pos len = if s_closed then raise Netchannels.Closed_channel; if s_underrun then ( self # want_minimum(); (* may raise Buffer_underrun *) s_underrun <- false; ); (* Assertion: Either window length >= minimum, or eof *) let len' = min len (Netbuffer.length s_netbuf) in Netbuffer.blit s_netbuf 0 buf pos len'; Netbuffer.delete s_netbuf 0 len'; s_pos <- s_pos + len'; ( try self # want_minimum(); (* may raise Buffer_underrun *) with Buffer_underrun -> s_underrun <- true ); if len'=0 && len>0 then raise End_of_file; len' method close_in () = if not s_closed then ( s_channel # close_in(); s_closed <- true; ) end (* let find_prefix s1 pos len s2 = (* Checks where a non-empty prefix of [s2] occurs at the end of the substring * of [s1] beginning at [pos] with length [len]. The function returns * the position [p] of the prefix in [s1]. * The function raises Not_found if it does not find a prefix. * POSTCONDITION: * - s1[p..p+n-1] = s2[0..n-1] for some biggest n, n <= String.length s2 * "The string s1 contains the prefix of s2 at position p, and the * prefix has the maximum length n." * - n < String.length s2 ==> p+n = String.length s1 * "If the prefix is a proper prefix, it occurs at the end of s1" *) assert(String.length s2 > 0); let l1 = min (String.length s1) (pos+len) in let l2 = String.length s2 in let s2c0 = s2.[0] in let rec check_rec p k = k >= l2 || p+k >= l1 || (s1.[p+k] = s2.[k] && check_rec p (k+1)) in let rec search_rec p = if p >= l1 then raise Not_found; let p' = String.index_from s1 p s2c0 in (* or Not_found *) if p' >= l1 then raise Not_found; if check_rec p' 0 then p' else search_rec (p'+1) in search_rec pos ;; *) class sub_stream ?len ?delimiter in_stream : in_obj_stream = object(self) val s = (in_stream : in_obj_stream) val mutable s_winlen = 0 val mutable s_del = None (* initialized below *) val s_len = len val mutable s_underrun = false inherit input_methods (in_stream # window) initializer (match delimiter with Some "" -> invalid_arg "new Netstream.sub_stream"; | Some d -> s_del <- Some(d, Netaux.KMP.make_pattern d) | None -> s_del <- None ); (match s_len with Some l -> if l<0 then invalid_arg "new Netstream.sub_stream"; | None -> () ); try self # want_minimum() with Buffer_underrun -> s_underrun <- true method block_size = s # block_size method window = if s_closed then raise Netchannels.Closed_channel; s_netbuf method window_length = if s_closed then raise Netchannels.Closed_channel; s_winlen method window_at_eof = if s_closed then raise Netchannels.Closed_channel; s_at_eof method private compute_winlen() = (* sets [s_winlen], [s_at_eof], and returns whether the current window * is "ambigous" (it is not clear if the stream does end or does not * end) *) let ambigous = ref false in let w = s#window in let wlen = s#window_length in let weof = s#window_at_eof in begin match s_del with None -> s_winlen <- wlen; s_at_eof <- weof; | Some(d,pat) -> let p = Netaux.KMP.find_pattern pat ~len:wlen (Netbuffer.unsafe_buffer w) in if p >= wlen then begin (* Delimiter d does not occur in the buffer *) s_winlen <- wlen; s_at_eof <- weof; end else if (p + String.length d) > wlen then begin (* Case: prefix is a proper prefix *) ambigous := not weof; s_winlen <- wlen; s_at_eof <- weof; end else begin (* Case: [d] occurs in the window *) s_winlen <- p; s_at_eof <- true; end end; begin match s_len with None -> () | Some l -> if l - s_pos < s_winlen then begin ambigous := false; s_winlen <- l - s_pos; s_at_eof <- true; end end; !ambigous method want_another_block() = if s_closed then raise Netchannels.Closed_channel; s # want_another_block(); (* may raise Buffer_underrun *) while self # compute_winlen() do s # want_another_block(); (* may raise Buffer_underrun *) done method want n = if s_closed then raise Netchannels.Closed_channel; while not s_at_eof && s_winlen < n do self # want_another_block() (* may raise Buffer_underrun *) done method private want_minimum() = if self # compute_winlen() then self # want_another_block(); (* may raise Buffer_underrun *) self # want s#block_size method skip len = if s_closed then raise Netchannels.Closed_channel; let rec read len = if len > 0 then begin let k = min s_winlen len in s # skip k; (* may raise Buffer_underrun *) s_pos <- s_pos + k; self # want_minimum(); (* may raise Buffer_underrun *) if k > 0 then read (len - k) end in read len method input buf pos len = if s_closed then raise Netchannels.Closed_channel; if s_underrun then ( self # want_minimum(); (* may raise Buffer_underrun *) s_underrun <- false; ); (* Assertion: Either window length >= minimum, or eof *) let len' = min len s_winlen in Netbuffer.blit s_netbuf 0 buf pos len'; s # skip len'; (* never raises Buffer_underrun *) s_pos <- s_pos + len'; ( try self # want_minimum(); with Buffer_underrun -> s_underrun <- true ); if len'=0 && len>0 then raise End_of_file; len' method close_in () = if not s_closed then ( s # close_in(); s_closed <- true; ) end let print_in_obj_stream fmt s = Format.fprintf fmt "" s#pos_in s#window_length s#window_at_eof ;; ocamlnet-4.1.2/src/netstring/netbuffer.mli0000644000175000017500000002112412731530350017232 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** A Netbuffer.t is a buffer that can grow and shrink dynamically. *) open Netsys_types type t val create : int -> t (** Creates a netbuffer which allocates initially this number of bytes. * The logical length is zero. *) val contents : t -> string (** Returns the contents of the buffer as fresh string. *) val to_bytes : t -> Bytes.t (** Returns the contents of the buffer as fresh string. *) val to_tstring_poly : t -> 's Netstring_tstring.tstring_kind -> 's (** Return the buffer in the format as selected by the arg *) val to_tstring : t -> _ Netstring_tstring.tstring_kind -> tstring (** Returns the buffer as tagged string, selecting the chosen representation *) val length : t -> int (** Returns the logical length of the buffer *) (** {2 Extracting strings} *) val get : t -> int -> char (** [get nb pos]: Get the character at [pos] *) val nth : t -> int -> char (** Alias for [get] *) val sub : t -> int -> int -> string (** [sub nb k n]: returns the n characters starting at position [n] from * netbuffer [nb] as fresh string *) val sub_bytes : t -> int -> int -> Bytes.t (** Same for bytes *) (** {2 Extraction with blit} *) val blit_to_bytes : t -> int -> Bytes.t -> int -> int -> unit (** [blit_to_bytes nb srcpos dest destpos len]: Copies the [len] bytes at * position [srcpos] from [nb] to the string [dest] at position [destpos]. *) val blit_to_string : t -> int -> Bytes.t -> int -> int -> unit DEPRECATED("Use blit_to_bytes instead.") val blit : t -> int -> Bytes.t -> int -> int -> unit (** Compatibility name for [blit_to_bytes] *) val blit_to_memory : t -> int -> Netsys_mem.memory -> int -> int -> unit (** [blit_to_memory nb srcpos dest destpos len]: Copies the [len] bytes at * position [srcpos] from [nb] to the membuffer [dest] at position [destpos]. *) val blit_to_tbuffer : t -> int -> tbuffer -> int -> int -> unit (** Blits to a tagged buffer *) (** {2 Appending strings} *) val add_string : t -> string -> unit (** [add_string nb s]: Adds a copy of the string [s] to the logical end of * the netbuffer [nb]. If necessary, [nb] grows. *) val add_bytes : t -> Bytes.t -> unit (** Same for bytes *) val add_tstring : t -> tstring -> unit (** Same for tagged string *) val add_tstring_poly : t -> 's Netstring_tstring.tstring_ops -> 's -> unit (** Polymorphic version *) val add_substring : t -> string -> int -> int -> unit (** [add_substring nb s k n]: Adds the substring of [s] starting at position * [k] with length [n] to the logical end of the netbuffer [nb]. If necessary, * [nb] grows. * * This is semantically the same as * [add_string nb (String.sub s k n)], but the extra copy is avoided. *) val add_subbytes : t -> Bytes.t -> int -> int -> unit (** Same for bytes *) val add_subtstring : t -> tstring -> int -> int -> unit (** Same for tagged string *) val add_sub_string : t -> string -> int -> int -> unit DEPRECATED("Use add_substring instead.") val add_submemory : t -> Netsys_mem.memory -> int -> int -> unit (** Same as [add_substring], but gets data from a memory buffer *) val add_sub_memory : t -> Netsys_mem.memory -> int -> int -> unit DEPRECATED("Use add_submemory instead.") val add_subtstring_poly : t -> 's Netstring_tstring.tstring_ops -> 's -> int -> int -> unit (** Polymorphic version *) val add_char : t -> char -> unit (** [add_char nb c]: Adds a single char at the end of the buffer *) val add_char_2 : t -> char -> char -> unit (** [add_char_2 nb c1 c2]: Adds two chars at the end of the buffer *) val add_char_4 : t -> char -> char -> char -> char -> unit (** [add_char_4 nb c1 c2 c3 c4]: Adds four chars at the end of the buffer *) val add_inplace : ?len:int -> t -> (Bytes.t -> int -> int -> int) -> int (** [add_inplace nb f]: Calls the function [f] to add bytes to the * netbuffer [nb]. The arguments of [f] are the buffer, the position * in the buffer, and the maximum length. The function [f] must return * the actual number of added bytes; this number is also returned by * [add_inplace]. * * Example: let n = add_inplace nb (Pervasives.input ch) * * The argument [len] is the number of bytes to add (second argument of * [f]). It defaults to the number of free bytes in the buffer after space * for at least one byte has been allocated. *) val add_buffer : t -> t -> unit (** [add_buffer nb1 nb2]: Adds the contents of [nb2] to the end of [nb1] *) val area_for_additions : ?len:int -> t -> (Bytes.t * int * int) val advance : t -> int -> unit (** These two functions work together, so that the effect of [add_inplace] can be obtained in two steps. First, the user calls {[ let (s,pos,len) = area_for_additions nb ]} to get the area where to put new data of length [n], with [n <= len]. After this the data is made valid by {[ advance n ]} *) (** {2 Inserting strings} *) val insert_string : t -> int -> string -> unit (** [insert_string nb p s]: Inserts the value of string [s] at position * [p] into the netbuffer [nb] *) val insert_substring : t -> int -> string -> int -> int -> unit (** [insert_string nb p s k n]: Inserts a substring of string [s] at position * [p] into the netbuffer [nb]. The substring is denoted by position [k] * and has length [n] *) val insert_sub_string : t -> int -> string -> int -> int -> unit DEPRECATED("Use insert_substring instead.") val insert_subbytes : t -> int -> Bytes.t -> int -> int -> unit (** Same for bytes *) val insert_subtstring : t -> int -> tstring -> int -> int -> unit (** Same for tagged string *) val insert_submemory : t -> int -> memory -> int -> int -> unit (** Same for memory *) val insert_char : t -> int -> char -> unit (** [insert_char nb p c]: Inserts character [c] at position [p] into * the netbuffer [nb] *) (** {2 Overwriting strings} *) val set : t -> int -> char -> unit (** [set nb pos c]: Sets the character at [pos] to [c] *) val put_string : t -> int -> string -> unit (** [put_string nb pos s]: Copies the string [s] to the position [pos] of netbuffer [nb] *) val blit_from_string : string -> int -> t -> int -> int -> unit (** [blit_from_string src srcpos dest destpos len]: Copies the [len] bytes * at position [srcpos] from the string [src] to the netbuffer [dest] at * position [destpos]. * * It is possible to copy the string beyond the end of the buffer. The * buffer is automatically enlarged in this case. *) val blit_from_bytes : Bytes.t -> int -> t -> int -> int -> unit (** Same for bytes *) val blit_from_memory : memory -> int -> t -> int -> int -> unit (** Same for memory *) val blit_from_tstring : tstring -> int -> t -> int -> int -> unit (** Same for tagged string *) (** {2 Deleting} *) val delete : t -> int -> int -> unit (** [delete nb k n]: Deletes the [n] bytes at position [k] of netbuffer * [nb] in-place. * * The netbuffer does not shrink, however, i.e. the free space is not * given back to the memory manager. *) val clear : t -> unit (** Deletes all contents from the buffer. As [delete], the netbuffer does * not shrink. *) val reset : t -> unit (** Empty the buffer, deallocate the internal string, and replace it with a new string of length [n] that was allocated by {!Netbuffer.create} [n]. *) val try_shrinking : t -> unit (** [try_shrinking nb]: If the length of the buffer is less than half of * the allocated space, the netbuffer is reallocated in order to save * memory. *) (** {2 Searching} *) val index_from : t -> int -> char -> int (** [index_from nb k c]: Searches the character [c] in the netbuffer beginning * at position [k]. If found, the position of the left-most occurence is * returned. Otherwise, [Not_found] is raised. *) (** {2 Miscelleneous} *) val unsafe_buffer : t -> Bytes.t (** {b Warning! This is a low-level function!} * Returns the current string that internally holds the buffer. * The byte positions 0 to length - 1 actually store the contents of * the buffer. You can directly read and modify the buffer. Note that * there is no protection if you read or write positions beyond the * length of the buffer. *) val print_buffer : t -> unit (** For the toploop *) (* MISSING: searching substrings *) ocamlnet-4.1.2/src/netstring/netnumber.mli0000644000175000017500000002013612731530350017253 0ustar gerdgerd(* $Id$ *) (** Binary encodings of numbers *) (** This is the successor of the [Rtypes] module *) (** {2 Numeric types} *) (* 4- and 8-bytes representation of signed integers *) type int4 (** 32 bit signed integer *) type int8 (** 64 bit signed integer *) (* 4- and 8-bytes representation of non-negative integers *) type uint4 (** 32 bit unsigned integer *) type uint8 (** 64 bit unsigned integer *) (* Floating-point numbers of single and double precision according to IEEE *) type fp4 (** single precision float (IEEE "float") *) type fp8 (** double precision float (IEEE "double") *) exception Cannot_represent of string (** raised if a conversion can't be done *) exception Out_of_range (** raised if string position out of range *) (** {2 Basic encoding/decoding functions} *) val mk_int4 : char * char * char * char -> int4 val mk_int8 : char * char * char * char * char * char * char * char -> int8 val mk_uint4 : char * char * char * char -> uint4 val mk_uint8 : char * char * char * char * char * char * char * char -> uint8 (** [mk_] create integer values from character tuples. In these tuples * the MSB is the first component and the LSB the last. *) (* destroy integers and get tuples *) val dest_int4 : int4 -> char * char * char * char val dest_int8 : int8 -> char * char * char * char * char * char * char * char val dest_uint4 : uint4 -> char * char * char * char val dest_uint8 : uint8 -> char * char * char * char * char * char * char * char (** [dest_] destroy integer values and returns the corresponding char * tuples. *) val mk_fp4 : char * char * char * char -> fp4 val mk_fp8 : char * char * char * char * char * char * char * char -> fp8 val dest_fp4 : fp4 -> char * char * char * char val dest_fp8 : fp8 -> char * char * char * char * char * char * char * char (** {2 Conversions} *) (** Conversions from int to (u)int and vice versa. * On 32-bit computers, the type [int] can hold 31-bit signed integers * (including the sign, i.e. one bit cannot be used). * On 64-bit computers, the type [int] can hold 63-bit signed integers * (including the sign, i.e. one bit cannot be used). * The [int_of_xxx] functions raise [Cannot_represent] if the number to * convert is too big (or too small) to be represented as [int]. Note * that this depends on the word size of your architecture. *) val int_of_int4 : int4 -> int val int_of_uint4 : uint4 -> int val int_of_int8 : int8 -> int val int_of_uint8 : uint8 -> int val int4_of_int : int -> int4 val uint4_of_int : int -> uint4 val int8_of_int : int -> int8 val uint8_of_int : int -> uint8 val int32_of_int4 : int4 -> int32 val int32_of_uint4 : uint4 -> int32 val int32_of_int8 : int8 -> int32 val int32_of_uint8 : uint8 -> int32 val int4_of_int32 : int32 -> int4 val uint4_of_int32 : int32 -> uint4 val int8_of_int32 : int32 -> int8 val uint8_of_int32 : int32 -> uint8 val int64_of_int4 : int4 -> int64 val int64_of_uint4 : uint4 -> int64 val int64_of_int8 : int8 -> int64 val int64_of_uint8 : uint8 -> int64 val int4_of_int64 : int64 -> int4 val uint4_of_int64 : int64 -> uint4 val int8_of_int64 : int64 -> int8 val uint8_of_int64 : int64 -> uint8 (** Casts from [uint4]/[uint8] to [int32]/[int64]. Here, the sign is ignored and * simply considered as a bit. *) val logical_uint4_of_int32 : int32 -> uint4 val logical_int32_of_uint4 : uint4 -> int32 val logical_uint8_of_int64 : int64 -> uint8 val logical_int64_of_uint8 : uint8 -> int64 val fp8_of_fp4 : fp4 -> fp8 val fp4_of_fp8 : fp8 -> fp4 (** Note [fp4_of_fp8]: This conversion is not exact. It is quite * normal that precision is lost. Numbers too small or too large * for fp4 are converted to the "infinity" value. *) val float_of_fp4 : fp4 -> float val float_of_fp8 : fp8 -> float val fp4_of_float : float -> fp4 val fp8_of_float : float -> fp8 (** Note fp4_of_float: The same problems as in fp4_of_fp8 may arise *) (** {2 Comparisons} *) (** The comparisons "=" and "<>" work for all numbers. For signed integers, the operators "<", "<=", ">", and ">=" work, too. The unsigned integer type use representation that are not compatible with these operators, and the following functions need to be called. For [fp4] and [fp8] there are no comparison functions - convert to [float] first and compare then. *) val lt_uint4 : uint4 -> uint4 -> bool (** [lt_uint4] is true iff the first value is less than the second value as unsigned int *) val le_uint4 : uint4 -> uint4 -> bool val gt_uint4 : uint4 -> uint4 -> bool val ge_uint4 : uint4 -> uint4 -> bool (** Other comparisons *) val lt_uint8 : uint8 -> uint8 -> bool (** [lt_uint8] is true iff the first value is less than the second value as unsigned int *) val le_uint8 : uint8 -> uint8 -> bool val gt_uint8 : uint8 -> uint8 -> bool val ge_uint8 : uint8 -> uint8 -> bool (** Other comparisons *) (** {2 Minimum/maximum values} *) val min_int4 : int4 val min_uint4 : uint4 val min_int8 : int8 val min_uint8 : uint8 val max_int4 : int4 val max_uint4 : uint4 val max_int8 : int8 val max_uint8 : uint8 module type ENCDEC = sig (** Encode/decode numbers as strings. These functions exist in two flavors: - {!Netnumber.BE} implements network byte order (big endian) - {!Netnumber.LE} implements little endian *) val read_int4 : Bytes.t -> int -> int4 val read_int8 : Bytes.t -> int -> int8 val read_uint4 : Bytes.t -> int -> uint4 val read_uint8 : Bytes.t -> int -> uint8 (** [read_] create integer values from the characters found at a certain position in the string. Raises [Out_of_range] if the position is bad *) val read_int4_unsafe : Bytes.t -> int -> int4 val read_int8_unsafe : Bytes.t -> int -> int8 val read_uint4_unsafe : Bytes.t -> int -> uint4 val read_uint8_unsafe : Bytes.t -> int -> uint8 (** Same, but no index check *) val read_string_int4 : string -> int -> int4 val read_string_int8 : string -> int -> int8 val read_string_uint4 : string -> int -> uint4 val read_string_uint8 : string -> int -> uint8 val read_string_int4_unsafe : string -> int -> int4 val read_string_int8_unsafe : string -> int -> int8 val read_string_uint4_unsafe : string -> int -> uint4 val read_string_uint8_unsafe : string -> int -> uint8 (** For immutable strings *) val write_int4 : Bytes.t -> int -> int4 -> unit val write_int8 : Bytes.t -> int -> int8 -> unit val write_uint4 : Bytes.t -> int -> uint4 -> unit val write_uint8 : Bytes.t -> int -> uint8 -> unit (** [write_] copies the characters corresponding to the integer values into the string at the given positions. Raises [Out_of_range] if the position is bad. *) val write_int4_unsafe : Bytes.t -> int -> int4 -> unit val write_int8_unsafe : Bytes.t -> int -> int8 -> unit val write_uint4_unsafe : Bytes.t -> int -> uint4 -> unit val write_uint8_unsafe : Bytes.t -> int -> uint8 -> unit (** [write_][_unsafe]: Same, but no index check. *) val int4_as_bytes : int4 -> Bytes.t val int8_as_bytes : int8 -> Bytes.t val uint4_as_bytes : uint4 -> Bytes.t val uint8_as_bytes : uint8 -> Bytes.t (** [_as_bytes]: Returns the corresponding bytes for an integer value *) val int4_as_string : int4 -> string val int8_as_string : int8 -> string val uint4_as_string : uint4 -> string val uint8_as_string : uint8 -> string (** [_as_string]: Returns the corresponding string for an integer value *) val write_fp4 : Bytes.t -> int -> fp4 -> unit val write_fp8 : Bytes.t -> int -> fp8 -> unit val fp4_as_string : fp4 -> string val fp8_as_string : fp8 -> string val fp4_as_bytes : fp4 -> Bytes.t val fp8_as_bytes : fp8 -> Bytes.t val read_fp4 : Bytes.t -> int -> fp4 val read_fp8 : Bytes.t -> int -> fp8 val read_string_fp4 : string -> int -> fp4 val read_string_fp8 : string -> int -> fp8 end module BE : ENCDEC (** Encoders/decoders for big endian - network byte order *) module LE : ENCDEC (** Encoders/decoders for little endian *) module HO : ENCDEC (** Encoders/decoders for host byte order - which is either little endian or big endian, depending on the CPU (or CPU mode) *) ocamlnet-4.1.2/src/netstring/netsockaddr.mli0000644000175000017500000000361112731530350017554 0ustar gerdgerd(* $Id$ *) (** Parsing of socket addresses *) type socksymbol = [ `Inet of Unix.inet_addr * int | `Inet_byname of string * int | `Unix of string ] (** Symbolic socket names: - [`Inet(ip,port)]: An internet socket with IP [ip] and the given [port] - [`Inet_byname(n,port)]: An internet socket with the IP resulting from the resolution of the name [n], and with the given [port] - [`Unix p]: A Unix Domain socket with the path [p] Use {!Uq_resolver.sockaddr_of_socksymbol} to convert to a [Unix.sockaddr] (and resolve names). *) val socksymbol_of_string : string -> socksymbol (** Parses designations of the forms: - [:port] - [[:port] - [/path] - [./path] Raises [Failure] on parse error. *) val string_of_socksymbol : socksymbol -> string (** The reverse function *) val norm_socksymbol : socksymbol -> socksymbol (** Normalizes numeric IP addresses: if the address is an IPv4 address mapped to the IPv6 address space, the real IPv4 address is returned. This also works for numeric addresses in string form, whose writing is also normalized. E.g. - [norm_socksymbol (`Inet_by_name("::ffff:127.0.0.1", 80))] returns [`Inet_by_name("127.0.0.1",80)] - [norm_socksymbol (`Inet_by_name("0::1",80))] returns [`Inet_by_name("::1", 80)] *) val ipv6_socksymbol : socksymbol -> socksymbol (** IPv6-ification of numeric IP addresses: IPv4 addresses are mapped to the IPv6 address space. This also works for numeric addresses in string form, whose writing is also normalized. E.g. - [norm_socksymbol (`Inet_by_name("127.0.0.1", 80))] returns [`Inet_by_name("::ffff:127.0.0.1",80)] - [norm_socksymbol (`Inet_by_name("0::1",80))] returns [`Inet_by_name("::1", 80)] *) ocamlnet-4.1.2/src/netstring/nettls_support.ml0000644000175000017500000001400012731530350020201 0ustar gerdgerd(* $Id$ *) open Printf type credentials = [ `X509 of Netx509.x509_certificate | `Anonymous ] type raw_credentials = [ `X509 of string | `Anonymous ] type cred_type = [ `X509 | `Anonymous ] class type tls_session_props = object method id : string method addressed_server : string option method cipher_suite_type : string method endpoint_credentials : credentials method endpoint_credentials_type : cred_type method endpoint_credentials_raw : raw_credentials method peer_credentials : credentials method peer_credentials_type : cred_type method peer_credentials_raw : raw_credentials method cipher_algo : string method kx_algo : string method mac_algo : string method compression_algo : string method protocol : string end let cred_type = function | `X509 _ -> `X509 | `Anonymous -> `Anonymous let parse_creds = function | `X509 der -> `X509 (new Netx509.x509_certificate_from_DER der) | `Anonymous -> `Anonymous let get_tls_session_props (ep:Netsys_crypto_types.tls_endpoint) : tls_session_props = let module Endpoint = (val ep : Netsys_crypto_types.TLS_ENDPOINT) in let module TLS = Endpoint.TLS in let e1 = Endpoint.endpoint in let id = TLS.get_session_id e1 in let sni_l = try TLS.get_addressed_servers e1 with | TLS.Exc.TLS_error "" | TLS.Exc.TLS_error "GNUTLS_E_INVALID_REQUEST" -> [] in let sni = match sni_l with | `Domain n :: _ -> Some n | [] -> None in let cs_type = TLS.get_cipher_suite_type e1 in let ep_creds = TLS.get_endpoint_creds e1 in let ep_creds_lz = lazy(parse_creds ep_creds) in let p_creds = TLS.get_peer_creds e1 in let p_creds_lz = lazy(parse_creds p_creds) in let cipher_algo = TLS.get_cipher_algo e1 in let kx_algo = TLS.get_kx_algo e1 in let mac_algo = TLS.get_mac_algo e1 in let compression_algo = TLS.get_compression_algo e1 in let protocol = TLS.get_protocol e1 in ( object(self) method id = id method addressed_server = sni method cipher_suite_type = cs_type method endpoint_credentials_raw = ep_creds method endpoint_credentials_type = cred_type ep_creds method endpoint_credentials = Lazy.force ep_creds_lz method peer_credentials_raw = p_creds method peer_credentials_type = cred_type p_creds method peer_credentials = Lazy.force p_creds_lz method cipher_algo = cipher_algo method kx_algo = kx_algo method mac_algo = mac_algo method compression_algo = compression_algo method protocol = protocol end ) let squash_file_tls_endpoint file_ep = let module FEP = (val file_ep : Netsys_crypto_types.FILE_TLS_ENDPOINT) in let module EP = struct module TLS = FEP.TLS let endpoint = FEP.endpoint end in (module EP : Netsys_crypto_types.TLS_ENDPOINT) let get_tls_user_name props = let rec search_dn_loop dn at_list = match at_list with | [] -> raise Not_found | at :: at_list' -> try Netx509.lookup_dn_ava_utf8 dn at with | Not_found -> search_dn_loop dn at_list' in let search_dn dn = search_dn_loop dn [ Netx509.DN_attributes.at_uid; Netx509.DN_attributes.at_emailAddress; Netx509.DN_attributes.at_commonName; ] in match props # peer_credentials with | `X509 cert -> ( try let (san_der, _) = Netx509.find_extension Netx509.CE.ce_subject_alt_name cert#extensions in let san = Netx509.parse_subject_alt_name san_der in try let san_email = List.find (function | `Rfc822_name n -> true | _ -> false ) san in match san_email with | `Rfc822_name n -> n | _ -> assert false with | Not_found -> let san_dn = List.find (function | `Directory_name n -> true | _ -> false ) san in match san_dn with | `Directory_name dn -> search_dn dn | _ -> assert false with | Not_found | Netx509.Extension_not_found _ -> search_dn cert#subject ) | _ -> raise Not_found let dot_re = Netstring_str.regexp "[.]" let match_hostname n1 n2 = (* n1 may contain "*" as domain component patterns *) let l1 = Netstring_str.split dot_re n1 in let l2 = Netstring_str.split dot_re n2 in List.length l1 = List.length l2 && List.for_all2 (fun dc1 dc2 -> dc1 = "*" || String.uppercase dc1 = String.uppercase dc2 ) l1 l2 let is_dns_name = function `DNS_name _ -> true | _ -> false let is_this_dns_name n1 = function `DNS_name n2 -> match_hostname n2 n1 | _ -> false let is_endpoint_host name (props : tls_session_props) = match props # endpoint_credentials with | `X509 cert -> ( try let data, _ = Netx509.find_extension Netx509.CE.ce_subject_alt_name cert#extensions in let san = Netx509.parse_subject_alt_name data in (* if there is any DNS alternate name, one of these names must match *) if not(List.exists is_dns_name san) then raise Not_found; List.exists (is_this_dns_name name) san with | Netx509.Extension_not_found _ | Not_found -> let subj = cert#subject in let cn = Netx509.lookup_dn_ava_utf8 subj Netx509.DN_attributes.at_commonName in match_hostname cn name ) | `Anonymous -> true (* anonymous can be anybody *) ocamlnet-4.1.2/src/netstring/netascii_armor.mli0000644000175000017500000000325112731530350020252 0ustar gerdgerd(* $Id$ *) (** Messages with ASCII armor *) (** There are various forms of ASCII-armored messages: - PEM messages (privacy enhanced mail) - a historic message format - OpenPGP messages. This type of message has a header, a BASE-64-encoded body, and a checksum. - X.509 keys. These just use BASE-64. *) type armor_type = [ `Plain | `Base64 | `OpenPGP ] type armored_message = [ `Plain of Netmime.mime_body | `Base64 of Netmime.mime_body | `OpenPGP of Netmime.mime_header * Netmime.mime_body * int ] (** Messages: - [`Plain m]: The body [m] is written as-is - [`Base64 m]: The body [m] needs to be BASE-64-encoded in order to create the ASCII armor - [`OpenPGP(h,m,chksum)]: There is a header [h], a body [m] which will be BASE-64-encoded, and a checksum [chksum] *) type armored_message_ro = [ `Plain of Netmime.mime_body_ro | `Base64 of Netmime.mime_body_ro | `OpenPGP of Netmime.mime_header_ro * Netmime.mime_body_ro * int ] (** The read-only version of [armored_message] *) type armor_spec = (string * armor_type) list (** Which types of armor to decode, and how. The strings are the identifiers in the boundaries, e.g. include "PRIVACY-ENHANCED MESSAGE" if the boundaries are "-----BEGIN PRIVACY-ENHANCED MESSAGE-----" and "-----END PRIVACY-ENHANCED MESSAGE-----". For every type you can define the [armor_type]. *) val parse : armor_spec -> Netchannels.in_obj_channel -> (string * armored_message_ro) list (** Parses the channel, and returns all messages that are enabled in the specification. The channel is read line-by-line. *) ocamlnet-4.1.2/src/netstring/netaccel_link.mli0000644000175000017500000000015212731530350020043 0ustar gerdgerd(* $Id$ *) (** Enables accelerator module [Netaccel] * * This module exists for technical reasons. *) ocamlnet-4.1.2/src/netstring/netgssapi_support.ml0000644000175000017500000003571012731530350020700 0ustar gerdgerd(* $Id$ *) open Printf (* Encodings *) let encode_subidentifier buf n = (* See 8.19 of ITU.T X.690 *) let rec encode n = if n < 128 then [ n ] else (n land 127) :: encode (n lsr 7) in if n < 0 then failwith "Netgssapi_support.encode_subidentifier"; let l = List.rev(encode n) in let len = List.length l in let l = List.mapi (fun i k -> if i < len-1 then Char.chr(k lor 128) else Char.chr k ) l in List.iter (Buffer.add_char buf) l let decode_subidentifier s cursor = let n = ref 0 in let s_len = String.length s in while !cursor < s_len && s.[ !cursor ] >= '\x80' do let c = Char.code (s.[ !cursor ]) - 128 in n := (!n lsl 7) lor c; incr cursor done; if !cursor < s_len then ( let c = Char.code (s.[ !cursor ]) in n := (!n lsl 7) lor c; incr cursor; !n ) else failwith "Netgssapi_support.decode_subidentifier" let encode_definite_length buf n = (* See 8.1.3 of ITU-T X.690 *) let rec encode n = if n < 256 then [ n ] else (n land 255) :: encode (n lsr 8) in if n < 128 then ( Buffer.add_char buf (Char.chr n) ) else ( let l = List.map Char.chr (List.rev(encode n)) in Buffer.add_char buf (Char.chr (List.length l + 128)); List.iter (Buffer.add_char buf) l ) let decode_definite_length s cursor = let s_len = String.length s in if !cursor < s_len then ( let c = s.[ !cursor ] in incr cursor; if c < '\x80' then ( Char.code c ) else ( let p = Char.code c - 128 in let n = ref 0 in for q = 1 to p do if !cursor < s_len then ( let c = s.[ !cursor ] in incr cursor; n := (!n lsl 8) lor Char.code c; ) else failwith "Netgssapi_support.decode_definite_length" done; !n ) ) else failwith "Netgssapi_support.decode_definite_length" let oid_to_der_value oid = match Array.to_list oid with | [] -> failwith "Netgssapi_support.oid_to_der: empty OID" | [ _ ] -> failwith "Netgssapi_support.oid_to_der: invalid OID" | top :: second :: subids -> if top < 0 || top > 5 then (* actually only 0..2 possible *) failwith "Netgssapi_support.oid_to_der: invalid OID"; if second < 0 || second > 39 then failwith "Netgssapi_support.oid_to_der: invalid OID"; let subids_buf = Buffer.create 50 in List.iter (encode_subidentifier subids_buf) subids; let buf = Buffer.create 50 in Buffer.add_char buf (Char.chr (top * 40 + second)); Buffer.add_buffer buf subids_buf; Buffer.contents buf let oid_to_der oid = let buf = Buffer.create 50 in let s = oid_to_der_value oid in Buffer.add_char buf '\x06'; encode_definite_length buf (String.length s); Buffer.add_string buf s; Buffer.contents buf let der_value_to_oid der cursor oid_len = try let lim = !cursor + oid_len in let c = Char.code der.[ !cursor ] in incr cursor; let top = c / 40 in let second = c mod 40 in let oid = ref [ second; top ] in while !cursor < lim do let subid = decode_subidentifier der cursor in oid := subid :: !oid; done; if !cursor <> lim then raise Not_found; Array.of_list (List.rev !oid) with | _ -> failwith "Netgssapi_support.der_value_to_oid" let der_to_oid der cursor = try let der_len = String.length der in if !cursor >= der_len then raise Not_found; let c = der.[ !cursor ] in incr cursor; if c <> '\x06' then raise Not_found; let oid_len = decode_definite_length der cursor in let lim = !cursor + oid_len in if lim > der_len then raise Not_found; if oid_len = 0 then raise Not_found; der_value_to_oid der cursor oid_len with | _ -> failwith "Netgssapi_support.der_to_oid" let wire_encode_token oid token = try let buf = Buffer.create (50 + String.length token) in Buffer.add_char buf '\x60'; let oid_as_der = oid_to_der oid in let len = String.length oid_as_der + String.length token in encode_definite_length buf len; Buffer.add_string buf oid_as_der; Buffer.add_string buf token; Buffer.contents buf with | _ -> failwith "Netgssapi_support.wire_encode_token" let wire_decode_token s cursor = try let s_len = String.length s in if !cursor > s_len then raise Not_found; let c = s.[ !cursor ] in incr cursor; if c <> '\x60' then raise Not_found; let len = decode_definite_length s cursor in let lim = !cursor + len in if lim > s_len then raise Not_found; let oid = der_to_oid s cursor in if !cursor > lim then raise Not_found; let token = String.sub s !cursor (lim - !cursor) in cursor := lim; (oid, token) with | _ -> failwith "Netgsspi.wire_decode_token" let encode_exported_name mech_oid name = let buf = Buffer.create (50 + String.length name) in Buffer.add_string buf "\x04\x01"; let mech_oid_der = oid_to_der mech_oid in let mech_oid_len = String.length mech_oid_der in if mech_oid_len > 65535 then failwith "Netgssapi_support.encode_exported_name: OID too long"; Buffer.add_char buf (Char.chr (mech_oid_len / 256)); Buffer.add_char buf (Char.chr (mech_oid_len mod 256)); Buffer.add_string buf mech_oid_der; let name_len = String.length name in let n3 = (name_len lsr 24) land 0xff in let n2 = (name_len lsr 16) land 0xff in let n1 = (name_len lsr 8) land 0xff in let n0 = name_len land 0xff in Buffer.add_char buf (Char.chr n3); Buffer.add_char buf (Char.chr n2); Buffer.add_char buf (Char.chr n1); Buffer.add_char buf (Char.chr n0); Buffer.add_string buf name; Buffer.contents buf let decode_exported_name s cursor = try let s_len = String.length s in if !cursor + 4 > s_len then raise Not_found; let c0 = s.[ !cursor ] in incr cursor; let c1 = s.[ !cursor ] in incr cursor; let c2 = s.[ !cursor ] in incr cursor; let c3 = s.[ !cursor ] in incr cursor; if c0 <> '\x04' || c1 <> '\x01' then raise Not_found; let mech_oid_len = (Char.code c2 lsl 8) + Char.code c3 in let mech_start = !cursor in if mech_start + mech_oid_len > s_len then raise Not_found; let mech_oid = der_to_oid s cursor in if !cursor <> mech_start + mech_oid_len then raise Not_found; if !cursor + 4 > s_len then raise Not_found; let n0 = Char.code s.[ !cursor ] in incr cursor; let n1 = Char.code s.[ !cursor ] in incr cursor; let n2 = Char.code s.[ !cursor ] in incr cursor; let n3 = Char.code s.[ !cursor ] in incr cursor; let name_len = (n0 lsl 24) lor (n1 lsl 16) lor (n2 lsl 8) lor (n3) in if !cursor + name_len > s_len then raise Not_found; let name = String.sub s !cursor name_len in cursor := !cursor + name_len; (mech_oid, name) with | _ -> failwith "Netgssapi_support.decode_exported_name" let comma_equals_re = Netstring_str.regexp "[,=]" let rev_comma_equals_re = Netstring_str.regexp "\\(=2C\\|=3D\\|=\\|,\\)" let gs2_encode_saslname s = ( try Netconversion.verify `Enc_utf8 s; if String.contains s '\000' then raise Not_found; with _ -> failwith "gs2_encode_saslname" ); Netstring_str.global_substitute comma_equals_re (fun r s -> match Netstring_str.matched_string r s with | "," -> "=2C" | "=" -> "=3D" | _ -> assert false ) s let gs2_decode_saslname s = let s' = Netstring_str.global_substitute rev_comma_equals_re (fun r s -> match Netstring_str.matched_string r s with | "=2C" -> "," | "=3D" -> "=" | "=" | "," -> failwith "gs2_decode_saslname" | _ -> assert false ) s in ( try Netconversion.verify `Enc_utf8 s'; if String.contains s' '\000' then raise Not_found; with _ -> failwith "gs2_decode_saslname" ); s' let encode_seq_nr x = let n7 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 56) 0xffL) in let n6 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 48) 0xffL) in let n5 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 40) 0xffL) in let n4 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 32) 0xffL) in let n3 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 24) 0xffL) in let n2 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 16) 0xffL) in let n1 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 8) 0xffL) in let n0 = Int64.to_int (Int64.logand x 0xffL) in let s = Bytes.create 8 in Bytes.set s 0 (Char.chr n7); Bytes.set s 1 (Char.chr n6); Bytes.set s 2 (Char.chr n5); Bytes.set s 3 (Char.chr n4); Bytes.set s 4 (Char.chr n3); Bytes.set s 5 (Char.chr n2); Bytes.set s 6 (Char.chr n1); Bytes.set s 7 (Char.chr n0); Bytes.unsafe_to_string s let decode_seq_nr s = assert(String.length s = 8); let n7 = Int64.of_int (Char.code s.[0]) in let n6 = Int64.of_int (Char.code s.[1]) in let n5 = Int64.of_int (Char.code s.[2]) in let n4 = Int64.of_int (Char.code s.[3]) in let n3 = Int64.of_int (Char.code s.[4]) in let n2 = Int64.of_int (Char.code s.[5]) in let n1 = Int64.of_int (Char.code s.[6]) in let n0 = Int64.of_int (Char.code s.[7]) in Int64.logor (Int64.shift_left n7 56) (Int64.logor (Int64.shift_left n6 48) (Int64.logor (Int64.shift_left n5 40) (Int64.logor (Int64.shift_left n4 32) (Int64.logor (Int64.shift_left n3 24) (Int64.logor (Int64.shift_left n2 16) (Int64.logor (Int64.shift_left n1 8) n0)))))) let parse_kerberos_name s = (* http://web.mit.edu/kerberos/krb5-latest/doc/appdev/refs/api/krb5_parse_name.html *) let l = String.length s in let rec parse_nc prev_nc buf k = if k >= l then (prev_nc @ [Buffer.contents buf], None) else match s.[k] with | '/' -> parse_nc (prev_nc @ [Buffer.contents buf]) (Buffer.create 20) (k+1) | '@' -> let realm = String.sub s (k+1) (l-k-1) in (prev_nc @ [Buffer.contents buf], Some realm) | '\\' -> if k+1 >= l then failwith "parse_kerberos_name"; ( match s.[k+1] with | '\\' -> Buffer.add_char buf '\\' | '/' -> Buffer.add_char buf '/' | '@' -> Buffer.add_char buf '@' | 'n' -> Buffer.add_char buf '\n' | 't' -> Buffer.add_char buf '\t' | 'b' -> Buffer.add_char buf '\b' | '0' -> Buffer.add_char buf '\000' | _ -> failwith "parse_kerberos_name" ); parse_nc prev_nc buf (k+2) | c -> Buffer.add_char buf c; parse_nc prev_nc buf (k+1) in parse_nc [] (Buffer.create 20) 0 let create_mic_token ~sent_by_acceptor ~acceptor_subkey ~sequence_number ~get_mic ~message = let header = sprintf "\x04\x04%c\xff\xff\xff\xff\xff%s" (Char.chr ( (if sent_by_acceptor then 1 else 0) lor (if acceptor_subkey then 4 else 0) ) ) (encode_seq_nr sequence_number) in let mic = get_mic (message @ [Netxdr_mstring.string_to_mstring header] ) in header ^ mic let parse_mic_token_header s = try if String.length s < 16 then raise Not_found; if s.[0] <> '\x04' || s.[1] <> '\x04' then raise Not_found; if String.sub s 3 5 <> "\xff\xff\xff\xff\xff" then raise Not_found; let flags = Char.code s.[2] in if flags land 7 <> flags then raise Not_found; let sent_by_acceptor = (flags land 1) <> 0 in let acceptor_subkey = (flags land 4) <> 0 in let sequence_number = decode_seq_nr (String.sub s 8 8) in (sent_by_acceptor, acceptor_subkey, sequence_number) with Not_found -> failwith "Netgssapi_support.parse_mic_token_header" let verify_mic_token ~get_mic ~message ~token = try ignore(parse_mic_token_header token); let header = String.sub token 0 16 in let mic = get_mic (message @ [Netxdr_mstring.string_to_mstring header]) in mic = (String.sub token 16 (String.length token - 16)) with | _ -> false let create_wrap_token_conf ~sent_by_acceptor ~acceptor_subkey ~sequence_number ~get_ec ~encrypt_and_sign ~message = let ec = get_ec (Netxdr_mstring.length_mstrings message + 16) in let header = sprintf "\x05\x04%c\xff%c%c\000\000%s" (Char.chr ( (if sent_by_acceptor then 1 else 0) lor (if acceptor_subkey then 4 else 0) lor 2 ) ) (Char.chr ((ec lsr 8) land 0xff)) (Char.chr (ec land 0xff)) (encode_seq_nr sequence_number) in let filler = String.make ec '\000' in let encrypted = encrypt_and_sign (message @ [ Netxdr_mstring.string_to_mstring (filler ^ header) ] ) in Netxdr_mstring.string_to_mstring header :: encrypted let parse_wrap_token_header m = try let l = Netxdr_mstring.length_mstrings m in if l < 16 then raise Not_found; let s = Netxdr_mstring.prefix_mstrings m 16 in if s.[0] <> '\x05' || s.[1] <> '\x04' then raise Not_found; if s.[3] <> '\xff' then raise Not_found; let flags = Char.code s.[2] in if flags land 7 <> flags then raise Not_found; let sent_by_acceptor = (flags land 1) <> 0 in let sealed = (flags land 2) <> 0 in let acceptor_subkey = (flags land 4) <> 0 in let sequence_number = decode_seq_nr (String.sub s 8 8) in (sent_by_acceptor, sealed, acceptor_subkey, sequence_number) with Not_found -> failwith "Netgssapi_support.parse_wrap_token_header" let unwrap_wrap_token_conf ~decrypt_and_verify ~token = let (_, sealed, _, _) = parse_wrap_token_header token in if not sealed then failwith "Netgssapi_support.unwrap_wrap_token_conf: not sealed"; let s = Netxdr_mstring.prefix_mstrings token 16 in let ec = ((Char.code s.[4]) lsl 8) lor (Char.code s.[5]) in let rrc = ((Char.code s.[6]) lsl 8) lor (Char.code s.[7]) in let l_decrypt = Netxdr_mstring.length_mstrings token - 16 in let rrc_eff = rrc mod l_decrypt in let u = if rrc = 0 then Netxdr_mstring.shared_sub_mstrings token 16 l_decrypt else ( Netxdr_mstring.shared_sub_mstrings token (rrc_eff+16) (l_decrypt - rrc_eff) @ Netxdr_mstring.shared_sub_mstrings token 16 rrc_eff ) in (* let u = String.create l_decrypt in String.blit token (rrc_eff+16) u 0 (l_decrypt - rrc_eff); String.blit token 16 u (l_decrypt - rrc_eff) rrc_eff; *) let decrypted = try decrypt_and_verify u with _ -> failwith "Netgssapi_support.unwrap_wrap_token_conf: cannot decrypt" in let l_decrypted = Netxdr_mstring.length_mstrings decrypted in if l_decrypted < ec + 16 then failwith "Netgssapi_support.unwrap_wrap_token_conf: bad EC"; let h1 = Netxdr_mstring.prefix_mstrings token 16 in let h2 = Netxdr_mstring.concat_mstrings (Netxdr_mstring.shared_sub_mstrings decrypted (l_decrypted - 16) 16) in if h1 <> h2 then failwith "Netgssapi_support.unwrap_wrap_token_conf: header integrity mismatch"; Netxdr_mstring.shared_sub_mstrings decrypted 0 (l_decrypted - ec - 16) ocamlnet-4.1.2/src/netstring/netmime_string.mli0000644000175000017500000015311012731530350020277 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Low-level functions to parse and print mail and MIME messages * * [Netmime_string] contains a lot of functions to scan and print strings * formatted as MIME messages. For a higher-level view on this topic, * see the [Netmime] module. * * {b Contents} * - {!Netmime_string.lines} * - {!Netmime_string.headers} * - {!Netmime_string.structured_values} * - {!Netmime_string.parsers_for_structured_values} * - {!Netmime_string.printers_for_structured_values} * - {!Netmime_string.scanning_mime} * - {!Netmime_string.helpers_mime} * *) open Netsys_types (** {1:lines Splitting a string into lines} *) (** These functions are all CR/LF-aware, i.e. lines can be terminated by either LF or CR/LF. *) val find_line_end : string -> int -> int -> int (** [find_line_end s pos len]: Searches the next line end (CR/LF or only LF), and returns the position. The search starts at position [pos], and covers the next [len] bytes. Raises [Not_found] if there is no line end. *) val find_line_end_poly : 's Netstring_tstring.tstring_ops -> 's -> int -> int -> int (** polymorphic version *) val find_line_start : string -> int -> int -> int (** [find_line_start s pos len]: Searches the next start, and returns its position. The line start is the position after the next line end (CR/LF or only LF). The search starts at position [pos], and covers the next [len] bytes. Raises [Not_found] if there is no line end. *) val find_line_start_poly : 's Netstring_tstring.tstring_ops -> 's -> int -> int -> int (** polymorphic version *) val find_double_line_start : string -> int -> int -> int (** [find_double_line_start s pos len]: Searches two adjacent line ends (each may be a CR/LF combination or a single LF), and returns the position after the second line end. The search starts at position [pos], and covers the next [len] bytes. Raises [Not_found] if the mentioned pattern is not found. *) val find_double_line_start_poly : 's Netstring_tstring.tstring_ops -> 's -> int -> int -> int (** polymorphic version *) val skip_line_ends : string -> int -> int -> int (** [skip_line_ends s pos len]: Skips over adjacent line ends (terminated by CR/LF or plain LF), and returns the position after the last line end. The search starts at position [pos], and covers the next [len] bytes. Note that this function cannot raise [Not_found]. *) val skip_line_ends_poly : 's Netstring_tstring.tstring_ops -> 's -> int -> int -> int (** polymorphic version *) val fold_lines_p : ('a -> int -> int -> int -> bool -> 'a) -> 'a -> string -> int -> int -> 'a (** [fold_lines_p f acc0 s pos len]: Splits the substring of [s] from [pos] to [pos+len] into lines, and folds over these lines like [List.fold_left]. The function [f] is called as [f acc p0 p1 p2 is_last] where [acc] is the current accumulator (initialized with [acc0]), and - [p0] is the start position of the line in [s] - [p1] is the position of the line terminator in [s] - [p2] is the position after the line terminator in [s] - [is_last] is true if this is the last line in the iteration The lines can be terminated with CR/LF or LF. For the last line the terminator is optional ([p1=p2] is possible). The function is tail-recursive. *) val fold_lines_p_poly : 's Netstring_tstring.tstring_ops -> ('a -> int -> int -> int -> bool -> 'a) -> 'a -> 's -> int -> int -> 'a (** even more polymorphic *) val fold_lines : ('a -> string -> 'a) -> 'a -> string -> int -> int -> 'a (** [fold_lines f acc0 s pos len]: Splits the substring of [s] from [pos] to [pos+len] into lines, and folds over these lines like [List.fold_left]. The function [f] is called as [f acc line] where [acc] is the current accumulator (initialized with [acc0]), and [line] is the current line w/o terminator. The lines can be terminated with CR/LF or LF. The function is tail-recursive. Example: Get the lines as list: {[ List.rev(fold_lines (fun l acc -> acc::l) [] s pos len) ]} *) val fold_lines_poly : 's Netstring_tstring.tstring_ops -> ('a -> 's -> 'a) -> 'a -> 's -> int -> int -> 'a (** even more polymorphic *) val iter_lines : (string -> unit) -> string -> int -> int -> unit (** [iter_lines f s pos len]: Splits the substring of [s] from [pos] to [pos+len] into lines, and calls [f line] for each line. The lines can be terminated with CR/LF or LF. *) val iter_lines_poly : 's Netstring_tstring.tstring_ops -> ('s -> unit) -> 's -> int -> int -> unit (** even more polymorphic *) val skip_whitespace_left : string -> int -> int -> int (** [skip_whitespace_left s pos len]: Returns the smallest [p] with [p >= pos && p < pos+len] so that [s.[p]] is not a whitesapce character (space, TAB, CR, LF), and [s.[q]] is a whitespace character for all [q int -> int -> int (** [skip_whitespace_right s pos len]: Returns the biggest [p] with [p >= pos && p < pos+len] so that [s.[p]] is not a whitesapce character (space, TAB, CR, LF), and [s.[q]] is a whitespace character for all [q>p]. If this is not possible [Not_found] will be raised. *) (* *********************************************************************) (* Collection of auxiliary functions to parse MIME headers *) (* *********************************************************************) (* See also the module Netmime for high-level MIME functions *) (** {1:headers Parsing and Printing Mail Headers} *) (** {b The Format of Mail Messages} Messages consist of a header and a body; the first empty line separates both parts. The header contains lines "{i param-name}[:] {i param-value}" where the param-name must begin on column 0 of the line, and the "[:]" separates the name and the value. So the format is roughly: {[ param1-name: param1-value ... paramN-name: paramN-value _ body ]} (Where "_" denotes an empty line.) {b Details} Note that parameter values are restricted; you cannot represent arbitrary strings. The following problems can arise: - Values cannot begin with whitespace characters, because there may be an arbitrary number of whitespaces between the "[:]" and the value. - Values (and names of parameters, too) must only be formed of 7 bit ASCII characters. (If this is not enough, the MIME standard knows the extension RFC 2047 that allows that header values may be composed of arbitrary characters of arbitrary character sets. See below how to decode such characters in values returned by this function.) - Header values may be broken into several lines. Continuation lines must begin with whitespace characters. This means that values must not contain line breaks as semantic part of the value. And it may mean that {i one} whitespace character is not distinguishable from {i several} whitespace characters. - Header lines must not be longer than 78 characters (soft limit) or 998 characters (hard limit). Values that would result into longer lines must be broken into several lines. This means that you cannot represent strings that contain too few whitespace characters. (Note: The soft limit is to avoid that user agents have problems with long lines. The hard limit means that transfer agents sometimes do not transfer longer lines correctly.) - Some old gateways pad the lines with spaces at the end of the lines. This implementation of a mail scanner tolerates a number of deviations from the standard: long lines are not rejected; 8 bit values are generally accepted; lines may be ended only with LF instead of CRLF. {b Compatibility} These functions can parse all mail headers that conform to RFC 822 or RFC 2822. But there may be still problems, as RFC 822 allows some crazy representations that are actually not used in practice. In particular, RFC 822 allows it to use backslashes to "indicate" that a CRLF sequence is semantically meant as line break. As this function normally deletes CRLFs, it is not possible to recognize such indicators in the result of the function. *) val fold_header : ?downcase:bool -> (* default: false *) ?unfold:bool -> (* default: false *) ?strip:bool -> (* default: false *) ('a -> string -> string -> 'a) -> 'a -> string -> int -> int -> 'a (** [fold_header f acc0 s pos len]: Parses a MIME header in the string [s] from [pos] to exactly [pos+len]. The MIME header must be terminated by an empty line. A folding operation is done over the header values while the lines are extracted from the string, very much like [List.fold_left]. For each header [(n,v)] where [n] is the name and [v] is the value, the function [f] is called as [f acc n v]. If the header cannot be parsed, a [Failure] is raised. Certain transformations may be applied (default: no transformations): - If [downcase] is set, the header names are converted to lowercase characters - If [unfold] is set, the line terminators are not included in the resulting values. This covers both the end of line characters at the very end of a header and the end of line characters introduced by continuation lines. - If [strip] is set, preceding and trailing white space is removed from the value (including line terminators at the very end of the value) *) val list_header : ?downcase:bool -> (* default: false *) ?unfold:bool -> (* default: false *) ?strip:bool -> (* default: false *) string -> int -> int -> (string * string) list (** [list_header s pos len]: Returns the headers as list of pairs [(name,value)]. For the meaning of the arguments see [fold_header] above. *) val scan_header : ?downcase:bool -> (* default: true *) ?unfold:bool -> (* default: true *) ?strip:bool -> (* default: false *) string -> start_pos:int -> end_pos:int -> ((string * string) list * int) (** [let params, header_end_pos = scan_header s start_pos end_pos]: {b Deprecated.} Scans the mail header that begins at position [start_pos] in the string [s] and that must end somewhere before position [end_pos]. It is intended that in [end_pos] the character position following the end of the body of the MIME message is passed. Returns the parameters of the header as [(name,value)] pairs (in [params]), and in [header_end_pos] the position of the character following directly after the header (i.e. after the blank line separating the header from the body). - If [downcase], header names are converted to lowercase characters - The arguments [unfold] and [strip] have a slightly different meaning as for the new function [fold_header] above. In particular, whitespace is already stripped off the returned values if {b any} of [unfold] or [strip] are enabled. (This is for backward compatibility.) Also, this function is different because [downcase] and [unfold] are enabled by default, and only [strip] is not enabled. *) val scan_header_tstring : ?downcase:bool -> (* default: true *) ?unfold:bool -> (* default: true *) ?strip:bool -> (* default: false *) tstring -> start_pos:int -> end_pos:int -> ((string * string) list * int) (** The same for tagged strings *) val scan_header_poly : ?downcase:bool -> (* default: true *) ?unfold:bool -> (* default: true *) ?strip:bool -> (* default: false *) 's Netstring_tstring.tstring_ops -> 's -> start_pos:int -> end_pos:int -> ((string * string) list * int) (** Polymorphic version *) val read_header : ?downcase:bool -> ?unfold:bool -> ?strip:bool -> Netstream.in_obj_stream -> (string * string) list (** This function expects that the current position of the passed * [in_obj_stream] is the first byte of the header. The function scans the * header and returns it. After that, the stream position is after * the header and the terminating empty line (i.e. at the beginning of * the message body). * * The options [downcase], [unfold], and [strip] have the same meaning * as in [scan_header]. * * {b Example} * * To read the mail message "[file.txt]": * * {[ * let ch = new Netchannels.input_channel (open_in "file.txt") in * let stream = new Netstream.input_stream ch in * let header = read_header stream in * stream#close_in() (* no need to close ch *) * ]} *) val write_header : ?soft_eol:string -> (* default: "\r\n" *) ?eol:string -> (* default: "\r\n" *) Netchannels.out_obj_channel -> (string * string) list -> unit (** This function writes the header to the passed [out_obj_channel]. The * empty line following the header is also written. * * Exact output format: * {ul * {- The header is not folded, i.e. no additional CRLF sequences * are inserted into the header to avoid long header lines. * In order to produce correct headers, the necessary CRLF bytes * must already exist in the field values. (You can use the * function [write_value] below for this.)} * {- However, this function helps getting some details right. First, * whitespace at the beginning of field values is suppressed. * * {b Example:} * * [write_header ch ["x","Field value"; "y"," Other value"]] outputs: * {[ x: Field value\r\n * y: Other value\r\n * \r\n]}} * {- The end-of-line sequences LF, and CRLF, followed by * whitespace are replaced by the passed [soft_eol] string. If the * necessary space or tab character following the eol is missing, an * additional space character will be inserted. * * {b Example:} * * [write_header ch ["x","Field\nvalue"; "y","Other\r\n\tvalue"]] outputs: * {[ x: Field\r\n * value * y: Other\r\n * \tvalue]}} * {- Empty lines (and lines only consisting of whitespace) are suppressed * if they occur inside the header. * * {b Example:} * * [write_header ch ["x","Field\n\nvalue"]] outputs: * {[ x: Field\r\n * value]}} * {- Whitespace at the end of a header field is suppressed. One field * is separated from the next field by printing [eol] once.} * } * * These rules ensure that the printed header will be well-formed with * two exceptions: * - Long lines (> 72 characters) are neither folded nor rejected * - True 8 bit characters are neither properly encoded nor rejected * * These two problems cannot be addressed without taking the syntax * of the header fields into account. See below how to create * proper header fields from [s_token] lists. *) (* *********************************************************************) (** {1:structured_values Parsing Structured Values} *) (** The following types and functions allow it to build scanners for * structured mail and MIME values in a highly configurable way. * * {b Structured Values} * * RFC 822 (together with some other RFCs) defines lexical rules * how formal mail header values should be divided up into tokens. Formal * mail headers are those headers that are formed according to some * grammar, e.g. mail addresses or MIME types. * * Some of the characters separate phrases of the value; these are * the "special" characters. For example, '\@' is normally a special * character for mail addresses, because it separates the user name * from the domain name (as in [user\@domain]). RFC 822 defines a fixed set * of special * characters, but other RFCs use different sets. Because of this, * the following functions allow it to configure the set of special characters. * * Every sequence of characters may be embraced by double quotes, * which means that the sequence is meant as literal data item; * special characters are not recognized inside a quoted string. You may * use the backslash to insert any character (including double quotes) * verbatim into the quoted string (e.g. "He said: \"Give it to me!\""). * The sequence of a backslash character and another character is called * a quoted pair. * * Structured values may contain comments. The beginning of a comment * is indicated by '(', and the end by ')'. Comments may be nested. * Comments may contain quoted pairs. A * comment counts as if a space character were written instead of it. * * Control characters are the ASCII characters 0 to 31, and 127. * RFC 822 demands that mail headers are 7 bit ASCII strings. Because * of this, this module also counts the characters 128 to 255 as * control characters. * * Domain literals are strings embraced by '\[' and '\]'; such literals * may contain quoted pairs. Today, domain literals are used to specify * IP addresses (rare), e.g. [user\@[192.168.0.44]]. * * Every character sequence not falling in one of the above categories * is an atom (a sequence of non-special and non-control characters). * When recognized, atoms may be encoded in a character set different than * US-ASCII; such atoms are called encoded words (see RFC 2047). * * {b Scanning Using the Extended Interface} * * In order to scan a string containing a structured value, you must first * create a [mime_scanner] using the function [create_mime_scanner]. * The scanner contains the reference to the scanned string, and a * specification how the string is to be scanned. The specification * consists of the lists [specials] and [scan_options]. * * The character list [specials] specifies the set of special characters. * These are the characters that are not regarded as part of atoms, * because they work as delimiters that separate atoms (like [@] in the * above example). In addition to this, when '"', '(', and '\[' are * seen as regular characters not delimiting quoted string, comments, and * domain literals, respectively, these characters must also be added * to [specials]. In detail, these rules apply: * * {ul * {- {b Spaces:} * - If [' '] {i in} [specials]: A space character is returned as [Special ' ']. * Note that there may also be an effect on how comments are returned * (see below). * - If [' '] {i not in} [specials]: Spaces are not returned, although * they still delimit atoms. * * } * {- {b Tabs, CRs, LFs:} * - If ['\t'] {i in} [specials]: A tab character is returned as * [Special '\t']. * - If ['\t'] {i not in} [specials]: Tabs are not returned, although * they still delimit atoms. * - If ['\r'] {i in} [specials]: A CR character is returned as * [Special '\r']. * - If ['\r'] {i not in} [specials]: CRs are not returned, although * they still delimit atoms. * - If ['\n'] {i in} [specials]: A LF character is returned as * [Special '\n']. * - If ['\n'] {i not in} [specials]: LFs are not returned, although * they still delimit atoms. * * } * {- {b Comments:} * {ul * {- If ['('] {i in} [specials]: Comments are not recognized. The * character '(' is returned as [Special '('].} * {- If ['('] {i not in} [specials]: Comments are recognized. How comments * are returned, depends on the following: * + If [Return_comments] {i in} [scan_options]: Outer comments are * returned as [Comment] (note that inner comments are recognized but * are not returned as tokens) * + If otherwise [' '] {i in} [specials]: Outer comments are returned as * [Special ' '] * + Otherwise: Comments are recognized but not returned at all. * * } * } * } * {- {b Quoted strings:} * - If ['"'] {i in} [specials]: Quoted strings are not recognized, and * double quotes are returned as [Special '"']. * - If ['"'] {i not in} [specials]: Quoted strings are returned as * [QString] tokens. * * } * {- {b Domain literals:} * {ul * {- If '\[' {i in} [specials]: Domain literals are not recognized, and * left brackets are returned as [Special] '\['.} * {- If '\[' {i not in} [specials]: Domain literals are returned as * [DomainLiteral] tokens.} * } * } * } * * If recognized, quoted strings are returned as [QString s], where * [s] is the string without the embracing quotes, and with already * decoded quoted pairs. * * Control characters [c] are returned as [Control c]. * * If recognized, comments may either be returned as spaces (in the case * you are not interested in the contents of comments), or as [Comment] tokens. * The contents of comments are not further scanned; you must start a * subscanner to analyze comments as structured values. * * If recognized, domain literals are returned as [DomainLiteral s], where * [s] is the literal without brackets, and with decoded quoted pairs. * * Atoms are returned as [Atom s] where [s] is a longest sequence of * atomic characters (all characters which are neither special nor control * characters nor delimiters for substructures). If the option * [Recognize_encoded_words] is on, atoms which look like encoded words * are returned as [EncodedWord] tokens. (Important note: Neither '?' nor * '=' must be special in order to enable this functionality.) * * After the [mime_scanner] has been created, you can scan the tokens by * invoking [scan_token] which returns one token at a time, or by invoking * [scan_token_list] which returns all following tokens. * * There are two token types: [s_token] is the base type and is intended to * be used for pattern matching. [s_extended_token] is a wrapper that * additionally contains information where the token occurs. * * {b Scanning Using the Simple Interface} * * Instead of creating a [mime_scanner] and calling the scan functions, * you may also invoke [scan_structured_value]. This function returns the * list of tokens directly; however, it is restricted to [s_token]. * * {b Examples} * * - Simple address: {[ * scan_structured_value "user\@domain.com" [ '\@'; '.' ] [] * = [ Atom "user"; Special '\@'; Atom "domain"; Special '.'; Atom "com" ] * ]} * - Spaces are not returned: {[ * scan_structured_value "user \@ domain . com" [ '\@'; '.' ] [] * = [ Atom "user"; Special '\@'; Atom "domain"; Special '.'; Atom "com" ] * ]} * - Comments are not returned: {[ * scan_structured_value "user(Do you know him?)\@domain.com" [ '\@'; '.' ] [] * = [ Atom "user"; Special '\@'; Atom "domain"; Special '.'; Atom "com" ] * ]} * - Comments are indicated if requested: {[ * scan_structured_value "user(Do you know him?)\@domain.com" [ '\@'; '.' ] * [ Return_comments ] * = [ Atom "user"; Comment; Special '\@'; Atom "domain"; Special '.'; * Atom "com" ] * ]} * - Spaces are returned if special: {[ * scan_structured_value "user (Do you know him?) \@ domain . com" * [ '\@'; '.'; ' ' ] [] * = [ Atom "user"; Special ' '; Special ' '; Special ' '; Special '\@'; * Special ' '; Atom "domain"; * Special ' '; Special '.'; Special ' '; Atom "com" ] * ]} * - Both spaces and comments are requested: {[ * scan_structured_value "user (Do you know him?) \@ domain . com" * [ '\@'; '.'; ' ' ] [ Return_comments ] * = [ Atom "user"; Special ' '; Comment; Special ' '; Special '\@'; * Special ' '; Atom "domain"; * Special ' '; Special '.'; Special ' '; Atom "com" ] * ]} * - Another case: {[ * scan_structured_value "user \@ domain . com" [ '\@'; '.'; ' ' ] [] * = [ Atom "user"; Special ' '; Special '\@'; Special ' '; Atom "domain"; * Special ' '; Special '.'; Special ' '; Atom "com" ] * ]} * - '(' is special: {[ * scan_structured_value "user(Do you know him?)\@domain.com" ['\@'; '.'; '('] * [] * = [ Atom "user"; Special '('; Atom "Do"; Atom "you"; Atom "know"; * Atom "him?)"; Special '\@'; Atom "domain"; Special '.'; Atom "com" ] * ]} * - Quoted strings: {[ * scan_structured_value "\"My.name\"\@domain.com" [ '\@'; '.' ] [] * = [ QString "My.name"; Special '\@'; Atom "domain"; Special '.'; * Atom "com" ] * ]} * - Encoded words are not returned: {[ * scan_structured_value "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=" * [ ] [ ] * = [ Atom "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=" ] * ]} * - Encoded words are returned if requested: {[ * scan_structured_value "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=" * [ ] [ Recognize_encoded_words ] * = [ EncodedWord(("ISO-8859-1",""), "Q", "Keld_J=F8rn_Simonsen") ] * ]} *) type s_token = Atom of string | EncodedWord of ((string * string) * string * string) (** Args: [((charset,lang),encoding,encoded_word)] *) | QString of string | Control of char | Special of char | DomainLiteral of string | Comment | End (** *) (** A token may be one of: * - [QString s]: The quoted string [s], i.e a string between double * quotes. Quoted pairs are already decoded in [s]. * - [Control c]: The control character [c] (0-31, 127, 128-255) * - [Special c]: The special character [c], i.e. a character from * the [specials] list * - [DomainLiteral s]: The bracketed string [s], i.e. a string between * brackets. Quoted pairs are already decoded in [s]. * - [Comment]: A string between parentheses. This kind of token is only * generated when the option [Return_comments] is in effect. * - [EncodedWord((charset,lang),encoding,encoded_word)]: An RFC-2047 style * encoded word: [charset] is the name of the character set; [lang] is * the language specifier (from RFC 2231) or ""; [encoding] is either * "Q" or "B"; and [encoded_word] is the word encoded in [charset] and * [encoding]. This kind of token is only generated when the option * [Recognize_encoded_words] is in effect (if not, [Atom] is generated * instead). * - [Atom s]: A string which is neither quoted not bracketed nor * written in RFC 2047 notation, and which is not a control or special * character, i.e. the "rest" * - [End]: The end of the string *) type s_option = No_backslash_escaping (** Do not handle backslashes in quoted string and comments as escape * characters; backslashes are handled as normal characters. * For example: The wrong qstring ["C:\dir\file"] will be returned as * [QString "C:\dir\file"] when this option is in effect, and not as * [QString "C:dirfile"] as by default. * -- This is a common error in many MIME implementations. *) | Return_comments (** Comments are returned as token [Comment] (unless '(' is included * in the list of special characters, in which case comments are * not recognized at all). * You may get the exact location of the comment by applying * [get_pos] and [get_length] to the extended token. *) | Recognize_encoded_words (** Enables that encoded words are recognized and returned as * [EncodedWord] instead of [Atom]. *) type s_extended_token (** An opaque type containing the information of [s_token] plus: * - where the token occurs * - RFC-2047 access functions *) val get_token : s_extended_token -> s_token (** Return the [s_token] within the [s_extended_token] *) val get_decoded_word : s_extended_token -> string val get_charset : s_extended_token -> string (** Return the decoded word (the contents of the word after decoding the * "Q" or "B" representation), and the character set of the decoded word * (uppercase). * * These functions not only work for [EncodedWord]. The function * [get_decoded_word] returns for the other kinds of token: * - [Atom]: Returns the atom without decoding it * - [QString]: Returns the characters inside the double quotes, and * ensures that any quoted pairs are decoded * - [Control]: Returns the one-character string * - [Special]: Returns the one-character string * - [DomainLiteral]: Returns the characters inside the brackets, and * ensures that any quoted pairs are decoded * - [Comment]: Returns [""] * * The function [get_charset] returns ["US-ASCII"] for them. *) val get_language : s_extended_token -> string (** Returns the language if the token is an [EncodedWord], and [""] for * all other tokens. *) val get_pos : s_extended_token -> int (** Return the byte position where the token starts in the string * (the first byte has position 0) *) val get_line : s_extended_token -> int (** Return the line number where the token starts (numbering begins * usually with 1) *) val get_column : s_extended_token -> int (** Return the column of the line where the token starts (first column * is number 0) *) val get_length : s_extended_token -> int (** Return the length of the token in bytes *) val separates_adjacent_encoded_words : s_extended_token -> bool (** True iff the current token is white space (i.e. [Special ' '], * [Special '\t'], [Special '\r'] or [Special '\n']) and the last * non-white space token was [EncodedWord] and the next non-white * space token will be [EncodedWord]. * * The background of this function is that white space between * encoded words does not have a meaning, and must be ignored * by any application interpreting encoded words. *) type mime_scanner (** The opaque type of a scanner for structured values *) val create_mime_scanner : specials:char list -> scan_options:s_option list -> ?pos:int -> ?line:int -> ?column:int -> string -> mime_scanner (** Creates a new [mime_scanner] scanning the passed string. * * @param specials The list of characters recognized as special characters. * @param scan_options The list of global options modifying the behaviour * of the scanner * @param pos The position of the byte where the scanner starts in the * passed string. Defaults to 0. * @param line The line number of this first byte. Defaults to 1. * @param column The column number of this first byte. Default to 0. *) (** Note for [create_mime_scanner]: * * The optional parameters [pos], [line], [column] are intentionally placed after * [scan_options] and before the string argument, so you can specify * scanners by partially applying arguments to [create_mime_scanner] * which are not yet connected with a particular string: * {[ * let my_scanner_spec = create_mime_scanner my_specials my_options in * ... * let my_scanner = my_scanner_spec my_string in * ...]} *) val get_pos_of_scanner : mime_scanner -> int val get_line_of_scanner : mime_scanner -> int val get_column_of_scanner : mime_scanner -> int (** Return the current position, line, and column of a [mime_scanner]. * The primary purpose of these functions is to simplify switching * from one [mime_scanner] to another within a string: * * {[ * let scanner1 = create_mime_scanner ... s in * ... now scanning some tokens from s using scanner1 ... * let scanner2 = create_mime_scanner ... * ?pos:(get_pos_of_scanner scanner1) * ?line:(get_line_of_scanner scanner1) * ?column:(get_column_of_scanner scanner1) * s in * ... scanning more tokens from s using scanner2 ... ]} * * {b Restriction:} These functions are not available if the option * [Recognize_encoded_words] is on. The reason is that this option * enables look-ahead scanning; please use the location of the last * scanned token instead. * * Note: To improve the performance of switching, it is recommended to * create scanner specs in advance (see the example [my_scanner_spec] * above). *) val scan_token : mime_scanner -> (s_extended_token * s_token) (** Returns the next token, or [End] if there is no more token. The * token is returned both as extended and as normal token. *) val scan_token_list : mime_scanner -> (s_extended_token * s_token) list (** Returns all following tokens as a list (excluding [End]) *) val scan_structured_value : string -> char list -> s_option list -> s_token list (** This function is included for backwards compatibility, and for all * cases not requiring extended tokens. * * It scans the passed string according to the list of special characters * and the list of options, and returns the list of all tokens. *) val specials_rfc822 : char list val specials_rfc2045 : char list (** The sets of special characters defined by the RFCs 822 and 2045. *) (* *********************************************************************) (* Widely used scanners: *) (** {1:parsers_for_structured_values Parsing Certain Forms of Structured Values} *) val scan_encoded_text_value : string -> s_extended_token list (** Scans a "text" value. The returned token list contains only * [Special], [Atom] and [EncodedWord] tokens. * Spaces, TABs, CRs, LFs are returned (as [Special]) unless * they occur between adjacent encoded words in which case * they are suppressed. The characters '(', '\[', and '"' are also * returned as [Special] tokens, and are not interpreted as delimiters. * * For instance, this function can be used to scan the "Subject" * field of mail messages. *) val scan_value_with_parameters : string -> s_option list -> (string * (string * string) list) (** [let name, params = scan_value_with_parameters s options]: * Scans values with annotations like * [name ; p1=v1 ; p2=v2 ; ...] * For example, MIME types like "text/plain;charset=ISO-8859-1" can * be parsed. * * The values may or may not be quoted. The characters ";", "=", and * even "," are only accepted as part of values when they are quoted. * On sytax errors, the function fails. * * RFC 2231: This function supports some features of this RFC: * Continued parameter values are concatenated. For example: * * {[ * Content-Type: message/external-body; access-type=URL; * URL*0="ftp://"; * URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" ]} * * This is returned as: * {["message/external-body", * [ ("access-type", "URL"); * ("URL", "ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar") ] ) ]} * * However, encoded parameter values are not handled specially. The * parameter * [title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A] * would be returned as * [("title*", "us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A")]. * Use [scan_values_with_parameters_ep] instead (see below). * * Raises [Failure] on syntax errors. *) type s_param (** The type of encoded parameters (RFC 2231) *) val param_value : s_param -> string val param_charset : s_param -> string val param_language : s_param -> string (** Return the decoded value of the parameter, the charset (uppercase), * and the language. * If the charset is not available, [""] will be returned. * If the language is not available, [""] will be returned. *) val mk_param : ?charset:string -> ?language:string -> string -> s_param (** Creates a parameter from a value (in decoded form). The parameter * may have a charset and a language. *) val print_s_param : Format.formatter -> s_param -> unit (** Prints a parameter to the formatter (as toploop printer) *) val scan_value_with_parameters_ep : string -> s_option list -> (string * (string * s_param) list) (** [let name, params = scan_value_with_parameters_ep s options]: * This version of the scanner copes with encoded parameters according * to RFC 2231. * Note: "ep" means "encoded parameters". * * Example: * [doc.html;title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A] * * The parameter [title] would be returned as: * - name is ["title"] * - value is ["This is ***fun***"] * - charset is ["US-ASCII"] * - language is ["en-us"] * * Raises [Failure] on syntax errors. *) val scan_mime_type : string -> s_option list -> (string * (string * string) list) (** [let name, params = scan_mime_type s options]: * Scans MIME types like * [text/plain; charset=iso-8859-1] * The name of the type and the names of the parameters are converted * to lower case. * * Raises [Failure] on syntax errors. *) val scan_mime_type_ep : string -> s_option list -> (string * (string * s_param) list) (** [let name, params = scan_mime_type_ep s options]: * This version copes with RFC-2231-encoded parameters. * * Raises [Failure] on syntax errors. *) val split_mime_type : string -> (string * string) (** [let (main_type, sub_type) = split_mime_type content_type]: * Splits the MIME type into main and sub type, for example * [ split_mime_type "text/plain" = ("text", "plain") ]. * The returned strings are always lowercase. * * Raises [Failure] on syntax errors. *) (* *********************************************************************) (* Write s_token list *) (** {1:printers_for_structured_values Printing Structured Values} *) exception Line_too_long (** Raised when the hard limit of the line length is exceeded *) val write_value : ?maxlen1:int -> (* Default: no max length *) ?maxlen:int -> (* Default: no max length *) ?hardmaxlen1:int -> (* Default: no hard max length *) ?hardmaxlen:int -> (* Default: no hard max length *) ?fold_qstring:bool -> (* Default: true *) ?fold_literal:bool -> (* Default: true *) ?unused:int ref -> (* Default: do not store this value *) ?hardunused:int ref -> (* Default: do not store this value *) Netchannels.out_obj_channel -> s_token list -> unit (** Writes the list of [s_token] to the [out_obj_channel]. The value * is optionally folded into several lines while writing, but this * is off by default. To enable folding, pass {b both} [maxlen1] and * [maxlen]: * The [maxlen1] parameter specifies the length of the first line * to write, the [maxlen] parameter specifies the length of the * other lines. * * If enabled, folding tries to ensure that the value is written * in several lines that are not longer as specified by * [maxlen1] and [maxlen]. The value is split into lines by inserting * "folding space" at certain locations (which is usually a linefeed * followed by a space character, see below). The following * table specifies between which tokens folding may happen: * * {[ * +=========================================================+ * 1st \ 2nd | Atom | QString | DLiteral | EncWord | Special | Spec ' '| * ==============+======+=========+==========+=========+=========+=========+ * Atom | FS | FS | FS | FS | - | F | * QString | FS | FS | FS | FS | - | F | * DomainLiteral | FS | FS | FS | FS | - | F | * EncodedWord | FS | FS | FS | FS | - | F | * Special | - | - | - | - | - | F | * Special ' ' | - | - | - | - | - | - | * ==============+======+=========+==========+=========+=========+=========+ *]} * * The table shows between which two types of tokens a space or a folding * space is inserted: * - [FS]: folding space * - [F]: linefeed without extra space * - [-]: nothing can be inserted here * * Folding space is ["\n "], i.e. only LF, not CRLF is used as end-of-line * character. The function [write_header] will convert these LF to CRLF * if needed. * * [Special '\t'] is handled like [Special ' ']. Control characters are just * printed, without folding. Comments, however, are substituted by * either space or folding space. The token [End] is ignored. * * Furthermore, folding may also happen within tokens: * - [Atom], [Control], and [Special] are never split up into parts. * They are simply printed. * - [EncodedWord]s, however, are reformatted. This especially means: * adjacent encoded words are first concatenated if possible * (same character set, same encoding, same language), and then * split up into several pieces with optimally chosen lengths. * {b Note:} Because this function gets [s_token] as input and not * [s_extended_token], it is not known whether [Special ' '] tokens * (or other whitespace) between adjacent EncodedWords must be * ignored. Because of this, [write_value] only reformats adjacent encoded * words when there is not any whitespace between them. * - [QString] may be split up in a special way unless [fold_qstring] * is set to [false]. For example, ["One Two Three"] may be split up into * three lines ["One\n Two\n \ Three"]. Because some header fields * explicitly forbid folding of quoted strings, it is possible to * set [~fold_qstring:false] (it is [true] by default). * {b Note:} Software should not rely on that the different types of * whitespace (especially space and TAB) remain intact at the * beginning of a line. Furthermore, it may also happen that * additional whitespace is added at the end of a line by the * transport layer. * - [DomainLiteral]: These are handled like [QString]. The parameter * [~fold_literal:false] turns folding off if it must be prevented, * it is [true] by default. * - [Comment]: Comments are effectively omitted! Instead of [Comment], * a space or folding space is printed. However, you can output comments * by passing sequences like [ Special "("; ...; Special ")" ]. * * It is possible to get the actual number of characters back that * can still be printed into the last line without making the line * too long. Pass an [int ref] as [unused] to get this value (it may * be negative!). Pass an * [int ref] as [hardunused] to get the number of characters that may * be printed until the hard limit is exceeded. * * The function normally does not fail when a line becomes too long, * i.e. it exceeds [maxlen1] or [maxlen]. * However, it is possible to specify a hard maximum length * ([hardmaxlen1] and [hardmaxlen]). If these are exceeded, the function * will raise [Line_too_long]. * * For electronic mail, a [maxlen] of 78 and a [hardmaxlen] of 998 is * recommended. * * {b Known Problems:} * - The reformatter for EncodedWords takes into * account that multi-byte characters must not be split up. However, * this works only when the multi-byte character set is known * to [Netconversion]. You can assume that UTF-8 and UTF-16 always * work. If the character set is not known the reformatter may * split the string at wrong positions. * - The reformatter for EncodedWords may parse the token, and if * this fails, you will get the exception [Malformed_code]. * This is only done in some special cases, however. * - The function prints spaces between adjacent atoms. Although * this is allowed in principal, other MIME implementations might fail when * there are spaces at unexpected locations. Workaround: If * no spaces are desired, concatenate adjacent atoms before * passing them to this function. * * {b Further Tips:} * - Pass ~maxlen1:0 and ~maxlen:0 to get shortest lines * - Use the reformatter for encoded words! It works well. For * example, to output a long sentence, just wrap it into * {b one} [EncodedWord]. The reformatter takes care to * fold the word into several lines. *) val param_tokens : ?maxlen:int -> (string*s_param) list -> s_token list (** Formats a parameter list. For example, * [[ "a", "b"; "c", "d" ]] is transformed to the token sequence * corresponding to [; a=b; c=d]. * If [maxlen] is specified, it is ensured that the individual * parameter (e.g. ["a=b;"]) is not longer than [maxlen-1], such that * it will fit into a line with maximum length [maxlen]. * By default, no maximum length is guaranteed. * If [maxlen] is passed, or if a parameter specifies a character * set or language, the encoding of RFC 2231 will be applied. If these * conditions are not met, the parameters will be encoded traditionally. *) val split_uri : string -> s_token list (** Splits a long URI according to the algorithm of RFC 2017. * The input string must only contain 7 bit characters, and * must be, if necessary, already be URL-encoded. *) (* *********************************************************************) (* Scanners for MIME bodies *) (** {1:scanning_mime Scanning MIME Messages} *) val scan_multipart_body : string -> start_pos:int -> end_pos:int -> boundary:string -> ((string * string) list * string) list (** [let [params1, value1; params2, value2; ...] * = scan_multipart_body s start_pos end_pos boundary]: * * Scans the string [s] that is the body of a multipart message. * The multipart message begins at position [start_pos] in [s], and * [end_pos] is the position * of the character following the message. In [boundary] the boundary string * must be passed (this is the "boundary" parameter of the multipart * MIME type, e.g. [multipart/mixed;boundary="some string"] ). * * The return value is the list of the parts, where each part * is returned as pair [(params, value)]. The left component [params] * is the list of name/value pairs of the header of the part. The * right component is the raw content of the part, i.e. if the part * is encoded ("content-transfer-encoding"), the content is returned * in the encoded representation. The caller is responsible for decoding * the content. * * The material before the first boundary and after the last * boundary is not returned. * * {b Multipart Messages} * * The MIME standard defines a way to group several message parts to * a larger message (for E-Mails this technique is known as "attaching" * files to messages); these are the so-called multipart messages. * Such messages are recognized by the major type string "multipart", * e.g. [multipart/mixed] or [multipart/form-data]. Multipart types MUST * have a [boundary] parameter because boundaries are essential for the * representation. * * Multipart messages have a format like (where "_" denotes empty lines): * {[ * ...Header... * Content-type: multipart/xyz; boundary="abc" * ...Header... * _ * Body begins here ("prologue") * --abc * ...Header part 1... * _ * ...Body part 1... * --abc * ...Header part 2... * _ * ...Body part 2 * --abc * ... * --abc-- * Epilogue ]} * * The parts are separated by boundary lines which begin with "--" and * the string passed as boundary parameter. (Note that there may follow * arbitrary text on boundary lines after "--abc".) The boundary is * chosen such that it does not occur as prefix of any line of the * inner parts of the message. * * The parts are again MIME messages, with header and body. Note * that it is explicitely allowed that the parts are even multipart * messages. * * The texts before the first boundary and after the last boundary * are ignored. * * Note that multipart messages as a whole MUST NOT be encoded. * Only the PARTS of the messages may be encoded (if they are not * multipart messages themselves). * * Please read RFC 2046 if want to know the gory details of this * brain-dead format. *) val scan_multipart_body_and_decode : string -> start_pos:int -> end_pos:int -> boundary:string -> ((string * string) list * string) list (** Same as [scan_multipart_body], but decodes the bodies of the parts * if they are encoded using the methods "base64" or "quoted printable". * Fails, if an unknown encoding is used. *) val scan_multipart_body_from_netstream : Netstream.in_obj_stream -> boundary:string -> create:((string * string) list -> 'a) -> add:('a -> Netstream.in_obj_stream -> int -> int -> unit) -> stop:('a -> unit) -> unit (** [scan_multipart_body_from_netstream s boundary create add stop]: * * Reads the MIME message from the netstream [s] block by block. The * parts are delimited by the [boundary]. * * Once a new part is detected and begins, the function [create] is * called with the MIME header as argument. The result [p] of this function * may be of any type. * * For every chunk of the part that is being read, the function [add] * is invoked: [add p s k n]. * * Here, [p] is the value returned by the [create] invocation for the * current part. [s] is the netstream. The current window of [s] contains * the read chunk completely; the chunk begins at position [k] of the * window (relative to the beginning of the window) and has a length * of [n] bytes. * * When the part has been fully read, the function [stop] is * called with [p] as argument. * * That means, for every part the following is executed: * - [let p = create h] * - [add p s k1 n1] * - [add p s k2 n2] * - ... * - [add p s kN nN] * - [stop p] * * {b Important Precondition:} * - The block size of the netstream [s] must be at least * [String.length boundary + 4] * * {b Exceptions:} * - Exceptions can happen because of ill-formed input, and within * the callbacks of the functions [create], [add], [stop]. * - If the exception happens while part [p] is being read, and the * [create] function has already been called (successfully), the * [stop] function is also called (you have the chance to close files). * The exception is re-raised after [stop] returns. *) val read_multipart_body : (Netstream.in_obj_stream -> 'a) -> string -> Netstream.in_obj_stream -> 'a list (** This is the "next generation" multipart message parser. It is * called as follows: * * [let parts = read_multipart_body f boundary s] * * As precondition, the current position of the stream [s] must be at * the beginning of the message body. The string [boundary] must * be the message boundary (without "--"). The function [f] is called * for every message part, and the resulting list [parts] is the * concatentation of the values returned by [f]. * * The stream passed to [f] is a substream of [s] that begins at the * first byte of the header of the message part. The function [f] * can read data from the substream as necessary. The substream * terminates at the end of the message part. This means that [f] can simply * read the data of the substream from the beginning to the end. It is * not necessary that [f] reads the substream until EOF, however. * * After all parts have been read, the trailing material of stream [s] * is skipped until EOF of [s] is reached. *) (* *********************************************************************) (* Tools to create multipart messages *) (** {1:helpers_mime Helpers for MIME Messages} *) val create_boundary : ?random:string list -> ?nr:int -> unit -> string (** Creates a boundary string that can be used to separate multipart * messages. * The string is 63 characters long and has the following "features": * - Most of the string consists of the minus character yielding * a clear optical effect * - The string contains "=__". This sequence cannot be obtained * by the quoted-printable encoding, so you need not to care whether * strings encoded as quoted-printable contain the boundary. * - The string contains "<&>;" which is illegal in HTML, XML, and * SGML. * - The string does not contain double quotes or backslashes, * so you can safely put double quotes around it in the MIME header. * - The string contains [nr], so you can safely distinguish between * several boundaries occurring in the same MIME body if you * assign different [nr]. * - The string contains a hash value composed of the first * 256 bytes of all strings passed as [random], and influenced * by the current GC state. *) (* THREAD-SAFETY: * The functions are thread-safe as long as the threads do not share * values. *) ocamlnet-4.1.2/src/netstring/netasn1_encode.ml0000644000175000017500000001465112731530350017776 0ustar gerdgerd(* $Id$ *) (* TODO: - verify strings *) open Netasn1 exception Encode_error of string let tag_of_value = function | Value.Bool _ -> Value.Universal, 1 | Value.Integer _ -> Value.Universal, 2 | Value.Bitstring _ -> Value.Universal, 3 | Value.Octetstring _ -> Value.Universal, 4 | Value.Null -> Value.Universal, 5 | Value.OID _ -> Value.Universal, 6 | Value.ObjectDescriptor _ -> Value.Universal, 7 | Value.External _ -> Value.Universal, 8 | Value.Real _ -> Value.Universal, 9 | Value.Enum _ -> Value.Universal, 10 | Value.Embedded_PDV _ -> Value.Universal, 11 | Value.UTF8String _ -> Value.Universal, 12 | Value.ROID _ -> Value.Universal, 13 | Value.Seq _ -> Value.Universal, 16 | Value.Set _ -> Value.Universal, 17 | Value.NumericString _ -> Value.Universal, 18 | Value.PrintableString _ -> Value.Universal, 19 | Value.TeletexString _ -> Value.Universal, 20 | Value.VideotexString _ -> Value.Universal, 21 | Value.IA5String _ -> Value.Universal, 22 | Value.UTCTime _ -> Value.Universal, 23 | Value.GeneralizedTime _ -> Value.Universal, 24 | Value.GraphicString _ -> Value.Universal, 25 | Value.VisibleString _ -> Value.Universal, 26 | Value.GeneralString _ -> Value.Universal, 27 | Value.UniversalString _ -> Value.Universal, 28 | Value.CharString _ -> Value.Universal, 29 | Value.BMPString _ -> Value.Universal, 30 | Value.ITag(tc, tag, _) -> if tag < 0 then failwith "Netasn1_encode.tag_of_value"; tc, tag | Value.Tag(tc, tag, _, _) -> if tag < 0 then failwith "Netasn1_encode.tag_of_value"; tc, tag | Value.Tagptr(tc, tag, _, _, _, _) -> if tag < 0 then failwith "Netasn1_encode.tag_of_value"; tc, tag let encode_error s = raise(Encode_error s) let encode_base128 buf n = let rec encode n = if n < 128 then [ n ] else (n land 127) :: encode (n lsr 7) in if n < 0 then encode_error "bad input"; let l = List.rev(encode n) in let len = List.length l in let l = List.mapi (fun i k -> if i < len-1 then Char.chr(k lor 128) else Char.chr k ) l in List.iter (Netbuffer.add_char buf) l let rec encode_ber_contents buf v = match v with | Value.Null -> Value.Primitive | Value.Bool b -> Netbuffer.add_char buf (if b then '\xff' else '\x00'); Value.Primitive | Value.Integer n | Value.Enum n -> let s = Value.get_int_repr n in Netbuffer.add_string buf s; Value.Primitive | Value.Real n -> let s = Value.get_real_repr n in Netbuffer.add_string buf s; Value.Primitive | Value.OID oid -> if Array.length oid <= 2 then encode_error "bad OID in input"; let x = oid.(0) in let y = oid.(1) in if x < 0 || x > 2 || y < 0 || y > 39 then encode_error "bad OID in input"; encode_base128 buf (x * 40 + y); for k = 2 to Array.length oid - 1 do encode_base128 buf oid.(k) done; Value.Primitive | Value.ROID oid -> for k = 0 to Array.length oid - 1 do encode_base128 buf oid.(k) done; Value.Primitive | Value.Octetstring s | Value.ObjectDescriptor s | Value.UTF8String s | Value.NumericString s | Value.PrintableString s | Value.TeletexString s | Value.VideotexString s | Value.IA5String s | Value.GraphicString s | Value.VisibleString s | Value.GeneralString s | Value.UniversalString s | Value.CharString s | Value.BMPString s -> Netbuffer.add_string buf s; Value.Primitive | Value.UTCTime t -> if Value.get_time_subtype t <> `U then encode_error "wrong time format for UTCTime"; let s = Value.get_time_repr t in Netbuffer.add_string buf s; Value.Primitive | Value.GeneralizedTime t -> if Value.get_time_subtype t <> `G then encode_error "wrong time format for GeneralizedTime"; let s = Value.get_time_repr t in Netbuffer.add_string buf s; Value.Primitive | Value.Bitstring bs -> let s = Value.get_bitstring_repr bs in Netbuffer.add_string buf s; Value.Primitive | Value.Seq vals | Value.Set vals | Value.External vals | Value.Embedded_PDV vals -> List.iter (fun v -> ignore(encode_ber buf v) ) vals; Value.Constructed | Value.ITag(_,_,v) -> ( match v with | Value.ITag _ | Value.Tagptr _ -> encode_ber buf v | _ -> encode_ber_contents buf v ) | Value.Tag(_,_,_,v) -> encode_ber buf v | Value.Tagptr(_,_,pc,box,pos,len) -> let Netstring_tstring.Tstring_polybox(ops,s) = box in Netbuffer.add_subtstring_poly buf ops s pos len; pc and encode_ber buf v = let buf' = Netbuffer.create 80 in let pc = encode_ber_contents buf' v in let length = Netbuffer.length buf' in let tc, tag = tag_of_value v in let tc_bits = match tc with | Value.Universal -> 0 | Value.Application -> 1 | Value.Context -> 2 | Value.Private -> 3 in let pc_bit = match pc with | Value.Primitive -> 0 | Value.Constructed -> 1 in let octet0 = (tc_bits lsl 6) lor (pc_bit lsl 5) lor (if tag <= 30 then tag else 31) in Netbuffer.add_char buf (Char.chr octet0); if tag > 30 then encode_base128 buf tag; if length < 128 then Netbuffer.add_char buf (Char.chr length) else ( if length <= 0xff then ( Netbuffer.add_char buf '\x81'; Netbuffer.add_char buf (Char.chr length); ) else if length <= 0xffff then ( Netbuffer.add_char buf '\x82'; Netbuffer.add_char buf (Char.chr (length lsr 8)); Netbuffer.add_char buf (Char.chr (length land 0xff)); ) else ( let i = Value.int length in let s0 = Value.get_int_repr i in let s1 = (* integers are signed, but we need here unsigned ints: *) if s0.[0] = '\x00' then String.sub s0 1 (String.length s0 - 1) else s0 in Netbuffer.add_char buf (Char.chr (0x80 + String.length s1)); Netbuffer.add_string buf s1; ) ); Netbuffer.add_buffer buf buf'; pc ocamlnet-4.1.2/src/netstring/netmech_gs2_sasl.ml0000644000175000017500000006015012731530350020323 0ustar gerdgerd(* $Id$ *) open Printf module type PROFILE = sig val mechanism_name : string val announce_channel_binding : bool val mechanism_oid : Netsys_gssapi.oid val client_additional_params : string list val server_additional_params : string list val client_map_user_name : params:(string * string) list -> string -> string * Netsys_gssapi.oid val server_map_user_name : params:(string * string) list -> (string * Netsys_gssapi.oid) -> string val client_get_target_name : params:(string * string) list -> (string * Netsys_gssapi.oid) val server_bind_target_name : params:(string * string) list -> (string * Netsys_gssapi.oid) option val server_check_target_name : params:(string * string) list -> (string * Netsys_gssapi.oid) -> bool val client_flags : params:(string * string) list -> ( Netsys_gssapi.req_flag * bool ) list val server_flags : params:(string * string) list -> Netsys_gssapi.req_flag list val client_credential : exn option end module GS2(P:PROFILE)(G:Netsys_gssapi.GSSAPI) : Netsys_sasl_types.SASL_MECHANISM = struct module M = Netgssapi_auth.Manage(G) module C = struct let raise_error msg = failwith msg end module A = Netgssapi_auth.Auth(G)(C) let mechanism_name = P.mechanism_name ^ (if P.announce_channel_binding then "-PLUS" else "") let client_first = `Required let server_sends_final_data = true let supports_authz = false let available() = true (* Well, let's assume this. We don't know yet whether we can get credentials, and we don't know yet whether we are acting as client or as server. *) type credentials = unit let init_credentials _ = () let map_opt f = function | None -> None | Some x -> Some(f x) (* ------------------------ *) (* Client *) (* ------------------------ *) type client_sub_state = [ `Pre_init_context | `Init_context | `Established ] type client_session = { mutable ccontext : G.context option; cuser : string; cauthz : string; cstate : Netsys_sasl_types.client_state; csubstate : client_sub_state; ctoken : string; cparams : (string * string) list; cconf : Netsys_gssapi.client_config; ctarget_name : G.name; ccred : G.credential; ccb_data : string; ccb : Netsys_sasl_types.cb; cprops : Netsys_gssapi.client_props option; } let client_state cs = cs.cstate let cvalidity cs0 = let cs1 = { cs0 with ccontext = cs0.ccontext } in cs0.ccontext <- None; cs1 let client_del_ctx cs = M.delete_context cs.ccontext (); { cs with ccontext = None } let check_gssapi_status fn_name ((calling_error,routine_error,_) as major_status) minor_status = if calling_error <> `None || routine_error <> `None then ( let msg = M.format_status ~fn:fn_name ~minor_status major_status in (* eprintf "STATUS: %s %s %s\n%!" fn_name error minor_s; *) failwith msg ) let call_init_sec_context cs input_token = let (out_context, out_token, ret_flags, props_opt) = A.init_sec_context ~initiator_cred:cs.ccred ~context:cs.ccontext ~target_name:cs.ctarget_name ~req_flags:(A.get_client_flags cs.cconf) ~chan_bindings:(Some(`Unspecified "", `Unspecified "", cs.ccb_data)) ~input_token cs.cconf in { cs with ccontext = Some out_context; ctoken = out_token; cprops = props_opt; cstate = `Emit; csubstate = ( if props_opt = None then `Init_context else if out_token = "" then `Established else`Init_context ) } let client_cb_string cs = match cs.ccb with | `None -> "n," | `SASL_none_but_advertise -> "y," | `SASL_require(ty,data) -> "p=" ^ ty ^ "," | `GSSAPI _ -> failwith "GSSAPI channel binding not supported" let client_rewrite_initial_token cs token = let (non_std, token_no_header) = try let p = ref 0 in let (_,token') = Netgssapi_support.wire_decode_token token p in if !p <> String.length token then failwith "bad token"; (false, token') with | Failure _ -> (true, token) in String.concat "" [ if non_std then "F," else ""; client_cb_string cs; ( if cs.cauthz = "" then "" else "a=" ^ Netgssapi_support.gs2_encode_saslname cs.cauthz ); ","; token_no_header ] let client_create_cb_data cs = (* RFC 5801, section 5.1 *) { cs with ccb_data = String.concat "" [ client_cb_string cs; ( if cs.cauthz = "" then "" else "a=" ^ Netgssapi_support.gs2_encode_saslname cs.cauthz ); ","; ( match cs.ccb with | `SASL_require(_,data) -> data | _ -> "" ) ] } let create_client_session ~user ~authz ~creds ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_krb5_sasl.create_client_session:" ([ "mutual"; "secure" ] @ P.client_additional_params) params in let (targ_name, target_name_type) = P.client_get_target_name ~params in let (init_name, init_name_type) = P.client_map_user_name ~params user in let flags = List.map (fun (flag, is_required) -> (flag, (if is_required then `Required else `If_possible)) ) (P.client_flags ~params) @ [ `Mutual_flag, `Required ] @ [ `Sequence_flag, `If_possible ] in let integrity = try List.assoc `Integ_flag flags with Not_found -> `None in let privacy = try List.assoc `Conf_flag flags with Not_found -> `None in let cconf = Netsys_gssapi.create_client_config ~mech_type:P.mechanism_oid ?initiator_name:(if init_name_type = [| |] then None else Some(init_name,init_name_type)) ?initiator_cred:P.client_credential ?target_name:(if target_name_type = [| |] then None else Some(targ_name, target_name_type)) ~flags ~privacy ~integrity () in let initiator_name = A.get_initiator_name cconf in let ccred = A.get_initiator_cred ~initiator_name cconf in let ctarget_name = A.get_target_name cconf in let cs = { cuser = user; cauthz = authz; ccontext = None; cstate = `Emit; csubstate = `Pre_init_context; ctoken = ""; cconf; ctarget_name; ccred; cparams = params; ccb_data = ""; ccb = `None; cprops = None; } in let cs = client_create_cb_data cs in cs let client_configure_channel_binding cs cb = { (cvalidity cs) with ccb = cb } let client_state cs = cs.cstate let client_channel_binding cs = cs.ccb let client_restart cs = if cs.cstate <> `OK then failwith "Netmech_gs2_sasl.client_restart: unfinished auth"; { (cvalidity cs) with ccontext = None; cstate = `Emit; csubstate = `Pre_init_context; ctoken = ""; } let client_context cs = match cs.ccontext with | None -> failwith "client_context" | Some c -> c let client_process_challenge cs msg = let cs = cvalidity cs in if cs.cstate <> `Wait then { cs with cstate = `Auth_error "protocol error" } else match cs.csubstate with | `Pre_init_context -> assert false | `Init_context -> ( try call_init_sec_context cs (Some msg) with | Failure msg -> let cs = client_del_ctx cs in { cs with cstate = `Auth_error msg } ) | `Established -> let cs = client_del_ctx cs in { cs with cstate = `Auth_error "unexpected challenge" } let client_emit_response cs = let cs = cvalidity cs in if cs.cstate <> `Emit then failwith "Netmech_gs2_sasl.client_emit_response: bad state"; let cs = match cs.csubstate with | `Pre_init_context -> ( try let cs = call_init_sec_context cs None in { cs with cstate = `Wait; ctoken = client_rewrite_initial_token cs cs.ctoken; } with | Failure msg -> let cs = client_del_ctx cs in { cs with cstate = `Auth_error msg } ) | `Init_context -> { cs with cstate = `Wait } | `Established -> let cs = client_del_ctx cs in (* no longer needed *) { cs with cstate = `OK } in (cs, cs.ctoken) let client_session_id cs = None let client_prop cs key = raise Not_found let client_gssapi_props cs = match cs.cprops with | None -> raise Not_found | Some p -> p let client_user_name cs = "" let client_authz_name cs = cs.cauthz let client_stash_session cs = (* GSSAPI does not support that unfinished contexts are exported. We do not need the context anyway after session establishment, so we don't save it at all. *) if cs.cstate <> `OK then failwith "Netmech_gs5_sasl.client_stash_session: the session \ must be established (implementation restriction)"; "client,t=GS2;" ^ Marshal.to_string (cs.cuser, cs.cauthz, cs.cparams, cs.ccb, map_opt Netsys_gssapi.marshal_client_props cs.cprops) [] let cs_re = Netstring_str.regexp "client,t=GS2;" let client_resume_session s = match Netstring_str.string_match cs_re s 0 with | None -> failwith "Netmech_gs2_sasl.client_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let (cuser, cauthz, cparams, ccb, mprops) = Marshal.from_string data 0 in { cuser; cauthz; ccontext = None; cstate = `OK; csubstate = `Established; ctoken = ""; cparams; cconf = Netsys_gssapi.create_client_config(); ctarget_name = G.interface # no_name; ccred = G.interface # no_credential; ccb_data = ""; ccb; cprops = map_opt Netsys_gssapi.unmarshal_client_props mprops; } (* ------------------------ *) (* Server *) (* ------------------------ *) type server_sub_state = [ `Acc_context | `Skip_empty | `Established ] type server_session = { mutable scontext : G.context option; sstate : Netsys_sasl_types.server_state; ssubstate : server_sub_state; stoken : string; suser : string option; sauthz : string option; scb_data : string; sconf : Netsys_gssapi.server_config; scred : G.credential; slookup : (string -> string -> credentials option); sparams : (string * string) list; scb : (string * string) list; sprops : Netsys_gssapi.server_props option; } let svalidity ss0 = let ss1 = { ss0 with scontext = ss0.scontext } in ss0.scontext <- None; ss1 let server_state ss = ss.sstate let server_del_ctx ss = M.delete_context ss.scontext (); { ss with scontext = None } let server_check_gssapi_status ss fn_name major_status minor_status = try check_gssapi_status fn_name major_status minor_status with | error -> server_del_ctx ss; raise error let create_server_session ~lookup ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_krb5_sasl.create_server_session:" ( [ "mutual"; "secure" ] @ P.server_additional_params ) params in let flags = List.map (fun (flag, is_required) -> (flag, (if is_required then `Required else `If_possible)) ) (P.client_flags ~params) @ [ `Mutual_flag, `Required ] @ [ `Sequence_flag, `If_possible ] in let integrity = try List.assoc `Integ_flag flags with Not_found -> `None in let privacy = try List.assoc `Conf_flag flags with Not_found -> `None in let sconf = Netsys_gssapi.create_server_config ~mech_types:[ P.mechanism_oid ] ?acceptor_name:(P.server_bind_target_name ~params) ~flags ~integrity ~privacy () in let scred_name = A.get_acceptor_name sconf in let scred = A.get_acceptor_cred ~acceptor_name:scred_name sconf in { scontext = None; sstate = `Wait; ssubstate = `Acc_context; stoken = ""; suser = None; sauthz = None; slookup = lookup; sparams = params; sconf; scred; scb_data = ""; scb = []; sprops = None; } let server_configure_channel_binding ss l = { (svalidity ss) with scb = l } let server_context ss = match ss.scontext with | None -> assert false | Some c -> c let server_finish ss = let user = match ss.suser with | None -> raise Not_found | Some u -> u in let authz = match ss.sauthz with | None -> raise Not_found | Some a -> a in let user_cred_opt = ss.slookup user authz in if user_cred_opt = None then failwith "unauthorized user"; let ss = server_del_ctx ss in (* no longer needed *) { ss with ssubstate = `Established; sstate = `OK } let server_create_cb_data ss authz cb = (* RFC 5801, section 5.1 *) { ss with scb_data = String.concat "" [ ( match cb with | `None -> "n," | `SASL_none_but_advertise -> "y," | `SASL_require(ty,_) -> "p=" ^ ty ^ "," | `GSSAPI _ -> assert false ); ( if authz = "" then "" else "a=" ^ Netgssapi_support.gs2_encode_saslname authz ); ","; ( match cb with | `SASL_require(_,data) -> data | _ -> "" ) ] } let server_process_response_accept_context ss msg = let (out_context, out_token, ret_flags, props_opt) = A.accept_sec_context ~context:ss.scontext ~acceptor_cred:ss.scred ~input_token:msg ~chan_bindings:(Some(`Unspecified "", `Unspecified "", ss.scb_data)) ss.sconf in let ss = svalidity { ss with scontext = Some out_context; stoken = out_token; } in if props_opt = None then { ss with sstate = `Emit } else ( let ss = { ss with sprops = props_opt } in let src_name, targ_name = G.interface # inquire_context ~context:(server_context ss) ~out:(fun ~src_name ~targ_name ~lifetime_req ~mech_type ~ctx_flags ~locally_initiated ~is_open ~minor_status ~major_status () -> server_check_gssapi_status ss "inquire_context" major_status minor_status; if mech_type <> P.mechanism_oid then failwith "the mechanism is not the selected one"; src_name, targ_name ) () in try let (targ_disp_name, targ_disp_name_type) = A.get_display_name targ_name in let ok = P.server_check_target_name ~params:ss.sparams (targ_disp_name,targ_disp_name_type) in if not ok then failwith "target name check not passed"; let (src_disp_name, src_disp_name_type) = A.get_display_name src_name in let user = try P.server_map_user_name ~params:ss.sparams (src_disp_name,src_disp_name_type) with | Not_found -> failwith "user name not acceptable" in let ss = { ss with suser = Some user } in if ss.stoken = "" then server_finish ss else ( { ss with ssubstate = `Skip_empty; sstate = `Emit } ) with | error -> ignore(server_del_ctx ss); raise error ) let itoken_re = Netstring_str.regexp "\\(F,\\)?\ \\(p=[-a-zA-Z0-9.]*\\|n\\|y\\),\ \\(a=[^,]*\\)?," let server_rewrite_initial_token ss token = match Netstring_str.string_match itoken_re token 0 with | Some m -> let is_non_std = try Netstring_str.matched_group m 1 token <> "" with Not_found -> false in let cb_str = Netstring_str.matched_group m 2 token in let cb = if cb_str = "n" then ( if P.announce_channel_binding then failwith "no channel binding from client"; `None ) else if cb_str = "y" then ( if P.announce_channel_binding then failwith "no channel binding from client"; `SASL_none_but_advertise ) else ( assert (cb_str.[0] = 'p'); if not P.announce_channel_binding then failwith "client requires channel binding"; let ty = String.sub cb_str 2 (String.length cb_str - 2) in let data = try List.assoc ty ss.scb with Not_found -> failwith "unsupported type of channel binding" in `SASL_require(ty, data) ) in let a_str = try let s = Netstring_str.matched_group m 3 token in String.sub s 2 (String.length s - 2) with Not_found -> "" in let authz = Netgssapi_support.gs2_decode_saslname a_str in let p = Netstring_str.match_end m in let token1 = String.sub token p (String.length token - p) in let token2 = if is_non_std then token1 else Netgssapi_support.wire_encode_token P.mechanism_oid token1 in (token2, authz, cb) | None -> failwith "bad initial token" let server_process_response ss msg = let ss = svalidity ss in try if ss.sstate <> `Wait then raise Not_found; match ss.ssubstate with | `Acc_context -> if ss.scontext = None then ( let (msg1, authz, cb) = server_rewrite_initial_token ss msg in let ss = { ss with sauthz = Some authz } in let ss = server_create_cb_data ss authz cb in server_process_response_accept_context ss msg1 ) else server_process_response_accept_context ss msg | `Skip_empty -> server_finish ss | `Established -> raise Not_found with | Not_found -> let ss = server_del_ctx ss in { ss with sstate = `Auth_error "unspecified" } | Failure msg -> let ss = server_del_ctx ss in { ss with sstate = `Auth_error msg } let server_process_response_restart ss msg set_stale = failwith "Netmech_gs2_sasl.server_process_response_restart: \ not available" let server_emit_challenge ss = if ss.sstate <> `Emit then failwith "Netmech_gs2_sasl.server_emit_challenge: bad state"; let ss = { (svalidity ss) with sstate = `Wait } in (ss, ss.stoken) let server_channel_binding ss = `None let server_stash_session ss = (* GSSAPI does not support that unfinished contexts are exported. We do not need the context anyway after session establishment, so we don't save it at all. *) if ss.sstate <> `OK then failwith "Netmech_gs2_sasl.server_stash_session: the session \ must be established (implementation restriction)"; "server,t=GS2;" ^ Marshal.to_string (ss.suser, ss.sauthz, ss.sparams, ss.scb, map_opt Netsys_gssapi.marshal_server_props ss.sprops) [] let ss_re = Netstring_str.regexp "server,t=GS2;" let server_resume_session ~lookup s = match Netstring_str.string_match ss_re s 0 with | None -> failwith "Netmech_gs2_sasl.server_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let (suser, sauthz, sparams, scb, mprops) = Marshal.from_string data 0 in { scontext = None; sstate = `OK; ssubstate = `Established; stoken = ""; suser; sauthz; slookup = lookup; sparams; sconf = Netsys_gssapi.create_server_config(); scred = G.interface#no_credential; scb_data = ""; scb; sprops = map_opt Netsys_gssapi.unmarshal_server_props mprops; } let server_session_id ss = None let server_prop ss key = raise Not_found let server_gssapi_props ss = match ss.sprops with | None -> raise Not_found | Some p -> p let server_user_name ss = if ss.sstate <> `OK then raise Not_found; match ss.suser with | None -> assert false | Some u -> u let server_authz_name ss = if ss.sstate <> `OK then raise Not_found; match ss.sauthz with | None -> assert false | Some u -> u end (* Works only when "test" is added to /etc/services! ktadmin > addprinc -randkey test/office1.lan.sumadev.de > ktadd -k test.keytab test/office1.lan.sumadev.de KRB5_KTNAME=test.keytab OCAMLPATH=src ledit ocaml #use "topfind";; #require "netstring,netgss-system";; open Printf;; module S = Netmech_krb5_sasl.Krb5_gs2(Netgss.System);; let no_creds = S.init_credentials [];; let cs = S.create_client_session ~user:"" ~authz:"foo" ~creds:no_creds ~params:[ "gssapi-acceptor", "test@office1.lan.sumadev.de", false ] ();; let lookup user authz = eprintf "user=%S authz=%S\n%!" user authz; Some no_creds;; let ss = S.create_server_session ~lookup ~params:["gssapi-acceptor-service", "test", false ] ();; let cs, msg1 = S.client_emit_response cs;; let ss = S.server_process_response ss msg1;; let ss, msg2 = S.server_emit_challenge ss;; let cs = S.client_process_challenge cs msg2;; let cs, msg3 = S.client_emit_response cs;; assert(S.client_state cs = `OK);; let ss = S.server_process_response ss msg3;; assert(S.server_state ss = `OK);; *) ocamlnet-4.1.2/src/netstring/netoid.ml0000644000175000017500000000423712731530350016371 0ustar gerdgerd(* $Id$ *) type t = int array let equal oid1 oid2 = (oid1 = oid2) let compare oid1 oid2 = let l1 = Array.length oid1 in let l2 = Array.length oid2 in let rec cmp k = if k >= l1 || k >= l2 then if k >= l1 then ( if k >= l2 then 0 else (-1) ) else (* k >= l2 *) 1 else let p = oid1.(k) - oid2.(k) in if p = 0 then cmp (k+1) else p in cmp 0 let dec_re = Netstring_str.regexp "^[0-9]+$" let int_of_decimal s = match Netstring_str.string_match dec_re s 0 with | Some _ -> int_of_string s | None -> raise Not_found let split_re = Netstring_str.regexp "[.]" let of_string s = try Array.of_list (List.map int_of_decimal (Netstring_str.split split_re s)) with _ -> failwith "Netoid.of_string" let to_string oid = String.concat "." (List.map string_of_int (Array.to_list oid)) (* Curly notation follows RFC 2078, but additional information about DER can also be found in ITU-T X.690: http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf *) let of_string_curly s = let oid_str_re = Netstring_str.regexp "[ \t\r\n]+\\|{\\|}" in let rec cont1 l = match l with | Netstring_str.Delim "{" :: l' -> cont2 l' | Netstring_str.Delim "}" :: _ -> raise Not_found | Netstring_str.Delim _ :: l' -> cont1 l' (* whitespace *) | _ -> raise Not_found and cont2 l = (* after "{" *) match l with | Netstring_str.Delim "{" :: _ -> raise Not_found | Netstring_str.Delim "}" :: l' -> cont3 l' | Netstring_str.Delim _ :: l' -> cont2 l' | Netstring_str.Text s :: l' -> int_of_string s :: cont2 l' | _ -> raise Not_found and cont3 l = (* after "}" *) match l with | Netstring_str.Delim ("{" | "}") :: _ -> raise Not_found | Netstring_str.Delim _ :: l' -> cont3 l' | [] -> [] | _ -> raise Not_found in let l = Netstring_str.full_split oid_str_re s in try Array.of_list(cont1 l) with | _ -> failwith "Netoid.of_string_curly" let to_string_curly oid = "{" ^ String.concat " " (List.map string_of_int (Array.to_list oid)) ^ "}" ocamlnet-4.1.2/src/netstring/netaddress.mli0000644000175000017500000000513112731530350017406 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Parsing of mail addresses *) (** Addresses indicate the senders and recipients of messages and * correspond to either an individual mailbox or a group of * mailboxes. *) type local_part = string (** Usually the user name *) type domain = string (** The domain of the mailbox *) type addr_spec = local_part * domain option (** The pair [local_part\@domain] as O'Caml type. The domain may be * missing. *) (** A [mailbox] has a name, optionally a route (not used nowadays), and * a formal address specification. * * Create a [mailbox] with * * [ new mailbox ~name route addr_spec ] * * Pass [route = []] if not used (formerly, routes were used to specify * the way the mail should take from the sender to the receiver, and * contained a list of hostnames/IP addresses). *) class mailbox : ?name:string -> string list -> addr_spec -> object method name : string (** The name of the mailbox. Raises [Not_found] if not set *) method route : string list (** The route to the mailbox *) method spec : addr_spec (** The formal address specification *) end (** A [group] has a name, and consists of a number of mailboxes. * * Create a group with [new group name mailboxes]. *) class group : string -> mailbox list -> object method name : string (** The name of the group *) method mailboxes : mailbox list (** The member mailboxes *) end (** The union of [mailbox] and [group] *) type t = [ `Mailbox of mailbox | `Group of group ] exception Parse_error of int * string (** A parsing error. The [int] is the position in the parsed string *) val parse : string -> t list (** Parse a list of addresses in string representation, and return * them as list of mailboxes or groups. * * Examples: * - [parse "gerd\@gerd-stolpmann.de"] returns a single [mailbox] * without name and route, and the given spec * - [parse "Gerd Stolpmann "] returns a * single [mailbox] with name and spec, but without route * - [parse "abc\@def.net, ghi"] returns two [mailbox]es without * name and route, and the two specs. The second address only * has a local part, but no domain. * - [parse "g:abc\@def.net, Me ;, gs\@npc.de"] * returns one group [g] with members [abc\@def.net] and * [me\@domain.net], and another [mailbox] [gs\@npc.de]. * * Old-style naming of mailboxes is not supported * (e.g. "gerd\@gerd-stolpmann.de (Gerd Stolpmann)" - the part * in parentheses is simply ignored. *) ocamlnet-4.1.2/src/netstring/netmappings.mli0000644000175000017500000000374312731530350017606 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- *) (** Internal access to the character conversion database * * This is an internal module. *) type from_uni_list = U_nil | U_single of (int*int) | U_double of (int*int * int*int) | U_array of int array ;; (* A representation of (int*int) list that is optimized for the case that * lists with 0 and 1 and 2 elements are the most frequent cases. *) val get_to_unicode : string -> int array val get_from_unicode : string -> from_uni_list array (* These functions get the conversion tables from local encodings to * Unicode and vice versa. * It is normally not necessary to access these tables; the * Netconversion module does it already for you. * * The argument is the internal name of the encoding. (E.g. if * encoding = `Enc_iso88591, the internal name is "iso88591", i.e. * the "`Enc_" prefix is removed. However, for "composite encodings" * like `Enc_eucjp things are more complicated.) * * Specification of the conversion tables: * * to_unicode: maps a local code to Unicode, i.e. * let m = Hashtbl.find `Enc_isoXXX to_unicode in * let unicode = m.(isocode) * - This may be (-1) to indicate that the code point is not defined. * * from_unicode: maps Unicode to a local code, i.e. * let m = Hashtbl.find `Enc_isoXXX from_unicode in * let l = m.(unicode land mask) * Now search in l the pair (unicode, isocode), and return isocode. * Where mask = Array.length from_unicode - 1 *) val lock : unit -> unit (* In multi-threaded applications: obtains a lock which is required to * Lazy.force the values found in to_unicode and from_unicode. * In single-threaded applications: a NO-OP *) val unlock : unit -> unit (* In multi-threaded applications: releases the lock which is required to * Lazy.force the values found in to_unicode and from_unicode. * In single-threaded applications: a NO-OP *) ocamlnet-4.1.2/src/netstring/netulex.mli0000644000175000017500000002455112731530350016745 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * PXP: The polymorphic XML parser for Objective Caml. * Copyright by Gerd Stolpmann. See LICENSE for details. *) (** Support module for Alain Frisch's [ulex] lexer generator * * The sub module [ULB] is a Unicode-based lexing buffer that * reads encoded strings and makes them available to the lexer * as both Unicode arrays and UTF-8 strings. * * The sub module [Ulexing] is a replacement for the module * in [ulex] with the same name. It uses [ULB] to represent * the main lexing buffer. It is much faster than the original * [Ulexing] implementation when the scanned text is UTF-8 * encoded and [Ulexing.utf8_lexeme] is frequently called to * get the lexeme strings. Furthermore, it can process input * data of all encodings available to [Netconversion]. It is, * however, no drop-in replacement as it has a different * signature. * * To enable this version of [Ulexing], simply put an * [open Netulex] before using the [ulex] lexers. * * Note that the tutorial has been moved to {!Netulex_tut}. *) (** {1:modules Modules} *) module ULB : sig (** This module provides the [unicode_lexbuf] record with * access functions. In this record, the data is available * in two forms: As an array of Unicode code points * [ulb_chars], and as string of encoded chars [ulb_rawbuf]. * Both buffers are synchronised by [ulb_chars_pos]. This * array stores where every character of [ulb_chars] can be * found in [ulb_rawbuf]. *) type unicode_lexbuf = private { mutable ulb_encoding : Netconversion.encoding; (** The character encoding of [ulb_rawbuf] *) mutable ulb_encoding_start : int; (** The first character position to which [ulb_encoding] * applies (the encoding of earlier positions is * lost) *) mutable ulb_rawbuf : Bytes.t; (** The encoded string to analyse *) mutable ulb_rawbuf_len : int; (** The filled part of [ulb_rawbuf] *) mutable ulb_rawbuf_end : int; (** The analysed part of [ulb_rawbuf]. We have always * [ulb_rawbuf_end <= ulb_rawbuf_len]. The analysed part * may be shorter than the filled part because there is * not enough space in [ulb_chars], or because the filled * part ends with an incomplete multi-byte character *) mutable ulb_rawbuf_const : bool; (** Whether [ulb_rawbuf] is considered as a constant. If * [true], it is never blitted. *) mutable ulb_chars : int array; (** The analysed part of [ulb_rawbuf] as array of Unicode * code points. Only the positions 0 to [ulb_chars_len-1] * of the array are filled. *) mutable ulb_chars_pos : int array; (** For every analysed character this array stores the * byte position where the character begins in [ulb_rawbuf]. * In addition, the array contains at [ulb_chars_len] the * value of [ulb_rawbuf_end]. * * This array is one element longer than [ulb_chars]. *) mutable ulb_chars_len : int; (** The filled part of [ulb_chars] *) mutable ulb_eof : bool; (** Whether EOF has been seen *) mutable ulb_refill : Bytes.t -> int -> int -> int; (** The refill function *) mutable ulb_enc_change_hook : unicode_lexbuf -> unit; (** This function is called when the encoding changes *) mutable ulb_cursor : Bytes.t Netconversion.poly_cursor; (** Internally used by the implementation *) } val from_function : ?raw_size:int -> ?char_size:int -> ?enc_change_hook:(unicode_lexbuf -> unit) -> refill:(Bytes.t -> int -> int -> int) -> Netconversion.encoding -> unicode_lexbuf (** Creates a [unicode_lexbuf] to analyse strings of the * passed [encoding] coming from the [refill] function. * * @param raw_size The initial size for [ulb_rawbuf]. Defaults to 512 * @param char_size The initial size for [ulb_chars]. Defaults to 256 * @param enc_change_hook This function is called when the encoding * is changed, either by this module, or by the user calling * [set_encoding]. * @param refill This function is called with arguments [ulb_rawbuf], * [ulb_rawbuf_len], and [l], where * [l = String.length ulb_rawbuf - ulb_rawbuf_len] is the free * space in the buffer. The function should fill new bytes into * this substring, and return the number of added bytes. The * return value 0 signals EOF. *) val from_in_obj_channel : ?raw_size:int -> ?char_size:int -> ?enc_change_hook:(unicode_lexbuf -> unit) -> Netconversion.encoding -> Netchannels.in_obj_channel -> unicode_lexbuf (** Creates a [unicode_lexbuf] to analyse strings of the * passed [encoding] coming from the object channel. * * @param raw_size The initial size for [ulb_rawbuf]. Defaults to 512 * @param char_size The initial size for [ulb_chars]. Defaults to 256 * @param enc_change_hook This function is called when the encoding * is changed, either by this module, or by the user calling * [set_encoding]. *) val from_string : ?enc_change_hook:(unicode_lexbuf -> unit) -> Netconversion.encoding -> string -> unicode_lexbuf (** Creates a [unicode_lexbuf] analysing the passed string encoded in * the passed encoding. This function copies the input string. * * @param enc_change_hook This function is called when the encoding * is changed, either by this module, or by the user calling * [set_encoding] *) val from_bytes : ?enc_change_hook:(unicode_lexbuf -> unit) -> Netconversion.encoding -> Bytes.t -> unicode_lexbuf (** Same for bytes *) val from_bytes_inplace : ?enc_change_hook:(unicode_lexbuf -> unit) -> Netconversion.encoding -> Bytes.t -> unicode_lexbuf (** Creates a [unicode_lexbuf] analysing the passed string encoded in * the passed encoding. This function does not copy the input string, * but uses it directly as [ulb_rawbuf]. The string is not modified by [ULB], * but the caller must ensure that other program parts do not * modify it either. * * @param enc_change_hook This function is called when the encoding * is changed, either by this module, or by the user calling * [set_encoding] *) (** Regarding [from_string_inplace], this function has been removed as strings are now considered immutable. *) val delete : int -> unicode_lexbuf -> unit (** Deletes the number of characters from [unicode_lexbuf]. * These characters * are removed from the beginning of the buffer, i.e. * [ulb_chars.(n)] becomes the new first character of the * buffer. All three buffers [ulb_rawbuf], [ulb_chars], and * [ulb_chars_pos] are blitted as necessary. * * When the buffer is already at EOF, the function fails. * * For efficiency, it should be tried to call [delete] as seldom as * possible. Its speed is linear to the number of characters to move. *) val refill : unicode_lexbuf -> unit (** Tries to add characters to the [unicode_lexbuf] by calling the * [ulb_refill] function. When the buffer is already at EOF, the * exception [End_of_file] is raised, and the buffer is not modified. * Otherwise, the [ulb_refill] function is called to * add new characters. If necessary, [ulb_rawbuf], [ulb_chars], and * [ulb_chars_pos] are enlarged such that it is ensured that either * at least one new character is added, or that EOF is found for * the first time * In the latter case, [ulb_eof] is set to [true] (and the next call * of [refill_unicode_lexbuf] will raise [End_of_file]). *) val set_encoding : Netconversion.encoding -> unicode_lexbuf -> unit (** Sets the [encoding] to the passed value. This only affects future * [refill] calls. The hook [enc_change_hook] is invoked when defined. *) val close : unicode_lexbuf -> unit (** Sets [ulb_eof] of the [unicode_lexbuf]. The rest of the buffer * is not modified *) val utf8_sub_string : int -> int -> unicode_lexbuf -> string (** The two [int] arguments are the position and length of a sub * string of the lexbuf that is returned as UTF8 string. Position * and length are given as character multiples, not byte multiples. *) val utf8_sub_string_length : int -> int -> unicode_lexbuf -> int (** Returns [String.length(utf8_sub_string args)]. Tries not to * allocate the UTF-8 string. *) end (* module ULB *) module Ulexing : sig (** This is a lexing buffer for [ulex]. *) type lexbuf exception Error (** Lexical error *) val from_ulb_lexbuf : ULB.unicode_lexbuf -> lexbuf (** Creates a new [lexbuf] from the [unicode_lexbuf]. After that, * the [unicode_lexbuf] must no longer be modified. *) val lexeme_start: lexbuf -> int (** The character position of the start of the lexeme *) val lexeme_end: lexbuf -> int (** The character position of the end of the lexeme *) val lexeme_length: lexbuf -> int (** The length of the lexeme in characters *) val lexeme: lexbuf -> int array (** Returns the lexeme as array of Unicode code points *) val lexeme_char: lexbuf -> int -> int (** Returns the code point of a certain character of the * lexeme *) val sub_lexeme: lexbuf -> int -> int -> int array (** Returns a substring of the lexeme as array of Unicode * code points. The first [int] is the characater position * where to start, the second [int] is the number of * characters. *) val utf8_lexeme: lexbuf -> string (** Returns the lexeme as UTF-8 encoded string *) val utf8_sub_lexeme: lexbuf -> int -> int -> string (** Returns a substring of the lexeme as UTF-8 encoded * string. The first [int] is the characater position * where to start, the second [int] is the number of * characters. *) val utf8_sub_lexeme_length: lexbuf -> int -> int -> int (** Same as * String.length(utf8_sub_lexeme args), i.e. returns * the number of bytes a certain sub lexeme will have * when encoded as UTF-8 string. *) (**/**) (* "Internal" interface. This must match ulex's ones. *) val start: lexbuf -> unit val next: lexbuf -> int val mark: lexbuf -> int -> unit val backtrack: lexbuf -> int end ocamlnet-4.1.2/src/netstring/netmime_channels.ml0000644000175000017500000002047612731530350020423 0ustar gerdgerd(* $Id$ *) open Netmime open Netchannels let read_mime_header ?(unfold=false) ?(strip=true) ?(ro=false) stream = let h = Netmime_string.read_header ~downcase:false ~unfold ~strip stream in let hobj = new basic_mime_header h in if ro then wrap_mime_header_ro hobj else hobj ;; type multipart_style = [ `None | `Flat | `Deep ] ;; let decode_mime_body hdr = let encoding = try Netmime_header.get_content_transfer_encoding hdr with Not_found -> "7bit" in match encoding with ("7bit"|"8bit"|"binary") -> (fun s -> s) | "base64" -> (fun s -> new output_filter (new Netencoding.Base64.decoding_pipe ~accept_spaces:true ()) s) | "quoted-printable" -> (fun s -> new output_filter (new Netencoding.QuotedPrintable.decoding_pipe()) s) | _ -> failwith "Netmime.decode_mime_body: Unknown Content-transfer-encoding" ;; let encode_mime_body ?(crlf = true) hdr = let encoding = try Netmime_header.get_content_transfer_encoding hdr with Not_found -> "7bit" in match encoding with ("7bit"|"8bit"|"binary") -> (fun s -> s) | "base64" -> (fun s -> new output_filter (new Netencoding.Base64.encoding_pipe ~linelength:76 ~crlf ()) s) | "quoted-printable" -> (fun s -> new output_filter (new Netencoding.QuotedPrintable.encoding_pipe ~crlf ()) s) | _ -> failwith "Netmime.encode_mime_body: Unknown Content-transfer-encoding" ;; let storage ?fin : store -> (mime_body * out_obj_channel) = function `Memory -> let body = new memory_mime_body "" in let body_ch = body#open_value_wr() in body, body_ch | `File filename -> let body = new file_mime_body ?fin filename in let body_ch = body#open_value_wr() in body, body_ch ;; let rec read_mime_message1 ?unfold ?strip ?(multipart_style = (`Deep : multipart_style)) ?(storage_style = fun _ -> storage `Memory) stream : complex_mime_message = (* First read the header: *) let h_obj = read_mime_header ?unfold ?strip ~ro:false stream in let mime_type, mime_type_params = try Netmime_header.get_content_type h_obj with Not_found -> "", [] in let multipart = "multipart/" in let is_multipart_type = (String.length mime_type >= String.length multipart) && (String.sub mime_type 0 (String.length multipart) = multipart) in (* Now parse the body, (with multiparts or without) *) let body = if is_multipart_type && multipart_style <> `None then begin (* --- Divide the message into parts: --- *) let boundary = try List.assoc "boundary" mime_type_params with Not_found -> failwith "Netmime.read_mime_message: missing boundary parameter" in let multipart_style = (* of the sub parser *) if multipart_style = `Flat then `None else multipart_style in `Parts (Netmime_string.read_multipart_body (read_mime_message1 ~multipart_style ~storage_style) (Netmime_string.param_value boundary) stream ) end else begin (* --- Read the body and optionally decode it: --- *) (* Where to store the body: *) let decoder = decode_mime_body h_obj in let body, body_ch = storage_style h_obj in if with_out_obj_channel (decoder body_ch) (fun body_ch' -> body_ch' # output_channel (stream :> in_obj_channel); body_ch' <> body_ch ) then body_ch # close_out(); `Body body end in (h_obj, body) ;; let read_mime_message ?unfold ?strip ?(ro=false) ?multipart_style ?storage_style stream = let msg = read_mime_message1 ?unfold ?strip ?multipart_style ?storage_style stream in if ro then wrap_complex_mime_message_ro (msg :> complex_mime_message_ro) else msg let rec augment_message (hdr,cbody) = (* Computes the content-transfer-encoding field for multipart messages. * The resulting message uses `Parts_ag(cte,parts) instead of `Parts(parts) * where cte is the content-transfer-encoding field. *) match cbody with `Body _ as b -> (hdr,b) | `Parts p -> let p' = List.map augment_message p in let mp_cte_id = List.fold_left (fun x (hdr,body) -> let cte = match body with `Body _ -> (try Netmime_header.get_content_transfer_encoding hdr with Not_found -> "7bit") | `Parts_ag(cte,_) -> cte in let cte_id = match cte with "7bit" | "quoted-printable" | "base64" -> 0 | "8bit" -> 1 | _ -> 2 in max x cte_id ) 0 p' in let mp_cte = match mp_cte_id with 0 -> "7bit" | 1 -> "8bit" | 2 -> "binary" | _ -> assert false in (hdr, `Parts_ag(mp_cte,p')) ;; let rec write_mime_message_int ?(wr_header = true) ?(wr_body = true) ?(nr = 0) ?ret_boundary ?(crlf = true) outch (hdr,cbody) = let eol = if crlf then "\r\n" else "\n" in let mk_boundary parts = (* For performance reasons, gather random data only from the first * `Body *) let rec gather_data parts = match parts with (_,`Body body) :: parts' -> let s = Bytes.make 240 ' ' in (* So it is in the minor heap *) with_in_obj_channel (body # open_value_rd()) (fun ch -> try ignore(ch # input s 0 240) with End_of_file -> () (* When body is empty *) ); [Bytes.unsafe_to_string s] | (_,`Parts_ag(_, parts'')) :: parts' -> (try gather_data parts'' with Not_found -> gather_data parts') | [] -> raise Not_found in let data = try gather_data parts with Not_found -> [] in Netmime_string.create_boundary ~random:data ~nr () in match cbody with `Body body -> (* Write the header as it is, and append the body *) if wr_header then Netmime_string.write_header ~eol ~soft_eol:eol outch hdr#fields; if wr_body then begin let outch' = encode_mime_body ~crlf hdr outch in with_in_obj_channel (body # open_value_rd()) (fun bodych -> outch' # output_channel bodych); if outch' <> outch then outch' # close_out(); end | `Parts_ag(cte,parts) -> if parts = [] then failwith "Netmime.write_mime_message: Cannot write multipart message with empty list of parts"; (* If the header does not include a proper content-type field, repair * this now. *) let hdr' = new basic_mime_header hdr#fields in (* hdr' will contain the repaired header as side effect *) let boundary = try let ctype,params = try Netmime_header.get_content_type hdr (* or Not_found *) with Not_found as ex -> raise ex (* falls through to next [try] *) | ex -> failwith ("Netmime.write_mime_message: Cannot parse content-type field: " ^ Netexn.to_string ex) in if String.length ctype < 10 || String.sub ctype 0 10 <> "multipart/" then failwith "Netmime.write_mime_message: The content type of a multipart message must be 'multipart/*'"; try let b = List.assoc "boundary" params in (* or Not_found *) Netmime_string.param_value b with Not_found -> (* Add the missing boundary parameter: *) let b = mk_boundary parts in let ctype_field = hdr # field "content-type" ^ ";" ^ eol ^ " boundary=\"" ^ b ^ "\"" in hdr' # update_field "content-type" ctype_field; b with Not_found -> (* Add the missing content-type header: *) let b = mk_boundary parts in let ctype_field = "multipart/mixed;" ^ eol ^ " boundary=\"" ^ b ^ "\"" in hdr' # update_field "content-type" ctype_field; b in (* Now fix the content-transfer-encoding field *) hdr' # update_field "content-transfer-encoding" cte; (* Write now the header fields *) if wr_header then Netmime_string.write_header ~eol ~soft_eol:eol outch hdr'#fields; (* Write the parts: *) if wr_body then begin let boundary_string = "--" ^ boundary ^ eol in List.iter (fun part -> outch # output_string boundary_string; write_mime_message_int ~wr_header:true ~wr_body:true ~nr:(nr + 1) ~crlf outch part; outch # output_string eol; ) parts; outch # output_string ("--" ^ boundary ^ "--" ^ eol); end; ( match ret_boundary with None -> () | Some r -> r := boundary ) ;; let write_mime_message ?wr_header ?wr_body ?nr ?ret_boundary ?crlf ch msg = write_mime_message_int ?wr_header ?wr_body ?nr ?ret_boundary ?crlf ch (augment_message msg) ;; ocamlnet-4.1.2/src/netstring/netstring_str.mli0000644000175000017500000001672612731530350020173 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Wrapper for regexps with [Str] syntax * * This module was written at a time when we had only the [Str] module * for regular expressions. However, [Str] has an interface that does * not work for multi-threaded programs, because the state of the module * is visible to the outside. The module [Netstring_str] is similar to [Str], * but has a thread-compatible interface. * * For an explanation why we need this module, please read {!Regexp}. *) (** {b Supported regexp syntax} * * {[ * . matches every character but newline * e* matches e several times * e+ matches e several times but at least once * e? matches e optionally * e{m,n} matches e at least m times and at most n times * e1\|e2 matches e1 or e2 * [set] matches the characters from set * [^set] matches the characters except from set * \(...\) group paranthesis * \n back reference (n is digit) * ^ matches at beginning of line * $ matches at end of line * ]} * * This is exactly what [Str] supports. Character classes * are not implemented. *) type regexp (** The type of regular expressions *) type split_result = Str.split_result = Text of string | Delim of string;; (** Here we keep compatibility with [Str] *) type result;; (** The type of matching results *) val regexp: string -> regexp (** Parses a regexp *) val regexp_case_fold: string -> regexp (** Parses a case-insensitive regexp *) val quote: string -> string (** Quotes a string such that it can be included in a regexp *) val regexp_string: string -> regexp (** Returns a regexp that matches exactly the string *) val regexp_string_case_fold: string -> regexp (** Returns a case-insensitive regexp that matches exactly the string *) val quote_set : string -> string (** Returns a regexp (as string) that matches any of the characters in the argument. The argument must be non-empty *) val string_match: regexp -> string -> int -> result option (** Matches the string at the position with the regexp. Returns * [None] if no match is found. Returns [Some r] on success, * and [r] describes the match. *) val bytes_match: regexp -> Bytes.t -> int -> result option (** Same for bytes *) val search_forward: regexp -> string -> int -> (int * result) (** Searches a match of the string with the regexp, starting at * the position and in forward direction. * Raises [Not_found] if no match could be found. * Returns [(p,r)] when a match at position [p] is found, * described by [r]. *) val search_forward_bytes: regexp -> Bytes.t -> int -> (int * result) (** Same for bytes *) val search_backward: regexp -> string -> int -> (int * result) (** Searches a match of the string with the regexp, starting at * the position and in backward direction. * Raises [Not_found] if no match could be found. * Returns [(p,r)] when a match at position [p] is found, * described by [r]. *) val search_backward_bytes : regexp -> Bytes.t -> int -> (int * result) (** Same for bytes *) (* NOT SUPPORTED: * * val string_partial_match: * ?groups:int -> pat:regexp -> string -> pos:int -> result option * * The function [string_partial_match] cannot be emulated using PCRE. *) val matched_string : result -> string -> string (** Extracts the matched part from the string. The string argument * must be the same string passed to [string_match] or the search * functions, and the result argument must be the corresponding * result. *) val matched_bytes : result -> Bytes.t -> Bytes.t (** Same for bytes *) val match_beginning : result -> int (** Returns the position where the matched part begins *) val match_end : result -> int (** Returns the position where the matched part ends *) val matched_group : result -> int -> string -> string (** Extracts the substring the nth group matches from the whole * string. The string argument * must be the same string passed to [string_match] or the search * functions, and the result argument must be the corresponding * result. *) val matched_group_bytes : result -> int -> Bytes.t -> Bytes.t (** Same for bytes *) val group_beginning : result -> int -> int (** Returns the position where the substring matching the nth * group begins *) val group_end : result -> int -> int (** Returns the position where the substring matching the nth * group ends *) val global_replace: regexp -> (*templ:*) string -> string -> string (** [global_replace re templ s]: Replaces all matchings of [re] in * [s] by [templ]. * * In [templ] one can refer to matched groups by the backslash notation: * [\1] refers to the first group, [\2] to the second etc. * [\0] is the whole match. [\\ ] is the backslash character. *) val replace_first: regexp -> (*templ:*) string -> string -> string (** [replace_first re templ s]: Replaces the first match of [re] in * [s] by [templ]. * * In [templ] one can refer to matched groups by the backslash notation: * [\1] refers to the first group, [\2] to the second etc. * [\0] is the whole match. [\\ ] is the backslash character. *) val global_substitute : regexp -> (result -> string -> string) -> string -> string (** [global_substitute re subst s]: Applies the substitution function * [subst] to all matchings of [re] in [s], and returns the * transformed string. [subst] is called with the current [result] * of the match and the whole string [s]. *) val substitute_first: regexp -> (result -> string -> string) -> string -> string (** [substitute_first re subst s]: Applies the substitution function * [subst] to the first matching of [re] in [s], and returns the * transformed string. [subst] is called with the current [result] * of the match and the whole string [s]. *) (* replace_matched: not available *) val split: regexp -> string -> string list (** Splits the string according to the regexp in substrings. * Occurrences of the delimiter at the beginning and the end * are ignored. *) val bounded_split: regexp -> string -> int -> string list (** Splits into at most [n] substrings, based on [split] *) val split_delim: regexp -> string -> string list (** Same as [split], but occurrences of the delimiter at the beginning * and the end are returned as empty strings *) val bounded_split_delim: regexp -> string -> int -> string list (** Splits into at most [n] substrings, based on [split_delim] *) val full_split: regexp -> string -> split_result list (** Like [split_delim], but returns the delimiters in the result *) val bounded_full_split: regexp -> string -> int -> split_result list (** Splits into at most [n] substrings, based on [full_split] *) val string_before: string -> int -> string (** The first [n] characters of a string *) val string_after: string -> int -> string (** The last [n] characters of a string *) val first_chars: string -> int -> string (** Same as [string_before] *) val last_chars: string -> int -> string (** Same as [string_after] *) (* Private: *) (* NOT NECESSARY: * val init_mt : (unit -> unit) -> (unit -> unit) -> unit * In previous versions of Netstring_str it was necessary to intialize the * module in a special way when used in multi-threaded environment. This * is no longer necessary. *) module Debug : sig val enable : bool ref end ocamlnet-4.1.2/src/netstring/netsaslprep_data.ml0000644000175000017500000050325612731530350020445 0ustar gerdgerd(* Generated file! *) let exclusions = [| 2392; 2393; 2394; 2395; 2396; 2397; 2398; 2399; 2524; 2525; 2527; 2611; 2614; 2649; 2650; 2651; 2654; 2908; 2909; 3907; 3917; 3922; 3927; 3932; 3945; 3958; 3960; 3987; 3997; 4002; 4007; 4012; 4025; 64285; 64287; 64298; 64299; 64300; 64301; 64302; 64303; 64304; 64305; 64306; 64307; 64308; 64309; 64310; 64312; 64313; 64314; 64315; 64316; 64318; 64320; 64321; 64323; 64324; 64326; 64327; 64328; 64329; 64330; 64331; 64332; 64333; 64334; 10972; 119134; 119135; 119136; 119137; 119138; 119139; 119140; 119227; 119228; 119229; 119230; 119231; 119232 |] let cano_classes = [| -1; 820; 821; 822; 823; 824; 8402; 8403; 8408; 8409; 8410; 8421; 8422; 8426; 119143; 119144; 119145; -7; 2364; 2492; 2620; 2748; 2876; 4151; -8; 12441; 12442; -9; 2381; 2509; 2637; 2765; 2893; 3021; 3149; 3277; 3405; 3530; 3642; 3972; 4153; 5908; 5940; 6098; -10; 1456; -11; 1457; -12; 1458; -13; 1459; -14; 1460; -15; 1461; -16; 1462; -17; 1463; -18; 1464; -19; 1465; -20; 1467; -21; 1468; -22; 1469; -23; 1471; -24; 1473; -25; 1474; -26; 64286; -27; 1611; -28; 1612; -29; 1613; -30; 1614; -31; 1615; -32; 1616; -33; 1617; -34; 1618; -35; 1648; -36; 1809; -84; 3157; -91; 3158; -103; 3640; 3641; -107; 3656; 3657; 3658; 3659; -118; 3768; 3769; -122; 3784; 3785; 3786; 3787; -129; 3953; -130; 3954; 3962; 3963; 3964; 3965; 3968; -132; 3956; -202; 801; 802; 807; 808; -216; 795; 3897; 119141; 119142; 119150; 119151; 119152; 119153; 119154; -218; 12330; -220; 790; 791; 792; 793; 796; 797; 798; 799; 800; 803; 804; 805; 806; 809; 810; 811; 812; 813; 814; 815; 816; 817; 818; 819; 825; 826; 827; 828; 839; 840; 841; 845; 846; 1425; 1430; 1435; 1443; 1444; 1445; 1446; 1447; 1450; 1621; 1763; 1770; 1773; 1841; 1844; 1847; 1848; 1849; 1851; 1852; 1854; 1858; 1860; 1862; 1864; 2386; 3864; 3865; 3893; 3895; 4038; 8424; 119163; 119164; 119165; 119166; 119167; 119168; 119169; 119170; 119178; 119179; -222; 1434; 1453; 12333; -224; 12334; 12335; -226; 119149; -228; 1454; 6313; 12331; -230; 768; 769; 770; 771; 772; 773; 774; 775; 776; 777; 778; 779; 780; 781; 782; 783; 784; 785; 786; 787; 788; 829; 830; 831; 832; 833; 834; 835; 836; 838; 842; 843; 844; 867; 868; 869; 870; 871; 872; 873; 874; 875; 876; 877; 878; 879; 1155; 1156; 1157; 1158; 1426; 1427; 1428; 1429; 1431; 1432; 1433; 1436; 1437; 1438; 1439; 1440; 1441; 1448; 1449; 1451; 1452; 1455; 1476; 1619; 1620; 1750; 1751; 1752; 1753; 1754; 1755; 1756; 1759; 1760; 1761; 1762; 1764; 1767; 1768; 1771; 1772; 1840; 1842; 1843; 1845; 1846; 1850; 1853; 1855; 1856; 1857; 1859; 1861; 1863; 1865; 1866; 2385; 2387; 2388; 3970; 3971; 3974; 3975; 8400; 8401; 8404; 8405; 8406; 8407; 8411; 8412; 8417; 8423; 8425; 65056; 65057; 65058; 65059; 119173; 119174; 119175; 119176; 119177; 119210; 119211; 119212; 119213; -232; 789; 794; 12332; -233; 866; -234; 864; 865; -240; 837 |] let decompositions = [| -321; 32; -337; 32; 776; -341; 97; -351; 32; 772; -357; 50; -359; 51; -361; 32; 769; -363; 956; -369; 32; 807; -371; 49; -373; 111; -377; 49; 8260; 52; -379; 49; 8260; 50; -381; 51; 8260; 52; -384; 65; 768; -386; 65; 769; -388; 65; 770; -390; 65; 771; -392; 65; 776; -394; 65; 778; -398; 67; 807; -400; 69; 768; -402; 69; 769; -404; 69; 770; -406; 69; 776; -408; 73; 768; -410; 73; 769; -412; 73; 770; -414; 73; 776; -418; 78; 771; -420; 79; 768; -422; 79; 769; -424; 79; 770; -426; 79; 771; -428; 79; 776; -434; 85; 768; -436; 85; 769; -438; 85; 770; -440; 85; 776; -442; 89; 769; -448; 97; 768; -450; 97; 769; -452; 97; 770; -454; 97; 771; -456; 97; 776; -458; 97; 778; -462; 99; 807; -464; 101; 768; -466; 101; 769; -468; 101; 770; -470; 101; 776; -472; 105; 768; -474; 105; 769; -476; 105; 770; -478; 105; 776; -482; 110; 771; -484; 111; 768; -486; 111; 769; -488; 111; 770; -490; 111; 771; -492; 111; 776; -498; 117; 768; -500; 117; 769; -502; 117; 770; -504; 117; 776; -506; 121; 769; -510; 121; 776; -512; 65; 772; -514; 97; 772; -516; 65; 774; -518; 97; 774; -520; 65; 808; -522; 97; 808; -524; 67; 769; -526; 99; 769; -528; 67; 770; -530; 99; 770; -532; 67; 775; -534; 99; 775; -536; 67; 780; -538; 99; 780; -540; 68; 780; -542; 100; 780; -548; 69; 772; -550; 101; 772; -552; 69; 774; -554; 101; 774; -556; 69; 775; -558; 101; 775; -560; 69; 808; -562; 101; 808; -564; 69; 780; -566; 101; 780; -568; 71; 770; -570; 103; 770; -572; 71; 774; -574; 103; 774; -576; 71; 775; -578; 103; 775; -580; 71; 807; -582; 103; 807; -584; 72; 770; -586; 104; 770; -592; 73; 771; -594; 105; 771; -596; 73; 772; -598; 105; 772; -600; 73; 774; -602; 105; 774; -604; 73; 808; -606; 105; 808; -608; 73; 775; -613; 73; 74; -615; 105; 106; -616; 74; 770; -618; 106; 770; -620; 75; 807; -622; 107; 807; -626; 76; 769; -628; 108; 769; -630; 76; 807; -632; 108; 807; -634; 76; 780; -636; 108; 780; -639; 76; 183; -641; 108; 183; -646; 78; 769; -648; 110; 769; -650; 78; 807; -652; 110; 807; -654; 78; 780; -656; 110; 780; -659; 700; 110; -664; 79; 772; -666; 111; 772; -668; 79; 774; -670; 111; 774; -672; 79; 779; -674; 111; 779; -680; 82; 769; -682; 114; 769; -684; 82; 807; -686; 114; 807; -688; 82; 780; -690; 114; 780; -692; 83; 769; -694; 115; 769; -696; 83; 770; -698; 115; 770; -700; 83; 807; -702; 115; 807; -704; 83; 780; -706; 115; 780; -708; 84; 807; -710; 116; 807; -712; 84; 780; -714; 116; 780; -720; 85; 771; -722; 117; 771; -724; 85; 772; -726; 117; 772; -728; 85; 774; -730; 117; 774; -732; 85; 778; -734; 117; 778; -736; 85; 779; -738; 117; 779; -740; 85; 808; -742; 117; 808; -744; 87; 770; -746; 119; 770; -748; 89; 770; -750; 121; 770; -752; 89; 776; -754; 90; 769; -756; 122; 769; -758; 90; 775; -760; 122; 775; -762; 90; 780; -764; 122; 780; -767; 115; -832; 79; 795; -834; 111; 795; -862; 85; 795; -864; 117; 795; -905; 68; 381; -907; 68; 382; -909; 100; 382; -911; 76; 74; -913; 76; 106; -915; 108; 106; -917; 78; 74; -919; 78; 106; -921; 110; 106; -922; 65; 780; -924; 97; 780; -926; 73; 780; -928; 105; 780; -930; 79; 780; -932; 111; 780; -934; 85; 780; -936; 117; 780; -938; 220; 772; -940; 252; 772; -942; 220; 769; -944; 252; 769; -946; 220; 780; -948; 252; 780; -950; 220; 768; -952; 252; 768; -956; 196; 772; -958; 228; 772; -960; 550; 772; -962; 551; 772; -964; 198; 772; -966; 230; 772; -972; 71; 780; -974; 103; 780; -976; 75; 780; -978; 107; 780; -980; 79; 808; -982; 111; 808; -984; 490; 772; -986; 491; 772; -988; 439; 780; -990; 658; 780; -992; 106; 780; -995; 68; 90; -997; 68; 122; -999; 100; 122; -1000; 71; 769; -1002; 103; 769; -1008; 78; 768; -1010; 110; 768; -1012; 197; 769; -1014; 229; 769; -1016; 198; 769; -1018; 230; 769; -1020; 216; 769; -1022; 248; 769; -1024; 65; 783; -1026; 97; 783; -1028; 65; 785; -1030; 97; 785; -1032; 69; 783; -1034; 101; 783; -1036; 69; 785; -1038; 101; 785; -1040; 73; 783; -1042; 105; 783; -1044; 73; 785; -1046; 105; 785; -1048; 79; 783; -1050; 111; 783; -1052; 79; 785; -1054; 111; 785; -1056; 82; 783; -1058; 114; 783; -1060; 82; 785; -1062; 114; 785; -1064; 85; 783; -1066; 117; 783; -1068; 85; 785; -1070; 117; 785; -1072; 83; 806; -1074; 115; 806; -1076; 84; 806; -1078; 116; 806; -1084; 72; 780; -1086; 104; 780; -1100; 65; 775; -1102; 97; 775; -1104; 69; 807; -1106; 101; 807; -1108; 214; 772; -1110; 246; 772; -1112; 213; 772; -1114; 245; 772; -1116; 79; 775; -1118; 111; 775; -1120; 558; 772; -1122; 559; 772; -1124; 89; 772; -1126; 121; 772; -1377; 104; -1379; 614; -1381; 106; -1383; 114; -1385; 633; -1387; 635; -1389; 641; -1391; 119; -1393; 121; -1457; 32; 774; -1459; 32; 775; -1461; 32; 778; -1463; 32; 808; -1465; 32; 771; -1467; 32; 779; -1473; 611; -1475; 108; -1477; 115; -1479; 120; -1481; 661; -1664; 768; -1666; 769; -1670; 787; -1672; 776; 769; -1768; 697; -1781; 32; 837; -1788; 59; -1801; 32; 769; -1802; 168; 769; -1804; 913; 769; -1806; 183; -1808; 917; 769; -1810; 919; 769; -1812; 921; 769; -1816; 927; 769; -1820; 933; 769; -1822; 937; 769; -1824; 970; 769; -1876; 921; 776; -1878; 933; 776; -1880; 945; 769; -1882; 949; 769; -1884; 951; 769; -1886; 953; 769; -1888; 971; 769; -1940; 953; 776; -1942; 965; 776; -1944; 959; 769; -1946; 965; 769; -1948; 969; 769; -1953; 946; -1955; 952; -1957; 933; -1958; 978; 769; -1960; 978; 776; -1963; 966; -1965; 960; -2017; 954; -2019; 961; -2021; 962; -2025; 920; -2027; 949; -2048; 1045; 768; -2050; 1045; 776; -2054; 1043; 769; -2062; 1030; 776; -2072; 1050; 769; -2074; 1048; 768; -2076; 1059; 774; -2098; 1048; 774; -2162; 1080; 774; -2208; 1077; 768; -2210; 1077; 776; -2214; 1075; 769; -2222; 1110; 776; -2232; 1082; 769; -2234; 1080; 768; -2236; 1091; 774; -2284; 1140; 783; -2286; 1141; 783; -2434; 1046; 774; -2436; 1078; 774; -2464; 1040; 774; -2466; 1072; 774; -2468; 1040; 776; -2470; 1072; 776; -2476; 1045; 774; -2478; 1077; 774; -2484; 1240; 776; -2486; 1241; 776; -2488; 1046; 776; -2490; 1078; 776; -2492; 1047; 776; -2494; 1079; 776; -2500; 1048; 772; -2502; 1080; 772; -2504; 1048; 776; -2506; 1080; 776; -2508; 1054; 776; -2510; 1086; 776; -2516; 1256; 776; -2518; 1257; 776; -2520; 1069; 776; -2522; 1101; 776; -2524; 1059; 772; -2526; 1091; 772; -2528; 1059; 776; -2530; 1091; 776; -2532; 1059; 779; -2534; 1091; 779; -2536; 1063; 776; -2538; 1095; 776; -2544; 1067; 776; -2546; 1099; 776; -2831; 1381; 1410; -3140; 1575; 1619; -3142; 1575; 1620; -3144; 1608; 1620; -3146; 1575; 1621; -3148; 1610; 1620; -3307; 1575; 1652; -3309; 1608; 1652; -3311; 1735; 1652; -3313; 1610; 1652; -3456; 1749; 1620; -3460; 1729; 1620; -3494; 1746; 1620; -4690; 2344; 2364; -4706; 2352; 2364; -4712; 2355; 2364; -4784; 2325; 2364; -4786; 2326; 2364; -4788; 2327; 2364; -4790; 2332; 2364; -4792; 2337; 2364; -4794; 2338; 2364; -4796; 2347; 2364; -4798; 2351; 2364; -5014; 2503; 2494; -5016; 2503; 2519; -5048; 2465; 2492; -5050; 2466; 2492; -5054; 2479; 2492; -5222; 2610; 2620; -5228; 2616; 2620; -5298; 2582; 2620; -5300; 2583; 2620; -5302; 2588; 2620; -5308; 2603; 2620; -5776; 2887; 2902; -5782; 2887; 2878; -5784; 2887; 2903; -5816; 2849; 2876; -5818; 2850; 2876; -5928; 2962; 3031; -6036; 3014; 3006; -6038; 3015; 3006; -6040; 3014; 3031; -6288; 3142; 3158; -6528; 3263; 3285; -6542; 3270; 3285; -6544; 3270; 3286; -6548; 3270; 3266; -6550; 3274; 3285; -6804; 3398; 3390; -6806; 3399; 3390; -6808; 3398; 3415; -7092; 3545; 3530; -7096; 3545; 3535; -7098; 3548; 3530; -7100; 3545; 3551; -7271; 3661; 3634; -7527; 3789; 3762; -7609; 3755; 3737; -7611; 3755; 3745; -7705; 3851; -7814; 3906; 4023; -7834; 3916; 4023; -7844; 3921; 4023; -7854; 3926; 4023; -7864; 3931; 4023; -7890; 3904; 4021; -7910; 3953; 3954; -7914; 3953; 3956; -7916; 4018; 3968; -7919; 4018; 3969; -7920; 4019; 3968; -7923; 4019; 3969; -7938; 3953; 3968; -7974; 3986; 4023; -7994; 3996; 4023; -8004; 4001; 4023; -8014; 4006; 4023; -8024; 4011; 4023; -8050; 3984; 4021; -8268; 4133; 4142; -15360; 65; 805; -15362; 97; 805; -15364; 66; 775; -15366; 98; 775; -15368; 66; 803; -15370; 98; 803; -15372; 66; 817; -15374; 98; 817; -15376; 199; 769; -15378; 231; 769; -15380; 68; 775; -15382; 100; 775; -15384; 68; 803; -15386; 100; 803; -15388; 68; 817; -15390; 100; 817; -15392; 68; 807; -15394; 100; 807; -15396; 68; 813; -15398; 100; 813; -15400; 274; 768; -15402; 275; 768; -15404; 274; 769; -15406; 275; 769; -15408; 69; 813; -15410; 101; 813; -15412; 69; 816; -15414; 101; 816; -15416; 552; 774; -15418; 553; 774; -15420; 70; 775; -15422; 102; 775; -15424; 71; 772; -15426; 103; 772; -15428; 72; 775; -15430; 104; 775; -15432; 72; 803; -15434; 104; 803; -15436; 72; 776; -15438; 104; 776; -15440; 72; 807; -15442; 104; 807; -15444; 72; 814; -15446; 104; 814; -15448; 73; 816; -15450; 105; 816; -15452; 207; 769; -15454; 239; 769; -15456; 75; 769; -15458; 107; 769; -15460; 75; 803; -15462; 107; 803; -15464; 75; 817; -15466; 107; 817; -15468; 76; 803; -15470; 108; 803; -15472; 7734; 772; -15474; 7735; 772; -15476; 76; 817; -15478; 108; 817; -15480; 76; 813; -15482; 108; 813; -15484; 77; 769; -15486; 109; 769; -15488; 77; 775; -15490; 109; 775; -15492; 77; 803; -15494; 109; 803; -15496; 78; 775; -15498; 110; 775; -15500; 78; 803; -15502; 110; 803; -15504; 78; 817; -15506; 110; 817; -15508; 78; 813; -15510; 110; 813; -15512; 213; 769; -15514; 245; 769; -15516; 213; 776; -15518; 245; 776; -15520; 332; 768; -15522; 333; 768; -15524; 332; 769; -15526; 333; 769; -15528; 80; 769; -15530; 112; 769; -15532; 80; 775; -15534; 112; 775; -15536; 82; 775; -15538; 114; 775; -15540; 82; 803; -15542; 114; 803; -15544; 7770; 772; -15546; 7771; 772; -15548; 82; 817; -15550; 114; 817; -15552; 83; 775; -15554; 115; 775; -15556; 83; 803; -15558; 115; 803; -15560; 346; 775; -15562; 347; 775; -15564; 352; 775; -15566; 353; 775; -15568; 7778; 775; -15570; 7779; 775; -15572; 84; 775; -15574; 116; 775; -15576; 84; 803; -15578; 116; 803; -15580; 84; 817; -15582; 116; 817; -15584; 84; 813; -15586; 116; 813; -15588; 85; 804; -15590; 117; 804; -15592; 85; 816; -15594; 117; 816; -15596; 85; 813; -15598; 117; 813; -15600; 360; 769; -15602; 361; 769; -15604; 362; 776; -15606; 363; 776; -15608; 86; 771; -15610; 118; 771; -15612; 86; 803; -15614; 118; 803; -15616; 87; 768; -15618; 119; 768; -15620; 87; 769; -15622; 119; 769; -15624; 87; 776; -15626; 119; 776; -15628; 87; 775; -15630; 119; 775; -15632; 87; 803; -15634; 119; 803; -15636; 88; 775; -15638; 120; 775; -15640; 88; 776; -15642; 120; 776; -15644; 89; 775; -15646; 121; 775; -15648; 90; 770; -15650; 122; 770; -15652; 90; 803; -15654; 122; 803; -15656; 90; 817; -15658; 122; 817; -15660; 104; 817; -15662; 116; 776; -15664; 119; 778; -15666; 121; 778; -15669; 97; 702; -15670; 383; 775; -15680; 65; 803; -15682; 97; 803; -15684; 65; 777; -15686; 97; 777; -15688; 194; 769; -15690; 226; 769; -15692; 194; 768; -15694; 226; 768; -15696; 194; 777; -15698; 226; 777; -15700; 194; 771; -15702; 226; 771; -15704; 7840; 770; -15706; 7841; 770; -15708; 258; 769; -15710; 259; 769; -15712; 258; 768; -15714; 259; 768; -15716; 258; 777; -15718; 259; 777; -15720; 258; 771; -15722; 259; 771; -15724; 7840; 774; -15726; 7841; 774; -15728; 69; 803; -15730; 101; 803; -15732; 69; 777; -15734; 101; 777; -15736; 69; 771; -15738; 101; 771; -15740; 202; 769; -15742; 234; 769; -15744; 202; 768; -15746; 234; 768; -15748; 202; 777; -15750; 234; 777; -15752; 202; 771; -15754; 234; 771; -15756; 7864; 770; -15758; 7865; 770; -15760; 73; 777; -15762; 105; 777; -15764; 73; 803; -15766; 105; 803; -15768; 79; 803; -15770; 111; 803; -15772; 79; 777; -15774; 111; 777; -15776; 212; 769; -15778; 244; 769; -15780; 212; 768; -15782; 244; 768; -15784; 212; 777; -15786; 244; 777; -15788; 212; 771; -15790; 244; 771; -15792; 7884; 770; -15794; 7885; 770; -15796; 416; 769; -15798; 417; 769; -15800; 416; 768; -15802; 417; 768; -15804; 416; 777; -15806; 417; 777; -15808; 416; 771; -15810; 417; 771; -15812; 416; 803; -15814; 417; 803; -15816; 85; 803; -15818; 117; 803; -15820; 85; 777; -15822; 117; 777; -15824; 431; 769; -15826; 432; 769; -15828; 431; 768; -15830; 432; 768; -15832; 431; 777; -15834; 432; 777; -15836; 431; 771; -15838; 432; 771; -15840; 431; 803; -15842; 432; 803; -15844; 89; 768; -15846; 121; 768; -15848; 89; 803; -15850; 121; 803; -15852; 89; 777; -15854; 121; 777; -15856; 89; 771; -15858; 121; 771; -15872; 945; 787; -15874; 945; 788; -15876; 7936; 768; -15878; 7937; 768; -15880; 7936; 769; -15882; 7937; 769; -15884; 7936; 834; -15886; 7937; 834; -15888; 913; 787; -15890; 913; 788; -15892; 7944; 768; -15894; 7945; 768; -15896; 7944; 769; -15898; 7945; 769; -15900; 7944; 834; -15902; 7945; 834; -15904; 949; 787; -15906; 949; 788; -15908; 7952; 768; -15910; 7953; 768; -15912; 7952; 769; -15914; 7953; 769; -15920; 917; 787; -15922; 917; 788; -15924; 7960; 768; -15926; 7961; 768; -15928; 7960; 769; -15930; 7961; 769; -15936; 951; 787; -15938; 951; 788; -15940; 7968; 768; -15942; 7969; 768; -15944; 7968; 769; -15946; 7969; 769; -15948; 7968; 834; -15950; 7969; 834; -15952; 919; 787; -15954; 919; 788; -15956; 7976; 768; -15958; 7977; 768; -15960; 7976; 769; -15962; 7977; 769; -15964; 7976; 834; -15966; 7977; 834; -15968; 953; 787; -15970; 953; 788; -15972; 7984; 768; -15974; 7985; 768; -15976; 7984; 769; -15978; 7985; 769; -15980; 7984; 834; -15982; 7985; 834; -15984; 921; 787; -15986; 921; 788; -15988; 7992; 768; -15990; 7993; 768; -15992; 7992; 769; -15994; 7993; 769; -15996; 7992; 834; -15998; 7993; 834; -16000; 959; 787; -16002; 959; 788; -16004; 8000; 768; -16006; 8001; 768; -16008; 8000; 769; -16010; 8001; 769; -16016; 927; 787; -16018; 927; 788; -16020; 8008; 768; -16022; 8009; 768; -16024; 8008; 769; -16026; 8009; 769; -16032; 965; 787; -16034; 965; 788; -16036; 8016; 768; -16038; 8017; 768; -16040; 8016; 769; -16042; 8017; 769; -16044; 8016; 834; -16046; 8017; 834; -16050; 933; 788; -16054; 8025; 768; -16058; 8025; 769; -16062; 8025; 834; -16064; 969; 787; -16066; 969; 788; -16068; 8032; 768; -16070; 8033; 768; -16072; 8032; 769; -16074; 8033; 769; -16076; 8032; 834; -16078; 8033; 834; -16080; 937; 787; -16082; 937; 788; -16084; 8040; 768; -16086; 8041; 768; -16088; 8040; 769; -16090; 8041; 769; -16092; 8040; 834; -16094; 8041; 834; -16096; 945; 768; -16098; 940; -16100; 949; 768; -16102; 941; -16104; 951; 768; -16106; 942; -16108; 953; 768; -16110; 943; -16112; 959; 768; -16114; 972; -16116; 965; 768; -16118; 973; -16120; 969; 768; -16122; 974; -16128; 7936; 837; -16130; 7937; 837; -16132; 7938; 837; -16134; 7939; 837; -16136; 7940; 837; -16138; 7941; 837; -16140; 7942; 837; -16142; 7943; 837; -16144; 7944; 837; -16146; 7945; 837; -16148; 7946; 837; -16150; 7947; 837; -16152; 7948; 837; -16154; 7949; 837; -16156; 7950; 837; -16158; 7951; 837; -16160; 7968; 837; -16162; 7969; 837; -16164; 7970; 837; -16166; 7971; 837; -16168; 7972; 837; -16170; 7973; 837; -16172; 7974; 837; -16174; 7975; 837; -16176; 7976; 837; -16178; 7977; 837; -16180; 7978; 837; -16182; 7979; 837; -16184; 7980; 837; -16186; 7981; 837; -16188; 7982; 837; -16190; 7983; 837; -16192; 8032; 837; -16194; 8033; 837; -16196; 8034; 837; -16198; 8035; 837; -16200; 8036; 837; -16202; 8037; 837; -16204; 8038; 837; -16206; 8039; 837; -16208; 8040; 837; -16210; 8041; 837; -16212; 8042; 837; -16214; 8043; 837; -16216; 8044; 837; -16218; 8045; 837; -16220; 8046; 837; -16222; 8047; 837; -16224; 945; 774; -16226; 945; 772; -16228; 8048; 837; -16230; 945; 837; -16232; 940; 837; -16236; 945; 834; -16238; 8118; 837; -16240; 913; 774; -16242; 913; 772; -16244; 913; 768; -16246; 902; -16248; 913; 837; -16251; 32; 787; -16252; 953; -16255; 32; 787; -16257; 32; 834; -16258; 168; 834; -16260; 8052; 837; -16262; 951; 837; -16264; 942; 837; -16268; 951; 834; -16270; 8134; 837; -16272; 917; 768; -16274; 904; -16276; 919; 768; -16278; 905; -16280; 919; 837; -16282; 8127; 768; -16284; 8127; 769; -16286; 8127; 834; -16288; 953; 774; -16290; 953; 772; -16292; 970; 768; -16294; 912; -16300; 953; 834; -16302; 970; 834; -16304; 921; 774; -16306; 921; 772; -16308; 921; 768; -16310; 906; -16314; 8190; 768; -16316; 8190; 769; -16318; 8190; 834; -16320; 965; 774; -16322; 965; 772; -16324; 971; 768; -16326; 944; -16328; 961; 787; -16330; 961; 788; -16332; 965; 834; -16334; 971; 834; -16336; 933; 774; -16338; 933; 772; -16340; 933; 768; -16342; 910; -16344; 929; 788; -16346; 168; 768; -16348; 901; -16350; 96; -16356; 8060; 837; -16358; 969; 837; -16360; 974; 837; -16364; 969; 834; -16366; 8182; 837; -16368; 927; 768; -16370; 908; -16372; 937; 768; -16374; 911; -16376; 937; 837; -16378; 180; -16381; 32; 788; -16384; 8194; -16386; 8195; -16389; 32; -16391; 32; -16393; 32; -16395; 32; -16397; 32; -16399; 32; -16401; 32; -16403; 32; -16405; 32; -16419; 8208; -16431; 32; 819; -16457; 46; -16459; 46; 46; -16461; 46; 46; 46; -16479; 32; -16487; 8242; 8242; -16489; 8242; 8242; 8242; -16493; 8245; 8245; -16495; 8245; 8245; 8245; -16505; 33; 33; -16509; 32; 773; -16527; 63; 63; -16529; 63; 33; -16531; 33; 63; -16559; 8242; 8242; 8242; 8242; -16575; 32; -16609; 48; -16611; 105; -16617; 52; -16619; 53; -16621; 54; -16623; 55; -16625; 56; -16627; 57; -16629; 43; -16631; 8722; -16633; 61; -16635; 40; -16637; 41; -16639; 110; -16641; 48; -16643; 49; -16645; 50; -16647; 51; -16649; 52; -16651; 53; -16653; 54; -16655; 55; -16657; 56; -16659; 57; -16661; 43; -16663; 8722; -16665; 61; -16667; 40; -16669; 41; -16721; 82; 115; -16897; 97; 47; 99; -16899; 97; 47; 115; -16901; 67; -16903; 176; 67; -16907; 99; 47; 111; -16909; 99; 47; 117; -16911; 400; -16915; 176; 70; -16917; 103; -16919; 72; -16921; 72; -16923; 72; -16925; 104; -16927; 295; -16929; 73; -16931; 73; -16933; 76; -16935; 108; -16939; 78; -16941; 78; 111; -16947; 80; -16949; 81; -16951; 82; -16953; 82; -16955; 82; -16961; 83; 77; -16963; 84; 69; 76; -16965; 84; 77; -16969; 90; -16972; 937; -16977; 90; -16980; 75; -16982; 197; -16985; 66; -16987; 67; -16991; 101; -16993; 69; -16995; 70; -16999; 77; -17001; 111; -17003; 1488; -17005; 1489; -17007; 1490; -17009; 1491; -17011; 105; -17019; 947; -17021; 915; -17023; 928; -17025; 8721; -17035; 68; -17037; 100; -17039; 101; -17041; 105; -17043; 106; -17063; 49; 8260; 51; -17065; 50; 8260; 51; -17067; 49; 8260; 53; -17069; 50; 8260; 53; -17071; 51; 8260; 53; -17073; 52; 8260; 53; -17075; 49; 8260; 54; -17077; 53; 8260; 54; -17079; 49; 8260; 56; -17081; 51; 8260; 56; -17083; 53; 8260; 56; -17085; 55; 8260; 56; -17087; 49; 8260; -17089; 73; -17091; 73; 73; -17093; 73; 73; 73; -17095; 73; 86; -17097; 86; -17099; 86; 73; -17101; 86; 73; 73; -17103; 86; 73; 73; 73; -17105; 73; 88; -17107; 88; -17109; 88; 73; -17111; 88; 73; 73; -17113; 76; -17115; 67; -17117; 68; -17119; 77; -17121; 105; -17123; 105; 105; -17125; 105; 105; 105; -17127; 105; 118; -17129; 118; -17131; 118; 105; -17133; 118; 105; 105; -17135; 118; 105; 105; 105; -17137; 105; 120; -17139; 120; -17141; 120; 105; -17143; 120; 105; 105; -17145; 108; -17147; 99; -17149; 100; -17151; 109; -17204; 8592; 824; -17206; 8594; 824; -17244; 8596; 824; -17306; 8656; 824; -17308; 8660; 824; -17310; 8658; 824; -17416; 8707; 824; -17426; 8712; 824; -17432; 8715; 824; -17480; 8739; 824; -17484; 8741; 824; -17497; 8747; 8747; -17499; 8747; 8747; 8747; -17503; 8750; 8750; -17505; 8750; 8750; 8750; -17538; 8764; 824; -17544; 8771; 824; -17550; 8773; 824; -17554; 8776; 824; -17600; 61; 824; -17604; 8801; 824; -17626; 8781; 824; -17628; 60; 824; -17630; 62; 824; -17632; 8804; 824; -17634; 8805; 824; -17640; 8818; 824; -17642; 8819; 824; -17648; 8822; 824; -17650; 8823; 824; -17664; 8826; 824; -17666; 8827; 824; -17672; 8834; 824; -17674; 8835; 824; -17680; 8838; 824; -17682; 8839; 824; -17752; 8866; 824; -17754; 8872; 824; -17756; 8873; 824; -17758; 8875; 824; -17856; 8828; 824; -17858; 8829; 824; -17860; 8849; 824; -17862; 8850; 824; -17876; 8882; 824; -17878; 8883; 824; -17880; 8884; 824; -17882; 8885; 824; -18002; 12296; -18004; 12297; -18625; 49; -18627; 50; -18629; 51; -18631; 52; -18633; 53; -18635; 54; -18637; 55; -18639; 56; -18641; 57; -18643; 49; 48; -18645; 49; 49; -18647; 49; 50; -18649; 49; 51; -18651; 49; 52; -18653; 49; 53; -18655; 49; 54; -18657; 49; 55; -18659; 49; 56; -18661; 49; 57; -18663; 50; 48; -18665; 40; 49; 41; -18667; 40; 50; 41; -18669; 40; 51; 41; -18671; 40; 52; 41; -18673; 40; 53; 41; -18675; 40; 54; 41; -18677; 40; 55; 41; -18679; 40; 56; 41; -18681; 40; 57; 41; -18683; 40; 49; 48; 41; -18685; 40; 49; 49; 41; -18687; 40; 49; 50; 41; -18689; 40; 49; 51; 41; -18691; 40; 49; 52; 41; -18693; 40; 49; 53; 41; -18695; 40; 49; 54; 41; -18697; 40; 49; 55; 41; -18699; 40; 49; 56; 41; -18701; 40; 49; 57; 41; -18703; 40; 50; 48; 41; -18705; 49; 46; -18707; 50; 46; -18709; 51; 46; -18711; 52; 46; -18713; 53; 46; -18715; 54; 46; -18717; 55; 46; -18719; 56; 46; -18721; 57; 46; -18723; 49; 48; 46; -18725; 49; 49; 46; -18727; 49; 50; 46; -18729; 49; 51; 46; -18731; 49; 52; 46; -18733; 49; 53; 46; -18735; 49; 54; 46; -18737; 49; 55; 46; -18739; 49; 56; 46; -18741; 49; 57; 46; -18743; 50; 48; 46; -18745; 40; 97; 41; -18747; 40; 98; 41; -18749; 40; 99; 41; -18751; 40; 100; 41; -18753; 40; 101; 41; -18755; 40; 102; 41; -18757; 40; 103; 41; -18759; 40; 104; 41; -18761; 40; 105; 41; -18763; 40; 106; 41; -18765; 40; 107; 41; -18767; 40; 108; 41; -18769; 40; 109; 41; -18771; 40; 110; 41; -18773; 40; 111; 41; -18775; 40; 112; 41; -18777; 40; 113; 41; -18779; 40; 114; 41; -18781; 40; 115; 41; -18783; 40; 116; 41; -18785; 40; 117; 41; -18787; 40; 118; 41; -18789; 40; 119; 41; -18791; 40; 120; 41; -18793; 40; 121; 41; -18795; 40; 122; 41; -18797; 65; -18799; 66; -18801; 67; -18803; 68; -18805; 69; -18807; 70; -18809; 71; -18811; 72; -18813; 73; -18815; 74; -18817; 75; -18819; 76; -18821; 77; -18823; 78; -18825; 79; -18827; 80; -18829; 81; -18831; 82; -18833; 83; -18835; 84; -18837; 85; -18839; 86; -18841; 87; -18843; 88; -18845; 89; -18847; 90; -18849; 97; -18851; 98; -18853; 99; -18855; 100; -18857; 101; -18859; 102; -18861; 103; -18863; 104; -18865; 105; -18867; 106; -18869; 107; -18871; 108; -18873; 109; -18875; 110; -18877; 111; -18879; 112; -18881; 113; -18883; 114; -18885; 115; -18887; 116; -18889; 117; -18891; 118; -18893; 119; -18895; 120; -18897; 121; -18899; 122; -18901; 48; -21529; 8747; 8747; 8747; 8747; -21737; 58; 58; 61; -21739; 61; 61; -21741; 61; 61; 61; -21944; 10973; 824; -23871; 27597; -24039; 40863; -24065; 19968; -24067; 20008; -24069; 20022; -24071; 20031; -24073; 20057; -24075; 20101; -24077; 20108; -24079; 20128; -24081; 20154; -24083; 20799; -24085; 20837; -24087; 20843; -24089; 20866; -24091; 20886; -24093; 20907; -24095; 20960; -24097; 20981; -24099; 20992; -24101; 21147; -24103; 21241; -24105; 21269; -24107; 21274; -24109; 21304; -24111; 21313; -24113; 21340; -24115; 21353; -24117; 21378; -24119; 21430; -24121; 21448; -24123; 21475; -24125; 22231; -24127; 22303; -24129; 22763; -24131; 22786; -24133; 22794; -24135; 22805; -24137; 22823; -24139; 22899; -24141; 23376; -24143; 23424; -24145; 23544; -24147; 23567; -24149; 23586; -24151; 23608; -24153; 23662; -24155; 23665; -24157; 24027; -24159; 24037; -24161; 24049; -24163; 24062; -24165; 24178; -24167; 24186; -24169; 24191; -24171; 24308; -24173; 24318; -24175; 24331; -24177; 24339; -24179; 24400; -24181; 24417; -24183; 24435; -24185; 24515; -24187; 25096; -24189; 25142; -24191; 25163; -24193; 25903; -24195; 25908; -24197; 25991; -24199; 26007; -24201; 26020; -24203; 26041; -24205; 26080; -24207; 26085; -24209; 26352; -24211; 26376; -24213; 26408; -24215; 27424; -24217; 27490; -24219; 27513; -24221; 27571; -24223; 27595; -24225; 27604; -24227; 27611; -24229; 27663; -24231; 27668; -24233; 27700; -24235; 28779; -24237; 29226; -24239; 29238; -24241; 29243; -24243; 29247; -24245; 29255; -24247; 29273; -24249; 29275; -24251; 29356; -24253; 29572; -24255; 29577; -24257; 29916; -24259; 29926; -24261; 29976; -24263; 29983; -24265; 29992; -24267; 30000; -24269; 30091; -24271; 30098; -24273; 30326; -24275; 30333; -24277; 30382; -24279; 30399; -24281; 30446; -24283; 30683; -24285; 30690; -24287; 30707; -24289; 31034; -24291; 31160; -24293; 31166; -24295; 31348; -24297; 31435; -24299; 31481; -24301; 31859; -24303; 31992; -24305; 32566; -24307; 32593; -24309; 32650; -24311; 32701; -24313; 32769; -24315; 32780; -24317; 32786; -24319; 32819; -24321; 32895; -24323; 32905; -24325; 33251; -24327; 33258; -24329; 33267; -24331; 33276; -24333; 33292; -24335; 33307; -24337; 33311; -24339; 33390; -24341; 33394; -24343; 33400; -24345; 34381; -24347; 34411; -24349; 34880; -24351; 34892; -24353; 34915; -24355; 35198; -24357; 35211; -24359; 35282; -24361; 35328; -24363; 35895; -24365; 35910; -24367; 35925; -24369; 35960; -24371; 35997; -24373; 36196; -24375; 36208; -24377; 36275; -24379; 36523; -24381; 36554; -24383; 36763; -24385; 36784; -24387; 36789; -24389; 37009; -24391; 37193; -24393; 37318; -24395; 37324; -24397; 37329; -24399; 38263; -24401; 38272; -24403; 38428; -24405; 38582; -24407; 38585; -24409; 38632; -24411; 38737; -24413; 38750; -24415; 38754; -24417; 38761; -24419; 38859; -24421; 38893; -24423; 38899; -24425; 38913; -24427; 39080; -24429; 39131; -24431; 39135; -24433; 39318; -24435; 39321; -24437; 39340; -24439; 39592; -24441; 39640; -24443; 39647; -24445; 39717; -24447; 39727; -24449; 39730; -24451; 39740; -24453; 39770; -24455; 40165; -24457; 40565; -24459; 40575; -24461; 40613; -24463; 40635; -24465; 40643; -24467; 40653; -24469; 40657; -24471; 40697; -24473; 40701; -24475; 40718; -24477; 40723; -24479; 40736; -24481; 40763; -24483; 40778; -24485; 40786; -24487; 40845; -24489; 40860; -24491; 40864; -24577; 32; -24685; 12306; -24689; 21313; -24691; 21316; -24693; 21317; -24728; 12363; 12441; -24732; 12365; 12441; -24736; 12367; 12441; -24740; 12369; 12441; -24744; 12371; 12441; -24748; 12373; 12441; -24752; 12375; 12441; -24756; 12377; 12441; -24760; 12379; 12441; -24764; 12381; 12441; -24768; 12383; 12441; -24772; 12385; 12441; -24778; 12388; 12441; -24782; 12390; 12441; -24786; 12392; 12441; -24800; 12399; 12441; -24802; 12399; 12442; -24806; 12402; 12441; -24808; 12402; 12442; -24812; 12405; 12441; -24814; 12405; 12442; -24818; 12408; 12441; -24820; 12408; 12442; -24824; 12411; 12441; -24826; 12411; 12442; -24872; 12358; 12441; -24887; 32; 12441; -24889; 32; 12442; -24892; 12445; 12441; -24895; 12424; 12426; -24920; 12459; 12441; -24924; 12461; 12441; -24928; 12463; 12441; -24932; 12465; 12441; -24936; 12467; 12441; -24940; 12469; 12441; -24944; 12471; 12441; -24948; 12473; 12441; -24952; 12475; 12441; -24956; 12477; 12441; -24960; 12479; 12441; -24964; 12481; 12441; -24970; 12484; 12441; -24974; 12486; 12441; -24978; 12488; 12441; -24992; 12495; 12441; -24994; 12495; 12442; -24998; 12498; 12441; -25000; 12498; 12442; -25004; 12501; 12441; -25006; 12501; 12442; -25010; 12504; 12441; -25012; 12504; 12442; -25016; 12507; 12441; -25018; 12507; 12442; -25064; 12454; 12441; -25070; 12527; 12441; -25072; 12528; 12441; -25074; 12529; 12441; -25076; 12530; 12441; -25084; 12541; 12441; -25087; 12467; 12488; -25187; 4352; -25189; 4353; -25191; 4522; -25193; 4354; -25195; 4524; -25197; 4525; -25199; 4355; -25201; 4356; -25203; 4357; -25205; 4528; -25207; 4529; -25209; 4530; -25211; 4531; -25213; 4532; -25215; 4533; -25217; 4378; -25219; 4358; -25221; 4359; -25223; 4360; -25225; 4385; -25227; 4361; -25229; 4362; -25231; 4363; -25233; 4364; -25235; 4365; -25237; 4366; -25239; 4367; -25241; 4368; -25243; 4369; -25245; 4370; -25247; 4449; -25249; 4450; -25251; 4451; -25253; 4452; -25255; 4453; -25257; 4454; -25259; 4455; -25261; 4456; -25263; 4457; -25265; 4458; -25267; 4459; -25269; 4460; -25271; 4461; -25273; 4462; -25275; 4463; -25277; 4464; -25279; 4465; -25281; 4466; -25283; 4467; -25285; 4468; -25287; 4469; -25289; 4448; -25291; 4372; -25293; 4373; -25295; 4551; -25297; 4552; -25299; 4556; -25301; 4558; -25303; 4563; -25305; 4567; -25307; 4569; -25309; 4380; -25311; 4573; -25313; 4575; -25315; 4381; -25317; 4382; -25319; 4384; -25321; 4386; -25323; 4387; -25325; 4391; -25327; 4393; -25329; 4395; -25331; 4396; -25333; 4397; -25335; 4398; -25337; 4399; -25339; 4402; -25341; 4406; -25343; 4416; -25345; 4423; -25347; 4428; -25349; 4593; -25351; 4594; -25353; 4439; -25355; 4440; -25357; 4441; -25359; 4484; -25361; 4485; -25363; 4488; -25365; 4497; -25367; 4498; -25369; 4500; -25371; 4510; -25373; 4513; -25381; 19968; -25383; 20108; -25385; 19977; -25387; 22235; -25389; 19978; -25391; 20013; -25393; 19979; -25395; 30002; -25397; 20057; -25399; 19993; -25401; 19969; -25403; 22825; -25405; 22320; -25407; 20154; -25601; 40; 4352; 41; -25603; 40; 4354; 41; -25605; 40; 4355; 41; -25607; 40; 4357; 41; -25609; 40; 4358; 41; -25611; 40; 4359; 41; -25613; 40; 4361; 41; -25615; 40; 4363; 41; -25617; 40; 4364; 41; -25619; 40; 4366; 41; -25621; 40; 4367; 41; -25623; 40; 4368; 41; -25625; 40; 4369; 41; -25627; 40; 4370; 41; -25629; 40; 4352; 4449; 41; -25631; 40; 4354; 4449; 41; -25633; 40; 4355; 4449; 41; -25635; 40; 4357; 4449; 41; -25637; 40; 4358; 4449; 41; -25639; 40; 4359; 4449; 41; -25641; 40; 4361; 4449; 41; -25643; 40; 4363; 4449; 41; -25645; 40; 4364; 4449; 41; -25647; 40; 4366; 4449; 41; -25649; 40; 4367; 4449; 41; -25651; 40; 4368; 4449; 41; -25653; 40; 4369; 4449; 41; -25655; 40; 4370; 4449; 41; -25657; 40; 4364; 4462; 41; -25665; 40; 19968; 41; -25667; 40; 20108; 41; -25669; 40; 19977; 41; -25671; 40; 22235; 41; -25673; 40; 20116; 41; -25675; 40; 20845; 41; -25677; 40; 19971; 41; -25679; 40; 20843; 41; -25681; 40; 20061; 41; -25683; 40; 21313; 41; -25685; 40; 26376; 41; -25687; 40; 28779; 41; -25689; 40; 27700; 41; -25691; 40; 26408; 41; -25693; 40; 37329; 41; -25695; 40; 22303; 41; -25697; 40; 26085; 41; -25699; 40; 26666; 41; -25701; 40; 26377; 41; -25703; 40; 31038; 41; -25705; 40; 21517; 41; -25707; 40; 29305; 41; -25709; 40; 36001; 41; -25711; 40; 31069; 41; -25713; 40; 21172; 41; -25715; 40; 20195; 41; -25717; 40; 21628; 41; -25719; 40; 23398; 41; -25721; 40; 30435; 41; -25723; 40; 20225; 41; -25725; 40; 36039; 41; -25727; 40; 21332; 41; -25729; 40; 31085; 41; -25731; 40; 20241; 41; -25733; 40; 33258; 41; -25735; 40; 33267; 41; -25763; 50; 49; -25765; 50; 50; -25767; 50; 51; -25769; 50; 52; -25771; 50; 53; -25773; 50; 54; -25775; 50; 55; -25777; 50; 56; -25779; 50; 57; -25781; 51; 48; -25783; 51; 49; -25785; 51; 50; -25787; 51; 51; -25789; 51; 52; -25791; 51; 53; -25793; 4352; -25795; 4354; -25797; 4355; -25799; 4357; -25801; 4358; -25803; 4359; -25805; 4361; -25807; 4363; -25809; 4364; -25811; 4366; -25813; 4367; -25815; 4368; -25817; 4369; -25819; 4370; -25821; 4352; 4449; -25823; 4354; 4449; -25825; 4355; 4449; -25827; 4357; 4449; -25829; 4358; 4449; -25831; 4359; 4449; -25833; 4361; 4449; -25835; 4363; 4449; -25837; 4364; 4449; -25839; 4366; 4449; -25841; 4367; 4449; -25843; 4368; 4449; -25845; 4369; 4449; -25847; 4370; 4449; -25857; 19968; -25859; 20108; -25861; 19977; -25863; 22235; -25865; 20116; -25867; 20845; -25869; 19971; -25871; 20843; -25873; 20061; -25875; 21313; -25877; 26376; -25879; 28779; -25881; 27700; -25883; 26408; -25885; 37329; -25887; 22303; -25889; 26085; -25891; 26666; -25893; 26377; -25895; 31038; -25897; 21517; -25899; 29305; -25901; 36001; -25903; 31069; -25905; 21172; -25907; 31192; -25909; 30007; -25911; 22899; -25913; 36969; -25915; 20778; -25917; 21360; -25919; 27880; -25921; 38917; -25923; 20241; -25925; 20889; -25927; 27491; -25929; 19978; -25931; 20013; -25933; 19979; -25935; 24038; -25937; 21491; -25939; 21307; -25941; 23447; -25943; 23398; -25945; 30435; -25947; 20225; -25949; 36039; -25951; 21332; -25953; 22812; -25955; 51; 54; -25957; 51; 55; -25959; 51; 56; -25961; 51; 57; -25963; 52; 48; -25965; 52; 49; -25967; 52; 50; -25969; 52; 51; -25971; 52; 52; -25973; 52; 53; -25975; 52; 54; -25977; 52; 55; -25979; 52; 56; -25981; 52; 57; -25983; 53; 48; -25985; 49; 26376; -25987; 50; 26376; -25989; 51; 26376; -25991; 52; 26376; -25993; 53; 26376; -25995; 54; 26376; -25997; 55; 26376; -25999; 56; 26376; -26001; 57; 26376; -26003; 49; 48; 26376; -26005; 49; 49; 26376; -26007; 49; 50; 26376; -26017; 12450; -26019; 12452; -26021; 12454; -26023; 12456; -26025; 12458; -26027; 12459; -26029; 12461; -26031; 12463; -26033; 12465; -26035; 12467; -26037; 12469; -26039; 12471; -26041; 12473; -26043; 12475; -26045; 12477; -26047; 12479; -26049; 12481; -26051; 12484; -26053; 12486; -26055; 12488; -26057; 12490; -26059; 12491; -26061; 12492; -26063; 12493; -26065; 12494; -26067; 12495; -26069; 12498; -26071; 12501; -26073; 12504; -26075; 12507; -26077; 12510; -26079; 12511; -26081; 12512; -26083; 12513; -26085; 12514; -26087; 12516; -26089; 12518; -26091; 12520; -26093; 12521; -26095; 12522; -26097; 12523; -26099; 12524; -26101; 12525; -26103; 12527; -26105; 12528; -26107; 12529; -26109; 12530; -26113; 12450; 12497; 12540; 12488; -26115; 12450; 12523; 12501; 12449; -26117; 12450; 12531; 12506; 12450; -26119; 12450; 12540; 12523; -26121; 12452; 12491; 12531; 12464; -26123; 12452; 12531; 12481; -26125; 12454; 12457; 12531; -26127; 12456; 12473; 12463; 12540; 12489; -26129; 12456; 12540; 12459; 12540; -26131; 12458; 12531; 12473; -26133; 12458; 12540; 12512; -26135; 12459; 12452; 12522; -26137; 12459; 12521; 12483; 12488; -26139; 12459; 12525; 12522; 12540; -26141; 12460; 12525; 12531; -26143; 12460; 12531; 12510; -26145; 12462; 12460; -26147; 12462; 12491; 12540; -26149; 12461; 12517; 12522; 12540; -26151; 12462; 12523; 12480; 12540; -26153; 12461; 12525; -26155; 12461; 12525; 12464; 12521; 12512; -26157; 12461; 12525; 12513; 12540; 12488; 12523; -26159; 12461; 12525; 12527; 12483; 12488; -26161; 12464; 12521; 12512; -26163; 12464; 12521; 12512; 12488; 12531; -26165; 12463; 12523; 12476; 12452; 12525; -26167; 12463; 12525; 12540; 12493; -26169; 12465; 12540; 12473; -26171; 12467; 12523; 12490; -26173; 12467; 12540; 12509; -26175; 12469; 12452; 12463; 12523; -26177; 12469; 12531; 12481; 12540; 12512; -26179; 12471; 12522; 12531; 12464; -26181; 12475; 12531; 12481; -26183; 12475; 12531; 12488; -26185; 12480; 12540; 12473; -26187; 12487; 12471; -26189; 12489; 12523; -26191; 12488; 12531; -26193; 12490; 12494; -26195; 12494; 12483; 12488; -26197; 12495; 12452; 12484; -26199; 12497; 12540; 12475; 12531; 12488; -26201; 12497; 12540; 12484; -26203; 12496; 12540; 12524; 12523; -26205; 12500; 12450; 12473; 12488; 12523; -26207; 12500; 12463; 12523; -26209; 12500; 12467; -26211; 12499; 12523; -26213; 12501; 12449; 12521; 12483; 12489; -26215; 12501; 12451; 12540; 12488; -26217; 12502; 12483; 12471; 12455; 12523; -26219; 12501; 12521; 12531; -26221; 12504; 12463; 12479; 12540; 12523; -26223; 12506; 12477; -26225; 12506; 12491; 12498; -26227; 12504; 12523; 12484; -26229; 12506; 12531; 12473; -26231; 12506; 12540; 12472; -26233; 12505; 12540; 12479; -26235; 12509; 12452; 12531; 12488; -26237; 12508; 12523; 12488; -26239; 12507; 12531; -26241; 12509; 12531; 12489; -26243; 12507; 12540; 12523; -26245; 12507; 12540; 12531; -26247; 12510; 12452; 12463; 12525; -26249; 12510; 12452; 12523; -26251; 12510; 12483; 12495; -26253; 12510; 12523; 12463; -26255; 12510; 12531; 12471; 12519; 12531; -26257; 12511; 12463; 12525; 12531; -26259; 12511; 12522; -26261; 12511; 12522; 12496; 12540; 12523; -26263; 12513; 12460; -26265; 12513; 12460; 12488; 12531; -26267; 12513; 12540; 12488; 12523; -26269; 12516; 12540; 12489; -26271; 12516; 12540; 12523; -26273; 12518; 12450; 12531; -26275; 12522; 12483; 12488; 12523; -26277; 12522; 12521; -26279; 12523; 12500; 12540; -26281; 12523; 12540; 12502; 12523; -26283; 12524; 12512; -26285; 12524; 12531; 12488; 12466; 12531; -26287; 12527; 12483; 12488; -26289; 48; 28857; -26291; 49; 28857; -26293; 50; 28857; -26295; 51; 28857; -26297; 52; 28857; -26299; 53; 28857; -26301; 54; 28857; -26303; 55; 28857; -26305; 56; 28857; -26307; 57; 28857; -26309; 49; 48; 28857; -26311; 49; 49; 28857; -26313; 49; 50; 28857; -26315; 49; 51; 28857; -26317; 49; 52; 28857; -26319; 49; 53; 28857; -26321; 49; 54; 28857; -26323; 49; 55; 28857; -26325; 49; 56; 28857; -26327; 49; 57; 28857; -26329; 50; 48; 28857; -26331; 50; 49; 28857; -26333; 50; 50; 28857; -26335; 50; 51; 28857; -26337; 50; 52; 28857; -26339; 104; 80; 97; -26341; 100; 97; -26343; 65; 85; -26345; 98; 97; 114; -26347; 111; 86; -26349; 112; 99; -26359; 24179; 25104; -26361; 26157; 21644; -26363; 22823; 27491; -26365; 26126; 27835; -26367; 26666; 24335; 20250; 31038; -26369; 112; 65; -26371; 110; 65; -26373; 956; 65; -26375; 109; 65; -26377; 107; 65; -26379; 75; 66; -26381; 77; 66; -26383; 71; 66; -26385; 99; 97; 108; -26387; 107; 99; 97; 108; -26389; 112; 70; -26391; 110; 70; -26393; 956; 70; -26395; 956; 103; -26397; 109; 103; -26399; 107; 103; -26401; 72; 122; -26403; 107; 72; 122; -26405; 77; 72; 122; -26407; 71; 72; 122; -26409; 84; 72; 122; -26411; 956; 8467; -26413; 109; 8467; -26415; 100; 8467; -26417; 107; 8467; -26419; 102; 109; -26421; 110; 109; -26423; 956; 109; -26425; 109; 109; -26427; 99; 109; -26429; 107; 109; -26431; 109; 109; 178; -26433; 99; 109; 178; -26435; 109; 178; -26437; 107; 109; 178; -26439; 109; 109; 179; -26441; 99; 109; 179; -26443; 109; 179; -26445; 107; 109; 179; -26447; 109; 8725; 115; -26449; 109; 8725; 115; 178; -26451; 80; 97; -26453; 107; 80; 97; -26455; 77; 80; 97; -26457; 71; 80; 97; -26459; 114; 97; 100; -26461; 114; 97; 100; 8725; 115; -26463; 114; 97; 100; 8725; 115; 178; -26465; 112; 115; -26467; 110; 115; -26469; 956; 115; -26471; 109; 115; -26473; 112; 86; -26475; 110; 86; -26477; 956; 86; -26479; 109; 86; -26481; 107; 86; -26483; 77; 86; -26485; 112; 87; -26487; 110; 87; -26489; 956; 87; -26491; 109; 87; -26493; 107; 87; -26495; 77; 87; -26497; 107; 937; -26499; 77; 937; -26501; 97; 46; 109; 46; -26503; 66; 113; -26505; 99; 99; -26507; 99; 100; -26509; 67; 8725; 107; 103; -26511; 67; 111; 46; -26513; 100; 66; -26515; 71; 121; -26517; 104; 97; -26519; 72; 80; -26521; 105; 110; -26523; 75; 75; -26525; 75; 77; -26527; 107; 116; -26529; 108; 109; -26531; 108; 110; -26533; 108; 111; 103; -26535; 108; 120; -26537; 109; 98; -26539; 109; 105; 108; -26541; 109; 111; 108; -26543; 80; 72; -26545; 112; 46; 109; 46; -26547; 80; 80; 77; -26549; 80; 82; -26551; 115; 114; -26553; 83; 118; -26555; 87; 98; -26561; 49; 26085; -26563; 50; 26085; -26565; 51; 26085; -26567; 52; 26085; -26569; 53; 26085; -26571; 54; 26085; -26573; 55; 26085; -26575; 56; 26085; -26577; 57; 26085; -26579; 49; 48; 26085; -26581; 49; 49; 26085; -26583; 49; 50; 26085; -26585; 49; 51; 26085; -26587; 49; 52; 26085; -26589; 49; 53; 26085; -26591; 49; 54; 26085; -26593; 49; 55; 26085; -26595; 49; 56; 26085; -26597; 49; 57; 26085; -26599; 50; 48; 26085; -26601; 50; 49; 26085; -26603; 50; 50; 26085; -26605; 50; 51; 26085; -26607; 50; 52; 26085; -26609; 50; 53; 26085; -26611; 50; 54; 26085; -26613; 50; 55; 26085; -26615; 50; 56; 26085; -26617; 50; 57; 26085; -26619; 51; 48; 26085; -26621; 51; 49; 26085; -127488; 35912; -127490; 26356; -127492; 36554; -127494; 36040; -127496; 28369; -127498; 20018; -127500; 21477; -127502; 40860; -127504; 40860; -127506; 22865; -127508; 37329; -127510; 21895; -127512; 22856; -127514; 25078; -127516; 30313; -127518; 32645; -127520; 34367; -127522; 34746; -127524; 35064; -127526; 37007; -127528; 27138; -127530; 27931; -127532; 28889; -127534; 29662; -127536; 33853; -127538; 37226; -127540; 39409; -127542; 20098; -127544; 21365; -127546; 27396; -127548; 29211; -127550; 34349; -127552; 40478; -127554; 23888; -127556; 28651; -127558; 34253; -127560; 35172; -127562; 25289; -127564; 33240; -127566; 34847; -127568; 24266; -127570; 26391; -127572; 28010; -127574; 29436; -127576; 37070; -127578; 20358; -127580; 20919; -127582; 21214; -127584; 25796; -127586; 27347; -127588; 29200; -127590; 30439; -127592; 32769; -127594; 34310; -127596; 34396; -127598; 36335; -127600; 38706; -127602; 39791; -127604; 40442; -127606; 30860; -127608; 31103; -127610; 32160; -127612; 33737; -127614; 37636; -127616; 40575; -127618; 35542; -127620; 22751; -127622; 24324; -127624; 31840; -127626; 32894; -127628; 29282; -127630; 30922; -127632; 36034; -127634; 38647; -127636; 22744; -127638; 23650; -127640; 27155; -127642; 28122; -127644; 28431; -127646; 32047; -127648; 32311; -127650; 38475; -127652; 21202; -127654; 32907; -127656; 20956; -127658; 20940; -127660; 31260; -127662; 32190; -127664; 33777; -127666; 38517; -127668; 35712; -127670; 25295; -127672; 27138; -127674; 35582; -127676; 20025; -127678; 23527; -127680; 24594; -127682; 29575; -127684; 30064; -127686; 21271; -127688; 30971; -127690; 20415; -127692; 24489; -127694; 19981; -127696; 27852; -127698; 25976; -127700; 32034; -127702; 21443; -127704; 22622; -127706; 30465; -127708; 33865; -127710; 35498; -127712; 27578; -127714; 36784; -127716; 27784; -127718; 25342; -127720; 33509; -127722; 25504; -127724; 30053; -127726; 20142; -127728; 20841; -127730; 20937; -127732; 26753; -127734; 31975; -127736; 33391; -127738; 35538; -127740; 37327; -127742; 21237; -127744; 21570; -127746; 22899; -127748; 24300; -127750; 26053; -127752; 28670; -127754; 31018; -127756; 38317; -127758; 39530; -127760; 40599; -127762; 40654; -127764; 21147; -127766; 26310; -127768; 27511; -127770; 36706; -127772; 24180; -127774; 24976; -127776; 25088; -127778; 25754; -127780; 28451; -127782; 29001; -127784; 29833; -127786; 31178; -127788; 32244; -127790; 32879; -127792; 36646; -127794; 34030; -127796; 36899; -127798; 37706; -127800; 21015; -127802; 21155; -127804; 21693; -127806; 28872; -127808; 35010; -127810; 35498; -127812; 24265; -127814; 24565; -127816; 25467; -127818; 27566; -127820; 31806; -127822; 29557; -127824; 20196; -127826; 22265; -127828; 23527; -127830; 23994; -127832; 24604; -127834; 29618; -127836; 29801; -127838; 32666; -127840; 32838; -127842; 37428; -127844; 38646; -127846; 38728; -127848; 38936; -127850; 20363; -127852; 31150; -127854; 37300; -127856; 38584; -127858; 24801; -127860; 20102; -127862; 20698; -127864; 23534; -127866; 23615; -127868; 26009; -127870; 27138; -127872; 29134; -127874; 30274; -127876; 34044; -127878; 36988; -127880; 40845; -127882; 26248; -127884; 38446; -127886; 21129; -127888; 26491; -127890; 26611; -127892; 27969; -127894; 28316; -127896; 29705; -127898; 30041; -127900; 30827; -127902; 32016; -127904; 39006; -127906; 20845; -127908; 25134; -127910; 38520; -127912; 20523; -127914; 23833; -127916; 28138; -127918; 36650; -127920; 24459; -127922; 24900; -127924; 26647; -127926; 29575; -127928; 38534; -127930; 21033; -127932; 21519; -127934; 23653; -127936; 26131; -127938; 26446; -127940; 26792; -127942; 27877; -127944; 29702; -127946; 30178; -127948; 32633; -127950; 35023; -127952; 35041; -127954; 37324; -127956; 38626; -127958; 21311; -127960; 28346; -127962; 21533; -127964; 29136; -127966; 29848; -127968; 34298; -127970; 38563; -127972; 40023; -127974; 40607; -127976; 26519; -127978; 28107; -127980; 33256; -127982; 31435; -127984; 31520; -127986; 31890; -127988; 29376; -127990; 28825; -127992; 35672; -127994; 20160; -127996; 33590; -127998; 21050; -128000; 20999; -128002; 24230; -128004; 25299; -128006; 31958; -128008; 23429; -128010; 27934; -128012; 26292; -128014; 36667; -128016; 34892; -128018; 38477; -128020; 35211; -128022; 24275; -128024; 20800; -128026; 21952; -128032; 22618; -128036; 26228; -128042; 20958; -128044; 29482; -128046; 30410; -128048; 31036; -128050; 31070; -128052; 31077; -128054; 31119; -128056; 38742; -128058; 31934; -128060; 32701; -128064; 34322; -128068; 35576; -128074; 36920; -128076; 37117; -128084; 39151; -128086; 39164; -128088; 39208; -128090; 40372; -128096; 20398; -128098; 20711; -128100; 20813; -128102; 21193; -128104; 21220; -128106; 21329; -128108; 21917; -128110; 22022; -128112; 22120; -128114; 22592; -128116; 22696; -128118; 23652; -128120; 23662; -128122; 24724; -128124; 24936; -128126; 24974; -128128; 25074; -128130; 25935; -128132; 26082; -128134; 26257; -128136; 26757; -128138; 28023; -128140; 28186; -128142; 28450; -128144; 29038; -128146; 29227; -128148; 29730; -128150; 30865; -128152; 31038; -128154; 31049; -128156; 31048; -128158; 31056; -128160; 31062; -128162; 31069; -128164; 31117; -128166; 31118; -128168; 31296; -128170; 31361; -128172; 31680; -128174; 32244; -128176; 32265; -128178; 32321; -128180; 32626; -128182; 32773; -128184; 33261; -128186; 33401; -128188; 33401; -128190; 33879; -128192; 35088; -128194; 35222; -128196; 35585; -128198; 35641; -128200; 36051; -128202; 36104; -128204; 36790; -128206; 36920; -128208; 38627; -128210; 38911; -128212; 38971; -128513; 102; 102; -128515; 102; 105; -128517; 102; 108; -128519; 102; 102; 105; -128521; 102; 102; 108; -128523; 383; 116; -128525; 115; 116; -128551; 1396; 1398; -128553; 1396; 1381; -128555; 1396; 1387; -128557; 1406; 1398; -128559; 1396; 1389; -128570; 1497; 1460; -128574; 1522; 1463; -128577; 1506; -128579; 1488; -128581; 1491; -128583; 1492; -128585; 1499; -128587; 1500; -128589; 1501; -128591; 1512; -128593; 1514; -128595; 43; -128596; 1513; 1473; -128598; 1513; 1474; -128600; 64329; 1473; -128602; 64329; 1474; -128604; 1488; 1463; -128606; 1488; 1464; -128608; 1488; 1468; -128610; 1489; 1468; -128612; 1490; 1468; -128614; 1491; 1468; -128616; 1492; 1468; -128618; 1493; 1468; -128620; 1494; 1468; -128624; 1496; 1468; -128626; 1497; 1468; -128628; 1498; 1468; -128630; 1499; 1468; -128632; 1500; 1468; -128636; 1502; 1468; -128640; 1504; 1468; -128642; 1505; 1468; -128646; 1507; 1468; -128648; 1508; 1468; -128652; 1510; 1468; -128654; 1511; 1468; -128656; 1512; 1468; -128658; 1513; 1468; -128660; 1514; 1468; -128662; 1493; 1465; -128664; 1489; 1471; -128666; 1499; 1471; -128668; 1508; 1471; -128671; 1488; 1500; -128673; 1649; -128675; 1649; -128677; 1659; -128679; 1659; -128681; 1659; -128683; 1659; -128685; 1662; -128687; 1662; -128689; 1662; -128691; 1662; -128693; 1664; -128695; 1664; -128697; 1664; -128699; 1664; -128701; 1658; -128703; 1658; -128705; 1658; -128707; 1658; -128709; 1663; -128711; 1663; -128713; 1663; -128715; 1663; -128717; 1657; -128719; 1657; -128721; 1657; -128723; 1657; -128725; 1700; -128727; 1700; -128729; 1700; -128731; 1700; -128733; 1702; -128735; 1702; -128737; 1702; -128739; 1702; -128741; 1668; -128743; 1668; -128745; 1668; -128747; 1668; -128749; 1667; -128751; 1667; -128753; 1667; -128755; 1667; -128757; 1670; -128759; 1670; -128761; 1670; -128763; 1670; -128765; 1671; -128767; 1671; -128769; 1671; -128771; 1671; -128773; 1677; -128775; 1677; -128777; 1676; -128779; 1676; -128781; 1678; -128783; 1678; -128785; 1672; -128787; 1672; -128789; 1688; -128791; 1688; -128793; 1681; -128795; 1681; -128797; 1705; -128799; 1705; -128801; 1705; -128803; 1705; -128805; 1711; -128807; 1711; -128809; 1711; -128811; 1711; -128813; 1715; -128815; 1715; -128817; 1715; -128819; 1715; -128821; 1713; -128823; 1713; -128825; 1713; -128827; 1713; -128829; 1722; -128831; 1722; -128833; 1723; -128835; 1723; -128837; 1723; -128839; 1723; -128841; 1728; -128843; 1728; -128845; 1729; -128847; 1729; -128849; 1729; -128851; 1729; -128853; 1726; -128855; 1726; -128857; 1726; -128859; 1726; -128861; 1746; -128863; 1746; -128865; 1747; -128867; 1747; -128935; 1709; -128937; 1709; -128939; 1709; -128941; 1709; -128943; 1735; -128945; 1735; -128947; 1734; -128949; 1734; -128951; 1736; -128953; 1736; -128955; 1655; -128957; 1739; -128959; 1739; -128961; 1733; -128963; 1733; -128965; 1737; -128967; 1737; -128969; 1744; -128971; 1744; -128973; 1744; -128975; 1744; -128977; 1609; -128979; 1609; -128981; 1574; 1575; -128983; 1574; 1575; -128985; 1574; 1749; -128987; 1574; 1749; -128989; 1574; 1608; -128991; 1574; 1608; -128993; 1574; 1735; -128995; 1574; 1735; -128997; 1574; 1734; -128999; 1574; 1734; -129001; 1574; 1736; -129003; 1574; 1736; -129005; 1574; 1744; -129007; 1574; 1744; -129009; 1574; 1744; -129011; 1574; 1609; -129013; 1574; 1609; -129015; 1574; 1609; -129017; 1740; -129019; 1740; -129021; 1740; -129023; 1740; -129025; 1574; 1580; -129027; 1574; 1581; -129029; 1574; 1605; -129031; 1574; 1609; -129033; 1574; 1610; -129035; 1576; 1580; -129037; 1576; 1581; -129039; 1576; 1582; -129041; 1576; 1605; -129043; 1576; 1609; -129045; 1576; 1610; -129047; 1578; 1580; -129049; 1578; 1581; -129051; 1578; 1582; -129053; 1578; 1605; -129055; 1578; 1609; -129057; 1578; 1610; -129059; 1579; 1580; -129061; 1579; 1605; -129063; 1579; 1609; -129065; 1579; 1610; -129067; 1580; 1581; -129069; 1580; 1605; -129071; 1581; 1580; -129073; 1581; 1605; -129075; 1582; 1580; -129077; 1582; 1581; -129079; 1582; 1605; -129081; 1587; 1580; -129083; 1587; 1581; -129085; 1587; 1582; -129087; 1587; 1605; -129089; 1589; 1581; -129091; 1589; 1605; -129093; 1590; 1580; -129095; 1590; 1581; -129097; 1590; 1582; -129099; 1590; 1605; -129101; 1591; 1581; -129103; 1591; 1605; -129105; 1592; 1605; -129107; 1593; 1580; -129109; 1593; 1605; -129111; 1594; 1580; -129113; 1594; 1605; -129115; 1601; 1580; -129117; 1601; 1581; -129119; 1601; 1582; -129121; 1601; 1605; -129123; 1601; 1609; -129125; 1601; 1610; -129127; 1602; 1581; -129129; 1602; 1605; -129131; 1602; 1609; -129133; 1602; 1610; -129135; 1603; 1575; -129137; 1603; 1580; -129139; 1603; 1581; -129141; 1603; 1582; -129143; 1603; 1604; -129145; 1603; 1605; -129147; 1603; 1609; -129149; 1603; 1610; -129151; 1604; 1580; -129153; 1604; 1581; -129155; 1604; 1582; -129157; 1604; 1605; -129159; 1604; 1609; -129161; 1604; 1610; -129163; 1605; 1580; -129165; 1605; 1581; -129167; 1605; 1582; -129169; 1605; 1605; -129171; 1605; 1609; -129173; 1605; 1610; -129175; 1606; 1580; -129177; 1606; 1581; -129179; 1606; 1582; -129181; 1606; 1605; -129183; 1606; 1609; -129185; 1606; 1610; -129187; 1607; 1580; -129189; 1607; 1605; -129191; 1607; 1609; -129193; 1607; 1610; -129195; 1610; 1580; -129197; 1610; 1581; -129199; 1610; 1582; -129201; 1610; 1605; -129203; 1610; 1609; -129205; 1610; 1610; -129207; 1584; 1648; -129209; 1585; 1648; -129211; 1609; 1648; -129213; 32; 1612; 1617; -129215; 32; 1613; 1617; -129217; 32; 1614; 1617; -129219; 32; 1615; 1617; -129221; 32; 1616; 1617; -129223; 32; 1617; 1648; -129225; 1574; 1585; -129227; 1574; 1586; -129229; 1574; 1605; -129231; 1574; 1606; -129233; 1574; 1609; -129235; 1574; 1610; -129237; 1576; 1585; -129239; 1576; 1586; -129241; 1576; 1605; -129243; 1576; 1606; -129245; 1576; 1609; -129247; 1576; 1610; -129249; 1578; 1585; -129251; 1578; 1586; -129253; 1578; 1605; -129255; 1578; 1606; -129257; 1578; 1609; -129259; 1578; 1610; -129261; 1579; 1585; -129263; 1579; 1586; -129265; 1579; 1605; -129267; 1579; 1606; -129269; 1579; 1609; -129271; 1579; 1610; -129273; 1601; 1609; -129275; 1601; 1610; -129277; 1602; 1609; -129279; 1602; 1610; -129281; 1603; 1575; -129283; 1603; 1604; -129285; 1603; 1605; -129287; 1603; 1609; -129289; 1603; 1610; -129291; 1604; 1605; -129293; 1604; 1609; -129295; 1604; 1610; -129297; 1605; 1575; -129299; 1605; 1605; -129301; 1606; 1585; -129303; 1606; 1586; -129305; 1606; 1605; -129307; 1606; 1606; -129309; 1606; 1609; -129311; 1606; 1610; -129313; 1609; 1648; -129315; 1610; 1585; -129317; 1610; 1586; -129319; 1610; 1605; -129321; 1610; 1606; -129323; 1610; 1609; -129325; 1610; 1610; -129327; 1574; 1580; -129329; 1574; 1581; -129331; 1574; 1582; -129333; 1574; 1605; -129335; 1574; 1607; -129337; 1576; 1580; -129339; 1576; 1581; -129341; 1576; 1582; -129343; 1576; 1605; -129345; 1576; 1607; -129347; 1578; 1580; -129349; 1578; 1581; -129351; 1578; 1582; -129353; 1578; 1605; -129355; 1578; 1607; -129357; 1579; 1605; -129359; 1580; 1581; -129361; 1580; 1605; -129363; 1581; 1580; -129365; 1581; 1605; -129367; 1582; 1580; -129369; 1582; 1605; -129371; 1587; 1580; -129373; 1587; 1581; -129375; 1587; 1582; -129377; 1587; 1605; -129379; 1589; 1581; -129381; 1589; 1582; -129383; 1589; 1605; -129385; 1590; 1580; -129387; 1590; 1581; -129389; 1590; 1582; -129391; 1590; 1605; -129393; 1591; 1581; -129395; 1592; 1605; -129397; 1593; 1580; -129399; 1593; 1605; -129401; 1594; 1580; -129403; 1594; 1605; -129405; 1601; 1580; -129407; 1601; 1581; -129409; 1601; 1582; -129411; 1601; 1605; -129413; 1602; 1581; -129415; 1602; 1605; -129417; 1603; 1580; -129419; 1603; 1581; -129421; 1603; 1582; -129423; 1603; 1604; -129425; 1603; 1605; -129427; 1604; 1580; -129429; 1604; 1581; -129431; 1604; 1582; -129433; 1604; 1605; -129435; 1604; 1607; -129437; 1605; 1580; -129439; 1605; 1581; -129441; 1605; 1582; -129443; 1605; 1605; -129445; 1606; 1580; -129447; 1606; 1581; -129449; 1606; 1582; -129451; 1606; 1605; -129453; 1606; 1607; -129455; 1607; 1580; -129457; 1607; 1605; -129459; 1607; 1648; -129461; 1610; 1580; -129463; 1610; 1581; -129465; 1610; 1582; -129467; 1610; 1605; -129469; 1610; 1607; -129471; 1574; 1605; -129473; 1574; 1607; -129475; 1576; 1605; -129477; 1576; 1607; -129479; 1578; 1605; -129481; 1578; 1607; -129483; 1579; 1605; -129485; 1579; 1607; -129487; 1587; 1605; -129489; 1587; 1607; -129491; 1588; 1605; -129493; 1588; 1607; -129495; 1603; 1604; -129497; 1603; 1605; -129499; 1604; 1605; -129501; 1606; 1605; -129503; 1606; 1607; -129505; 1610; 1605; -129507; 1610; 1607; -129509; 1600; 1614; 1617; -129511; 1600; 1615; 1617; -129513; 1600; 1616; 1617; -129515; 1591; 1609; -129517; 1591; 1610; -129519; 1593; 1609; -129521; 1593; 1610; -129523; 1594; 1609; -129525; 1594; 1610; -129527; 1587; 1609; -129529; 1587; 1610; -129531; 1588; 1609; -129533; 1588; 1610; -129535; 1581; 1609; -129537; 1581; 1610; -129539; 1580; 1609; -129541; 1580; 1610; -129543; 1582; 1609; -129545; 1582; 1610; -129547; 1589; 1609; -129549; 1589; 1610; -129551; 1590; 1609; -129553; 1590; 1610; -129555; 1588; 1580; -129557; 1588; 1581; -129559; 1588; 1582; -129561; 1588; 1605; -129563; 1588; 1585; -129565; 1587; 1585; -129567; 1589; 1585; -129569; 1590; 1585; -129571; 1591; 1609; -129573; 1591; 1610; -129575; 1593; 1609; -129577; 1593; 1610; -129579; 1594; 1609; -129581; 1594; 1610; -129583; 1587; 1609; -129585; 1587; 1610; -129587; 1588; 1609; -129589; 1588; 1610; -129591; 1581; 1609; -129593; 1581; 1610; -129595; 1580; 1609; -129597; 1580; 1610; -129599; 1582; 1609; -129601; 1582; 1610; -129603; 1589; 1609; -129605; 1589; 1610; -129607; 1590; 1609; -129609; 1590; 1610; -129611; 1588; 1580; -129613; 1588; 1581; -129615; 1588; 1582; -129617; 1588; 1605; -129619; 1588; 1585; -129621; 1587; 1585; -129623; 1589; 1585; -129625; 1590; 1585; -129627; 1588; 1580; -129629; 1588; 1581; -129631; 1588; 1582; -129633; 1588; 1605; -129635; 1587; 1607; -129637; 1588; 1607; -129639; 1591; 1605; -129641; 1587; 1580; -129643; 1587; 1581; -129645; 1587; 1582; -129647; 1588; 1580; -129649; 1588; 1581; -129651; 1588; 1582; -129653; 1591; 1605; -129655; 1592; 1605; -129657; 1575; 1611; -129659; 1575; 1611; -129697; 1578; 1580; 1605; -129699; 1578; 1581; 1580; -129701; 1578; 1581; 1580; -129703; 1578; 1581; 1605; -129705; 1578; 1582; 1605; -129707; 1578; 1605; 1580; -129709; 1578; 1605; 1581; -129711; 1578; 1605; 1582; -129713; 1580; 1605; 1581; -129715; 1580; 1605; 1581; -129717; 1581; 1605; 1610; -129719; 1581; 1605; 1609; -129721; 1587; 1581; 1580; -129723; 1587; 1580; 1581; -129725; 1587; 1580; 1609; -129727; 1587; 1605; 1581; -129729; 1587; 1605; 1581; -129731; 1587; 1605; 1580; -129733; 1587; 1605; 1605; -129735; 1587; 1605; 1605; -129737; 1589; 1581; 1581; -129739; 1589; 1581; 1581; -129741; 1589; 1605; 1605; -129743; 1588; 1581; 1605; -129745; 1588; 1581; 1605; -129747; 1588; 1580; 1610; -129749; 1588; 1605; 1582; -129751; 1588; 1605; 1582; -129753; 1588; 1605; 1605; -129755; 1588; 1605; 1605; -129757; 1590; 1581; 1609; -129759; 1590; 1582; 1605; -129761; 1590; 1582; 1605; -129763; 1591; 1605; 1581; -129765; 1591; 1605; 1581; -129767; 1591; 1605; 1605; -129769; 1591; 1605; 1610; -129771; 1593; 1580; 1605; -129773; 1593; 1605; 1605; -129775; 1593; 1605; 1605; -129777; 1593; 1605; 1609; -129779; 1594; 1605; 1605; -129781; 1594; 1605; 1610; -129783; 1594; 1605; 1609; -129785; 1601; 1582; 1605; -129787; 1601; 1582; 1605; -129789; 1602; 1605; 1581; -129791; 1602; 1605; 1605; -129793; 1604; 1581; 1605; -129795; 1604; 1581; 1610; -129797; 1604; 1581; 1609; -129799; 1604; 1580; 1580; -129801; 1604; 1580; 1580; -129803; 1604; 1582; 1605; -129805; 1604; 1582; 1605; -129807; 1604; 1605; 1581; -129809; 1604; 1605; 1581; -129811; 1605; 1581; 1580; -129813; 1605; 1581; 1605; -129815; 1605; 1581; 1610; -129817; 1605; 1580; 1581; -129819; 1605; 1580; 1605; -129821; 1605; 1582; 1580; -129823; 1605; 1582; 1605; -129829; 1605; 1580; 1582; -129831; 1607; 1605; 1580; -129833; 1607; 1605; 1605; -129835; 1606; 1581; 1605; -129837; 1606; 1581; 1609; -129839; 1606; 1580; 1605; -129841; 1606; 1580; 1605; -129843; 1606; 1580; 1609; -129845; 1606; 1605; 1610; -129847; 1606; 1605; 1609; -129849; 1610; 1605; 1605; -129851; 1610; 1605; 1605; -129853; 1576; 1582; 1610; -129855; 1578; 1580; 1610; -129857; 1578; 1580; 1609; -129859; 1578; 1582; 1610; -129861; 1578; 1582; 1609; -129863; 1578; 1605; 1610; -129865; 1578; 1605; 1609; -129867; 1580; 1605; 1610; -129869; 1580; 1581; 1609; -129871; 1580; 1605; 1609; -129873; 1587; 1582; 1609; -129875; 1589; 1581; 1610; -129877; 1588; 1581; 1610; -129879; 1590; 1581; 1610; -129881; 1604; 1580; 1610; -129883; 1604; 1605; 1610; -129885; 1610; 1581; 1610; -129887; 1610; 1580; 1610; -129889; 1610; 1605; 1610; -129891; 1605; 1605; 1610; -129893; 1602; 1605; 1610; -129895; 1606; 1581; 1610; -129897; 1602; 1605; 1581; -129899; 1604; 1581; 1605; -129901; 1593; 1605; 1610; -129903; 1603; 1605; 1610; -129905; 1606; 1580; 1581; -129907; 1605; 1582; 1610; -129909; 1604; 1580; 1605; -129911; 1603; 1605; 1605; -129913; 1604; 1580; 1605; -129915; 1606; 1580; 1581; -129917; 1580; 1581; 1610; -129919; 1581; 1580; 1610; -129921; 1605; 1580; 1610; -129923; 1601; 1605; 1610; -129925; 1576; 1581; 1610; -129927; 1603; 1605; 1605; -129929; 1593; 1580; 1605; -129931; 1589; 1605; 1605; -129933; 1587; 1582; 1610; -129935; 1606; 1580; 1610; -130017; 1589; 1604; 1746; -130019; 1602; 1604; 1746; -130021; 1575; 1604; 1604; 1607; -130023; 1575; 1603; 1576; 1585; -130025; 1605; 1581; 1605; 1583; -130027; 1589; 1604; 1593; 1605; -130029; 1585; 1587; 1608; 1604; -130031; 1593; 1604; 1610; 1607; -130033; 1608; 1587; 1604; 1605; -130035; 1589; 1604; 1609; -130037; 1589; 1604; 1609; 32; 1575; 1604; 1604; 1607; 32; 1593; 1604; 1610; 1607; 32; 1608; 1587; 1604; 1605; -130039; 1580; 1604; 32; 1580; 1604; 1575; 1604; 1607; -130041; 1585; 1740; 1575; 1604; -130145; 8229; -130147; 8212; -130149; 8211; -130151; 95; -130153; 95; -130155; 40; -130157; 41; -130159; 123; -130161; 125; -130163; 12308; -130165; 12309; -130167; 12304; -130169; 12305; -130171; 12298; -130173; 12299; -130175; 12296; -130177; 12297; -130179; 12300; -130181; 12301; -130183; 12302; -130185; 12303; -130195; 8254; -130197; 8254; -130199; 8254; -130201; 8254; -130203; 95; -130205; 95; -130207; 95; -130209; 44; -130211; 12289; -130213; 46; -130217; 59; -130219; 58; -130221; 63; -130223; 33; -130225; 8212; -130227; 40; -130229; 41; -130231; 123; -130233; 125; -130235; 12308; -130237; 12309; -130239; 35; -130241; 38; -130243; 42; -130245; 43; -130247; 45; -130249; 60; -130251; 62; -130253; 61; -130257; 92; -130259; 36; -130261; 37; -130263; 64; -130273; 32; 1611; -130275; 1600; 1611; -130277; 32; 1612; -130281; 32; 1613; -130285; 32; 1614; -130287; 1600; 1614; -130289; 32; 1615; -130291; 1600; 1615; -130293; 32; 1616; -130295; 1600; 1616; -130297; 32; 1617; -130299; 1600; 1617; -130301; 32; 1618; -130303; 1600; 1618; -130305; 1569; -130307; 1570; -130309; 1570; -130311; 1571; -130313; 1571; -130315; 1572; -130317; 1572; -130319; 1573; -130321; 1573; -130323; 1574; -130325; 1574; -130327; 1574; -130329; 1574; -130331; 1575; -130333; 1575; -130335; 1576; -130337; 1576; -130339; 1576; -130341; 1576; -130343; 1577; -130345; 1577; -130347; 1578; -130349; 1578; -130351; 1578; -130353; 1578; -130355; 1579; -130357; 1579; -130359; 1579; -130361; 1579; -130363; 1580; -130365; 1580; -130367; 1580; -130369; 1580; -130371; 1581; -130373; 1581; -130375; 1581; -130377; 1581; -130379; 1582; -130381; 1582; -130383; 1582; -130385; 1582; -130387; 1583; -130389; 1583; -130391; 1584; -130393; 1584; -130395; 1585; -130397; 1585; -130399; 1586; -130401; 1586; -130403; 1587; -130405; 1587; -130407; 1587; -130409; 1587; -130411; 1588; -130413; 1588; -130415; 1588; -130417; 1588; -130419; 1589; -130421; 1589; -130423; 1589; -130425; 1589; -130427; 1590; -130429; 1590; -130431; 1590; -130433; 1590; -130435; 1591; -130437; 1591; -130439; 1591; -130441; 1591; -130443; 1592; -130445; 1592; -130447; 1592; -130449; 1592; -130451; 1593; -130453; 1593; -130455; 1593; -130457; 1593; -130459; 1594; -130461; 1594; -130463; 1594; -130465; 1594; -130467; 1601; -130469; 1601; -130471; 1601; -130473; 1601; -130475; 1602; -130477; 1602; -130479; 1602; -130481; 1602; -130483; 1603; -130485; 1603; -130487; 1603; -130489; 1603; -130491; 1604; -130493; 1604; -130495; 1604; -130497; 1604; -130499; 1605; -130501; 1605; -130503; 1605; -130505; 1605; -130507; 1606; -130509; 1606; -130511; 1606; -130513; 1606; -130515; 1607; -130517; 1607; -130519; 1607; -130521; 1607; -130523; 1608; -130525; 1608; -130527; 1609; -130529; 1609; -130531; 1610; -130533; 1610; -130535; 1610; -130537; 1610; -130539; 1604; 1570; -130541; 1604; 1570; -130543; 1604; 1571; -130545; 1604; 1571; -130547; 1604; 1573; -130549; 1604; 1573; -130551; 1604; 1575; -130553; 1604; 1575; -130563; 33; -130565; 34; -130567; 35; -130569; 36; -130571; 37; -130573; 38; -130575; 39; -130577; 40; -130579; 41; -130581; 42; -130583; 43; -130585; 44; -130587; 45; -130589; 46; -130591; 47; -130593; 48; -130595; 49; -130597; 50; -130599; 51; -130601; 52; -130603; 53; -130605; 54; -130607; 55; -130609; 56; -130611; 57; -130613; 58; -130615; 59; -130617; 60; -130619; 61; -130621; 62; -130623; 63; -130625; 64; -130627; 65; -130629; 66; -130631; 67; -130633; 68; -130635; 69; -130637; 70; -130639; 71; -130641; 72; -130643; 73; -130645; 74; -130647; 75; -130649; 76; -130651; 77; -130653; 78; -130655; 79; -130657; 80; -130659; 81; -130661; 82; -130663; 83; -130665; 84; -130667; 85; -130669; 86; -130671; 87; -130673; 88; -130675; 89; -130677; 90; -130679; 91; -130681; 92; -130683; 93; -130685; 94; -130687; 95; -130689; 96; -130691; 97; -130693; 98; -130695; 99; -130697; 100; -130699; 101; -130701; 102; -130703; 103; -130705; 104; -130707; 105; -130709; 106; -130711; 107; -130713; 108; -130715; 109; -130717; 110; -130719; 111; -130721; 112; -130723; 113; -130725; 114; -130727; 115; -130729; 116; -130731; 117; -130733; 118; -130735; 119; -130737; 120; -130739; 121; -130741; 122; -130743; 123; -130745; 124; -130747; 125; -130749; 126; -130751; 10629; -130753; 10630; -130755; 12290; -130757; 12300; -130759; 12301; -130761; 12289; -130763; 12539; -130765; 12530; -130767; 12449; -130769; 12451; -130771; 12453; -130773; 12455; -130775; 12457; -130777; 12515; -130779; 12517; -130781; 12519; -130783; 12483; -130785; 12540; -130787; 12450; -130789; 12452; -130791; 12454; -130793; 12456; -130795; 12458; -130797; 12459; -130799; 12461; -130801; 12463; -130803; 12465; -130805; 12467; -130807; 12469; -130809; 12471; -130811; 12473; -130813; 12475; -130815; 12477; -130817; 12479; -130819; 12481; -130821; 12484; -130823; 12486; -130825; 12488; -130827; 12490; -130829; 12491; -130831; 12492; -130833; 12493; -130835; 12494; -130837; 12495; -130839; 12498; -130841; 12501; -130843; 12504; -130845; 12507; -130847; 12510; -130849; 12511; -130851; 12512; -130853; 12513; -130855; 12514; -130857; 12516; -130859; 12518; -130861; 12520; -130863; 12521; -130865; 12522; -130867; 12523; -130869; 12524; -130871; 12525; -130873; 12527; -130875; 12531; -130877; 12441; -130879; 12442; -130881; 12644; -130883; 12593; -130885; 12594; -130887; 12595; -130889; 12596; -130891; 12597; -130893; 12598; -130895; 12599; -130897; 12600; -130899; 12601; -130901; 12602; -130903; 12603; -130905; 12604; -130907; 12605; -130909; 12606; -130911; 12607; -130913; 12608; -130915; 12609; -130917; 12610; -130919; 12611; -130921; 12612; -130923; 12613; -130925; 12614; -130927; 12615; -130929; 12616; -130931; 12617; -130933; 12618; -130935; 12619; -130937; 12620; -130939; 12621; -130941; 12622; -130949; 12623; -130951; 12624; -130953; 12625; -130955; 12626; -130957; 12627; -130959; 12628; -130965; 12629; -130967; 12630; -130969; 12631; -130971; 12632; -130973; 12633; -130975; 12634; -130981; 12635; -130983; 12636; -130985; 12637; -130987; 12638; -130989; 12639; -130991; 12640; -130997; 12641; -130999; 12642; -131001; 12643; -131009; 162; -131011; 163; -131013; 172; -131015; 175; -131017; 166; -131019; 165; -131021; 8361; -131025; 9474; -131027; 8592; -131029; 8593; -131031; 8594; -131033; 8595; -131035; 9632; -131037; 9675; -238268; 119127; 119141; -238270; 119128; 119141; -238272; 119135; 119150; -238274; 119135; 119151; -238276; 119135; 119152; -238278; 119135; 119153; -238280; 119135; 119154; -238454; 119225; 119141; -238456; 119226; 119141; -238458; 119227; 119150; -238460; 119228; 119150; -238462; 119227; 119151; -238464; 119228; 119151; -239617; 65; -239619; 66; -239621; 67; -239623; 68; -239625; 69; -239627; 70; -239629; 71; -239631; 72; -239633; 73; -239635; 74; -239637; 75; -239639; 76; -239641; 77; -239643; 78; -239645; 79; -239647; 80; -239649; 81; -239651; 82; -239653; 83; -239655; 84; -239657; 85; -239659; 86; -239661; 87; -239663; 88; -239665; 89; -239667; 90; -239669; 97; -239671; 98; -239673; 99; -239675; 100; -239677; 101; -239679; 102; -239681; 103; -239683; 104; -239685; 105; -239687; 106; -239689; 107; -239691; 108; -239693; 109; -239695; 110; -239697; 111; -239699; 112; -239701; 113; -239703; 114; -239705; 115; -239707; 116; -239709; 117; -239711; 118; -239713; 119; -239715; 120; -239717; 121; -239719; 122; -239721; 65; -239723; 66; -239725; 67; -239727; 68; -239729; 69; -239731; 70; -239733; 71; -239735; 72; -239737; 73; -239739; 74; -239741; 75; -239743; 76; -239745; 77; -239747; 78; -239749; 79; -239751; 80; -239753; 81; -239755; 82; -239757; 83; -239759; 84; -239761; 85; -239763; 86; -239765; 87; -239767; 88; -239769; 89; -239771; 90; -239773; 97; -239775; 98; -239777; 99; -239779; 100; -239781; 101; -239783; 102; -239785; 103; -239789; 105; -239791; 106; -239793; 107; -239795; 108; -239797; 109; -239799; 110; -239801; 111; -239803; 112; -239805; 113; -239807; 114; -239809; 115; -239811; 116; -239813; 117; -239815; 118; -239817; 119; -239819; 120; -239821; 121; -239823; 122; -239825; 65; -239827; 66; -239829; 67; -239831; 68; -239833; 69; -239835; 70; -239837; 71; -239839; 72; -239841; 73; -239843; 74; -239845; 75; -239847; 76; -239849; 77; -239851; 78; -239853; 79; -239855; 80; -239857; 81; -239859; 82; -239861; 83; -239863; 84; -239865; 85; -239867; 86; -239869; 87; -239871; 88; -239873; 89; -239875; 90; -239877; 97; -239879; 98; -239881; 99; -239883; 100; -239885; 101; -239887; 102; -239889; 103; -239891; 104; -239893; 105; -239895; 106; -239897; 107; -239899; 108; -239901; 109; -239903; 110; -239905; 111; -239907; 112; -239909; 113; -239911; 114; -239913; 115; -239915; 116; -239917; 117; -239919; 118; -239921; 119; -239923; 120; -239925; 121; -239927; 122; -239929; 65; -239933; 67; -239935; 68; -239941; 71; -239947; 74; -239949; 75; -239955; 78; -239957; 79; -239959; 80; -239961; 81; -239965; 83; -239967; 84; -239969; 85; -239971; 86; -239973; 87; -239975; 88; -239977; 89; -239979; 90; -239981; 97; -239983; 98; -239985; 99; -239987; 100; -239991; 102; -239995; 104; -239997; 105; -239999; 106; -240001; 107; -240005; 109; -240007; 110; -240011; 112; -240013; 113; -240015; 114; -240017; 115; -240019; 116; -240021; 117; -240023; 118; -240025; 119; -240027; 120; -240029; 121; -240031; 122; -240033; 65; -240035; 66; -240037; 67; -240039; 68; -240041; 69; -240043; 70; -240045; 71; -240047; 72; -240049; 73; -240051; 74; -240053; 75; -240055; 76; -240057; 77; -240059; 78; -240061; 79; -240063; 80; -240065; 81; -240067; 82; -240069; 83; -240071; 84; -240073; 85; -240075; 86; -240077; 87; -240079; 88; -240081; 89; -240083; 90; -240085; 97; -240087; 98; -240089; 99; -240091; 100; -240093; 101; -240095; 102; -240097; 103; -240099; 104; -240101; 105; -240103; 106; -240105; 107; -240107; 108; -240109; 109; -240111; 110; -240113; 111; -240115; 112; -240117; 113; -240119; 114; -240121; 115; -240123; 116; -240125; 117; -240127; 118; -240129; 119; -240131; 120; -240133; 121; -240135; 122; -240137; 65; -240139; 66; -240143; 68; -240145; 69; -240147; 70; -240149; 71; -240155; 74; -240157; 75; -240159; 76; -240161; 77; -240163; 78; -240165; 79; -240167; 80; -240169; 81; -240173; 83; -240175; 84; -240177; 85; -240179; 86; -240181; 87; -240183; 88; -240185; 89; -240189; 97; -240191; 98; -240193; 99; -240195; 100; -240197; 101; -240199; 102; -240201; 103; -240203; 104; -240205; 105; -240207; 106; -240209; 107; -240211; 108; -240213; 109; -240215; 110; -240217; 111; -240219; 112; -240221; 113; -240223; 114; -240225; 115; -240227; 116; -240229; 117; -240231; 118; -240233; 119; -240235; 120; -240237; 121; -240239; 122; -240241; 65; -240243; 66; -240247; 68; -240249; 69; -240251; 70; -240253; 71; -240257; 73; -240259; 74; -240261; 75; -240263; 76; -240265; 77; -240269; 79; -240277; 83; -240279; 84; -240281; 85; -240283; 86; -240285; 87; -240287; 88; -240289; 89; -240293; 97; -240295; 98; -240297; 99; -240299; 100; -240301; 101; -240303; 102; -240305; 103; -240307; 104; -240309; 105; -240311; 106; -240313; 107; -240315; 108; -240317; 109; -240319; 110; -240321; 111; -240323; 112; -240325; 113; -240327; 114; -240329; 115; -240331; 116; -240333; 117; -240335; 118; -240337; 119; -240339; 120; -240341; 121; -240343; 122; -240345; 65; -240347; 66; -240349; 67; -240351; 68; -240353; 69; -240355; 70; -240357; 71; -240359; 72; -240361; 73; -240363; 74; -240365; 75; -240367; 76; -240369; 77; -240371; 78; -240373; 79; -240375; 80; -240377; 81; -240379; 82; -240381; 83; -240383; 84; -240385; 85; -240387; 86; -240389; 87; -240391; 88; -240393; 89; -240395; 90; -240397; 97; -240399; 98; -240401; 99; -240403; 100; -240405; 101; -240407; 102; -240409; 103; -240411; 104; -240413; 105; -240415; 106; -240417; 107; -240419; 108; -240421; 109; -240423; 110; -240425; 111; -240427; 112; -240429; 113; -240431; 114; -240433; 115; -240435; 116; -240437; 117; -240439; 118; -240441; 119; -240443; 120; -240445; 121; -240447; 122; -240449; 65; -240451; 66; -240453; 67; -240455; 68; -240457; 69; -240459; 70; -240461; 71; -240463; 72; -240465; 73; -240467; 74; -240469; 75; -240471; 76; -240473; 77; -240475; 78; -240477; 79; -240479; 80; -240481; 81; -240483; 82; -240485; 83; -240487; 84; -240489; 85; -240491; 86; -240493; 87; -240495; 88; -240497; 89; -240499; 90; -240501; 97; -240503; 98; -240505; 99; -240507; 100; -240509; 101; -240511; 102; -240513; 103; -240515; 104; -240517; 105; -240519; 106; -240521; 107; -240523; 108; -240525; 109; -240527; 110; -240529; 111; -240531; 112; -240533; 113; -240535; 114; -240537; 115; -240539; 116; -240541; 117; -240543; 118; -240545; 119; -240547; 120; -240549; 121; -240551; 122; -240553; 65; -240555; 66; -240557; 67; -240559; 68; -240561; 69; -240563; 70; -240565; 71; -240567; 72; -240569; 73; -240571; 74; -240573; 75; -240575; 76; -240577; 77; -240579; 78; -240581; 79; -240583; 80; -240585; 81; -240587; 82; -240589; 83; -240591; 84; -240593; 85; -240595; 86; -240597; 87; -240599; 88; -240601; 89; -240603; 90; -240605; 97; -240607; 98; -240609; 99; -240611; 100; -240613; 101; -240615; 102; -240617; 103; -240619; 104; -240621; 105; -240623; 106; -240625; 107; -240627; 108; -240629; 109; -240631; 110; -240633; 111; -240635; 112; -240637; 113; -240639; 114; -240641; 115; -240643; 116; -240645; 117; -240647; 118; -240649; 119; -240651; 120; -240653; 121; -240655; 122; -240657; 65; -240659; 66; -240661; 67; -240663; 68; -240665; 69; -240667; 70; -240669; 71; -240671; 72; -240673; 73; -240675; 74; -240677; 75; -240679; 76; -240681; 77; -240683; 78; -240685; 79; -240687; 80; -240689; 81; -240691; 82; -240693; 83; -240695; 84; -240697; 85; -240699; 86; -240701; 87; -240703; 88; -240705; 89; -240707; 90; -240709; 97; -240711; 98; -240713; 99; -240715; 100; -240717; 101; -240719; 102; -240721; 103; -240723; 104; -240725; 105; -240727; 106; -240729; 107; -240731; 108; -240733; 109; -240735; 110; -240737; 111; -240739; 112; -240741; 113; -240743; 114; -240745; 115; -240747; 116; -240749; 117; -240751; 118; -240753; 119; -240755; 120; -240757; 121; -240759; 122; -240761; 65; -240763; 66; -240765; 67; -240767; 68; -240769; 69; -240771; 70; -240773; 71; -240775; 72; -240777; 73; -240779; 74; -240781; 75; -240783; 76; -240785; 77; -240787; 78; -240789; 79; -240791; 80; -240793; 81; -240795; 82; -240797; 83; -240799; 84; -240801; 85; -240803; 86; -240805; 87; -240807; 88; -240809; 89; -240811; 90; -240813; 97; -240815; 98; -240817; 99; -240819; 100; -240821; 101; -240823; 102; -240825; 103; -240827; 104; -240829; 105; -240831; 106; -240833; 107; -240835; 108; -240837; 109; -240839; 110; -240841; 111; -240843; 112; -240845; 113; -240847; 114; -240849; 115; -240851; 116; -240853; 117; -240855; 118; -240857; 119; -240859; 120; -240861; 121; -240863; 122; -240865; 65; -240867; 66; -240869; 67; -240871; 68; -240873; 69; -240875; 70; -240877; 71; -240879; 72; -240881; 73; -240883; 74; -240885; 75; -240887; 76; -240889; 77; -240891; 78; -240893; 79; -240895; 80; -240897; 81; -240899; 82; -240901; 83; -240903; 84; -240905; 85; -240907; 86; -240909; 87; -240911; 88; -240913; 89; -240915; 90; -240917; 97; -240919; 98; -240921; 99; -240923; 100; -240925; 101; -240927; 102; -240929; 103; -240931; 104; -240933; 105; -240935; 106; -240937; 107; -240939; 108; -240941; 109; -240943; 110; -240945; 111; -240947; 112; -240949; 113; -240951; 114; -240953; 115; -240955; 116; -240957; 117; -240959; 118; -240961; 119; -240963; 120; -240965; 121; -240967; 122; -240977; 913; -240979; 914; -240981; 915; -240983; 916; -240985; 917; -240987; 918; -240989; 919; -240991; 920; -240993; 921; -240995; 922; -240997; 923; -240999; 924; -241001; 925; -241003; 926; -241005; 927; -241007; 928; -241009; 929; -241011; 1012; -241013; 931; -241015; 932; -241017; 933; -241019; 934; -241021; 935; -241023; 936; -241025; 937; -241027; 8711; -241029; 945; -241031; 946; -241033; 947; -241035; 948; -241037; 949; -241039; 950; -241041; 951; -241043; 952; -241045; 953; -241047; 954; -241049; 955; -241051; 956; -241053; 957; -241055; 958; -241057; 959; -241059; 960; -241061; 961; -241063; 962; -241065; 963; -241067; 964; -241069; 965; -241071; 966; -241073; 967; -241075; 968; -241077; 969; -241079; 8706; -241081; 1013; -241083; 977; -241085; 1008; -241087; 981; -241089; 1009; -241091; 982; -241093; 913; -241095; 914; -241097; 915; -241099; 916; -241101; 917; -241103; 918; -241105; 919; -241107; 920; -241109; 921; -241111; 922; -241113; 923; -241115; 924; -241117; 925; -241119; 926; -241121; 927; -241123; 928; -241125; 929; -241127; 1012; -241129; 931; -241131; 932; -241133; 933; -241135; 934; -241137; 935; -241139; 936; -241141; 937; -241143; 8711; -241145; 945; -241147; 946; -241149; 947; -241151; 948; -241153; 949; -241155; 950; -241157; 951; -241159; 952; -241161; 953; -241163; 954; -241165; 955; -241167; 956; -241169; 957; -241171; 958; -241173; 959; -241175; 960; -241177; 961; -241179; 962; -241181; 963; -241183; 964; -241185; 965; -241187; 966; -241189; 967; -241191; 968; -241193; 969; -241195; 8706; -241197; 1013; -241199; 977; -241201; 1008; -241203; 981; -241205; 1009; -241207; 982; -241209; 913; -241211; 914; -241213; 915; -241215; 916; -241217; 917; -241219; 918; -241221; 919; -241223; 920; -241225; 921; -241227; 922; -241229; 923; -241231; 924; -241233; 925; -241235; 926; -241237; 927; -241239; 928; -241241; 929; -241243; 1012; -241245; 931; -241247; 932; -241249; 933; -241251; 934; -241253; 935; -241255; 936; -241257; 937; -241259; 8711; -241261; 945; -241263; 946; -241265; 947; -241267; 948; -241269; 949; -241271; 950; -241273; 951; -241275; 952; -241277; 953; -241279; 954; -241281; 955; -241283; 956; -241285; 957; -241287; 958; -241289; 959; -241291; 960; -241293; 961; -241295; 962; -241297; 963; -241299; 964; -241301; 965; -241303; 966; -241305; 967; -241307; 968; -241309; 969; -241311; 8706; -241313; 1013; -241315; 977; -241317; 1008; -241319; 981; -241321; 1009; -241323; 982; -241325; 913; -241327; 914; -241329; 915; -241331; 916; -241333; 917; -241335; 918; -241337; 919; -241339; 920; -241341; 921; -241343; 922; -241345; 923; -241347; 924; -241349; 925; -241351; 926; -241353; 927; -241355; 928; -241357; 929; -241359; 1012; -241361; 931; -241363; 932; -241365; 933; -241367; 934; -241369; 935; -241371; 936; -241373; 937; -241375; 8711; -241377; 945; -241379; 946; -241381; 947; -241383; 948; -241385; 949; -241387; 950; -241389; 951; -241391; 952; -241393; 953; -241395; 954; -241397; 955; -241399; 956; -241401; 957; -241403; 958; -241405; 959; -241407; 960; -241409; 961; -241411; 962; -241413; 963; -241415; 964; -241417; 965; -241419; 966; -241421; 967; -241423; 968; -241425; 969; -241427; 8706; -241429; 1013; -241431; 977; -241433; 1008; -241435; 981; -241437; 1009; -241439; 982; -241441; 913; -241443; 914; -241445; 915; -241447; 916; -241449; 917; -241451; 918; -241453; 919; -241455; 920; -241457; 921; -241459; 922; -241461; 923; -241463; 924; -241465; 925; -241467; 926; -241469; 927; -241471; 928; -241473; 929; -241475; 1012; -241477; 931; -241479; 932; -241481; 933; -241483; 934; -241485; 935; -241487; 936; -241489; 937; -241491; 8711; -241493; 945; -241495; 946; -241497; 947; -241499; 948; -241501; 949; -241503; 950; -241505; 951; -241507; 952; -241509; 953; -241511; 954; -241513; 955; -241515; 956; -241517; 957; -241519; 958; -241521; 959; -241523; 960; -241525; 961; -241527; 962; -241529; 963; -241531; 964; -241533; 965; -241535; 966; -241537; 967; -241539; 968; -241541; 969; -241543; 8706; -241545; 1013; -241547; 977; -241549; 1008; -241551; 981; -241553; 1009; -241555; 982; -241565; 48; -241567; 49; -241569; 50; -241571; 51; -241573; 52; -241575; 53; -241577; 54; -241579; 55; -241581; 56; -241583; 57; -241585; 48; -241587; 49; -241589; 50; -241591; 51; -241593; 52; -241595; 53; -241597; 54; -241599; 55; -241601; 56; -241603; 57; -241605; 48; -241607; 49; -241609; 50; -241611; 51; -241613; 52; -241615; 53; -241617; 54; -241619; 55; -241621; 56; -241623; 57; -241625; 48; -241627; 49; -241629; 50; -241631; 51; -241633; 52; -241635; 53; -241637; 54; -241639; 55; -241641; 56; -241643; 57; -241645; 48; -241647; 49; -241649; 50; -241651; 51; -241653; 52; -241655; 53; -241657; 54; -241659; 55; -241661; 56; -241663; 57; -389120; 20029; -389122; 20024; -389124; 20033; -389126; 131362; -389128; 20320; -389130; 20398; -389132; 20411; -389134; 20482; -389136; 20602; -389138; 20633; -389140; 20711; -389142; 20687; -389144; 13470; -389146; 132666; -389148; 20813; -389150; 20820; -389152; 20836; -389154; 20855; -389156; 132380; -389158; 13497; -389160; 20839; -389162; 20877; -389164; 132427; -389166; 20887; -389168; 20900; -389170; 20172; -389172; 20908; -389174; 20917; -389176; 168415; -389178; 20981; -389180; 20995; -389182; 13535; -389184; 21051; -389186; 21062; -389188; 21106; -389190; 21111; -389192; 13589; -389194; 21191; -389196; 21193; -389198; 21220; -389200; 21242; -389202; 21253; -389204; 21254; -389206; 21271; -389208; 21321; -389210; 21329; -389212; 21338; -389214; 21363; -389216; 21373; -389218; 21375; -389220; 21375; -389222; 21375; -389224; 133676; -389226; 28784; -389228; 21450; -389230; 21471; -389232; 133987; -389234; 21483; -389236; 21489; -389238; 21510; -389240; 21662; -389242; 21560; -389244; 21576; -389246; 21608; -389248; 21666; -389250; 21750; -389252; 21776; -389254; 21843; -389256; 21859; -389258; 21892; -389260; 21892; -389262; 21913; -389264; 21931; -389266; 21939; -389268; 21954; -389270; 22294; -389272; 22022; -389274; 22295; -389276; 22097; -389278; 22132; -389280; 20999; -389282; 22766; -389284; 22478; -389286; 22516; -389288; 22541; -389290; 22411; -389292; 22578; -389294; 22577; -389296; 22700; -389298; 136420; -389300; 22770; -389302; 22775; -389304; 22790; -389306; 22810; -389308; 22818; -389310; 22882; -389312; 136872; -389314; 136938; -389316; 23020; -389318; 23067; -389320; 23079; -389322; 23000; -389324; 23142; -389326; 14062; -389328; 136042; -389330; 23304; -389332; 23358; -389334; 23358; -389336; 137672; -389338; 23491; -389340; 23512; -389342; 23527; -389344; 23539; -389346; 138008; -389348; 23551; -389350; 23558; -389352; 24371; -389354; 23586; -389356; 14209; -389358; 23648; -389360; 23662; -389362; 23744; -389364; 23693; -389366; 138724; -389368; 23875; -389370; 138726; -389372; 23918; -389374; 23915; -389376; 23932; -389378; 24033; -389380; 24034; -389382; 14383; -389384; 24061; -389386; 24104; -389388; 24125; -389390; 24169; -389392; 14434; -389394; 139651; -389396; 14460; -389398; 24240; -389400; 24243; -389402; 24246; -389404; 24266; -389406; 172946; -389408; 24318; -389410; 140081; -389412; 140081; -389414; 33281; -389416; 24354; -389418; 24354; -389420; 14535; -389422; 144056; -389424; 156122; -389426; 24418; -389428; 24427; -389430; 14563; -389432; 24474; -389434; 24525; -389436; 24535; -389438; 24569; -389440; 24705; -389442; 14650; -389444; 14620; -389446; 24724; -389448; 141012; -389450; 24775; -389452; 24904; -389454; 24908; -389456; 24910; -389458; 24908; -389460; 24954; -389462; 24974; -389464; 25010; -389466; 24996; -389468; 25007; -389470; 25054; -389472; 25074; -389474; 25078; -389476; 25104; -389478; 25115; -389480; 25181; -389482; 25265; -389484; 25300; -389486; 25424; -389488; 142092; -389490; 25405; -389492; 25340; -389494; 25448; -389496; 25475; -389498; 25572; -389500; 142321; -389502; 25634; -389504; 25541; -389506; 25513; -389508; 14894; -389510; 25705; -389512; 25726; -389514; 25757; -389516; 25719; -389518; 14956; -389520; 25935; -389522; 25964; -389524; 143370; -389526; 26083; -389528; 26360; -389530; 26185; -389532; 15129; -389534; 26257; -389536; 15112; -389538; 15076; -389540; 20882; -389542; 20885; -389544; 26368; -389546; 26268; -389548; 32941; -389550; 17369; -389552; 26391; -389554; 26395; -389556; 26401; -389558; 26462; -389560; 26451; -389562; 144323; -389564; 15177; -389566; 26618; -389568; 26501; -389570; 26706; -389572; 26757; -389574; 144493; -389576; 26766; -389578; 26655; -389580; 26900; -389582; 15261; -389584; 26946; -389586; 27043; -389588; 27114; -389590; 27304; -389592; 145059; -389594; 27355; -389596; 15384; -389598; 27425; -389600; 145575; -389602; 27476; -389604; 15438; -389606; 27506; -389608; 27551; -389610; 27578; -389612; 27579; -389614; 146061; -389616; 138507; -389618; 146170; -389620; 27726; -389622; 146620; -389624; 27839; -389626; 27853; -389628; 27751; -389630; 27926; -389632; 27966; -389634; 28023; -389636; 27969; -389638; 28009; -389640; 28024; -389642; 28037; -389644; 146718; -389646; 27956; -389648; 28207; -389650; 28270; -389652; 15667; -389654; 28363; -389656; 28359; -389658; 147153; -389660; 28153; -389662; 28526; -389664; 147294; -389666; 147342; -389668; 28614; -389670; 28729; -389672; 28702; -389674; 28699; -389676; 15766; -389678; 28746; -389680; 28797; -389682; 28791; -389684; 28845; -389686; 132389; -389688; 28997; -389690; 148067; -389692; 29084; -389694; 17323; -389696; 29224; -389698; 29237; -389700; 29264; -389702; 149000; -389704; 29312; -389706; 29333; -389708; 149301; -389710; 149524; -389712; 29562; -389714; 29579; -389716; 16044; -389718; 29605; -389720; 16056; -389722; 16056; -389724; 29767; -389726; 29788; -389728; 29809; -389730; 29829; -389732; 29898; -389734; 16155; -389736; 29988; -389738; 150582; -389740; 30014; -389742; 150674; -389744; 30064; -389746; 139679; -389748; 30224; -389750; 151457; -389752; 151480; -389754; 151620; -389756; 16380; -389758; 16392; -389760; 30452; -389762; 151795; -389764; 151794; -389766; 151833; -389768; 151859; -389770; 30494; -389772; 30495; -389774; 30495; -389776; 30538; -389778; 16441; -389780; 30603; -389782; 16454; -389784; 16534; -389786; 152605; -389788; 30798; -389790; 30860; -389792; 30924; -389794; 16611; -389796; 153126; -389798; 31062; -389800; 153242; -389802; 153285; -389804; 31119; -389806; 31211; -389808; 16687; -389810; 31296; -389812; 31306; -389814; 31311; -389816; 153980; -389818; 154279; -389820; 154279; -389822; 31406; -389824; 16898; -389826; 154539; -389828; 31686; -389830; 31689; -389832; 16935; -389834; 154752; -389836; 31954; -389838; 17056; -389840; 31976; -389842; 31971; -389844; 32000; -389846; 155526; -389848; 32099; -389850; 17153; -389852; 32199; -389854; 32258; -389856; 32325; -389858; 17204; -389860; 156200; -389862; 156231; -389864; 17241; -389866; 156377; -389868; 32634; -389870; 156478; -389872; 32661; -389874; 32762; -389876; 32773; -389878; 156890; -389880; 156963; -389882; 32864; -389884; 157096; -389886; 32880; -389888; 144223; -389890; 17365; -389892; 32946; -389894; 33027; -389896; 17419; -389898; 33086; -389900; 23221; -389902; 157607; -389904; 157621; -389906; 144275; -389908; 144284; -389910; 33281; -389912; 33284; -389914; 36766; -389916; 17515; -389918; 33425; -389920; 33419; -389922; 33437; -389924; 21171; -389926; 33457; -389928; 33459; -389930; 33469; -389932; 33510; -389934; 158524; -389936; 33509; -389938; 33565; -389940; 33635; -389942; 33709; -389944; 33571; -389946; 33725; -389948; 33767; -389950; 33879; -389952; 33619; -389954; 33738; -389956; 33740; -389958; 33756; -389960; 158774; -389962; 159083; -389964; 158933; -389966; 17707; -389968; 34033; -389970; 34035; -389972; 34070; -389974; 160714; -389976; 34148; -389978; 159532; -389980; 17757; -389982; 17761; -389984; 159665; -389986; 159954; -389988; 17771; -389990; 34384; -389992; 34396; -389994; 34407; -389996; 34409; -389998; 34473; -390000; 34440; -390002; 34574; -390004; 34530; -390006; 34681; -390008; 34600; -390010; 34667; -390012; 34694; -390014; 19799; -390016; 34785; -390018; 34817; -390020; 17913; -390022; 34912; -390024; 34915; -390026; 161383; -390028; 35031; -390030; 35038; -390032; 17973; -390034; 35066; -390036; 13499; -390038; 161966; -390040; 162150; -390042; 18110; -390044; 18119; -390046; 35488; -390048; 35565; -390050; 35722; -390052; 35925; -390054; 162984; -390056; 36011; -390058; 36033; -390060; 36123; -390062; 36215; -390064; 163631; -390066; 133124; -390068; 36299; -390070; 36284; -390072; 36336; -390074; 133342; -390076; 36564; -390078; 36664; -390080; 165330; -390082; 165357; -390084; 37012; -390086; 37105; -390088; 37137; -390090; 165678; -390092; 37147; -390094; 37432; -390096; 37591; -390098; 37592; -390100; 37500; -390102; 37881; -390104; 37909; -390106; 166906; -390108; 38283; -390110; 18837; -390112; 38327; -390114; 167287; -390116; 18918; -390118; 38595; -390120; 23986; -390122; 38691; -390124; 168261; -390126; 168474; -390128; 19054; -390130; 19062; -390132; 38880; -390134; 168970; -390136; 19122; -390138; 169110; -390140; 38923; -390142; 38923; -390144; 38953; -390146; 169398; -390148; 39138; -390150; 19251; -390152; 39209; -390154; 39335; -390156; 39362; -390158; 39422; -390160; 19406; -390162; 170800; -390164; 39698; -390166; 40000; -390168; 40189; -390170; 19662; -390172; 19693; -390174; 40295; -390176; 172238; -390178; 19704; -390180; 172293; -390182; 172558; -390184; 172689; -390186; 40635; -390188; 19798; -390190; 40697; -390192; 40702; -390194; 40709; -390196; 40719; -390198; 40726; -390200; 40763; -390202; 173568 |] let randalcat = [| (1470,1470); (1472,1472); (1475,1475); (1488,1514); (1520,1524); (1563,1563); (1567,1567); (1569,1594); (1600,1610); (1645,1647); (1649,1749); (1757,1757); (1765,1766); (1786,1790); (1792,1805); (1808,1808); (1810,1836); (1920,1957); (1969,1969); (8207,8207); (64285,64285); (64287,64296); (64298,64310); (64312,64316); (64318,64318); (64320,64321); (64323,64324); (64326,64433); (64467,64829); (64848,64911); (64914,64967); (65008,65020); (65136,65140); (65142,65276) |] let lcat = [| (65,90); (97,122); (170,170); (181,181); (186,186); (192,214); (216,246); (248,544); (546,563); (592,685); (688,696); (699,705); (720,721); (736,740); (750,750); (890,890); (902,902); (904,906); (908,908); (910,929); (931,974); (976,1013); (1024,1154); (1162,1230); (1232,1269); (1272,1273); (1280,1295); (1329,1366); (1369,1375); (1377,1415); (1417,1417); (2307,2307); (2309,2361); (2365,2368); (2377,2380); (2384,2384); (2392,2401); (2404,2416); (2434,2435); (2437,2444); (2447,2448); (2451,2472); (2474,2480); (2482,2482); (2486,2489); (2494,2496); (2503,2504); (2507,2508); (2519,2519); (2524,2525); (2527,2529); (2534,2545); (2548,2554); (2565,2570); (2575,2576); (2579,2600); (2602,2608); (2610,2611); (2613,2614); (2616,2617); (2622,2624); (2649,2652); (2654,2654); (2662,2671); (2674,2676); (2691,2691); (2693,2699); (2701,2701); (2703,2705); (2707,2728); (2730,2736); (2738,2739); (2741,2745); (2749,2752); (2761,2761); (2763,2764); (2768,2768); (2784,2784); (2790,2799); (2818,2819); (2821,2828); (2831,2832); (2835,2856); (2858,2864); (2866,2867); (2870,2873); (2877,2878); (2880,2880); (2887,2888); (2891,2892); (2903,2903); (2908,2909); (2911,2913); (2918,2928); (2947,2947); (2949,2954); (2958,2960); (2962,2965); (2969,2970); (2972,2972); (2974,2975); (2979,2980); (2984,2986); (2990,2997); (2999,3001); (3006,3007); (3009,3010); (3014,3016); (3018,3020); (3031,3031); (3047,3058); (3073,3075); (3077,3084); (3086,3088); (3090,3112); (3114,3123); (3125,3129); (3137,3140); (3168,3169); (3174,3183); (3202,3203); (3205,3212); (3214,3216); (3218,3240); (3242,3251); (3253,3257); (3262,3262); (3264,3268); (3271,3272); (3274,3275); (3285,3286); (3294,3294); (3296,3297); (3302,3311); (3330,3331); (3333,3340); (3342,3344); (3346,3368); (3370,3385); (3390,3392); (3398,3400); (3402,3404); (3415,3415); (3424,3425); (3430,3439); (3458,3459); (3461,3478); (3482,3505); (3507,3515); (3517,3517); (3520,3526); (3535,3537); (3544,3551); (3570,3572); (3585,3632); (3634,3635); (3648,3654); (3663,3675); (3713,3714); (3716,3716); (3719,3720); (3722,3722); (3725,3725); (3732,3735); (3737,3743); (3745,3747); (3749,3749); (3751,3751); (3754,3755); (3757,3760); (3762,3763); (3773,3773); (3776,3780); (3782,3782); (3792,3801); (3804,3805); (3840,3863); (3866,3892); (3894,3894); (3896,3896); (3902,3911); (3913,3946); (3967,3967); (3973,3973); (3976,3979); (4030,4037); (4039,4044); (4047,4047); (4096,4129); (4131,4135); (4137,4138); (4140,4140); (4145,4145); (4152,4152); (4160,4183); (4256,4293); (4304,4344); (4347,4347); (4352,4441); (4447,4514); (4520,4601); (4608,4614); (4616,4678); (4680,4680); (4682,4685); (4688,4694); (4696,4696); (4698,4701); (4704,4742); (4744,4744); (4746,4749); (4752,4782); (4784,4784); (4786,4789); (4792,4798); (4800,4800); (4802,4805); (4808,4814); (4816,4822); (4824,4846); (4848,4878); (4880,4880); (4882,4885); (4888,4894); (4896,4934); (4936,4954); (4961,4988); (5024,5108); (5121,5750); (5761,5786); (5792,5872); (5888,5900); (5902,5905); (5920,5937); (5941,5942); (5952,5969); (5984,5996); (5998,6000); (6016,6070); (6078,6085); (6087,6088); (6100,6106); (6108,6108); (6112,6121); (6160,6169); (6176,6263); (6272,6312); (7680,7835); (7840,7929); (7936,7957); (7960,7965); (7968,8005); (8008,8013); (8016,8023); (8025,8025); (8027,8027); (8029,8029); (8031,8061); (8064,8116); (8118,8124); (8126,8126); (8130,8132); (8134,8140); (8144,8147); (8150,8155); (8160,8172); (8178,8180); (8182,8188); (8206,8206); (8305,8305); (8319,8319); (8450,8450); (8455,8455); (8458,8467); (8469,8469); (8473,8477); (8484,8484); (8486,8486); (8488,8488); (8490,8493); (8495,8497); (8499,8505); (8509,8511); (8517,8521); (8544,8579); (9014,9082); (9109,9109); (9372,9449); (12293,12295); (12321,12329); (12337,12341); (12344,12348); (12353,12438); (12445,12447); (12449,12538); (12540,12543); (12549,12588); (12593,12686); (12688,12727); (12784,12828); (12832,12867); (12896,12923); (12927,12976); (12992,13003); (13008,13054); (13056,13174); (13179,13277); (13280,13310); (13312,13312); (19893,19893); (19968,19968); (40869,40869); (40960,42124); (44032,44032); (55203,55203); (55296,55296); (56191,56192); (56319,56320); (57343,57344); (63743,64045); (64048,64106); (64256,64262); (64275,64279); (65313,65338); (65345,65370); (65382,65470); (65474,65479); (65482,65487); (65490,65495); (65498,65500); (66304,66334); (66336,66339); (66352,66378); (66560,66597); (66600,66637); (118784,119029); (119040,119078); (119082,119142); (119146,119154); (119171,119172); (119180,119209); (119214,119261); (119808,119892); (119894,119964); (119966,119967); (119970,119970); (119973,119974); (119977,119980); (119982,119993); (119995,119995); (119997,120000); (120002,120003); (120005,120069); (120071,120074); (120077,120084); (120086,120092); (120094,120121); (120123,120126); (120128,120132); (120134,120134); (120138,120144); (120146,120483); (120488,120777); (131072,131072); (173782,173782); (194560,195101); (983040,983040); (1048573,1048573); (1048576,1048576); (1114109,1114109) |] let map_to_nothing = [| 173; 847; 6150; 6155; 6156; 6157; 8203; 8204; 8205; 8288; 65024; 65025; 65026; 65027; 65028; 65029; 65030; 65031; 65032; 65033; 65034; 65035; 65036; 65037; 65038; 65039; 65279 |] let map_to_space = [| 160; 5760; 8192; 8193; 8194; 8195; 8196; 8197; 8198; 8199; 8200; 8201; 8202; 8203; 8239; 8287; 12288 |] let forbidden = [| (0,31); (127,127); (128,159); (1757,1757); (1807,1807); (6158,6158); (8204,8205); (8232,8233); (8288,8291); (8298,8303); (65279,65279); (65529,65532); (119155,119162); (57344,63743); (983040,1048573); (1048576,1114109); (64976,65007); (65534,65535); (131070,131071); (196606,196607); (262142,262143); (327678,327679); (393214,393215); (458750,458751); (524286,524287); (589822,589823); (655358,655359); (720894,720895); (786430,786431); (851966,851967); (917502,917503); (983038,983039); (1048574,1048575); (1114110,1114111); (55296,57343); (65529,65533); (12272,12283); (832,833); (8206,8207); (8234,8238); (8298,8303); (917505,917505); (917536,917631) |] ocamlnet-4.1.2/src/netstring/netmech_scram_sasl.ml0000644000175000017500000002461012731530350020736 0ustar gerdgerd(* $Id$ *) open Printf module type PROFILE = sig val hash_function : Netsys_digests.iana_hash_fn val iteration_count_limit : int val announce_channel_binding : bool end module SHA1 = struct let hash_function = `SHA_1 let iteration_count_limit = 100000 let announce_channel_binding = false end module SHA1_PLUS = struct let hash_function = `SHA_1 let iteration_count_limit = 100000 let announce_channel_binding = true end module SHA256 = struct let hash_function = `SHA_256 let iteration_count_limit = 100000 let announce_channel_binding = false end module SHA256_PLUS = struct let hash_function = `SHA_256 let iteration_count_limit = 100000 let announce_channel_binding = true end module SCRAM(P:PROFILE) : Netsys_sasl_types.SASL_MECHANISM = struct let profile = let open Netmech_scram in { ptype = `SASL; hash_function = P.hash_function; return_unknown_user = false; (* The SASL API does not allow to indicate unknown users anyway *) iteration_count_limit = P.iteration_count_limit; } let default_iteration_count = 4096 let basic_mname = Netmech_scram.mechanism_name profile let mechanism_name = if P.announce_channel_binding then basic_mname ^ "-PLUS" else basic_mname let client_first = `Required let server_sends_final_data = true let supports_authz = true let available() = try ignore(Netsys_digests.iana_find P.hash_function); true with Not_found -> false type credentials = (string * string * (string * string) list) list let init_credentials l = (l:credentials) let extract_password = Netsys_sasl_util.extract_password let colon_re = Netstring_str.regexp ":" let colon_split = Netstring_str.split colon_re let extract_credentials ~fallback_i (c:credentials) = try let (_, value, params) = List.find (function | (n, _, _) -> n = "authPassword-" ^ basic_mname ) c in let info = List.assoc "info" params in let (st_key, srv_key) = match colon_split value with | [ st_key; srv_key ] -> ( try Netencoding.Base64.decode st_key, Netencoding.Base64.decode srv_key with Invalid_argument _ -> raise Not_found ) | _ -> raise Not_found in let (i, salt) = match colon_split info with | [ istr; salt ] -> ( try int_of_string istr, Netencoding.Base64.decode salt with Invalid_argument _ | Failure _ -> raise Not_found ) | _ -> raise Not_found in `Stored_creds(st_key,srv_key,salt,i) with | Not_found -> let pw = extract_password c in let salt = Netmech_scram.create_salt() in let i = fallback_i in let h = profile.Netmech_scram.hash_function in let (st_key, srv_key) = Netmech_scram.stored_key h pw salt i in `Stored_creds(st_key,srv_key,salt,i) type server_session = { ss : Netmech_scram.server_session; ss_fallback_i : int; ss_cb : (string * string) list; mutable ss_cb_ok : bool option; } let check_channel_binding ss = match ss.ss_cb_ok with | None -> let flag = match Netmech_scram.server_channel_binding ss.ss with | `None | `SASL_none_but_advertise -> not (P.announce_channel_binding) | `SASL_require(ty,data) -> P.announce_channel_binding && ( try let exp_data = List.assoc ty ss.ss_cb in data = exp_data with | Not_found -> false ) | `GSSAPI _ -> assert false in ss.ss_cb_ok <- Some flag; flag | Some flag -> flag let server_state ss = if Netmech_scram.server_emit_flag ss.ss then `Emit else if Netmech_scram.server_recv_flag ss.ss then `Wait else if Netmech_scram.server_finish_flag ss.ss then ( if check_channel_binding ss then `OK else `Auth_error "bad channel binding" ) else if Netmech_scram.server_error_flag ss.ss then `Auth_error "SCRAM error" else assert false let scram_auth fallback_i lookup = (fun user authz -> match lookup user authz with | None -> raise Not_found | Some creds -> extract_credentials ~fallback_i creds (* or Not_found *) ) let server_known_params = [ "i"; "nonce"; "mutual"; "secure" ] let create_server_session ~lookup ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_scram_sasl.create_server_session:" server_known_params params in let fallback_i = try int_of_string (List.assoc "i" params) with Not_found -> default_iteration_count in let ss = Netmech_scram.create_server_session2 ?nonce:(try Some(List.assoc "nonce" params) with Not_found -> None) profile (scram_auth fallback_i lookup) in { ss; ss_fallback_i = fallback_i; ss_cb = []; ss_cb_ok = None; } let server_configure_channel_binding ss cb_list = { ss with ss_cb = cb_list } let server_process_response ss msg = { ss with ss = Netmech_scram.server_recv_message ss.ss msg } let server_process_response_restart ss msg set_stale = failwith "Netmech_scram_sasl.server_process_response_restart: \ not available" let server_emit_challenge ss = let s, msg = Netmech_scram.server_emit_message ss.ss in { ss with ss = s }, msg let server_channel_binding ss = Netmech_scram.server_channel_binding ss.ss let server_stash_session ss = sprintf "server,t=SCRAM,%s" (Marshal.to_string (Netmech_scram.server_export ss.ss, ss.ss_fallback_i, ss.ss_cb, ss.ss_cb_ok) []) let ss_re = Netstring_str.regexp "server,t=SCRAM," let server_resume_session ~lookup s = match Netstring_str.string_match ss_re s 0 with | None -> failwith "Netmech_scram_sasl.server_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let (scram_data, ss_fallback_i, ss_cb, ss_cb_ok) = Marshal.from_string data 0 in let auth = scram_auth ss_fallback_i lookup in let ss = Netmech_scram.server_import_any2 scram_data auth in { ss; ss_fallback_i; ss_cb; ss_cb_ok } let server_session_id ss = None let server_prop ss key = Netmech_scram.server_prop ss.ss key let server_gssapi_props ss = raise Not_found let server_user_name ss = match Netmech_scram.server_user_name ss.ss with | None -> raise Not_found | Some name -> name let server_authz_name ss = match Netmech_scram.server_authz_name ss.ss with | None -> raise Not_found | Some name -> name type client_session = Netmech_scram.client_session let client_state cs = if Netmech_scram.client_emit_flag cs then `Emit else if Netmech_scram.client_recv_flag cs then `Wait else if Netmech_scram.client_finish_flag cs then `OK else match Netmech_scram.client_error_flag cs with | Some error -> `Auth_error (Netmech_scram.error_of_exn error) | None -> assert false let client_known_params = [ "nonce"; "mutual"; "secure" ] let create_client_session ~user ~authz ~creds ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_scram_sasl.create_client_session:" client_known_params params in let pw = try extract_password creds with Not_found -> failwith "Netmech_scram_sasl.create_client_session: no password \ found in credentials" in Netmech_scram.create_client_session2 ?nonce:(try Some(List.assoc "nonce" params) with Not_found -> None) profile user authz pw let client_configure_channel_binding cs cb = Netmech_scram.client_configure_channel_binding cs cb let client_channel_binding cs = Netmech_scram.client_channel_binding cs let client_restart cs = if client_state cs <> `OK then failwith "Netmech_scram_sasl.client_restart: unfinished auth"; let user = Netmech_scram.client_user_name cs in let authz = Netmech_scram.client_authz_name cs in let pw = Netmech_scram.client_password cs in Netmech_scram.create_client_session2 profile user authz pw let client_process_challenge cs msg = Netmech_scram.client_recv_message cs msg let client_emit_response cs = Netmech_scram.client_emit_message cs let client_stash_session cs = "client,t=SCRAM;" ^ Netmech_scram.client_export cs let cs_re = Netstring_str.regexp "client,t=SCRAM;" let client_resume_session s = match Netstring_str.string_match cs_re s 0 with | None -> failwith "Netmech_scram_sasl.client_resume_session" | Some m -> let data_pos = Netstring_str.match_end m in let data = String.sub s data_pos (String.length s - data_pos) in Netmech_scram.client_import data let client_session_id cs = None let client_prop cs key = Netmech_scram.client_prop cs key let client_gssapi_props cs = raise Not_found let client_user_name cs = Netmech_scram.client_user_name cs let client_authz_name cs = Netmech_scram.client_authz_name cs end module SCRAM_SHA1 = SCRAM(SHA1) module SCRAM_SHA1_PLUS = SCRAM(SHA1_PLUS) module SCRAM_SHA256 = SCRAM(SHA256) module SCRAM_SHA256_PLUS = SCRAM(SHA256_PLUS) (* #use "topfind";; #require "netclient,nettls-gnutls";; Netpop.Debug.enable := true;; let addr = `Socket(`Sock_inet_byname(Unix.SOCK_STREAM, "office1", 110), Uq_client.default_connect_options);; let client = new Netpop.connect addr 60.0;; module S = Netmech_scram_sasl.SCRAM_SHA1;; let password = "xxx";; Netpop.authenticate ~sasl_mechs:[ (module S) ] ~user:"gerd" ~creds:[ "password", password, [] ] ~sasl_params:[] client;; *) ocamlnet-4.1.2/src/netstring/META.in0000644000175000017500000000061412731530350015626 0ustar gerdgerdversion = "@VERSION@" requires = "@REGEXP_PROVIDER@ unix netsys @COMPAT_PCRE_PROVIDER@" description = "Ocamlnet - String processing library" archive(byte) = "netstring.cma" archive(byte,toploop) = "netstring.cma netstring_top.cmo" archive(native) = "netstring.cmxa" archive(native,gprof) = "netstring.p.cmxa" archive(byte,-nonetaccel) += "netaccel.cma netaccel_link.cmo" ocamlnet-4.1.2/src/netstring/netsendmail_tut.txt0000644000175000017500000001647712731530350020526 0ustar gerdgerd{1:tutorial Netsendmail Tutorial} Generating mail messages is a very complicated procedure. [Netsendmail] provides a comparatively simple interface to accomplish this task without knowing too much about the details of the mail format. Here is a kind of cookbook: {2 Generate an ASCII Mail} In the simplest case, the mail is an ASCII text. Generate the mail with {[ compose ~from_addr ~to_addrs ~subject main_text ]} Here, [from_addr] is the sender's address as pair [(name,formal_address)], and [to_addrs] is the list of recipients in the same format. The variable [subject] contains the subject of the message as string. Finally, [main_text] is the ASCII text. {2 Generate an Internationalised Mail} When addresses or the main text contain non-ASCII characters, you should care about the [in_charset] and [out_charset] parameters. In general, the strings you pass to [compose] are encoded as [in_charset], and the strings in the generated mail are encoded as [out_charset]. Usually, it is a good idea to have [in_charset = out_charset], or [out_charset] as a superset of [in_charset] (otherwise you might get conversion errors). The default for both parameters is [`Enc_iso88591]. Not everything can be internationalised. In particular, the [subject], the informal names of mail addresses, the [content_description], and the main text can be encoded in a non-ASCII character set. Especially, the formal mail addresses cannot be internationalised. Example: {[ compose ~in_charset:`Enc_iso885915 ~out_charset:`Enc_iso885915 ~from_addr:("Heinz Dräger", "heinz\@draeger.de") ~to_addr:("Marion Schröder", "marion\@irgendwo.de") ~subject:"Geschäftlich" "Verkaufe Teddy-Bären für 100¤" ]} Note that when you also pass [content_type], the main text is no longer converted according to [in_charset] and [out_charset]. It is expected that the main text has already the right encoding, and that the encoding is indicated by the [content_type]. Example: {[ compose ~in_charset:`Enc_iso885915 ~out_charset:`Enc_iso885915 ~from_addr:("Heinz Dräger", "heinz\@draeger.de") ~to_addr:("Marion Schröder", "marion\@irgendwo.de") ~content_type:("text/html", ["charset", Netmime_string.mk_param "ISO-8859-1"]) ~subject:"Geschäftlich" "Verkaufe Teddy-Bären für 100€" ]} Here, the header fields are encoded in ISO-8859-15, but the main text uses ISO-8859-1. The function {!Netmime_string.mk_param} encapsulates parameter values for several kinds of structured values that may occur in mail headers, here for [Content-type]. This function takes care of the appropriate representation of the parameter value (e.g. for parameters like "title" that can be internationalised). {2 Generate a Mail with Attachments} An attachment can simply be passed to [compose]. For example, to add a file "foo.gif": {[ compose ... attachments:[ wrap_attachment ~content_type:("image/gif", []) (new Netmime.file_mime_body "foo.gif") ] ... ]} This creates a [multipart/mixed] mail. The class {!Netmime.file_mime_body} encapsulates a file as a MIME body that can be attached to the mail (note: The file is not read as a whole into memory, but only chunk by chunk, so you can even attach large files without exhausting memory). The type [multipart/mixed] has the special feature that the attached parts can either by displayed "inline" with the other contents, or suggested for saving in a file. This hint is indicated by the [Content-disposition] header. For example, to have the first attachment "inline", and the second as a file with name "foo.gif", use: {[ compose ... attachments:[ wrap_attachment ~content_type:("image/gif", []) ~content_disposition:("inline", []) (new Netmime.file_mime_body "foo.gif"); wrap_attachment ~content_type:("image/gif", []) ~content_disposition:("attachment", ["filename", Netmime_string.mk_param "foo.gif"]) (new Netmime.file_mime_body "foo.gif") ] ... ]} {2 Generate a Multi-Format Mail} It is possible to generate messages where the main part is available in several formats, e.g. in [text/plain] and [text/html]. The mail reader program can select which format can be presented best to the user. The [compose] function is not the right means to produce such a mail. It is better to use the more capable functions [wrap_parts] and [wrap_mail] for this purpose. For example, to get a message with the [text/plain] version [s_plain] and the [text/html] version [s_html], use: {[ wrap_mail ~from_addr ~to_addrs ~subject (wrap_parts ~content_type:("multipart/alternative", []) [ wrap_attachment ~content_type:("text/plain", []) (new Netmime.memory_mime_body s_plain); wrap_attachment ~content_type:("text/html", []) (new Netmime.memory_mime_body s_html) ]) ]} Here, [wrap_attachment] is used to encapsulate the two versions of the main text. This works because there is no difference between the format of an attachment and the format of a text part. (Actually, [wrap_attachment] should be better called [wrap_body].) The class {!Netmime.memory_mime_body} encapsulates a string as MIME body. The function [wrap_parts] bundles the two versions to the main message, and [wrap_mail] adds the mail headers necessary to deliver the mail. Note that the simplest version of the message should be added first, and the fanciest version of the message should be added last. As a variant, one can also add file attachments. To do so, insert a [multipart/mixed] container around the [multipart/alternative] message: {[ wrap_mail ~from_addr ~to_addrs ~subject (wrap_parts ~content_type:("multipart/mixed", []) [ wrap_parts ~content_type:("multipart/alternative", []) [ wrap_attachment ~content_type:("text/plain", []) (new Netmime.memory_mime_body s_plain); wrap_attachment ~content_type:("text/html", []) (new Netmime.memory_mime_body s_html) ]; wrap_attachment ~content_type:("audio/wav", []) (new Netmime.file_mime_body "music.wav") ]) ]} {2 Generate an MHTML Message} MHTML is an HTML document with attached resource files like images or style sheets. For example, to have the HTML text [s_html] bundled with an image and a style sheet, use: {[ wrap_mail ~from_addr ~to_addrs ~subject (wrap_parts ~content_type:("multipart/related", [ "type", Netmime_string.mk_param "text/html" ]) [ wrap_attachment ~content_type:("text/html", []) (new Netmime.memory_mime_body s_html); wrap_attachment ~content_type:("image/gif", []) ~content_id:"img1" (new Netmime.file_mime_body "my.gif") wrap_attachment ~content_type:("text/css", []) ~content_id:"style1" (new Netmime.file_mime_body "style.css") ]) ]} Note the [content_id] arguments that assign names to the individual parts. One can now refer to the parts from the HTML document by [cid] URLs, e.g. [cid:img1] points to the image in the second part. There is another mechanism using the [Content-Location] header to resolve hyperlinks to message parts. See RFC 2557 for details. ocamlnet-4.1.2/src/netstring/netasn1_encode.mli0000644000175000017500000000132012731530350020134 0ustar gerdgerd(* $Id$ *) (** ASN.1 encoder *) (** Note that the encoder does not check whether the value is well-formed, in particular whether the constrained string values are correct. *) val encode_ber : Netbuffer.t -> Netasn1.Value.value -> Netasn1.Value.pc (** Appends a BER encoding of the value to the buffer (including the header). Returns whether a primitive or constructed encoding was generated. *) val encode_ber_contents : Netbuffer.t -> Netasn1.Value.value -> Netasn1.Value.pc (** Appends a BER encoding of the value to the buffer (excluding the header). Returns whether a primitive or constructed encoding was generated. *) ocamlnet-4.1.2/src/netstring/netsaslprep.ml0000644000175000017500000002061012731530350017440 0ustar gerdgerd(* $Id$ *) exception SASLprepError open Netsaslprep_data let map (u : int array) = let to_space = Hashtbl.create 41 in let to_nothing = Hashtbl.create 41 in Array.iter (fun p -> Hashtbl.add to_space p ()) map_to_space; Array.iter (fun p -> Hashtbl.add to_nothing p ()) map_to_nothing; let u0 = Array.to_list u in let u1 = List.filter (fun p -> not (Hashtbl.mem to_nothing p)) u0 in let u2 = List.map (fun p -> if Hashtbl.mem to_space p then 32 else p ) u1 in Array.of_list u2 (* The KC normalizer follows roughly https://web.archive.org/web/20070514031407/http://www.unicode.org/unicode/reports/tr15/Normalizer.html *) type buffer = { mutable buf : int array; mutable len : int } let create_buffer() = { buf = Array.make 42 0; len = 0 } let buffer_at buf k = assert(k >= 0 && k < buf.len); buf.buf.(k) let set_buffer_at buf k ch = assert(k >= 0 && k < buf.len); buf.buf.(k) <- ch let resize buf = let nbuf = Array.make (Array.length buf.buf * 2) 0 in Array.blit buf.buf 0 nbuf 0 (Array.length buf.buf); buf.buf <- nbuf let insert_at buf k ch = assert(k >= 0 && k <= buf.len); if buf.len = Array.length buf.buf then resize buf; if k < buf.len then Array.blit buf.buf k buf.buf (k+1) (buf.len - k); buf.buf.(k) <- ch; buf.len <- buf.len + 1 let length buf = buf.len let contents buf = Array.sub buf.buf 0 buf.len let get_cano_tab() = let cano_tab = Hashtbl.create 41 in let last = ref 0 in Array.iter (fun p -> if p < 0 then last := -p else Hashtbl.add cano_tab p !last ) cano_classes; cano_tab let cano_tab = (* this table is pretty small *) get_cano_tab() (* Hangul *) let h_SBase = 0xAC00 let h_LBase = 0x1100 let h_VBase = 0x1161 let h_TBase = 0x11A7 let h_LCount = 19 let h_VCount = 21 let h_TCount = 28 let h_NCount = h_VCount * h_TCount let h_SCount = h_LCount * h_NCount let decompose_hangul code = if code < h_SBase || code >= h_SBase + h_SCount then raise Not_found; let si = code - h_SBase in let l = h_LBase + si/h_NCount in let v = h_VBase + (si mod h_NCount) / h_TCount in let t = h_TBase + si mod h_TCount in if t = h_TBase then [ l; v ] else [ l; v; t ] let compose_hangul first second = (* check for L and V *) if first >= h_LBase && first < h_LBase + h_LCount && second >= h_VBase && second < h_VBase + h_VCount then (* create LV syllable *) let l = first - h_LBase in let v = second - h_VBase in h_SBase + (l*h_VCount + v) * h_TCount else (* check for LV and T *) let si = first - h_SBase in if first >= h_SBase && first < h_SBase + h_SCount && si mod h_TCount = 0 then let ti = second - h_TBase in first + ti else raise Not_found let decompose (u : int array) = (* "compatibility decomposition" as required for NFKC *) let decomp_tab = Hashtbl.create 41 in let last = ref (ref []) in Array.iter (fun p -> if p < 0 then ( last := ref []; Hashtbl.add decomp_tab ((-p) lsr 1) !last ) else !last := p :: ! !last ) decompositions; let rec get_recursive_decomp ch = try let chars = List.rev (! (Hashtbl.find decomp_tab ch)) in List.flatten (List.map get_recursive_decomp chars) with | Not_found -> try decompose_hangul ch with | Not_found -> [ch] in let get_cc ch = try Hashtbl.find cano_tab ch with Not_found -> 0 in let target = create_buffer() in for i = 0 to Array.length u - 1 do let decomp = get_recursive_decomp u.(i) in List.iter (fun ch -> let cc = get_cc ch in let k = ref (length target) in if cc <> 0 then ( while !k > 0 && get_cc (buffer_at target (!k-1)) > cc do decr k done ); insert_at target !k ch ) decomp done; contents target let compose_1 (u : int array) = (* "canonical composition" as required for NFKC *) (* u <> [| |] required *) let excl_tab = Hashtbl.create 41 in Array.iter (fun p -> Hashtbl.add excl_tab p ()) exclusions; let comp_tab = Hashtbl.create 41 in let last_p = ref 0 in let last = ref [] in Array.iter (fun p -> if p < 0 then ( if !last <> [] then ( let q = (- !last_p) lsr 1 in let is_canonical = (- !last_p) land 1 = 0 in let is_excluded = Hashtbl.mem excl_tab q in if is_canonical && not is_excluded then ( match !last with | [ c0 ] -> () | [ c1; c0 ] -> (* NB. We can at most support 15 bits *) assert(c0 < 16384); assert(c1 < 16384); Hashtbl.add comp_tab ((c0 lsl 14) lor c1) q | _ -> assert false ) ); last_p := p; last := []; ) else last := p :: !last ) decompositions; let get_cc ch = try Hashtbl.find cano_tab ch with Not_found -> 0 in let target = create_buffer() in let starter_pos = ref 0 in let starter_ch = ref u.(!starter_pos) in let last_class = ref (get_cc !starter_ch) in if !last_class <> 0 then last_class := 256; insert_at target 0 !starter_ch; for i = 1 to Array.length u - 1 do let ch = u.(i) in let cc = get_cc ch in try let composite = try if !starter_ch >= 16384 || ch >= 16384 then raise Not_found; Hashtbl.find comp_tab ((!starter_ch lsl 14) lor ch) with | Not_found -> compose_hangul !starter_ch ch in if !last_class >= cc && !last_class <> 0 then raise Not_found; set_buffer_at target !starter_pos composite; starter_ch := composite with | Not_found -> if cc = 0 then ( starter_pos := length target; starter_ch := ch; ); last_class := cc; insert_at target (length target) ch done; contents target let compose u = if u = [| |] then [| |] else compose_1 u let exists f a = try Array.iter (fun p -> if f p then raise Exit) a; false with Exit -> true let norm_needed u = (* If the string uses only certain characters we don't need to normalize. These are practically all Latin, Greek and Cyrillic characters. *) let quick_need_norm c = not ((c >= 0x20 && c <= 0x7e) || (c >= 0xc0 && c <= 0x131) || (c >= 0x134 && c <= 0x13e) || (c >= 0x141 && c <= 0x148) || (c >= 0x14a && c <= 0x17e) || (c >= 0x180 && c <= 0x1c3) || (c >= 0x1cd && c <= 0x1f0) || (c >= 0x1f4 && c <= 0x2ad) || (c >= 0x374 && c <= 0x375) || (c = 0x37e) || (c >= 0x385 && c <= 0x3ce) || (c >= 0x400 && c <= 0x482) || (c >= 0x48a && c <= 0x50f) ) in exists quick_need_norm u let normalize u = (* normalization form KC (NFKC) *) if norm_needed u then compose (decompose u) else u let prohibited u = Array.iter (fun p -> Array.iter (fun (p0, p1) -> if p >= p0 && p <= p1 then raise SASLprepError; ) forbidden; ) u; u let is_randalcat c = exists (fun (c0,c1) -> c >= c0 && c <= c1) randalcat let is_lcat c = exists (fun (c0,c1) -> c >= c0 && c <= c1) lcat let bidicheck u = let u_randalcat = Array.map is_randalcat u in let u_lcat = Array.map is_lcat u in let has_randalcat = exists (fun p -> p) u_randalcat in let has_lcat = exists (fun p -> p) u_lcat in if has_randalcat && has_lcat then raise SASLprepError; if has_randalcat && u <> [| |] then ( if not u_randalcat.(0) || not u_randalcat.(Array.length u - 1) then raise SASLprepError ); u let basecheck u = if exists (fun p -> p < 0 || p > 0x10ffff) u then raise SASLprepError; () let saslprep_a u = basecheck u; bidicheck ( prohibited (normalize (map u))) let saslprep s = Netconversion.ustring_of_uarray `Enc_utf8 (saslprep_a (Netconversion.uarray_of_ustring `Enc_utf8 s ) ) ocamlnet-4.1.2/src/netstring/netstring_str.ml0000644000175000017500000006650612731530350020023 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) open Printf module Debug = struct let enable = ref false end let dlog = Netlog.Debug.mk_dlog "Netstring_str" Debug.enable let dlogr = Netlog.Debug.mk_dlogr "Netstring_str" Debug.enable let () = Netlog.Debug.register_module "Netstring_str" Debug.enable let explode s = let l = String.length s in let rec loop k = if k < l then s.[k] :: loop (k+1) else [] in loop 0 let implode l = let n = List.length l in let s = Bytes.create n in let k = ref 0 in List.iter (fun c -> Bytes.set s !k c; incr k ) l; Bytes.to_string s let quote_set s = let l = explode s in let have_circum = List.mem '^' l in let have_minus = List.mem '-' l in let have_rbracket = List.mem ']' l in let l1 = List.filter (fun c -> c <> '^' && c <> '-' && c <> ']') l in let l2 = if have_rbracket then ']' :: l1 else l1 in let l3 = if have_circum then l2 @ ['^'] else l2 in let l4 = if have_minus then l3 @ ['-'] else l3 in let s4 = implode l4 in let s' = match s4 with | "" -> failwith "Netstring_str.quote_set: empty" | "^" -> "^" | "^-" -> "[-^]" | _ -> "[" ^ s4 ^ "]" in if !Debug.enable then dlogr (fun () -> sprintf "quote_set: orig: %s - quoted: %s" s s' ); s' (**********************************************************************) (* HAVE_PCRE *) (**********************************************************************) #ifndef ENABLE_STR_EXTERNALS #ifdef HAVE_PCRE (* This implementation of Netstring_str uses the PCRE engine. The * syntax for regular expressions is compatible with previous versions. *) (**********************************************************************) (* Parsing types *) type setatom = | Schar of char | Srange of (char * char) and set = setatom list ;; type re_term = Texact of string (* literal characters (except NUL) *) | Tnullchar (* NUL characer *) | Tany (* . but no newline *) | Tnull (* emptiness *) | Tconcat of re_term list | Tstar of re_term (* x* *) | Tplus of re_term (* x+ *) | Toption of re_term (* x? *) | Tset of set (* [...] *) | Tnegset of set (* [^...] *) | Tbegline (* ^ *) | Tendline (* $ *) | Talt of re_term list (* x\|y *) | Tgroup of (int * re_term) (* \(...\) *) | Trefer of int (* \i *) | Tinterval of (re_term * int * int) (* x{n,m}. m=-1 means infinite *) | Twordchar (* \w *) | Tnowordchar (* \W *) | Twordbeg (* \< *) | Twordend (* \> *) | Twordbound (* \b *) | Tnowordbound (* \B *) | Tbegbuf (* \` *) | Tendbuf (* \' *) ;; (**********************************************************************) (* Final types *) type regexp = Pcre.regexp;; type split_result = Str.split_result = Text of string | Delim of string;; type result = Netstring_pcre.result ;; (**********************************************************************) (* Parse Str-style regexps, and convert to Pcre-style regexps *) let scan_str_regexp re_string = let l = String.length re_string in let k = ref (-1) in let c = ref ' ' in let esc = ref false in let group = ref 1 in let n_open_groups = ref 0 in let closed_groups = Array.create 10 false in let next() = incr k; if ( !k < l ) then begin let c1 = re_string.[ !k ] in if c1 = '\\' then begin if !k < l then begin incr k; c := re_string.[ !k ]; esc := true end else failwith "regexp: bad backslash" end else begin esc := false; c := c1 end end in let next_noesc() = incr k; if ( !k < l ) then begin c := re_string.[ !k ]; esc := false end in let rec scan_alternative () = let t1 = scan_concatenation () in if !k < l then begin if !esc & !c = '|' then begin next(); match scan_alternative() with Talt alist -> Talt (t1::alist) | t -> Talt [ t1; t] end else t1 end else t1 and scan_concatenation () = let t1 = scan_repetition () in if t1 = Tnull then t1 else let t2 = scan_concatenation() in match t2 with Tnull -> t1 | Texact s2 -> begin match t1 with Texact s1 -> Texact (s1 ^ s2) | _ -> Tconcat [t1;t2] end | Tconcat clist -> Tconcat (t1::clist) | _ -> Tconcat [ t1; t2 ] and scan_repetition () = let t1 = ref (scan_literal_or_group ()) in let continue = ref true in while !continue do if !k < l & not !esc then begin match !c with '*' -> next(); t1 := Tstar !t1 | '+' -> next(); t1 := Tplus !t1 | '?' -> next(); t1 := Toption !t1 (* {...} is not implemented in Str *) (* | '{' -> next_noesc(); let n1 = ref None in let n2 = ref None in let j = ref 0 in if !k < l & !c >= '0' & !c <= '9' then begin while !k < l & !c >= '0' & !c <= '9' do j := 10* !j + (Char.code !c - Char.code '0'); next_noesc() done; n1 := Some !j end; if !k < l & !n1 <> None & !c = '}' then begin next(); t1 := Tinterval (!t1, !j, !j) end else begin if !k >= l or !c <> ',' then failwith "regexp: error in {...} phrase"; next_noesc(); j := 0; if !k < l & !c >= '0' & !c <= '9' then begin while !k < l & !c >= '0' & !c <= '9' do j := 10* !j + (Char.code !c - Char.code '0'); next_noesc() done; n2 := Some !j end; if !k >= l || !c <> '}' then failwith "regexp: error in {...} phrase"; next(); ( match !n1 with None -> ( match !n2 with None -> failwith "regexp: error in {...} phrase"; | Some m2 -> t1 := Tinterval (!t1, 0, m2) ) | Some m1 -> ( match !n2 with None -> t1 := Tinterval (!t1, m1, -1) | Some m2 -> t1 := Tinterval (!t1, m1, m2) ) ) end *) | _ -> continue := false end else continue := false done; !t1 and scan_literal_or_group () = if !k >= l then Tnull else if !esc then begin match !c with '(' -> next(); let n = !group in incr group; incr n_open_groups; let t = scan_alternative() in decr n_open_groups; if !k < l & !esc & !c = ')' then begin next(); closed_groups.(n) <- true; Tgroup (n, t) end else failwith "regexp: closing paranthesis \\) not found" | ('1'..'9') -> let n = (Char.code !c - Char.code '0') in if closed_groups.(n) then begin next(); Trefer n end else failwith "regexp: bad reference to group" (* | 'w' -> next(); Twordchar | 'W' -> next(); Tnowordchar *) | 'b' -> next(); Twordbound (* | 'B' -> next(); Tnowordbound | '<' -> next(); Twordbeg | '>' -> next(); Twordend | '`' -> next(); Tbegbuf | '\'' -> next(); Tendbuf *) | '\\' -> next(); Texact (String.make 1 '\\') | '|' -> Tnull | ')' -> if !n_open_groups > 0 then Tnull else failwith "regexp: unmatched closing parenthesis" | ch -> next(); Texact (String.make 1 ch) end else begin match !c with '*' -> Tnull | '+' -> Tnull | '?' -> Tnull | '{' -> Tnull | '^' -> next(); Tbegline | '$' -> next(); Tendline | '.' -> next(); Tany | '\000' -> next(); Tnullchar | '[' -> next_noesc(); if !k < l then begin let negated = ref false in let set = ref [] in let add_char c = set := Schar c :: !set in let add_range c1 c2 = set := Srange(c1,c2) :: !set in if !c = '^' then begin next_noesc(); negated := true end; let continue = ref true in let first = ref true in (* the character after [ or [^ ? *) while !continue & !k < l do match () with () when !c = '[' & !k + 1 < l & re_string.[!k + 1] = ':' -> failwith "regexp: Character classes such as [[:digit:]] not implemented"; (* TODO: check for predefined sets *) | () when !c = ']' & not !first -> next(); continue := false | () when (!k + 2 < l) & (re_string.[!k + 1] = '-') & (re_string.[!k + 2] <> ']') -> (* range *) add_range !c (re_string.[!k + 2]); next_noesc(); next_noesc(); next_noesc(); first := false; | () -> add_char !c; next_noesc(); first := false; done; if !continue then failwith "regexp: closing bracket ] not found"; if !negated then Tnegset !set else Tset !set end else failwith "regexp: closing bracket ] not found" | ch -> next(); Texact (String.make 1 ch ) end in try next(); scan_alternative () with | Failure msg -> failwith (msg ^ " - regexp: " ^ re_string) ;; let pcre_safe_quote c = (* for print_set *) match c with 'a'..'z'|'A'..'Z'|'0'..'9'|'_' -> String.make 1 c | '\000' -> "\\000" | _ -> "\\" ^ String.make 1 c ;; let rec print_pcre_regexp ret = match ret with Texact s -> Pcre.quote s | Tnullchar -> (* Pcre.quote "\000" returns nonsense *) "[\\000]" | Tany -> "." | Tnull -> "(?:)" | Tconcat l -> String.concat "" (List.map print_pcre_regexp l) | Tstar ret' -> print_pcre_subregexp ret' ^ "*" | Tplus ret' -> print_pcre_subregexp ret' ^ "+" | Toption ret' -> print_pcre_subregexp ret' ^ "?" | Tset s -> "[" ^ print_set s ^ "]" | Tnegset s -> "[^" ^ print_set s ^ "]" | Talt l -> String.concat "|" (List.map print_pcre_subregexp l) | Tgroup(_,ret') -> "(" ^ print_pcre_regexp ret' ^ ")" | Trefer n -> (* Put parentheses around \n to disambiguate from \nn *) "(?:\\" ^ string_of_int n ^ ")" | Tinterval(ret',m,n) -> print_pcre_subregexp ret' ^ "{" ^ string_of_int m ^ "," ^ (if n >= 0 then string_of_int n else "") ^ "}" | Tbegline -> "^" | Tendline -> "(?:$)" | Twordchar -> "\\w" | Tnowordchar -> "\\W" | Twordbeg -> "\\b(?=\\w)" | Twordend -> "(?<=\\w)\\b" | Twordbound -> "\\b" | Tnowordbound -> "\\B" | Tbegbuf -> "\\A" | Tendbuf -> "\\z" and print_pcre_subregexp ret = (* Print ret, but put parentheses around ret *) match ret with Tset _ | Tnegset _ | Tgroup(_,_) -> (* No additional parentheses needed *) print_pcre_regexp ret | _ -> (* Print (?:ret). This is the "neutral" form of grouping that only * changes precedence *) "(?:" ^ print_pcre_regexp ret ^ ")" and print_set s = String.concat "" (List.map (function Schar c -> pcre_safe_quote c | Srange(c1,c2) -> pcre_safe_quote c1 ^ "-" ^ pcre_safe_quote c2 ) s ) ;; (**********************************************************************) (* Emulation *) let regexp s = let ret = scan_str_regexp s in let s' = print_pcre_regexp ret in if !Debug.enable then dlogr (fun () -> sprintf "regexp: orig: %s - translated: %s" s s' ); Pcre.regexp ~flags:[`MULTILINE] s' ;; let regexp_case_fold s = let ret = scan_str_regexp s in let s' = print_pcre_regexp ret in if !Debug.enable then dlogr (fun () -> sprintf "regexp_case_fold: orig: %s - translated: %s" s s' ); Pcre.regexp ~flags:[`MULTILINE; `CASELESS] s' ;; let pcre_quote s = (* Note that Pcre.quote is incorrect for NUL chars, which simply remain in place, although they need to be encoded *) let s1 = Pcre.quote s in let s' = Pcre.qreplace ~pat:"\\000" ~templ:"\\000" s1 in if !Debug.enable then dlogr (fun () -> sprintf "quote: orig: %s - quoted: %s" s s' ); s' ;; let unsafe_str_re = Pcre.regexp "[\\]\\[+*?.\\\\^$]" let quote s = (* This returns, of course, a Str-syntax regexp! *) Pcre.replace ~rex:unsafe_str_re ~templ:"\\$&" s let regexp_string s = Pcre.regexp ~flags:[`MULTILINE] (pcre_quote s) ;; let regexp_string_case_fold s = Pcre.regexp ~flags:[`MULTILINE; `CASELESS] (pcre_quote s) ;; let string_match = Netstring_pcre.string_match ;; let bytes_match = Netstring_pcre.bytes_match ;; (* let string_partial_match = Netstring_pcre.string_partial_match ;; *) (* N/A *) let search_forward = Netstring_pcre.search_forward ;; let search_backward = Netstring_pcre.search_backward ;; let search_forward_bytes = Netstring_pcre.search_forward_bytes ;; let search_backward_bytes = Netstring_pcre.search_backward_bytes ;; let matched_string = Netstring_pcre.matched_string ;; let matched_bytes = Netstring_pcre.matched_bytes ;; let match_beginning = Netstring_pcre.match_beginning ;; let match_end = Netstring_pcre.match_end ;; let matched_group = Netstring_pcre.matched_group ;; let matched_group_bytes = Netstring_pcre.matched_group_bytes ;; let group_beginning = Netstring_pcre.group_beginning ;; let group_end = Netstring_pcre.group_end ;; let global_replace pat templ s = Netstring_pcre.global_replace pat templ s;; let replace_first pat templ s = Netstring_pcre.replace_first pat templ s ;; let global_substitute = Netstring_pcre.global_substitute ;; let substitute_first = Netstring_pcre.substitute_first ;; (* replace_matched: n/a *) let split = Netstring_pcre.split ;; let bounded_split = Netstring_pcre.bounded_split ;; let split_delim = Netstring_pcre.split_delim ;; let bounded_split_delim = Netstring_pcre.bounded_split_delim ;; let tr_split_result r = List.map (function Pcre.Text t -> Text t | Pcre.Delim d -> Delim d | _ -> assert false ) (List.filter (function Pcre.Group(_,_) | Pcre.NoGroup -> false | _ -> true ) r ) ;; let full_split sep s = tr_split_result (Netstring_pcre.full_split sep s);; let bounded_full_split sep s max = tr_split_result (Netstring_pcre.bounded_full_split sep s max);; let string_before = Netstring_pcre.string_before ;; let string_after = Netstring_pcre.string_after ;; let first_chars = Netstring_pcre.first_chars ;; let last_chars = Netstring_pcre.last_chars ;; #endif #else (* i.e. ENABLE_STR_EXTERNALS *) (**********************************************************************) (* ENABLE_STR_EXTERNALS *) (**********************************************************************) (* We use here the Str externals directly, and reimplement parts of the Str module to make it thread-safe *) type regexp = Str.regexp;; type split_result = Str.split_result = Text of string | Delim of string;; type result = { pos : int; sr : int array; } (* sr.(2*k) is the beginning of group k sr.(2*k+1) is the end of group k sr.(0) is match beginning sr.(1) is match end *) let match_beg sr = sr.(0) let match_e sr = sr.(1) let group_beg sr k = sr.(k+k) let group_e sr k = sr.(k+k+1) let n_groups sr = (Array.length sr - 2) lsr 1 (* Groups are numbered 1 .. n_groups *) external re_string_match: regexp -> string -> int -> int array = "re_string_match" external re_partial_match: regexp -> string -> int -> int array = "re_partial_match" external re_search_forward: regexp -> string -> int -> int array = "re_search_forward" external re_search_backward: regexp -> string -> int -> int array = "re_search_backward" external re_replacement_text: string -> int array -> string -> string = "re_replacement_text" let regexp s = let re = Str.regexp s in if !Debug.enable then dlogr (fun () -> sprintf "regexp: %s" s ); re let regexp_case_fold s = let re = Str.regexp_case_fold s in if !Debug.enable then dlogr (fun () -> sprintf "regexp_case_fold: %s" s ); re let quote s = let s' = Str.quote s in if !Debug.enable then dlogr (fun () -> sprintf "quote: orig: %s - quoted: %s" s s' ); s' let regexp_string = Str.regexp_string let regexp_string_case_fold = Str.regexp_string_case_fold let return_result pos sr = { pos = pos; sr = sr } let string_match pat s pos = let sr = re_string_match pat s pos in if Array.length sr > 0 then Some (return_result pos sr) else None let bytes_match pat s pos = string_match pat (Bytes.unsafe_to_string s) pos let search_forward pat s pos = let sr = re_search_forward pat s pos in if Array.length sr = 0 then raise Not_found; sr.(0), return_result pos sr let search_forward_bytes pat s pos = search_forward pat (Bytes.unsafe_to_string s) pos let search_backward pat s pos = let sr = re_search_backward pat s pos in if Array.length sr = 0 then raise Not_found; sr.(0), return_result pos sr let search_backward_bytes pat s pos = search_backward pat (Bytes.unsafe_to_string s) pos let matched_generic sub result s = if match_beg result.sr < 0 || match_e result.sr < 0 then raise Not_found; sub s (match_beg result.sr) (match_e result.sr - match_beg result.sr) let matched_string = matched_generic String.sub let matched_bytes = matched_generic Bytes.sub let match_beginning result = if match_beg result.sr < 0 then raise Not_found; match_beg result.sr let match_end result = if match_e result.sr < 0 then raise Not_found; match_e result.sr let matched_group_generic sub result n s = if n < 0 || n > n_groups result.sr then raise Not_found; if n = 0 then matched_generic sub result s else let gbeg = group_beg result.sr n in let gend = group_e result.sr n in if gbeg < 0 || gend < 0 then raise Not_found; sub s gbeg (gend - gbeg) let matched_group = matched_group_generic String.sub let matched_group_bytes = matched_group_generic Bytes.sub let group_beginning result n = if n < 0 || n > n_groups result.sr then raise Not_found; if n = 0 then match_beginning result else let gbeg = group_beg result.sr n in if gbeg < 0 then raise Not_found else gbeg let group_end result n = if n < 0 || n > n_groups result.sr then raise Not_found; if n = 0 then match_e result.sr else let gend = group_e result.sr n in if gend < 0 then raise Not_found else gend let substitute_first pat subst s = try let pos, m = search_forward pat s 0 in String.concat "" [ Str.string_before s pos; subst m s; Str.string_after s (match_end m) ] with Not_found -> s exception Cont of int let global_substitute pat subst s = let l = String.length s in let b = Buffer.create (l/2) in let rec loop k = try if k <= l then ( let pos, m = search_forward pat s k in (* or Not_found *) Buffer.add_string b (String.sub s k (pos-k)); let repl = subst m s in Buffer.add_string b repl; let pos' = match_end m in if pos = pos' then ( if pos < l then Buffer.add_char b s.[pos]; raise (Cont (pos'+1)) ) else raise (Cont pos') ) with | Cont k_next -> loop k_next | Not_found -> Buffer.add_string b (String.sub s k (l-k)) in loop 0; Buffer.contents b let replace_matched repl m s = re_replacement_text repl m.sr s let global_replace pat repl s = global_substitute pat (replace_matched repl) s let replace_first pat repl s = substitute_first pat (replace_matched repl) s (* The splitting functions are practically copied from str.ml *) let opt_search_forward re s pos = try Some(search_forward re s pos) with Not_found -> None let opt_search_forward_progress expr text start = match opt_search_forward expr text start with | None -> None | Some (pos, m) -> if match_end m > start then Some (pos,m) else if start < String.length text then opt_search_forward expr text (start + 1) else None let bounded_split expr text num = let start = match string_match expr text 0 with | Some m -> match_end m | None -> 0 in let rec split accu start n = if start >= String.length text then accu else if n = 1 then Str.string_after text start :: accu else match opt_search_forward_progress expr text start with | None -> Str.string_after text start :: accu | Some (pos,m) -> split (String.sub text start (pos-start) :: accu) (match_end m) (n-1) in List.rev (split [] start num) let split expr text = bounded_split expr text 0 let bounded_split_delim expr text num = let rec split accu start n = if start > String.length text then accu else if n = 1 then Str.string_after text start :: accu else match opt_search_forward_progress expr text start with | None -> Str.string_after text start :: accu | Some (pos,m) -> split (String.sub text start (pos-start) :: accu) (match_end m) (n-1) in if text = "" then [] else List.rev (split [] 0 num) let split_delim expr text = bounded_split_delim expr text 0 let bounded_full_split expr text num = let rec split accu start n = if start >= String.length text then accu else if n = 1 then Text(Str.string_after text start) :: accu else match opt_search_forward_progress expr text start with | None -> Text(Str.string_after text start) :: accu | Some (pos,m) -> let s = matched_string m text in if pos > start then split (Delim(s) :: Text(String.sub text start (pos-start)) :: accu) (match_end m) (n-1) else split (Delim(s) :: accu) (match_end m) (n-1) in List.rev (split [] 0 num) let full_split expr text = bounded_full_split expr text 0 let string_before = Str.string_before;; let string_after = Str.string_after;; let first_chars = Str.first_chars;; let last_chars = Str.last_chars;; #endif #ifndef HAVE_PCRE #ifndef ENABLE_STR_EXTERNALS (**********************************************************************) (* DEFAULT *) (**********************************************************************) (* Alternate implementation without Pcre: Just use Str directly, and ensure thread-safety with mutexes *) let mutex = (!Netsys_oothr.provider) # create_mutex() let protect f arg = Netsys_oothr.serialize mutex f arg type regexp = Str.regexp;; type split_result = Str.split_result = Text of string | Delim of string;; type result = { pos : int; match_beg : int; match_end : int; group_beg : int array; group_end : int array; } let regexp = protect (fun s -> let re = Str.regexp s in if !Debug.enable then dlogr (fun () -> sprintf "regexp: %s" s ); re ) let regexp_case_fold = protect (fun s -> let re = Str.regexp_case_fold s in if !Debug.enable then dlogr (fun () -> sprintf "regexp_case_fold: %s" s ); re ) let quote = protect (fun s -> let s' = Str.quote s in if !Debug.enable then dlogr (fun () -> sprintf "quote: orig: %s - quoted: %s" s s' ); s' ) let regexp_string = protect Str.regexp_string let regexp_string_case_fold = protect Str.regexp_string_case_fold let n_groups = 9 let return_result pos = let r = { pos = pos; match_beg = (try Str.match_beginning() with Not_found -> -1); match_end = (try Str.match_end() with Not_found -> -1); group_beg = Array.create n_groups (-1); group_end = Array.create n_groups (-1); } in for g = 0 to n_groups - 1 do r.group_beg.(g) <- (try Str.group_beginning (g+1) with Not_found | Invalid_argument _ -> -1); r.group_end.(g) <- (try Str.group_end (g+1) with Not_found | Invalid_argument _ -> -1); done; r let string_match pat s = protect (fun pos -> if Str.string_match pat s pos then Some (return_result pos) else None ) let bytes_match pat s pos = string_match pat (Bytes.unsafe_to_string s) pos let search_forward pat s = protect (fun pos -> let i = Str.search_forward pat s pos in i, return_result pos ) let search_forward_bytes pat s pos = search_forward pat (Bytes.unsafe_to_string s) pos let search_backward pat s = protect (fun pos -> let i = Str.search_backward pat s pos in i, return_result pos ) let search_backward_bytes pat s pos = search_backward pat (Bytes.unsafe_to_string s) pos let matched_generic sub result s = if result.match_beg < 0 or result.match_end < 0 then raise Not_found; sub s result.match_beg (result.match_end - result.match_beg) let matched_string = matched_generic String.sub let matched_bytes = matched_generic Bytes.sub let match_beginning result = if result.match_beg < 0 then raise Not_found; result.match_beg let match_end result = if result.match_end < 0 then raise Not_found; result.match_end let matched_group_generic sub result n s = if n < 0 || n >= Array.length result.group_beg then raise Not_found; if n = 0 then matched_generic sub result s else let gbeg = result.group_beg.(n-1) in let gend = result.group_end.(n-1) in if gbeg < 0 or gend < 0 then raise Not_found; sub s gbeg (gend - gbeg) let matched_group = matched_group_generic String.sub let matched_group_bytes = matched_group_generic Bytes.sub let group_beginning result n = if n < 0 || n >= Array.length result.group_beg then raise Not_found; if n = 0 then match_beginning result else let gbeg = result.group_beg.(n-1) in if gbeg < 0 then raise Not_found else gbeg let group_end result n = if n < 0 || n >= Array.length result.group_end then raise Not_found; if n = 0 then match_end result else let gend = result.group_end.(n-1) in if gend < 0 then raise Not_found else gend let global_replace pat templ = protect (fun s -> Str.global_replace pat templ s) let replace_first pat templ = protect (fun s -> Str.replace_first pat templ s) let global_substitute pat subst = protect (fun s -> let xsubst s = let r = return_result 0 in subst r s in Str.global_substitute pat xsubst s) let substitute_first pat subst = protect (fun s -> let xsubst s = let r = return_result 0 in subst r s in Str.substitute_first pat xsubst s) let split sep = protect (fun s -> Str.split sep s) let bounded_split sep s = protect (fun max -> Str.bounded_split sep s max) let split_delim sep = protect (fun s -> Str.split_delim sep s) let bounded_split_delim sep s = protect (fun max -> Str.bounded_split_delim sep s max) let full_split sep = protect (fun s -> Str.full_split sep s) let bounded_full_split sep s = protect (fun max -> Str.bounded_full_split sep s max) let string_before = Str.string_before;; let string_after = Str.string_after;; let first_chars = Str.first_chars;; let last_chars = Str.last_chars;; #endif #endif ocamlnet-4.1.2/src/netstring/netasn1.ml0000644000175000017500000010172512731530350016460 0ustar gerdgerd(* $Id$ *) exception Out_of_range exception Parse_error of int exception Header_too_short module Type_name = struct type type_name = | Bool | Integer | Enum | Real | Bitstring | Octetstring | Null | Seq | Set | OID | ROID | ObjectDescriptor | External | Embedded_PDV | NumericString | PrintableString | TeletexString | VideotexString | VisibleString | IA5String | GraphicString | GeneralString | UniversalString | BMPString | UTF8String | CharString | UTCTime | GeneralizedTime end module Value = struct type pc = Primitive | Constructed type value = | Bool of bool | Integer of int_value | Enum of int_value | Real of real_value | Bitstring of bitstring_value | Octetstring of string | Null | Seq of value list | Set of value list | Tagptr of tag_class * int * pc * Netstring_tstring.tstring_polybox * int * int | Tag of tag_class * int * pc * value | ITag of tag_class * int * value | OID of int array | ROID of int array | ObjectDescriptor of string | External of value list | Embedded_PDV of value list | NumericString of string | PrintableString of string | TeletexString of string | VideotexString of string | VisibleString of string | IA5String of string | GraphicString of string | GeneralString of string | UniversalString of string | BMPString of string | UTF8String of string | CharString of string | UTCTime of time_value | GeneralizedTime of time_value and tag_class = | Universal | Application | Context | Private and int_value = string and real_value = string and bitstring_value = string and time_value = U of string | G of string type time_subtype = [ `U | `G ] let rec equal v1 v2 = let open Netstring_tstring in match (v1, v2) with | (Seq s1, Seq s2) -> List.length s1 = List.length s2 && List.for_all2 equal s1 s2 | (Set s1, Set s2) -> (* FIXME: compare the set *) List.length s1 = List.length s2 && List.for_all2 equal s1 s2 | (Tag(c1,t1,pc1,sub1), Tag(c2,t2,pc2,sub2)) -> c1=c2 && t1=t2 && pc1=pc2 && equal sub1 sub2 | (Tagptr(c1,t1,pc1,box1,pos1,len1), Tagptr(c2,t2,pc2,box2,pos2,len2)) -> let Tstring_polybox(ops1,s1) = box1 in let Tstring_polybox(ops2,s2) = box2 in c1=c2 && t1=t2 && pc1=pc2 && ops1.substring s1 pos1 len1 = ops2.substring s2 pos2 len2 | (External s1, External s2) -> List.length s1 = List.length s2 && List.for_all2 equal s1 s2 | (Embedded_PDV s1, Embedded_PDV s2) -> List.length s1 = List.length s2 && List.for_all2 equal s1 s2 | _ -> v1 = v2 let type_of_value = function | Bool _ -> Some Type_name.Bool | Integer _ -> Some Type_name.Integer | Enum _ -> Some Type_name.Enum | Real _ -> Some Type_name.Real | Bitstring _ -> Some Type_name.Bitstring | Octetstring _ -> Some Type_name.Octetstring | Null -> Some Type_name.Null | Seq _ -> Some Type_name.Seq | Set _ -> Some Type_name.Set | OID _ -> Some Type_name.OID | ROID _ -> Some Type_name.ROID | ObjectDescriptor _ -> Some Type_name.ObjectDescriptor | External _ -> Some Type_name.External | Embedded_PDV _ -> Some Type_name.Embedded_PDV | NumericString _ -> Some Type_name.NumericString | PrintableString _ -> Some Type_name.PrintableString | TeletexString _ -> Some Type_name.TeletexString | VideotexString _ -> Some Type_name.VideotexString | VisibleString _ -> Some Type_name.VisibleString | IA5String _ -> Some Type_name.IA5String | GraphicString _ -> Some Type_name.GraphicString | GeneralString _ -> Some Type_name.GeneralString | UniversalString _ -> Some Type_name.UniversalString | BMPString _ -> Some Type_name.BMPString | UTF8String _ -> Some Type_name.UTF8String | CharString _ -> Some Type_name.CharString | UTCTime _ -> Some Type_name.UTCTime | GeneralizedTime _ -> Some Type_name.GeneralizedTime | Tagptr _ | Tag _ | ITag _ -> None let get_int_repr v = v let get_int_b256 v = if v = "\000" then [| |] else Array.init (String.length v) (fun k -> Char.code v.[k]) let get_int64 v = match get_int_b256 v with | [| |] -> 0L | [| x0 |] -> Int64.shift_right (Int64.shift_left (Int64.of_int x0) 56) 56 | i when Array.length i <= 8 -> let x = ref 0L in let shift = ref 64 in for k = 0 to Array.length i - 1 do shift := !shift - 8; x := Int64.logor !x (Int64.shift_left (Int64.of_int i.(k)) !shift); done; Int64.shift_right !x !shift | _ -> raise Out_of_range let max_intL = Int64.of_int max_int let min_intL = Int64.of_int min_int let max_int32L = Int64.of_int32 (Int32.max_int) let min_int32L = Int64.of_int32 (Int32.min_int) let get_int v = let x = get_int64 v in if x > max_intL || x < min_intL then raise Out_of_range; Int64.to_int x let get_int32 v = let x = get_int64 v in if x > max_int32L || x < min_int32L then raise Out_of_range; Int64.to_int32 x let int64_a n = let rec recurse n p bit7 = if n = 0L then if bit7 then ( let a = Array.make (p+1) 0 in a.(0) <- 0; a ) else Array.make p 0 else if n = (-1L) then if bit7 then Array.make p 0 else ( let a = Array.make (p+1) 0 in a.(0) <- 255; a ) else let byte = Int64.to_int (Int64.logand n 0xffL) in let n' = Int64.shift_right n 8 in (* arithm. shift *) let a = recurse n' (p+1) (byte >= 0x80) in let l = Array.length a in a.(l-1-p) <- byte; a in if n = 0L || n = (-1L) then ( [| Int64.to_int (Int64.logand n 0xffL) |] ) else recurse n 0 false let intstr a = let l = Array.length a in let s = Bytes.make l '\x00' in for k = 0 to l-1 do Bytes.set s k (Char.chr a.(k)) done; Bytes.unsafe_to_string s let int64 n = intstr(int64_a n) let int32 n = int64 (Int64.of_int32 n) let int n = int64 (Int64.of_int n) let int_b256_a a = (* normalize the number (express it with as few bytes as possible) *) let l = Array.length a in if l=0 then [| 0 |] else ( let k = ref 0 in while !k < l-1 && ((a.(!k) = 0 && a.(!k+1) < 0x80) || (a.(!k) = 0xff && a.(!k+1) >= 0x80)) do incr k done; Array.sub a !k (l - !k) ) let int_b256 a = intstr (int_b256_a a) let get_real_repr v = v let get_bitstring_repr v = v let get_bitstring_size v = let n_unused = Char.code v.[0] in (String.length v - 1) * 8 - n_unused let get_bitstring_data v = String.sub v 1 (String.length v - 1) let get_bitstring_bits ?size v = let v_size = get_bitstring_size v in let size = match size with | None -> v_size | Some n -> n in Array.init size (fun k -> if k < v_size then let p = k lsr 3 in let q = k land 7 in let x = Char.code v.[ p + 1 ] in (x lsl q) land 0x80 <> 0 else false ) let bitstring_of_bits bits = let buf = Buffer.create 80 in let l = Array.length bits in let p = l land 0x7 in Buffer.add_char buf (Char.chr (if p=0 then 0 else 8-p)); let c = ref 0 in let sh = ref 7 in Array.iteri (fun k bit -> let b = if bit then 1 else 0 in c := !c lor (b lsl !sh); if !sh = 0 then ( Buffer.add_char buf (Char.chr !c); c := 0; sh := 7 ) else decr sh ) bits; if !sh < 7 then Buffer.add_char buf (Char.chr !c); Buffer.contents buf let mask = [| 0b1000_0000; 0b1100_0000; 0b1110_0000; 0b1111_0000; 0b1111_1000; 0b1111_1100; 0b1111_1110; 0b1111_1111; |] let bitstring_of_string s size = if size < 0 then invalid_arg "Netasn1.Value.bitstring_of_string"; let slen = String.length s in let buf = Buffer.create 80 in let p = size land 0x7 in Buffer.add_char buf (Char.chr (if p=0 then 0 else 8-p)); let q = size / 8 in Buffer.add_string buf (String.sub s 0 (min q slen)); if slen < q then Buffer.add_string buf (String.make (q - slen) '\x00'); if p > 0 then ( let last = if slen > q then Char.code (s.[q]) else 0 in let m = mask.(p-1) in let last' = last land m in Buffer.add_char buf (Char.chr last') ); Buffer.contents buf let truncate_trailing_zero_bits s = let slen = String.length s in let size_in = ((slen - 1) lsl 3) - Char.code s.[0] in let size = ref size_in in let k = ref (slen-1) in let cont = ref true in while !cont && !k >= 1 do let b = 8 - (if !k = slen-1 then Char.code s.[0] else 0) in if s.[ !k ] = '\x00' then size := !size - b else ( let c = Char.code s.[ !k ] in let j = ref 0 in while (mask.( !j ) land c) <> c do incr j done; size := !size - b + !j + 1; cont := false ); decr k; done; bitstring_of_string (String.sub s 1 (slen-1)) !size let utc_re = Netstring_str.regexp "^\\([0-9][0-9]\\)\ \\([0-9][0-9]\\)\ \\([0-9][0-9]\\)\ \\([0-9][0-9]\\)\ \\([0-9][0-9]\\)\ \\([0-9][0-9]\\)\\(.*\\)$" let gentime_re = Netstring_str.regexp "^\\([0-9][0-9][0-9][0-9]\\)\ \\([0-9][0-9]\\)\ \\([0-9][0-9]\\)\ \\([0-9][0-9]\\)\ \\([0-9][0-9]\\)\ \\([0-9][0-9]\\)\ \\(.[0-9]+\\)?\\([-Z+].*\\)$" let zone_re = Netstring_str.regexp "^[-+][0-9][0-9][0-9][0-9]$" let get_time_subtype = function | U s -> `U | G s -> `G let get_time_repr = function | U s -> s | G s -> s let get_zone s = if s = "Z" then 0 else ( match Netstring_str.string_match zone_re s 0 with | None -> failwith "Netasn1.Value.get_zone" | Some _ -> let h = int_of_string (String.sub s 1 2) in let m = int_of_string (String.sub s 3 2) in let v = h*60 + m in if s.[0] = '-' then -v else v ) let get_time = function | U s -> (match Netstring_str.string_match utc_re s 0 with | Some m -> let y2 = int_of_string (Netstring_str.matched_group m 1 s) in let year = if y2 >= 50 then 1950 + y2 else 2000 + y2 in let month = int_of_string (Netstring_str.matched_group m 2 s) in let day = int_of_string (Netstring_str.matched_group m 3 s) in let hour = int_of_string (Netstring_str.matched_group m 4 s) in let minute = int_of_string (Netstring_str.matched_group m 5 s) in let second = int_of_string (Netstring_str.matched_group m 6 s) in let zonestr = Netstring_str.matched_group m 7 s in let zone = get_zone zonestr in if month = 0 || month > 12 || day = 0 || day > 31 || hour > 23 || minute > 59 || second > 59 then failwith "Netasn1.Value.get_time"; { Netdate.year; month; day; hour; minute; second; nanos = 0; zone; week_day = (-1) } | None -> failwith "Netasn1.Value.get_time" ) | G s -> (match Netstring_str.string_match gentime_re s 0 with | Some m -> let year = int_of_string (Netstring_str.matched_group m 1 s) in let month = int_of_string (Netstring_str.matched_group m 2 s) in let day = int_of_string (Netstring_str.matched_group m 3 s) in let hour = int_of_string (Netstring_str.matched_group m 4 s) in let minute = int_of_string (Netstring_str.matched_group m 5 s) in let second = int_of_string (Netstring_str.matched_group m 6 s) in let zonestr = Netstring_str.matched_group m 8 s in let zone = get_zone zonestr in if month = 0 || month > 12 || day = 0 || day > 31 || hour > 23 || minute > 59 || second > 59 then failwith "Netasn1.Value.get_time"; let nanos = try let n1 = Netstring_str.matched_group m 7 s in let n2 = String.sub n1 1 (String.length n1 - 1) in let n3 = if String.length n2 > 9 then String.sub n2 0 9 else n2 in let n4 = n3 ^ String.make (9 - String.length n3) '0' in int_of_string n4 with Not_found -> 0 in { Netdate.year; month; day; hour; minute; second; nanos; zone; week_day = (-1) } | None -> failwith "Netasn1.Value.get_time" ) let utctime date = let open Netdate in if date.year < 1950 || date.year >= 2050 then failwith "Netasn1.Value.utctime: year out of valid range"; let s = if date.zone = 0 then Netdate.format ~fmt:"%y%m%d%H%M%SZ" date else Netdate.format ~fmt:"%y%m%d%H%M%S%z" date in U s let gentime ~digits date = if digits > 9 then invalid_arg "Netasn1.Value.gentime"; let s = if Netdate.(date.zone)=0 then Netdate.format ~fmt:("%Y%m%d%H%M%." ^ string_of_int digits ^ "SZ") date else Netdate.format ~fmt:("%Y%m%d%H%M%." ^ string_of_int digits ^ "S%z") date in G s end let type_of_tag = function | 1 -> Type_name.Bool | 2 -> Type_name.Integer | 3 -> Type_name.Bitstring | 4 -> Type_name.Octetstring | 5 -> Type_name.Null | 6 -> Type_name.OID | 7 -> Type_name.ObjectDescriptor | 8 -> Type_name.External | 9 -> Type_name.Real | 10 -> Type_name.Enum | 11 -> Type_name.Embedded_PDV | 12 -> Type_name.UTF8String | 13 -> Type_name.ROID | 16 -> Type_name.Seq | 17 -> Type_name.Set | 18 -> Type_name.NumericString | 19 -> Type_name.PrintableString | 20 -> Type_name.TeletexString | 21 -> Type_name.VideotexString | 22 -> Type_name.IA5String | 23 -> Type_name.UTCTime | 24 -> Type_name.GeneralizedTime | 25 -> Type_name.GraphicString | 26 -> Type_name.VisibleString | 27 -> Type_name.GeneralString | 28 -> Type_name.UniversalString | 29 -> Type_name.CharString | 30 -> Type_name.BMPString | _ -> raise Not_found let n_max = if Sys.word_size = 32 then 3 else 7 let decode_rel_oid s = (* will raise Not_found on parse error *) let cur = ref 0 in let end_pos = String.length s in let l = ref [] in while !cur < end_pos do let x = ref 0 in while s.[ !cur ] >= '\128' do x := (!x lsl 7) lor (Char.code s.[ !cur ] - 128); incr cur; if !cur > end_pos then raise Not_found; done; x := (!x lsl 7) lor (Char.code s.[ !cur ]); l := !x :: !l; incr cur; done; Array.of_list (List.rev !l) let decode_region_poly ?(pos=0) ?len ops s = let open Netstring_tstring in let pos_end = match len with | None -> ops.length s | Some n -> pos+n in (pos, pos_end) let decode_ber_header_poly ?pos ?len ?(skip_length_check=false) ops s = let open Netstring_tstring in let pos, pos_end = decode_region_poly ?pos ?len ops s in let cur = ref pos in let next() = if !cur < pos_end then ( let c = Char.code (ops.get s !cur) in incr cur; c ) else raise Header_too_short in let id0 = next() in let pc = if (id0 land 0x20) <> 0 then Value.Constructed else Value.Primitive in let tc = match id0 land 0xc0 with | 0x00 -> Value.Universal | 0x40 -> Value.Application | 0x80 -> Value.Context | 0xc0 -> Value.Private | _ -> assert false in let tag0 = id0 land 0x1f in let tag = ( if tag0 < 31 then tag0 else ( let tag = ref 0 in let b = ref (next()) in let n = ref 1 in while !b > 127 do incr n; if !n = 5 then raise(Parse_error !cur); (* impl limit *) tag := (!tag lsl 7) lor (!b land 0x7f); b := next(); done; tag := (!tag lsl 7) lor !b; !tag ) ) in let length_opt = ( let l0 = next() in if l0 < 128 then Some l0 else ( let n = l0-128 in if n=0 then None (* indefinite length *) else ( if n > n_max then raise(Parse_error !cur); (* impl limit *) let l = ref 0 in for k = 1 to n do l := (!l lsl 8) lor (next()) done; Some !l ) ) ) in ( match length_opt with | None -> if pc = Value.Primitive then raise(Parse_error !cur) | Some n -> if not skip_length_check && n > pos_end - !cur then raise(Parse_error !cur) ); let hdr_len = !cur - pos in (hdr_len, tc, pc, tag, length_opt) let rec decode_ber_length_poly ?pos ?len ops s = let open Netstring_tstring in let pos, pos_end = decode_region_poly ?pos ?len ops s in let (hdr_len, tc, pc, tag, length_opt) = try decode_ber_header_poly ~pos ~len:(pos_end - pos) ops s with | Header_too_short -> raise(Parse_error pos_end) in match length_opt with | Some n -> hdr_len + n | None -> let cur = ref (pos + hdr_len) in let at_end_marker() = !cur+2 <= pos_end && ops.get s !cur = '\000' && ops.get s (!cur+1) = '\000' in while not (at_end_marker()) do assert(!cur < pos_end); let n = decode_ber_length_poly ~pos:!cur ~len:(pos_end - !cur) ops s in cur := !cur + n; done; (!cur - pos) + 2 let rec decode_homo_construction_poly f pos pos_end indefinite expected_tag ops s = (* A construction where the primitives have all the same tag. The depth is arbitrary. [f] is called for every found primitive. *) let open Netstring_tstring in let cur = ref pos in let at_end() = if indefinite then !cur+2 <= pos_end && ops.get s !cur = '\000' && ops.get s (!cur+1) = '\000' else !cur = pos_end in while not (at_end()) do assert(!cur < pos_end); let (hdr_len, tc, pc, tag, length_opt) = try decode_ber_header_poly ~pos:!cur ~len:(pos_end - !cur) ops s with | Header_too_short -> raise (Parse_error pos_end) in if tc <> Value.Universal then raise (Parse_error !cur); if tag <> expected_tag then raise (Parse_error !cur); ( match pc with | Value.Primitive -> let n = match length_opt with | None -> assert false | Some n -> n in f (!cur + hdr_len) n; cur := !cur + hdr_len + n | Value.Constructed -> let sub_pos_end = match length_opt with | None -> pos_end | Some n -> !cur + hdr_len + n in let real_n = decode_homo_construction_poly f (!cur + hdr_len) sub_pos_end (length_opt = None) expected_tag ops s in ( match length_opt with | None -> () | Some n -> if n <> real_n then raise (Parse_error !cur) ); cur := !cur + hdr_len + real_n ); done; if indefinite then cur := !cur + 2; if not indefinite && !cur <> pos_end then raise (Parse_error !cur); !cur - pos let rec decode_ber_poly ?pos ?len ops s = let pos, pos_end = decode_region_poly ?pos ?len ops s in let (hdr_len, tc, pc, tag, length_opt) = try decode_ber_header_poly ~pos ~len:(pos_end - pos) ops s with | Header_too_short -> raise (Parse_error pos_end) in match tc with | Value.Universal -> let cur = pos + hdr_len in let ty_name = try type_of_tag tag with Not_found -> raise(Parse_error cur) in let len = match length_opt with | None -> pos_end - cur | Some n -> n in let content_len, value = decode_ber_contents_poly ~pos:cur ~len ~indefinite:(length_opt = None) ops s pc ty_name in ( match length_opt with | None -> () | Some n -> if content_len <> n then raise(Parse_error cur) ); (content_len + hdr_len, value) | _ -> let content_len = match length_opt with | None -> (decode_ber_length_poly ~pos ~len:(pos_end - pos) ops s) - hdr_len - 2 | Some n -> n in let box = Netstring_tstring.Tstring_polybox(ops,s) in let value = Value.Tagptr(tc, tag, pc, box, pos+hdr_len, content_len) in (content_len + hdr_len, value) and decode_ber_contents_poly ?pos ?len ?(indefinite=false) ops s pc ty = let open Netstring_tstring in let pos, pos_end = decode_region_poly ?pos ?len ops s in let len = pos_end - pos in if indefinite && pc=Value.Primitive then invalid_arg "Netasn1.decode_ber_contents: only constructed values \ permit indefinite length"; match ty with | Type_name.Null -> if pc <> Value.Primitive then raise(Parse_error pos); if len<>0 then raise(Parse_error pos); (0, Value.Null) | Type_name.Bool -> if pc <> Value.Primitive then raise(Parse_error pos); if len=0 then raise(Parse_error pos); let v = Value.Bool( ops.get s pos <> '\000' ) in (1, v) | Type_name.Integer -> if pc <> Value.Primitive then raise(Parse_error pos); if len=0 then raise(Parse_error pos); let u = ops.substring s pos len in (* FIXME: value check *) let v = Value.Integer u in (len, v) | Type_name.Enum -> if pc <> Value.Primitive then raise(Parse_error pos); if len=0 then raise(Parse_error pos); let u = ops.substring s pos len in (* FIXME: value check *) let v = Value.Enum u in (len, v) | Type_name.Real -> if pc <> Value.Primitive then raise(Parse_error pos); let u = ops.substring s pos len in (* FIXME: value check *) let v = Value.Real u in (len, v) | Type_name.OID -> if pc <> Value.Primitive then raise(Parse_error pos); let u = ops.substring s pos len in let r = try decode_rel_oid u with Not_found -> raise(Parse_error pos) in if Array.length r < 1 then raise(Parse_error pos); let x = if r.(0) < 40 then 0 else if r.(0) < 80 then 1 else 2 in let y = if x < 2 then r.(0) mod 40 else r.(0) - 80 in let oid = Array.append [| x; y |] (Array.sub r 1 (Array.length r - 1)) in let v = Value.OID oid in (len, v) | Type_name.ROID -> if pc <> Value.Primitive then raise(Parse_error pos); let u = ops.substring s pos len in let r = try decode_rel_oid u with Not_found -> raise(Parse_error pos) in let v = Value.ROID r in (len, v) | Type_name.Octetstring -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.Octetstring octets) | Type_name.ObjectDescriptor -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.ObjectDescriptor octets) | Type_name.UTF8String -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.UTF8String octets) | Type_name.NumericString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.NumericString octets) | Type_name.PrintableString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.PrintableString octets) | Type_name.TeletexString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.TeletexString octets) | Type_name.VideotexString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.VideotexString octets) | Type_name.IA5String -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.IA5String octets) | Type_name.GraphicString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.GraphicString octets) | Type_name.VisibleString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.VisibleString octets) | Type_name.GeneralString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.GeneralString octets) | Type_name.UniversalString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.UniversalString octets) | Type_name.CharString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.CharString octets) | Type_name.BMPString -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.BMPString octets) | Type_name.UTCTime -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.UTCTime (Value.U octets)) | Type_name.GeneralizedTime -> let (len, octets) = decode_ber_octets_poly pos pos_end indefinite ops s pc in (len, Value.GeneralizedTime (Value.G octets)) | Type_name.Bitstring -> let (len, bitstring) = decode_ber_bits_poly pos pos_end indefinite ops s pc in (len, Value.Bitstring bitstring) | Type_name.Seq -> if pc <> Value.Constructed then raise(Parse_error pos); let (len, list) = decode_list_construction_poly pos pos_end indefinite ops s in (len, Value.Seq list) | Type_name.Set -> if pc <> Value.Constructed then raise(Parse_error pos); let (len, list) = decode_list_construction_poly pos pos_end indefinite ops s in (len, Value.Set list) | Type_name.External -> if pc <> Value.Constructed then raise(Parse_error pos); let (len, list) = decode_list_construction_poly pos pos_end indefinite ops s in (len, Value.External list) | Type_name.Embedded_PDV -> if pc <> Value.Constructed then raise(Parse_error pos); let (len, list) = decode_list_construction_poly pos pos_end indefinite ops s in (len, Value.Embedded_PDV list) and decode_ber_octets_poly pos pos_end indefinite ops s pc = let open Netstring_tstring in let len = pos_end - pos in match pc with | Value.Primitive -> (len, ops.substring s pos len) | Value.Constructed -> let buf = Netbuffer.create 500 in let f p l = Netbuffer.add_subtstring_poly buf ops s p l in let n = decode_homo_construction_poly f pos pos_end indefinite 4 ops s in (n, Netbuffer.contents buf) and decode_ber_bits_poly pos pos_end indefinite ops s pc = let open Netstring_tstring in let len = pos_end - pos in match pc with | Value.Primitive -> if len = 0 then raise(Parse_error pos); let c0 = ops.get s pos in if c0 >= '\008' || (len = 1 && c0 <> '\000') then raise(Parse_error pos); (len, ops.substring s pos len) | Value.Constructed -> let c0_prev = ref '\000' in let buf = Netbuffer.create 500 in Netbuffer.add_char buf '\000'; let f p l = if !c0_prev <> '\000' then raise(Parse_error pos); if l = 0 then raise(Parse_error pos); let c0 = ops.get s p in if c0 >= '\008' || (l = 1 && c0 <> '\000') then raise(Parse_error pos); c0_prev := c0; Netbuffer.add_subtstring_poly buf ops s (p+1) (l-1) in let n = decode_homo_construction_poly f pos pos_end indefinite 3 ops s in let bitstring = Netbuffer.to_bytes buf in Bytes.set bitstring 0 !c0_prev; (n, Bytes.unsafe_to_string bitstring) and decode_list_construction_poly pos pos_end indefinite ops s = let open Netstring_tstring in let acc = ref [] in let cur = ref pos in let at_end() = if indefinite then !cur+2 <= pos_end && ops.get s !cur = '\000' && ops.get s (!cur+1) = '\000' else !cur = pos_end in while not(at_end()) do assert(!cur < pos_end); let (ber_len, value) = decode_ber_poly ~pos:!cur ~len:(pos_end - !cur) ops s in acc := value :: !acc; cur := !cur + ber_len; done; if indefinite then cur := !cur + 2; if not indefinite && !cur <> pos_end then raise (Parse_error !cur); (!cur - pos, List.rev !acc) let decode_ber ?pos ?len s = decode_ber_poly ?pos ?len Netstring_tstring.string_ops s let decode_ber_tstring ?pos ?len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> decode_ber_poly ?pos ?len ops s ) } ts let decode_ber_contents ?pos ?len ?indefinite s v ty = let ops = Netstring_tstring.string_ops in decode_ber_contents_poly ?pos ?len ?indefinite ops s v ty let decode_ber_contents_tstring ?pos ?len ?indefinite ts v ty = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> decode_ber_contents_poly ?pos ?len ?indefinite ops s v ty ) } ts let decode_ber_length ?pos ?len s = let ops = Netstring_tstring.string_ops in decode_ber_length_poly ?pos ?len ops s let decode_ber_length_tstring ?pos ?len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> decode_ber_length_poly ?pos ?len ops s ) } ts let decode_ber_header ?pos ?len ?skip_length_check s = let ops = Netstring_tstring.string_ops in decode_ber_header_poly ?pos ?len ?skip_length_check ops s let decode_ber_header_tstring ?pos ?len ?skip_length_check ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> decode_ber_header_poly ?pos ?len ?skip_length_check ops s ) } ts let rec streamline_seq expected seq = let open Netstring_tstring in match expected, seq with | [], [] -> [] | [], _ -> failwith "Netasn1.streamline_seq [1]" | ((exp_tc, exp_tag, exp_ty)::expected1), (Value.ITag(act_tc, act_tag, act_v)::seq1) when exp_tc=act_tc && exp_tag=act_tag -> if Value.type_of_value act_v <> Some exp_ty then failwith "Netasn1.streamline_seq [2]"; Some act_v :: streamline_seq expected1 seq1 | ((exp_tc, exp_tag, exp_ty)::expected1), (Value.Tagptr(act_tc,act_tag,pc,box,pos,len)::seq1) when exp_tc=act_tc && exp_tag=act_tag -> let Tstring_polybox(ops,s) = box in let act_len, v = decode_ber_contents_poly ~pos ~len ops s pc exp_ty in if act_len <> len then failwith "Netasn1.streamline_seq [3]"; Some v :: streamline_seq expected1 seq1 | _, (Value.Tag _ :: _) -> failwith "Netasn1.streamline_seq [4]" | ((Value.Universal, exp_tag, exp_ty)::expected1), (v::seq1) when Value.type_of_value v = Some exp_ty -> Some v :: streamline_seq expected1 seq1 | (_ :: expected1), _ -> None :: streamline_seq expected1 seq let streamline_set typeinfo set = let open Netstring_tstring in let ht = Hashtbl.create 5 in List.iter (fun (tc,tag,ty) -> Hashtbl.replace ht (tc,tag) ty) typeinfo; List.map (function | Value.ITag(tc, tag, v) -> let ty = try Hashtbl.find ht (tc,tag) with Not_found -> failwith "Netasn1.streamline_set" in if Value.type_of_value v <> Some ty then failwith "Netasn1.streamline_set"; v | Value.Tagptr(tc, tag, pc, box, pos, len) -> let ty = try Hashtbl.find ht (tc,tag) with Not_found -> failwith "Netasn1.streamline_set" in let Tstring_polybox(ops,s) = box in let act_len, v = decode_ber_contents_poly ~pos ~len ops s pc ty in if act_len <> len then failwith "Netasn1.streamline_set"; v | v -> v ) set ocamlnet-4.1.2/src/netstring/netstring_top.mli0000644000175000017500000000033712731530350020154 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (* You may load this module into the toploop in order to install * the printers for the various opaque data types of Netstring. *) ocamlnet-4.1.2/src/netstring/netpagebuffer.ml0000644000175000017500000003034012731530350017716 0ustar gerdgerd(* $Id$ *) open Netsys_types type t = { pgsize : int; mutable pages : Netsys_mem.memory array; (* Used pages have size pgsize. Unused pages are set to a dummy page *) mutable n_pages : int; (* The pages 0 .. n_pages-1 are used. n_pages >= 1 (exception below) *) mutable free_page : (unit -> unit) array; (* For each element of [pages] a function for freeing the page (quicker than by GC) *) mutable start_index : int; (* start_index: The first byte in the first page has this index *) mutable stop_index : int; (* stop_index: The first free byte in the last page *) mutable pool : Netsys_mem.memory_pool (* Pages that can be reclaimed *) } (* Except for one case we have this invariant: invariant: there is at least one free byte on the last page The exception is that we also tolerate n_pages=0, which is treated in the same way as an empty single page. When needed this empty single page is allocated to enforce the invariant (fix_invariant). *) let dummy_page = Bigarray.Array1.create Bigarray.char Bigarray.c_layout 0 let length buf = if buf.n_pages = 0 then 0 else buf.n_pages * buf.pgsize - buf.start_index - (buf.pgsize - buf.stop_index) let alloc_pages buf n = let need_resize = n + buf.n_pages > Array.length buf.pages in if need_resize then ( let new_size = max (min (2 * Array.length buf.pages) Sys.max_array_length) (buf.n_pages + n) in if new_size > Sys.max_array_length then failwith "Netpagebuffer: too large"; let pages' = Array.make new_size dummy_page in Array.blit buf.pages 0 pages' 0 buf.n_pages; let free_page' = Array.make new_size (fun () -> ()) in Array.blit buf.free_page 0 free_page' 0 buf.n_pages; buf.pages <- pages'; buf.free_page <- free_page' ); let n_pages' = buf.n_pages + n in for k = buf.n_pages to n_pages'-1 do let p, f = Netsys_mem.pool_alloc_memory2 buf.pool in buf.pages.(k) <- p; buf.free_page.(k) <- f done; buf.n_pages <- n_pages' let create pgsize = let sys_pgsize = Netsys_mem.pagesize in if pgsize mod sys_pgsize <> 0 then failwith "Netpagebuffer.create: invalid pagesize"; let pool = if pgsize = Netsys_mem.default_block_size then Netsys_mem.default_pool else if pgsize = Netsys_mem.small_block_size then Netsys_mem.small_pool else Netsys_mem.create_pool pgsize in { pgsize = pgsize; pages = [| dummy_page |]; n_pages = 0; free_page = [| fun () -> () |]; start_index = 0; stop_index = 0; pool = pool; } let fix_invariant buf = if buf.n_pages = 0 then ( alloc_pages buf 1; buf.start_index <- 0; buf.stop_index <- 0; ) let blit_to_bytes buf pos s s_pos len = let buf_len = length buf in let s_len = Bytes.length s in if pos < 0 || s_pos < 0 || len < 0 || len > buf_len - pos || len > s_len - s_pos then invalid_arg "Netpagebuffer.blit_to_string"; let abs_pos1 = pos + buf.start_index in let pg1 = abs_pos1 / buf.pgsize in let idx1 = abs_pos1 mod buf.pgsize in (* let abs_pos2 = abs_pos1 + len in let pg2 = abs_pos2 / buf.pgsize in let idx2 = abs_pos2 mod buf.pgsize in *) let cur_pg = ref pg1 in let cur_s_pos = ref s_pos in let rem_len = ref len in while !rem_len > 0 do let l = min (if !cur_pg = pg1 then buf.pgsize - idx1 else buf.pgsize) !rem_len in Netsys_mem.blit_memory_to_bytes buf.pages.( !cur_pg ) (if !cur_pg = pg1 then idx1 else 0) s !cur_s_pos l; cur_s_pos := !cur_s_pos + l; rem_len := !rem_len - l; incr cur_pg; done let blit_to_string = blit_to_bytes let blit = blit_to_bytes let blit_to_memory buf pos m m_pos len = let buf_len = length buf in let m_len = Bigarray.Array1.dim m in if pos < 0 || m_pos < 0 || len < 0 || len > buf_len - pos || len > m_len - m_pos then invalid_arg "Netpagebuffer.blit_to_memory"; let abs_pos1 = pos + buf.start_index in let pg1 = abs_pos1 / buf.pgsize in let idx1 = abs_pos1 mod buf.pgsize in (* let abs_pos2 = abs_pos1 + len in let pg2 = abs_pos2 / buf.pgsize in let idx2 = abs_pos2 mod buf.pgsize in *) let cur_pg = ref pg1 in let cur_m_pos = ref m_pos in let rem_len = ref len in while !rem_len > 0 do let l = min (if !cur_pg = pg1 then buf.pgsize - idx1 else buf.pgsize) !rem_len in Bigarray.Array1.blit (Bigarray.Array1.sub buf.pages.( !cur_pg ) (if !cur_pg = pg1 then idx1 else 0) l) (Bigarray.Array1.sub m !cur_m_pos l); cur_m_pos := !cur_m_pos + l; rem_len := !rem_len - l; incr cur_pg; done let blit_to_tbuffer buf pos tbuf pos2 len = match tbuf with | `Bytes s | `String s -> blit_to_bytes buf pos s pos2 len | `Memory m -> blit_to_memory buf pos m pos2 len let sub_bytes buf pos len = let buf_len = length buf in if pos < 0 || len < 0 || len > buf_len - pos then invalid_arg "Netpagebuffer.sub"; let s = Bytes.create len in blit_to_bytes buf pos s 0 len; s let sub buf pos len = Bytes.unsafe_to_string (sub_bytes buf pos len) let contents buf = sub buf 0 (length buf) let to_bytes buf = sub_bytes buf 0 (length buf) let to_memory buf = let buf_len = length buf in let m = Bigarray.Array1.create Bigarray.char Bigarray.c_layout buf_len in blit_to_memory buf 0 m 0 buf_len; m let to_tstring_poly : type s . t -> s Netstring_tstring.tstring_kind -> s = fun buf kind -> match kind with | Netstring_tstring.String_kind -> contents buf | Netstring_tstring.Bytes_kind -> to_bytes buf | Netstring_tstring.Memory_kind -> to_memory buf let to_tstring : type s . t -> s Netstring_tstring.tstring_kind -> tstring = fun buf kind -> match kind with | Netstring_tstring.String_kind -> `String (contents buf) | Netstring_tstring.Bytes_kind -> `Bytes(to_bytes buf) | Netstring_tstring.Memory_kind -> `Memory(to_memory buf) let add_substring buf s pos len = let s_len = String.length s in if pos < 0 || len < 0 || len > s_len - pos then invalid_arg "Netpagebuffer.add_sub_string"; fix_invariant buf; let len_for_new_pages = len - (buf.pgsize - buf.stop_index) in let new_pages = if len_for_new_pages >= 0 then len_for_new_pages / buf.pgsize + 1 else 0 in let old_last_page = buf.n_pages - 1 in alloc_pages buf new_pages; let len_old_last_page = min len (buf.pgsize - buf.stop_index) in Netsys_mem.blit_string_to_memory s pos buf.pages.(old_last_page) buf.stop_index len_old_last_page; buf.stop_index <- buf.stop_index + len_old_last_page; if buf.stop_index = buf.pgsize then buf.stop_index <- 0; let len_remaining = ref (len - len_old_last_page) in let cur_pos = ref (pos + len_old_last_page) in let cur_pg = ref(old_last_page + 1) in while !len_remaining > 0 do let l = min !len_remaining buf.pgsize in Netsys_mem.blit_string_to_memory s !cur_pos buf.pages.(!cur_pg) 0 l; cur_pos := !cur_pos + l; len_remaining := !len_remaining - l; incr cur_pg; if !len_remaining = 0 then ( buf.stop_index <- l; if l = buf.pgsize then buf.stop_index <- 0 ) done let add_sub_string = add_substring let add_string buf s = add_substring buf s 0 (String.length s) let add_subbytes buf s pos len = add_substring buf (Bytes.unsafe_to_string s) pos len let add_bytes buf s = add_subbytes buf s 0 (Bytes.length s) let add_submemory buf m pos len = (* very similar to add_sub_string. For performance reasons this is a copy of the above algorithm *) let m_len = Bigarray.Array1.dim m in if pos < 0 || len < 0 || len > m_len - pos then invalid_arg "Netpagebuffer.add_sub_memory"; fix_invariant buf; let len_for_new_pages = len - (buf.pgsize - buf.stop_index) in let new_pages = if len_for_new_pages >= 0 then len_for_new_pages / buf.pgsize + 1 else 0 in let old_last_page = buf.n_pages - 1 in alloc_pages buf new_pages; let len_old_last_page = min len (buf.pgsize - buf.stop_index) in Bigarray.Array1.blit (Bigarray.Array1.sub m pos len_old_last_page) (Bigarray.Array1.sub buf.pages.(old_last_page) buf.stop_index len_old_last_page); buf.stop_index <- buf.stop_index + len_old_last_page; if buf.stop_index = buf.pgsize then buf.stop_index <- 0; let len_remaining = ref (len - len_old_last_page) in let cur_pos = ref (pos + len_old_last_page) in let cur_pg = ref(old_last_page + 1) in while !len_remaining > 0 do let l = min !len_remaining buf.pgsize in Bigarray.Array1.blit (Bigarray.Array1.sub m !cur_pos l) (Bigarray.Array1.sub buf.pages.(!cur_pg) 0 l); cur_pos := !cur_pos + l; len_remaining := !len_remaining - l; incr cur_pg; if !len_remaining = 0 then ( buf.stop_index <- l; if l = buf.pgsize then buf.stop_index <- 0 ) done let add_sub_memory = add_submemory let add_tstring buf ts = match ts with | `String s -> add_string buf s | `Bytes s -> add_bytes buf s | `Memory s -> add_submemory buf s 0 (Bigarray.Array1.dim s) let add_subtstring buf ts pos len = match ts with | `String s -> add_substring buf s pos len | `Bytes s -> add_subbytes buf s pos len | `Memory s -> add_submemory buf s pos len let page_for_additions buf = fix_invariant buf; let last_page = buf.n_pages - 1 in ( buf.pages.(last_page), buf.stop_index, buf.pgsize - buf.stop_index ) let advance buf n = fix_invariant buf; if n < 0 || n > buf.pgsize - buf.stop_index then invalid_arg "Netpagebuffer.advance"; buf.stop_index <- buf.stop_index + n; if buf.stop_index = buf.pgsize then ( alloc_pages buf 1; buf.stop_index <- 0; ) let add_inplace buf f = let (page, pos, len) = page_for_additions buf in let n = f page pos len in if n < 0 || n > len then invalid_arg "Netpagebuffer.add_inplace"; advance buf n; n let page_for_consumption buf = fix_invariant buf; let stop = if buf.n_pages = 1 then buf.stop_index else buf.pgsize in ( buf.pages.(0), buf.start_index, stop ) let delete_hd buf n = let blen = length buf in if n < 0 || n > blen then invalid_arg "Netpagebuffer.delete_hd"; if n > 0 then ( (* hence, blen > 0, and the invariant holds *) let l_first_page = buf.pgsize - buf.start_index in if n < l_first_page then buf.start_index <- buf.start_index + n else ( let pages_to_delete = (n - l_first_page) / buf.pgsize + 1 in let new_start_index = (n - l_first_page) mod buf.pgsize in for k = 0 to pages_to_delete-1 do buf.free_page.(k) () done; let m = buf.n_pages - pages_to_delete in Array.blit buf.pages pages_to_delete buf.pages 0 m; Array.blit buf.free_page pages_to_delete buf.free_page 0 m; buf.n_pages <- buf.n_pages - pages_to_delete; buf.start_index <- new_start_index; for k = buf.n_pages to Array.length buf.pages - 1 do buf.pages.(k) <- dummy_page; buf.free_page.(k) <- (fun () -> ()) done ); if buf.n_pages = 1 && buf.start_index = buf.stop_index then ( buf.free_page.(0) (); buf.pages.(0) <- dummy_page; buf.free_page.(0) <- (fun () -> ()); buf.n_pages <- 0; buf.start_index <- 0; buf.stop_index <- 0; ) ) let clear buf = for k = 0 to buf.n_pages - 1 do buf.free_page.(k) (); buf.pages.(k) <- dummy_page; buf.free_page.(k) <- (fun () -> ()) done; buf.n_pages <- 0; buf.start_index <- 0; buf.stop_index <- 0 exception Found of int let index_from buf k c = if k < 0 || k > length buf then (* we allow k=length *) invalid_arg "Netpagebuffer.index_from"; let abs_pos1 = k + buf.start_index in let pg1 = abs_pos1 / buf.pgsize in let idx1 = abs_pos1 mod buf.pgsize in let pg = ref pg1 in let idx = ref idx1 in try while !pg < buf.n_pages do let page = buf.pages.( !pg ) in let stop_idx = if !pg = buf.n_pages - 1 then buf.stop_index else buf.pgsize in while !idx < stop_idx && Bigarray.Array1.unsafe_get page !idx <> c do incr idx done; if !idx < stop_idx then ( let pos = !pg * buf.pgsize + !idx - buf.start_index in raise(Found pos) ); incr pg; idx := 0 done; raise Not_found with | Found pos -> pos ocamlnet-4.1.2/src/netstring/netchannels_tut.txt0000644000175000017500000005734312731530350020522 0ustar gerdgerd{1:tutorial Netchannels Tutorial} [Netchannels] is one of the basic modules of this library, because it provides some very basic abstractions needed for many other functions of the library. The key abstractions [Netchannels] defines are the types [in_obj_channel] and [out_obj_channel]. Both are class types providing sequential access to byte streams, one for input, one for output. They are comparable to the types [in_channel] and [out_channel] of the standard library that allow access to files. However, there is one fundamental difference: [in_channel] and [out_channel] are restricted to resources that are available through file descriptors, whereas [in_obj_channel] and [out_obj_channel] are just class types, and by providing implementations for them any kind of resources can be accessed. {2 Motivation} In some respect, [Netchannels] fixes a deficiency of the standard library. Look at the module [Printf] which defines six variants of the [printf] function: {[ val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a val printf : ('a, out_channel, unit) format -> 'a val eprintf : ('a, out_channel, unit) format -> 'a val sprintf : ('a, unit, string) format -> 'a val bprintf : Buffer.t -> ('a, Buffer.t, unit) format -> 'a val kprintf : (string -> string) -> ('a, unit, string) format -> 'a ]} It is possible to write into six different kinds of print targets. The basic problem of this style is that the provider of a service function like [printf] must define it for every commonly used print target. The other solution is that the provider defines only one version of the service function, but that the caller of the function arranges the polymorphism. A [Netchannels]-aware [Printf] would have only one variant of [printf]: {[ val printf : out_obj_channel -> ('a, out_obj_channel, unit) format -> 'a ]} The caller would create the right [out_obj_channel] object for the real print target: {[ let file_ch = new output_file (file : out_channel) in printf file_ch ... ]} (printing into files), or: {[ let buffer_ch = new output_buffer (buf : Buffer.t) in printf buffer_ch ... ]} (printing into buffers). Of course, this is only a hypothetical example. The point is that this library defines many parsers and printers, and that it is really a simplification for both the library and the user of the library to have this object encapsulation of I/O resources. {2 Programming with [in_obj_channel] } For example, let us program a function reading a data source line by line, and returning the sum of all lines which must be integer numbers. The argument [ch] is an open {!Netchannels.in_obj_channel}, and the return value is the sum: {[ let sum_up (ch : in_obj_channel) = let sum = ref 0 in try while true do let line = ch # input_line() in sum := !sum + int_of_string line done; assert false with End_of_file -> !sum ]} The interesting point is that the data source can be anything: a channel, a string, or any other class that implements the class type [in_obj_channel]. This expression opens the file ["data"] and returns the sum of this file: {[ let ch = new input_channel (open_in "data") in sum_up ch ]} The class {!Netchannels.input_channel} is an implementation of the type [in_obj_channel] where every method of the class simply calls the corresponding function of the module [Pervasives]. (By the way, it would be a good idea to close the channel afterwards: [ch#close_in()]. We will discuss that below.) This expression sums up the contents of a constant string: {[ let s = "1\n2\n3\n4" in let ch = new input_string s in sum_up ch ]} The class {!Netchannels.input_string} is an implementation of the type [in_obj_channel] that reads from a string that is treated like a channel. The effect of using the [Netchannels] module is that the same implementation [sum_up] can be used to read from multiple data sources, as it is sufficient to call the function with different implementations of [in_obj_channel]. {2 The details of [in_obj_channel] } The properties of any class that implements [in_obj_channel] can be summarized as follows: - After the object has been created ([new]), the netchannel is open. The netchannel remains open until it is explicitly closed (method [close_in : unit -> unit]). When you call a method of a closed netchannel, the exception [Closed_channel] is raised (even if you try to close the channel again). - The methods {[ really_input : string -> int -> int -> unit input_char : unit -> char input_byte : unit -> int input_line : unit -> string ]} work like their counterparts of the standard library. In particular, the end of file condition is signaled by rasising [End_of_file]. - The method {[ input : string -> int -> int -> int ]} works like its counterpart of the standard library, except that the end of the file is also signaled by [End_of_file], and not by the return value 0. - The method [pos_in : int] returns the current byte position of the channel in a way that is logically consistent with the input methods: After reading [n] bytes, the method must return a position that is increased by [n]. Usually the position is zero after the object has been created, but this is not specified. Positions are available even for file descriptors that are not seekable. - There is intentionally no [seek_in] method. Seekable channels are currently out of scope, as netstring focuses on non-seekable channels. {2 Programming with [out_obj_channel] } The following function outputs the numbers of an [int list] sequentially on the passed netchannel: {[ let print_int_list (ch : out_obj_channel) l = List.iter (fun n -> ch # output_string (string_of_int n); ch # output_char '\n'; ) l; ch # flush() ]} The following statements write the output into a file: {[ let ch = new output_channel (open_out "data") in print_int_list ch [1;2;3] ]} And these statements write the output into a buffer: {[ let b = Buffer.create 16 in let ch = new output_buffer b in print_int_list ch [1;2;3] ]} Again, the caller of the function [print_int_list] determines the type of the output destination, and you do not need several functions for several types of destination. {2 The details of [out_obj_channel] } The properties of any class that implements [out_obj_channel] can be summarized as follows: - After the object has been created ([new]), the netchannel is open. The netchannel remains open until it is explicitly closed (method [close_out : unit -> unit]). When you call a method of a closed netchannel, the exception [Closed_channel] is raised (even if you try to close the channel again). - The methods {[ output : string -> int -> int -> int really_output : string -> int -> int -> unit output_char : char -> unit output_byte : int -> unit output_string : string -> unit ]} work like their counterparts of the standard library. There is usually an output buffer, but this is not specified. By calling [flush : unit -> unit], the contents of the output buffer are forced to be written to the destination. - The method {[ output_buffer : Buffer.t -> unit ]} works like [Buffer.output_channel], i.e. the contents of the buffer are printed to the channel. - The method {[ output_channel : ?len:int -> in_obj_channel -> unit ]} reads data from the argument [in_obj_channel] and prints them to the output channel. By default, the input channel is read until the EOF position. If the [len] argument is passed, at most this number of bytes are copied from the input channel to the output channel. The input channel remains open in all cases. - The method [pos_out : int] returns byte positions that are logically consistent: After writing [n] bytes, the method must return a position that is increased by [n]. Usually the position is zero after the object has been created, but this is not specified. Positions are available even for file descriptors that are not seekable. - There is intentionally no [seek_out] method. Seekable channels are currently out of scope, as netstring focuses on non-seekable channels. {2 How to close channels} As channels may use file descriptors for their implementation, it is very important that all open channels are closed after they have been used; otherwise the operating system will certainly get out of file descriptors. The simple way, {[ let ch = new args ... in ... do something ... ch # close_in() or close_out() ]} is dangerous because an exception may be raised between channel creation and the [close_*] invocation. An elegant solution is to use [with_in_obj_channel] and [with_out_obj_channel], as in: {[ with_in_obj_channel (* or with_out_obj_channel *) (new ...) (fun ch -> ... do something ... ) ]} This programming idiom ensures that the channel is always closed after usage, even in the case of exceptions. Complete examples: {[ let sum = with_in_obj_channel (new input_channel (open_in "data")) sum_up ;; ]} {[ with_out_obj_channel (new output_channel (open_out "data")) (fun ch -> print_int_list ch ["1";"2";"3"]) ;; ]} {2 Examples: HTML Parsing and Printing} In the Netstring library there are lots of parsers and printers that accept netchannels as data sources and destinations, respectively. One of them is the {!Nethtml} module providing an HTML parser and printer. A few code snippets how to call them, just to get used to netchannels: {[ let html_document = with_in_obj_channel (new input_channel (open_in "myfile.html")) Nethtml.parse ;; with_out_obj_channel (new output_channel (open_out "otherfile.html")) (fun ch -> Nethtml.write ch html_document) ;; ]} {2 Transactional Output Channels} Sometimes you do not want that generated output is directly sent to the underlying file descriptor, but rather buffered until you know that everything worked fine. Imagine you program a network service, and you want to return the result only when the computations are successful, and an error message otherwise. One way to achieve this effect is to manually program a buffer: {[ let network_service ch = try let b = Buffer.create 16 in let ch' = new output_buffer b in ... computations, write results into ch' ... ch' # close_out; ch # output_buffer b with error -> ... write error message to ch ... ]} There is a better way to do this, as there are transactional output channels. This type of netchannels provide a buffer for all written data like the above example, and only if data is explicitly committed it is copied to the real destination. Alternatively, you can also rollback the channel, i.e. delete the internal buffer. The signature of the type [trans_out_obj_channel] is: {[ class type trans_out_obj_channel = object inherit out_obj_channel method commit_work : unit -> unit method rollback_work : unit -> unit end ]} They have the same methods as [out_obj_channel] plus [commit_work] and [rollback_work]. There are two implementations, one of them keeping the buffer in memory, and the other using a temporary file: {[ let ch' = new buffered_trans_channel ch ]} And: {[ let ch' = new tempfile_trans_channel ch ]} In the latter case, there are optional arguments specifiying where the temporary file is created. Now the network service would look like: {[ let network_service transaction_provider ch = try let ch' = transaction_provider ch in ... computations, write results into ch' ... ch' # commit_work(); ch' # close_out() (* implies ch # close_out() *) with error -> ch' # rollback_work(); ... write error message to ch' ... ch' # commit_work(); ch' # close_out() (* implies ch # close_out() *) ]} You can program this function without specifying which of the two implementations is used. Just call this function as {[ network_service (new buffered_trans_channel) ch ]} or {[ network_service (new tempfile_trans_channel) ch ]} to determine the type of transaction buffer. Some details: - The method [commit_work] copies all uncommitted data to the underlying channel, and flushes all buffers. - When [rollback_work] is called the uncommitted data are deleted. - The method [flush] does not have any effect. - The reported position adds the committed and the uncommitted amounts of data. This means that [rollback_work] resets the position to the value of the last [commit_work] call. - When the transactional channel is closed, the underlying channel is closed, too. By default, the uncommitted data is deleted, but the current implementations can optionally commit data in this case. {2 Pipes and Filters} The class [pipe] is an [in_obj_channel] and an [out_obj_channel] at the same time (i.e. the class has the type [io_obj_channel]). A pipe has two endpoints, one for reading and one for writing (similar in concept to the pipes provided by the operating system, but note that our pipes have nothing to do with the OS pipes). Of course, you cannot read and write at the same time, so there must be an internal buffer storing the data that have been written but not yet read. How can such a construction be useful? Imagine you have two routines that run alternately, and one is capable of writing into netchannels, and the other can read from a netchannel. Pipes are the missing communication link in this situation, because the writer routine can output into the pipe, and the reader routine can read from the buffer of the pipe. In the following example, the writer outputs numbers from 1 to 100, and the reader sums them up: {[ let pipe = new pipe() ;; let k = ref 1 ;; let writer() = if !k <= 100 then ( pipe # output_string (string_of_int !k); incr k; if !k > 100 then pipe # close_out() else pipe # output_char '\n'; ) ;; let sum = ref 0 ;; let reader() = let line = pipe # input_line() in sum := !sum + int_of_string line ;; try while true do writer(); reader() done with End_of_file -> () ;; ]} The [writer] function prints the numbers into the pipe, and the [reader] function reads them in. By closing only the output end Of the pipe the [writer] signals the end of the stream, and the [input_line] method raises the exception [End_of_file]. Of course, this example is very simple. What does happen when more is printed into the pipe than read? The internal buffer grows. What does happen when more is tried to read from the pipe than available? The input methods signal this by raising the special exception [Buffer_underrun]. Unfortunately, handling this exception can be very complicated, as the reader must be able to deal with partial reads. This could be solved by using the {!Netstream} module. A netstream is another extension of [in_obj_channel] that allows one to look ahead, i.e. you can look at the bytes that will be read next, and use this information to decide whether enough data are available or not. Netstreams are explained in another chapter of this manual. Pipes have another feature that makes them useful even for "normal" programming. You can specify a conversion function that is called when data is to be transferred from the writing end to the reading end of the pipe. The module {!Netencoding.Base64} defines such a pipe that converts data: The class [encoding_pipe] automatically encodes all bytes written into it by the Base64 scheme: {[ let pipe = new Netencoding.Base64.encoding_pipe() ;; pipe # output_string "Hello World"; pipe # close_out() ;; let s = pipe # input_line() ;; ]} [s] has now the value ["SGVsbG8gV29ybGQ="], the encoded form of the input. This kind of pipe has the same interface as the basic pipe class, and the same problems to use it. Fortunately, the Netstring library has another facility simplifying the usage of pipes, namely {b filters}. There are two kinds of filters: The class {!Netchannels.output_filter} redirects data written to an [out_obj_channel] through a pipe, and the class {!Netchannels.input_filter} arranges that data read from an [in_obj_channel] flows through a pipe. An example makes that clearer. Imagine you have a function [write_results] that writes the results of a computation into an [out_obj_channel]. Normally, this channel is simply a file: {[ with_out_obj_channel (new output_channel (open_out "results")) write_results ]} Now you want that the file is Base64-encoded. This can be arranged by calling [write_results] differently: {[ let pipe = new Netencoding.Base64.encoding_pipe() in with_out_obj_channel (new output_channel (open_out "results")) (fun ch -> let ch' = new output_filter pipe ch in write_results ch'; ch' # close_out() ) ]} Now any invocation of an output method for [ch'] actually prints into the filter, which redirects the data through the [pipe], thus encoding them, and finally passing the encoded data to the underlying channel [ch]. Note that you must close [ch'] to ensure that all data are filtered, it is not sufficient to flush output. It is important to understand why filters must be closed to work properly. The problem is that the Base64 encoding converts triples of three bytes into quadruples of four bytes. Because not every string to convert is a multiple of three, there are special rules how to handle the exceeding one or two bytes at the end. The pipe must know the end of the input data in order to apply these rules correctly. If you only flush the filter, the exceeding bytes would simply remain in the internal buffer, because it is possible that more bytes follow. By closing the filter, you indicate that the definite end is reached, and the special rules for trailing data must be performed. \- Many conversions have similar problems, and because of this it is a good advice to always close output filters after usage. There is not only the class [output_filter] but also [input_filter]. This class can be used to perform conversions while reading from a file. Note that you often do not need to close input filters, because input channels can signal the end by raising [End_of_file], so the mentioned problems usually do not occur. There are a number of predefined conversion pipes: - {!Netencoding.Base64.encoding_pipe}: Performs Base64 encoding - {!Netencoding.Base64.decoding_pipe}: Performs Base64 decoding - {!Netencoding.QuotedPrintable.encoding_pipe}: Performs QuotedPrintable encoding - {!Netencoding.QuotedPrintable.decoding_pipe}: Performs QuotedPrintable decoding - {!Netconversion.conversion_pipe}: Converts the character encoding form charset A to charset B {2 Defining Classes for Object Channels} As subtyping and inheritance are orthogonal in O'Caml, you can simply create your own netchannels by defining classes that match the [in_obj_channel] or [out_obj_channel] types. E.g. {[ class my_in_channel : in_obj_channel = object (self) method input s pos len = ... method close_in() = ... method pos_in = ... method really_input s pos len = ... method input_char() = ... method input_line() = ... method input_byte() = ... end ]} Of course, this is non-trivial, especially for the [in_obj_channel] case. Fortunately, the Netchannels module includes a "construction kit" that allows one to define a channel class from only a few methods. A closer look at [in_obj_channel] and [out_obj_channel] shows that some methods can be derived from more fundamental methods. The following class types include only the fundamental methods: {[ class type raw_in_channel = object method input : string -> int -> int -> int method close_in : unit -> unit method pos_in : int end ]} {[ class type raw_out_channel = object method output : string -> int -> int -> int method close_out : unit -> unit method pos_out : int method flush : unit -> unit end ]} In order to define a new class, it is sufficient to define this raw version of the class, and to lift it to the full functionality. For example, to define [my_in_channel]: {[ class my_raw_in_channel : raw_in_channel = object (self) method input s pos len = ... method close_in() = ... method pos_in = ... end class my_in_channel = in_obj_channel_delegation (lift_in (`Raw(new my_raw_in_channel))) ]} The function {!Netchannels.lift_in} can lift several forms of incomplete channel objects to the full class type [in_obj_channel]. There is also the corresponding function {!Netchannels.lift_out}. Note that lifting adds by default another internal buffer to the channel that must be explicitly turned off when it is not wanted. The rationale for this buffer is that it avoids some cases with extremely poor performance which might be surprising for many users. The class [in_obj_channel_delegation] is just an auxiliary construction to turn the [in_obj_channel] {i object} returned by [lift_in] again into a class. {2 Some FAQ} {ul {- {i Netchannels add further layers on top of the built-in channels or file descriptors. Does this make them slow?} Of course, Netchannels are slower than the underlying built-in I/O facilities. There is at least one, but often even more than one method call until the data is transferred to or from the final I/O target. This costs time, and it is a good idea to reduce the number of method calls for maximum speed. Especially the character- or byte-based method calls should be avoided, it is better to collect data and pass them in larger chunks. This reduces the number of method calls that are needed to transfer a block of data. However, some classes implement buffers themselves, and data are only transferred when the buffers are full (or empty). The overhead for the extra method calls is small for these classes. The classes that implement their own buffers are the transactional channels, the pipes, and all the classes with "buffer" in their name. Netchannels are often stacked, i.e. one netchannel object transfers data to an underlying object, and this object passes the data to further objects. Often buffers are involved, and data are copied between buffers several times. Of course, these copies can reduce the speed, too.} {- {i Why do Netchannels not support seeking?} Netchannels were invented to support the implementation of network protocols. Network endpoints are not seekable.} {- {i What about [printf] and [scanf]?} In principle, methods for [printf] and [scanf] could be added to [out_obj_channel] and [in_obj_channel], respectively, as recent versions of O'Caml added the necessary language means (polymorphic methods, [kprintf], [kscanf]). However, polymorphic methods work only well when the type of the channel object is always annotated (e.g. as [(ch : out_obj_channel) # printf ...]), so this is not that much better than [ch # output_string (sprintf ...)].} {- {i Can I pass an [in_obj_channel] to an ocamllex-generated lexer?} Yes, just call {!Netchannels.lexbuf_of_in_obj_channel} to turn the [in_obj_channel] into a [lexbuf].} {- {i Do Netchannels support non-blocking I/O?} Yes and no. Yes, because you can open a descriptor in non-blocking mode, and create a netchannel from it. When the program would block, the [input] and [output] methods return 0 to indicate this. However, the non-raw methods cannot cope with these situations.} {- {i Do Netchannels support multiplexed I/O?} No, there is no equivalent to [Unix.select] on the level of netchannels.} {- {i Can I use Netchannels in multi-threaded programs?} Yes. However, shared netchannels are not locked, and strange things can happen when netchannels are used by several threads at the same time.} {- {i Can I use pipes to communicate between threads?} This could be made work, but it is currently not the case. A multithreading-aware wrapper around pipes could do the job.} {- {i Pipes call external programs to do their job, don't they?} No, they do not call external programs, nor do they need any parallel execution threads. Pipes are just a tricky way of organizing buffers.} {- {i How do I define my own conversion pipe?} Look at the sources [netencoding.ml], it includes several examples of conversion pipes.} } ocamlnet-4.1.2/src/netstring/neturl.mli0000644000175000017500000006241012731530350016566 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (* This module applies already O'Caml-3 features. *) (** Uniform Resource Locators (URLs) * * {b Contents} * * - {!Neturl.interface} * * The tutorial has been moved to {!Neturl_tut}. *) (** {1:interface Interface} * * This module provides functions to parse URLs, to print URLs, to * store URLs, to modify URLs, and to apply relative URLs. * * URLs are strings formed according to pattern (1) or (2): * * + [scheme://user;userparams:password\@host:port/path;params?query#fragment] * + [scheme:other;params?query#fragment] * * The word at the beginning of the URL identifies the URL scheme * (such as "http" or "file"). Depending on the scheme, not all of the * parts are allowed, or parts may be omitted. This module defines the * type [url_syntax] whose values describe which parts are allowed/required/ * not allowed for a concrete URL scheme (see below). * * Not all characters are allowed in a URL. Some characters are allowed, * but have the special task to separate the various parts of the URL * (reserved characters). * However, it is possible to include even invalid or reserved characters * as normal content by applying the [%]-encoding on these characters: * A ['%'] indicates that an encoded character follows, and the character * is denoted by a two-digit hexadecimal number (e.g. [%2f] for ['/']). * In the following descriptions, the term "encoded string" means a string * containing such [%]-encoded characters, and the "decoded string" means a * string not containing such characters. * See the module {!Netencoding.Url} for functions encoding or decoding * strings. * * The type [url] describes values storing the components of a URL, * and the [url_syntax] for the URL. In general, the components are * stored as encoded strings; however, not for all components the * [%]-encoding is applicable. * * For convenience, the functions creating, modifying, and accessing * URLs can handle both encoded and decoded strings. In order to * avoid errors, the functions pass strings even in their decoded form. * * Note that there is currently no function to compare URLs. The * canoncical comparison ( [=] ) is not applicable because the same URL * may be written in different ways. * * Note that nothing is said about the character set/encoding of URLs. * Some protocols and standards prefer UTF-8 as fundamental encoding * and apply the [%]-encoding on top of it; i.e. the byte sequence * representing a character in UTF-8 is [%]-encoded. * * {b Standards Compliance} * * This module implements RFC 1738 and RFC 1808. There is also a newer * RFC, 2396, updating the former RFCs, but this module is not fully * compatible with RFC 2396. The following (minor) problems may occur: * * - The module escapes more characters than needed. All characters that * are "unsafe" or "reserved" in either RFC document are escaped. * - URL parameters (appended with a ";") are handled as in RFCs 1738/1808. * In RFC 2396, every path component may have parameters, and the * algorithm to resolve relative URLs is different in this point. * If it is required to apply RFC 2396, one can disable URL parameters * in the syntax, and extract them from the path by a self-written * postprocessor. Usually, this is only required for [imap] URLs. * * In one point, RFC 2396 is preferred: * * - Authorities may be terminated by a question mark, as in * ["http://host?query"]. This is illegal in RFC 1738. The consequence * is, however, that question marks in user strings must be escaped. * * RFC 3986 introduces IPv6 addresses. These are now supported (but see * the comments below). *) exception Malformed_URL (** Raised by a number of functions when encountering a badly formed * URL. *) val extract_url_scheme : string -> string (** Returns the URL scheme from the string representation of an URL. * E.g. [extract_url_scheme "http://host/path" = "http"]. * The scheme name is always converted to lowercase characters. * Raises [Malformed_URL] if the scheme name is not found. *) type url_syntax_option = Url_part_not_recognized (** The part, even if there, is not even recognized *) | Url_part_allowed (** The part can be present *) | Url_part_required (** The part must be present *) type url_syntax = { url_enable_scheme : url_syntax_option; url_enable_user : url_syntax_option; url_enable_user_param: url_syntax_option; url_enable_password : url_syntax_option; url_enable_host : url_syntax_option; url_enable_port : url_syntax_option; url_enable_path : url_syntax_option; url_enable_param : url_syntax_option; url_enable_query : url_syntax_option; url_enable_fragment : url_syntax_option; url_enable_other : url_syntax_option; url_accepts_8bits : bool; url_is_valid : url -> bool; url_enable_relative : bool; } (** Values of type [url_syntax] describe which components of an URL are * recognized, which are allowed (and optional), and which are required. * Not all combinations are valid; the predicate expressed by the * function [url_syntax_is_valid] must hold. * * The function [url_is_valid] is applied when a fresh URL is created * and must return [true]. This function allows it to add an arbitrary * validity criterion to [url_syntax]. (Note that the URL passed to * this function is not fully working; you can safely assume that the * accessor functions [url_scheme] etc. can be applied to it.) * * Switch [url_accepts_8bit]: If [true], the bytes with code 128 to * 255 are treated like alphanumeric characters; if [false] these bytes * are illegal (but it is still possible to include such byte in their * encoded form: [%80] to [%FF]). * * Switch [url_enable_relative]: If [true], the syntax allows relative * URLs in principle. Actually, parsing of relative URLs is possible * when the optional parts are flagged as [Url_part_allowed] and not * as [Url_part_required]. However, it is useful to specify URL syntaxes * always as absolute URLs, and to weaken them on demand when a relative * URL is found by the parser. This switch enables that. In particular, * the function [partial_url_syntax] checks this flag. *) and url (** Values of type [url] describe concrete URLs. Every URL must have * a fundamental [url_syntax], and it is only possible to create URLs * conforming to the syntax. See [make_url] for further information. *) ;; val url_syntax_is_valid : url_syntax -> bool (** Checks whether the passed [url_syntax] is valid. This means: * - If passwords are recognized, users (and hosts) must be recognized, too * - If ports are recognized, hosts must be recognized, too * - If users are recognized, hosts must be recognized, too * - Either the syntax recognizes one of the phrases * \{ user, password, host, port, path \}, or the syntax recognized * the phrase 'other'. *) val partial_url_syntax : url_syntax -> url_syntax (** Transforms the syntax into another syntax where all required parts are * changed into optional parts. *) (* Note that all following url_syntaxes do not allow 8bit bytes. *) val null_url_syntax : url_syntax (** An URL syntax that recognizes nothing. Use this as base for your own * definitions, e.g. * {[ * let my_syntax = { null_url_syntax with * url_enable_host = Url_part_required; ... } * ]} *) val ip_url_syntax : url_syntax (** Syntax for IP based protocols. This syntax allows scheme, user, * password, host, port, path, param, query, fragment, but not "other". * It does not accept 8 bit bytes. *) val common_url_syntax : (string, url_syntax) Hashtbl.t (** Syntax descriptions for common URL schemes. The key of the hashtable * is the scheme name, and the value is the corresponding syntax. * * - ["file"]: scheme, host?, path * - ["ftp"]: scheme, user?, password?, host, port?, path?, param? * Note: param is not checked. * - ["http"], ["https"]: * scheme, user?, password?, host, port?, path?, query? * - ["mailto"]: scheme, other, query? (RFC 2368) * - ["pop"], ["pops"]: scheme, user?, user_param?, password?, host, port? * Note: user_param is not checked. * (RFC 2384) * - ["imap"], ["imaps"]: scheme, user?, user_param?, password?, host, port?, * path?, query? (RFC 2192) * Note: "param" is intentionally not recognized to get the resolution of * relative URLs as described in the RFC. When analysing this kind of URL, * it is recommended to re-parse it with "param" enabled. * - ["news"]: scheme, other (RFC 1738) * - ["nntp"], ["nntps"]: scheme, host, port?, path (with two components) * (RFC 1738) * - ["data"]: scheme, other (RFC 2397). "other" is not further decomposed. * - ["ipp"], ["ipps"]: scheme, host, port? , path?, query? (RFC 3510) * - ["cid"], ["mid"]: Content/message identifiers: scheme, other * - ["ldap"]: scheme, host?, port?, path?, query? (RFC 4516) * * Notes: * - These syntax descriptions can be weakened for partial/relative URLs * by changing the required parts to optional parts: See the function * [partial_url_syntax]. * - None of the descriptions allows fragments. These can be enabled by * setting [url_enable_fragment] to [Url_part_allowed]. E.g. * {[ { file_url_syntax with url_enable_fragment = Url_part_allowed } ]} * - 8 bit bytes are not accepted * - A large number of standardised scheme syntaxes are not available, * e.g. gopher, prospero, wais. The selection is a bit subjective, * but I have tried to omit protocols that are no longer in common * use, or that are very special. * - The LDAP URL syntax (RFC 1959) does not fit into our scheme, it * is omitted for now because of this. *) val null_url : url (** A URL without any component and [null_url_syntax] *) val make_url : ?encoded:bool -> ?scheme:string -> ?user:string -> ?user_param:string list -> ?password:string -> ?host:string -> ?addr:Unix.inet_addr -> ?port:int -> ?socksymbol: Netsockaddr.socksymbol -> ?path:string list -> ?param:string list -> ?query:string -> ?fragment:string -> ?other:string -> url_syntax -> url (** Creates a URL from components: * * - The components [scheme] and [host] are simple strings to which the * [%]-encoding is not applicable. [host] may be a (DNS) name, an * IPv4 address as "dotted quad", or an IPv6 address enclosed in * brackets. * - [addr] also sets [host], but directly from an [inet_addr]. * - The component [port] is a simple number. Of course, the [%]-encoding * is not applicable, too. * - [socksymbol] sets both [host] and [port] from the socksymbol of * type [`Inet] or [`Inet_byname]. * - The components [user], [password], [query], [fragment], and [other] * are strings which may contain [%]-encoded characters. By default, * you can pass any string for these components, and problematic characters * are automatically encoded. If you set [encoded:true], the passed * strings must already be encoded, but the function checks whether * the encoding is syntactically correct. * Note that for [query] even the characters ['?'] and ['='] are encoded * by default, so you need to set [encoded:true] to pass a reasonable * query string. * - The components [user_param], [path] and [param] are lists of strings which may * contain [%]-encoded characters. Again, the default is to pass * decoded strings to the function, and the function encodes them * automatically, and by setting [encoded:true] the caller is responsible * for encoding the strings. Passing empty lists for these components * means that they are not part of the constructed URL. * See below for the respresentation of these components. * * [socksymbol] has precedence over [addr], which has precedence over * [host]. [socksymbol] also has precedence over [port]. * * The strings representing the components do not * contain the characters separating the components from each other. * * The created URL must conform to the [url_syntax], i.e.: * - The URL must only contain components which are recognized by the * syntax * - The URL must contain components which are required by the syntax * - The URL must fulfill the predicate expressed by the [url_is_valid] * function of the syntax. * * The path of a URL is represented as a list of ['/']-separated path * components. i.e. * * [ [ s1; s2; ...; sN ] ] represents the path * [s1 ^ "/" ^ s2 ^ "/" ^ ... ^ "/" ^ sN] * * As special cases: * - [[]] is the non-existing path * - [[ "" ]] is ["/"] * - [[ "";"" ]] is illegal * * Except of [s1] and [sN], the path components must not be empty strings. * * To avoid ambiguities, it is illegal to create URLs with both relative * paths ([s1 <> ""]) and host components. * * Parameters of URLs ([param] and [user_param]) are components * beginning with [';']. The list * of parameters is represented as list of strings where the strings * contain the value following [';']. *) val modify_url : ?syntax:url_syntax -> ?encoded:bool -> ?scheme:string -> ?user:string -> ?user_param:string list -> ?password:string -> ?host:string -> ?addr:Unix.inet_addr -> ?port:int -> ?socksymbol: Netsockaddr.socksymbol -> ?path:string list -> ?param:string list -> ?query:string -> ?fragment:string -> ?other:string -> url -> url (** Modifies the passed components and returns the modified URL. * The modfied URL shares unmodified components with the original * URL. *) val remove_from_url : ?scheme:bool -> ?user:bool -> ?user_param:bool -> ?password:bool -> ?host:bool -> ?port:bool -> ?path:bool -> ?param:bool -> ?query:bool -> ?fragment:bool -> ?other:bool -> url -> url (** Removes the [true] components from the URL, and returns the modified * URL. * The modfied URL shares unmodified components with the original * URL. *) val default_url : ?encoded:bool -> ?scheme:string -> ?user:string -> ?user_param:string list -> ?password:string -> ?host:string -> ?port:int -> ?path:string list -> ?param:string list -> ?query:string -> ?fragment:string -> ?other:string -> url -> url (** Adds missing components and returns the modified URL. * The modfied URL shares unmodified components with the original * URL. *) val undefault_url : ?scheme:string -> ?user:string -> ?user_param:string list -> ?password:string -> ?host:string -> ?port:int -> ?path:string list -> ?param:string list -> ?query:string -> ?fragment:string -> ?other:string -> url -> url (** Removes components from the URL if they have the passed value, and * returns the modified URL. * Note: The values must always be passed in {b encoded} form! * The modfied URL shares unmodified components with the original * URL. *) val url_syntax_of_url : url -> url_syntax (** Returns the [url_syntax] record of a URL. *) val url_of_string : url_syntax -> string -> url (** Parses the passed string according to the passed [url_syntax]. *) val string_of_url : url -> string (** Returns the URL as string *) val parse_url : ?schemes:(string, url_syntax) Hashtbl.t -> ?base_syntax:url_syntax -> ?accept_8bits:bool -> ?enable_fragment:bool -> string -> url (** Parses the string and returns the URL the string represents. * If the URL is absolute (i.e. begins with a scheme like * "http:..."), the syntax will be looked up in [schemes]. * If the URL is relative, the [base_syntax] will be taken * if passed. Without [base_syntax], relative URLs cannot be * parsed. * * @param schemes This hashtable maps scheme names to syntax descriptions. * The default is [common_url_syntax]. * @param base_syntax If passed, the function can parse relative URLs * according to this syntax. If not passed, the function will raise * [Malformed_URL] on a relative URL. * @param accept_8bits If [false], the default, it depends on the * syntax descriptions in [schemes] whether 8 bit characters are * accepted in the input or not. If [true], 8 bit characters are * always accepted. * @param enable_fragment If [false], the default, it depends on the * syntax descriptions in [schemes] whether fragment identifiers * (e.g. "#fragment") are recognized or not. If [true], fragments * are always recognized. *) val fixup_url_string : ?escape_hash:bool -> string -> string (** Escapes some unsafe or "unwise" characters that are commonly used * in URL strings: space, < > \{ \} ^ \\ | and double quotes. * Call this function before parsing the URL to support these * characters. * * If [escape_hash] is set, '#' is also escaped. * * Change: Since Ocamlnet-3.4, square brackets are no longer fixed up, * because they have now a legal use to denote IPv6 addresses. *) val url_provides : ?scheme:bool -> ?user:bool -> ?user_param:bool -> ?password:bool -> ?host:bool -> ?port:bool -> ?path:bool -> ?param:bool -> ?query:bool -> ?fragment:bool -> ?other:bool -> url -> bool (** Returns [true] iff the URL has all of the components passed with * [true] value. *) val url_scheme : url -> string val url_user : ?encoded:bool -> url -> string val url_user_param: ?encoded:bool -> url -> string list val url_password : ?encoded:bool -> url -> string val url_host : url -> string val url_port : url -> int val url_path : ?encoded:bool -> url -> string list val url_param : ?encoded:bool -> url -> string list val url_query : ?encoded:bool -> url -> string val url_fragment : ?encoded:bool -> url -> string val url_other : ?encoded:bool -> url -> string (** Return components of the URL. The functions return decoded strings * unless [encoded:true] is set. * If the component does not exist, the exception [Not_found] * is raised. * * Note that IPv6 addresses, when returned by [url_host], are enclosed * in square brackets. Modules calling [url_host] may require porting * to support this syntax variant. *) val url_addr : url -> Unix.inet_addr (** If the [host] part of the URL is an IP address, the address is returned. Works for IPv4 and IPv6 addresses. Otherwise [Not_found] is raised. *) val url_socksymbol : url -> int -> Netsockaddr.socksymbol (** [url_socksymbol url default_port]: Returns the [host] and [port] parts of the URL as [socksymbol]. If the port is missing in the URL, [default_port] is substituted. If the [host] is missing in the URL the exception [Not_found] is raised. *) val split_path : string -> string list (** Splits a ['/']-separated path into components (e.g. to set up the * [path] argument of [make_url]). * E.g. * {[ * split_path "a/b/c" = [ "a"; "b"; "c" ], * split_path "/a/b" = [ ""; "a"; "b" ], * split_path "a/b/" = [ "a"; "b"; "" ] ]} * Beware that [split_path ".."] returns [[".."]] while [split_path "../"] * returns [[".."; ""]]. The two will behave differently, for example * when used with {!Neturl.apply_relative_url}. *) val join_path : string list -> string (** Concatenates the path components (reverse function of split_path). *) val norm_path : string list -> string list (** Removes ["."] and [".."] from the path if possible. Deletes double slashes. * * {b Examples} * * {ul * {- [norm_path ["."] = []] * * means: "." = ""} * {- [norm_path ["."; ""] = []] * * means: "./" = ""} * {- [norm_path ["a"; "."] = ["a"; ""]] * * means: "a/." = "a/"} * {- [norm_path ["a"; "b"; "."] = ["a"; "b"; ""]] * * means: "a/b/." = "a/b/"} * {- [norm_path ["a"; "."; "b"; "."] = ["a"; "b"; ""]] * * means: "a/./b/." = "a/b/"} * {- [norm_path [".."] = [".."; ""]] * * means: ".." = "../"} * {- [norm_path [".."; ""] = [".."; ""]] * * means: "../" = "../"} * {- [norm_path ["a"; "b"; ".."; "c" ] = ["a"; "c"]] * * means: "a/b/../c" = "a/c"} * {- [norm_path ["a"; "b"; ".."; "c"; ""] = ["a"; "c"; ""]] * * means: "a/b/../c/" = "a/c/"} * {- [norm_path ["";"";"a";"";"b"] = [""; "a"; "b"]] * * means: "//a//b" = "/a/b"} * {- [norm_path ["a"; "b"; ""; ".."; "c"; ""] = ["a"; "c"; ""]] * * means: "a/b//../c/" = "a/c/"} * {- [norm_path ["a"; ".."] = []] * * means: "a/.." = ""} * } *) val apply_relative_url : url -> url -> url (** [apply_relative_url base rel]: * Interprets [rel] relative to [base] and returns the new URL. This * function implements RFC 1808. * * It is not necessary that [rel] has the same syntax as [base]. * Note, however, that it is checked whether the resulting URL is * syntactically correct with the syntax of [base]. If not, the * exception [Malformed_URL] will be raised. * * Examples (the URLs are represented as strings, see {!Neturl.split_path} * to split them for {!Neturl.make_url}): * * base="x/y", url="a/b" => result="x/a/b" * base="x/y/", url="a/b" => result="x/y/a/b" * base="x/y/..", url="a/b" => result="x/y/a/b" (beware!) * base="x/y/../", url="a/b" => result="x/a/b" *) val ensure_absolute_url : ?base:url -> url -> url (** If the anonymous URL is absolute, it is just returned as result of * this function. If the URL is relative, it is tried to make it * absolute by resolving it relative to [base]. If there is no [base] * or if the the base URL does not allow the parts that would be added * (e.g. if the anonymous URL possesses a fragment and [base] does not * allow that), this will fail, and the function raises [Malformed_URL]. *) val file_url_of_local_path : ?getcwd:(unit -> string) -> string -> url (** Generates a URL with "file" scheme from the passed path name. The * URL is always absolute, i.e. the current directory is prepended if the * path is not absolute. * * Note that no character set conversions are performed. * * Win32: The input path name may use forward or backward slashes. * Absolute paths with drive letters and UNC paths are recognised. * Relative paths with drive letters, however, are not recognised * (e.g. ["c:file"]), as it is not possible to access the drive-specific * working directory from the O'Caml runtime. * * Cygwin: The input path name may use forward or backward slashes. * Absolute paths with drive letters and UNC paths are recognised. * The former are translated to ["/cygdrive"] names. * * @param getcwd The function returns the path taken as current working * directory. Note that for * Win32 this must be either an absolute name with drive letter, * or an UNC path. Default: [Sys.getcwd] *) val local_path_of_file_url : url -> string (** Extracts the path from an absolute file URL, and returns a * correct path name. * * If the URL is not a file URL, or is not absolute, the function will * fail. * * Win32: The URL must either contain a drive letter, or must refer * to another host. * * Cygwin: Drive letters and remote URLs are recognised. *) val print_url : url -> unit (** Printer for the toploop. *) (* ---------------------------------------------------------------------- *) (* Special accessors *) (* val mailto_recipients : url -> Netaddress.mailbox list - Returns all recipients, incl the recpients in the "to" header val ftp_type : url -> XXX - Returns the FTP transfer type val auth_param : url -> XXX - if the URL has an AUTH style [user_param] the value is returned val data_content_type : url -> XXX val data_contents : url -> XXX - Decomposes "data" URLs *) (* ---------------------------------------------------------------------- *) (* EXAMPLES: * * let http = Hashtbl.find common_url_syntax "http";; * let u = url_of_string http "http://g:pw@host/a/%62/";; * string_of_url u;; * --> "http://g:pw@host/a/%62/" * url_scheme u;; * --> "http" * url_user u;; * --> "g" * url_password u;; * --> "pw" * url_host u;; * --> "host" * url_path u;; * --> [ ""; "a"; "b"; "" ] (* sic! *) * url_path ~encoded:true u;; * --> [ ""; "a"; "%62"; "" ] * let v = make_url * ~path:[ ".."; "c" ] * ~fragment:"near-the-#-character" * { (partial_url_syntax http) with url_enable_fragment = Url_part_allowed };; * string_of_url v;; * --> "../c#near-the-%23-character" * let u' = modify_url ~syntax:(url_syntax_of_url v) u;; * (* u does not permit fragments *) * let w = apply_relative_url u' v;; * string_of_url w;; * --> "http://g:pw@host/c#near-the-%23-character" *) (* ---------------------------------------------------------------------- *) (**/**) val ldap_url_syntax : url_syntax ocamlnet-4.1.2/src/netstring/netoid.mli0000644000175000017500000000131112731530350016530 0ustar gerdgerd(* $Id$ *) (** X.500 Object Identifiers *) type t = int array val equal : t -> t -> bool (** Whether two OIDs are equal *) val compare : t -> t -> int (** Lexicographic ordering of OIDs *) val of_string : string -> t (** Parses an OID in dot notation, e.g. [of_string "2.3.4" = [| 2; 3; 4 |]] *) val to_string : t -> string (** Returns the OID in dot notation, e.g. [to_string [| 2; 3; 4 |] = "2.3.4"] *) val of_string_curly : string -> t (** Parses an OID in curly brace notation, e.g. [of_string "{2 3 4}" = [| 2; 3; 4 |]] *) val to_string_curly : t -> string (** Returns the OID in curly brace notation, e.g. [to_string [| 2; 3; 4 |] = "{2 3 4}"] *) ocamlnet-4.1.2/src/netstring/netconst.mlp0000644000175000017500000000006212731530350017114 0ustar gerdgerd(* $Id$ *) let ocamlnet_version = "@VERSION@" ;; ocamlnet-4.1.2/src/netstring/netaccel_link.ml0000644000175000017500000000003612731530350017673 0ustar gerdgerd(* $Id$ *) Netaccel.init();; ocamlnet-4.1.2/src/netstring/netmech_digest_http.mli0000644000175000017500000000532212731530350021275 0ustar gerdgerd(* $Id$ *) (** Digest authentication for HTTP *) module Digest : Nethttp.HTTP_CLIENT_MECHANISM (** This is the standard HTTP digest authentication mechanism (see RFCs 2069, 2617, 7616). The hash functions MD5 and SHA-256 are supported, in server preference. This version does not include mutual authentication, i.e. it does not matter what the server responds in the Authentication-Info header. There is no support for the "auth-int" level of protection. How to use with {!Nethttp_client}: The handlers {!Nethttp_client.unified_auth_handler} and {!Nethttp_client.digest_auth_handler} wrap this mechanism already. Additionally, there is also the option of plugging in this module directly. For this, you need the adapter {!Nethttp_client.generic_auth_handler}, e.g. {[ let m = ( module Netmech_digest_http.Digest ) let h = new Nethttp_client.generic_auth_handler key_ring [ m ] http_pipeline # add_auth_handler h ]} Get [key_ring] by instantiating {!Nethttp_client.key_ring}. Note that the key ring must use UTF-8 encoding (although the Digest protocol might need to recode to ISO-8859-1 - note that authentication will fail if this is not possible). *) module Digest_mutual : Nethttp.HTTP_CLIENT_MECHANISM (** This is the standard HTTP digest authentication mechanism (see RFCs 2069, 2617, 7616). This version also authenticates the server by checking the Authentication-Info header which must include the correct [rspauth] parameter. This parameter proves that the server actually knew the password. Note that mutual authentication does generally not prevent that request data is sent to the server before the authentication succeeds. This includes the header and also the request body (for POST and PUT methods). Because of this it is recommended to ensure that requests not carrying any sensitive data precede those requests that need protection. You need to explicitly plug in this module into the HTTP client in order to enable it. See {!Netmech_digest_http.Digest} for details. *) module type PROFILE = sig val mutual : bool (** If true, the Authentication-Info header is checked. If false, this header is ignored. *) val hash_functions : Netsys_digests.iana_hash_fn list (** List of enabled hash functions. The mechanism checks whether the function is provided by {!Netsys_digests}, and automatically removed unavailable hashes. MD5 is always supported. *) end module Make_digest(P:PROFILE) : Nethttp.HTTP_CLIENT_MECHANISM (** Create a custom version of the digest mechanism *) ocamlnet-4.1.2/src/netstring/netulex_tut.txt0000644000175000017500000000414312731530350017672 0ustar gerdgerd{1:tutorial Netulex Tutorial} Of course, you need Alain Frisch's [ulex] utility first. It installs itself under the name [ulex] as findlib library. Next, write your lexer, e.g. (line numbers in brackets): {[ [1] open Netulex [2] let digits = lexer [3] | ['0'-'9']+ -> `Number(int_of_string(Ulexing.utf8_lexeme lexbuf)) [4] | 8364 -> `Euro_sign (* Code point #8364 in Unicode *) ]} This is a very trivial example. The lexer accepts sequences of digits, and returns them as `Number tokens. Furthermore, the euro sign is recognized and returned as `Euro_sign. Note that in the first case {!Netulex.Ulexing.utf8_lexeme} is called to retrieve the current lexeme as UTF-8 string. (Well, digits are a bad example, as they are only ASCII, and UTF-8 is not really needed. Imagine you want to extend the scanner to other number systems represented in the Unicode character set.) Line 1 is quite important. If you don't open [Netulex], the generated [ulex] code will use the version of the [Ulexing] module coming with [ulex], and not this one. Call the lexer as follows (line numbers in brackets): {[ [5] let sample = "42543\226\130\172";; [6] let ulb = Netulex.ULB.from_string `Enc_utf8 sample;; [7] let lexbuf = Netulex.Ulexing.from_ulb_lexbuf ulb;; [8] let first_token = digits lexbuf;; ]} Now, [first_token] is [`Number 42543]. After {[ [9] let second_token = digits lexbuf;; ]} this variable is set to [`Euro_sign], because the three-byte sequence "\226\130\172" represents the euro sign in UTF-8. In line 6, the encoding [`Enc_utf8] selects that [sample] is an UTF-8 string. You can pass here any encoding the {!Netconversion} module understands. If you would like to scan from another source, just change line 6, e.g. {[ [6'] let ulb = Netulex.ULB.from_in_obj_channel ch ]} where [ch] is any input channel the {!Netchannels} module supports. For example, to read from a file: {[ let ch = new Netchannels.input_channel (open_in "filename") ]} You should compile the examples with {[ ocamlfind ... -package ulex,netstring -syntax camlp4o ... ]} For the syntax of the lexer rules, see the documentation coming with [ulex]. ocamlnet-4.1.2/src/netstring/netsaslprep.mli0000644000175000017500000000114712731530350017615 0ustar gerdgerd(* $Id$ *) (** The SASLprep algorithm (RFC 4013) *) (** This module implements the SASLprep string preparation algorithm, often used for normalizing passwords. Note that SASLprep is SLOOOOOOW, and should really only be used on short strings like passwords. This version of SASLprep doesn't check for unassigned codepoints. *) exception SASLprepError (** Raised when a string cannot be transformed *) val saslprep_a : int array -> int array (** Transform a string given as array of Unicode code points *) val saslprep : string -> string (** Transform a string given as UTF-8 string *) ocamlnet-4.1.2/src/netstring/netencoding.mli0000644000175000017500000004411012731530350017547 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Base64, Quoted Printable, URL encoding, HTML escaping *) (* *********************************************************************) (* Several encodings important for the net *) (* *********************************************************************) open Netsys_types (* *********************************************************************) (* Base 64 encoding *) (* *********************************************************************) (* See RFC 2045 for a description of Base 64 encoding. *) (* THREAD-SAFETY: * All Base64 functions are reentrant and thus thread-safe. *) module Base64 : sig (** Base64 encoding as described in RFC 2045 *) val encode : ?pos:int -> ?len:int -> ?linelength:int -> ?crlf:bool -> ?plus:char -> ?slash:char -> string -> string (** Compute the "base 64" encoding of the given string argument. * Note that the result is a string that only contains the characters * a-z, A-Z, 0-9, +, /, =, and optionally spaces, CR and LF characters. * * If [pos] and/or [len] are passed, only the substring starting at * [pos] (default: 0) with length [len] (default: rest of the string) * is encoded. * * The result is divided up into lines not longer than [linelength] * (without counting the line separator); default: do not divide lines. * If [linelength] is smaller than 4, no line division is performed. * If [linelength] is not divisible by 4, the produced lines are a * bit shorter than [linelength]. * * If [crlf] (default: false) the lines are ended by CRLF; otherwise * they are only ended by LF. * (You need the crlf option to produce correct MIME messages.) * * By default, the 63rd character of the alphabet is '+', and the * 64th character is '/'. By passing [plus] and [slash] you can * choose different characters. * *) val encode_tstring : ?pos:int -> ?len:int -> ?linelength:int -> ?crlf:bool -> ?plus:char -> ?slash:char -> tstring -> Bytes.t (** Same for tagged string inputs. The result are always bytes, though *) val encode_poly : ?pos:int -> ?len:int -> ?linelength:int -> ?crlf:bool -> ?plus:char -> ?slash:char -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t (** Polymorphic version *) val decode : ?pos:int -> ?len:int -> ?accept_spaces:bool -> ?plus:char -> ?slash:char -> string -> string (** Decodes the given string argument. * * If [pos] and/or [len] are passed, only the substring starting at * [pos] (default: 0) with length [len] (default: rest of the string) * is decoded. * * If [accept_spaces] (default: [false]) is set, the function ignores * white space contained in the string to decode (otherwise the * function fails if it finds white space). Furthermore, the character * '>' is considered as "space", too (so you don't have trouble with * mbox mailboxes that accidentally quote "From"). * * By default, the 63rd character of the alphabet is '+', and the * 64th character is '/'. By passing [plus] and [slash] you can * choose different characters. *) val decode_tstring : ?pos:int -> ?len:int -> ?accept_spaces:bool -> ?plus:char -> ?slash:char -> tstring -> Bytes.t (** Same for tagged string inputs. The result are always bytes, though *) val decode_poly : ?pos:int -> ?len:int -> ?accept_spaces:bool -> ?plus:char -> ?slash:char -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t (** Polymorphic version *) class encoding_pipe : ?linelength:int -> ?crlf:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipe (** This pipe encodes the data written into the pipe. * [linelength] and [crlf] work as in [encode]. *) class decoding_pipe : ?accept_spaces:bool -> ?plus:char -> ?slash:char -> unit -> Netchannels.pipe (** This pipe decodes the data written into the pipe. * [url_variant] and [accept_spaces] work as in [decode]. *) end (* *********************************************************************) (* Quoted printable encoding *) (* *********************************************************************) (* THREAD-SAFETY: * All QuotedPrintable functions are reentrant and thus thread-safe. *) module QuotedPrintable : sig (** This module implements the "Quoted Printable" encoding as * described in RFC 2045. * * This implementation assumes that the encoded string has a text MIME * type. On input both CR/LF and LF are accepted as end-of-line (eol) terminators, * but the output normalizes the eol delimiter as the [crlf] argument * specifies. Note that this implies that * - If [crlf], the output uses CR/LF as line separator as MIME prescribes * - the encoding is not invertible for binary data *) val encode : ?crlf:bool -> ?pos:int -> ?len:int -> string -> string (** Encodes the string and returns it. * * Since OcamlNet 0.98, soft line breaks are added to the output * to ensure that all output lines have a length <= 76 bytes. * * Note unsafe characters: * As recommended by RFC 2045, the characters [!#$\@[]^`|{}~] * and the double quotes * are additionally represented as hex tokens. * Furthermore, the letter 'F' is considered as unsafe if it * occurs at the beginning of the line, so the encoded text * never contains the word "From" at the beginning of a line. * * If [pos] and/or [len] are passed, only the substring starting at * [pos] (default: 0) with length [len] (default: rest of the string) * is encoded. * * If [crlf] is set (the default), the output text uses CR/LF as * line separator. Otherwise only LF is used. *) val encode_tstring : ?crlf:bool -> ?pos:int -> ?len:int -> tstring -> Bytes.t (** Same for tagged string inputs. The result are always bytes, though *) val encode_poly : ?crlf:bool -> ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t (** Polymorphic version *) val decode : ?pos:int -> ?len:int -> string -> string (** Decodes the string and returns it. * * Most format errors cause an [Invalid_argument] exception. * * If [pos] and/or [len] are passed, only the substring starting at * [pos] (default: 0) with length [len] (default: rest of the string) * is decoded. *) val decode_tstring : ?pos:int -> ?len:int -> tstring -> Bytes.t (** Same for tagged string inputs. The result are always bytes, though *) val decode_poly : ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t (** Polymorphic version *) class encoding_pipe : ?crlf:bool -> unit -> Netchannels.pipe (** This pipe encodes the data written into the pipe. *) class decoding_pipe : unit -> Netchannels.pipe (** This pipe decodes the data written into the pipe. *) end (* *********************************************************************) (* Q encoding *) (* *********************************************************************) (* See RFC 2047. * The functions behave similar to those of QuotedPrintable. *) (* THREAD-SAFETY: * All Q functions are reentrant and thus thread-safe. *) module Q : sig (** The "Q" encoding as described by RFC 2047. *) val encode : ?pos:int -> ?len:int -> string -> string (** Note: * All characters except alphanumeric characters are protected by * hex tokens. * In particular, spaces are represented as "=20", not as "_". *) val encode_tstring : ?pos:int -> ?len:int -> tstring -> Bytes.t (** Same for tagged string inputs. The result are always bytes, though *) val encode_poly : ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t (** Polymorphic version *) val decode : ?pos:int -> ?len:int -> string -> string (** Q-decode a string *) val decode_tstring : ?pos:int -> ?len:int -> tstring -> Bytes.t (** Same for tagged string inputs. The result are always bytes, though *) val decode_poly : ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> Bytes.t (** Polymorphic version *) end (* *********************************************************************) (* B encoding *) (* *********************************************************************) (* The B encoding of RFC 2047 is the same as Base64. *) (* *********************************************************************) (* URL-encoding *) (* *********************************************************************) (* THREAD-SAFETY: * The Url functions are thread-safe. *) module Url : sig (** Encoding/Decoding within URLs: * * The following two functions perform the '%'-substitution for * characters that may otherwise be interpreted as metacharacters. * * According to: RFC 1738, RFC 1630 * * Option [plus]: This option has been added because there are some * implementations that do not map ' ' to '+', for example Javascript's * [escape] function. The default is [true] because this is the RFC- * compliant definition. *) (** There are no tstring and polymorphic versions of the encode and decode functions, as URLs are comparatively short, and it is considered as acceptable for the user to convert types as needed, even if strings need to be copied for that. *) val decode : ?plus:bool -> ?pos:int -> ?len:int -> string -> string (** Option [plus]: Whether '+' is converted to space. The default * is true. If false, '+' is returned as it is. * * The optional arguments [pos] and [len] may restrict the string * to process to this substring. *) val encode : ?plus:bool -> string -> string (** Option [plus]: Whether spaces are converted to '+'. The default * is true. If false, spaces are converted to "%20", and * only %xx sequences are produced. *) (** URL-encoded parameters: * * The following two functions create and analyze URL-encoded parameters. * Format: [name1=val1&name2=val2&...] *) val mk_url_encoded_parameters : (string * string) list -> string (** The argument is a list of (name,value) pairs. The result is the * single URL-encoded parameter string. *) val dest_url_encoded_parameters : string -> (string * string) list (** The argument is the URL-encoded parameter string. The result is * the corresponding list of (name,value) pairs. * Note: Whitespace within the parameter string is ignored. * If there is a format error, the function fails. *) end (* *********************************************************************) (* HTMLization *) (* *********************************************************************) (* THREAD-SAFETY: * The Html functions are thread-safe. *) module Html : sig (** Encodes characters that need protection by converting them to * entity references. E.g. ["<"] is converted to ["<"]. * As the entities may be named, there is a dependency on the character * set. *) (* OLD ENCODE/DECODE FUNCTIONS: *) (** Legacy functions: *) val encode_from_latin1 : string -> string (* Encodes the characters 0-8, 11-12, 14-31, '<', '>', '"', '&', * 127-255. If the characters have a name, a named entity is * preferred over a numeric entity. *) val decode_to_latin1 : string -> string (* Decodes the string. Unknown named entities are left as they * are (i.e. decode_to_latin1 "&nonsense;" = "&nonsense;"). * The same applies to numeric entities greater than 255. *) (* NEW ENCODE/DECODE FUNCTIONS: *) (** These functions have a more general interface and should be preferred * in new programs. *) val unsafe_chars_html4 : string (** The string contains '<', '>', '"', '&' and the control characters * 0-8, 11-12, 14-31, 127. *) val encode : in_enc:Netconversion.encoding -> ?out_enc:Netconversion.encoding -> (* default: `Enc_usascii *) ?prefer_name:bool -> (* default: true *) ?unsafe_chars:string -> (* default: unsafe_chars_html4 *) unit -> string -> string (** The input string that is encoded as [in_enc] is recoded to * [out_enc], and the following characters are encoded as HTML * entity ([&name;] or [&#num;]): * - The ASCII characters contained in [unsafe_chars] * - The characters that cannot be represented in [out_enc]. By * default ([out_enc=`Enc_usascii]), only ASCII characters can be * represented, and thus all code points >= 128 are encoded as * HTML entities. If you pass [out_enc=`Enc_utf8], all characters * can be represented. * * For example, the string ["(ad)"] is encoded as * ["(a<b) & (c>d)"]. * * It is required that [out_enc] is an ASCII-compatible encoding. * * The option [prefer_name] selects whether named entities (e.g. [<]) * or numeric entities (e.g. [<]) are prefered. * * The efficiency of the function can be improved when the same encoding * is applied to several strings. Create a specialized encoding function * by passing all arguments up to the unit argument, and apply this * function several times. For example: * {[ * let my_enc = encode ~in_enc:`Enc_utf8 () in * let s1' = my_enc s1 in * let s2' = my_enc s2 in ... * ]} *) val encode_tstring : in_enc:Netconversion.encoding -> out_kind:'s Netstring_tstring.tstring_kind -> ?out_enc:Netconversion.encoding -> ?prefer_name:bool -> ?unsafe_chars:string -> unit -> tstring -> 's (** This version takes a tstring argument, and returns the string type chosen by the [out_kind] arg. *) val encode_poly : in_enc:Netconversion.encoding -> in_ops:'s Netstring_tstring.tstring_ops -> out_kind:'t Netstring_tstring.tstring_kind -> ?out_enc:Netconversion.encoding -> ?prefer_name:bool -> ?unsafe_chars:string -> unit -> 's -> 't (** Fully polymorphic version *) type entity_set = [ `Html | `Xml | `Empty ];; val decode : in_enc:Netconversion.encoding -> out_enc:Netconversion.encoding -> ?lookup:(string -> string) -> (* default: see below *) ?subst:(int -> string) -> (* default: see below *) ?entity_base:entity_set -> (* default: `Html *) unit -> string -> string (** The input string is recoded from [in_enc] to [out_enc], and HTML * entities ([&name;] or [&#num;]) are resolved. The input encoding * [in_enc] must be ASCII-compatible. * * By default, the function knows all entities defined for HTML 4 (this * can be changed using [entity_base], see below). If other * entities occur, the function [lookup] is called and the name of * the entity is passed as input string to the function. It is * expected that [lookup] returns the value of the entity, and that this * value is already encoded as [out_enc]. * By default, [lookup] raises a [Failure] exception. * * If a character cannot be represented in the output encoding, * the function [subst] is called. [subst] must return a substitute * string for the character. * By default, [subst] raises a [Failure] exception. * * The option [entity_base] determines which set of entities are * considered as the known entities that can be decoded without * help by the [lookup] function: [`Html] selects all entities defined * for HTML 4, [`Xml] selects only [<], [>], [&], ["], * and ['], * and [`Empty] selects the empty set (i.e. [lookup] is always called). *) val decode_tstring : in_enc:Netconversion.encoding -> out_kind:'s Netstring_tstring.tstring_kind -> out_enc:Netconversion.encoding -> ?lookup:(string -> string) -> (* default: see below *) ?subst:(int -> string) -> (* default: see below *) ?entity_base:entity_set -> (* default: `Html *) unit -> tstring -> 's (** This version takes a tstring argument, and returns the string type chosen by the [out_kind] arg. *) val decode_poly : in_enc:Netconversion.encoding -> in_ops:'s Netstring_tstring.tstring_ops -> out_kind:'t Netstring_tstring.tstring_kind -> out_enc:Netconversion.encoding -> ?lookup:(string -> string) -> (* default: see below *) ?subst:(int -> string) -> (* default: see below *) ?entity_base:entity_set -> (* default: `Html *) unit -> 's -> 't (** Fully polymorphic version *) end (* TODO: module with hex routines *) val to_hex : ?lc:bool -> string -> string ocamlnet-4.1.2/src/netstring/netglob.mli0000644000175000017500000005131712731530350016713 0ustar gerdgerd(* $Id$ *) (** Globbing *) (** Globbing resolves shell wildcards like "*" and "?". For example, {[ let files = Netglob.glob (`String "*.cm[iox]") ]} would return all files matching this pattern (e.g. module.cmi, module.cmo). The main user function is {!Netglob.glob}. Globbing accesses the local filesystem by default, but one can also run the globbing algorithm on any other filesystem, provided the access primitives of {!Netglob.glob_fsys} are available. *) (** {2 Types and exceptions} *) type glob_expr = glob_expr_atom list and glob_expr_atom = [ `Literal of string | `Star | `Qmark | `Bracket of (bool * glob_set) | `Brace of glob_expr list | `Tilde of string ] (** Atoms: - [`Literal s]: Matches the string literally. The string must not be empty. The backslash is not an escape character, but matches the backslash character. - [`Star]: The "*" operator - [`Qmark]: The "?" operator - [`Bracket(negated,set)]: The [[...]] operator. The [set] argument describes the characters that are matched. The [negated] argument is true when the expression is negated (i.e. [[^...]]). - [`Brace l]: The [{e1,e2,...}] operator - [`Tilde t]: The [~username] operator. If [t=""] the current user is meant. The [`Tilde] atom may only occur at the beginning of the list. The [`Tilde] atom always matches a directory, and must be followed by a literal slash (if anything follows). Compatibility: Conforms to POSIX with extensions (braces). Shells often implement brace expressions in a slightly different way (braces are parsed and expanded in a separate step before the other pattern constructors are handled). The cases where this leads to different results are quite exotic (e.g. ["{~g,~h}1"] would mean ["~g1 ~h1"], but this implementation rejects the pattern). *) and glob_set = < set : (int * int) list > (** A set of code points is given as a list of ranges [(from,to)], with [from <= to]. It is allowed that ranges overlap. *) type valid_glob_expr (** A validated [glob_expr] *) (** Access to the user database *) class type user_info = object method path_encoding : Netconversion.encoding option (** Paths of filesystems may be encoded *) method home_directory : string -> string (** Returns the home directory of the passed user, or the home directory of the current user for the empty string. Raises [Not_found] if the lookup fails. *) end (** Filesystem primitives. This is intentionally not the same as {!Netfs.stream_fs} because only a few access functions are needed here, and because the functions here should also be capable of accessing relative paths (not starting with /). It is possible to turn a {!Netfs.stream_fs} into {!Netglob.glob_fs} by calling {!Netglob.of_stream_fs}. *) class type glob_fsys = object method path_encoding : Netconversion.encoding option (** Paths of filesystems may be encoded *) method read_dir : string -> string list (** Returns the file names contained in the directory, without path. The names "." and ".." should be returned. It is acceptable to return the empty list for an unreadable directory. *) method file_is_dir : string -> bool (** Whether the file name is valid and a directory, or a symlink to a directory. *) method file_exists : string -> bool (** Whether the file name is valid and refers to an existing file, or to a symlink pointing to an existing file. *) end type glob_mode = [ `Existing_paths | `All_paths | `All_words ] (** Modes: - [`Existing_paths]: Only paths are returned that really exist - [`All_paths]: Generated paths not including [*], [?] and bracket expressions are returned even if they do not exist. For example, globbing for ["fictive{1,2,3}"] would return [["ficitve1";"fictive2";"fictive3"]] independent of whether these files exist. - [`All_words]: Patterns that cannot be resolved are returned as-is (like the shell does) *) type pattern = [ `String of string | `Expr of valid_glob_expr ] (** Input for {!Netglob.glob} *) exception Bad_glob_expr of string (** An syntax error in the glob expression; the argument is the bad expression *) exception Unsupported_expr of string (** The notations [:class:], [.symbol.], [=eqclass=] inside [...] are * not supported by this implementation. If they are found, this exception * will be raised, and the argument is the whole glob expression *) (** {2 Parsing and printing} *) val parse_glob_expr : ?encoding:Netconversion.encoding -> ?enable_star:bool -> (* Recognize "*" *) ?enable_qmark:bool -> (* Recognize "?" *) ?enable_brackets:bool -> (* Recognize "[set]" *) ?enable_braces:bool -> (* Recognize "{alt,...}" *) ?enable_tilde:bool -> (* recognize ~ *) ?enable_escape:bool -> (* Recognize backslash as escape char *) string -> valid_glob_expr (** Parses the glob expression. By default, all syntax features are enabled. * May raise [Bad_glob_expr] or [Unsupported_expr]. * * The glob expressions are POSIX-compliant with the extension of * brace expressions, and tildes, and the omission of internationalized * bracket expressions: * - [*]: Matches a sequence of zero or more arbitrary characters * - [?]: Matches one arbitrary character * - [[abc]]: Matches one of the mentioned characters * - [[a-z]]: Matches one of the characters of the range. This is here * only permitted when the range falls into the ASCII set. (Otherwise * the interpretation would be dependent on the encoding.) Note that * the ASCII restriction does not comply to POSIX. * - [[!expr]] or [[^expr]]: Negates the bracket expression * - [{expr,expr,...}]: Generates a string for each of the alternatives. * A brace expression is even recognized if there is no comma, or even * no contents (i.e. ["{expr}"] and ["{}"]). The elements of brace expressions * may be again glob expressions; nested brace expressions are allowed. * - [~username]: Generates the home directory of this user * - [~]: Generates the home directory of the current user * - If enabled, the backslash character is the escape character. Within * bracket expressions, the backslash character never escapes. * - Not supported: Collating symbols [[.a.]], equivalence classes * [[=a=]], and character classes [[:name:]]. If they are found, the * exception [Unsupported_expr] will be raised. * * Glob expressions have a character [encoding]. This defaults to * [`Enc_iso88591]. Encodings must be ASCII-compatible. *) val validate_glob_expr : Netconversion.encoding -> glob_expr -> valid_glob_expr (** Checks whether the passed expression is syntactically valid. If so, a validated expression is returned. Otherwise, this function fails. *) val recover_glob_expr : valid_glob_expr -> glob_expr (** Returns the explicit representation *) val encoding_of_glob_expr : valid_glob_expr -> Netconversion.encoding (** Returns the encoding *) val literal_glob_expr : Netconversion.encoding -> string -> valid_glob_expr (** Returns an expression that matches literally the passed string *) val print_glob_expr : ?escape_in_literals:bool -> valid_glob_expr -> string (** Prints the glob expression as string. Meta characters are * escaped by a backslash when possible. Meta characters are: * ["*"], ["?"], ["["], ["]"], ["{"], ["}"], [","], ["~"] and ["\\"] * * - [escape_in_literals]: Whether meta characters in [`Literal] * subexpressions are escaped. This is true by default. *) (** {2 Operations on [valid_glob_expr]} *) val expand_glob_expr : ?user_info:user_info -> ?expand_brace:bool -> ?expand_tilde:bool -> valid_glob_expr -> valid_glob_expr list (** Resolve generative sub expressions by expanding them. The returned * list of glob expr no longer contains the expanded constructions. * * - [expand_brace]: Expands [`Brace] subexpressions. * - [expand_tilde]: Expands [`Tilde] subexpressions. * - [user_info]: The subset of file system operations needed for tilde * expansion. Defaults to {!Netglob.local_user_info} (see below). * * Both [expand_*] options are enabled by default. *) val match_glob_expr : ?protect_period:bool -> (* Protect leading dots; default: true *) ?protect_slash:bool -> (* Protect slashes; default: true *) ?encoding:Netconversion.encoding -> valid_glob_expr -> string -> bool (** Matches the glob_expr against a string. * * The input must neither contain brace expressions nor tildes (i.e. call * [expand_glob_expr] first). The function fails if it encounters such an * expression. * * - [protect_period]: If true, a leading period cannot be not matched by * [*], [?], [[...]], but only by a literal [.]. A leading period is * a [.] at the beginning of the string to be matched against, or * if also [protect_slash] a [.] after a [/] * - [protect_slash]: If true, a slash cannot be matched by [*], [?], [[...]], * but only by a literal [/] * * Both options are enabled by default. * * - [encoding]: The encoding of the string argument. Defaults to the * encoding of the glob pattern. *) val split_glob_expr : valid_glob_expr -> valid_glob_expr list (** Splits the glob expression into filename components separated by * literal [/] characters. For example, for the glob expression * ["a*b/c/d?"], the list [["a*b"; "c"; "d?"]] is returned. * * If the first component begins with a slash, the slash is not removed * from the first returned list element, e.g. for ["/ab/c*"], the list * [[ "/ab"; "c*" ]] is computed. Use [check_rooted_glob_expr] to test this * case. * * Several adjacent slashes are handled like a single slash. E.g. * for ["a//b"], the list [["a"; "b"]] is returned. * * If the last component ends with a slash, it is not removed from the * returned list element, e.g. for ["a/b/"], the list [[ "a"; "b/" ]] is * returned. Use [check_directory_glob_expr] to test this case. * * The glob expression passed to this function must not contain brace * or tilde expressions. *) val check_rooted_glob_expr : valid_glob_expr -> valid_glob_expr option (** If the glob expression matches the root directory (i.e. the expression * begins with a literal [/]), the function returns [Some expr'], where * [expr'] matches the path relative to the root directory (i.e. the * expression without the [/] at the beginning). * * Otherwise, [None] is returned. * * Example: For ["/a/b*"], the expression ["a/b*"] is returned. * * Special case: for ["/"], the expression [""] (only matching the empty * string) is returned. * * The glob expression passed to this function must not contain brace * or tilde expressions. *) val check_directory_glob_expr : valid_glob_expr -> valid_glob_expr option (** If the last component of the glob expression matches only directories * because it ends with a literal [/] character, the value [Some expr'] is * returned where [expr'] matches the same path without the trailing [/]. * * Otherwise, [None] is returned. * * Example: For ["a/b*/"], the expression ["a/b*"] is returned. * * Special case: for ["/"], the expression [""] (only matching the empty * string) is returned. * * The glob expression passed to this function must not contain brace * or tilde expressions. *) (** {2 Globbing} *) val glob : ?encoding:Netconversion.encoding -> (* default: `Enc_iso88591 *) ?base_dir:string -> (* default: current directory *) ?protect_period:bool -> (* default: true *) ?fsys:glob_fsys -> (* default: access real file system *) ?user_info:user_info -> ?mode:glob_mode -> (* default: `Existing_paths *) pattern -> string list (** Forms a set of filenames as described below, and matches this set * against the pattern. The pattern can be given as a [`String s] * in which case [s] is parsed (with all features enabled, and * it is assumed it has the passed [encoding]). Alternatively, * an already parsed [`Expr e] can be given. (Note that [encoding] * is ignored in this case.) * * {b Slashes must be explicitly matched:} * "/" must literally occur in order to be a candidate for matching. * It is not matched by [*] or [?] or a bracket expression. * * {b Periods:} The leading period is protected if [protect_period]. * It must then also literally occur to be matched. * * {b Anchoring:} If the [glob_expr] begins with a literal "/", the set * of filenames is * anchored at the root directory; otherwise the set is anchored at * the current directory or, if [base_dir] is passed, at this directory. * (If [fsys] is passed, it is required to also set [base_dir].) * * Initially, the set contains all files of the anchor * directory (for the root directory, a "/" is prepended). * * After that, the set is extended by adding the paths of * subdirectories relative to the anchor directory. Note that the * constructed set is always infinite, because "." and ".." are not * handled specially, and are also regarded as "subdirectories". However, * after applying the matching criterion, the returned list is always * finite. * * Note that the anchor directory itself is not part of the generated * set. For example, for the expression "/*" the root directory "/" is * not returned. As an exception of this rule, for the glob expression * "/" the file "/" is returned. * * {b Braces:} Brace expressions are handled by expanding them first, even * before filename generation starts. * * {b Mode:} By default, only existing paths are returned * ([mode=`Existing_paths]). * If no files match, the empty list is returned (and not the pattern * as the shell does). By passing a different [mode], this can be changed: * - [`All_paths]: It is allowed that non-existing paths * are returned when the paths do not contain *, ?, or \[ * metacharacters after the brace expansion. Path expressions * with these metacharacters are still checked for existence. * - [`All_words]: When an expression does not refer to existing * paths, it is returned as such, leaving the metacharacters *, ?, \[ * unexpanded (i.e., what the Bourne shell does). Note that * either all metacharacters are resolved, or none, but not * a subset of them. * * {b Encodings:} Often, only the pattern has an encoding, but not * the filesystem (as in Unix). In this case, no conversion is attempted, * and the byte representation of the pattern is matched with the * byte representation of the filenames. Good luck. * * If the filesystem has an encoding, however, conversions may * be required, and this can cause problems. Usually, network filesystems * provide an encoding, and the Win32 local filesystem. (For Unix, * one can pass a custom [fsys] with encoding knowledge.) Conversion * problems can be avoided if (1) the encoding of the pattern is a superset * of the filename encoding. Also, (2) one should not use literals * in the pattern that cannot be represented in the filename encoding. * If (2) cannot be satisfied, ensure you have at least * [mode=`Existing_paths], i.e. the default mode (this removes results * from the returned list when a conversion problem occurs). * * The return value of [glob] is encoded in the encoding of the filesystem * if the filesystem provides an encoding. (If you want to check this * encoding, pass [fsys], e.g. as [local_fsys()], and call the * [path_encoding] method of [fsys].) *) (** {2 Remarks} *) (** {b Examples demonstrating the effect of encodings:} (Linux) {[ let fsys = local_fsys ~encoding:`Enc_utf8() let l = glob ~fsys (`String "\214*") ]} The byte 214 is O-umlaut in ISO-8859-1 (the default encoding for patterns). By passing an [fsys] argument we change the encoding for filenames to UTF-8. For example, if "\195\150ffentlich" was a file in the current directory, it would be found and returned in [l]. Conversions: For example, assume we have a file "\226\130\172uro" (EUR-uro in UTF-8). The glob {[ let fsys = local_fsys ~encoding:`Enc_utf8() let l = glob ~fsys (`String "*") ]} finds it although the euro sign cannot be represented in ISO-8859-1, the default pattern encoding. We run into a problem, however, if we want to generate the euro sign even if the file is not present, and the filesystem uses an encoding that does not include this sign: {[ let fsys = local_fsys ~encoding:`Enc_iso88591() let l = glob ~fsys ~encoding:`Enc_utf8 ~mode:`All_paths (`String "\226\130\172uro") ]} This raises an exception [Netconversion.Cannot_represent 8364]. *) (** {b Notes for Win32:} - Globbing only supports forward slashes, not backslashes as path separators - Globbing does neither recognize drive letters nor UNC paths as special cases. This may lead to subtle bugs. Glob expressions like "c:/file.*" may or may not work depending on the context. - The usually case-insensitive file system is not taken into account. (To be fixed.) *) (** {2 Default access objects} *) class local_user_info : unit -> user_info val local_user_info : unit -> user_info (** Get the home directory of a user from the local user database. *) class local_fsys : ?encoding:Netconversion.encoding -> unit -> glob_fsys val local_fsys : ?encoding:Netconversion.encoding -> unit -> glob_fsys (** Accesses the local filesystem *) class of_stream_fs : #Netfs.stream_fs -> glob_fsys val of_stream_fs : #Netfs.stream_fs -> glob_fsys (** Use an arbitrary network filesystem for globbing *) (** {2 Compatibility} This implementation is not fully compatible with the POSIX specs. The differences: - Missing support for character classes, equivalence classes and collating symbols. - Ranges in brackets are restricted to ASCII. - Unparseable patterns are indicated by exceptions. POSIX, however, requires that such patterns are taken literally. E.g. a pattern "\[" would match a left bracket in POSIX, but this module throws a syntax error. - If the slash character is protected, it is still allowed inside brackets. POSIX, however, requires that the pattern is scanned for slashes before brackets. For instance, the pattern "\[a/b*\]" is scanned as [ [`Literal "[a/b]"; `Star] ] following the POSIX rules while this implementation sees a bracket expression with "a", "b", "/" and "*" characters. - The "^" character negates the set if used at the beginning of bracket expressions. POSIX leaves this unspecified. - Brace expresions are an extension (although commonly implemented in shells). - The default globbing mode is [`Existing_paths] which is not defined by POSIX. Use [`All_paths] for getting POSIX behavior. Compared with popular shells, there are some subtle differences in how the various syntax elements (wildcards, braces, tildes) are parsed and processed. Shells do it in this order: - Parse and expand brace expressions - Parse and expand tildes - Split the paths at slashes into path components - Parse and expand wildcards For example, after expanding braces it is possible to see totally new tilde or wildcard expressions, e.g. ["~user{1,2}/file"] would be legal. This implementation here does not support this - we first parse the expression, and then interpret it. However, users interested in a higher degree of compatibility can call the {!Netglob} parsing, processing and printing functions in the required order, and emulate the shell behavior. For example, {[ let alt_glob pat = let g1 = parse_glob_expr ~enable_star:false ~enable_qmark:false ~enable_brackets:false ~enable_tilde:false (* only braces remain enabled *) pat in let g2_list = expand_glob_expr g1 in let pat2_list = List.map (print_glob_expr ~escape_in_literals:false) g2_list in let g3_list = List.map (fun pat2 -> parse_glob_expr ~enable_braces:false pat2) pat2_list in List.flatten (List.map (fun g3 -> glob (`Expr g3)) g3_list) ]} would parse and expand brace expressions in a separate step before running [glob] on the remaining syntactic elements. *) ocamlnet-4.1.2/src/netstring/netmech_crammd5_sasl.ml0000644000175000017500000001563012731530350021163 0ustar gerdgerd(* $Id$ *) (* TODO: add saslprep to at least the server, so far we have it *) (* Unit tests: tests/netstring/bench/test_netmech.ml *) let next_challenge = ref None (* testing *) let override_challenge s = next_challenge := Some s module CRAM_MD5 : Netsys_sasl_types.SASL_MECHANISM = struct let mechanism_name = "CRAM-MD5" let client_first = `No let server_sends_final_data = false let supports_authz = false let available() = true type credentials = (string * string * (string * string) list) list let init_credentials l = (l:credentials) type server_session = { sstate : Netsys_sasl_types.server_state; schallenge : string; suser : string option; lookup : string -> string -> credentials option; } let server_state ss = ss.sstate let no_mutual = "The CRAM-MD5 mechanism does not support mutual authentication" let create_server_session ~lookup ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_crammd5_sasl.create_server_session:" [ "mutual"; "secure" ] params in let req_mutual = try List.assoc "mutual" params = "true" with Not_found -> false in (* Ignore "secure" *) let r = Bytes.create 16 in Netsys_rng.fill_random r; let c1 = Netencoding.to_hex ~lc:true (Bytes.to_string r) in let c = match !next_challenge with | None -> c1 | Some c -> c in next_challenge := None; { sstate = if req_mutual then `Auth_error no_mutual else `Emit; schallenge = "<" ^ c ^ ">"; suser = None; lookup } let server_configure_channel_binding ss cb_list = failwith "Netmach_crammd5_sasl.server_configure_channel_binding: \ not supported" let compute_response user password challenge = let k = if String.length password < 64 then password (* padding is done by hmac anyway *) else Digest.string password in let r = Netauth.hmac ~h:Digest.string (* MD5, actually *) ~b:64 ~l:16 ~k ~message:challenge in let r_hex = Netencoding.to_hex ~lc:true r in user ^ " " ^ r_hex let verify_utf8 s = try Netconversion.verify `Enc_utf8 s with _ -> failwith "UTF-8 mismatch" let server_process_response ss msg = try if ss.sstate <> `Wait then failwith "protocol error"; (* let n = String.length msg in *) let k1 = String.rindex msg ' ' in let user = String.sub msg 0 k1 in (* let resp = String.sub msg (k1+1) (n-k1-1) in *) let expected_password = match ss.lookup user "" with | None -> failwith "unknown user" | Some creds -> Netsys_sasl_util.extract_password creds in let expected_msg = compute_response user expected_password ss.schallenge in if msg <> expected_msg then failwith "bad password"; verify_utf8 user; verify_utf8 expected_password; { ss with sstate = `OK; suser = Some user; } with | Failure msg -> { ss with sstate = `Auth_error msg } let server_process_response_restart ss msg set_stale = failwith "Netmech_crammd5_sasl.server_process_response_restart: \ not available" let server_emit_challenge ss = if ss.sstate <> `Emit then failwith "Netmech_crammd5_sasl.server_emit_challenge: bad state"; let data = ss.schallenge in ( { ss with sstate = `Wait }, data ) let server_channel_binding ss = `None let server_stash_session ss = "server,t=CRAM-MD5;" ^ Marshal.to_string (ss.sstate, ss.schallenge, ss.suser) [] let ss_re = Netstring_str.regexp "server,t=CRAM-MD5;" let server_resume_session ~lookup s = match Netstring_str.string_match ss_re s 0 with | None -> failwith "Netmech_crammd5_sasl.server_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let (state,chal,user) = Marshal.from_string data 0 in { sstate = state; suser = user; schallenge = chal; lookup } let server_session_id ss = None let server_prop ss key = raise Not_found let server_gssapi_props ss = raise Not_found let server_user_name ss = match ss.suser with | None -> raise Not_found | Some name -> name let server_authz_name ss = "" type client_session = { cstate : Netsys_sasl_types.client_state; cresp : string; cuser : string; cauthz : string; cpasswd : string; } let create_client_session ~user ~authz ~creds ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_crammd5_sasl.create_client_session:" [ "mutual"; "secure" ] params in let req_mutual = try List.assoc "mutual" params = "true" with Not_found -> false in (* Ignore "secure" *) let pw = try Netsys_sasl_util.extract_password creds with Not_found -> failwith "Netmech_crammd5_sasl.create_client_session: no password \ found in credentials" in { cstate = if req_mutual then `Auth_error no_mutual else `Wait; cresp = ""; cuser = user; cauthz = authz; cpasswd = pw; } let client_configure_channel_binding cs cb = if cb <> `None then failwith "Netmech_crammd5_sasl.client_configure_channel_binding: \ not supported" else cs let client_state cs = cs.cstate let client_channel_binding cs = `None let client_restart cs = if cs.cstate <> `OK then failwith "Netmech_crammd5_sasl.client_restart: unfinished auth"; { cs with cstate = `Wait } let client_process_challenge cs msg = if cs.cstate <> `Wait then { cs with cstate = `Auth_error "protocol error" } else { cs with cresp = compute_response cs.cuser cs.cpasswd msg; cstate = `Emit; } let client_emit_response cs = if cs.cstate <> `Emit then failwith "Netmech_crammd5_sasl.client_emit_response: bad state"; ( { cs with cstate = `OK }, cs.cresp ) let client_stash_session cs = "client,t=CRAM-MD5;" ^ Marshal.to_string cs [] let cs_re = Netstring_str.regexp "client,t=CRAM-MD5;" let client_resume_session s = match Netstring_str.string_match cs_re s 0 with | None -> failwith "Netmech_crammd5_sasl.client_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let cs = Marshal.from_string data 0 in (cs : client_session) let client_session_id cs = None let client_prop cs key = raise Not_found let client_gssapi_props cs = raise Not_found let client_user_name cs = cs.cuser let client_authz_name cs = "" end ocamlnet-4.1.2/src/netstring/netmech_scram.mli0000644000175000017500000004067412731530350020075 0ustar gerdgerd(* $Id$ *) (** SCRAM mechanism for authentication (RFC 5802) *) (** This implements SCRAM for SASL and GSSAPI. {b This module needs the SHA-1 hash function. In order to use it, initialize crypto support, e.g. by including the [nettls-gnutls] packages and calling {!Nettls_gnutls.init}.} As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of SCRAM should pass user names and passwords through {!Netsaslprep.saslprep}. *) type ptype = [ `GSSAPI | `SASL ] (** Profile types: - [`GSSAPI]: as defined in RFC 5802, the gs2-header is omitted - [`SASL]: as defined in RFC 5802 *) type profile = { ptype : ptype; hash_function : Netsys_digests.iana_hash_fn; (** Which hash function *) return_unknown_user : bool; (** Whether servers exhibit the fact that the user is unknown *) iteration_count_limit : int; (** Largest supported iteration number *) } (** Profile *) type cb = Netsys_sasl_types.cb (** Using the same channel binding type as for SASL *) type server_error = [ `Invalid_encoding | `Extensions_not_supported | `Invalid_proof | `Channel_bindings_dont_match | `Server_does_support_channel_binding | `Channel_binding_not_supported | `Unsupported_channel_binding_type | `Unknown_user | `Invalid_username_encoding | `No_resources | `Other_error | `Extension of string ] (** Error codes of this protocol *) type client_session (** Session context for clients *) type server_session (** Session context for servers *) (** Client exceptions: The exceptions are returned by [client_error_flag], but never raised. *) exception Invalid_encoding of string * string (** Returned by clients when something cannot be decoded. First string is an error message, the second string the raw message that cannot be decoded *) exception Invalid_username_encoding of string * string (** Returned by clients when the username does not match the requirements. Arguments as for [Invalid_encoding]. *) exception Extensions_not_supported of string * string (** Returned by clients when the server enables an unsupported extension. Arguments as for [Invalid_encoding]. *) exception Protocol_error of string (** Returned by clients when the server violates the protocol. The argument is a message. *) exception Invalid_server_signature (** Returned by clients when the signature sent by the server is invalid (i.e. the server does not know the client password) *) exception Server_error of server_error (** Returned by clients when the server sent an error code *) val error_of_exn : exn -> string (** Converts one of the above exceptions to a human-readable string *) val profile : ?return_unknown_user:bool -> ?iteration_count_limit:int -> ptype -> Netsys_digests.iana_hash_fn -> profile (** Creates a profile *) val string_of_server_error : server_error -> string val server_error_of_string : string -> server_error (** Conversion *) val mechanism_name : profile -> string (** The official name of the mechanism *) (** {2 Clients} *) (** The idea is to create a client session [s] first. The functions [client_emit_flag] and [client_recv_flag] indicate now whether the client needs to emit a new message, or whether it needs to receive a message, respectively. Emission is done by [client_emit_message], reception by [client_recv_message]. If everything goes well, the protocol state advances, and finally [client_finish_flag] is true. This indicates that the client is authenticated and that the server knows the client's password. If an error occurs, an exception is raised (see above for possibilities), and [client_error_flag] signals [true]. *) val create_client_session : ?nonce: string -> profile -> string -> string -> client_session (** [create_client_session p username password]: Creates a new client session for profile [p] so that the client authenticates as user [username], and proves its identity with the given [password]. *) val create_client_session2 : ?nonce:string -> profile -> string -> string -> string -> client_session (** [create_client_session p username authzname password]: Like [create_client_session], but also sets the authorization name (only processed for the SASL profile). *) val client_configure_channel_binding : client_session -> cb -> client_session (** Sets whether to request channel binding. *) val client_restart : client_session -> string -> client_session (** Restart a client session (draft-ietf-httpauth-scram-auth-15). The string is the sr attribute. *) val client_restart_stale : client_session -> string -> client_session (** Restart a client session after the server indicated that the session is stale. The string arg is the new "sr" attribute (draft-ietf-httpauth-scram-auth-15). *) val client_emit_flag : client_session -> bool (** Whether [client_emit_message] can now be called *) val client_recv_flag : client_session -> bool (** Whether [client_recv_message] can now be called *) val client_finish_flag : client_session -> bool (** Whether the client is authenticated and the server verified *) val client_semifinish_flag : client_session -> bool (** Whether the client is authentication *) val client_error_flag : client_session -> exn option (** Whether an error occurred, and the protocol cannot advance anymore *) val client_channel_binding : client_session -> cb (** Returns the channel binding *) val client_emit_message : client_session -> client_session * string (** Emits the next message to be sent to the server *) val client_emit_message_kv : client_session -> client_session * string option * (string * string) list (** Emits the next message to be sent to the server. The message is not encoded as a single string, but as [(gs2_opt, kv)] where [gs2_opt] is the optional GS2 header (the production [gs2-header] from the RFC), and [kv] contains the parameters as key/value pairs. *) val client_recv_message : client_session -> string -> client_session (** Receives the next message from the server *) val client_protocol_key : client_session -> string option (** The 128-bit protocol key for encrypting messages. This is available as soon as the second client message is emitted. *) val client_user_name : client_session -> string (** The user name *) val client_authz_name : client_session -> string (** The authorization name *) val client_password : client_session -> string (** The password *) val client_export : client_session -> string val client_import : string -> client_session (** Exports a client session as string, and imports the string again. The export format is just a marshalled Ocaml value. *) val client_prop : client_session -> string -> string (** Returns a property of the client (or Not_found): - "snonce": server nonce - "cnonce": client nonce - "salt": password salt - "i": iteration count - "client_key": this key is derived from the salted password but cannot be derived from the stored key. Its presence proves that the password was entered. It is ideal for encrypting data with a per-user key. The client key is known both to the client and to the server (after running the protocol). - "protocol_key": another key defined in RFC-5801 known by both sides. The protocol key is additionally also dependent on the nonces. - "error" *) (** {2 Servers} *) (** The idea is to create a server session [s] first. The functions [server_emit_flag] and [server_recv_flag] indicate now whether the server needs to emit a new message, or whether it needs to receive a message, respectively. Emission is done by [server_emit_message], reception by [server_recv_message]. If everything goes well, the protocol state advances, and finally [server_finish_flag] is true. This indicates that the client could be authenticated. If an error occurs, {b no} exception is raised, and the protocol advances nevertheless, and finally the server sends an error token to the client. After this, [server_error_flag] returns true. *) type credentials = [ `Salted_password of string * string * int | `Stored_creds of string * string * string * int ] (** Two forms of providing credentials: - [`Salted_password(spw,salt,iteration_count)]: get the salted password with [spw = salt_password h password salt iteration_count] - [`Stored(stkey, srvkey, salt, iteration_count)]: get the pair (stkey, srvkey) with [stored_key h password salt iteration_count] *) val create_server_session : ?nonce:string -> profile -> (string -> credentials) -> server_session (** [create_server_session p auth]: Creates a new server session with profile [p] and authenticator function [auth]. The function is [auth] is called when the credentials of the client have been received to check whether the client can be authenticated. It is called as {[ let credentials = auth username ]} where [username] is the user name. The function can now raise [Not_found] if the user is unknown, or it can return the credentials. Note that the cleartext password needs not to be known. The credentials contain a salt and an iteration count: [salt] is a random string, and [iteration_count] a security parameter that should be at least 4096. Whereas [salt] should be different for each user, the [iteration_count] can be chosen as a constant (e.g. 4096). Now [salted_password] can be computed from the cleartext password and these two extra parameters. See [salt_password] below. *) val create_server_session2 : ?nonce:string -> profile -> (string -> string -> credentials) -> server_session (** Same as [create_server_session], but the authentication callback gets two arguments: {[ let credentials = auth username authzname ]} where [authzname] is the passed authorization name (or "" if na). *) val create_salt : unit -> string (** Creates a random string suited as salt *) val salt_password : Netsys_digests.iana_hash_fn -> string -> string -> int -> string (** [let salted_password = salt_password h password salt iteration_count] Use this now as credentials [`Salted_password(salted_password,salt,iteration_count)]. As we do not implement [SASLprep] only passwords consisting of US-ASCII characters are accepted ([Invalid_encoding] otherwise). *) val stored_key : Netsys_digests.iana_hash_fn -> string -> string -> int -> string * string (** [let stkey,srvkey = stored_key h password salt iteration_count] Use this now as credentials [`Stored_creds(stkey,srvkey,salt,iteration_count)]. *) val server_emit_flag : server_session -> bool (** Whether [server_emit_message] can now be called *) val server_recv_flag : server_session -> bool (** Whether [server_recv_message] can now be called *) val server_finish_flag : server_session -> bool (** Whether the client is authenticated *) val server_error_flag : server_session -> bool (** Whether an error occurred, and the protocol cannot advance anymore *) val server_emit_message : server_session -> server_session * string (** Emits the next message to be sent to the client *) val server_emit_message_kv : server_session -> server_session * (string * string) list (** Emits the next message to be sent to the client. The message is returned as a list of key/value pairs. *) val server_recv_message : server_session -> string -> server_session (** Receives the next message from the client *) val server_protocol_key : server_session -> string option (** The 128-bit protocol key for encrypting messages. This is available as soon as the second client message has been received. *) val server_channel_binding : server_session -> cb (** Returns the channel binding requirement. It is up to the application to enforce the binding. This information is available as soon as the second client message has been received *) val server_user_name : server_session -> string option (** The user name as transmitted from the client. This is returned here even before the authentication is completed! *) val server_authz_name : server_session -> string option (** The authorization name as transmitted from the client. This is returned here even before the authentication is completed! *) val server_export : server_session -> string val server_import : string -> server_session val server_import_any : string -> (string -> credentials) -> server_session val server_import_any2 : string -> (string -> string -> credentials) -> server_session (** Exports a server session as string, and imports the string again. [server_import] can only import established sessions. [server_import_any] can also import unfinished sessions, but one needs to pass the authentication function as for [server_create_session]. [server_import_any2] uses the modified auth function as in [server_create_session2]. *) val server_prop : server_session -> string -> string (** Returns a property of the server (or Not_found) - see also [client_prop] above: - "snonce" - "cnonce" - "salt" - "i" (iteration_count) - "client_key" - "protocol_key" *) (** {2 Confidentiality} *) type specific_keys = { kc : string; ke : string; ki : string } (** The specific keys to use *) (** This module implements AES in Ciphertext Stealing mode (see RFC 3962) *) module AES_CTS : sig val c : int val m : int val encrypt : string -> string -> string val encrypt_mstrings : string -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list val decrypt : string -> string -> string val decrypt_mstrings : string -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list val tests : (string * string * string) list val run_tests : unit -> bool val run_mtests : unit -> bool end (** This is the cryptosystem as defined in RFC 3961, so far needed here. This uses [AES_CTS] as cipher, and SHA1-96 for signing. *) module Cryptosystem : sig exception Integrity_error val derive_keys : string -> int -> specific_keys (** [derive_keys protocol_key usage]: Returns the specific keys for this [protocol_key] and this [usage] numbers. See RFC 4121 for applicable usage numbers *) val encrypt_and_sign : specific_keys -> string -> string (** Encrypts the plaintext message and adds a signature to the ciphertext. Returns [ciphertext_with_signature]. *) val encrypt_and_sign_mstrings : specific_keys -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list (** Same, but with data representation as [mstring list] *) val decrypt_and_verify : specific_keys -> string -> string (** Decrypts the ciphertext and verifies the attached signature. Returns the restored plaintext. For very short plaintexts (< 16 bytes) there will be some padding at the end ("residue"), as returned as [ec] above. We ignore this problem generally, because GSS-API adds a 16-byte header to the plaintext anyway, so these short messages do not occur. If the signature is not valid, the exception [Integrity_error] is raised. *) val decrypt_and_verify_mstrings : specific_keys -> Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list (** Same, but with data representation as [mstring list] *) val get_ec : specific_keys -> int -> int (** [let ec = get_ec e_keys n]: Returns the required value for the "extra count" field of RFC 4121 if the plaintext message has size [n]. Here, [n] is the size of the payload message plus the token header of 16 bytes, i.e. the function is always called with [n >= 16]. Here, the returned [ec] value is always 0. *) val get_mic : specific_keys -> string -> string (** Returns a message integrity code *) val get_mic_mstrings : specific_keys -> Netxdr_mstring.mstring list -> string (** Same, but with data representation as [mstring list] *) end module Debug : sig val enable : bool ref (** Enable debugging of this module *) end ocamlnet-4.1.2/src/netstring/netmech_scram_http.mli0000644000175000017500000000077012731530350021125 0ustar gerdgerd(** SCRAM for HTTP (prerelease) *) (** Implements SCRAM-SHA-256 and SCRAM-SHA-1 as described in https://tools.ietf.org/html/draft-ietf-httpauth-scram-auth-15 Restarts are not yet covered. As long as the RFC isn't released yet, this should be considered as experimental work. *) module type PROFILE = sig val mutual : bool val hash_function : Netsys_digests.iana_hash_fn val test_nonce : string option end module Make_SCRAM(P:PROFILE) : Nethttp.HTTP_CLIENT_MECHANISM ocamlnet-4.1.2/src/netstring/netmech_digest.ml0000644000175000017500000005264112731530350020073 0ustar gerdgerd(* $Id$ *) (* Unit tests: tests/netstring/bench/test_netmech.ml (SASL only) *) (* The core of digest authentication *) (* What is implemented in the client (when H is the name of the hash function): - HTTP: RFC-2069 mode - HTTP: RFC-2617 mode: qop="auth", both H and H-sess - HTTP: charset is iso-8859-1 - HTTP: user name hashing - SASL mode: qop="auth", H-sess, charset=utf-8 What is implemented in the server: - HTTP: NO RFC-2069 mode - HTTP: RFC-2617 mode: qop="auth", both H and H-sess (selected by ss.snosess) - HTTP: NO user name hashing - HTTP: charset can be iso-8859-1 or utf-8 - SASL mode: qop="auth", H-sess, charset=utf-8 So far: H=MD5. We are prepared for other hash functions, though. *) open Printf module StrMap = Map.Make(String) module StrSet = Set.Make(String) type ptype = [ `SASL | `HTTP ] type profile = { ptype : ptype; hash_functions : Netsys_digests.iana_hash_fn list; (* The server will only use the first one. The client will accept any of these *) mutual : bool; (* Only for clients: whether it is required that the server includes (for HTTP) or includes the right rspauth header. *) } type response_params = { r_ptype : ptype; r_hash : Netsys_digests.iana_hash_fn; r_no_sess : bool; (* simple scheme w/o -sess. Only HTTP *) r_rfc2069 : bool; r_user : string; (* UTF-8 or ISO-8859-1 *) r_authz : string option; r_realm : string; (* UTF-8 or ISO-8859-1 *) r_nonce : string; r_cnonce : string; r_nc : int; r_method : string; r_digest_uri : string; r_utf8 : bool; r_opaque : string option; (* only HTTP *) r_domain : string list; (* only HTTP *) r_userhash : bool; (* only HTTP *) } type credentials = (string * string * (string * string) list) list type server_session = { sstate : Netsys_sasl_types.server_state; sresponse : (response_params * string * string) option; snextnc : int; sstale : bool; snonce : string; srealm : string option; (* always UTF-8 *) sprofile : profile; sutf8 : bool; (* whether to use UTF-8 on the wire *) snosess : bool; lookup : string -> string -> credentials option; } let create_nonce() = let nonce_data = Bytes.create 16 in Netsys_rng.fill_random nonce_data; Netencoding.to_hex (Bytes.to_string nonce_data) let hash iana_name = if iana_name = `MD5 then Digest.string else Netsys_digests.digest_string (Netsys_digests.iana_find iana_name) let hash_available iana_name = iana_name = `MD5 || ( try ignore(Netsys_digests.iana_find iana_name); true with Not_found -> false ) (* Quotes strings: *) let qstring = Nethttp.qstring_of_value let hex s = Netencoding.to_hex ~lc:true s let compute_response (p:response_params) password a2_prefix = (* a2_prefix: either "AUTHENTICATE:" or ":" *) let nc = sprintf "%08x" p.r_nc in (* eprintf "compute_response user=%s authz=%s realm=%s password=%s nonce=%s cnonce=%s digest-uri=%s nc=%s a2_prefix=%s\n" p.r_user (match p.r_authz with None -> "n/a" | Some a -> a) p.r_realm password p.r_nonce p.r_cnonce p.r_digest_uri nc a2_prefix; *) (* Note that RFC-2617 has an error here (it would calculate a1_a = hex (h ...)), and this made it into the standard. So DIGEST-MD5 as SASL is incompatible with Digest Authentication for HTTP. *) let h = hash p.r_hash in let a1 = if p.r_no_sess then p.r_user ^ ":" ^ p.r_realm ^ ":" ^ password else let a1_a = h (p.r_user ^ ":" ^ p.r_realm ^ ":" ^ password) in let a1_a = match p.r_ptype with | `HTTP -> hex a1_a (* see comment above *) | `SASL -> a1_a in let a1_b = a1_a ^ ":" ^ p.r_nonce ^ ":" ^ p.r_cnonce in match p.r_authz with | None -> a1_b | Some authz -> a1_b ^ ":" ^ authz in let a2 = a2_prefix ^ p.r_digest_uri in let auth_body = if p.r_rfc2069 then (* RFC 2069 mode *) [ hex (h a1); p.r_nonce; hex (h a2) ] else [ hex (h a1); p.r_nonce; nc; p.r_cnonce; "auth"; hex (h a2) ] in hex (h (String.concat ":" auth_body)) let verify_utf8 s = try Netconversion.verify `Enc_utf8 s with _ -> failwith "UTF-8 mismatch" let to_utf8 is_utf8 s = (* Convert from client encoding to UTF-8 *) if is_utf8 then ( verify_utf8 s; s ) else (* it is ISO-8859-1 *) Netconversion.convert ~in_enc:`Enc_iso88591 ~out_enc:`Enc_utf8 s let to_client is_utf8 s = (* Convert from UTF-8 to client encoding *) if is_utf8 then ( verify_utf8 s; s (* client uses utf-8, too *) ) else try Netconversion.convert ~in_enc:`Enc_utf8 ~out_enc:`Enc_iso88591 s with | Netconversion.Malformed_code -> failwith "cannot convert to ISO-8859-1" let to_strmap l = (* will raise Not_found if a key appears twice *) fst (List.fold_left (fun (m,s) (name,value) -> if StrSet.mem name s then raise Not_found; (StrMap.add name value m, StrSet.add name s) ) (StrMap.empty, StrSet.empty) l ) let space_re = Netstring_str.regexp "[ \t]+" let space_split = Netstring_str.split space_re let nc_re = let hex = "[0-9a-f]" in Netstring_str.regexp (hex ^ hex ^ hex ^ hex ^ hex ^ hex ^ hex ^ hex ^ "$") let get_nc s = match Netstring_str.string_match nc_re s 0 with | None -> raise Not_found | Some _ -> ( try int_of_string ("0x" ^ s) with Failure _ -> raise Not_found ) let server_emit_initial_challenge_kv ?(quote=false) ss = (* for HTTP: "domain" is not returned *) let q s = if quote then qstring s else s in let h = List.hd ss.sprofile.hash_functions in let h_name = List.assoc h Netsys_digests.iana_rev_alist in let l = ( match ss.srealm with | None -> [] | Some realm -> [ "realm", q (to_utf8 ss.sutf8 realm) ] ) @ [ "nonce", q ss.snonce; "qpop", "auth" ] @ ( if ss.sstale then [ "stale", "true" ] else [] ) @ ( if ss.sutf8 then [ "charset", "utf-8" ] else [] ) @ [ "algorithm", String.uppercase h_name ^ (if ss.snosess then "" else "-sess") ] in ( { ss with sstate = `Wait; sstale = false; }, l ) let server_emit_final_challenge_kv ?(quote=false) ss = let q s = if quote then qstring s else s in match ss.sresponse with | None -> assert false | Some(rp,_,srv_resp) -> ( { ss with sstate = `OK; }, [ "rspauth", q srv_resp ] @ ( match ss.sprofile.ptype with | `SASL -> [] | `HTTP -> [ "qop", "auth"; "cnonce", q rp.r_cnonce; "nc", sprintf "%08x" rp.r_nc ] ) ) let iana_sess_alist = List.map (fun (name,code) -> (name ^ "-sess", code)) Netsys_digests.iana_alist let decode_response ptype msg_params method_name = let m = to_strmap msg_params in let user = StrMap.find "username" m in let realm = try StrMap.find "realm" m with Not_found -> "" in let nonce = StrMap.find "nonce" m in (* We only support qop="auth" in server mode, so there is always a cnonce and nc. *) let qop = StrMap.find "qop" m in if qop <>"auth" then failwith "bad qop"; let cnonce = StrMap.find "cnonce" m in let nc_str = StrMap.find "nc" m in let nc = get_nc nc_str in let digest_uri_name = match ptype with | `HTTP -> "uri" | `SASL -> "digest-uri" in let digest_uri = StrMap.find digest_uri_name m in let response = StrMap.find "response" m in let utf8 = if StrMap.mem "charset" m then ( let v = StrMap.find "charset" m in if v <> "utf-8" then failwith "bad charset"; true ) else false in let opaque = try Some(StrMap.find "opaque" m) with Not_found -> None in let authz0 = try Some(StrMap.find "authzid" m) with Not_found -> None in let authz = if authz0 = Some "" then None else authz0 in let userhash = try StrMap.find "userhash" m = "true" with Not_found -> false in let alg_lc = try StrMap.find "algorithm" m with Not_found -> "" in let hash, no_sess = try (List.assoc alg_lc Netsys_digests.iana_alist, true) with Not_found -> try (List.assoc alg_lc iana_sess_alist, false) with Not_found -> match ptype with | `SASL -> (`MD5, false) | `HTTP -> raise Not_found in let r = { r_ptype = ptype; r_hash = hash; r_no_sess = no_sess; r_user = user; r_authz = authz; r_realm = realm; r_nonce = nonce; r_cnonce = cnonce; r_nc = nc; r_method = method_name; r_digest_uri = digest_uri; r_utf8 = utf8; r_rfc2069 = false; (* not in the server *) r_opaque = opaque; r_domain = []; (* not repeated in response *) r_userhash = userhash; } in (r, response) let validate_response ss r response = let realm_utf8 = to_utf8 r.r_utf8 r.r_realm in ( match ss.srealm with | None -> () | Some expected_realm -> if expected_realm <> realm_utf8 then failwith "bad realm"; ); if r.r_hash <> List.hd ss.sprofile.hash_functions then failwith "unexpected hash function"; if r.r_no_sess <> ss.snosess then failwith "parameter mismatch"; if r.r_userhash then failwith "user name hashing not supported"; (* not supported on server side *) let user_utf8 = to_utf8 r.r_utf8 r.r_user in let authz = match r.r_authz with | None -> "" | Some authz -> verify_utf8 authz; authz in let password_utf8 = match ss.lookup user_utf8 authz with | None -> failwith "bad user" | Some creds -> Netsys_sasl_util.extract_password creds in let password = to_client r.r_utf8 password_utf8 in let expected_response = compute_response r password (r.r_method ^ ":") in if response <> expected_response then failwith "bad password"; password exception Restart of string let server_process_response_kv ss msg_params method_name = try let (r, response) = decode_response ss.sprofile.ptype msg_params method_name in if r.r_nc > 1 then raise(Restart r.r_nonce); if ss.sstate <> `Wait then raise Not_found; let password = validate_response ss r response in (* success: *) let srv_response = compute_response r password ":" in { ss with snextnc = r.r_nc + 1; sresponse = Some(r, response, srv_response); sstate = `Emit; } with | Failure msg -> { ss with sstate = `Auth_error msg } | Not_found -> { ss with sstate = `Auth_error "unspecified" } | Restart id -> { ss with sstate = `Restart id } let server_process_response_restart_kv ss msg_params set_stale method_name = try let old_r = match ss.sresponse with | None -> assert false | Some (r, _, _) -> r in let (new_r, response) = decode_response ss.sprofile.ptype msg_params method_name in if old_r.r_hash <> new_r.r_hash || old_r.r_no_sess <> new_r.r_no_sess || old_r.r_user <> new_r.r_user || old_r.r_authz <> new_r.r_authz || old_r.r_realm <> new_r.r_realm || old_r.r_nonce <> new_r.r_nonce || old_r.r_cnonce <> new_r.r_cnonce || old_r.r_nc + 1 <> new_r.r_nc (* || old_r.r_digest_uri <> new_r.r_digest_uri *) (* CHECK *) || old_r.r_utf8 <> new_r.r_utf8 then raise Not_found; let password = validate_response ss new_r response in (* success *) if set_stale then raise Exit; let srv_response = compute_response new_r password ":" in ( { ss with snextnc = new_r.r_nc + 1; sresponse = Some(new_r, response, srv_response); sstate = `Emit; }, true ) with | Failure _ -> (* from validate_response *) ( { ss with snonce = create_nonce(); snextnc = 1; sresponse = None; sstate = `Emit; }, false ) | Not_found -> ( { ss with snonce = create_nonce(); snextnc = 1; sresponse = None; sstate = `Emit; }, false ) | Exit -> ( { ss with snonce = create_nonce(); snextnc = 1; sresponse = None; sstate = `Emit; sstale = true }, false ) let server_stash_session_i ss = let tuple = (ss.sprofile, ss.sstate, ss.sresponse, ss.snextnc, ss.sstale, ss.srealm, ss.snonce, ss.sutf8, ss.snosess) in "server,t=DIGEST;" ^ Marshal.to_string tuple [] let ss_re = Netstring_str.regexp "server,t=DIGEST;" let server_resume_session_i ~lookup s = match Netstring_str.string_match ss_re s 0 with | None -> failwith "Netmech_digest.server_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let (sprofile,sstate, sresponse, snextnc, sstale, srealm, snonce, sutf8, snosess) = Marshal.from_string data 0 in { sprofile; sstate; sresponse; snextnc; sstale; srealm; snonce; sutf8; snosess; lookup } let server_prop_i ss key = match key with | "nonce" -> ss.snonce | _ -> ( match ss.sresponse with | None -> raise Not_found | Some(rp,_,_) -> match key with | "digest-uri" | "uri" -> rp.r_digest_uri | "cnonce" -> rp.r_cnonce | "nc" -> string_of_int rp.r_nc | "realm" -> (* may be in ISO-8859-1 *) to_utf8 rp.r_utf8 rp.r_realm | _ -> raise Not_found ) type client_session = { cstate : Netsys_sasl_types.client_state; cresp : response_params option; cdigest_uri : string; cmethod : string; cprofile : profile; crealm : string option; (* always UTF-8 *) cuser : string; (* always UTF-8 *) cauthz : string; (* always UTF-8 *) cpasswd : string; (* always UTF-8 *) cnonce : string; } let client_restart_i cs = match cs.cresp with | None -> assert false | Some rp -> let rp_next = { rp with r_nc = rp.r_nc+1 } in { cs with cresp = Some rp_next; cstate = `Emit } let client_process_final_challenge_kv cs msg_params = try if cs.cstate <> `Wait then raise Not_found; if cs.cprofile.mutual then ( let m = to_strmap msg_params in let rspauth = StrMap.find "rspauth" m in match cs.cresp with | None -> raise Not_found | Some rp -> let pw = to_client rp.r_utf8 cs.cpasswd in let resp = compute_response rp pw ":" in if resp <> rspauth then raise Not_found; { cs with cstate = `OK } ) else { cs with cstate = `OK } with | Failure msg -> { cs with cstate = `Auth_error msg } | Not_found -> { cs with cstate = `Auth_error "cannot authenticate server" } let client_process_initial_challenge_kv cs msg_params = try if cs.cstate <> `Wait then raise Not_found; let m = to_strmap msg_params in let utf8 = try StrMap.find "charset" m = "utf-8" with Not_found -> false in (* UTF-8: we encode our message in UTF-8 when the server sets the utf-8 attribute *) let realm = try StrMap.find "realm" m with Not_found -> match cs.crealm with | Some r -> to_client utf8 r | None -> "" in let nonce = StrMap.find "nonce" m in let qop_s, rfc2069 = try (StrMap.find "qop" m, false) with Not_found -> ("auth", true) in let qop_l = space_split qop_s in if not (List.mem "auth" qop_l) then failwith "bad qop"; let stale = try StrMap.find "stale" m = "true" with Not_found -> false in if stale && cs.cresp = None then raise Not_found; if cs.cprofile.ptype = `SASL && not utf8 then failwith "missing utf-8"; let opaque = try Some(StrMap.find "opaque" m) with Not_found -> None in let domain = try space_split (StrMap.find "domain" m) with Not_found -> [] in let alg_lc = try String.lowercase(StrMap.find "algorithm" m) with Not_found when cs.cprofile.ptype = `HTTP -> "md5" in let hash, no_sess = try (List.assoc alg_lc Netsys_digests.iana_alist, true) with Not_found -> (List.assoc alg_lc iana_sess_alist, false) in let userhash = try StrMap.find "userhash" m = "true" with Not_found -> false in if cs.cprofile.ptype = `SASL && no_sess then raise Not_found; if not (List.mem hash cs.cprofile.hash_functions) then failwith "unsupported hash function"; (* If this is an initial challenge after we tried to resume the old session, we need a new conce *) let cnonce = match cs.cresp with | None -> cs.cnonce | Some _ -> create_nonce() in let rp = { r_ptype = cs.cprofile.ptype; r_hash = hash; r_no_sess = no_sess; r_user = to_client utf8 cs.cuser; r_authz = if cs.cauthz="" then None else Some(to_client utf8 cs.cauthz); r_realm = realm; r_nonce = nonce; r_cnonce = cnonce; r_nc = 1; r_method = cs.cmethod; r_digest_uri = cs.cdigest_uri; r_utf8 = utf8; r_rfc2069 = cs.cprofile.ptype=`HTTP && rfc2069; r_opaque = opaque; r_domain = domain; r_userhash = userhash; } in { cs with cresp = Some rp; cstate = if stale then `Stale else `Emit; cnonce = cnonce; } with | Failure msg -> { cs with cstate = `Auth_error msg } | Not_found -> { cs with cstate = `Auth_error "unspecified" } let client_modify ?mod_method ?mod_uri cs = match cs.cresp with | None -> invalid_arg "Netmech_digest.client_modify" | Some rp -> let rp1 = { rp with r_method = (match mod_method with | None -> rp.r_method | Some m -> m ); r_digest_uri = (match mod_uri with | None -> rp.r_digest_uri | Some u -> u ) } in { cs with cresp = Some rp1 } let client_emit_response_kv ?(quote=false) cs = (* SASL: method_name="AUTHENTICATE" *) let q s = if quote then qstring s else s in match cs.cresp with | None -> assert false | Some rp -> let pw = to_client rp.r_utf8 cs.cpasswd in let resp = compute_response rp pw (rp.r_method ^ ":") in let digest_uri_name = match cs.cprofile.ptype with | `SASL -> "digest-uri" | `HTTP -> "uri" in let username = if rp.r_userhash then let h = hash rp.r_hash in h (rp.r_user ^ ":" ^ rp.r_realm) else rp.r_user in let l = [ "username", q username; "realm", q rp.r_realm; "nonce", q rp.r_nonce; digest_uri_name, q rp.r_digest_uri; "response", q resp; ] @ ( if rp.r_rfc2069 then [] else [ "cnonce", q rp.r_cnonce; "nc", sprintf "%08x" rp.r_nc; "qop", "auth"; ] ) @ ( if rp.r_utf8 then [ "charset", "utf-8" ] else [] ) @ ( match rp.r_authz with | None -> [] | Some authz -> [ "authzid", q authz ] ) @ ( match rp.r_opaque with | None -> [] | Some s -> [ "opaque", q s ] ) @ ( if rp.r_ptype = `SASL && rp.r_hash = `MD5 then [] else let alg = String.uppercase (List.assoc rp.r_hash Netsys_digests.iana_rev_alist) in let suffix = if rp.r_no_sess then "" else "-sess" in [ "algorithm", alg ^ suffix ] ) in ( { cs with cstate = (if cs.cprofile.mutual then `Wait else `OK) }, l ) let client_stash_session_i cs = "client,t=DIGEST;" ^ Marshal.to_string cs [] let cs_re = Netstring_str.regexp "client,t=DIGEST;" let client_resume_session_i s = match Netstring_str.string_match cs_re s 0 with | None -> failwith "Netmech_digest.client_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let cs = Marshal.from_string data 0 in (cs : client_session) let client_prop_i cs key = match key with | "cnonce" -> cs.cnonce | "digest-uri" | "uri" -> cs.cdigest_uri | _ -> (match cs.cresp with | None -> raise Not_found | Some rp -> match key with | "realm" -> rp.r_realm | "nonce" -> rp.r_nonce | "nc" -> string_of_int rp.r_nc | _ -> raise Not_found ) ocamlnet-4.1.2/src/netstring/netmime_header.mli0000644000175000017500000000264612731530350020230 0ustar gerdgerd(* $Id$ *) (** MIME: Access methods for frequent standard fields. * * These functions will raise [Not_found] if the fields are not * present. * * Many HTTP-specific header functions can be found in {!Nethttp.Header}. *) open Netmime val get_content_length : #mime_header_ro -> int (** Returns the Content-length field as integer *) val get_content_type : #mime_header_ro -> (string * (string * Netmime_string.s_param)list) (** Returns the Content-type as parsed value. The left value of the * pair is the main type, and the right value is the list of * parameters. For example, for the field value * ["text/plain; charset=utf-8"] this method returns * [("text/plain", ["charset", p])] where [p] is an opaque value * with [Netmime_string.param_value p = "utf-8"]. *) val get_content_disposition : #mime_header_ro -> (string * (string * Netmime_string.s_param)list) (** Returns the Content-disposition field as parsed value. The * left value is the main disposition, and the right value is the * list of parameters. For example, for the field value * ["attachment; filename=xy.dat"] this method returns * [("attachment", ["filename", p])] where [p] is an opaque value * with [Netmime_string.param_value p = "xy.dat"]. *) val get_content_transfer_encoding : #mime_header_ro -> string (** Returns the Content-transfer-encoding as string *) ocamlnet-4.1.2/src/netstring/netaccel.ml0000644000175000017500000000334012731530350016657 0ustar gerdgerd(* $Id$ *) external int_blit : int array -> int -> int array -> int -> int -> unit = "netstring_int_blit_ml" ;; external int_series : int array -> int -> int array -> int -> int -> int -> unit = "netstring_int_series_byte" "netstring_int_series_ml";; external read_iso88591_str : int -> Netconversion.encoding -> int array -> int array -> string -> int -> int -> (int*int*Netconversion.encoding) = "netstring_read_iso88591_byte" "netstring_read_iso88591_ml" ;; external read_utf8_str : bool -> int array -> int array -> string -> int -> int -> (int*int*Netconversion.encoding) = "netstring_read_utf8_byte" "netstring_read_utf8_ml" ;; let read_iso88591 limit enc = let open Netstring_tstring in let open Netconversion in let read : type s . s tstring_ops -> _ -> _ -> s -> _ -> _ -> _ = fun ops chars blen s pos len -> match ops.kind with | Some String_kind -> read_iso88591_str limit enc chars blen s pos len | _ -> (Netconversion.read_iso88591 limit enc).read ops chars blen s pos len in { Netconversion.read } let read_utf8 is_java = let open Netstring_tstring in let open Netconversion in let read : type s . s tstring_ops -> _ -> _ -> s -> _ -> _ -> _ = fun ops chars blen s pos len -> match ops.kind with | Some String_kind -> read_utf8_str is_java chars blen s pos len | _ -> (Netconversion.read_utf8 is_java).read ops chars blen s pos len in { Netconversion.read } let init() = Netaux.ArrayAux.int_blit_ref := int_blit; Netaux.ArrayAux.int_series_ref := int_series; Netconversion.read_iso88591_ref := read_iso88591; Netconversion.read_utf8_ref := read_utf8;; ocamlnet-4.1.2/src/netstring/netmech_plain_sasl.ml0000644000175000017500000001461412731530350020737 0ustar gerdgerd(* $Id$ *) (* Unit tests: tests/netstring/bench/test_netmech.ml *) module PLAIN : Netsys_sasl_types.SASL_MECHANISM = struct let mechanism_name = "PLAIN" let client_first = `Required let server_sends_final_data = false let supports_authz = true let available() = true type credentials = (string * string * (string * string) list) list let init_credentials l = (l:credentials) type server_session = { sstate : Netsys_sasl_types.server_state; suser : string option; sauthz : string option; lookup : string -> string -> credentials option; } let server_state ss = ss.sstate let no_mutual = "The PLAIN mechanism does not support mutual authentication" let no_secure = "The PLAIN mechanism is not a secure mechanism" let create_server_session ~lookup ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_plain_sasl.create_server_session:" [ "mutual"; "secure" ] params in let req_mutual = try List.assoc "mutual" params = "true" with Not_found -> false in let req_secure = try List.assoc "secure" params = "true" with Not_found -> false in { sstate = ( if req_mutual then `Auth_error no_mutual else if req_secure then `Auth_error no_secure else `Wait ); suser = None; sauthz = None; lookup } let server_configure_channel_binding ss cb_list = failwith "Netmach_plain_sasl.server_configure_channel_binding: \ not supported" let verify_utf8 s = try Netconversion.verify `Enc_utf8 s with _ -> failwith "UTF-8 mismatch" let server_process_response ss msg = try if ss.sstate <> `Wait then failwith "protocol error"; let n = String.length msg in let k1 = String.index_from msg 0 '\000' in if k1 = n-1 then raise Not_found; let k2 = String.index_from msg (k1+1) '\000' in let authz = String.sub msg 0 k1 in let user = String.sub msg (k1+1) (k2-k1-1) in let passwd = String.sub msg (k2+1) (n-k2-1) in verify_utf8 authz; verify_utf8 user; verify_utf8 passwd; match ss.lookup user authz with | None -> failwith "unknown user" | Some creds -> let expected_passwd = Netsys_sasl_util.extract_password creds in if passwd <> expected_passwd then failwith "bad password"; { ss with sstate = `OK; suser = Some user; sauthz = Some authz; } with | Failure msg -> { ss with sstate = `Auth_error msg } let server_process_response_restart ss msg set_stale = failwith "Netmech_plain_sasl.server_process_response_restart: \ not available" let server_emit_challenge ss = failwith "Netmech_plain_sasl.server_emit_challenge: no challenge" let server_channel_binding ss = `None let server_stash_session ss = "server,t=PLAIN;" ^ Marshal.to_string (ss.sstate, ss.suser, ss.sauthz) [] let ss_re = Netstring_str.regexp "server,t=PLAIN;" let server_resume_session ~lookup s = match Netstring_str.string_match ss_re s 0 with | None -> failwith "Netmech_plain_sasl.server_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let (state,user,authz) = Marshal.from_string data 0 in { sstate = state; suser = user; sauthz = authz; lookup } let server_session_id ss = None let server_prop ss key = raise Not_found let server_gssapi_props ss = raise Not_found let server_user_name ss = match ss.suser with | None -> raise Not_found | Some name -> name let server_authz_name ss = match ss.sauthz with | None -> raise Not_found | Some name -> name type client_session = { cstate : Netsys_sasl_types.client_state; cuser : string; cauthz : string; cpasswd : string; } let create_client_session ~user ~authz ~creds ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_plain_sasl.create_client_session:" [ "mutual"; "secure" ] params in let req_mutual = try List.assoc "mutual" params = "true" with Not_found -> false in let req_secure = try List.assoc "secure" params = "true" with Not_found -> false in let pw = try Netsys_sasl_util.extract_password creds with Not_found -> failwith "Netmech_plain_sasl.create_client_session: no password \ found in credentials" in { cstate = ( if req_mutual then `Auth_error no_mutual else if req_secure then `Auth_error no_secure else `Emit ); cuser = user; cauthz = authz; cpasswd = pw; } let client_configure_channel_binding cs cb = if cb <> `None then failwith "Netmech_plain_sasl.client_configure_channel_binding: \ not supported" else cs let client_state cs = cs.cstate let client_channel_binding cs = `None let client_restart cs = if cs.cstate <> `OK then failwith "Netmech_plain_sasl.client_restart: unfinished auth"; { cs with cstate = `Emit } let client_process_challenge cs msg = { cs with cstate = `Auth_error "protocol error" } let client_emit_response cs = if cs.cstate <> `Emit then failwith "Netmech_plain_sasl.client_emit_response: bad state"; ( { cs with cstate = `OK; }, cs.cauthz ^ "\000" ^ cs.cuser ^ "\000" ^ cs.cpasswd ) let client_stash_session cs = "client,t=PLAIN;" ^ Marshal.to_string cs [] let cs_re = Netstring_str.regexp "client,t=PLAIN;" let client_resume_session s = match Netstring_str.string_match cs_re s 0 with | None -> failwith "Netmech_plain_sasl.client_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let cs = Marshal.from_string data 0 in (cs : client_session) let client_session_id cs = None let client_prop cs key = raise Not_found let client_gssapi_props cs = raise Not_found let client_user_name cs = cs.cuser let client_authz_name cs = cs.cauthz end ocamlnet-4.1.2/src/netstring/netmappings_asn1.pmap0000644000175000017500000000536212731530350020703 0ustar gerdgerdasn1_iso646 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27 27 28 28 29 29 30 30 31 31 32 32 33 33 34 34 37 37 38 38 39 39 40 40 41 41 42 42 43 43 44 44 45 45 46 46 47 47 48 48 49 49 50 50 51 51 52 52 53 53 54 54 55 55 56 56 57 57 58 58 59 59 60 60 61 61 62 62 63 63 65 65 66 66 67 67 68 68 69 69 70 70 71 71 72 72 73 73 74 74 75 75 76 76 77 77 78 78 79 79 80 80 81 81 82 82 83 83 84 84 85 85 86 86 87 87 88 88 89 89 90 90 95 95 97 97 98 98 99 99 100 100 101 101 102 102 103 103 104 104 105 105 106 106 107 107 108 108 109 109 110 110 111 111 112 112 113 113 114 114 115 115 116 116 117 117 118 118 119 119 120 120 121 121 122 122 127 127 asn1_printable 32 32 39 39 40 40 41 41 43 43 44 44 45 45 46 46 47 47 48 48 49 49 50 50 51 51 52 52 53 53 54 54 55 55 56 56 57 57 58 58 61 61 63 63 65 65 66 66 67 67 68 68 69 69 70 70 71 71 72 72 73 73 74 74 75 75 76 76 77 77 78 78 79 79 80 80 81 81 82 82 83 83 84 84 85 85 86 86 87 87 88 88 89 89 90 90 97 97 98 98 99 99 100 100 101 101 102 102 103 103 104 104 105 105 106 106 107 107 108 108 109 109 110 110 111 111 112 112 113 113 114 114 115 115 116 116 117 117 118 118 119 119 120 120 121 121 122 122 asn1_t61 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27 27 28 28 29 29 30 30 31 31 32 32 33 33 34 34 37 37 38 38 39 39 40 40 41 41 42 42 43 43 44 44 45 45 46 46 47 47 48 48 49 49 50 50 51 51 52 52 53 53 54 54 55 55 56 56 57 57 58 58 59 59 60 60 61 61 62 62 63 63 64 64 65 65 66 66 67 67 68 68 69 69 70 70 71 71 72 72 73 73 74 74 75 75 76 76 77 77 78 78 79 79 80 80 81 81 82 82 83 83 84 84 85 85 86 86 87 87 88 88 89 89 90 90 91 91 93 93 95 95 97 97 98 98 99 99 100 100 101 101 102 102 103 103 104 104 105 105 106 106 107 107 108 108 109 109 110 110 111 111 112 112 113 113 114 114 115 115 116 116 117 117 118 118 119 119 120 120 121 121 122 122 124 124 127 127 128 128 129 129 130 130 131 131 132 132 133 133 134 134 135 135 136 136 137 137 138 138 139 139 140 140 141 141 142 142 143 143 144 144 145 145 146 146 147 147 148 148 149 149 150 150 151 151 152 152 153 153 154 154 155 155 156 156 157 157 158 158 159 159 160 160 161 161 162 162 163 163 164 36 165 165 166 35 167 167 168 164 171 171 176 176 177 177 178 178 179 179 180 215 181 181 182 182 183 183 184 247 187 187 188 188 189 189 190 190 191 191 193 768 194 769 195 770 196 771 197 772 198 774 199 775 200 776 202 778 203 807 204 818 205 779 206 808 207 780 224 8486 225 198 226 208 227 170 228 294 230 306 231 319 232 321 233 216 234 338 235 186 236 222 237 358 238 330 239 329 240 312 241 230 242 273 243 253 244 295 245 305 246 307 247 320 248 322 249 248 250 339 251 223 252 254 253 359 254 331 ocamlnet-4.1.2/src/netstring/netstring_top.ml0000644000175000017500000000104112731530350017774 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) let exec s = let l = Lexing.from_string s in let ph = !Toploop.parse_toplevel_phrase l in assert(Toploop.execute_phrase false Format.err_formatter ph) ;; (* Install the printers: *) exec "#install_printer Netmime_string.print_s_param;;";; exec "#install_printer Neturl.print_url;;";; exec "#install_printer Netbuffer.print_buffer;;";; exec "#install_printer Netstream.print_in_obj_stream;;";; (* exec "#install_printer Cgi.print_argument;;";; *) ocamlnet-4.1.2/src/netstring/netcompression.mli0000644000175000017500000000170112731530350020321 0ustar gerdgerd(* $Id$ *) (** Registry for compression algorithms *) (** This registry is initially empty. The {!Netgzip} module can be used to register the [gzip] algorithm, just run {[ Netgzip.init() ]} to get this effect. *) val register : iana_name:string -> ?encoder:(unit -> Netchannels.io_obj_channel) -> ?decoder:(unit -> Netchannels.io_obj_channel) -> unit -> unit (** Registers a compression algorithm. The algorithm is given as a pair of functions returning {!Netchannels.io_obj_channel}. *) val lookup_encoder : iana_name:string -> unit -> Netchannels.io_obj_channel (** Returns the encoder, or raises [Not_found] *) val lookup_decoder : iana_name:string -> unit -> Netchannels.io_obj_channel (** Returns the decoder, or raises [Not_found] *) val all_encoders : unit -> string list val all_decoders : unit -> string list (** The iana names of all encoders and decoders, resp. *) ocamlnet-4.1.2/src/netstring/netmech_krb5_sasl.ml0000644000175000017500000006225612731530350020504 0ustar gerdgerd(* $Id$ *) open Printf let krb5_oid = [| 1;2;840;113554;1;2;2 |] let map_opt f = function | None -> None | Some x -> Some(f x) module Krb5_gs2_profile = struct let mechanism_name = "GS2-KRB5" let announce_channel_binding = false let mechanism_oid = krb5_oid let client_additional_params = [ "gssapi-acceptor" ] let server_additional_params = [ "gssapi-acceptor-service"; "realm" ] let client_map_user_name ~params user = ("", [| |]) let server_map_user_name ~params (name,name_type) = if name_type <> Netsys_gssapi.nt_krb5_principal_name then raise Not_found; let realm_opt = try Some(List.assoc "realm" params) with Not_found -> None in match realm_opt with | None -> name | Some r -> let components, name_realm = Netgssapi_support.parse_kerberos_name name in if name_realm <> Some r then raise Not_found; ( match components with | [ n ] -> n | _ -> raise Not_found ) let client_get_target_name ~params = try (List.assoc "gssapi-acceptor" params, Netsys_gssapi.nt_hostbased_service) with | Not_found -> failwith "missing parameter 'gssapi-acceptor'" let server_bind_target_name ~params = None let server_check_target_name ~params (name,name_type) = try let expected_service = List.assoc "gssapi-acceptor-service" params in if name_type = Netsys_gssapi.nt_hostbased_service || name_type = Netsys_gssapi.nt_hostbased_service_alt then ( let service, _ = Netsys_gssapi.parse_hostbased_service name in if service <> expected_service then raise Not_found; ) else ( if name_type = Netsys_gssapi.nt_krb5_principal_name then ( let components, _ = Netgssapi_support.parse_kerberos_name name in match components with | [service;_] -> if service <> expected_service then raise Not_found | _ -> raise Not_found ) else raise Not_found ); true with | Not_found | Failure _ -> false let client_flags ~params = [] let server_flags ~params = [] let client_credential = None (* Anybody who wants to pass in a client credential should do so this way: module My_profile = struct include Netmech_krb5_sasl.Krb5_gs2_profile let client_credential = ... end module Krb5_gs2(G:Netsys_gssapi.GSSAPI) = Netmech_gs2_sasl.GS2(My_profile)(G) *) end module Krb5_gs2(G:Netsys_gssapi.GSSAPI) = Netmech_gs2_sasl.GS2(Krb5_gs2_profile)(G) module Krb5_gs1(G:Netsys_gssapi.GSSAPI) : Netsys_sasl_types.SASL_MECHANISM = struct module M = Netgssapi_auth.Manage(G) module C = struct let raise_error = failwith end module A = Netgssapi_auth.Auth(G)(C) let mechanism_name = "GSSAPI" let client_first = `Required let server_sends_final_data = true let supports_authz = true let available() = true (* Well, let's assume this. We don't know yet whether we can get credentials, and we don't know yet whether we are acting as client or as server. *) type credentials = unit let init_credentials _ = () (* ------------------------ *) (* Client *) (* ------------------------ *) type client_sub_state = [ `Pre_init_context | `Init_context | `Skip_empty | `Neg_security | `Established ] type client_session = { mutable ccontext : G.context option; cauthz : string; cstate : Netsys_sasl_types.client_state; csubstate : client_sub_state; ctoken : string; cconf : Netsys_gssapi.client_config; ctarget_name : G.name; cprops : Netsys_gssapi.client_props option; } let cvalidity cs0 = let cs1 = { cs0 with ccontext = cs0.ccontext } in cs0.ccontext <- None; cs1 let client_state cs = cs.cstate let client_del_ctx cs = match cs.ccontext with | None -> cs | Some ctx -> M.delete_context cs.ccontext (); { cs with ccontext = None } let check_gssapi_status fn_name ((calling_error,routine_error,_) as major_status) minor_status = if calling_error <> `None || routine_error <> `None then ( let msg = M.format_status ~fn:fn_name ~minor_status major_status in (* eprintf "STATUS: %s %s %s\n%!" fn_name error minor_s; *) failwith msg ) let client_check_gssapi_status cs fn_name major_status minor_status = try check_gssapi_status fn_name major_status minor_status with | error -> ignore(client_del_ctx cs); raise error let call_init_sec_context cs input_token = let (out_context, out_token, ret_flags, props_opt) = A.init_sec_context ~initiator_cred:G.interface#no_credential ~context:cs.ccontext ~target_name:cs.ctarget_name ~req_flags:(A.get_client_flags cs.cconf) ~chan_bindings:None ~input_token cs.cconf in { cs with ccontext = Some out_context; ctoken = out_token; cprops = props_opt; cstate = `Emit; csubstate = ( if props_opt <> None then `Skip_empty else `Init_context ) } let create_client_session ~user ~authz ~creds ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_krb5_sasl.create_client_session:" [ "gssapi-acceptor"; "mutual"; "secure" ] params in let mutual_flag = try if List.assoc "mutual" params = "true" then [`Mutual_flag,`Required] else [] with Not_found -> [] in let cconf = Netsys_gssapi.create_client_config ~mech_type:krb5_oid ~target_name:(Krb5_gs2_profile.client_get_target_name ~params) ~privacy:`None ~integrity:`Required ~flags:( [ `Integ_flag, `Required ] @ mutual_flag ) () in let ctarget_name = A.get_target_name cconf in let cs = { cauthz = authz; ccontext = None; cstate = `Emit; csubstate = `Pre_init_context; ctoken = ""; ctarget_name; cconf; cprops = None; } in cs let client_configure_channel_binding cs cb = if cb <> `None then failwith "Netmech_krb5_sasl.client_configure_channel_binding: \ not supported" else cs let client_state cs = cs.cstate let client_channel_binding cs = `None let client_restart cs = if cs.cstate <> `OK then failwith "Netmech_krb5_sasl.client_restart: unfinished auth"; { (cvalidity cs) with ccontext = None; cstate = `Emit; csubstate = `Pre_init_context; ctoken = "" } let client_context cs = match cs.ccontext with | None -> failwith "client_context" | Some c -> c let client_process_challenge cs msg = let cs = cvalidity cs in if cs.cstate <> `Wait then ( let cs = client_del_ctx cs in { cs with cstate = `Auth_error "protocol error" } ) else match cs.csubstate with | `Pre_init_context -> assert false | `Init_context -> ( try call_init_sec_context cs (Some msg) with | Failure msg -> let cs = client_del_ctx cs in { cs with cstate = `Auth_error msg } ) | `Skip_empty when msg="" -> { cs with cstate = `Emit; ctoken = ""; csubstate = `Neg_security; } | `Neg_security | `Skip_empty -> ( try let input_message = [ Netxdr_mstring.string_to_mstring msg ] in let context = client_context cs in let msg_unwrapped = G.interface # unwrap ~context ~input_message ~output_message_preferred_type:`Bytes ~out:(fun ~output_message ~conf_state ~qop_state ~minor_status ~major_status () -> client_check_gssapi_status cs "unwrap" major_status minor_status; Netxdr_mstring.concat_mstrings output_message ) () in if String.length msg_unwrapped <> 4 then failwith "bad message"; let out_msg = "\001\000\000\000" ^ cs.cauthz in let out_message = [ Netxdr_mstring.string_to_mstring out_msg ] in let out_msg_wrapped = G.interface # wrap ~context ~conf_req:false ~qop_req:0l ~input_message:out_message ~output_message_preferred_type:`Bytes ~out:(fun ~conf_state ~output_message ~minor_status ~major_status () -> client_check_gssapi_status cs "wrap" major_status minor_status; Netxdr_mstring.concat_mstrings output_message ) () in let cs = { cs with ctoken = out_msg_wrapped; cstate = `Emit; csubstate = `Established; } in client_del_ctx cs; (* no longer needed *) with | Failure msg -> let cs = client_del_ctx cs in { cs with cstate = `Auth_error msg } ) | `Established -> let cs = client_del_ctx cs in { cs with cstate = `Auth_error "unexpected token" } let client_emit_response cs = if cs.cstate <> `Emit then failwith "Netmech_krb5_sasl.client_emit_response: bad state"; let cs = cvalidity cs in let cs = match cs.csubstate with | `Pre_init_context -> ( try let cs = call_init_sec_context cs None in { cs with cstate = `Wait } with | Failure msg -> let cs = client_del_ctx cs in { cs with cstate = `Auth_error msg } ) | `Established -> let cs = client_del_ctx cs in (* no longer needed *) { cs with cstate = `OK } | _ -> { cs with cstate = `Wait } in (cs, cs.ctoken) let client_session_id cs = None let client_prop cs key = raise Not_found let client_gssapi_props cs = match cs.cprops with | None -> raise Not_found | Some p -> p let client_user_name cs = "" let client_authz_name cs = cs.cauthz let client_stash_session cs = (* GSSAPI does not support that unfinished contexts are exported. We do not need the context anyway after session establishment, so we don't save it at all. *) if cs.cstate <> `OK then failwith "Netmech_krb5_sasl.client_stash_session: the session \ must be established (implementation restriction)"; "client,t=GSSAPI;" ^ Marshal.to_string (cs.cauthz, map_opt Netsys_gssapi.marshal_client_props cs.cprops ) [] let cs_re = Netstring_str.regexp "client,t=GSSAPI;" let client_resume_session s = match Netstring_str.string_match cs_re s 0 with | None -> failwith "Netmech_krb5_sasl.client_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let (cauthz, mprops) = Marshal.from_string data 0 in { cauthz; ccontext = None; cstate = `OK; csubstate = `Established; ctoken = ""; cconf = Netsys_gssapi.create_client_config(); ctarget_name = G.interface # no_name; cprops = map_opt Netsys_gssapi.unmarshal_client_props mprops; } (* #use "topfind";; #require "netclient,netgss-system";; Netpop.Debug.enable := true;; let addr = `Socket(`Sock_inet_byname(Unix.SOCK_STREAM, "office1", 110), Uq_client.default_connect_options);; let client = new Netpop.connect addr 60.0;; module S = Netmech_krb5_sasl.Krb5_gs1(Netgss.System);; module S = Netmech_krb5_sasl.Krb5_gs2(Netgss.System);; Netpop.authenticate ~sasl_mechs:[ (module S) ] ~user:"" ~creds:[] ~sasl_params:["gssapi-acceptor", "pop@office1.lan.sumadev.de", false] client;; *) (* ------------------------ *) (* Server *) (* ------------------------ *) type server_sub_state = [ `Acc_context | `Neg_security1 | `Neg_security2 | `Established ] type server_session = { mutable scontext : G.context option; sstate : Netsys_sasl_types.server_state; ssubstate : server_sub_state; stoken : string; suser : string option; sauthz : string option; sconf : Netsys_gssapi.server_config; scred : G.credential; slookup : (string -> string -> credentials option); sservice : string; srealm : string option; sprops : Netsys_gssapi.server_props option; } let svalidity ss0 = let ss1 = { ss0 with scontext = ss0.scontext } in ss0.scontext <- None; ss1 let server_state ss = ss.sstate let server_del_ctx ss = match ss.scontext with | None -> ss | Some ctx -> M.delete_context ss.scontext (); { ss with scontext = None } let server_check_gssapi_status ss fn_name major_status minor_status = try check_gssapi_status fn_name major_status minor_status with | error -> ignore(server_del_ctx ss); raise error let create_server_session ~lookup ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_krb5_sasl.create_server_session:" [ "gssapi-acceptor-service"; "realm"; "mutual"; "secure" ] params in let sservice = try List.assoc "gssapi-acceptor-service" params with Not_found -> failwith "Netmech_krb5_sasl.create_server_session: \ missing parameter 'gssapi-acceptor-service'" in let srealm = try Some(List.assoc "realm" params) with Not_found -> None in let mutual_flag = try if List.assoc "mutual" params = "true" then [`Mutual_flag, `Required] else [] with Not_found -> [] in let sconf = Netsys_gssapi.create_server_config ~mech_types:[ krb5_oid ] ~acceptor_name:(sservice, Netsys_gssapi.nt_hostbased_service) ~privacy:`None ~integrity:`Required ~flags:( [`Integ_flag, `Required ] @ mutual_flag ) () in let scred = A.get_acceptor_cred ~acceptor_name:G.interface#no_name sconf in { scontext = None; sstate = `Wait; ssubstate = `Acc_context; stoken = ""; suser = None; sauthz = None; slookup = lookup; sservice; srealm; scred; sconf; sprops = None } let server_configure_channel_binding ss cb_list = failwith "Netmech_krb5_sasl.Krb5_gs1.server_configure_channel_binding: \ not supported" let server_context ss = match ss.scontext with | None -> assert false | Some c -> c let server_set_neg_security_token ss = (* we do not offer any security layer *) let context = server_context ss in let out_msg = "\001\000\000\000" in let out_message = [ Netxdr_mstring.string_to_mstring out_msg ] in let out_msg_wrapped = G.interface # wrap ~context ~conf_req:false ~qop_req:0l ~input_message:out_message ~output_message_preferred_type:`Bytes ~out:(fun ~conf_state ~output_message ~minor_status ~major_status () -> server_check_gssapi_status ss "wrap" major_status minor_status; Netxdr_mstring.concat_mstrings output_message ) () in { ss with stoken = out_msg_wrapped } let server_process_response_accept_context ss msg = let (out_context, out_token, ret_flags, props_opt) = A.accept_sec_context ~context:ss.scontext ~acceptor_cred:ss.scred ~input_token:msg ~chan_bindings:None ss.sconf in let ss = { ss with scontext = Some out_context; stoken = out_token; sprops = props_opt; sstate = `Emit; (* even an empty token *) } in if props_opt <> None then ( let src_name, targ_name = G.interface # inquire_context ~context:(server_context ss) ~out:(fun ~src_name ~targ_name ~lifetime_req ~mech_type ~ctx_flags ~locally_initiated ~is_open ~minor_status ~major_status () -> server_check_gssapi_status ss "inquire_context" major_status minor_status; if mech_type <> krb5_oid then failwith "the mechanism is not Kerberos 5"; src_name, targ_name ) () in try let (targ_disp_name, targ_disp_name_type) = A.get_display_name targ_name in let ok = Krb5_gs2_profile.server_check_target_name ~params:["gssapi-acceptor-service", ss.sservice] (targ_disp_name, targ_disp_name_type) in if not ok then failwith "unexpected target or decoding error"; let (src_disp_name, src_disp_name_type) = A.get_display_name src_name in let n = try Krb5_gs2_profile.server_map_user_name ~params:( match ss.srealm with | None -> [] | Some r -> ["realm", r] ) (src_disp_name,src_disp_name_type) with | Not_found -> failwith "cannot parse client name" in let ss = { ss with suser = Some n } in if ss.stoken = "" then ( let ss = server_set_neg_security_token ss in { ss with ssubstate = `Neg_security2 } ) else { ss with ssubstate = `Neg_security1 } with error -> ignore(server_del_ctx ss); raise error ) else ss let server_process_response_neg_security1 ss msg = (* any msg is acceptable *) let ss = server_set_neg_security_token ss in { ss with ssubstate = `Neg_security2; sstate = `Emit } let server_process_response_neg_security2 ss msg = let input_message = [ Netxdr_mstring.string_to_mstring msg ] in let context = server_context ss in let msg_unwrapped = G.interface # unwrap ~context ~input_message ~output_message_preferred_type:`Bytes ~out:(fun ~output_message ~conf_state ~qop_state ~minor_status ~major_status () -> server_check_gssapi_status ss "unwrap" major_status minor_status; Netxdr_mstring.concat_mstrings output_message ) () in if String.length msg_unwrapped < 4 then failwith "bad security token"; if String.sub msg_unwrapped 0 4 <> "\001\000\000\000" then failwith "bad security token"; let authz = String.sub msg_unwrapped 4 (String.length msg_unwrapped - 4) in let ss = { ss with sauthz = Some authz } in let user = match ss.suser with | None -> raise Not_found | Some u -> u in let user_cred_opt = ss.slookup user authz in if user_cred_opt = None then failwith "unauthorized user"; let ss = server_del_ctx ss in (* no longer needed *) { ss with ssubstate = `Established; sstate = `OK } let server_process_response ss msg = let ss = svalidity ss in try if ss.sstate <> `Wait then raise Not_found; match ss.ssubstate with | `Acc_context -> server_process_response_accept_context ss msg | `Neg_security1 -> server_process_response_neg_security1 ss msg | `Neg_security2 -> server_process_response_neg_security2 ss msg | `Established -> raise Not_found with | Not_found -> let ss = server_del_ctx ss in { ss with sstate = `Auth_error "unspecified" } | Failure msg -> let ss = server_del_ctx ss in { ss with sstate = `Auth_error msg } let server_process_response_restart ss msg set_stale = failwith "Netmech_krb5_sasl.server_process_response_restart: \ not available" let server_emit_challenge ss = if ss.sstate <> `Emit then failwith "Netmech_krb5_sasl.server_emit_challenge: bad state"; ( { (svalidity ss) with sstate = `Wait }, ss.stoken ) let server_channel_binding ss = `None let server_stash_session ss = (* GSSAPI does not support that unfinished contexts are exported. We do not need the context anyway after session establishment, so we don't save it at all. *) if ss.sstate <> `OK then failwith "Netmech_krb5_sasl.server_stash_session: the session \ must be established (implementation restriction)"; "server,t=GSSAPI;" ^ Marshal.to_string (ss.suser, ss.sauthz, ss.sservice, ss.srealm, map_opt Netsys_gssapi.marshal_server_props ss.sprops ) [] let ss_re = Netstring_str.regexp "server,t=GSSAPI;" let server_resume_session ~lookup s = match Netstring_str.string_match ss_re s 0 with | None -> failwith "Netmech_krb5_sasl.server_resume_session" | Some m -> let p = Netstring_str.match_end m in let data = String.sub s p (String.length s - p) in let (suser, sauthz, sservice, srealm, mprops) = Marshal.from_string data 0 in { scontext = None; sstate = `OK; ssubstate = `Established; stoken = ""; suser; sauthz; slookup = lookup; sservice; srealm; scred = G.interface#no_credential; sconf = Netsys_gssapi.create_server_config(); sprops = map_opt Netsys_gssapi.unmarshal_server_props mprops; } let server_session_id ss = None let server_prop ss key = raise Not_found let server_gssapi_props ss = match ss.sprops with | None -> raise Not_found | Some p -> p let server_user_name ss = if ss.sstate <> `OK then raise Not_found; match ss.suser with | None -> assert false | Some u -> u let server_authz_name ss = if ss.sstate <> `OK then raise Not_found; match ss.sauthz with | None -> assert false | Some u -> u end (* Works only when "test" is added to /etc/services! KRB5_KTNAME=test.keytab OCAMLPATH=src ledit ocaml #use "topfind";; #require "netstring,netgss-system";; open Printf;; module S = Netmech_krb5_sasl.Krb5_gs1(Netgss.System);; let no_creds = S.init_credentials [];; let cs = S.create_client_session ~user:"" ~authz:"foo" ~creds:no_creds ~params:[ "gssapi-acceptor", "test@office1.lan.sumadev.de", false ] ();; let lookup user authz = eprintf "user=%S authz=%S\n%!" user authz; Some no_creds;; let ss = S.create_server_session ~lookup ~params:["gssapi-acceptor-service", "test", false ] ();; let cs, msg1 = S.client_emit_response cs;; let ss = S.server_process_response ss msg1;; let ss, msg2 = S.server_emit_challenge ss;; let cs = S.client_process_challenge cs msg2;; let cs, msg3 = S.client_emit_response cs;; let ss = S.server_process_response ss msg3;; let ss, msg4 = S.server_emit_challenge ss;; let cs = S.client_process_challenge cs msg4;; let cs, msg5 = S.client_emit_response cs;; assert(S.client_state cs = `OK);; let ss = S.server_process_response ss msg5;; assert(S.server_state ss = `OK);; *) ocamlnet-4.1.2/src/netstring/netxdr_mstring.ml0000644000175000017500000002514012731530350020152 0ustar gerdgerd(* $Id$ *) open Netsys_mem class type mstring = object method length : int method blit_to_bytes : int -> Bytes.t -> int -> int -> unit method blit_to_string : int -> Bytes.t -> int -> int -> unit method blit_to_memory : int -> memory -> int -> int -> unit method as_bytes : Bytes.t * int method as_string : string * int method as_memory : memory * int method preferred : [ `Memory | `Bytes ] end (* This def must be the same as the one in Netsys_types: *) let _ = (fun (ms : mstring ) -> (ms : Netsys_types.mstring)) class type mstring_factory = object method create_from_string : string -> int -> int -> bool -> mstring method create_from_bytes : Bytes.t -> int -> int -> bool -> mstring method create_from_memory : memory -> int -> int -> bool -> mstring end type named_mstring_factories = (string, mstring_factory) Hashtbl.t let bbm s pos len : mstring = if len < 0 || pos < 0 || pos > Bytes.length s - len then invalid_arg "Netxdr_mstring.bbm"; ( object(self) method length = len method blit_to_bytes mpos u upos l = if l < 0 then invalid_arg "Netxdr_mstring#blit_to_bytes"; if mpos < 0 || mpos > len - l then invalid_arg "Netxdr_mstring#blit_to_bytes"; if upos < 0 || upos > Bytes.length u - l then invalid_arg "Netxdr_mstring#blit_to_bytes"; Bytes.blit s (pos+mpos) u upos l method blit_to_string = self # blit_to_bytes method blit_to_memory mpos u upos l = if l < 0 then invalid_arg "Netxdr_mstring#blit_to_memory"; if mpos < 0 || mpos > len - l then invalid_arg "Netxdr_mstring#blit_to_memory"; if upos < 0 || upos > Bigarray.Array1.dim u - l then invalid_arg "Netxdr_mstring#blit_to_memory"; Netsys_mem.blit_bytes_to_memory s (pos+mpos) u upos l method as_bytes = (s,pos) method as_string = (Bytes.sub_string s pos len,0) method as_memory = let m = Bigarray.Array1.create Bigarray.char Bigarray.c_layout len in Netsys_mem.blit_bytes_to_memory s pos m 0 len; (m,0) method preferred = `Bytes end ) let mbm m pos len : mstring = if len < 0 || pos < 0 || pos > Bigarray.Array1.dim m - len then invalid_arg "Netxdr_mstring.mbm"; ( object(self) method length = len method blit_to_bytes mpos u upos l = if l < 0 then invalid_arg "Netxdr_mstring#blit_to_bytes"; if mpos < 0 || mpos > len - l then invalid_arg "Netxdr_mstring#blit_to_bytes"; if upos < 0 || upos > Bytes.length u - l then invalid_arg "Netxdr_mstring#blit_to_bytes"; Netsys_mem.blit_memory_to_bytes m (pos+mpos) u upos l method blit_to_string = self # blit_to_bytes method blit_to_memory mpos u upos l = if l < 0 then invalid_arg "Netxdr_mstring#blit_to_memory"; if mpos < 0 || mpos > len - l then invalid_arg "Netxdr_mstring#blit_to_memory"; if upos < 0 || upos > Bigarray.Array1.dim u - l then invalid_arg "Netxdr_mstring#blit_to_memory"; Bigarray.Array1.blit (Bigarray.Array1.sub m (pos+mpos) l) (Bigarray.Array1.sub u upos l) method as_bytes = let s = Bytes.create len in Netsys_mem.blit_memory_to_bytes m pos s 0 len; (s,0) method as_string = let (b,p) = self # as_bytes in (Bytes.unsafe_to_string b,p) method as_memory = (m,pos) method preferred = `Memory end ) let bytes_based_mstrings : mstring_factory = ( object method create_from_string s pos len must_copy = let b = Bytes.create len in Bytes.blit_string s pos b 0 len; bbm b 0 len method create_from_bytes s pos len must_copy = if must_copy then bbm (Bytes.sub s pos len) 0 len else bbm s pos len method create_from_memory m pos len must_copy = let s = Bytes.create len in Netsys_mem.blit_memory_to_bytes m pos s 0 len; bbm s 0 len end ) let string_based_mstrings = bytes_based_mstrings let string_to_mstring ?(pos=0) ?len s = let s_len = String.length s in let len = match len with Some n -> n | None -> s_len - pos in bytes_based_mstrings # create_from_string s pos len false let bytes_to_mstring ?(pos=0) ?len s = let s_len = Bytes.length s in let len = match len with Some n -> n | None -> s_len - pos in bytes_based_mstrings # create_from_bytes s pos len false let memory_based_mstrings_1 create : mstring_factory = ( object method create_from_string s pos len must_copy = let m = create len in Netsys_mem.blit_string_to_memory s pos m 0 len; mbm m 0 len method create_from_bytes s pos len must_copy = let m = create len in Netsys_mem.blit_bytes_to_memory s pos m 0 len; mbm m 0 len method create_from_memory m pos len must_copy = if must_copy then ( let m' = create len in Bigarray.Array1.blit (Bigarray.Array1.sub m pos len) (Bigarray.Array1.sub m' 0 len); mbm m' 0 len ) else mbm m pos len end ) let memory_based_mstrings = memory_based_mstrings_1 (Bigarray.Array1.create Bigarray.char Bigarray.c_layout) let memory_to_mstring ?(pos=0) ?len m = let m_len = Bigarray.Array1.dim m in let len = match len with Some n -> n | None -> m_len - pos in memory_based_mstrings # create_from_memory m pos len false let paligned_memory_based_mstrings = memory_based_mstrings_1 (fun n -> Netsys_mem.alloc_memory_pages n ) let memory_pool_based_mstrings pool = memory_based_mstrings_1 (fun n -> if n <= Netsys_mem.pool_block_size pool then Netsys_mem.pool_alloc_memory pool else failwith "memory_pool_based_mstrings: string too large for pool" ) let length_mstrings mstrings = List.fold_left (fun acc ms -> acc + ms#length) 0 mstrings let concat_mstrings_bytes (mstrings : mstring list) = match mstrings with | [] -> Bytes.create 0 | _ -> let length = length_mstrings mstrings in let s = Bytes.create length in let p = ref 0 in List.iter (fun ms -> let l = ms#length in ms # blit_to_bytes 0 s !p l; p := !p + l ) mstrings; s let concat_mstrings mstrings = Bytes.unsafe_to_string (concat_mstrings_bytes mstrings) let prefix_mstrings_bytes mstrings n = let length = length_mstrings mstrings in if n < 0 || n > length then failwith "prefix_mstrings"; let s = Bytes.create n in let p = ref 0 in ( try List.iter (fun ms -> if !p >= n then raise Exit; let l = ms#length in let l' = min l (n - !p) in ms # blit_to_bytes 0 s !p l'; p := !p + l' ) mstrings with Exit -> () ); s let prefix_mstrings mstrings n = Bytes.unsafe_to_string (prefix_mstrings_bytes mstrings n) let blit_mstrings_to_memory mstrings mem = let length = length_mstrings mstrings in if length > Bigarray.Array1.dim mem then failwith "blit_mstrings_to_memory"; let p = ref 0 in List.iter (fun ms -> let l = ms#length in ms # blit_to_memory 0 mem !p l; p := !p + l ) mstrings let shared_sub_mstring (ms : mstring) sub_pos sub_len : mstring = (* Returns an mstring that accesses the substring of ms at sub_pos with length sub_len. The returned mstring shares the representation with ms *) let ms_len = ms#length in if sub_len < 0 || sub_pos < 0 || sub_pos > ms_len - sub_len then invalid_arg "Netxdr_mstring.shared_sub_mstring"; ( object(self) method length = sub_len method blit_to_bytes mpos s spos len = ms#blit_to_bytes (sub_pos+mpos) s spos len method blit_to_string = self#blit_to_bytes method blit_to_memory mpos mem mempos len = ms#blit_to_memory (sub_pos+mpos) mem mempos len method as_bytes = let (s,pos) = ms#as_bytes in (s,pos+sub_pos) method as_string = let (s,pos) = ms#as_string in (s,pos+sub_pos) method as_memory = let (m,pos) = ms#as_memory in (m,pos+sub_pos) method preferred = ms#preferred end ) let shared_sub_mstrings l sub_pos sub_len = let l_len = length_mstrings l in if sub_len < 0 || sub_pos < 0 || sub_pos > l_len - sub_len then invalid_arg "Netxdr_mstring.shared_sub_mstrings"; let sub_pos' = sub_pos + sub_len in let rec map l pos = match l with | ms :: l' -> let len = ms#length in let pos' = pos+len in let cond1 = pos' > sub_pos in let cond2 = pos < sub_pos' in if cond1 && cond2 && len > 0 then ( let ms' = if pos < sub_pos then let q = min (pos' - sub_pos) sub_len in shared_sub_mstring ms (sub_pos - pos) q else if pos' > sub_pos' then shared_sub_mstring ms 0 (sub_pos' - pos) else ms in ms' :: map l' pos' ) else map l' pos' | [] -> [] in map l 0 let copy_mstring ms = let len = ms#length in match ms#preferred with | `Bytes -> let (s, pos) = ms#as_string in string_based_mstrings#create_from_string s pos len true | `Memory -> let (m, pos) = ms#as_memory in memory_based_mstrings#create_from_memory m pos len true let copy_mstrings l = List.map copy_mstring l let in_channel_of_mstrings ms_list = let ms_list = ref ms_list in let ms_pos = ref 0 in let in_pos = ref 0 in ( object(self) inherit Netchannels.augment_raw_in_channel method input s pos len = match !ms_list with | [] -> raise End_of_file | ms :: ms_list' -> let ms_len = ms#length in if !ms_pos >= ms_len then ( ms_list := ms_list'; ms_pos := 0; self # input s pos len ) else ( match ms#preferred with | `Bytes -> let (u,start) = ms#as_string in let n = min len ms_len in String.blit u start s pos n; ms_pos := !ms_pos + n; in_pos := !in_pos + n; n | `Memory -> let (m,start) = ms#as_memory in let n = min len ms_len in Netsys_mem.blit_memory_to_bytes m start s pos n; ms_pos := !ms_pos + n; in_pos := !in_pos + n; n ) method close_in() = () method pos_in = !in_pos end ) let mstrings_of_in_channel ch = let len = 1024 in let acc = ref [] in let buf = ref (Bytes.create len) in let pos = ref 0 in let rec loop() : unit = let n = ch # input !buf !pos (len - !pos) in (* or End_of_file *) pos := !pos + n; if !pos < len then loop() else ( acc := bytes_to_mstring !buf :: !acc; buf := Bytes.create len; pos := 0; loop() ) in try loop(); assert false with End_of_file -> if !pos > 0 then acc := bytes_to_mstring ~pos:0 ~len:!pos !buf :: !acc; List.rev !acc ocamlnet-4.1.2/src/netstring/netdate.ml0000644000175000017500000007622312731530350016537 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (* Thanks to Nicolas George for contributing the parsing and format code *) open Printf (* Calculate local zone offset in minutes *) let get_localzone_at t = let gt = Unix.gmtime t and lt = Unix.localtime t in let min_diff = (lt.Unix.tm_hour * 60 + lt.Unix.tm_min) - (gt.Unix.tm_hour * 60 + gt.Unix.tm_min) in let day_diff = lt.Unix.tm_yday - gt.Unix.tm_yday in if day_diff < -1 || day_diff = 1 then (* local day is UTC day + 1 *) min_diff + 24*60 else if day_diff > 1 || day_diff = -1 then (* local day is UTC day - 1 *) min_diff - 24*60 else (* local day is UTC day *) min_diff ;; let get_localzone() = get_localzone_at (Unix.time()) ;; let localzone_nodst = (* Get the timezone on 01-01-1970 and on 01-07-1970, and take the smaller one. This hopefully works on the northern and southern hemisphere *) min (get_localzone_at 0.0) (get_localzone_at 15638400.0) ;; let localzone = get_localzone() ;; type localization = { full_day_names : string array; abbr_day_names : string array; parsed_day_names : string list array; full_month_names : string array; abbr_month_names : string array; parsed_month_names : string list array; timezone_names : (string * int * bool) list; am_particle : string; pm_particle : string; d_format : string; t_format : string; d_t_format : string; t_format_ampm : string; char_encoding : string; } let posix_l9n = { full_day_names = [| "Sunday"; "Monday"; "Tuesday"; "Wednesday"; "Thursday"; "Friday"; "Saturday" |]; abbr_day_names = [| "Sun"; "Mon"; "Tue"; "Wed"; "Thu"; "Fri"; "Sat" |] ; parsed_day_names = [| [ "sunday"; "sun" ]; [ "monday"; "mon" ]; [ "tuesday"; "tue"; "tues" ]; [ "wednesday"; "wed"; "wednes" ]; [ "thursday"; "thu"; "thur"; "thurs" ]; [ "friday"; "fri" ]; [ "saturday"; "sat" ]; |]; full_month_names = [| "January"; "February"; "March"; "April"; "May"; "June"; "July"; "August"; "September"; "October"; "November"; "December" |]; abbr_month_names = [| "Jan"; "Feb"; "Mar"; "Apr"; "May"; "Jun"; "Jul"; "Aug"; "Sep"; "Oct"; "Nov"; "Dec" |]; parsed_month_names = [| [ "january"; "jan" ]; [ "february"; "feb" ]; [ "march"; "mar" ]; [ "april"; "apr" ]; [ "may"; "may" ]; [ "june"; "jun" ]; [ "july"; "jul" ]; [ "august"; "aug" ]; [ "september"; "sep"; "sept" ]; [ "october"; "oct" ]; [ "november"; "nov" ]; [ "december"; "dec" ] |]; timezone_names = (* For a more complete list see http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations We HAVE to implement the timezones mentioned in RFC-822 *) ( let z n = (n/100) * 60 in [ "gmt", z 0000, false; "ut", z 0000, false; "utc", z 0000, false; "wet", z 0000, false; "z", z 0000, false; "bst", z 0100, true; "cet", z 0100, false; "cest", z 0200, true; "met", z 0100, false; "mewt", z 0100, false; "mest", z 0200, true; "mesz", z 0200, true; "swt", z 0100, false; "sst", z 0200, true; "fwt", z 0100, false; "fst", z 0100, true; "eet", z 0200, false; "bt", z 0300, false; "zp4", z 0400, false; "zp5", z 0500, false; "zp6", z 0600, false; "wast", z 0700, false; "wadt", z 0800, true; "cct", z 0800, false; "jst", z 0900, false; "east", z 1000, false; "eadt", z 1100, true; "gst", z 1000, false; "nzt", z 1200, false; "nzst", z 1200, false; "nzdt", z 1300, true; "idle", z 1200, false; "idlw", z(-1200), false; "nt", z(-1100), false; "hst", z(-1000), false; "hdt", z(-0900), true; "cat", z(-1000), false; "ahst", z(-1000), false; "ydt", z(-0800), true; "yst", z(-0900), false; "pst", z(-0800), false; "pdt", z(-0700), true; "mst", z(-0700), false; "mdt", z(-0600), true; "cst", z(-0600), false; "cdt", z(-0500), true; "est", z(-0500), false; "edt", z(-0400), true; "ast", z(-0400), false; "adt", z(-0300), true; "wat", z(-0100), false; "at", z(-0200), false; ]); am_particle = "am"; pm_particle = "pm"; d_format = "%m/%d/%y"; t_format = "%H:%M:%S"; d_t_format = "%a %b %e %H:%M:%S %Y"; t_format_ampm = "%I:%M:%S %p"; char_encoding = "US-ASCII"; } let l9n_from_locale name = let open Netsys_posix in try let info = Netsys_posix.query_langinfo name in let enc = Netconversion.encoding_of_string info.nl_CODESET in let to_lower = Netconversion.ustring_to_lower enc in { full_day_names = [| info.nl_DAY_1; info.nl_DAY_2; info.nl_DAY_3; info.nl_DAY_4; info.nl_DAY_5; info.nl_DAY_6; info.nl_DAY_7; |]; abbr_day_names = [| info.nl_ABDAY_1; info.nl_ABDAY_2; info.nl_ABDAY_3; info.nl_ABDAY_4; info.nl_ABDAY_5; info.nl_ABDAY_6; info.nl_ABDAY_7; |]; parsed_day_names = [| [ to_lower info.nl_DAY_1; to_lower info.nl_ABDAY_1 ]; [ to_lower info.nl_DAY_2; to_lower info.nl_ABDAY_2 ]; [ to_lower info.nl_DAY_3; to_lower info.nl_ABDAY_3 ]; [ to_lower info.nl_DAY_4; to_lower info.nl_ABDAY_4 ]; [ to_lower info.nl_DAY_5; to_lower info.nl_ABDAY_5 ]; [ to_lower info.nl_DAY_6; to_lower info.nl_ABDAY_6 ]; [ to_lower info.nl_DAY_7; to_lower info.nl_ABDAY_7 ]; |]; full_month_names = [| info.nl_MON_1; info.nl_MON_2; info.nl_MON_3; info.nl_MON_4; info.nl_MON_5; info.nl_MON_6; info.nl_MON_7; info.nl_MON_8; info.nl_MON_9; info.nl_MON_10; info.nl_MON_11; info.nl_MON_12; |]; abbr_month_names = [| info.nl_ABMON_1; info.nl_ABMON_2; info.nl_ABMON_3; info.nl_ABMON_4; info.nl_ABMON_5; info.nl_ABMON_6; info.nl_ABMON_7; info.nl_ABMON_8; info.nl_ABMON_9; info.nl_ABMON_10; info.nl_ABMON_11; info.nl_ABMON_12; |]; parsed_month_names = [| [ to_lower info.nl_MON_1; to_lower info.nl_ABMON_1 ]; [ to_lower info.nl_MON_2; to_lower info.nl_ABMON_2 ]; [ to_lower info.nl_MON_3; to_lower info.nl_ABMON_3 ]; [ to_lower info.nl_MON_4; to_lower info.nl_ABMON_4 ]; [ to_lower info.nl_MON_5; to_lower info.nl_ABMON_5 ]; [ to_lower info.nl_MON_6; to_lower info.nl_ABMON_6 ]; [ to_lower info.nl_MON_7; to_lower info.nl_ABMON_7 ]; [ to_lower info.nl_MON_8; to_lower info.nl_ABMON_8 ]; [ to_lower info.nl_MON_9; to_lower info.nl_ABMON_9 ]; [ to_lower info.nl_MON_10; to_lower info.nl_ABMON_10 ]; [ to_lower info.nl_MON_11; to_lower info.nl_ABMON_11 ]; [ to_lower info.nl_MON_12; to_lower info.nl_ABMON_12 ]; |]; timezone_names = posix_l9n.timezone_names; am_particle = to_lower info.nl_AM_STR; pm_particle = to_lower info.nl_PM_STR; d_format = info.nl_D_FMT; t_format = info.nl_T_FMT; d_t_format = info.nl_D_T_FMT; t_format_ampm = info.nl_T_FMT_AMPM; char_encoding = info.nl_CODESET } with | _ -> posix_l9n type token = | Number of int * int (* number of digits, value *) | Day of int | Month of int | Meridian of bool | Zone of int * bool | Dst | Plus | Minus | Comma | Colon | Slash | Dot | Time (* "T" *) | Invalid ;; type compiled_localization = { l9n : localization; tokens : (string, token) Hashtbl.t } let compile_l9n l9n = let tokens = Hashtbl.create 53 in let add_token (name, value) = Hashtbl.replace tokens name value in List.iter (fun (name,zone,isdst) -> add_token (name, (Zone(zone,isdst))) ) l9n.timezone_names; add_token (l9n.am_particle, Meridian false); add_token (l9n.pm_particle, Meridian true); Array.iteri (fun i names -> List.iter (fun name -> add_token (name, Month(i+1)) ) names ) l9n.parsed_month_names; Array.iteri (fun i names -> List.iter (fun name -> add_token (name, Day i) ) names ) l9n.parsed_day_names; add_token ("t", Time); add_token ("dst", Dst); { l9n = l9n; tokens = tokens } let c_posix_l9n = compile_l9n posix_l9n let rec ten_power n = if n<=0 then 1 else 10 * (ten_power (n-1)) let to_lower cl9n = try let enc = Netconversion.encoding_of_string cl9n.l9n.char_encoding in fun s -> Netconversion.ustring_to_lower enc s with _ -> (fun s -> s) let to_upper cl9n = try let enc = Netconversion.encoding_of_string cl9n.l9n.char_encoding in fun s -> Netconversion.ustring_to_upper enc s with _ -> (fun s -> s) let stream_cons prefix stream = (* Prefix the list [prefix] before stream *) let prefix = ref prefix in Stream.from (fun _ -> match !prefix with | [] -> ( try Some(Stream.next stream) with Stream.Failure -> None ) | p :: prefix' -> prefix := prefix'; Some p ) let stream_njunk n stream = for k = 1 to n do Stream.junk stream done let tokens_of_string cl9n str = let to_lower = to_lower cl9n in let rec scan_any stream = match Stream.peek stream with | Some('0'..'9' as c) -> Stream.junk stream; scan_number (1, int_of_char c - 48) stream | Some(('a'..'z' | 'A'..'Z' | '\128'..'\255') as c) -> Stream.junk stream; let b = Buffer.create 16 in Buffer.add_char b c; scan_word b stream | Some '(' -> Stream.junk stream; scan_comment 0 stream | Some (' ' | '\t') -> Stream.junk stream; scan_any stream | Some '+' -> Stream.junk stream; stream_cons [ Plus ] (scan_any stream) | Some '-' -> Stream.junk stream; stream_cons [ Minus ] (scan_any stream) | Some ':' -> Stream.junk stream; stream_cons [ Colon ] (scan_any stream) | Some ',' -> Stream.junk stream; stream_cons [ Comma ] (scan_any stream) | Some '/' -> Stream.junk stream; stream_cons [ Slash ] (scan_any stream) | Some '.' -> Stream.junk stream; stream_cons [ Dot ] (scan_any stream) | Some _ -> Stream.junk stream; stream_cons [ Invalid ] (scan_any stream) | None -> Stream.of_list [] and scan_number (l,a) stream = match Stream.peek stream with | Some ( ('0'..'9') as c ) -> Stream.junk stream; if l = 9 then failwith "Netdate: number too large"; scan_number (l+1, a * 10 + (int_of_char c - 48)) stream | _ -> stream_cons [ Number(l,a) ] (scan_any stream) and scan_word b stream = match Stream.peek stream with | Some(('a'..'z' | 'A'..'Z' | '\128'..'\255') as c) -> Stream.junk stream; Buffer.add_char b c; scan_word b stream | Some '.' -> Stream.junk stream; scan_word b stream | _ -> let s = to_lower (Buffer.contents b) in let tok = try Hashtbl.find cl9n.tokens s with Not_found -> Invalid in stream_cons [ tok ] (scan_any stream) and scan_comment n stream = match Stream.peek stream with | Some ')' -> Stream.junk stream; if n=0 then scan_any stream else scan_comment (n-1) stream | Some '(' -> Stream.junk stream; scan_comment (n+1) stream | Some _ -> Stream.junk stream; scan_comment n stream | None -> raise Stream.Failure in scan_any (Stream.of_string str) ;; type t = { year : int; (* complete year *) month : int; (* 1..12 *) day : int; (* 1..31 *) hour : int; minute : int; second : int; nanos : int; zone : int; (* in minutes; 60 = UTC+0100 *) week_day : int (* 0 = sunday; -1 if not given *) } ;; let parse ?(localzone=false) ?zone:dzone ?(l9n = c_posix_l9n) str = let invalid() = invalid_arg "Netdate.parse" in let tokens = tokens_of_string l9n str in let hour = ref None and minute = ref None and second = ref None and nanos = ref None and zone = ref None and week_day = ref None and day = ref None and month = ref None and year = ref None in let add_data ?h ?m ?s ?ns ?mdn ?tz ?wd ?md ?mo ?y ?y2 () = (* tz as in the above table *) let may_store r = function | None -> () | v when !r = None -> r := v | _ -> invalid() in let h = match h with | None -> None | Some h -> match mdn with | None when h >= 0 && h <= 23 -> Some h | Some false when h > 0 && h <= 11 -> Some h | Some false when h = 12 -> Some 0 | Some true when h > 0 && h <= 11 -> Some (h + 12) | Some true when h = 12 -> Some 12 | _ -> invalid() in let y = match y with | None -> ( match y2 with | Some y -> if y < 69 then Some (2000 + y) else Some(1900 + y) | None -> None ) | Some y -> Some y in may_store hour h; may_store minute m; may_store second s; may_store nanos ns; may_store zone tz; may_store week_day wd; may_store day md; may_store month mo; may_store year y in let rec scan_gen stream = match Stream.peek stream with | Some(Number(l,n)) -> Stream.junk stream; scan_number (l,n) stream | Some Time -> Stream.junk stream; let tok1 = Stream.next stream in let tok2 = Stream.next stream in let tok3 = Stream.next stream in ( match tok1,tok2,tok3 with | Number((0|1|2),n), Colon, Number((0|1|2),m) -> scan_hour n m stream | _ -> invalid() ) | Some(Zone(tz,isdst)) -> Stream.junk stream; let dst = scan_dst stream in let eff_tz = if isdst then tz else match dst with | Some true -> tz + 60 | _ -> tz in add_data ~tz:eff_tz (); scan_gen stream | Some(Day wd) -> Stream.junk stream; let _ = scan_opt_coma stream in add_data ~wd (); scan_gen stream | Some(Month mo) -> Stream.junk stream; let tok1 = Stream.next stream in ( match tok1 with | Number(lmd,md) -> scan_date_m mo (lmd,md) stream | _ -> invalid() ) | Some _ -> Stream.junk stream; invalid() | None -> () and scan_number (l,n) stream = match Stream.peek stream with | Some(Meridian mdn) -> Stream.junk stream; add_data ~h:n ~mdn (); scan_gen stream | Some Colon -> Stream.junk stream; let tok1 = Stream.next stream in ( match tok1 with | Number((0|1|2),m) -> if l <= 2 then scan_hour n m stream else invalid() | _ -> invalid() ) | Some Slash -> Stream.junk stream; let tok1 = Stream.next stream in ( match tok1 with | Number((0|1|2),m) -> scan_date_s (l,n) m stream | _ -> invalid() ) | Some Dot -> Stream.junk stream; let tok1 = Stream.next stream in ( match tok1 with | Number((0|1|2),m) -> if l<=2 then scan_date_dot n m stream else invalid() | _ -> invalid() ) | Some Minus -> Stream.junk stream; scan_date_d (l,n) stream | Some (Month mo) -> Stream.junk stream; add_data ~md:n ~mo (); scan_gen stream | _ -> if l=4 then add_data ~y:n () else invalid(); scan_gen stream and scan_hour h m stream = match Stream.peek stream with | Some Colon -> Stream.junk stream; let tok1 = Stream.next stream in ( match tok1 with | Number(_,s) -> scan_hour_second_frac h m s stream | _ -> invalid() ) | _ -> let tz_opt = scan_tz_opt stream in ( match tz_opt with | Some tz -> add_data ~h ~m ~tz (); scan_gen stream | None -> let mdn = scan_opt_meridian stream in add_data ~h ~m ?mdn (); scan_gen stream ) and scan_tz_opt stream = match Stream.peek stream with | Some Plus -> Stream.junk stream; Some(scan_tz_details 1 stream) | Some Minus -> Stream.junk stream; Some(scan_tz_details (-1) stream) | _ -> None and scan_tz_details sign stream = match Stream.peek stream with | Some(Number(l,tz)) when l=4 -> Stream.junk stream; sign * ((tz/100) * 60 + (tz mod 100)) | Some(Number(l,tz)) when l<=2 -> Stream.junk stream; scan_tz_details2 sign tz stream | _ -> invalid() and scan_tz_details2 sign tz1 stream = match Stream.npeek 2 stream with | [ Colon; Number((0|1|2),tz2) ] -> stream_njunk 2 stream; sign * (60 * tz1 + tz2) | _ -> sign * 60 * tz1 and scan_hour_second_frac h m s stream = match Stream.npeek 2 stream with | [ Dot; Number(l,f) ] -> (* e.g. 12:50:48.12345 *) stream_njunk 2 stream; let ns = f * ten_power (9-l) in scan_hour_second h m s ns stream | _ -> scan_hour_second h m s 0 stream and scan_hour_second h m s ns stream = match scan_tz_opt stream with | Some tz -> add_data ~h ~m ~s ~ns ~tz (); scan_gen stream | None -> let mdn = scan_opt_meridian stream in add_data ~h ~m ~s ~ns ?mdn (); scan_gen stream and scan_date_s (ln,n) m stream = match Stream.npeek 2 stream with | [ Slash; Number(lp,p) ] -> stream_njunk 2 stream; if ln = 4 then add_data ~y:n ~mo:m ~md:p () else if lp = 4 then add_data ~y:p ~mo:n ~md:m () else if lp = 2 then add_data ~y2:p ~mo:n ~md:m () else invalid(); scan_gen stream | _ -> add_data ~mo:n ~md:m (); scan_gen stream and scan_date_dot n m stream = match Stream.npeek 2 stream with | [ Dot; Number(l,p) ] -> stream_njunk 2 stream; if l=4 then add_data ~md:n ~mo:m ~y: p () else if l=2 then add_data ~md:n ~mo:m ~y2: p () else invalid(); scan_gen stream | _ -> add_data ~md:n ~mo:m (); scan_gen stream and scan_date_d (ln,n) stream = match Stream.npeek 3 stream with | [ Number(_,mo); Minus; Number(_,md) ] -> stream_njunk 3 stream; if ln=4 then add_data ~y:n ~mo ~md () else if ln=2 then add_data ~y2:n ~mo ~md () else invalid(); scan_gen stream | [ Month mo; Minus; Number(ly,y) ] -> stream_njunk 3 stream; if ly=4 then add_data ~y ~mo ~md:n () else if ly=2 then add_data ~y2:y ~mo ~md:n () else invalid(); scan_gen stream | _ -> invalid() and scan_date_m mo (lmd,md) stream = match Stream.npeek 2 stream with | [ Comma; Number(4,y) ] -> stream_njunk 2 stream; add_data ~y ~mo ~md (); scan_gen stream | _ -> add_data ~mo ~md (); scan_gen stream and scan_dst stream = match Stream.peek stream with | Some Dst -> Stream.junk stream; Some true | _ -> None and scan_opt_coma stream = match Stream.peek stream with | Some Comma -> Stream.junk stream; () | _ -> () and scan_opt_meridian stream = match Stream.peek stream with | Some (Meridian mdn) -> Stream.junk stream; Some mdn | _ -> None in (try scan_gen tokens; with | Stream.Error _ -> invalid() | Stream.Failure -> invalid() ); let may_get r = match !r with | None -> invalid() | Some r -> r in let get_default d r = match !r with | None -> d | Some r -> r in let month = may_get month in if month < 1 || month > 12 then invalid(); let date = { year = may_get year; month = month; day = may_get day; hour = get_default 0 hour; minute = get_default 0 minute; second = get_default 0 second; nanos = get_default 0 nanos; zone = get_default (match dzone with None -> 0 | Some z -> z) zone; week_day = get_default (-1) week_day } in if !zone=None && dzone=None && localzone then let tm = { Unix.tm_year = date.year - 1900; tm_mon = date.month - 1; tm_mday = date.day; tm_hour = date.hour; tm_min = date.minute; tm_sec = date.second; tm_wday = 0; tm_yday = 0; tm_isdst = false } in let (_,tm) = Unix.mktime tm in let zone = localzone_nodst + (if tm.Unix.tm_isdst then 60 else 0) in { date with zone = zone } else date ;; let months_start = [| 0; 31; 59; 90; 120; 151; 181; 212; 243; 273; 304; 334 |] ;; let is_leap year = year mod 4 = 0 && (year mod 100 <> 0 || year mod 400 = 0) ;; let since_epoch date = if date.month < 1 || date.month > 12 then invalid_arg "Netdate.since_epoch"; let in_day = float_of_int (date.hour * 3600 + (date.minute - date.zone) * 60 + date.second) in let days = date.year * 365 + (date.year + 3) / 4 - (date.year + 99) / 100 + (date.year + 399) / 400 - 719528 in let days = days + months_start.(date.month - 1) + date.day - 1 in let days = if is_leap date.year && date.month > 2 then days + 1 else days in 86400.0 *. (float_of_int days) +. in_day ;; let since_epoch_timespec date = (since_epoch date, date.nanos) let since_epoch_approx date = since_epoch date +. (float date.nanos) *. 1E-9 let parse_epoch ?l9n ?localzone ?zone str = since_epoch (parse ?l9n ?localzone ?zone str) ;; let parse_epoch_timespec ?l9n ?localzone ?zone str = since_epoch_timespec (parse ?l9n ?localzone ?zone str) ;; let parse_epoch_approx ?l9n ?localzone ?zone str = since_epoch_approx (parse ?l9n ?localzone ?zone str) ;; let billion = 1_000_000_000 let create ?(localzone=false) ?zone ?(nanos=0) time = (* Add nanos to time: *) let t0 = floor time in let ns0 = truncate ( (time -. t0) *. 1E9 ) in let ns1 = if ns0 >= billion - nanos then (nanos-billion)+ns0 else nanos+ns0 in let t1 = if ns0 >= billion - nanos then t0 +. 1.0 else t0 in let zone = match zone with | Some z -> z | None -> if localzone then get_localzone_at t1 else 0 in let t2 = t1 +. (float_of_int (zone * 60)) in let days = floor (t2 /. 86400.0) in let in_day = int_of_float (t2 -. 86400.0 *. days) in let days = days +. 719528.0 in let n400 = floor (days /. 146097.0) in let r400 = int_of_float (days -. n400 *. 146097.0) in let n400 = int_of_float n400 in let (n100, r100) = if r400 < 36525 then (0, r400) else ((r400 - 1) / 36524, (r400 - 1) mod 36524) in let (n4, r4) = if n100 = 0 then (r100 / 1461, r100 mod 1461) else if r100 < 1460 then (0, r100) else ((r100 + 1) / 1461, (r100 + 1) mod 1461) in let (n1, r1) = if n4 = 0 && n100 <> 0 then (r4 / 365, r4 mod 365) else if r4 < 366 then (0, r4) else ((r4 - 1) / 365, (r4 - 1) mod 365) in let year = 400 * n400 + 100 * n100 + 4 * n4 + n1 in let month_start = if is_leap year then fun m -> months_start.(m) + (if m > 1 then 1 else 0) else fun m -> months_start.(m) in let month_guess = r1 / 29 in let month = if month_guess = 12 then 11 else if r1 >= month_start month_guess then month_guess else month_guess - 1 in let second = in_day mod 60 and minutes = in_day / 60 in let minute = minutes mod 60 and hour = minutes / 60 in { year = year; month = month + 1; day = r1 - (month_start month) + 1; hour = hour; minute = minute; second = second; nanos = ns1; zone = zone; week_day = int_of_float (mod_float (days +. 6.0) 7.0) } ;; let week_day date = (* 0..6, relative to timezone *) if date.week_day = (-1) then let t1 = since_epoch date in let t2 = t1 +. (float_of_int (date.zone * 60)) in let days = floor (t2 /. 86400.0) in int_of_float (mod_float (days +. 4.0) 7.0) else date.week_day ;; let year_day date = (* 0..365, relative to timezone *) let is_leap_year = is_leap date.year in months_start.(date.month - 1) + (if date.month >= 3 && is_leap_year then 1 else 0) + date.day - 1 ;; let rec iso8601_week_pair date = let ( % ) a b = if a >= 0 then a mod b else a mod b + b in let d_wday = week_day date in let d_yday = year_day date in let wday_jan_1 = (* wday of jan 1 *) (d_wday - d_yday) % 7 in let shift = if wday_jan_1 = 1 then 7 else (wday_jan_1 - 1) % 7 in let offset = if wday_jan_1 >= 2 && wday_jan_1 <= 4 then 1 else 0 in let week = (d_yday + shift) / 7 + offset in if week = 0 then (* replace with last week of last year *) let date' = { date with year = date.year - 1; month = 12; day = 31; week_day = (-1) } in iso8601_week_pair date' else if week = 53 then (* only if dec 31 is a thu/fri/sat/sun *) let date' = { date with month = 12; day = 31; week_day = (-1) } in let d_wday' = week_day date' in if d_wday' >= 4 || d_wday' = 0 then (53, date.year) else (1, date.year+1) else (week, date.year) let rec format_to ?(l9n=c_posix_l9n) out_ch ~fmt date = let to_lower = to_lower l9n in let to_upper = to_upper l9n in let add_char c = out_ch#output_char c and add_string s = out_ch#output_string s in let fail () = invalid_arg "Netdate.format_to" in let add_digits w b n = if n >= b * 10 then fail (); let rec aux b n = add_char (char_of_int (48 + n / b)); if b >= 10 then aux (b / 10) (n mod b) in if w then ( let rec aux_spaces b = if n >= b || b < 10 then ( aux b n ) else ( add_char ' '; aux_spaces (b / 10) ) in aux_spaces b ) else ( aux b n ) in let wd_lz = lazy (week_day date) in let wd () = Lazy.force wd_lz in let yd_lz = lazy (year_day date) in let yd () = Lazy.force yd_lz in let wp_lz = lazy (iso8601_week_pair date) in let wp() = Lazy.force wp_lz in let rec do_format ?(have_colon=false) ?(precision=0) = function | 'a' -> add_string l9n.l9n.abbr_day_names.( wd() ) | 'A' -> add_string l9n.l9n.full_day_names.( wd() ) | 'b' | 'h' -> add_string l9n.l9n.abbr_month_names.(date.month - 1) | 'B' -> add_string l9n.l9n.full_month_names.(date.month - 1) | 'C' -> add_digits false 10 (date.year / 100) | 'd' -> add_digits false 10 date.day | 'e' -> add_digits true 10 date.day | 'g' -> add_digits false 10 (snd(wp()) mod 10) | 'G' -> add_digits false 1000 (snd(wp())) | 'H' -> add_digits false 10 date.hour | 'I' -> add_digits false 10 (match date.hour mod 12 with 0 -> 12 | d -> d) | 'j' -> add_digits false 100 (yd () + 1) | 'k' -> add_digits true 10 date.hour | 'l' -> add_digits true 10 (match date.hour mod 12 with 0 -> 12 | d -> d) | 'm' -> add_digits false 10 date.month | 'M' -> add_digits false 10 date.minute | 'n' -> add_char '\n' | 'p' -> add_string (if date.hour >= 12 then to_upper l9n.l9n.pm_particle else to_upper l9n.l9n.am_particle ) | 'P' -> add_string (if date.hour >= 12 then to_lower l9n.l9n.pm_particle else to_lower l9n.l9n.am_particle) | 's' -> add_string (string_of_float (since_epoch date)) | 'S' -> add_digits false 10 date.second; if precision > 0 then ( add_char '.'; add_string (sprintf "%0*d" precision (date.nanos / ten_power(9-precision))) ) | 't' -> add_char '\t' | 'u' -> add_digits false 1 (match wd () with 0 -> 7 | n -> n) | 'y' -> add_digits false 10 (date.year mod 100) | 'Y' -> add_digits false 1000 date.year | 'z' | 'Z' -> let (s, z) = if date.zone >= 0 then ('+', date.zone) else ('-', -date.zone) in add_char s; add_digits false 10 (z / 60); if have_colon then add_char ':'; add_digits false 10 (z mod 60) | 'U' -> add_digits false 10 ((yd () - wd () + 7) / 7) | 'V' -> add_digits false 10 (fst(wp())) | 'W' -> let wdm = if wd() = 0 then 6 else wd() - 1 in add_digits false 10 ((yd () - wdm + 7) / 7) | 'w' -> add_digits false 1 (wd ()) | '%' -> add_char '%' | 'c' -> format_to ~l9n out_ch ~fmt:l9n.l9n.d_t_format date | 'F' -> do_format 'Y'; add_char '-'; do_format 'm'; add_char '-'; do_format 'd' | 'x' -> format_to ~l9n out_ch ~fmt:l9n.l9n.d_format date | 'X' -> format_to ~l9n out_ch ~fmt:l9n.l9n.t_format date | 'D' -> do_format 'm'; add_char '/'; do_format 'd'; add_char '/'; do_format 'y' | 'r' -> format_to ~l9n out_ch ~fmt:l9n.l9n.t_format_ampm date | 'R' -> do_format 'H'; add_char ':'; do_format 'M' | 'T' -> do_format 'R'; add_char ':'; do_format 'S' | _ -> fail () in let l_fmt = String.length fmt in let rec aux i = if i = l_fmt then () else match fmt.[i] with | '%' when i = l_fmt - 1 -> fail () | '%' -> if fmt.[i + 1] = ':' then ( if i+2 >= l_fmt then fail(); do_format ~have_colon:true fmt.[i + 2]; aux (i + 3) ) else ( if fmt.[i + 1] = '.' then ( if i+3 >= l_fmt then fail(); match fmt.[i+2] with | '0'..'9' as c -> let d = Char.code c - 48 in do_format ~precision:d fmt.[i + 3]; aux (i + 4) | _ -> fail() ) else ( do_format fmt.[i + 1]; aux (i + 2) ) ) | c -> add_char c; aux (i + 1) in try aux 0 with _ -> fail () ;; let format ?l9n ~fmt date = let b = Buffer.create (String.length fmt * 2) in format_to ?l9n (new Netchannels.output_buffer b) ~fmt date; Buffer.contents b ;; (* The format routines above may want to support internationalization * in the future. The following must use the English conventions * described in the relevant RFCs. *) let mk_date ?localzone ?zone ?nanos ~fmt t = format ~fmt (create ?localzone ?zone ?nanos t) let mk_mail_date ?localzone ?zone t = format "%a, %d %b %Y %H:%M:%S %z" (create ?localzone ?zone t) ;; let mk_usenet_date ?localzone ?zone t = format "%A, %d-%b-%y %H:%M:%S %z" (create ?localzone ?zone t) ;; let mk_internet_date ?localzone ?zone ?(digits=0) t = if digits < 0 || digits > 9 then failwith "Netdate.mk_internet_date: digits out of bounds"; let fmt = sprintf "%%Y-%%m-%%dT%%H:%%M:%%.%dS%%:z" digits in format ~fmt (create ?localzone ?zone t) ;; ocamlnet-4.1.2/src/netstring/netunichar.mli0000644000175000017500000000075412731530350017420 0ustar gerdgerd(* $Id$ *) (** Unicode character information *) val to_lower : int -> int (** Converts the input letter to lowercase. Returns the input unchanged if it is no letter, or there is no lowercase equivalent. This bases on the 1:1 lowercase transformation of letters, and ignores any transformation mapping one letter to several chars. *) val to_upper : int -> int (** Same for uppercase conversion *) val to_title : int -> int (** Same for titlecase conversion *) ocamlnet-4.1.2/src/netstring/netglob_lex.mll0000644000175000017500000001476312731530350017572 0ustar gerdgerd(* $Id$ *) { exception Bracket_Unsupported exception Lexing_Error type bracket_token = Bracket_char of char | Bracket_range of (char * char) | Bracket_code of int (* see Netglob.reparse_bracket_expr *) | Bracket_end type brace_token = Brace_literal of string | Brace_comma | Brace_braces of brace_token list (* inner braces *) | Brace_end type glob_features = { enable_star : bool; enable_qmark : bool; enable_brackets : bool; enable_braces : bool; enable_tilde : bool; enable_escape : bool; mutable escaped : bool; (* after a backslash *) } type glob_token = Glob_literal of string | Glob_star | Glob_qmark | Glob_brackets of (bool * bracket_token list) | Glob_braces of brace_token list | Glob_tilde of string * bool (* whether there is a slash *) | Glob_end type exploded_char = C of char (* An unescaped character *) | E of char (* An escaped character *) | Delim of char (* delimiter *) let rec collect_until end_token parse_fun lexbuf = let tok = parse_fun lexbuf in if tok = end_token then [] else tok :: (collect_until end_token parse_fun lexbuf) let string_of_exploded l = String.concat "" (List.map (function | C c -> String.make 1 c | E c -> String.make 1 c | Delim _ -> "" ) l ) let have_delim l = List.exists (function Delim _ -> true | _ -> false) l } (* bracket_rest: Scans a bracket expression beginning at the second * character (where ']' is always the terminating character) *) rule bracket_rest = parse "[:" [^ ':' ] ":]" { raise Bracket_Unsupported } | "[." [^ '.' ] ".]" { raise Bracket_Unsupported } | "[=" [^ '=' ] "=]" { raise Bracket_Unsupported } | "]" { Bracket_end } | [ ^ ']' ] "-" [^ ']' ] { let c0 = Lexing.lexeme_char lexbuf 0 in let c1 = Lexing.lexeme_char lexbuf 2 in if c0 > '\127' || c1 > '\127' then raise Lexing_Error; if c0 > c1 then raise Lexing_Error; Bracket_range(c0,c1) } | eof { raise Lexing_Error } | [ ^ ']' ] { Bracket_char (Lexing.lexeme_char lexbuf 0) } (* bracket_first: Scans the first token of a bracket expression * (after "[", "[^", or "[!"). * Here, ']' is not recognized as terminating character. *) and bracket_first = parse "[:" [^ ':' ] ":]" { raise Bracket_Unsupported } | "[." [^ '.' ] ".]" { raise Bracket_Unsupported } | "[=" [^ '=' ] "=]" { raise Bracket_Unsupported } | _ "-" [^ ']' ] { let c0 = Lexing.lexeme_char lexbuf 0 in let c1 = Lexing.lexeme_char lexbuf 2 in if c0 > '\127' || c1 > '\127' then raise Lexing_Error; if c0 > c1 then raise Lexing_Error; Bracket_range(c0,c1) } | eof { raise Lexing_Error } | _ { Bracket_char (Lexing.lexeme_char lexbuf 0) } (* brace: Collects material within brace expressions (case: backslash * is escape character *) and brace = parse "}" { Brace_end } | "," { Brace_comma } | "{" { let l = collect_until Brace_end brace lexbuf in Brace_braces l } | '\\' _ { Brace_literal (Lexing.lexeme lexbuf) } | [^ '}' ',' '\\' '{' ] { Brace_literal (Lexing.lexeme lexbuf) } | eof { raise Lexing_Error } | _ { raise Lexing_Error } (* brace_noescape: Used for the case that backslash is not an escape * character *) and brace_noescape = parse "}" { Brace_end } | "," { Brace_comma } | "{" { let l = collect_until Brace_end brace_noescape lexbuf in Brace_braces l } | [^ '}' ',' '{'] { Brace_literal (Lexing.lexeme lexbuf) } | eof { raise Lexing_Error } | _ { raise Lexing_Error } and glob_expr feat = parse "*" { if feat.enable_star && not feat.escaped then Glob_star else ( feat.escaped <- false; Glob_literal "*" ) } | "?" { if feat.enable_qmark && not feat.escaped then Glob_qmark else ( feat.escaped <- false; Glob_literal "?" ) } | "[" [ '!' '^' ]? { if feat.enable_brackets && not feat.escaped then ( let negated = String.length(Lexing.lexeme lexbuf) > 1 in let t0 = bracket_first lexbuf in let l = collect_until Bracket_end bracket_rest lexbuf in Glob_brackets (negated, t0 :: l) ) else ( feat.escaped <- false; Glob_literal (Lexing.lexeme lexbuf) ) } | "{" { if feat.enable_braces && not feat.escaped then ( let p = if feat.enable_escape then brace else brace_noescape in let l = collect_until Brace_end p lexbuf in Glob_braces l ) else ( feat.escaped <- false; Glob_literal "{" ) } | "~" { if (feat.enable_tilde && not feat.escaped && Lexing.lexeme_start lexbuf = 0) then ( let p = if feat.enable_escape then generic_lex_until '/' else generic_lex_noescape_until '/' in let l = p lexbuf in let s = string_of_exploded l in let slash = have_delim l in Glob_tilde(s,slash) ) else ( feat.escaped <- false; Glob_literal "~" ) } | "\\" { if feat.enable_escape && not feat.escaped then ( feat.escaped <- true; Glob_literal "" ) else ( feat.escaped <- false; Glob_literal "\\" ) } | [ ^ '*' '?' '[' '{' '\\' '~' ]+ { feat.escaped <- false; Glob_literal (Lexing.lexeme lexbuf) } | eof { if feat.escaped then raise Lexing_Error; Glob_end } and generic_lex_until c = parse '\\' _ { let char = E (Lexing.lexeme_char lexbuf 1) in char :: generic_lex_until c lexbuf } | _ { let lc = Lexing.lexeme_char lexbuf 0 in if c = lc then [ Delim c ] else ( let char = C lc in char :: generic_lex_until c lexbuf ) } | eof { [] } and generic_lex_noescape_until c = parse | _ { let lc = Lexing.lexeme_char lexbuf 0 in if c = lc then [ Delim c ] else ( let char = C lc in char :: generic_lex_noescape_until c lexbuf ) } | eof { [] } ocamlnet-4.1.2/src/netstring/Makefile.pre0000644000175000017500000000332712731530350017001 0ustar gerdgerdTOP_DIR=../.. include $(TOP_DIR)/Makefile.conf PRE = 1 PKGNAME = netstring GENERATE = netconst.ml netglob_lex.ml \ netunichar.ml netmappings_asn1.ml META CLEAN_LIST += $(GENERATE) NETNUMBER_DEFS = -D WORDSIZE_$(WORD_SIZE) -D HOST_IS_$(ENDIANESS) \ -D USE_NETSYS_XDR PP_OPTIONS = -pp "$(CPPO) $(NETNUMBER_DEFS) $(REGEXP_DEFS) $(PP_BYTES) $(PP_DEPRECATED)" INSTALL_EXTRA = netstring_top.cmo netaccel_link.cmo netaccel.cma netconst.ml: netconst.mlp sed -e 's/@VERSION@/$(VERSION)/' netconst.mlp >netconst.ml unicode_charinfo.txt: ocaml ../../tools/unicode_extract.ml > unicode_charinfo.txt netunichar.ml: unicode_charinfo.txt ocaml ../../tools/unicode_charinfo.ml unicode_charinfo.txt \ > netunichar.ml ASN1_MAPPINGS = ../netunidata/mappings/asn1_*.unimap unimap_to_ocaml = $(TOP_DIR)/tools/unimap_to_ocaml/unimap_to_ocaml # The .pmap files are the distributed files. The .unimap files cannot be # distributed because of license conditions. netmappings_asn1.pmap: $(unimap_to_ocaml) \ -o netmappings_asn1.pmap -pmap $(ASN1_MAPPINGS) netmappings_asn1.ml: netmappings_asn1.pmap $(unimap_to_ocaml) \ -o netmappings_asn1.ml netmappings_asn1.pmap # How I created netsaslprep_data.ml: #netsaslprep_data.ml: tmp/CompositionExclusions-3.2.0.txt \ # tmp/UnicodeData-3.2.0.txt # ocaml str.cma ../../tools/saslprep-extract-from-unicode.ml \ # > netsaslprep_data.ml # #tmp/CompositionExclusions-3.2.0.txt: # mkdir -p tmp # cd tmp && \ # wget 'http://www.unicode.org/Public/3.2-Update/CompositionExclusions-3.2.0.txt' # #tmp/UnicodeData-3.2.0.txt: # mkdir -p tmp # cd tmp && \ # wget 'http://www.unicode.org/Public/3.2-Update/UnicodeData-3.2.0.txt' include $(TOP_DIR)/Makefile.rules ocamlnet-4.1.2/src/netstring/netmime_string.ml0000644000175000017500000015160612731530350020136 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) module S = Netstring_str;; let rec skip_line_ends_poly ops s pos len = let open Netstring_tstring in if len > 0 then match ops.get s pos with | '\010' -> skip_line_ends_poly ops s (pos+1) (len-1) | '\013' -> if len > 1 && ops.get s (pos+1) = '\010' then skip_line_ends_poly ops s (pos+2) (len-2) else pos | _ -> pos else pos let skip_line_ends = skip_line_ends_poly Netstring_tstring.string_ops let rec find_line_end_poly ops s pos len = let open Netstring_tstring in if len > 0 then let k = ops.index_from3 s pos len '\010' '\013' '\013' in match ops.get s k with | '\010' -> k | '\013' -> if (k+1) < pos+len && ops.get s (k+1) = '\010' then k else find_line_end_poly ops s (k+1) (len-(k+1-pos)) | _ -> assert false else raise Not_found let find_line_end = find_line_end_poly Netstring_tstring.string_ops let find_line_start_poly ops s pos len = let open Netstring_tstring in let k = find_line_end_poly ops s pos len in match ops.get s k with | '\010' -> k+1 | '\013' -> k+2 | _ -> assert false let find_line_start = find_line_start_poly Netstring_tstring.string_ops let rec find_double_line_start_poly ops s pos len = let open Netstring_tstring in let pos' = find_line_start_poly ops s pos len in let len' = len - (pos' - pos) in if len' > 0 then match ops.get s pos' with | '\010' -> pos'+1 | '\013' -> if len' > 1 && ops.get s (pos'+1) = '\010' then pos'+2 else find_double_line_start_poly ops s pos' len' | _ -> find_double_line_start_poly ops s pos' len' else raise Not_found let find_double_line_start = find_double_line_start_poly Netstring_tstring.string_ops let fold_lines_p_poly : type s a . s Netstring_tstring.tstring_ops -> (a -> int -> int -> int -> bool -> a) -> a -> s -> int -> int -> a = fun ops f acc0 s pos len -> let e = pos+len in let rec loop acc p = if p < e then ( let p1 = try find_line_end_poly ops s p (e-p) with Not_found -> e in let p2 = try find_line_start_poly ops s p1 (e-p1) with Not_found -> e in let is_last = p2 = e in let acc' = f acc p p1 p2 is_last in loop acc' p2 ) else acc in loop acc0 pos let fold_lines_p f = fold_lines_p_poly Netstring_tstring.string_ops f let fold_lines_poly : type s a . s Netstring_tstring.tstring_ops -> (a -> s -> a) -> a -> s -> int -> int -> a = fun ops f acc0 s pos len -> let open Netstring_tstring in fold_lines_p_poly ops (fun acc p0 p1 p2 is_last -> f acc (ops.sub s p0 (p1-p0)) ) acc0 s pos len let fold_lines f = fold_lines_poly Netstring_tstring.string_ops f let iter_lines_poly ops f s pos len = fold_lines_poly ops (fun _ line -> let () = f line in ()) () s pos len let iter_lines f = iter_lines_poly Netstring_tstring.string_ops f let skip_whitespace_left_poly ops s pos len = let open Netstring_tstring in let e = pos+len in let rec skip_whitespace p = if p < e then ( let c = ops.get s p in match c with | ' ' | '\t' | '\r' | '\n' -> skip_whitespace(p+1) | _ -> p ) else raise Not_found in skip_whitespace pos let skip_whitespace_left = skip_whitespace_left_poly Netstring_tstring.string_ops let skip_whitespace_right s pos len = let rec skip_whitespace p = if p >= pos then ( let c = s.[p] in match c with | ' ' | '\t' | '\r' | '\n' -> skip_whitespace(p-1) | _ -> p ) else raise Not_found in skip_whitespace (pos+len-1) type header_line = | Header_start of string * string (* name, value *) | Header_cont of string (* continued value *) | Header_end (* empty line = header end *) let rec find_colon_poly ops s p e = let open Netstring_tstring in if p < e then ( let c = ops.get s p in match c with | ' ' | '\t' | '\r' | '\n' -> raise Not_found | ':' -> p | _ -> find_colon_poly ops s (p+1) e ) else raise Not_found let parse_header_line ops include_eol skip_ws s p0 p1 p2 is_last = (* p0: start of line p1: position of line terminator p2: position after line terminator is_last: whether last line in the iteration include_eol: whether to include the line terminator in the output string skip_ws: whether to skip whitespace after the ":" Raises Not_found if not parsable. *) let open Netstring_tstring in if p0 = p1 then ( if not is_last then raise Not_found; Header_end ) else ( let c0 = ops.get s p0 in let is_cont = (c0 = ' ' || c0 = '\t' || c0 = '\r') in if is_cont then ( let out = if include_eol then ops.substring s p0 (p2-p0) else ops.substring s p0 (p1-p0) in Header_cont out ) else ( let q = find_colon_poly ops s p0 p1 in let r = if skip_ws then try skip_whitespace_left_poly ops s (q+1) (p1-q-1) with Not_found -> p1 else q+1 in let out_name = ops.substring s p0 (q-p0) in let out_value = if include_eol then ops.substring s r (p2-r) else ops.substring s r (p1-r) in Header_start(out_name,out_value) ) ) let fold_header_poly ?(downcase=false) ?(unfold=false) ?(strip=false) ops f acc0 s pos len = let err k = failwith ("Netmime_string.fold_header [" ^ string_of_int k ^ "]") in let postprocess cur = match cur with | None -> None | Some(n, values) -> let cat_values1 = String.concat "" (List.rev values) in let cat_values2 = if strip then try let k = skip_whitespace_right cat_values1 0 (String.length cat_values1) in String.sub cat_values1 0 (k+1) with Not_found -> cat_values1 else cat_values1 in let n' = if downcase then String.lowercase n else n in Some(n', cat_values2) in let (user, cur, at_end) = fold_lines_p_poly ops (fun (acc_user, acc_cur, acc_end) p0 p1 p2 is_last -> if acc_end then err 1; let hd = try parse_header_line ops (not unfold) strip s p0 p1 p2 is_last with Not_found -> err 2 in match hd with | Header_start(n,v) -> let last_header_opt = postprocess acc_cur in let acc_cur' = Some(n, [v]) in let acc_user' = match last_header_opt with | None -> acc_user | Some(n,v) -> f acc_user n v in (acc_user', acc_cur', false) | Header_cont v -> ( match acc_cur with | None -> err 3 | Some(n, values) -> let acc_cur' = Some (n, (v::values)) in (acc_user, acc_cur', false) ) | Header_end -> let last_header_opt = postprocess acc_cur in let acc_user' = match last_header_opt with | None -> acc_user | Some(n,v) -> f acc_user n v in (acc_user', None, true) ) (acc0, None, false) s pos len in if not at_end then err 4; assert(cur = None); user let fold_header ?downcase ?unfold ?strip f acc0 s pos len = let ops = Netstring_tstring.string_ops in fold_header_poly ?downcase ?unfold ?strip ops f acc0 s pos len let list_header_poly ?downcase ?unfold ?strip ops s pos len = List.rev (fold_header_poly ?downcase ?unfold ?strip ops (fun acc n v -> (n,v) :: acc) [] s pos len ) let list_header ?downcase ?unfold ?strip s pos len = let ops = Netstring_tstring.string_ops in list_header_poly ?downcase ?unfold ?strip ops s pos len let find_end_of_header_poly ops s pos len = (* Returns the position after the header, or raises Not_found *) let open Netstring_tstring in if len > 0 && ops.get s pos='\n' then pos+1 else if len > 1 && ops.get s pos='\r' && ops.get s (pos+1)='\n' then pos+2 else find_double_line_start_poly ops s pos len let find_end_of_header = find_end_of_header_poly Netstring_tstring.string_ops let scan_header_poly ?(downcase=true) ?(unfold=true) ?(strip=false) ops s ~start_pos ~end_pos = let open Netstring_tstring in try let real_end_pos = find_end_of_header_poly ops s start_pos (end_pos-start_pos) in let s = ops.string s in let values = list_header ~downcase ~unfold ~strip:(unfold || strip) s start_pos (real_end_pos - start_pos) in (values, real_end_pos) with | Not_found | Failure _ -> failwith "Netmime_string.scan_header" let scan_header ?downcase ?unfold ?strip s ~start_pos ~end_pos = let ops = Netstring_tstring.string_ops in scan_header_poly ?downcase ?unfold ?strip ops s ~start_pos ~end_pos let scan_header_tstring ?downcase ?unfold ?strip ts ~start_pos ~end_pos = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> scan_header_poly ?downcase ?unfold ?strip ops s ~start_pos ~end_pos ) } ts let read_header ?(downcase=true) ?(unfold=true) ?(strip=false) (s : Netstream.in_obj_stream) = let ops = Netstring_tstring.bytes_ops in let rec search() = try let b = Netbuffer.unsafe_buffer s#window in find_end_of_header_poly ops b 0 s#window_length (* or Not_found *) with | Not_found -> if s#window_at_eof then ( failwith "Netmime_string.read_header"; ); s#want_another_block(); search() in let end_pos = search() in let b = Netbuffer.unsafe_buffer s#window in let l = list_header_poly ~downcase ~unfold ~strip:(unfold || strip) ops b 0 end_pos in s # skip end_pos; l ;; let write1_re = S.regexp "[ \t\r]*\\(\n\\)[ \t\r]*" ;; let write2_re = S.regexp "[ \t\r]*$" (* "$" means here: end of buffer *) ;; let rec wsearch s pos = (* Skip over linear white space *) try let k, r = S.search_forward write1_re s pos in let k_lf = S.group_beginning r 1 in let k_end = S.match_end r in (k, k_lf, k_end) with | Not_found -> (* no LF found *) let k, r = S.search_forward write2_re s pos in let k_end = S.match_end r in (k, k_end, k_end) let ws_re = S.regexp "^[ \t\r\n]*" ;; let write_header ?(soft_eol = "\r\n") ?(eol = "\r\n") ch h = let hd = Buffer.create 120 in List.iter (fun (n,v) -> Buffer.add_string hd (n ^ ": "); let l = String.length v in let pos = ref 0 in ( match S.string_match ws_re v 0 with Some r -> pos := S.match_end r | None -> assert false ); try while !pos < l do let k, k_lf, pos' = wsearch v !pos in (* might raise Not_found *) Buffer.add_substring hd v !pos (k - !pos); if pos' < l then begin (* Before printing linear whitespace, ensure that the line * would not be empty *) if v.[pos'] <> '\n' then begin (* The line would not be empty. Print eol and all found * spaces and TABs, but no CRs. Ensure that there is at least * one space. *) Buffer.add_string hd soft_eol; let found_space = ref false in for i = k_lf + 1 to pos' - 1 do let c = v.[i] in if c = ' ' || c = '\t' then begin Buffer.add_char hd c; found_space := true; end done; if not !found_space then Buffer.add_char hd ' '; end (* else: The line would consist only of whitespace. We simply * drop all of this whitespace. *) end; pos := pos' done; Buffer.add_string hd eol; with Not_found -> assert false (* The reg exp matches always *) ) h; Buffer.add_string hd eol; ch # output_buffer hd ;; type s_token = Atom of string | EncodedWord of ((string * string) * string * string) | QString of string | Control of char | Special of char | DomainLiteral of string | Comment | End ;; type s_option = No_backslash_escaping | Return_comments | Recognize_encoded_words ;; type s_extended_token = { token : s_token; token_pos : int; token_line : int; token_linepos : int; (* Position of the beginning of the line *) token_len : int; mutable token_sep : bool; (* separates adjacent encoded words *) } ;; let get_token et = et.token;; let get_pos et = et.token_pos;; let get_line et = et.token_line;; let get_column et = et.token_pos - et.token_linepos;; let get_length et = et.token_len;; let separates_adjacent_encoded_words et = et.token_sep;; let get_language et = match et.token with EncodedWord((_,lang),_,_) -> lang | _ -> "" ;; let get_decoded_word et = match et.token with Atom s -> s | QString s -> s | Control c -> String.make 1 c | Special c -> String.make 1 c | DomainLiteral s -> s | Comment -> "" | EncodedWord (_, encoding, content) -> ( match encoding with ("Q"|"q") -> Netencoding.Q.decode content | ("B"|"b") -> Netencoding.Base64.decode ~accept_spaces:false content | _ -> failwith "get_decoded_word" ) | End -> failwith "get_decoded_word" ;; let get_charset et = match et.token with EncodedWord ((charset,_), _, _) -> charset | End -> failwith "get_charset" | _ -> "US-ASCII" ;; type scanner_spec = { (* What the user specifies: *) scanner_specials : char list; scanner_options : s_option list; (* Derived from that: *) mutable opt_no_backslash_escaping : bool; mutable opt_return_comments : bool; mutable opt_recognize_encoded_words : bool; mutable is_special : bool array; mutable space_is_special : bool; } ;; type scanner_target = { scanned_string : string; mutable scanner_pos : int; mutable scanner_line : int; mutable scanner_linepos : int; (* Position of the beginning of the line *) mutable scanned_tokens : s_extended_token Queue.t; (* A queue of already scanned tokens in order to look ahead *) mutable last_token : s_token; (* The last returned token. It is only important whether it is * EncodedWord or not. *) } ;; type mime_scanner = scanner_spec * scanner_target ;; let get_pos_of_scanner (spec, target) = if spec.opt_recognize_encoded_words then failwith "get_pos_of_scanner" else target.scanner_pos ;; let get_line_of_scanner (spec, target) = if spec.opt_recognize_encoded_words then failwith "get_line_of_scanner" else target.scanner_line ;; let get_column_of_scanner (spec, target) = if spec.opt_recognize_encoded_words then failwith "get_column_of_scanner" else target.scanner_pos - target.scanner_linepos ;; let create_mime_scanner ~specials ~scan_options = let is_spcl = Array.make 256 false in List.iter (fun c -> is_spcl.( Char.code c ) <- true) specials; let spec = { scanner_specials = specials; scanner_options = scan_options; opt_no_backslash_escaping = List.mem No_backslash_escaping scan_options; opt_return_comments = List.mem Return_comments scan_options; opt_recognize_encoded_words = List.mem Recognize_encoded_words scan_options; is_special = is_spcl; space_is_special = is_spcl.(32); } in (* Grab the remaining arguments: *) fun ?(pos=0) ?(line=1) ?(column=0) s -> let target = { scanned_string = s; scanner_pos = pos; scanner_line = line; scanner_linepos = pos - column; scanned_tokens = Queue.create(); last_token = Comment; (* Must not be initialized with EncodedWord *) } in spec, target ;; let encoded_word_re = S.regexp "=[?]\ \\([^?]+\\)\ [?]\ \\([^?]+\\)\ [?]\ \\([^?]+\\)\ [?]=";; let scan_next_token (spec,target) = let mk_pair t len = { token = t; token_pos = target.scanner_pos; token_line = target.scanner_line; token_linepos = target.scanner_linepos; token_len = len; token_sep = false; }, t in (* Note: mk_pair creates a new token pair, and it assumes that * target.scanner_pos (and also scanner_line and scanner_linepos) * still contain the position of the beginning of the token. *) let s = target.scanned_string in let l = String.length s in let rec scan i = if i < l then begin let c = s.[i] in if spec.is_special.( Char.code c ) then begin let pair = mk_pair (Special c) 1 in target.scanner_pos <- target.scanner_pos + 1; (match c with '\n' -> target.scanner_line <- target.scanner_line + 1; target.scanner_linepos <- target.scanner_pos; | _ -> () ); pair end else match c with '"' -> (* Quoted string: *) scan_qstring (i+1) (i+1) 0 | '(' -> (* Comment: *) let i', line, linepos = scan_comment (i+1) 0 target.scanner_line target.scanner_linepos in let advance() = target.scanner_pos <- i'; target.scanner_line <- line; target.scanner_linepos <- linepos in if spec.opt_return_comments then begin let pair = mk_pair Comment (i' - i) in advance(); pair end else if spec.space_is_special then begin let pair = mk_pair (Special ' ') (i' - i) in advance(); pair end else begin advance(); scan i' end | (' '|'\t'|'\r') -> (* Ignore whitespace by default: *) target.scanner_pos <- target.scanner_pos + 1; scan (i+1) | '\n' -> (* Ignore whitespace by default: *) target.scanner_pos <- target.scanner_pos + 1; target.scanner_line <- target.scanner_line + 1; target.scanner_linepos <- target.scanner_pos; scan (i+1) | ('\000'..'\031'|'\127'..'\255') -> let pair = mk_pair (Control c) 1 in target.scanner_pos <- target.scanner_pos + 1; pair | '[' -> (* Domain literal: *) scan_dliteral (i+1) (i+1) 0 | _ -> scan_atom i i end else mk_pair End 0 and scan_atom i0 i = let return_atom() = let astring = String.sub s i0 (i-i0) in let r = if spec.opt_recognize_encoded_words then S.string_match encoded_word_re astring 0 else None in match r with None -> (* An atom contains never a linefeed character, so we can ignore * scanner_line here. *) let pair = mk_pair (Atom astring) (i-i0) in target.scanner_pos <- i; pair | Some mr -> (* Found an encoded word. *) let charset_lang = S.matched_group mr 1 astring in let encoding = S.matched_group mr 2 astring in let content = S.matched_group mr 3 astring in (* Check if it is an extended encoded word (RFC 2231): *) let charset,lang = try let l = String.length charset_lang in let k = String.index charset_lang '*' in (String.sub charset_lang 0 k, String.sub charset_lang (k+1) (l - k - 1)) with Not_found -> (charset_lang, "") in let t = EncodedWord((String.uppercase charset, lang), String.uppercase encoding, content) in let pair = mk_pair t (i-i0) in target.scanner_pos <- i; pair in if i < l then let c = s.[i] in match c with ('\000'..'\031'|'\127'..'\255'|'"'|'('|'['|' ') -> return_atom() | _ -> if spec.is_special.( Char.code c ) then return_atom() else scan_atom i0 (i+1) else return_atom() and scan_qstring i0 i n = if i < l then let c = s.[i] in match c with '"' -> (* Regular end of the quoted string: *) let content, line, linepos = copy_qstring i0 (i-1) n in let pair = mk_pair (QString content) (i-i0+2) in target.scanner_pos <- i+1; target.scanner_line <- line; target.scanner_linepos <- linepos; pair | '\\' when not spec.opt_no_backslash_escaping -> scan_qstring i0 (i+2) (n+1) | _ -> scan_qstring i0 (i+1) (n+1) else (* Missing right double quote *) let content, line, linepos = copy_qstring i0 (l-1) n in let pair = mk_pair (QString content) (l-i0+1) in target.scanner_pos <- l; target.scanner_line <- line; target.scanner_linepos <- linepos; pair and copy_qstring i0 i1 n = (* Used for quoted strings and for domain literals *) let r = Bytes.create n in let k = ref 0 in let line = ref target.scanner_line in let linepos = ref target.scanner_linepos in let esc = ref false in for i = i0 to i1 do let c = s.[i] in match c with '\\' when i < i1 && not spec.opt_no_backslash_escaping && not !esc -> esc := true | '\n' -> line := !line + 1; linepos := i+1; Bytes.set r !k c; incr k; esc := false | _ -> Bytes.set r !k c; incr k; esc := false done; assert (!k = n); Bytes.unsafe_to_string r, !line, !linepos and scan_dliteral i0 i n = if i < l then let c = s.[i] in match c with ']' -> (* Regular end of the domain literal: *) let content, line, linepos = copy_qstring i0 (i-1) n in let pair = mk_pair (DomainLiteral content) (i-i0+2) in target.scanner_pos <- i+1; target.scanner_line <- line; target.scanner_linepos <- linepos; pair | '\\' when not spec.opt_no_backslash_escaping -> scan_dliteral i0 (i+2) (n+1) | _ -> (* Note: '[' is not allowed by RFC 822; we treat it here as * a regular character (questionable) *) scan_dliteral i0 (i+1) (n+1) else (* Missing right bracket *) let content, line, linepos = copy_qstring i0 (l-1) n in let pair = mk_pair (DomainLiteral content) (l-i0+1) in target.scanner_pos <- l; target.scanner_line <- line; target.scanner_linepos <- linepos; pair and scan_comment i level line linepos = if i < l then let c = s.[i] in match c with ')' -> (i+1), line, linepos | '(' -> (* nested comment *) let i', line', linepos' = scan_comment (i+1) (level+1) line linepos in scan_comment i' level line' linepos' | '\\' when not spec.opt_no_backslash_escaping -> if (i+1) < l && s.[i+1] = '\n' then scan_comment (i+2) level (line+1) (i+2) else scan_comment (i+2) level line linepos | '\n' -> scan_comment (i+1) level (line+1) (i+1) | _ -> scan_comment (i+1) level line linepos else (* Missing closing ')' *) i, line, linepos in scan target.scanner_pos ;; let scan_token ((spec,target) as scn) = (* This function handles token queueing in order to recognize white space * that separates adjacent encoded words. *) let rec collect_whitespace () = (* Scans whitespace tokens and returns them as: * (ws_list, other_tok) if there is some other_tok following the * list (other_tok = End is possible) *) let (et, t) as pair = scan_next_token scn in ( match t with (Special ' '|Special '\t'|Special '\n'|Special '\r') -> let ws_list, tok = collect_whitespace() in pair :: ws_list, tok | _ -> [], pair ) in try (* Is there an already scanned token in the queue? *) let et = Queue.take target.scanned_tokens in let t = et.token in target.last_token <- t; et, et.token with Queue.Empty -> (* If not: inspect the last token. If that token is an EncodedWord, * the next tokens are scanned in advance to determine if there * are spaces separating two EncodedWords. These tokens are put * into the queue such that it is avoided that they are scanned * twice. (The sole purpose of the queue.) *) match target.last_token with EncodedWord(_,_,_) -> let ws_list, tok = collect_whitespace() in (* If tok is an EncodedWord, too, the tokens in ws_list must * be flagged as separating two adjacent encoded words. *) ( match tok with _, EncodedWord(_,_,_) -> List.iter (fun (et,t) -> et.token_sep <- true) ws_list | _ -> () ); (* Anyway, queue the read tokens but the first up *) ( match ws_list with [] -> (* Nothing to queue *) let et, t = tok in target.last_token <- t; tok | (et,t) as pair :: ws_list' -> List.iter (fun (et',_) -> Queue.add et' target.scanned_tokens) ws_list'; ( match tok with | _, End -> () | (et',_) -> Queue.add et' target.scanned_tokens ); (* Return the first scanned token *) target.last_token <- t; pair ) | _ -> (* Regular case: Scan one token; do not queue it up *) let (et, t) as pair = scan_next_token scn in target.last_token <- t; pair ;; let scan_token_list scn = let rec collect() = match scan_token scn with _, End -> [] | pair -> pair :: collect() in collect() ;; let scan_structured_value s specials options = let rec collect scn = match scan_token scn with _, End -> [] | _, t -> t :: collect scn in let scn = create_mime_scanner specials options s in collect scn ;; let specials_rfc822 = [ '<'; '>'; '@'; ','; ';'; ':'; '\\'; '.' ];; let specials_rfc2045 = [ '<'; '>'; '@'; ','; ';'; ':'; '\\'; '/' ];; let scan_encoded_text_value s = let specials = [ ' '; '\t'; '\r'; '\n'; '('; '['; '"' ] in let options = [ Recognize_encoded_words ] in let scn = create_mime_scanner specials options s in let rec collect () = match scan_token scn with _, End -> [] | et, _ when separates_adjacent_encoded_words et -> collect() | et, (Special _|Atom _|EncodedWord(_,_,_)) -> et :: collect () | et, (Control _) -> (* ignore control characters *) collect () | _, _ -> assert false in collect() ;; let split_mime_type ct_type = let specials = specials_rfc2045 @ [ '"'; '['; ']' ] in let scn = create_mime_scanner specials [] ct_type in let rec collect () = match scan_token scn with _, End -> [] | _, tok -> tok :: collect() in match collect() with [ Atom main_type; Special '/'; Atom sub_type ] -> (String.lowercase main_type, String.lowercase sub_type) | _ -> failwith "Netmime_string.split_mime_type" ;; type s_param = P_encoded of (string * string * string) | P of string ;; let param_value = function P_encoded(_,_,v) -> v | P v -> v ;; let param_charset = function P_encoded(cs,_,_) -> cs | P _ -> "" ;; let param_language = function P_encoded(_,l,_) -> l | P _ -> "" ;; let mk_param ?(charset = "") ?(language = "") v = if charset = "" && language = "" then P v else P_encoded(charset,language,v) ;; let print_s_param fmt = function P_encoded(cs,l,v) -> Format.fprintf fmt "" (String.escaped cs) (String.escaped l) (String.escaped v) | P v -> Format.fprintf fmt "" (String.escaped v) ;; let name_re = S.regexp "^\\([^*]+\\)\ \\([*][0-9]+\\)?\ \\([*]\\)?$" ;; let encoding_re = S.regexp "^\\([^']*\\)\ '\\([^']*\\)\ '\\(.*\\)$" ;; let opt f x = try Some(f x) with Not_found -> None ;; let decode_rfc2231_params ?(decode = true) params = (* Decodes the parameters passed as [(string * string) list] into * a [(string * s_param) list], applying the rules of RFC 2231. * * - Continuations are always recognized and decoded * - Encoded parameters are recognized if [~decode = true], and returned * as [P_encoded]. *) let p_complete = ref [] in (* Parameters not defined in fragments *) let p_hash = Hashtbl.create 10 in (* Fragmented parameters *) (* The keys are the names of the parameters. The values are pairs * (max, map) where max is the biggest fragment number so far, * and [map] is another hashtable mapping fragment number to [s_param]. *) List.iter (fun (rawname, rawvalue) -> (* First look at [rawname]. It may have one of the forms: * NAME * NAME* * NAME*N * NAME*N* *) let name, n, star = match S.string_match name_re rawname 0 with None -> (rawname, -1, false) | Some r -> (S.matched_group r 1 rawname, (match opt (S.matched_group r 2) rawname with None -> -1 | Some v -> int_of_string(String.sub v 1 (String.length v - 1)) ), (opt (S.matched_group r 3) rawname <> None) ) in let name, n, star = if star && not decode then (name ^ "*", n, false) (* suppress recognition of encoded parameters *) else (name, n, star) in (* If necessary, decode the parameter value *) let value = if star then begin if n <= 0 then begin match S.string_match encoding_re rawvalue 0 with None -> failwith "Netmime_string.decode_rfc2231_params" | Some r -> let charset = S.matched_group r 1 rawvalue in let lang = S.matched_group r 2 rawvalue in let escaped_value = S.matched_group r 3 rawvalue in P_encoded(String.uppercase charset, lang, Netencoding.Url.decode ~plus:false escaped_value) end else P (Netencoding.Url.decode ~plus:false rawvalue) end else P rawvalue in (* Store the value in p_complete or p_hash *) if n < 0 then p_complete := (name, value) :: !p_complete else begin let mx, map = try Hashtbl.find p_hash name with Not_found -> let pair = (ref (-1), Hashtbl.create 10) in Hashtbl.add p_hash name pair; pair in mx := max !mx n; if Hashtbl.mem map n then failwith "Netmime_string.decode_rfc2231_params"; Hashtbl.add map n value end ) params; (* Merge the fragments in p_hash: *) Hashtbl.iter (fun name (mx,map) -> let vl = ref [ ] in for i = 1 to !mx do let v = try Hashtbl.find map i with Not_found -> failwith "Netmime_string.decode_rfc2231_params" in match v with P s -> vl := s :: !vl | _ -> assert false done; match ( try Hashtbl.find map 0 with Not_found -> failwith "Netmime_string.decode_rfc2231_params" ) with P_encoded(charset,lang,v0) -> p_complete := (name, P_encoded (charset, lang, String.concat "" (v0 :: List.rev !vl)) ) :: !p_complete | P v0 -> p_complete := (name, P(String.concat "" (v0 :: List.rev !vl))) :: !p_complete ) p_hash; (* Return result *) List.rev !p_complete; ;; let scan_value_with_parameters_ep_int ?decode s options = let rec parse_params tl = match tl with Atom n :: Special '=' :: Atom v :: tl' -> (n,v) :: parse_rest tl' | Atom n :: Special '=' :: QString v :: tl' -> (n,v) :: parse_rest tl' (* The following cases are sometimes created by erroneous MUAs: *) | Special '=' :: Atom v :: tl' -> parse_rest tl' (* this may fail... *) | Special '=' :: QString v :: tl' -> parse_rest tl' | _ -> failwith "Netmime_string.scan_value_with_parameters" and parse_rest tl = match tl with [] -> [] | Special ';' :: tl' -> parse_params tl' | _ -> failwith "Netmime_string.scan_value_with_parameters" in (* Note: Even if not used here, the comma is a very common separator * and should be recognized as being special. You will get a * failure if there is a comma in the scanned string. *) let tl = scan_structured_value s [ ';'; '='; ',' ] options in let v, pl = match tl with [ Atom n ] -> n, [] | [ QString n ] -> n, [] | Atom n :: Special ';' :: tl' -> n, parse_params tl' | QString n :: Special ';' :: tl' -> n, parse_params tl' | _ -> failwith "Netmime_string.scan_value_with_parameters" in (v, decode_rfc2231_params ?decode pl) ;; let scan_value_with_parameters_ep s options = scan_value_with_parameters_ep_int ~decode:true s options ;; let scan_value_with_parameters s options = let v,pl = scan_value_with_parameters_ep_int ~decode:false s options in (v, List.map (function (_, P_encoded(_,_,_)) -> assert false (* not possible because of ~decode:false *) | (n,P v) -> (n,v) ) pl ) ;; let scan_mime_type s options = let n, params = scan_value_with_parameters s options in (String.lowercase n), (List.map (fun (n,v) -> (String.lowercase n, v)) params) ;; let scan_mime_type_ep s options = let n, params = scan_value_with_parameters_ep s options in (String.lowercase n), (List.map (fun (n,v) -> (String.lowercase n, v)) params) ;; let generate_encoded_words cs lang enc_tok text len1 len = (* Generate a list of encoded words for the charset [cs], the * language [lang], encoded as [enc_tok]. The text is passed * in [text] (encoded only in [cs], [enc_tok] is not applied). * * [len1] are the number of bytes of the first token, * [len] are the number of bytes for the following tokens. * If [len1] is too small for at least one token, [len] * is also used for the first token. * * If [cs] is not known to [Netconversion], it is assumed * it is a single-byte encoding. *) (* Determine prefix and suffix of encoded words: *) let prefix = "=?" ^ cs ^ (if lang <> "" then "*" ^ lang else "") ^ ( match enc_tok with "Q"|"q" -> "?Q?" | "B"|"b" -> "?B?" | _ -> failwith "Netmime_string.write_value: Unknown encoding" ) in let suffix = "?=" in let prefix_len = String.length prefix in let suffix_len = String.length suffix in let encode s = match enc_tok with "Q"|"q" -> Netencoding.Q.encode s | "B"|"b" -> Netencoding.Base64.encode s | _ -> assert false (* already caught above *) in let find_tok_single_byte k l = (* k: The position where to determine the token * l: Desired length of the token * * Returns the position of the end of the token *) let p = ref k in let l_cur() = let slice = String.sub text k (!p - k) in prefix_len + String.length (encode slice) + suffix_len in if l_cur() > l then k else ( try while l_cur() <= l do incr p; if !p >= String.length text then raise Exit done; decr p; !p with Exit -> !p (* at the end of the string *) ) in let rec generate_single_byte k l = (* k: Position in enc_text * l: Desired length of the token *) if k >= String.length text then [] else ( let j = ref(find_tok_single_byte k l) in if k = !j then ( (* l is too short, use len instead *) j := find_tok_single_byte k len; (* Still too short: Process only one char *) if k = !j then ( j := k+1 ) ); let tok = prefix ^ encode(String.sub text k (!j - k)) ^ suffix in tok :: generate_single_byte !j len ) in let find_tok_multi_byte cursor l = (* cursor: The cursor moving around text * l: Desired length of the token * * Moves the cursor to the end of the token *) let k_start = Netconversion.cursor_pos cursor in let l_cur() = let k_cur = Netconversion.cursor_pos cursor in let slice = String.sub text k_start (k_cur - k_start) in prefix_len + String.length (encode slice) + suffix_len in if l_cur() > l then () else ( try while l_cur() <= l do Netconversion.move cursor done; Netconversion.move ~num:(-1) cursor with Netconversion.Cursor_out_of_range -> () (* at the end of the string *) ) in let rec generate_multi_byte cursor l = (* cursor: The cursor moving around text * l: Desired length of the token *) if Netconversion.cursor_at_end cursor then [] else ( let k_start = Netconversion.cursor_pos cursor in find_tok_multi_byte cursor l; if k_start = Netconversion.cursor_pos cursor then ( (* l is too short, use len instead *) find_tok_multi_byte cursor len; (* Still too short: Process only one char *) if k_start = Netconversion.cursor_pos cursor then ( Netconversion.move cursor ) ); let k_end = Netconversion.cursor_pos cursor in let tok = prefix ^ encode(String.sub text k_start (k_end - k_start)) ^ suffix in tok :: generate_multi_byte cursor len ) in (* Check if the charset(encoding) is known, and if so, is available. *) let is_single_byte, e = try let enc = Netconversion.encoding_of_string cs in (* or Failure *) ( Netconversion.is_single_byte enc || not (List.mem enc (Netconversion.available_input_encodings())), enc ) with Failure _ -> (true, `Enc_empty) in (* For single-byte, or when the multi-byte encoding is not * available, use [generate_single_byte]. * For available multi-byte encodings, use [generate_multi_byte] * to split the string only at allowed positions. *) if is_single_byte then generate_single_byte 0 len1 else let cursor = Netconversion.create_cursor e text in generate_multi_byte cursor len1 ;; exception Line_too_long;; let write_value ?maxlen1 ?maxlen ?hardmaxlen1 ?hardmaxlen ?(fold_qstring = true) ?(fold_literal = true) ?unused ?hardunused (ch : Netchannels.out_obj_channel) tl = let do_folding = (maxlen <> None && maxlen1 <> None) in (* Whether to fold or not *) let have_hard_limit = do_folding && (hardmaxlen <> None && hardmaxlen1 <> None) in (* Whether there is a hard limit or not *) let still_unused = ref (match maxlen1 with Some x -> x | None -> 0) in (* The number of characters that will fit into the current line *) let still_unused_hard = ref (match hardmaxlen1 with Some x -> x | None ->0) in (* The same number for the hard limit *) let break_buffer = Buffer.create 80 in (* Collects characters after the last breakpoint *) let output_nobreak ?(pos=0) ?len s = (* Outputs the string s without any breakpoint *) let len = (match len with Some l -> l | None -> String.length s - pos) in if do_folding then Buffer.add_substring break_buffer s pos len else ch # really_output_string s pos len in let flush() = (* Flushes the buffer (used by [output_break]) *) let l = Buffer.length break_buffer in ch # output_buffer break_buffer; still_unused := !still_unused - l; if have_hard_limit then still_unused_hard := !still_unused_hard - l; Buffer.clear break_buffer; (* Check hard limit: *) if have_hard_limit && !still_unused_hard < 0 then raise Line_too_long; in let get_maxlen() = match maxlen with Some x -> x | None -> assert false in let output_break() = (* Outputs a breakpoint *) if do_folding then begin (* If the material collected in [break_buffer] fits into the line, * just output it, and clear the [break_buffer]. *) let l = Buffer.length break_buffer in if !still_unused >= l then flush() else if l > 0 then begin (* Otherwise output first a linefeed... *) let new_length = get_maxlen() in if new_length > !still_unused then begin (* otherwise \n does not help*) ch # output_char '\n'; still_unused := new_length; (match hardmaxlen with Some x -> still_unused_hard := x | None -> ()); end; (* ... and then the line: *) flush(); end end in let separate_words last = (* If [last] is one of the tokens Atom, QString, DomainLiteral, or * EncodedWord, output a breakpoint and a space. *) match last with Atom _ | QString _ | DomainLiteral _ | EncodedWord(_,_,_) -> output_break(); output_nobreak " " | _ -> () in let output_quoted special1 special2 fold s = let k1 = ref 0 in let k2 = ref 0 in let l = String.length s in let nobreak = ref true in while !k2 < l do let c = s.[ !k2 ] in match c with '\\' -> output_nobreak ~pos:!k1 ~len:(!k2 - !k1) s; output_nobreak "\\\\"; incr k2; k1 := !k2; nobreak := false; | ' ' | '\t' | '\n' -> output_nobreak ~pos:!k1 ~len:(!k2 - !k1) s; if fold && not !nobreak then output_break(); if fold && !nobreak && !k2 > 0 then output_nobreak "\\"; let s = match c with ' ' | '\n' -> " " | '\t' -> "\t" | _ -> assert false in output_nobreak s; incr k2; k1 := !k2; nobreak := true; (* After a space there is never a breakpoint *) | '\r' -> (* If the next character is LF: ignore. Otherwise * handle like space *) output_nobreak ~pos:!k1 ~len:(!k2 - !k1) s; incr k2; k1 := !k2; if !k2 >= l || s.[ !k2 ] <> '\n' then begin if fold && not !nobreak then output_break(); if fold && !nobreak && !k2 > 0 then output_nobreak "\\"; output_nobreak " "; nobreak := true; end | _ -> if c = special1 || c = special2 then begin output_nobreak ~pos:!k1 ~len:(!k2 - !k1) s; output_nobreak "\\"; output_nobreak (String.make 1 c); incr k2; k1 := !k2; end else begin incr k2; end; nobreak := false; done; output_nobreak ~pos:!k1 ~len:(!k2 - !k1) s; in let rec collect_words cs lang enc tl = match tl with EncodedWord((cs',lang'),enc',text) :: tl' -> if cs=cs' && lang=lang' && enc=enc' then let textrest, tl'' = collect_words cs lang enc tl' in (text :: textrest, tl'') else ([], tl') | _ -> ([], tl) in let output_encoded cs lang enc_tok text = let len1 = max 0 (!still_unused - Buffer.length break_buffer) in let len = if do_folding then get_maxlen () - 1 else max_int in let words = generate_encoded_words cs lang enc_tok text len1 len in let first = ref true in List.iter (fun word -> if not !first then ( output_break(); output_nobreak " "; ); output_nobreak word; first := false ) words in let rec output_tokens last tl = match tl with Atom atext as cur :: tl' -> separate_words last; output_nobreak atext; output_tokens cur tl' | Control c as cur :: tl' -> output_nobreak (String.make 1 c); output_tokens cur tl' | (Special ' ' | Special '\t' | Comment as cur) :: tl' -> ( match last with Special ' ' | Special '\t' | Comment -> () | Atom _ | QString _ | DomainLiteral _ | EncodedWord _ | Special _ -> output_break(); | _ -> () ); ( match cur with Special c -> output_nobreak (String.make 1 c) | Comment -> output_nobreak " " | _ -> assert false ); output_tokens cur tl' | Special c as cur :: tl' -> output_nobreak (String.make 1 c); output_tokens cur tl' | QString s as cur :: tl' -> separate_words last; output_nobreak "\""; output_quoted '"' '"' fold_qstring s; output_nobreak "\""; output_tokens cur tl' | DomainLiteral s as cur :: tl' -> separate_words last; output_nobreak "["; output_quoted '[' ']' fold_literal s; output_nobreak "]"; output_tokens cur tl' | EncodedWord((cs,lang),enc,_) as cur :: _ -> separate_words last; let (textlist, tl'') = collect_words cs lang enc tl in let text = String.concat "" textlist in output_encoded cs lang enc text; output_tokens cur tl'' | End :: tl' -> output_tokens End tl' | [] -> () in output_tokens End tl; output_break(); if do_folding then begin match unused with Some r -> r := !still_unused | None -> () end; if have_hard_limit then begin match hardunused with Some r -> r := !still_unused_hard | None -> () end ;; let hex = [| '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; 'A'; 'B'; 'C'; 'D'; 'E'; 'F' |] ;; let rec param_tokens ?(maxlen=max_int) pl = let qlen_char c = match c with '\\' | '"' -> 2 | _ -> 1 in let rec qlen s k = (* How long is [s] formatted as quoted string? *) if k >= String.length s then 2 (* 2*quote *) else qlen_char (s.[k]) + qlen s (k+1) in let rec continued_param n s pos k = if pos >= String.length s then [] else begin let name = n ^ "*" ^ string_of_int k in let l = ref (String.length name + 4) in (* 4 characters: semicolon, equal-to, 2*quote *) let p = ref pos in l := !l + qlen_char s.[pos]; incr p; while !l < maxlen-2 && !p < String.length s do l := !l + qlen_char s.[!p]; incr p; done; (* Now !l=maxlen-2 or !l=maxlen-1 or !p=String.length s *) let v = String.sub s pos (!p - pos) in ( [ Special ';'; Special ' '; Atom name; Special '='; QString v ] @ continued_param n s !p (k+1) ) end in let enclen_char c = match c with ' ' | '*' | '\'' | '%' | '<' | '>' | '@' | ',' | ';' | ':' | '\\' | '.' | '/' | '\000'..'\031' | '\127'..'\255' -> 3 | _ -> 1 in let rec enclen s k = (* How long is [s] formatted as %-encoded string? *) if k >= String.length s then 0 else enclen_char (s.[k]) + enclen s (k+1) in let enc s = (* Perform %-encoding *) let l = String.length s in let l' = enclen s 0 in let s' = Bytes.create l' in let k = ref 0 in for i = 0 to l-1 do if enclen_char s.[i] = 1 then begin Bytes.set s' !k s.[i]; incr k end else begin let code = Char.code s.[i] in Bytes.set s' !k '%'; Bytes.set s' (!k+1) hex.( code asr 4 ); Bytes.set s' (!k+2) hex.( code land 15 ); k := !k + 3 end done; Bytes.unsafe_to_string s' in let rec continued_enc_param cs lang n s pos k = if pos >= String.length s then [] else begin let name = n ^ "*" ^ string_of_int k ^ "*" in let designator = if k=0 then cs ^ "'" ^ lang ^ "'" else "" in let l = ref (String.length name + 2 + String.length designator) in (* 2 characters: semicolon, equal-to *) let p = ref pos in l := !l + enclen_char s.[pos]; incr p; while !l < maxlen-3 && !p < String.length s do l := !l + enclen_char s.[!p]; incr p; done; (* Now !l=maxlen-3 or !l=maxlen-2 or !l=maxlen-1 or !p=String.length s *) let v = String.sub s pos (!p - pos) in ( [ Special ';'; Special ' '; Atom name; Special '='; Atom (designator ^ enc v) ] @ continued_enc_param cs lang n s !p (k+1) ) end in match pl with (n,P s) :: pl' -> let l = String.length n + qlen s 0 + 2 in if l < maxlen then (Special ';' :: Special ' ' :: Atom n :: Special '=' :: QString s :: param_tokens ~maxlen pl') else continued_param n s 0 0 @ param_tokens ~maxlen pl' | (n,P_encoded(cs,lang,s)) :: pl' -> continued_enc_param cs lang n s 0 0 @ param_tokens ~maxlen pl' | [] -> [] ;; let split_uri uri = let rec split k = if k >= String.length uri then [] else let k' = min (k + 40) (String.length uri) in (QString (String.sub uri k (k' - k)) :: split k') in split 0 ;; let lf_re = S.regexp "[\n]";; let read_multipart_body f boundary s = let rec search_window re start = try let i,r = S.search_forward_bytes re (Netbuffer.unsafe_buffer s#window) start in (* If match_end <= window_length, the search was successful. * Otherwise, we searched in the uninitialized region of the * buffer. *) if S.match_end r > s#window_length then raise Not_found; r with Not_found -> if s # window_at_eof then raise Not_found; s#want_another_block(); search_window re start (* try again with enlarged window *) in let search_end_of_line k = (* Search LF beginning at position k *) try S.match_end (search_window lf_re k) with Not_found -> failwith "Netmime_string.read_multipart_body: MIME boundary without line end"; in let search_first_boundary() = (* Search boundary per regexp; return the position of the character * immediately following the boundary (on the same line), or * raise Not_found. *) let re = S.regexp ("\n--" ^ S.quote boundary) in S.match_end (search_window re 0) in let check_beginning_is_boundary() = let del = "--" ^ boundary in let ldel = String.length del in s # want ldel; let buf = Netbuffer.unsafe_buffer s#window in (s # window_length >= ldel) && (Bytes.sub_string buf 0 ldel = del) in let rec go_to_eof stream = if stream#window_at_eof then stream#skip stream#window_length else begin stream#skip (stream#block_size); go_to_eof stream end in let rec parse_parts uses_crlf = (* PRE: [s] is at the beginning of the next part. * [uses_crlf] must be true if CRLF is used as EOL sequence, and false * if only LF is used as EOL sequence. *) let delimiter = (if uses_crlf then "\r" else "" ) ^ "\n--" ^ boundary in let sub_s = new Netstream.sub_stream ~delimiter s in let y = f sub_s in go_to_eof sub_s; (* Now the position of [s] is at the beginning of the delimiter. * Check if there is a "--" after the delimiter (==> last part) *) let l_delimiter = String.length delimiter in s # want (l_delimiter+2); let buf = Netbuffer.unsafe_buffer s#window in let last_part = (s#window_length >= (l_delimiter+2)) && (Bytes.get buf l_delimiter = '-') && (Bytes.get buf (l_delimiter+1) = '-') in if last_part then begin go_to_eof s; [ y ] end else begin let k = search_end_of_line 2 in (* [k]: Beginning of next part *) s # skip k; y :: parse_parts uses_crlf end in (* Check whether s directly begins with a boundary: *) if check_beginning_is_boundary() then begin (* Move to the beginning of the next line: *) let k_eol = search_end_of_line 0 in let winbuf = Netbuffer.unsafe_buffer s#window in let uses_crlf = Bytes.get winbuf (k_eol-2) = '\r' in s # skip k_eol; (* Begin with first part: *) parse_parts uses_crlf end else begin (* Search the first boundary: *) try let k_eob = search_first_boundary() in (* or Not_found *) (* Printf.printf "k_eob=%d\n" k_eob; *) (* Move to the beginning of the next line: *) let k_eol = search_end_of_line k_eob in let winbuf = Netbuffer.unsafe_buffer s#window in let uses_crlf = Bytes.get winbuf (k_eol-2) = '\r' in (* Printf.printf "k_eol=%d\n" k_eol; *) s # skip k_eol; (* Begin with first part: *) parse_parts uses_crlf with Not_found -> (* No boundary at all: The body is empty. *) [] end; ;; let scan_multipart_body s ~start_pos ~end_pos ~boundary = let decode_part stream = let header = read_header stream in while not (stream # window_at_eof) do stream # want_another_block() done; let body = Netbuffer.sub stream#window 0 stream#window_length in header, body in let l_s = String.length s in if start_pos < 0 || end_pos < 0 || start_pos > l_s || end_pos >l_s then invalid_arg "Netmime_string.scan_multipart_body"; (* Set up a netstream beginning at ~start_pos and ending at ~end_pos: *) let len = end_pos - start_pos in let stream = new Netstream.input_stream (new Netchannels.input_string ~pos:start_pos ~len s) in (* Note: We would save a copy of the string if there was a class combining * input_stream and input_string *) (* read the multipart body: *) read_multipart_body decode_part boundary stream ;; let scan_multipart_body_and_decode s ~start_pos:i0 ~end_pos:i1 ~boundary = let parts = scan_multipart_body s i0 i1 boundary in List.map (fun (params, value) -> let encoding = try List.assoc "content-transfer-encoding" params with Not_found -> "7bit" in (* NOTE: In the case of "base64" and "quoted-printable", the allocation * of the string "value" could be avoided. *) let value' = match encoding with ("7bit"|"8bit"|"binary") -> value | "base64" -> Netencoding.Base64.decode ~accept_spaces:true value | "quoted-printable" -> Netencoding.QuotedPrintable.decode value | _ -> failwith "Netmime_string.scan_multipart_body_and_decode: Unknown content-transfer-encoding" in (params, value') ) parts ;; let scan_multipart_body_from_netstream s ~boundary ~create ~add ~stop = let decode_part stream = let header = read_header stream in let p = create header in try while stream#window_length > 0 do let l = stream#window_length in add p stream 0 l; stream # skip l done; stop p; () with error -> stop p; raise error in (* read the multipart body: *) let _ = read_multipart_body decode_part boundary s in () ;; let create_boundary ?(random = []) ?(nr = 0) () = let (x1,x2,x3) = Gc.counters() in let magic = ref(Printf.sprintf "%.0f,%.0f,%.0f" x1 x2 x3) in List.iter (fun s -> let l = min 256 (String.length s) in magic := !magic ^ (Digest.substring s 0 l) ) random; magic := Digest.string !magic; let hex = Printf.sprintf "%02X%02X%02X%02X%02X%02X%02X%02X" (Char.code !magic.[0]) (Char.code !magic.[1]) (Char.code !magic.[2]) (Char.code !magic.[3]) (Char.code !magic.[4]) (Char.code !magic.[5]) (Char.code !magic.[6]) (Char.code !magic.[7]) (* The other 8 bytes are ignored *) in Printf.sprintf "------------------------------=__%s<&>;%010d" hex nr ;; ocamlnet-4.1.2/src/netstring/netchannels.mli0000644000175000017500000011675312731530350017571 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Object-oriented I/O: Basic types and classes * * {b Contents} * * - {!Netchannels.types} * - {!Netchannels.input} * - {!Netchannels.output} * - {!Netchannels.delegation} * - {!Netchannels.lifting} * - {!Netchannels.descriptors} * - {!Netchannels.transactional} * - {!Netchannels.filters} * {ul {- {!Netchannels.filters_notes}}} * * The tutorial has been moved to {!Netchannels_tut}. *) open Netsys_types (** {1:types Types} *) (* ***************************** Types ******************************** *) (** There are three levels of class types for channels: * - [rec_in_channel] and [rec_out_channel]: Primitive, but standardized level * - [raw_in_channel] and [raw_out_channel]: Unix level * - [in_obj_channel] and [out_obj_channel]: Application level * * The "rec" level has been recently introduced to improve interoperability * with other libraries (e.g. camomile). The idea is to standardize the * real core methods of I/O, so they have the same meaning in all libraries. * Read * "{{:http://www.ocaml-programming.de/rec/IO-Classes.html}Basic I/O class types}" * for more. * * The "raw" level represents the level of Unix file descriptors. * * The application level is what should be used in programs. In addition * to the "raw" level one can find a number of convenience methods, * e.g. [input_line] to read a line from the channel. The downside is that * these methods usually work only for blocking I/O. * * One can lower the level by coercion, e.g. to turn an [in_obj_channel] * into a [rec_in_channel], apply the function * * [(fun ch -> (ch : in_obj_channel :> rec_in_channel))] * * To higher the level, apply [lift_in] or [lift_out], defined below. *) (** {b Interface changes:} Since ocamlnet-0.98, the semantics of * the methods [input] and [output] has slightly changed. When the end * of the channel is reached, [input] raises now [End_of_file]. In previous * releases of ocamlnet, the value 0 was returned. When the channel cannot * process data, but is in non-blocking mode, both methods now return the * value 0. In previous releases of ocamlnet, the behaviour was not * defined. * * {b Ocamlnet-3.0} changed the behavior of [close_out]. Errors are no longer * reported - instead, the exception is logged to {!Netlog}. For a stricter * error handling, it is suggested to call [flush] first. Also, [close_in] * and [close_out] no longer raise [Closed_channel] when the channel is * already closed. Read more about this in the section * {!Netchannels.rec_out_channel.close_error}. *) exception Closed_channel (** Raised when channel operations are called when the channel is closed *) exception Buffer_underrun (** Raised by input methods if the internal buffer of the channel is too * empty to read even one byte of data. * This exception is only used by certain implementations of channel * classes. *) exception Command_failure of Unix.process_status (** Raised by [close_in] or [close_out] if the channel is connected with * another process, and the execution of that process fails. *) (** Recommended input class type for library interoperability. *) class type rec_in_channel = object (** Description * * This class type is defined in * "{{:http://www.ocaml-programming.de/rec/IO-Classes.html}Basic I/O class types}" * as collaborative effort of several library creators. *) method input : Bytes.t -> int -> int -> int (** Reads octets from the channel and puts them into the string. The * first [int] argument is the position of the substring, and the second * [int] argument is the length of the substring where the data are * stored. The method returns the number of octets actually read and * stored. * * When the end of the channel is reached and there is no further octet * to read, the exception [End_of_file] will be raised. {b This has * been changed in ocamlnet-0.97! In previous releases the number 0 * was returned at the end of the channel.} * * When the channel is non-blocking, and there are currently no bytes * to read, the number 0 will be returned. {b This has * been changed in ocamlnet-0.97! In previous releases this behaviour * was undefined.} * * When the channel is closed, the exception [Closed_channel] will be * raised if an ocamlnet implementation is used. For implementations * of other libraries there is no standard for this case. *) method close_in : unit -> unit (** Closes the channel for input. * * When the channel is already closed, this is a no-op. * * Error policy: Exceptions are only raised in cases of serious * corruption, e.g. if the underlying descriptor is invalid. *) end (** Basic Unix-level class type for input channels as used by ocamlnet. In addition * to the recommended standard, ocamlnet always support a position counter *) class type raw_in_channel = object inherit rec_in_channel method pos_in : int (** Returns the current channel position. This position can be expected * to be consistent with the returned number of bytes of [input], i.e. * when [input] returns [n], the position is advanced by [n]. * * As seek operations are outside the scope of [Netchannels], * implementations may or may not take seek operations into account. *) end (** Recommended output class type for library interoperability. *) class type rec_out_channel = object (** Description * * This class type is defined in * "{{:http://www.ocaml-programming.de/rec/IO-Classes.html}Basic I/O class types}" * as collaborative effort of several library creators. *) method output : Bytes.t -> int -> int -> int (** Takes octets from the string and writes them into the channel. The * first [int] argument is the position of the substring, and the second * [int] argument is the length of the substring where the data can * be found. The method returns the number of octets actually written. * * The implementation may choose to collect written octets in a buffer * before they actually delivered to the underlying resource. * * When the channel is non-blocking, and there are currently no bytes * to write, the number 0 will be returned. {b This has * been changed in ocamlnet-0.97! In previous releases this behaviour * was undefined.} * * When the channel is closed, the exception [Closed_channel] will be * raised if an ocamlnet implementation is used. For implementations * of other libraries there is no standard for this case. *) method flush : unit -> unit (** If there is a write buffer, it will be flushed. Otherwise, nothing * happens. *) method close_out : unit -> unit (** Flushes the buffer, if any, and closes the channel for output. * * When the channel is already closed, this is a no-op. *) (** {2:close_error How to close channels in case of errors} The [close_out] method has actually two tasks: First, it writes out all remaining data (like [flush]), and second, it releases OS resources (e.g. closes file descriptors). There is the question what has to happen when the write part fails - is the resource released anyway or not? We choose here a pragmatic approach under the assumption that an OS error at close time is usually unrecoverable, and it is more important to release the OS resource. Also, we assume that the user is wise enough to call [flush] first if it is essential to know write errors at close time. Under these assumptions: - The [flush] method fully reports any errors when writing out the remaining data. - When [flush] raises an error exception, it should discard any data in the buffer. This is not obligatory, however, but considered good practice, and is subject to discussion. - The [close_out] method usually does not report errors by raising exceptions, but only by logging them via {!Netlog}. The OS resource is released in any case. As before, this behavior is not obligatory, but considered as good practice, and subject to discussion. This ensures that the following code snippet reports all errors, but also releases OS resources: {[ try ch # flush(); ch # close_out(); with error -> ch # close_out(); raise error ]} There are some cases where data can be first written when it is known that the channel is closed. These data would not be written by a preceding [flush]. In such cases: - The best way to deal with it is to define another method, e.g. called [write_eof], that marks the data as logically being complete, so a following [flush] can do the complete shutdown cycle of the channel. - At least, however, one should allow then that a double [close_out] releases the descriptor: the first [close_out] will report the error condition as exception, but discard all data in the channel. The second [close_out] finally releases the OS resource. In any way, hard errors indicating bugs of the program logic (like invalid file descriptors) should always be immediately reported. *) end (** Basic Unix-level class type for output channels as used by ocamlnet. In addition * to the recommended standard, ocamlnet always support a position counter *) class type raw_out_channel = object inherit rec_out_channel method pos_out : int (** Returns the current channel position. This position can be expected * to be consistent with the returned number of bytes of [output], i.e. * when [output] returns [n], the position is advanced by [n]. * * As seek operations are outside the scope of [Netchannels], * implementations may or may not take seek operations into account. *) end (** A channel supporting both input and output. The input and output * aspects are strictly separated *) class type raw_io_channel = object inherit raw_in_channel inherit raw_out_channel end (** Further methods usually supported by ocamlnet channel implementations. * These methods are only reasonable when the channel is of blocking type, * i.e. waits for input when not enough data are available to perform an * operation. Implementations may choose to fail when they detect the * channel is non-blocking. *) class type compl_in_channel = object method really_input : Bytes.t -> int -> int -> unit (** Reads exactly as many octets from the channel as the second [int] * argument specifies. The octets are placed at the position denoted * by the first [int] argument into the string. * * When the end of the channel is reached before the passed number of * octets are read, the exception [End_of_file] is raised. *) method really_input_string : int -> string (** [really_input_string ic len] reads [len] characters from channel [ic] and returns them in a new string. Raise [End_of_file] if the end of file is reached before [len] characters have been read. *) method input_char : unit -> char (** Reads exactly one character from the channel, or raises [End_of_file] *) method input_line : unit -> string (** Reads the next line from the channel. When the channel is already * at the end before [input_line] is called, the exception [End_of_file] * is raised. *) method input_byte : unit -> int (** Reads exactly one octet from the channel and returns its code, * or raises [End_of_file] *) end (** The application-level input channel supports raw and complemented methods *) class type in_obj_channel = object inherit raw_in_channel inherit compl_in_channel end (** Further methods usually supported by ocamlnet channel implementations. * These methods are only reasonable when the channel is of blocking type, * i.e. waits for output readiness when the underlying resource currently * cannot process enough data. Implementations may choose to fail when they * detect the channel is non-blocking. *) class type compl_out_channel = object method really_output : Bytes.t -> int -> int -> unit (** Writes exactly as many octets to the channel as the second [int] * argument specifies. The octets are taken from the string position * denoted by the first [int] argument. *) method really_output_string : string -> int -> int -> unit (** Same for strings *) method output_char : char -> unit (** Writes exactly one character *) method output_bytes : Bytes.t -> unit (** Writes exactly the passed string *) method output_string : string -> unit (** Writes exactly the passed string *) method output_byte : int -> unit (** Writes exactly one byte passed as integer code *) method output_buffer : Buffer.t -> unit (** Writes exactly the contents of the buffer *) method output_channel : ?len:int -> in_obj_channel -> unit (** Writes the contents of an [in_obj_channel] until the end of the * input channel is reached. * * @param len If passed, at most this number of octets are read from * the input channel and written to this channel. *) end (** The application-level output channel supports raw and complemented methods *) class type out_obj_channel = object inherit raw_out_channel inherit compl_out_channel end (** A channel supporting both input and output. The input and output * aspects are strictly separated *) class type io_obj_channel = object inherit in_obj_channel inherit out_obj_channel end (** A transactional output channel has a buffer for uncommitted data. * This means that all data written to this channel is collected in the * buffer until either [commit_work] or [rollback_work] is called. * * When the channel is closed, the buffer may optionally be committed. * This is implementation-defined. * * The method [flush] does not have any effect on the transaction * buffer. *) class type trans_out_obj_channel = object inherit out_obj_channel method commit_work : unit -> unit (** Flushes the transaction buffer, and writes its contents to the * underlying resource. *) method rollback_work : unit -> unit (** Empties the transaction buffer *) end (* ***************************** Input channels *********************** *) (** {1:input Input channels} *) class input_channel : ?onclose:(unit -> unit) -> in_channel -> in_obj_channel (** Creates an input channel from an [in_channel], which must be open. * * The method [pos_in] reflects the real position in the channel as * returned by [Pervasives.pos_in]. This works for both seekable and * non-seekable channels. * * The method [close_in] also closes the underlying [in_channel]. * * The function [onclose] is called after the [in_channel] has been closed. *) val input_channel : ?onclose:(unit -> unit) -> in_channel -> in_obj_channel (** Same as function *) class input_command : string -> in_obj_channel (** Runs the command with [/bin/sh], and reads the data the command prints * to stdout. * * The method [pos_in] returns the number of read octets. * * When [close_in] is invoked, the subprocess is [wait]ed for. If the * process exits with code 0, the method returns normally. Otherwise, * the exception [Command_failure] is raised. *) val input_command : string -> in_obj_channel (** Same as function *) class input_string : ?pos:int -> ?len:int -> string -> in_obj_channel (** Creates an input channel from a (constant) string. * * The method [pos_in] reflects the real position in the string, i.e. * a character read at position [k] can be found at [s.[k]] in the string * [s]. * * @param pos The data of the channel begins at this position of the string. * Default: 0 * @param len The data of the channel consists of this number of bytes. * Default: until the end of the string *) val input_string : ?pos:int -> ?len:int -> string -> in_obj_channel (** Same as function *) class input_bytes : ?pos:int -> ?len:int -> Bytes.t -> in_obj_channel (** Same for constant bytes *) val input_bytes : ?pos:int -> ?len:int -> Bytes.t -> in_obj_channel (** Same as function *) class input_memory : ?pos:int -> ?len:int -> memory -> in_obj_channel (** Same for constant memory *) val input_memory : ?pos:int -> ?len:int -> memory -> in_obj_channel (** Same as function *) val input_tstring : ?pos:int -> ?len:int -> tstring -> in_obj_channel (** Same for tagged strings (only as function) *) val create_input_netbuffer : ?keep_data:bool -> Netbuffer.t -> in_obj_channel * (* shutdown: *) (unit -> unit) (** Creates an input channel and a shutdown function for a netbuffer. * This is a destructive * implementation: Every time data is read, the octets are taken from the * beginning of the netbuffer, and they are deleted from the netbuffer * (recall that a netbuffer works like a queue of characters). * * Conversely, the user of this class may add new data to the netbuffer * at any time. When the shutdown function is called, the EOF condition * is recorded, and no further data must be added. * * If the netbuffer becomes empty, the input methods raise [Buffer_underrun] * when the EOF condition has not yet been set, and they raise * [End_of_file] when the EOF condition has been recorded. * * [keep_data]: do not delete read data from the buffer *) val lexbuf_of_in_obj_channel : in_obj_channel -> Lexing.lexbuf (** Creates a lexical buffer from an input channel. The input channel * is not closed when the end is reached * * This function does not work for non-blocking channels. *) val string_of_in_obj_channel : in_obj_channel -> string (** Reads from the input channel until EOF and returns the characters * as string. The input channel is not closed. * * This function does not work for non-blocking channels. *) val bytes_of_in_obj_channel : in_obj_channel -> Bytes.t (** Same for bytes *) val lines_of_in_obj_channel : in_obj_channel -> string list (** Reads from the input channel until EOF and returns the lines * as string list. The input channel is not closed. * * This function does not work for non-blocking channels. *) val with_in_obj_channel : (#in_obj_channel as 'a) -> ('a -> 'b) -> 'b (** [with_in_obj_channel ch f]: * Computes [f ch] and closes [ch]. If an exception happens, the channel is * closed, too. *) (* *************************** Output channels ************************ *) (** {1:output Output channels} *) class output_channel : ?onclose:(unit -> unit) -> (* default: fun _ -> () *) out_channel -> out_obj_channel (** Creates an output channel writing into an [out_channel]. * * The method [pos_out] reflects the real position in the channel as * returned by [Pervasives.pos_out]. This works for both seekable and * non-seekable channels. * * The method [close_out] also closes the underlying [out_channel]. * There is some implicit logic to either use [close_out] or [close_out_noerr] * depending on whether the immediately preceding operation already reported * an error. * * @param onclose this function is called when the [close_out] method is * invoked, just after the underlying [out_channel] has been closed. *) class output_command : ?onclose:(unit -> unit) -> (* default: fun _ -> () *) string -> out_obj_channel (** Runs the command with [/bin/sh], and data written to the channel is * piped to stdin of the command. * * The method [pos_out] returns the number of written octets. * * When [close_out] is invoked, the subprocess is [wait]ed for. If the * process exits with code 0, the method returns normally. Otherwise, * the exception [Command_failure] is raised. (The channel is closed * even if this exception is raised.) * * @param onclose this function is called when the [close_out] method is * invoked, just after the underlying descriptor has been closed. *) class output_buffer : ?onclose:(unit -> unit) -> (* default: fun _ -> () *) Buffer.t -> out_obj_channel (** This output channel writes the data into the passed buffer. * * The method [pos_out] returns the number of written octets. * * @param onclose this function is called when the [close_out] method is * invoked, just after the underlying descriptor has been closed. *) class output_netbuffer : ?onclose:(unit -> unit) -> (* default: fun _ -> () *) Netbuffer.t -> out_obj_channel (** This output channel writes the data into the passed netbuffer. * * The method [pos_out] returns the number of written octets. * * @param onclose this function is called when the [close_out] method is * invoked, just after the underlying descriptor has been closed. *) class output_null : ?onclose:(unit -> unit) -> (* default: fun _ -> () *) unit -> out_obj_channel (** This output channel discards all written data. * * The method [pos_out] returns the number of discarded bytes. * * @param onclose this function is called when the [close_out] method is * invoked, just after the underlying descriptor has been closed. *) val with_out_obj_channel : (#out_obj_channel as 'a) -> ('a -> 'b) -> 'b (** [with_out_obj_channel ch f]: * Computes [f ch] and closes [ch]. If an exception happens, the channel is * closed, too. *) (* ********************* Delegation *********************************** *) (** {1:delegation Delegation classes} *) (** Delegation classes just forward method calls to an parameter * object, i.e. when method [m] of the delegation class is called, * the definition of [m] is just to call the method with the same * name [m] of the parameter object. This is very useful in order * to redefine methods individually. * * For example, to redefine the method [pos_in] of an [in_obj_channel], * use * {[ * class my_channel = object(self) * inherit in_obj_channel_delegation ... * method pos_in = ... * end * ]} * * As a special feature, the following delegation classes can suppress * the delegation of [close_in] or [close_out], whatever applies. * Just pass [close:false] to get this effect, e.g. * {[ * class input_channel_don't_close c = * in_obj_channel_delegation ~close:false (new input_channel c) * ]} * This class does not close [c : in_channel] when the [close_in] * method is called. *) class rec_in_channel_delegation : ?close:bool -> rec_in_channel -> rec_in_channel class raw_in_channel_delegation : ?close:bool -> raw_in_channel -> raw_in_channel class in_obj_channel_delegation : ?close:bool -> in_obj_channel -> in_obj_channel class rec_out_channel_delegation : ?close:bool -> rec_out_channel -> rec_out_channel class raw_out_channel_delegation : ?close:bool -> raw_out_channel -> raw_out_channel class out_obj_channel_delegation : ?close:bool -> out_obj_channel -> out_obj_channel (* ********************* Raw channels ********************************* *) (** {1:lifting Lifting channels} *) (** The following classes and functions add missing methods to reach * a higher level in the hierarchy of channel class types. For most * uses, the [lift_in] and [lift_out] functions work best. *) val lift_in : ?eol:string list -> ?buffered:bool -> ?buffer_size:int -> ?pass_through:int -> [ `Rec of rec_in_channel | `Raw of raw_in_channel ] -> in_obj_channel (** Turns a [rec_in_channel] or [raw_in_channel], depending on the passed * variant, into a full [in_obj_channel] object. (This is a convenience * function, you can also use the classes below directly.) If you * want to define a class for the lifted object, use * {[ * class lifted_ch ... = * in_obj_channel_delegation (lift_in ...) * ]} * * @param eol The accepted end-of-line delimiters. The method * [input_line] recognizes any of the passed strings as EOL * delimiters. When more than one delimiter matches, the longest * is taken. Defaults to [ ["\n"] ]. The default cannot be * changed when [buffered=false] (would raise [Invalid_argument]). * The delimiter strings must neither be empty, nor longer than * [buffer_size]. * @param buffered Whether a buffer is added, by default {b true} * @param buffer_size The size of the buffer, if any, by default 4096 * @param pass_through If the read request has at least this size, * and the buffer is currently empty, the buffer will be bypassed. * Defaults to [max_int], i.e. it is off. *) val lift_out : ?buffered:bool -> ?buffer_size:int -> ?pass_through:int -> [ `Rec of rec_out_channel | `Raw of raw_out_channel ] -> out_obj_channel (** Turns a [rec_out_channel] or [raw_out_channel], depending on the passed * variant, into a full [out_obj_channel] object. (This is a convenience * function, you can also use the classes below directly.) If you * want to define a class for the lifted object, use * {[ * class lifted_ch ... = * out_obj_channel_delegation (lift_out ...) * ]} * * @param buffered Whether a buffer is added, by default {b true} * @param buffer_size The size of the buffer, if any, by default 4096 * @param pass_through If the write request has at least this size, * and the buffer is currently empty, the buffer will be bypassed. * Defaults to [max_int], i.e. it is off. *) (** This class implements the methods from [compl_in_channel] by calling * the methods of [raw_in_channel]. There is no additional buffering. * The performance of the method [input_line] is very bad (consider * to override it, e.g. by [enhanced_input_line] as defined below). *) class virtual augment_raw_in_channel : object inherit compl_in_channel method virtual input : Bytes.t -> int -> int -> int (** As in [raw_in_channel] *) method virtual close_in : unit -> unit (** As in [raw_in_channel] *) method virtual pos_in : int (** As in [raw_in_channel] *) end class lift_rec_in_channel : ?start_pos_in:int -> rec_in_channel -> in_obj_channel (** This class implements [pos_in] and the methods from [compl_in_channel] * by calling the methods of [rec_in_channel]. * There is no additional buffering. * * The performance of the method [input_line] is very bad (consider * to override it, e.g. by [enhanced_input_line] as defined below). * * The method [pos_in] is implemented by counting the number of octets * read by the [input] method. * * @param start_pos_in The initial value of the counter for [pos_in]. * Defaults to 0. *) (** This class implements the methods from [compl_out_channel] by calling * the methods of [raw_out_channel]. There is no additional buffering. *) class virtual augment_raw_out_channel : object inherit compl_out_channel method virtual output : Bytes.t -> int -> int -> int (** As in [raw_out_channel] *) method virtual close_out : unit -> unit (** As in [raw_out_channel] *) method virtual flush : unit -> unit (** As in [raw_out_channel] *) method virtual pos_out : int (** As in [raw_out_channel] *) end class lift_raw_out_channel : raw_out_channel -> out_obj_channel (** This class implements the methods from [compl_out_channel] by calling * the methods of [raw_out_channel]. There is no additional buffering. *) class lift_rec_out_channel : ?start_pos_out:int -> rec_out_channel -> out_obj_channel (** This class implements [pos_out] and the methods from [compl_out_channel] * by calling the methods of [rec_out_channel]. * There is no additional buffering. * * The method [pos_out] is implemented by counting the number of octets * read by the [output] method. * * @param start_pos_out The initial value of the counter for [pos_out]. * Defaults to 0. *) type input_result = [ `Data of int | `Separator of string ] (** This type is for the method [enhanced_input] of [enhanced_raw_in_channel]. * - [`Data n] means that [n] bytes have been copied to the target string * - [`Separator s] means that no bytes have been copied, but that an * end-of-line separator [s] has been found *) (** Defines private methods reading text line by line *) class type enhanced_raw_in_channel = object inherit raw_in_channel method private enhanced_input_line : unit -> string (** An improved implementation of [input_line] that uses the buffer *) method private enhanced_input : Bytes.t -> int -> int -> input_result (** Works similar to [input], but distinguishes between normal data * and end-of-line separators. The latter are returned as * [`Separator s]. When normal data is found, it is copied to the * string, and [`Data n] is returned to indicate that [n] bytes * were copied. *) end class buffered_raw_in_channel : ?eol:string list -> ?buffer_size:int -> (* default: 4096 *) ?pass_through:int -> raw_in_channel -> enhanced_raw_in_channel (** This class adds a buffer to the underlying [raw_in_channel]. * As additional feature, the method [enhanced_input_line] is a fast * version of [input_line] that profits from the buffer. * * @param eol The accepted end-of-line delimiters. The method * [enhanced_input_line] recognizes any of the passed strings as EOL * delimiters. When more than one delimiter matches, the longest * is taken. Defaults to [ ["\n"] ]. Note that [input_line] * always only recognizes ["\n"] as EOL character, this cannot * be changed. * The delimiter strings must neither be empty, nor longer than * [buffer_size]. * @param buffer_size The size of the buffer, by default 4096. * @param pass_through If the read request has at least this size, * and the buffer is currently empty, the buffer will be bypassed. * Defaults to [max_int], i.e. it is off. *) class buffered_raw_out_channel : ?buffer_size:int -> (* default: 4096 *) ?pass_through:int -> raw_out_channel -> raw_out_channel (** This class adds a buffer to the underlying [raw_out_channel]. * * @param buffer_size The size of the buffer, by default 4096. * @param pass_through If the write request has at least this size, * and the buffer is currently empty, the buffer will be bypassed. * Defaults to [max_int], i.e. it is off. *) (* ********************** Channels over descriptors ******************* *) (** {1:descriptors Channels over descriptors} *) class input_descr : ?blocking:bool -> ?start_pos_in:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_in_channel (** Creates a [raw_in_channel] for the passed file descriptor, which must * be open for reading. * * The [pos_in] method returns logical positions, i.e. it counts the number * of read octets. It is not tried to determine the real file position. * * The method [close_in] also closes the file descriptor. * * This class also supports Win32 proxy descriptors referring to an input * channel. * * @param blocking Whether the channel waits for data if it is not * possible to read from the (non-blocking) descriptor. Defaults to [true]. * @param start_pos_in The position to which [pos_in] is initialized when * the channel is created, by default 0 * @param fd_style The descriptor style. If omitted, it is automatically * determined if possible. *) class output_descr : ?blocking:bool -> ?start_pos_out:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_out_channel (** Creates a [raw_out_channel] for the passed file descriptor, which must * be open for writing. * * The [pos_out] method returns logical positions, i.e. it counts the number * of written octets. It is not tried to determine the real file position. * * The method [close_out] also closes the file descriptor. * * This class also supports Win32 proxy descriptors referring to an output * channel. * * @param blocking Whether the channel waits until it can output if it is not * possible to write to the (non-blocking) descriptor. Defaults to [true]. * @param start_pos_out The position to which [pos_out] is initialized when * the channel is created, by default 0 * @param fd_style The descriptor style. If omitted, it is automatically * determined if possible. *) class socket_descr : ?blocking:bool -> ?start_pos_in:int -> ?start_pos_out:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_io_channel (** Creates a [raw_io_channel] for the passed socket descriptor, which must * be open for reading and writing, and not yet shut down in either * direction. The [raw_io_channel] is used to represent a bidirectional * channel: [close_out] shuts the socket down for sending, [close_in] * shuts the socket down for reading, and when both directions are down, * the descriptor is closed. * * The [pos_in] and [pos_out] methods returns logical positions. * * This class supports sockets and Win32 named pipes. Note, however, * that for Win32 named pipes it is not possible to shut down only one * direction of the bidirectional data channel. * * @param blocking See {!input_descr} and {!output_descr} * @param start_pos_in The position to which [pos_in] is initialized when * the channel is created, by default 0 * @param start_pos_out The position to which [pos_out] is initialized when * the channel is created, by default 0 * @param fd_style The descriptor style. If omitted, it is automatically * determined if possible. *) (* ********************* Transactional output channels **************** *) (** {1:transactional Transactional channels} *) type close_mode = [ `Commit | `Rollback ] (** Whether a [close_out] implies a commit or rollback operation *) class buffered_trans_channel : ?close_mode:close_mode -> out_obj_channel -> trans_out_obj_channel (** A transactional output channel with a transaction buffer implemented * in memory * * @param close_mode Specifies the semantics of [close_out], by default * [`Commit] *) val make_temporary_file : ?mode:int -> ?limit:int -> ?tmp_directory:string -> ?tmp_prefix:string -> unit -> (string * in_channel * out_channel) (** Creates a temporary file in the directory [tmp_directory] with a name * prefix [tmp_prefix] and a unique suffix. The function returns * the triple (name, inch, outch) containing the file [name], * the file opened as in_channel [inch] and as out_channel [outch]. * * @param tmp_directory Defaults to {!Netsys_tmp.tmp_directory()} * @param tmp_prefix By default ["netstring"]. This needs not to be * unique, but just descriptive. * @param mode The creation mask of the file; defaults to 0o600, i.e. the * file is private for the current user * @param limit Limits the number of trials to find the unique suffix. * Defaults to 1000. *) class tempfile_trans_channel : ?close_mode:close_mode -> ?tmp_directory:string -> ?tmp_prefix:string -> out_obj_channel -> trans_out_obj_channel (** A transactional output channel with a transaction buffer implemented * as temporary file * * @param close_mode Specifies the semantics of [close_out], by default * [`Commit] * @param tmp_directory See [make_temporary_file] * @param tmp_prefix See [make_temporary_file] *) (* ************************ Pipes and filters ************************* *) (** {1:filters Pipes and Filters} *) (** Note that this has nothing to do with "pipes" on the Unix level. * It is, however, the same idea: Connecting two I/O resources with an * intermediate buffer. *) class pipe : ?conv:(Netbuffer.t -> bool -> Netbuffer.t -> unit) -> ?buffer_size:int -> unit -> io_obj_channel (** A [pipe] has two internal buffers (realized by Netbuffer). The * output methods of the class write to the incoming buffer. When * new data are appended to the incoming buffer, the conversion function * [conv] is called; the arguments are the incoming buffer and the outgoing * buffer. The conversion function must convert the data available in the * incoming buffer and append the result to the outgoing buffer. Finally, * the input methods of the class return the data found in the outgoing * buffer. * * The conversion function is called as follows: * [conv incoming_buffer at_eof outgoing_buffer] * * The conversion function is allowed to do nothing if the incoming data * are not complete enough to be converted. It is also allowed to convert * only the beginning of the incoming buffer. * * If the outgoing buffer is empty, the input methods will raise * [Buffer_underrun]. * * If [close_out] is invoked, the end of the data stream will be recorded. * In this case, the conversion function is called with [at_eof = true], * and it is expected that this function converts the whole data found * in the incoming buffer. * * [close_in] implies [close_out]. * * The conversion function may raise exceptions. The exceptions will * fall through to the caller of the input methods. (The output methods * and [close_in], [close_out] never fail because of such exceptions.) * * The default conversion function copies everything from the incoming * buffer to the outgoing buffer without modification. *) class output_filter : io_obj_channel -> out_obj_channel -> out_obj_channel (** An [output_filter] filters the data written to it through the * [io_obj_channel] (usually a [pipe]), and writes the filtered data * to the passed [out_obj_channel]. * * If the filter is closed, the [io_obj_channel] will be closed, too, * but not the destination [out_obj_channel] (so you can still append * further data). *) class input_filter : in_obj_channel -> io_obj_channel -> in_obj_channel (** An [input_filter] filters the data read from it through the * [io_obj_channel] (usually a [pipe] after the data have been * retrieved from the passed [in_obj_channel]. * * An [input_filter] object never generates [Buffer_underrun] exceptions. * However, if the passed [in_obj_channel] or [io_obj_channel] raises such * an exception, the exception will fall through the calling chain. * * If the filter is closed, the [io_obj_channel] will be closed, too, * but not the source [in_obj_channel] (so you can still read further * data from it). *) (** {2:filters_notes Notes, Examples} *) (** If you have the choice, prefer [output_filter] over [input_filter]. * The latter is slower. * * The primary application of filters is to encode or decode a channel * on the fly. For example, the following lines write a BASE64-encoded file: * * {[let ch = new output_channel (open_out "file.b64") in * let encoder = new Netencoding.Base64.encoding_pipe ~linelength:76 () in * let ch' = new output_filter encoder ch in * ... (* write to ch' *) * ch' # close_out(); * ch # close_out(); (* you must close both channels! *) * ]} * * All bytes written to [ch'] are BASE64-encoded and the encoded bytes are * written to [ch]. * * There are also pipes to decode BASE64, and to encode and decode the * "Quoted printable" format. Encoding and decoding work even if the * data is delivered in disadvantageous chunks, because the data is * "re-chunked" if needed. For example, BASE64 would require that data * arrive in multiples of three bytes, and to cope with that, the BASE64 pipe * only processes the prefix of the input buffer that is a multiple of three, * and defers the encoding of the extra bytes till the next opportunity. *) ocamlnet-4.1.2/src/netstring/netxdr.ml0000644000175000017500000015620512731530350016416 0ustar gerdgerd(* * $Id$ *) (* This is an XDR implementation. * See RFC 1014 *) open Netnumber open Printf exception Propagate of string;; (**********************************************************************) (* auxiliary stuff: *) let aux_cmp (ha,sa) (hb,sb) = if ha = hb then compare sa sb else ha - hb ;; let all_distinct_q l = (* returns whether all elements of l are distinct *) let a = Array.map (fun s -> (Hashtbl.hash s), s) (Array.of_list l) in Array.sort aux_cmp a; let distinct = ref true in let k = ref 0 in while !distinct && !k < Array.length a - 1 do let (ha,sa) = a.( !k ) in let (hb,sb) = a.( !k + 1 ) in distinct := (ha != hb) && (sa <> sb); incr k done; !distinct ;; let all_distinct = function [] | [_] -> true | [a;b] -> a <> b | l -> all_distinct_q l ;; let sub_set_q l1 l2 = (* returns whether all elements of l1 occur in l2 *) let a1 = Array.map (fun s -> (Hashtbl.hash s), s) (Array.of_list l1) in let a2 = Array.map (fun s -> (Hashtbl.hash s), s) (Array.of_list l2) in Array.sort aux_cmp a1; Array.sort aux_cmp a2; let occurs = ref true in let k1 = ref 0 in let k2 = ref 0 in while !occurs && !k1 < Array.length a1 && !k2 < Array.length a2 do let (h1,s1) = a1.( !k1 ) in let found = ref false in while not !found && !k2 < Array.length a2 do let (h2,s2) = a2.( !k2 ) in found := (h1 == h2) && (s1 = s2); if not !found then incr k2 done; occurs := !found; incr k1 done; !occurs ;; let sub_set l1 l2 = match (l1,l2) with ([],_) -> true | ([x],_) -> List.mem x l2 | _ -> sub_set_q l1 l2 ;; (* (* currently unused! *) let equal_sets_q l1 l2 = (* returns whether all elements of l1 occur in l2, and vice versa *) let a1 = Array.map (fun s -> (Hashtbl.hash s), s) (Array.of_list l1) in let a2 = Array.map (fun s -> (Hashtbl.hash s), s) (Array.of_list l2) in Array.sort aux_cmp a1; Array.sort aux_cmp a2; let equal = ref true in let k1 = ref 0 in let k2 = ref 0 in let k2_match = ref false in (* can only be false when !k2 = 0 *) while !equal && !k1 < Array.length a1 && !k2 < Array.length a2 do let (h1,s1) = a1.( !k1 ) in let (h2,s2) = a2.( !k2 ) in if (h1 == h2) && (s1 = s2) then ( incr k1; k2_match := true; (* a match for the k2 element has been found *) ) else ( if !k2_match then ( incr k2; while !k2 < Array.length a2 && (h2,s2) = a2.( !k2 ) do incr k2 done; if !k2 < Array.length a2 then ( let (h2',s2') = a2.( !k2 ) in if (h1 == h2') && (s1 = s2') then ( incr k1; ) else equal := false ) else equal := false ) else equal := false ) done; if !equal && !k1 = Array.length a1 && !k2 < Array.length a2 && !k1 > 0 then ( (* !k1 > 0 ==> a1 is not empty && !k2_match, * !k2 < length a2 ==> a2 is not empty *) let (h2,s2) = a2.( !k2 ) in incr k2; while !k2 < Array.length a2 && (h2,s2) = a2.( !k2 ) do incr k2 done; ); !equal && !k1 = Array.length a1 && !k2 = Array.length a2 ;; let equal_sets l1 l2 = match (l1,l2) with ([],[]) -> true | ([x],[y]) -> x = y | _ -> equal_sets_q l1 l2 ;; *) (**********************************************************************) (* definition of XDR values *) (**********************************************************************) type xdr_value_version = [ `V1 | `V2 | `V3 | `V4 | `Ocamlrpcgen ] type xdr_value = XV_int of int4 | XV_uint of uint4 | XV_hyper of int8 | XV_uhyper of uint8 | XV_enum of string | XV_float of fp4 | XV_double of fp8 | XV_opaque of string | XV_string of string | XV_array of xdr_value array | XV_struct of (string * xdr_value) list | XV_union_over_int of (int4 * xdr_value) | XV_union_over_uint of (uint4 * xdr_value) | XV_union_over_enum of (string * xdr_value) | XV_void | XV_enum_fast of int | XV_struct_fast of xdr_value array | XV_union_over_enum_fast of (int * xdr_value) | XV_array_of_string_fast of string array | XV_mstring of Netxdr_mstring.mstring | XV_direct of exn * int * (exn -> xdr_value) ;; let xv_true = XV_enum_fast 1 (* "TRUE" *);; let xv_false = XV_enum_fast 0 (* "FALSE" *);; let xv_none = XV_union_over_enum_fast (0,XV_void);; let xv_some v = XV_union_over_enum_fast (1,v);; exception Dest_failure let dest_xv_int v = match v with XV_int x -> x | _ -> raise Dest_failure;; let dest_xv_uint v = match v with XV_uint x -> x | _ -> raise Dest_failure;; let dest_xv_hyper v = match v with XV_hyper x -> x | _ -> raise Dest_failure;; let dest_xv_uhyper v = match v with XV_uhyper x -> x | _ -> raise Dest_failure;; let dest_xv_enum v = match v with XV_enum x -> x | _ -> raise Dest_failure;; let dest_xv_enum_fast v = match v with XV_enum_fast x -> x | _ -> raise Dest_failure;; let dest_xv_float v = match v with XV_float x -> x | _ -> raise Dest_failure;; let dest_xv_double v = match v with XV_double x -> x | _ -> raise Dest_failure;; let dest_xv_opaque v = match v with XV_opaque x -> x | _ -> raise Dest_failure;; let dest_xv_string v = match v with XV_string x -> x | _ -> raise Dest_failure;; let dest_xv_mstring v = match v with XV_mstring x -> x | _ -> raise Dest_failure;; let dest_xv_array v = match v with XV_array x -> x | _ -> raise Dest_failure;; let dest_xv_array_of_string_fast v = match v with XV_array_of_string_fast x -> x | _ -> raise Dest_failure;; let dest_xv_struct v = match v with XV_struct x -> x | _ -> raise Dest_failure;; let dest_xv_struct_fast v = match v with XV_struct_fast x -> x | _ -> raise Dest_failure;; let dest_xv_void v = match v with XV_void -> () | _ -> raise Dest_failure;; let dest_xv_union_over_int v = match v with XV_union_over_int x -> x | _ -> raise Dest_failure;; let dest_xv_union_over_uint v = match v with XV_union_over_uint x -> x | _ -> raise Dest_failure;; let dest_xv_union_over_enum v = match v with XV_union_over_enum x -> x | _ -> raise Dest_failure;; let dest_xv_union_over_enum_fast v = match v with XV_union_over_enum_fast x -> x | _ -> raise Dest_failure;; (**********************************************************************) (* definition of XDR types and type systems *) (**********************************************************************) (* restriction: it is not allowed to have an X_param as enumerator type * in union_over_enum. There must always be a real X_enum or, in a * type system, a resolvable X_type at this position. *) type xdr_type_term = X_int | X_uint | X_hyper | X_uhyper | X_enum of (string * int4) list | X_float | X_double | X_opaque_fixed of uint4 | X_opaque of uint4 | X_string of uint4 | X_mstring of string * uint4 | X_array_fixed of xdr_type_term * uint4 | X_array of xdr_type_term * uint4 | X_struct of (string * xdr_type_term) list | X_union_over_int of (int4 * xdr_type_term) list * xdr_type_term option | X_union_over_uint of (uint4 * xdr_type_term) list * xdr_type_term option | X_union_over_enum of xdr_type_term * (string * xdr_type_term) list * xdr_type_term option | X_void | X_type of string | X_param of string | X_rec of (string * xdr_type_term) (* define a recursive type *) | X_refer of string (* refer to a recursive type *) | X_direct of xdr_type_term * (Bytes.t -> int ref -> int -> exn) * (exn -> Bytes.t -> int ref -> unit) * (exn -> int) * (exn -> xdr_value) ;; module StringSet = Set.Make(String) ;; type xdr_type0 = { mutable term : xdr_term; mutable params : StringSet.t; (* "params" is normally only non-empty in the top node *) mutable min_size : int (* min_size: the minimum number of bytes every element of the array will take in XDR form. This does not include any inner parameters. *) } and xdr_term = T_int | T_uint | T_hyper | T_uhyper | T_enum of (string * int32) array (* array must be sorted by ascending int32 *) | T_float | T_double | T_opaque_fixed of uint4 | T_opaque of uint4 | T_string of uint4 | T_mstring of string * uint4 | T_array_fixed of xdr_type0 * uint4 | T_array of xdr_type0 * (* max size: *) uint4 | T_struct of (string * xdr_type0) array | T_union_over_int of (int4, xdr_type0) Hashtbl.t * xdr_type0 option | T_union_over_uint of (uint4, xdr_type0) Hashtbl.t * xdr_type0 option | T_union_over_enum of xdr_type0 * xdr_type0 option array * xdr_type0 option (* The array corresponds to the T_enum array. None means that the * constant is not mapped. *) | T_void | T_param of string | T_rec of (string * xdr_type0) | T_refer of (string * xdr_type0) | T_direct of xdr_type0 * (Bytes.t -> int ref -> int -> exn) * (exn -> Bytes.t -> int ref -> unit) * (exn -> int) * (exn -> xdr_value) ;; type xdr_type = xdr_type0 * xdr_type0 (* left: includes T_rec and T_refer, right: does not include T_rec, T_refer *) type xdr_type_term_system = (string * xdr_type_term) list ;; type xdr_type_system = (string * xdr_type) list (* export xdr_type_system in an opaque manner *) let t_name = function | T_int -> "T_int" | T_uint -> "T_uint" | T_hyper -> "T_hyper" | T_uhyper -> "T_uhyper" | T_enum _ -> "T_enum" | T_float -> "T_float" | T_double -> "T_double" | T_opaque_fixed _ -> "T_opaque_fixed" | T_opaque _ -> "T_opaque" | T_string _ -> "T_string" | T_mstring(_,_) -> "T_mstring" | T_array_fixed (_,_) -> "T_array_fixed" | T_array (_,_) -> "T_array" | T_struct _ -> "T_struct" | T_union_over_int(_,_) -> "T_union_over_int" | T_union_over_uint(_,_) -> "T_union_over_uint" | T_union_over_enum(_,_,_) -> "T_union_over_enum" | T_void -> "T_void" | T_param _ -> "T_param" | T_rec _ -> "T_rec" | T_refer _ -> "T_refer" | T_direct _ -> "T_direct" let x_bool = X_enum ["FALSE", int4_of_int 0; "TRUE", int4_of_int 1] ;; let x_optional t = X_union_over_enum (x_bool, ["TRUE", t; "FALSE", X_void], None) ;; let x_opaque_max = X_opaque (mk_uint4 ('\255', '\255', '\255', '\255'));; let x_string_max = X_string (mk_uint4 ('\255', '\255', '\255', '\255'));; let x_mstring_max name = X_mstring (name, mk_uint4 ('\255', '\255', '\255', '\255'));; let x_array_max t = X_array (t, (mk_uint4 ('\255', '\255', '\255', '\255')));; let fail_map_xv_enum_fast k = failwith ("Netxdr.map_xv_enum_fast [" ^ string_of_int k ^ "]") ;; let map_xv_enum_fast0 t v = match t.term with T_enum l -> let m = Array.length l in ( match v with XV_enum_fast k -> if k >= 0 && k < m then snd(Array.unsafe_get l k) else fail_map_xv_enum_fast 1 | XV_enum name -> let k = ref 0 in while !k < m && (fst l.( !k ) <> name) do incr k done; if !k >= m then fail_map_xv_enum_fast 2; snd(l.( !k )) | _ -> fail_map_xv_enum_fast 3 ) | _ -> fail_map_xv_enum_fast 4 let map_xv_enum_fast (_,t) v = map_xv_enum_fast0 t v let fail_map_xv_struct_fast k = failwith ("Netxdr.map_xv_struct_fast [" ^ string_of_int k ^ "]") ;; let map_xv_struct_fast0 t v = match t.term with T_struct decl -> let m = Array.length decl in ( match v with XV_struct_fast x -> let k = Array.length x in if k = m then x else fail_map_xv_struct_fast 1 | XV_struct l -> ( try Array.map (fun (name,y) -> List.assoc name l) decl with Not_found -> fail_map_xv_struct_fast 2 ) | _ -> fail_map_xv_struct_fast 3 ) | _ -> fail_map_xv_struct_fast 4 let map_xv_struct_fast (_,t) v = map_xv_struct_fast0 t v let fail_map_xv_union_over_enum_fast k = failwith ("Netxdr.map_xv_union_over_enum_fast [" ^ string_of_int k ^ "]") ;; let map_xv_union_over_enum_fast0 t v = match t.term with T_union_over_enum( { term = T_enum e }, u, u_dfl ) -> let m = Array.length e in assert( m = Array.length u ); ( match v with XV_union_over_enum_fast(k, x) -> if k >= 0 && k < m then (k, (snd e.(k)), x) else fail_map_xv_union_over_enum_fast 1 | XV_union_over_enum(name, x) -> let k = ref 0 in while !k < m && fst(e.( !k )) <> name do incr k done; if !k >= m then fail_map_xv_union_over_enum_fast 2; (!k, (snd e.(!k)), x) | _ -> fail_map_xv_union_over_enum_fast 3; ) | _ -> fail_map_xv_union_over_enum_fast 4 let map_xv_union_over_enum_fast (_,t) v = map_xv_union_over_enum_fast0 t v exception Xdr_format of string;; exception Xdr_format_message_too_long of xdr_value;; (* raised in unpack_xdr_value if the byte stream does not match * the expected type. The string is an explanation and might be * useful while debugging. In the special case Xdr_format_message_too_long * there are more bytes than expected, but a prefix matches the type. * The prefix is returned as xdr_value. *) let () = Netexn.register_printer (Xdr_format "") (function | Xdr_format s -> sprintf "Netxdr.Xdr_format(%S)" s | _ -> assert false ) exception Xdr_failure of string let safe_add x y = (* exported *) (* pre: x >= 0 && y >= 0 *) let s = x + y in if s < 0 then (* can only happen on 32 bit platforms *) raise(Xdr_failure "int overflow while computing size"); s let safe_mul x y = (* exported *) (* pre: x >= 0 && y >= 0 *) if x=0 || y=0 then 0 else let n = max_int / y in if x > n then raise(Xdr_failure "int overflow while computing size"); x * y (**********************************************************************) (* check if XDR types are well-formed *) (**********************************************************************) (* TODO: check on recursions without finite fix point. *) let rec validate_xdr_type_i1 (r:xdr_type_term -> xdr_type0) (b:(string * xdr_type0) list) (t:xdr_type_term) : xdr_type0 = (* r: function that resolves X_type references * t: the xdr_type_term to validate * b: list of recursive bindings * * raise Not_found on any error *) let mktype tm = { term = tm; params = StringSet.empty; min_size = (-1) } in (* min_size is calculated in a second pass *) match t with X_int -> mktype T_int | X_uint -> mktype T_uint | X_hyper -> mktype T_hyper | X_uhyper -> mktype T_uhyper | X_float -> mktype T_float | X_double -> mktype T_double | X_void -> mktype T_void | X_enum e -> let e_names, e_values = List.split e in if all_distinct e_names && all_distinct e_values then let ea = Array.map (fun (n,i) -> (n, Netnumber.int32_of_int4 i)) (Array.of_list e) in Array.sort (fun (_,i) (_,i') -> compare i i') ea; mktype (T_enum ea) else raise (Propagate "Bad enumeration type: double values") | X_opaque_fixed n -> mktype (T_opaque_fixed n) | X_opaque n -> mktype (T_opaque n) | X_string n -> mktype (T_string n) | X_mstring (name,n) -> mktype (T_mstring (name,n)) | X_array_fixed (s,n) -> let nL = int64_of_uint4 n in if nL > 0x3fff_ffff_ffffL then raise (Propagate "Bad fixed array: bound too high"); mktype (T_array_fixed(validate_xdr_type_i1 r b s, n)) | X_array (s,n) -> mktype (T_array (validate_xdr_type_i1 r b s, n)) | X_struct s -> let s_names, s_types = List.split s in if all_distinct s_names then mktype (T_struct (Array.of_list (List.map (fun (n,x) -> n,validate_xdr_type_i1 r b x) s))) else raise (Propagate "Bad struct type: components with same names found") | X_union_over_int (u, default) -> let u_values, u_types = List.split u in if all_distinct u_values then begin let default' = match default with Some d -> Some (validate_xdr_type_i1 r b d) | None -> None in let htbl = Hashtbl.create(List.length u) in List.iter (fun (n,x) -> let x' = validate_xdr_type_i1 r b x in Hashtbl.add htbl n x') u; mktype(T_union_over_int(htbl, default')) end else raise (Propagate "Bad union_over_int type: variants found with same tags") | X_union_over_uint (u,default) -> let u_values, u_types = List.split u in if all_distinct u_values then begin let default' = match default with Some d -> Some (validate_xdr_type_i1 r b d) | None -> None in let htbl = Hashtbl.create(List.length u) in List.iter (fun (n,x) -> let x' = validate_xdr_type_i1 r b x in Hashtbl.add htbl n x') u; mktype(T_union_over_uint(htbl, default')) end else raise (Propagate "Bad union_over_uint type: variants found with same tags") | X_union_over_enum (e,u,default) -> let e' = validate_xdr_type_i1 r b e in let u_values, u_types = List.split u in let el = match e'.term with T_enum x -> x | _ -> raise (Propagate "Bad union_over_enum type: discriminator is not enumerator") in let el_names, el_values = List.split (Array.to_list el) in if all_distinct u_values && sub_set u_values el_names then begin let default' = match default with Some d -> Some (validate_xdr_type_i1 r b d) | None -> None in mktype (T_union_over_enum (e', Array.map (fun (name, _) -> try Some(validate_xdr_type_i1 r b (List.assoc name u)) with Not_found -> default' ) el, default')) end else raise (Propagate "Bad union_over_enum type: variants found with identical tags") | X_type _ -> r t | X_param p -> mktype (T_param p) | X_rec (name, s) -> let node = mktype T_void in let t' = validate_xdr_type_i1 r ((name,node)::b) s in node.term <- T_rec (name, t'); node | X_refer name -> mktype (T_refer (name, List.assoc name b)) | X_direct(s, read, write, size, expand) -> mktype (T_direct (validate_xdr_type_i1 r b s, read, write, size, expand)) ;; let rec find_params (t:xdr_type0) : StringSet.t = (* collect all parameters *) match t.term with T_param p -> StringSet.singleton p | T_array_fixed (t',n) -> find_params t' | T_array (t',n) -> find_params t' | T_struct s -> Array.fold_left (fun set (s,t') -> StringSet.union (find_params t') set) StringSet.empty s | T_union_over_int (htbl,def_opt) -> Hashtbl.fold (fun n t' set -> StringSet.union (find_params t') set) htbl (match def_opt with None -> StringSet.empty | Some def -> find_params def) | T_union_over_uint (htbl,def_opt) -> Hashtbl.fold (fun n t' set -> StringSet.union (find_params t') set) htbl (match def_opt with None -> StringSet.empty | Some def -> find_params def) | T_union_over_enum (e,u,def_opt) -> Array.fold_left (fun set t' -> match t' with Some t'' -> StringSet.union (find_params t'') set | None -> set) (match def_opt with None -> StringSet.empty | Some def -> find_params def) u | T_rec (_,t') -> find_params t' | T_direct(t',_,_,_,_) -> find_params t' | _ -> StringSet.empty ;; (* Elimination of rec/refer *) let map_opt f o = match o with | None -> None | Some x -> Some(f x) let map_hashtbl f t = let acc = Hashtbl.create (Hashtbl.length t) in Hashtbl.iter (fun k v -> let v' = f k v in Hashtbl.add acc k v'; (* !!! reverses order of bindings !!! *) ) t; acc let rec elim_rec t = (* get rid of T_rec and T_refer *) match t.term with | T_int | T_uint | T_hyper | T_uhyper | T_enum _ | T_float | T_double | T_opaque_fixed _ | T_opaque _ | T_string _ | T_mstring _ | T_void | T_param _ -> t | T_array_fixed(t',n) -> { t with term = T_array_fixed(elim_rec t', n) } | T_array(t',n) -> { t with term = T_array(elim_rec t', n) } | T_struct s -> let s' = Array.map (fun (n,t') -> (n, elim_rec t')) s in { t with term = T_struct s' } | T_union_over_int(ht, dt) -> let ht' = map_hashtbl (fun c t' -> elim_rec t') ht in let dt' = map_opt elim_rec dt in { t with term = T_union_over_int(ht', dt') } | T_union_over_uint(ht, dt) -> let ht' = map_hashtbl (fun c t' -> elim_rec t') ht in let dt' = map_opt elim_rec dt in { t with term = T_union_over_uint(ht', dt') } | T_union_over_enum(et,ct,dt) -> let et' = elim_rec et in let ct' = Array.map (map_opt elim_rec) ct in let dt' = map_opt elim_rec dt in { t with term = T_union_over_enum(et',ct',dt') } | T_rec(n,t') -> elim_rec t' | T_refer(n,t') -> t' | T_direct(t',read,write,size,expand) -> { t with term = T_direct(elim_rec t', read, write, size, expand) } let rec calc_min_size t = let ( ++ ) x y = (* pre: x >= 0 && y >= 0 *) let s = x + y in if s < 0 then (* can only happen on 32 bit platforms *) raise(Propagate("Minimum size of type exceeds limit")); s in let calc_for_union u_snd default = ( match default with | None -> () | Some d -> calc_min_size d ); List.iter (fun t' -> calc_min_size t') u_snd; let l = (match default with | None -> [] | Some d -> [d] ) @ u_snd in assert(l <> []); 4 ++ (List.fold_left (fun acc x -> min acc x.min_size ) ((List.hd l).min_size) (List.tl l) ) in let hashtbl_vals h = Hashtbl.fold (fun _ v acc -> v :: acc) h [] in let optarray_elems a = Array.fold_left (fun acc x_opt -> match x_opt with | None -> acc | Some x -> x :: acc ) [] a in if t.min_size < 0 then ( t.min_size <- 0; (* for stopping recursions *) ( match t.term with T_int -> t.min_size <- 4 | T_uint -> t.min_size <- 4 | T_hyper -> t.min_size <- 8 | T_uhyper -> t.min_size <- 8 | T_float -> t.min_size <- 4 | T_double -> t.min_size <- 8 | T_void -> t.min_size <- 0 | T_enum e -> t.min_size <- 4 | T_opaque_fixed n -> let nL = int64_of_uint4 n in let min_size = if nL=0L then 0 else Int64.to_int(Int64.succ (Int64.div (Int64.pred nL) 4L)) in t.min_size <- min_size | T_opaque n -> t.min_size <- 4 | T_string n -> t.min_size <- 4 | T_mstring (name,n) -> t.min_size <- 4 | T_array_fixed (s,n) -> calc_min_size s; if s.min_size = 0 then raise(Propagate "Array elements must not have length 0"); let nL = int64_of_uint4 n in let n_max = max_int / s.min_size in if nL > Int64.of_int n_max then raise(Propagate "Minimum size of type exceeds limit"); let iL = Int64.of_int s.min_size in t.min_size <- Int64.to_int (Int64.mul nL iL) | T_array (s,n) -> calc_min_size s; if s.min_size = 0 then raise(Propagate "Array elements must not have length 0"); t.min_size <- 4 | T_struct s -> Array.iter (fun (_,t') -> calc_min_size t') s; t.min_size <- (Array.fold_left (fun acc (_,x) -> acc ++ x.min_size ) 0 s ) | T_union_over_int (u, default) -> t.min_size <- calc_for_union (hashtbl_vals u) default | T_union_over_uint (u, default) -> t.min_size <- calc_for_union (hashtbl_vals u) default | T_union_over_enum (e,u,default) -> t.min_size <- calc_for_union (optarray_elems u) default | T_param p -> (* not optimal, but we do not know it better at this point *) t.min_size <- 0 | T_direct(t',_,_,_,_) -> calc_min_size t'; t.min_size <- t'.min_size | T_rec (_,t') -> calc_min_size t'; t.min_size <- t'.min_size | T_refer (r,t') -> calc_min_size t'; t.min_size <- t'.min_size; (* eprintf "%s: " r*) ); (* eprintf "min_size(%s) = %d\n" (t_name t.term) t.min_size*) ) let rec validate_xdr_type (t:xdr_type_term) : xdr_type = let r n = raise (Propagate "Cannot resolve X_type element") in try let t0' = validate_xdr_type_i1 r [] t in let pl = find_params t0' in t0'.params <- pl; let t1' = elim_rec t0' in calc_min_size t0'; calc_min_size t1'; (t0', t1') with Not_found -> failwith "Netxdr.validate_xdr_type: unspecified error" | Propagate s -> failwith ("Netxdr.validate_xdr_type: " ^ s) ;; let params (t:xdr_type) = StringSet.fold (fun p acc -> p :: acc) (fst t).params [] let rec expand_X_type (s:xdr_type_system) (t:xdr_type_term) : xdr_type0 = match t with X_type n -> begin let rec r s1 s2 = match s2 with [] -> raise (Propagate ("Cannot resolve X_type " ^ n)) | (n',t') :: s2' -> if n = n' then fst t' else r (s1 @ [n',t']) s2' in r [] s end | _ -> raise (Propagate "Found X_type where it must not occur") ;; let validate_xdr_type_system (s:xdr_type_term_system) : xdr_type_system = let names = List.map fst s in if all_distinct names then begin let rec r (s1:xdr_type_system) (s2:xdr_type_term_system) = match s2 with [] -> [] | (n,t) :: s2' -> let t2 = begin try let t0' = validate_xdr_type_i1 (expand_X_type s1) [] t in let pl = find_params t0' in t0'.params <- pl; let t1' = elim_rec t0' in calc_min_size t0'; calc_min_size t1'; (t0',t1') with Not_found -> failwith "Netxdr.validate_xdr_type_system: unspecified error" | Propagate s -> failwith ("Netxdr.validate_xdr_type_system: " ^ s) end in (n,t2)::(r (s1 @ [n,t2]) s2') in r [] s end else failwith "Netxdr.validate_xdr_type_system: type system has members with same names" ;; (**********************************************************************) (* the reverse way *) (**********************************************************************) let rec xdr_type_term0 (t:xdr_type0) : xdr_type_term = let conv_list l = List.map (fun (x, t') -> x, xdr_type_term0 t') l in let conv_htbl htbl = Hashtbl.fold (fun x t' l -> (x, xdr_type_term0 t') :: l) htbl [] in let conv_option p = match p with None -> None | Some t' -> Some (xdr_type_term0 t') in match t.term with T_int -> X_int | T_uint -> X_uint | T_hyper -> X_hyper | T_uhyper -> X_uhyper | T_enum l -> X_enum (Array.to_list (Array.map (fun (n,i) -> (n,Netnumber.int4_of_int32 i)) l)) | T_float -> X_float | T_double -> X_double | T_void -> X_void | T_param p -> X_param p | T_opaque_fixed n -> X_opaque_fixed n | T_opaque n -> X_opaque n | T_string n -> X_string n | T_mstring(name,n)-> X_mstring(name,n) | T_array_fixed (t', n) -> X_array_fixed (xdr_type_term0 t',n) | T_array (t', n) -> X_array (xdr_type_term0 t',n) | T_struct s -> X_struct (conv_list (Array.to_list s)) | T_rec (n, t') -> X_rec (n, xdr_type_term0 t') | T_refer (n, t') -> X_refer n | T_union_over_int (u,d) -> X_union_over_int (conv_htbl u, conv_option d) | T_union_over_uint (u,d) -> X_union_over_uint (conv_htbl u, conv_option d) | T_union_over_enum ( { term = T_enum e } as e_term ,u,d) -> let u' = List.flatten (Array.to_list (Array.mapi (fun k t'_opt -> match t'_opt with Some t' -> let name = fst(e.(k)) in [ name, xdr_type_term0 t' ] | None -> [] ) u ) ) in X_union_over_enum (xdr_type_term0 e_term, u', conv_option d) | T_direct (t', read, write, size, expand) -> X_direct (xdr_type_term0 t',read, write, size, expand) | _ -> assert false ;; let xdr_type_term (t:xdr_type) : xdr_type_term = xdr_type_term0 (fst t) let xdr_type_term_system (s:xdr_type_system) : xdr_type_term_system = List.map (fun (n,t) -> n,xdr_type_term t) s ;; (**********************************************************************) (* expand X_type members relative to given systems *) (**********************************************************************) (* The implementation of "expanded_xdr_type_term" repeats many phrases * that have been defined for "validate_xdr_type" in a very similar * way. * TODO: Currently many checks have been left out *) let rec expanded_xdr_type_term (s:xdr_type_term_system) (t:xdr_type_term) : xdr_type_term = match t with X_array_fixed (t',n) -> X_array_fixed ((expanded_xdr_type_term s t'), n) | X_array (t',n) -> X_array ((expanded_xdr_type_term s t'), n) | X_struct st -> let s_names, s_types = List.split st in X_struct (List.combine s_names (List.map (expanded_xdr_type_term s) s_types)) | X_union_over_int (u,default) -> let u_values, u_types = List.split u in let default' = match default with Some d -> Some (expanded_xdr_type_term s d) | None -> None in X_union_over_int (List.combine u_values (List.map (expanded_xdr_type_term s) u_types), default') | X_union_over_uint (u,default) -> let u_values, u_types = List.split u in let default' = match default with Some d -> Some (expanded_xdr_type_term s d) | None -> None in X_union_over_uint (List.combine u_values (List.map (expanded_xdr_type_term s) u_types), default') | X_union_over_enum (e,u,default) -> let u_values, u_types = List.split u in let default' = match default with Some d -> Some (expanded_xdr_type_term s d) | None -> None in X_union_over_enum ( (expanded_xdr_type_term s e), (List.combine u_values (List.map (expanded_xdr_type_term s) u_types)), default') | X_type n -> let rec r s1 s2 = match s2 with [] -> failwith ("Netxdr.expanded_xdr_type_term: cannot resolve X_type " ^ n) | (n',t') :: s2' -> if n = n' then expanded_xdr_type_term s1 t' else r (s1 @ [n',t']) s2' in r [] s | X_rec (n, t') -> X_rec (n, expanded_xdr_type_term s t') | X_direct (t',read, write, size, expand) -> X_direct ((expanded_xdr_type_term s t'), read, write, size, expand) | _ -> t ;; let expanded_xdr_type (s:xdr_type_system) (t:xdr_type_term) : xdr_type = try let t0 = validate_xdr_type_i1 (expand_X_type s) [] t in let t1 = elim_rec t0 in calc_min_size t0; calc_min_size t1; (t0,t1) with Not_found -> failwith "Netxdr.expanded_xdr_type: unspecified error" | Propagate s -> failwith ("Netxdr.expanded_xdr_type: " ^ s) ;; (**********************************************************************) (* test on compatibility *) (**********************************************************************) let are_compatible (s1:xdr_type) (s2:xdr_type) : bool = (* implementation: * enum, struct and union members can be swapped *) failwith "Netxdr.are_compatible: not implemented" ;; (**********************************************************************) (* common implementation of value_matches_type & pack_xdr_value *) (**********************************************************************) (* pack: interestingly, two loops over the value where one loop only determines the size of the final buffer are _faster_ than a single loop over the value doing everything. Whoever understands that. *) type encoder = Netxdr_mstring.mstring list -> Netxdr_mstring.mstring list type decoder = Bytes.t -> int -> int -> (Bytes.t * int) let overflow() = raise(Xdr_failure "overflow in ++") let ( ++ ) x y = (* pre: x >= 0 && y >= 0 *) let s = x + y in if s < 0 then overflow(); s let get_string_decoration_size x_len n = (* header field plus padding *) let x_len_u = uint4_of_int x_len in let x_len_mod_4 = x_len land 3 in if Netnumber.le_uint4 x_len_u n then begin (if x_len_mod_4 = 0 then 4 else 8 - x_len_mod_4 ) end else raise (Xdr_failure "string is longer than allowed") let sizefn_string n x = let x_len = String.length x in get_string_decoration_size x_len n + x_len let sizefn_mstring n x = let x_len = x#length in get_string_decoration_size x_len n + x_len let pack_size (v:xdr_value) (t:xdr_type0) (get_param:string->xdr_type) (get_encoder:string->encoder option) : int = (* returned size does not include mstrings! *) let rec get_size v t = match t.term with | T_int -> 4 | T_uint -> 4 | T_hyper -> 8 | T_uhyper -> 8 | T_enum e -> 4 | T_float -> 4 | T_double -> 8 | T_opaque_fixed n -> let x = dest_xv_opaque v in let i = int_of_uint4 n in if String.length x <> i then raise (Xdr_failure "opaque string has unexpected length"); let i4 = i land 3 in if i4=0 then i else i+(4-i4) | T_opaque n -> let x = dest_xv_opaque v in sizefn_string n x | T_string n -> let x = dest_xv_string v in sizefn_string n x | T_mstring(_,n) -> (* for an mstring we only count the length field plus padding *) let x = dest_xv_mstring v in let l = x#length in get_string_decoration_size l n | T_array_fixed (t',n) -> get_array_size v t' n (fun m n -> m=n) | T_array (t',n) -> 4 + get_array_size v t' n Netnumber.le_uint4 | T_struct s -> let v_array = map_xv_struct_fast0 t v in let sum = ref 0 in Array.iteri (fun k v_component -> sum := !sum ++ get_size v_component (snd s.(k))) v_array; !sum | T_union_over_int (u,default) -> let i,x = dest_xv_union_over_int v in let t' = try Hashtbl.find u i with Not_found -> match default with Some d -> d | None -> raise (Xdr_failure "T_union_over_int") in 4 ++ get_size x t' | T_union_over_uint (u,default) -> let i,x = dest_xv_union_over_uint v in let t' = try Hashtbl.find u i with Not_found -> match default with Some d -> d | None -> raise (Xdr_failure "T_union_over_uint") in 4 ++ get_size x t' | T_union_over_enum (et,u,default) -> let k,i,x = map_xv_union_over_enum_fast0 t v in let t' = match u.(k) with Some u_t -> u_t | None -> ( match default with Some d -> d | None -> raise (Xdr_failure "T_union_over_enum") ) in 4 ++ get_size x t' | T_void -> 0 | T_param n -> let t' = get_param n in let enc_opt = get_encoder n in if enc_opt = None then get_size v (snd t') else 0 | T_rec (n, t') -> get_size v t' | T_refer (n, t') -> get_size v t' | T_direct(t', _, _, _, _) -> ( match v with | XV_direct(_,size,_) -> size | _ -> get_size v t' ) and get_array_size v t' n cmp = (* w/o array header *) (* TODO: optimize arrays of types with fixed repr length *) match v with | XV_array x -> (* generic *) let m = uint4_of_int (Array.length x) in if cmp m n then ( let s = ref 0 in Array.iter (fun v' -> s := !s ++ get_size v' t') x; !s ) else raise (Xdr_failure "array length mismatch") | XV_array_of_string_fast x -> ( match t'.term with | T_string sn -> let m = uint4_of_int (Array.length x) in if cmp m n then ( let sum = ref 0 in Array.iter (fun s -> sum := !sum ++ sizefn_string sn s) x; !sum ) else raise (Xdr_failure "array length mismatch") | T_direct(t1, _, _, _, _) -> get_array_size v t1 n cmp | _ -> raise Dest_failure ) | _ -> raise Dest_failure in get_size v t let print_string_padding l buf pos = let n = 4-(l land 3) in if n < 4 then begin let p = !pos in if n >= 1 then Bytes.unsafe_set buf p '\000'; if n >= 2 then Bytes.unsafe_set buf (p + 1) '\000'; if n >= 3 then Bytes.unsafe_set buf (p + 2) '\000'; pos := p + n end let rec pack_mstring (v:xdr_value) (t:xdr_type0) (get_param:string->xdr_type) (get_encoder:string->encoder option) : Netxdr_mstring.mstring list = (* The recursion over pack_mstring is only used for encoded parameters *) let size = pack_size v t get_param get_encoder in (* all sanity checks are done here! Also, [size] does not include the size for mstrings (only the length field, and padding), and it does not include encoded parameters *) let buf = Bytes.create size in let buf_start = ref 0 in let buf_pos = ref 0 in let result = ref [] in (* The resulting mstrings in reverse order *) let save_buf() = if !buf_pos > !buf_start then ( let x = Netxdr_mstring.bytes_based_mstrings # create_from_bytes buf !buf_start (!buf_pos - !buf_start) false in result := x :: !result; buf_start := !buf_pos ) in let print_string s l = Bytes.blit_string s 0 buf !buf_pos l; (* FIXME: unsafe_blit_string ? *) buf_pos := !buf_pos + l; print_string_padding l buf buf_pos in let rec pack v t = match t.term with T_int -> let x = dest_xv_int v in Netnumber.BE.write_int4_unsafe buf !buf_pos x; buf_pos := !buf_pos + 4 | T_uint -> let x = dest_xv_uint v in Netnumber.BE.write_uint4_unsafe buf !buf_pos x; buf_pos := !buf_pos + 4 | T_hyper -> let x = dest_xv_hyper v in Netnumber.BE.write_int8_unsafe buf !buf_pos x; buf_pos := !buf_pos + 8 | T_uhyper -> let x = dest_xv_uhyper v in Netnumber.BE.write_uint8_unsafe buf !buf_pos x; buf_pos := !buf_pos + 8 | T_enum e -> let i = map_xv_enum_fast0 t v in Netnumber.BE.write_int4_unsafe buf !buf_pos (int4_of_int32 i); buf_pos := !buf_pos + 4 | T_float -> let x = dest_xv_float v in let s = Netnumber.BE.fp4_as_string x in String.unsafe_blit s 0 buf !buf_pos 4; buf_pos := !buf_pos + 4 | T_double -> let x = dest_xv_double v in let s = Netnumber.BE.fp8_as_string x in String.unsafe_blit s 0 buf !buf_pos 8; buf_pos := !buf_pos + 8 | T_opaque_fixed n -> let x = dest_xv_opaque v in print_string x (String.length x) | T_opaque n -> let x = dest_xv_opaque v in let x_len = String.length x in Netnumber.BE.write_uint4_unsafe buf !buf_pos (uint4_of_int x_len); buf_pos := !buf_pos + 4; print_string x x_len | T_string n -> let x = dest_xv_string v in let x_len = String.length x in Netnumber.BE.write_uint4_unsafe buf !buf_pos (uint4_of_int x_len); buf_pos := !buf_pos + 4; print_string x x_len | T_mstring(_,n) -> let x = dest_xv_mstring v in let x_len = x#length in Netnumber.BE.write_uint4_unsafe buf !buf_pos (uint4_of_int x_len); buf_pos := !buf_pos + 4; save_buf(); result := x :: !result; print_string_padding x_len buf buf_pos | T_array_fixed (t',n) -> pack_array v t' n false | T_array (t',n) -> pack_array v t' n true | T_struct s -> let v_array = map_xv_struct_fast0 t v in Array.iteri (fun k v_component -> pack v_component (snd s.(k))) v_array | T_union_over_int (u,default) -> let i,x = dest_xv_union_over_int v in let t' = try Hashtbl.find u i with Not_found -> match default with Some d -> d | None -> raise (Xdr_failure "T_union_over_int") in Netnumber.BE.write_int4_unsafe buf !buf_pos i; buf_pos := !buf_pos + 4; pack x t' | T_union_over_uint (u,default) -> let i,x = dest_xv_union_over_uint v in let t' = try Hashtbl.find u i with Not_found -> match default with Some d -> d | None -> raise (Xdr_failure "T_union_over_uint") in Netnumber.BE.write_uint4_unsafe buf !buf_pos i; buf_pos := !buf_pos + 4; pack x t' | T_union_over_enum (et,u,default) -> let k,i,x = map_xv_union_over_enum_fast0 t v in let t' = match u.(k) with Some u_t -> u_t | None -> ( match default with Some d -> d | None -> raise (Xdr_failure "T_union_over_enum") ) in Netnumber.BE.write_int4_unsafe buf !buf_pos (int4_of_int32 i); buf_pos := !buf_pos + 4; pack x t' | T_void -> () | T_param n -> let t' = get_param n in let enc_opt = get_encoder n in ( match enc_opt with | None -> pack v (snd t') | Some enc -> save_buf(); let l = pack_mstring v (snd t') (fun _ -> assert false) (fun _ -> assert false) in let e = enc l in result := List.rev e @ !result ) | T_rec (n, t') -> pack v t' | T_refer (n, t') -> pack v t' | T_direct(t', _, write, _, _) -> ( match v with | XV_direct(x,xv_size,_) -> let old = !buf_pos in write x buf buf_pos; (* Printf.eprintf "old=%d new=%d size=%d\n" old !buf_pos size; *) assert(!buf_pos = old + xv_size); | _ -> pack v t' ) and pack_array v t' n have_array_header = match v with | XV_array x -> (* generic *) if have_array_header then pack_array_header (Array.length x); Array.iter (fun v' -> pack v' t') x | XV_array_of_string_fast x -> ( match t'.term with | T_string n -> if have_array_header then pack_array_header (Array.length x); Array.iter (fun s -> let s_len = String.length s in Netnumber.BE.write_uint4_unsafe buf !buf_pos (uint4_of_int s_len); buf_pos := !buf_pos + 4; print_string s s_len ) x | T_direct(t1,_,_,_,_) -> pack_array v t1 n have_array_header | _ -> raise Dest_failure ) | _ -> raise Dest_failure and pack_array_header x_len = Netnumber.BE.write_uint4_unsafe buf !buf_pos (uint4_of_int x_len); buf_pos := !buf_pos + 4; in pack v t; save_buf(); List.rev !result ;; let write_string_fixed n x buf pos = (* exported *) let x_len = String.length x in if x_len <> n then raise (Xdr_failure "fixed string has bad length"); String.unsafe_blit x 0 buf !pos x_len; pos := !pos + x_len; print_string_padding x_len buf pos let write_string x buf pos = (* exported *) let x_len = String.length x in Netnumber.BE.write_uint4_unsafe buf !pos (uint4_of_int x_len); pos := !pos + 4; String.unsafe_blit x 0 buf !pos x_len; pos := !pos + x_len; print_string_padding x_len buf pos let value_matches_type (v:xdr_value) ((_,t):xdr_type) (p:(string * xdr_type) list) : bool = if StringSet.for_all (fun n -> List.mem_assoc n p) t.params && List.for_all (fun (n,t') -> StringSet.is_empty (fst t').params) p then try ignore(pack_size v t (fun n -> List.assoc n p) (fun _ -> None)); true with _ -> (* we assume here that no other errors can occur *) false else false ;; (**********************************************************************) (* pack and unpack values *) (**********************************************************************) let pack_xdr_value_as_mstrings ?(rm = false) ?(encode = []) (v:xdr_value) ((_,t):xdr_type) (p:(string * xdr_type) list) = if StringSet.for_all (fun n -> List.mem_assoc n p) t.params && List.for_all (fun (n,t') -> StringSet.is_empty (fst t').params) p then try let mstrings0 = pack_mstring v t (fun n -> List.assoc n p) (fun n -> try Some(List.assoc n encode) with Not_found -> None) in let rm_prefix = if rm then let s = "\000\000\000\000" in [ Netxdr_mstring.bytes_based_mstrings # create_from_string s 0 4 false ] else [] in rm_prefix @ mstrings0 with | Dest_failure -> raise(Xdr_failure "Netxdr.pack_xdr_value_as_mstring [2]: XDR type mismatch") | Netnumber.Cannot_represent _ -> raise (Xdr_failure "Netxdr.pack_xdr_value_as_mstring [3]: integer not representable") | Netnumber.Out_of_range -> raise(Xdr_failure "Netxdr.pack_xdr_value_as_mstring [4]: index out of range") | Failure s -> raise(Xdr_failure ("Netxdr.pack_xdr_value_as_mstring [5]: " ^ s)) else raise(Xdr_failure "Netxdr.pack_xdr_value_as_mstring [1]") ;; let pack_xdr_value_as_bytes ?rm ?encode v ty p = let mstrings = pack_xdr_value_as_mstrings ?rm ?encode v ty p in Netxdr_mstring.concat_mstrings_bytes mstrings let pack_xdr_value_as_string ?rm ?encode v ty p = let mstrings = pack_xdr_value_as_mstrings ?rm ?encode v ty p in Netxdr_mstring.concat_mstrings mstrings let pack_xdr_value ?encode v ty p print = let mstrings = pack_xdr_value_as_mstrings ?encode v ty p in List.iter (fun ms -> let (s,p) = ms#as_bytes in print (Bytes.sub s p ms#length) ) mstrings (* "let rec" prevents that these functions are inlined. This is wanted here, because these are error cases, and for a function call less code is generated than for raising an exception *) let rec raise_xdr_format_too_short () = raise (Xdr_format "message too short") let rec raise_xdr_format_value_not_included () = raise (Xdr_format "value not included in enumeration") let rec raise_xdr_format_maximum_length () = raise (Xdr_format "maximum length of field exceeded") let rec raise_xdr_format_undefined_descriminator() = raise (Xdr_format "undefined discriminator") let rec find_enum (e : (string * int32) array) (i : int32) = (* no inlining! *) let rec loop lb ub = (* The element is between lb and ub *) if lb > ub then raise_xdr_format_value_not_included (); let m = (ub + lb) lsr 1 in let x_m = snd(e.(m)) in if i = x_m then (* Found! *) m else if i < x_m then loop lb (m-1) else (* i > x_m *) loop (m+1) ub in loop 0 (Array.length e - 1) ;; (* DEBUG*) (* let hex_dump_s s pos len = let b = Buffer.create 100 in for k = 0 to len - 1 do let c = s.[pos+k] in bprintf b "%02x " (Char.code c) done; Buffer.contents b *) let read_string_fixed n str k k_end = (* exported *) let k0 = !k in let m = if n land 3 = 0 then n else n+4-(n land 3) in if k0 > k_end - m then raise_xdr_format_too_short (); let s = Bytes.create n in Bytes.unsafe_blit str k0 s 0 n; k := k0 + m; Bytes.unsafe_to_string s let read_string n str k k_end = (* exported *) let k0 = !k in k := k0 + 4; if !k > k_end then raise_xdr_format_too_short(); let m = Netnumber.BE.read_uint4_unsafe str k0 in (* Test: n < m as unsigned int32: *) if Netnumber.lt_uint4 n m then raise_xdr_format_maximum_length (); read_string_fixed (int_of_uint4 m) str k k_end let empty_mf = (Hashtbl.create 1 : (string, Netxdr_mstring.mstring_factory) Hashtbl.t) let rec unpack_term ?(pos = 0) ?len ?(fast = false) ?(prefix = false) ?(mstring_factories = empty_mf) ?(xv_version = if fast then `Ocamlrpcgen else `V1) (str:Bytes.t) (t:xdr_type0) (get_param:string->xdr_type) (get_decoder:string->decoder option) : xdr_value * int = (* The recursion over unpack_term is only used for decoding encrypted parameters *) let xv_version = if xv_version = `Ocamlrpcgen then `V4 else xv_version in let v2 = (xv_version <> `V1) in (* meaning: at least v2 *) let v3 = v2 && (xv_version <> `V2) in let v4 = v3 && (xv_version <> `V3) in let len = match len with None -> Bytes.length str - pos | Some l -> l in if pos < 0 || len < 0 || len > Bytes.length str - pos then invalid_arg "Netxdr.unpack_xdr_value"; let k_end = pos+len in let k = ref pos in let rec read_fp4 k0 = if k0 + 4 > k_end then raise_xdr_format_too_short(); k := !k + 4; Netnumber.BE.read_fp4 str k0 in let rec read_fp8 k0 = if k0 + 8 > k_end then raise_xdr_format_too_short(); k := !k + 8; Netnumber.BE.read_fp8 str k0 in let rec read_enum e k0 = k := k0 + 4; if !k > k_end then raise_xdr_format_too_short(); let i = Netnumber.int32_of_int4(Netnumber.BE.read_int4_unsafe str k0) in let j = find_enum e i in (* returns array position, or Xdr_format *) if v2 then XV_enum_fast j else XV_enum(fst(e.(j))) in let rec read_string_or_opaque n k0 = k := k0 + 4; if !k > k_end then raise_xdr_format_too_short(); let m = Netnumber.BE.read_uint4_unsafe str k0 in (* Test: n < m as unsigned int32: *) if Netnumber.lt_uint4 n m then raise_xdr_format_maximum_length (); read_string_fixed (int_of_uint4 m) str k k_end in let rec read_mstring name n k0 = let factory = try Hashtbl.find mstring_factories name with Not_found -> ( try Hashtbl.find mstring_factories "*" with Not_found -> failwith "read_mstring: no such factory" ) in k := k0 + 4; if !k > k_end then raise_xdr_format_too_short(); let m = Netnumber.BE.read_uint4_unsafe str k0 in (* Test: n < m as unsigned int32: *) if Netnumber.lt_uint4 n m then raise_xdr_format_maximum_length (); let m = int_of_uint4 m in let p = if m land 3 = 0 then m else m+4-(m land 3) in if !k > k_end - p then raise_xdr_format_too_short (); let ms = factory # create_from_bytes str !k m false in k := !k + p; ms in let rec unpack_array t' p = (* Estimate the maximum p *) (* eprintf "unpack_array: t' = %s\n" (t_name t'.term);*) assert(t'.min_size > 0); let p_max = (k_end - !k) / t'.min_size in if p > p_max then raise_xdr_format_too_short(); match t'.term with | T_string n -> let n' = Netnumber.logical_int32_of_uint4 n in let a = Array.make p "" in let k' = Netsys_xdr.s_read_string_array_unsafe str !k (k_end - !k) n' a in if k' = (-1) then raise_xdr_format_too_short(); if k' = (-2) then raise_xdr_format_maximum_length (); k := k'; if v3 then XV_array_of_string_fast a else XV_array(Array.map (fun s -> XV_string s) a) | _ -> let a = Array.make p XV_void in for i = 0 to p-1 do Array.unsafe_set a i (unpack t') done; XV_array a and unpack t = let k0 = !k in (* fprintf stderr "unpack k=%d t=%s\n%!" k0 (t_name t.term); *) match t.term with T_int -> k := k0 + 4; if !k > k_end then raise_xdr_format_too_short(); XV_int (Netnumber.BE.read_int4_unsafe str k0) | T_uint -> k := k0 + 4; if !k > k_end then raise_xdr_format_too_short(); XV_uint (Netnumber.BE.read_uint4_unsafe str k0) | T_hyper -> k := k0 + 8; if !k > k_end then raise_xdr_format_too_short(); XV_hyper (Netnumber.BE.read_int8_unsafe str k0) | T_uhyper -> k := !k + 8; if k0 > k_end then raise_xdr_format_too_short(); XV_uhyper (Netnumber.BE.read_uint8_unsafe str k0) | T_enum e -> read_enum e k0 | T_float -> XV_float (read_fp4 k0) | T_double -> XV_double (read_fp8 k0) | T_opaque_fixed n -> XV_opaque (read_string_fixed (int_of_uint4 n) str k k_end) | T_opaque n -> XV_opaque (read_string_or_opaque n k0) | T_string n -> XV_string (read_string_or_opaque n k0) | T_mstring(name,n) -> XV_mstring (read_mstring name n k0) | T_array_fixed (t',n) -> let p = int_of_uint4 n in unpack_array t' p | T_array (t',n) -> k := k0 + 4; let m = Netnumber.BE.read_uint4 str k0 in if Netnumber.lt_uint4 n m then raise_xdr_format_maximum_length (); unpack_array t' (int_of_uint4 m) | T_struct s -> if v2 then XV_struct_fast ( Array.map (fun (name,t') -> unpack t') s ) else XV_struct (List.map (fun (name,t') -> (name,unpack t')) (Array.to_list s) ) | T_union_over_int (u,default) -> unpack_union_over_int u default k0 | T_union_over_uint (u,default) -> unpack_union_over_uint u default k0 | T_union_over_enum ( { term = T_enum e },u,default) -> unpack_union_over_enum e u default k0 | T_void -> XV_void | T_param p -> let t' = get_param p in let dec_opt = get_decoder p in ( match dec_opt with | None -> unpack (snd t') | Some decoder -> let (dec_s, n) = decoder str k0 (k_end - k0) in k := !k + n; assert( !k <= k_end ); let (v, p) = unpack_term ~mstring_factories ~xv_version dec_s (snd t') (fun _ -> assert false) (fun _ -> None) in v ) | T_rec (_, t') | T_refer (_, t') -> unpack t' | T_direct(t', read, _, _, expand) -> if v4 then let k0 = !k in let xv = read str k k_end in XV_direct(xv, !k-k0, expand) else unpack t' | _ -> assert false and unpack_union_over_int u default k0 = k := k0 + 4; let n = Netnumber.BE.read_int4 str k0 in let t' = try Hashtbl.find u n with Not_found -> match default with None -> raise_xdr_format_undefined_descriminator() | Some d -> d in XV_union_over_int (n, unpack t') and unpack_union_over_uint u default k0 = k := k0 + 4; let n = Netnumber.BE.read_uint4 str k0 in let t' = try Hashtbl.find u n with Not_found -> match default with None -> raise_xdr_format_undefined_descriminator() | Some d -> d in XV_union_over_uint (n, unpack t') and unpack_union_over_enum e u default k0 = k := k0 + 4; let i = Netnumber.int32_of_int4 (Netnumber.BE.read_int4 str k0) in let j = find_enum e i (* returns array position, or Xdr_format *) in let t' = match u.(j) with Some u_t -> u_t | None -> ( match default with Some d -> d | None -> raise_xdr_format_undefined_descriminator() ) in if v2 then XV_union_over_enum_fast(j, unpack t') else let name = fst(e.(j)) in XV_union_over_enum(name, unpack t') in try let v = unpack t in if prefix || !k = k_end then (v, !k - pos) else ( (* fprintf stderr "Too LONG: k=%d k_end=%d\n%!" !k k_end; fprintf stderr "Dump: %s\n%!" (hex_dump_s str pos (k_end-pos)); *) raise (Xdr_format_message_too_long v) ) with Cannot_represent _ -> raise (Xdr_format "implementation restriction") | Out_of_range -> raise (Xdr_format "message too short") ;; let unpack_xdr_value ?pos ?len ?fast ?prefix ?mstring_factories ?xv_version ?(decode=[]) (str:Bytes.t) ((_,t):xdr_type) (p:(string * xdr_type) list) : xdr_value = if StringSet.for_all (fun n -> List.mem_assoc n p) t.params && List.for_all (fun (n,t') -> StringSet.is_empty (fst t').params) p then fst(unpack_term ?pos ?len ?fast ?prefix ?mstring_factories ?xv_version str t (fun n -> List.assoc n p) (fun n -> try Some(List.assoc n decode) with Not_found -> None) ) else failwith "Netxdr.unpack_xdr_value" ;; let unpack_xdr_value_l ?pos ?len ?fast ?prefix ?mstring_factories ?xv_version ?(decode=[]) (str:Bytes.t) ((_,t):xdr_type) (p:(string * xdr_type) list) : xdr_value * int = if StringSet.for_all (fun n -> List.mem_assoc n p) t.params && List.for_all (fun (n,t') -> StringSet.is_empty (fst t').params) p then unpack_term ?pos ?len ?fast ?prefix ?mstring_factories ?xv_version str t (fun n -> List.assoc n p) (fun n -> try Some(List.assoc n decode) with Not_found -> None) else failwith "Netxdr.unpack_xdr_value" ;; let unpack_xdr_value_str ?pos ?len ?fast ?prefix ?mstring_factories ?xv_version ?decode (str:string) ty p = unpack_xdr_value_l ?pos ?len ?fast ?prefix ?mstring_factories ?xv_version ?decode (Bytes.unsafe_of_string str) ty p type ctx = { ctx_direct : bool; ctx_direct_sub : bool; ctx_copy_string : string -> string } let default_ctx = (* By default, disallow direct mappings *) { ctx_direct = false; ctx_direct_sub = false; ctx_copy_string = String.copy } let expand_ctx = (* Special ctx for the generated "_expand_" functions *) { ctx_direct = false; ctx_direct_sub = true; ctx_copy_string = String.copy } let direct_ctx = (* This ctx allows to use direct mappings *) { ctx_direct = true; ctx_direct_sub = true; ctx_copy_string = (fun s -> s) } ocamlnet-4.1.2/src/netstring/netstring_tstring.mli0000644000175000017500000000622312731530350021044 0ustar gerdgerd(* $Id$ *) (** Support module for tagged strings *) open Netsys_types (** GADT for encoding the string type (string/bytes/bigarray) *) type _ tstring_kind = | String_kind : string tstring_kind | Bytes_kind : Bytes.t tstring_kind | Memory_kind : memory tstring_kind (** Operations to call on strings *) type 't tstring_ops = { kind : 't tstring_kind option; length : 't -> int; get : 't -> int -> char; unsafe_get : 't -> int -> char; unsafe_get3 : 't -> int -> int; (** get 3 chars packed into one int (first char shifted by 16 bits, second char shifted by 8 bits, third char unshifted) *) copy : 't -> 't; string : 't -> string; (** if possible this function does not make a copy *) bytes : 't -> Bytes.t; (** if possible this function does not make a copy *) sub : 't -> int -> int -> 't; substring : 't -> int -> int -> string; subbytes : 't -> int -> int -> Bytes.t; subpoly : 'u . 'u tstring_kind -> 't -> int -> int -> 'u; blit_to_bytes : 't -> int -> Bytes.t -> int -> int -> unit; blit_to_memory : 't -> int -> memory -> int -> int -> unit; index_from : 't -> int -> char -> int; index_from3 : 't -> int -> int -> char -> char -> char -> int; (** finds any of three chars. The second int is the search radius *) rindex_from : 't -> int -> char -> int; rindex_from3 : 't -> int -> int -> char -> char -> char -> int; (** finds any of three chars. The second int is the search radius *) } (** GADT for hiding the type parameter *) type tstring_ops_box = | Tstring_ops_box : 't tstring_kind * 't tstring_ops -> tstring_ops_box (** GADT for hiding the type parameter *) type tstring_box = | Tstring_box : 't tstring_kind * 't tstring_ops * 't -> tstring_box (** GADT for hiding the type parameter. Warning: This GADT does not permit you to recover the kind of string *) type tstring_polybox = | Tstring_polybox : 't tstring_ops * 't -> tstring_polybox val string_ops : string tstring_ops (** Implementation of the operations for [string] *) val bytes_ops : Bytes.t tstring_ops (** Implementation of the operations for [bytes] *) val memory_ops : memory tstring_ops (** Implementation of the operations for [memory] *) val ops_of_tstring : tstring -> tstring_ops_box (** Create a [Tstring_ops_box] *) (** A polymorphic function for strings *) type 'a with_fun = { with_fun : 's . 's tstring_ops -> 's -> 'a } val with_tstring : 'a with_fun -> tstring -> 'a (** [with_tstring f ts]: Calls [f.with_fun] with the right implementation of the [tstring_ops] argument *) val length_tstring : tstring -> int (** Get the length of a tagged string *) val tstring_of_tbuffer : tbuffer -> tstring (** Get the tagged string of a tagged buffer *) val polymorph_string_transformation : (string->string) -> 's tstring_ops -> 't tstring_kind -> 's -> 't (** [polymorph_string_transformation f ops kind s]: Converts [s] to a string, runs [f] on this string, and converts the result to the type demanded by [kind] *) (**/**) val bytes_subpoly : 'u tstring_kind -> Bytes.t -> int -> int -> 'u ocamlnet-4.1.2/src/netstring/netgssapi_auth.ml0000644000175000017500000002745112731530350020130 0ustar gerdgerd(* $Id$ *) module type CONFIG = sig val raise_error : string -> 'a end module Manage(G:Netsys_gssapi.GSSAPI) = struct let delete_context ctx_opt () = match ctx_opt with | None -> () | Some ctx -> G.interface # delete_sec_context ~context:ctx ~out:(fun ~minor_status ~major_status () -> ()) () let format_status ?fn ?minor_status ((calling_error,routine_error,_) as major_status) = if calling_error <> `None || routine_error <> `None then ( let error = Netsys_gssapi.string_of_major_status major_status in let minor_s = match minor_status with | None -> "" | Some n -> G.interface # display_minor_status ~mech_type:[||] ~status_value:n ~out:(fun ~status_strings ~minor_status ~major_status () -> " (details: " ^ String.concat "; " status_strings ^ ")" ) () in let s1 = match fn with | None -> "" | Some n -> " for " ^ n in "GSSAPI error" ^ s1 ^ ": " ^ error ^ minor_s ) else let s1 = match fn with | None -> "" | Some n -> " " ^ n in "GSSAPI call" ^ s1 ^ " is successful" end module Auth (G:Netsys_gssapi.GSSAPI)(C:CONFIG) = struct module M = Manage(G) let check_status ?fn ?minor_status ((calling_error,routine_error,_) as major_status) = if calling_error <> `None || routine_error <> `None then C.raise_error(M.format_status ?fn ?minor_status major_status) let get_initiator_name (config:Netsys_gssapi.client_config) = match config#initiator_name with | None -> G.interface # no_name (* means: default credential *) | Some(cred_string, cred_name_type) -> G.interface # import_name ~input_name:cred_string ~input_name_type:cred_name_type ~out:(fun ~output_name ~minor_status ~major_status () -> check_status ~fn:"import_name" ~minor_status major_status; output_name ) () let get_acceptor_name (config:Netsys_gssapi.server_config) = match config#acceptor_name with | None -> G.interface # no_name (* means: default credential *) | Some(cred_string, cred_name_type) -> G.interface # import_name ~input_name:cred_string ~input_name_type:cred_name_type ~out:(fun ~output_name ~minor_status ~major_status () -> check_status ~fn:"import_name" ~minor_status major_status; output_name ) () let acquire_initiator_cred ~initiator_name (config:Netsys_gssapi.client_config) = let mech_type = config#mech_type in G.interface # acquire_cred ~desired_name:initiator_name ~time_req:`Indefinite ~desired_mechs:(if mech_type = [| |] then [] else [mech_type]) ~cred_usage:`Initiate ~out:(fun ~cred ~actual_mechs ~time_rec ~minor_status ~major_status () -> check_status ~fn:"acquire_cred" ~minor_status major_status; cred ) () let get_initiator_cred ~initiator_name (config:Netsys_gssapi.client_config) = (* let mech_type = config#mech_type in *) match config#initiator_cred with | Some(G.Credential cred) -> (* Check that this is the cred for init_name *) if not(G.interface # is_no_name initiator_name) then ( G.interface # inquire_cred ~cred ~out:(fun ~name ~lifetime ~cred_usage ~mechanisms ~minor_status ~major_status () -> check_status ~fn:"inquire_cred" ~minor_status major_status; G.interface # compare_name ~name1:name ~name2:initiator_name ~out:(fun ~name_equal ~minor_status ~major_status () -> check_status ~fn:"compare_name" ~minor_status major_status; if not name_equal then C.raise_error "The user name does not \ match the credential" ) () ) () ); cred | _ -> acquire_initiator_cred ~initiator_name config let get_acceptor_cred ~acceptor_name (config:Netsys_gssapi.server_config) = G.interface # acquire_cred ~desired_name:acceptor_name ~time_req:`Indefinite ~desired_mechs:config#mech_types ~cred_usage:`Accept ~out:(fun ~cred ~actual_mechs ~time_rec ~minor_status ~major_status () -> check_status ~fn:"acquire_cred" ~minor_status major_status; cred ) () let get_target_name ?default (config:Netsys_gssapi.client_config) = if config#target_name=None && default=None then G.interface#no_name else let (name_string, name_type) = match config#target_name with | Some(n,t) -> (n,t) | None -> ( match default with | None -> assert false | Some(n,t) -> (n,t) ) in G.interface # import_name ~input_name:name_string ~input_name_type:name_type ~out:(fun ~output_name ~minor_status ~major_status () -> check_status ~fn:"import_name" ~minor_status major_status; output_name ) () let get_client_flags config = let flags1 = [ `Conf_flag, config#privacy; `Integ_flag, config#integrity ] @ config#flags in List.map fst (List.filter (fun (n,lev) -> lev <> `None) flags1) let get_server_flags = get_client_flags type t1 = < flags : (Netsys_gssapi.ret_flag * Netsys_gssapi.support_level) list; integrity : Netsys_gssapi.support_level; privacy : Netsys_gssapi.support_level; > let check_flags (config : t1) act_flags = let flags1 = [ `Conf_flag, config#privacy; `Integ_flag, config#integrity ] @ config#flags in let needed = List.map fst (List.filter (fun (n,lev) -> lev = `Required) flags1) in let missing = List.filter (fun flag -> not (List.mem flag act_flags) ) needed in if missing <> [] then C.raise_error ("GSSAPI error: the security mechanism could not \ grant the following required context flags: " ^ String.concat ", " (List.map Netsys_gssapi.string_of_flag missing)) let check_client_flags config act_flags = check_flags (config :> t1) act_flags let check_server_flags config act_flags = check_flags (config :> t1) act_flags let get_display_name name = G.interface # display_name ~input_name:name ~out:(fun ~output_name ~output_name_type ~minor_status ~major_status () -> check_status ~fn:"display_name" ~minor_status major_status; output_name, output_name_type ) () let get_exported_name name = G.interface # export_name ~name:name ~out:(fun ~exported_name ~minor_status ~major_status () -> check_status ~fn:"export_name" ~minor_status major_status; exported_name ) () let init_sec_context ~initiator_cred ~context ~target_name ~req_flags ~chan_bindings ~input_token config = let mech_type = config#mech_type in G.interface # init_sec_context ~initiator_cred ~context ~target_name ~mech_type ~req_flags ~time_req:None ~chan_bindings ~input_token ~out:(fun ~actual_mech_type ~output_context ~output_token ~ret_flags ~time_rec ~minor_status ~major_status () -> try check_status ~fn:"init_sec_context" ~minor_status major_status; let ctx = match output_context with | None -> assert false | Some ctx -> ctx in let (_,_,suppl) = major_status in let cont_flag = List.mem `Continue_needed suppl in if cont_flag then ( assert(output_token <> ""); (ctx, output_token, ret_flags, None) ) else ( check_client_flags config ret_flags; let props = ( object method mech_type = actual_mech_type method flags = ret_flags method time = time_rec end ) in (ctx, output_token, ret_flags, Some props) ) with | error -> M.delete_context output_context (); raise error ) () let accept_sec_context ~acceptor_cred ~context ~chan_bindings ~input_token config = G.interface # accept_sec_context ~context ~acceptor_cred ~input_token ~chan_bindings ~out:(fun ~src_name ~mech_type ~output_context ~output_token ~ret_flags ~time_rec ~delegated_cred ~minor_status ~major_status () -> try check_status ~fn:"accept_sec_context" ~minor_status major_status; let ctx = match output_context with | None -> assert false | Some ctx -> ctx in let (_,_,suppl) = major_status in let cont_flag = List.mem `Continue_needed suppl in if cont_flag then ( assert(output_token <> ""); (ctx, output_token, ret_flags, None) ) else ( check_server_flags config ret_flags; let (props : Netsys_gssapi.server_props) = ( object method mech_type = mech_type method flags = ret_flags method time = time_rec method initiator_name = get_display_name src_name method initiator_name_exported = get_exported_name src_name method deleg_credential = if List.mem `Deleg_flag ret_flags then let t = G.interface # inquire_cred ~cred:delegated_cred ~out:(fun ~name ~lifetime ~cred_usage ~mechanisms ~minor_status ~major_status () -> check_status ~fn:"inquire_cred" ~minor_status major_status; lifetime ) () in Some(G.Credential delegated_cred, t) else None end ) in (ctx, output_token, ret_flags, Some props) ) with | error -> M.delete_context output_context (); raise error ) () end ocamlnet-4.1.2/src/netstring/netmech_spnego_http.mli0000644000175000017500000001344312731530350021314 0ustar gerdgerd(* $Id$ *) (** SPNEGO (GSSAPI) authentication for HTTP *) (** This module enables the [Negotiate] authentication method for HTTP, which is an encapsulation of the SPNEGO protocol. SPNEGO in turn is a layer on top of GSSAPI, and adds mechanism negotiation. This is the usual way of kerberizing HTTP. This implementation of the [Negotiate] method requires a HTTPS connection by default. Running it over unencrypted HTTP would be possible, but we don't do it because the additional security can be easily lost. In particular, a man-in-the-middle could steal credentials, or he could run a downgrade attack on the authentication method (and replace it by e.g. "basic"). The [Negotiate] authentication method is somewhat special because it implicitly authenticates the whole connection, and not only a single message. At least this is what MS Windows implements, the reference implementation of this authentication method. Other implementations nevertheless require per-message authentication, e.g. Apache's mod_auth_kerb. Both behaviors are basically compatible to each other if implemented with some care. In order to keep authenticated messages somewhat separate, this client only submits requests bearing [Negotiate] headers on TCP connections that have been specially created for this purpose. Basically, the authenticated communication with the server is seen as a separate transport subsystem. The flow of requests/responses is as follows: - A fresh HTTP request does not carry any authentication data. Because of this, it is sent over the normal transports to the server. - The server replies with a 401 response and an SPNEGO token. - The client authenticates the request (usually this is a one step action) - The authenticated request cannot be sent over the existing TCP connection. A second connection is created which will be used for authenticated requests only. - The request is sent over this connection. - The server responds with content data This way we can be sure that requests are handled normally that either need not to be authenticated at all, or that are authenticated with different methods. Technically, the route of the HTTP request depends on the [transport_layer] ID. As long as the HTTP request has an ID of {!Nethttp_client.https_trans_id}, it will go over the normal transports. If the ID changes to {!Nethttp_client.spnego_trans_id}, the separate transports for SPNEGO are used. If it is already known that the HTTP request needs to be authenticated with SPNEGO, the authentication protocol can be abbreviated by directly switching to {!Nethttp_client.spnego_trans_id}: {[ c # set_transport_layer Nethttp_client.spnego_trans_id ]} The effect is that only one request/response cycle is needed to process the request [c] (except it is the very first request). Although GSSAPI mechanisms, and in particular Kerberos often do not require a password, you need to set up a "key" object. User and password of this key are ignored. The realm, however, must be set to the fixed string "SPNEGO" (and {b not} to the Kerberos realm). A full example how to use this method: {[ module A = Netmech_spnego_http.SPNEGO(Netmech_spnego_http.Default)(Netgss.System) let keys = new Nethttp_client.key_ring () let () = keys # add_key (key ~user:"" ~password:"" ~realm:"SPNEGO" ~domain:[]) let a = new Nethttp_client.generic_auth_handler keys [ (module A : Nethttp.HTTP_MECHANISM) ] let p = new Nethttp_client.pipeline let () = p # add_auth_handler a let c = new Nethttp_client.get "https://gps.dynxs.de/krb/" let () = p # add c; p # run() ]} At the moment, this authentication protocol cannot be configured, so you always get the default behaviour of GSSAPI. {b Statefulness:} The GSSAPI is stateful. Our HTTP authentication interface is stateless. We cannot hide the statefulness of the GSSAPI, and because of this old versions of sessions are invalidated. E.g. this does not work {[ let s1 = A.client_emit_resonse s0 m1 uri1 hdr1 let s2 = A.client_emit_resonse s0 m2 uri2 hdr2 ]} and the second attempt to continue with the old session [s0] will fail. *) (** Configure {!Netmech_spnego_http} *) module type PROFILE = sig val acceptable_transports_http : Nethttp.transport_layer_id list (** Which transport IDs are acceptable for authenticated requests on unencrypted connections. For new requests, the first ID of this list is the preferred ID. *) val acceptable_transports_https : Nethttp.transport_layer_id list (** Which transport IDs are acceptable for authenticated requests on HTTPS-secured connections. For new requests, the first ID of this list is the preferred ID. *) val enable_delegation : bool (** Whether to allow delegation of the credentials to the server. Enabling this means that the server can impersonate the local identity, so use with care. Also, getting tokens carrying the delegation information can be time-consuming (and the HTTP client will simply block while doing so). *) val deleg_credential : exn option (** If you already have a credential, you can set this value to the exception [Credential c] (from the GSSAPI provider). *) end (** The default profile for {!Netmech_spnego_http}: Use [spnego_trans_id] for the https transport, and reject any unencrypted transport (empty list). Delegations are off. *) module Default : PROFILE (** The SPNEGO mechanism for HTTP, see {!Netmech_spnego_http} *) module SPNEGO(P:PROFILE)(G:Netsys_gssapi.GSSAPI) : Nethttp.HTTP_CLIENT_MECHANISM ocamlnet-4.1.2/src/netstring/netstring_tstring.ml0000644000175000017500000002235712731530350020701 0ustar gerdgerd(* $Id$ *) open Netsys_types type _ tstring_kind = | String_kind : string tstring_kind | Bytes_kind : Bytes.t tstring_kind | Memory_kind : memory tstring_kind type 't tstring_ops = { kind : 't tstring_kind option; length : 't -> int; get : 't -> int -> char; unsafe_get : 't -> int -> char; unsafe_get3 : 't -> int -> int; (* get 3 chars packed into one int *) copy : 't -> 't; string : 't -> string; bytes : 't -> Bytes.t; sub : 't -> int -> int -> 't; substring : 't -> int -> int -> string; subbytes : 't -> int -> int -> Bytes.t; subpoly : 'u . 'u tstring_kind -> 't -> int -> int -> 'u; blit_to_bytes : 't -> int -> Bytes.t -> int -> int -> unit; blit_to_memory : 't -> int -> memory -> int -> int -> unit; index_from : 't -> int -> char -> int; index_from3 : 't -> int -> int -> char -> char -> char -> int; rindex_from : 't -> int -> char -> int; rindex_from3 : 't -> int -> int -> char -> char -> char -> int; } type tstring_ops_box = | Tstring_ops_box : 't tstring_kind * 't tstring_ops -> tstring_ops_box type tstring_box = | Tstring_box : 't tstring_kind * 't tstring_ops * 't -> tstring_box type tstring_polybox = | Tstring_polybox : 't tstring_ops * 't -> tstring_polybox (* Warning: you cannot match on the type 't here *) let str_subpoly : type u . u tstring_kind -> string -> int -> int -> u = function | String_kind -> String.sub | Bytes_kind -> (fun s pos len -> let b = Bytes.create len in Bytes.blit_string s pos b 0 len; b ) | Memory_kind -> (fun s pos len -> let m = Bigarray.Array1.create Bigarray.char Bigarray.c_layout len in Netsys_mem.blit_string_to_memory s pos m 0 len; m ) let str_index_from3 s p n c1 c2 c3 = (* FIXME: implement in C *) let sn = String.length s in if n < 0 || p < 0 || p > sn-n then invalid_arg "index_from3"; let lim = p+n in let p = ref p in while !p < lim && (let c = String.unsafe_get s !p in c <> c1 && c <> c2 && c <> c3) do incr p done; if !p >= lim then raise Not_found; !p let str_rindex_from3 s p n c1 c2 c3 = (* FIXME: implement in C *) let sn = String.length s in if n < 0 || p < -1 || p >= sn || n-1 > p then invalid_arg "rindex_from"; let lim = p-n+1 in let p = ref p in while !p >= lim && (let c = String.unsafe_get s !p in c <> c1 && c <> c2 && c <> c3) do decr p done; if !p < lim then raise Not_found; !p let string_ops = { kind = Some String_kind; length = String.length; get = String.get; unsafe_get = String.unsafe_get; unsafe_get3 = (fun s k -> let c0 = Char.code (String.unsafe_get s k) in let c1 = Char.code (String.unsafe_get s (k+1)) in let c2 = Char.code (String.unsafe_get s (k+2)) in (c0 lsl 16) lor (c1 lsl 8) lor c2 ); copy = String.copy; (* ... for the time being ... *) string = (fun s -> s); bytes = Bytes.of_string; sub = String.sub; substring = String.sub; subbytes = (fun s p l -> let b = Bytes.create l in Bytes.blit_string s p b 0 l; b ); subpoly = str_subpoly; blit_to_bytes = Bytes.blit_string; blit_to_memory = Netsys_mem.blit_string_to_memory; index_from = String.index_from; index_from3 = str_index_from3; rindex_from = String.rindex_from; rindex_from3 = str_rindex_from3; } let bytes_index_from3 s p n c1 c2 c3 = str_index_from3 (Bytes.unsafe_to_string s) p n c1 c2 c3 let bytes_rindex_from3 s p n c1 c2 c3 = str_rindex_from3 (Bytes.unsafe_to_string s) p n c1 c2 c3 let bytes_subpoly : type u . u tstring_kind -> Bytes.t -> int -> int -> u = function | String_kind -> Bytes.sub_string | Bytes_kind -> Bytes.sub | Memory_kind -> (fun s pos len -> let m = Bigarray.Array1.create Bigarray.char Bigarray.c_layout len in Netsys_mem.blit_bytes_to_memory s pos m 0 len; m ) let bytes_ops = { kind = Some Bytes_kind; length = Bytes.length; get = Bytes.get; unsafe_get = Bytes.unsafe_get; unsafe_get3 = (fun s k -> let c0 = Char.code (Bytes.unsafe_get s k) in let c1 = Char.code (Bytes.unsafe_get s (k+1)) in let c2 = Char.code (Bytes.unsafe_get s (k+2)) in (c0 lsl 16) lor (c1 lsl 8) lor c2 ); copy = Bytes.copy; string = Bytes.to_string; bytes = (fun s -> s); sub = Bytes.sub; substring = Bytes.sub_string; subbytes = Bytes.sub; subpoly = bytes_subpoly; blit_to_bytes = Bytes.blit; blit_to_memory = Netsys_mem.blit_bytes_to_memory; index_from = Bytes.index_from; index_from3 = bytes_index_from3; rindex_from = Bytes.rindex_from; rindex_from3 = bytes_rindex_from3; } let mem_index_from3 m p n c1 c2 c3 = (* FIXME: implement in C *) let sn = Bigarray.Array1.dim m in if n < 0 || p < 0 || p > sn-n then invalid_arg "index_from"; let lim = p+n in let p = ref p in while !p < lim && (let c = Bigarray.Array1.unsafe_get m !p in c <> c1 && c <> c2 && c <> c3) do incr p done; if !p >= lim then raise Not_found; !p let mem_index_from m p c = let sn = Bigarray.Array1.dim m in mem_index_from3 m p (sn-p) c c c let mem_rindex_from3 m p n c1 c2 c3 = (* FIXME: implement in C *) let sn = Bigarray.Array1.dim m in if n < 0 || p < -1 || p >= sn || n-1 > p then invalid_arg "rindex_from"; let lim = p-n+1 in let p = ref p in while !p >= lim && (let c = Bigarray.Array1.unsafe_get m !p in c <> c1 && c <> c2 && c <> c3) do decr p done; if !p < lim then raise Not_found; !p let mem_rindex_from m p c = mem_rindex_from3 m p (p+1) c c c let mem_sub m1 p len = let m2 = Bigarray.Array1.create Bigarray.char Bigarray.c_layout len in Bigarray.Array1.blit (Bigarray.Array1.sub m1 p len) m2; m2 let mem_subpoly : type u . u tstring_kind -> memory -> int -> int -> u = function | String_kind -> (fun m pos len -> Netsys_mem.string_of_memory (Bigarray.Array1.sub m pos len) ) | Bytes_kind -> (fun m pos len -> Netsys_mem.bytes_of_memory (Bigarray.Array1.sub m pos len) ) | Memory_kind -> mem_sub let memory_ops = { kind = Some Memory_kind; length = (Bigarray.Array1.dim : memory -> int); get = Bigarray.Array1.get; unsafe_get = Bigarray.Array1.unsafe_get; unsafe_get3 = (fun s k -> let c0 = Char.code (Bigarray.Array1.unsafe_get s k) in let c1 = Char.code (Bigarray.Array1.unsafe_get s (k+1)) in let c2 = Char.code (Bigarray.Array1.unsafe_get s (k+2)) in (c0 lsl 16) lor (c1 lsl 8) lor c2 ); copy = (fun m1 -> let n = Bigarray.Array1.dim m1 in mem_sub m1 0 n ); string = Netsys_mem.string_of_memory; bytes = Netsys_mem.bytes_of_memory; sub = mem_sub; substring = (fun m p l -> let m1 = Bigarray.Array1.sub m p l in Netsys_mem.string_of_memory m1 ); subbytes = (fun m p l -> let m1 = Bigarray.Array1.sub m p l in Netsys_mem.bytes_of_memory m1 ); subpoly = mem_subpoly; blit_to_bytes = Netsys_mem.blit_memory_to_bytes; blit_to_memory = (fun m1 p1 m2 p2 l -> let sub1 = Bigarray.Array1.sub m1 p1 l in let sub2 = Bigarray.Array1.sub m2 p2 l in Bigarray.Array1.blit sub1 sub2 ); index_from = mem_index_from; index_from3 = mem_index_from3; rindex_from = mem_rindex_from; rindex_from3 = mem_rindex_from3; } let ops_of_tstring = function | `String _ -> Tstring_ops_box(String_kind, string_ops) | `Bytes _ -> Tstring_ops_box(Bytes_kind, bytes_ops) | `Memory _ -> Tstring_ops_box(Memory_kind, memory_ops) type 'a with_fun = { with_fun : 's . 's tstring_ops -> 's -> 'a } let with_tstring : 'a with_fun -> tstring -> 'a = fun f -> function | `String s -> f.with_fun string_ops s | `Bytes s -> f.with_fun bytes_ops s | `Memory s -> f.with_fun memory_ops s let length_tstring ts = with_tstring { with_fun = (fun ops s -> ops.length s) } ts let polymorph_string_transformation : type s t . (string->string) -> s tstring_ops -> t tstring_kind -> s -> t = (fun f ops out_kind s -> let s' = f (ops.string s) in match out_kind with | String_kind -> s' | Bytes_kind -> Bytes.of_string s' | Memory_kind -> Netsys_mem.memory_of_string s' ) let tstring_of_tbuffer = function | `Bytes s -> `Bytes s | `String s -> `Bytes s | `Memory m -> `Memory m ocamlnet-4.1.2/src/netstring/nethttp.ml0000644000175000017500000017276712731530350016613 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * Nethttp: Basic definitions for the HTTP protocol *) type protocol_version = int * int type protocol_attribute = [ `Secure_https ] type protocol = [ `Http of (protocol_version * protocol_attribute list) | `Other ] let string_of_protocol = function | `Http((m,n),_) -> "HTTP/" ^ string_of_int m ^ "." ^ string_of_int n | `Other -> failwith "string_of_protocol" let http_re = Netstring_str.regexp "HTTP/\\([0-9]+\\)\\.\\([0-9]+\\)$" let protocol_of_string s = match Netstring_str.string_match http_re s 0 with | Some m -> ( try `Http ((int_of_string (Netstring_str.matched_group m 1 s), int_of_string (Netstring_str.matched_group m 2 s)), []) with Failure _ -> `Other (* Probably denial-of-service attack! *) ) | None -> `Other type http_status = (* 1xx: (informational) *) [ `Continue | `Switching_protocols (* 2xx: (successful) *) | `Ok | `Created | `Accepted | `Non_authoritative | `No_content | `Reset_content | `Partial_content (* 3xx: (redirection) *) | `Multiple_choices | `Moved_permanently | `Found | `See_other | `Not_modified | `Use_proxy | `Temporary_redirect (* 4xx: (client error) *) | `Bad_request | `Unauthorized | `Payment_required | `Forbidden | `Not_found | `Method_not_allowed | `Not_acceptable | `Proxy_auth_required | `Request_timeout | `Conflict | `Gone | `Length_required | `Precondition_failed | `Request_entity_too_large | `Request_uri_too_long | `Unsupported_media_type | `Requested_range_not_satisfiable | `Expectation_failed (* 5xx: (server error) *) | `Internal_server_error | `Not_implemented | `Bad_gateway | `Service_unavailable | `Gateway_timeout | `Http_version_not_supported ] let int_of_http_status = function (* 1xx: (informational) *) | `Continue -> 100 | `Switching_protocols -> 101 (* 2xx: (successful) *) | `Ok -> 200 | `Created -> 201 | `Accepted -> 202 | `Non_authoritative -> 203 | `No_content -> 204 | `Reset_content -> 205 | `Partial_content -> 206 (* 3xx: (redirection) *) | `Multiple_choices -> 300 | `Moved_permanently -> 301 | `Found -> 302 | `See_other -> 303 | `Not_modified -> 304 | `Use_proxy -> 305 | `Temporary_redirect -> 307 (* 4xx: (client error) *) | `Bad_request -> 400 | `Unauthorized -> 401 | `Payment_required -> 402 | `Forbidden -> 403 | `Not_found -> 404 | `Method_not_allowed -> 405 | `Not_acceptable -> 406 | `Proxy_auth_required -> 407 | `Request_timeout -> 408 | `Conflict -> 409 | `Gone -> 410 | `Length_required -> 411 | `Precondition_failed -> 412 | `Request_entity_too_large -> 413 | `Request_uri_too_long -> 414 | `Unsupported_media_type -> 415 | `Requested_range_not_satisfiable -> 416 | `Expectation_failed -> 417 (* 5xx: (server error) *) | `Internal_server_error -> 500 | `Not_implemented -> 501 | `Bad_gateway -> 502 | `Service_unavailable -> 503 | `Gateway_timeout -> 504 | `Http_version_not_supported -> 505 let string_of_http_status = function (* 1xx: (informational) *) | `Continue -> "Continue" | `Switching_protocols -> "Switching Protocols" (* 2xx: (successful) *) | `Ok -> "OK" | `Created -> "Created" | `Accepted -> "Accepted" | `Non_authoritative -> "Non-authoritative Information" | `No_content -> "No Content" | `Reset_content -> "Reset Content" | `Partial_content -> "Partial Content" (* 3xx: (redirection) *) | `Multiple_choices -> "Multiple Choices" | `Moved_permanently -> "Moved Permanently" | `Found -> "Found" | `See_other -> "See Other" | `Not_modified -> "Not Modified" | `Use_proxy -> "Use Proxy" | `Temporary_redirect -> "Temporary Redirect" (* 4xx: (client error) *) | `Bad_request -> "Bad Request" | `Unauthorized -> "Unauthorized" | `Payment_required -> "Payment Required" | `Forbidden -> "Forbidden" | `Not_found -> "Not Found" | `Method_not_allowed -> "Method Not Allowed" | `Not_acceptable -> "Not Acceptable" | `Proxy_auth_required -> "Proxy Authorization Required" | `Request_timeout -> "Request Timeout" | `Conflict -> "Conflict" | `Gone -> "Gone" | `Length_required -> "Length Required" | `Precondition_failed -> "Precondition Failed" | `Request_entity_too_large -> "Request Entity Too Large" | `Request_uri_too_long -> "Request URI Too Long" | `Unsupported_media_type -> "Unsupported Media Type" | `Requested_range_not_satisfiable -> "Request Range Not Satisfiable" | `Expectation_failed -> "Expectation Failed" (* 5xx: (server error) *) | `Internal_server_error -> "Internal Server Error" | `Not_implemented -> "Not Implemented" | `Bad_gateway -> "Bad Gateway" | `Service_unavailable -> "Service Unavailable" | `Gateway_timeout -> "Gateway Timeout" | `Http_version_not_supported -> "HTTP Version Not Supported" let http_status_of_int = function (* 1xx: (informational) *) | 100 -> `Continue | 101 -> `Switching_protocols (* 2xx: (successful) *) | 200 -> `Ok | 201 -> `Created | 202 -> `Accepted | 203 -> `Non_authoritative | 204 -> `No_content | 205 -> `Reset_content | 206 -> `Partial_content (* 3xx: (redirection) *) | 300 -> `Multiple_choices | 301 -> `Moved_permanently | 302 -> `Found | 303 -> `See_other | 304 -> `Not_modified | 305 -> `Use_proxy | 307 -> `Temporary_redirect (* 4xx: (client error) *) | 400 -> `Bad_request | 401 -> `Unauthorized | 402 -> `Payment_required | 403 -> `Forbidden | 404 -> `Not_found | 405 -> `Method_not_allowed | 406 -> `Not_acceptable | 407 -> `Proxy_auth_required | 408 -> `Request_timeout | 409 -> `Conflict | 410 -> `Gone | 411 -> `Length_required | 412 -> `Precondition_failed | 413 -> `Request_entity_too_large | 414 -> `Request_uri_too_long | 415 -> `Unsupported_media_type | 416 -> `Requested_range_not_satisfiable | 417 -> `Expectation_failed (* 5xx: (server error) *) | 500 -> `Internal_server_error | 501 -> `Not_implemented | 502 -> `Bad_gateway | 503 -> `Service_unavailable | 504 -> `Gateway_timeout | 505 -> `Http_version_not_supported | _ -> raise Not_found let base_code code = if code >= 100 && code < 200 then 100 else if code >= 200 && code < 300 then 200 else if code >= 300 && code < 400 then 300 else if code >= 400 && code < 500 then 400 else 500 type http_method = string * string (** Method name, URI *) type cache_control_token = [ `No_store | `Max_age of int | `Max_stale of int option | `Min_fresh of int | `No_transform | `Only_if_cached | `Public | `Private of string list | `No_cache of string list | `Must_revalidate | `Proxy_revalidate | `S_maxage of int | `Extension of string * string option ] type etag = [ `Weak of string | `Strong of string ] let weak_validator_match e1 e2 = match (e1,e2) with | (`Strong s1, `Strong s2) -> s1 = s2 | (`Strong s1, `Weak w2) -> s1 = w2 | (`Weak w1, `Strong s2) -> w1 = s2 | (`Weak w1, `Weak w2) -> w1 = w2 let strong_validator_match e1 e2 = match (e1,e2) with | (`Strong s1, `Strong s2) -> s1 = s2 | _ -> false exception Bad_header_field of string class type http_header = Netmime.mime_header class type http_header_ro = Netmime.mime_header_ro class type http_trailer = Netmime.mime_header class type http_trailer_ro = Netmime.mime_header_ro type netscape_cookie = { cookie_name : string; cookie_value : string; cookie_expires : float option; cookie_domain : string option; cookie_path : string option; cookie_secure : bool; } type cookie = netscape_cookie let status_re = Netstring_str.regexp "^\\([0-9]+\\)\\([ \t]+\\(.*\\)\\)?$" let status_of_cgi_header hdr = let (code, phrase) = try let status = hdr # field "Status" in ( match Netstring_str.string_match status_re status 0 with | Some m -> (int_of_string (Netstring_str.matched_group m 1 status), (try Netstring_str.matched_group m 3 status with Not_found -> "") ) | None -> failwith "Bad Status response header field" (* Don't know what to do *) ) with Not_found -> (* Maybe there is a [Location] header: *) ( try let _location = hdr # field "Location" in (302, "Found") with Not_found -> (* Default: 200 OK *) (200, "OK") ) in (* Repair [phrase] if empty: *) let phrase = if phrase = "" then ( try string_of_http_status (http_status_of_int code) with Not_found -> "Unknown" ) else phrase in (code, phrase) ;; let query_re = Netstring_str.regexp "^\\([^?]*\\)\\?\\(.*\\)$" let decode_query req_uri = match Netstring_str.string_match query_re req_uri 0 with | Some m -> (Netstring_str.matched_group m 1 req_uri, Netstring_str.matched_group m 2 req_uri) | None -> (req_uri, "") let host4_re = Netstring_str.regexp "\\([^]: \t[]+\\)\\(:\\([0-9]+\\)\\)?$" (* CHECK *) let host6_re = Netstring_str.regexp "\\[\\([^ \t]+\\)\\]\\(:\\([0-9]+\\)\\)?$" let split_host_port s = match Netstring_str.string_match host4_re s 0 with | Some m -> let host_name = Netstring_str.matched_group m 1 s in let host_port = try Some(int_of_string(Netstring_str.matched_group m 3 s)) with | Not_found -> None in (host_name, host_port) | None -> ( match Netstring_str.string_match host6_re s 0 with | Some m -> let host_name = Netstring_str.matched_group m 1 s in let host_port = try Some(int_of_string(Netstring_str.matched_group m 3 s)) with | Not_found -> None in (host_name, host_port) | None -> failwith "Invalid hostname" ) let uripath_encode s = let l = Neturl.split_path s in let l' = List.map (Netencoding.Url.encode ~plus:false) l in Neturl.join_path l' let uripath_decode s = let l = Neturl.split_path s in let l' = List.map (fun u -> let u' = Netencoding.Url.decode ~plus:false u in if String.contains u' '/' then failwith "Nethttp.uripath_decode"; u') l in Neturl.join_path l' let rev_split is_cut s = (* exported *) let rec seek_cut acc i0 i1 = if i1 >= String.length s then (String.sub s i0 (i1 - i0)) :: acc else if is_cut(String.unsafe_get s i1) then skip ((String.sub s i0 (i1 - i0)) :: acc) (i1 + 1) (i1 + 1) else seek_cut acc i0 (i1 + 1) and skip acc i0 i1 = if i1 >= String.length s then acc else if is_cut(String.unsafe_get s i1) then skip acc i0 (i1 + 1) else seek_cut acc i1 i1 in skip [] 0 0 module Cookie = struct (* This module has been written by Christophe Troestler. For full copyright message see netcgi.ml *) (* Cookies are chosen to be mutable because they are stored on the client -- there is no rollback possible -- and mutability kind of reflects that... *) type t = { mutable name : string; mutable value : string; mutable max_age : int option; mutable domain : string option; mutable path : string option; mutable secure : bool; mutable comment : string; mutable comment_url : string; mutable ports : int list option; } let make ?max_age ?domain ?path ?(secure=false) ?(comment="") ?(comment_url="") ?ports name value = { name = name; value = value; max_age = max_age; domain = domain; path = path; secure = secure; comment = comment; comment_url = comment_url; ports = ports; } (* Old version of cookies *) let of_netscape_cookie c = { name = c.cookie_name; value = c.cookie_value; max_age = (match c.cookie_expires with | None -> None | Some t -> Some(truncate(t -. Unix.time()))); domain = c.cookie_domain; path = c.cookie_path; secure = c.cookie_secure; comment = ""; comment_url = ""; ports = None } let to_netscape_cookie cookie = { cookie_name = cookie.name; cookie_value = cookie.value; cookie_expires = (match cookie.max_age with | None -> None | Some t -> Some(float t +. Unix.time())); cookie_domain = cookie.domain; cookie_path = cookie.path; cookie_secure = cookie.secure; } let name cookie = cookie.name let value cookie = cookie.value let max_age cookie = cookie.max_age let domain cookie = cookie.domain let path cookie = cookie.path let secure cookie = cookie.secure let comment cookie = cookie.comment let comment_url cookie = cookie.comment_url let ports cookie = cookie.ports let set_value cookie v = cookie.value <- v let set_max_age cookie t = cookie.max_age <- t let set_domain cookie dom = cookie.domain <- dom let set_path cookie s = cookie.path <- s let set_secure cookie b = cookie.secure <- b let set_comment cookie s = cookie.comment <- s let set_comment_url cookie s = cookie.comment_url <- s let set_ports cookie p = cookie.ports <- p (* Set -------------------------------------------------- *) (* Escape '"', '\\',... and surround the string with quotes. *) let escape s0 = let len = String.length s0 in let encoded_length = ref len in for i = 0 to len - 1 do match String.unsafe_get s0 i with | '\"' | '\\' | '\n' | '\r' -> incr encoded_length | '\000' .. '\031' -> decr encoded_length (* ignore *) | _ -> () done; let s = Bytes.create (!encoded_length + 2) in Bytes.unsafe_set s 0 '\"'; let j = ref 1 in for i = 0 to len - 1 do (match String.unsafe_get s0 i with | '\"' | '\\' as c -> Bytes.unsafe_set s !j '\\'; incr j; Bytes.unsafe_set s !j c; incr j | '\n' -> Bytes.unsafe_set s !j '\\'; incr j; Bytes.unsafe_set s !j 'n'; incr j | '\r' -> Bytes.unsafe_set s !j '\\'; incr j; Bytes.unsafe_set s !j 'r'; incr j | '\000' .. '\031' -> () (* Ignore these control chars, useless for comments *) | c -> Bytes.unsafe_set s !j c; incr j ); done; Bytes.unsafe_set s !j '\"'; Bytes.unsafe_to_string s (* [gen_cookie c] returns a buffer containing an attribute suitable for "Set-Cookie" (RFC 2109) and "Set-Cookie2" (RFC 2965). which is backward compatible with Netscape spec. It is the minimal denominator. *) let gen_cookie c = let buf = Buffer.create 128 in (* Encode, do not quote, key-val for compatibility with old browsers. *) Buffer.add_string buf (Netencoding.Url.encode ~plus:false c.name); Buffer.add_string buf "="; Buffer.add_string buf (Netencoding.Url.encode ~plus:false c.value); Buffer.add_string buf ";Version=1"; (* FIXME: Although values of Domain and Path can be quoted since RFC2109, it seems that browsers do not understand them -- they take the quotes as part of the value. One way to get correct headers is to strip [d] and [p] of unsafe chars -- if they have any. *) (match c.domain with | None -> () | Some d -> Buffer.add_string buf ";Domain="; Buffer.add_string buf d); (match c.path with | None -> () | Some p -> Buffer.add_string buf ";Path="; Buffer.add_string buf p); if c.secure then Buffer.add_string buf ";secure"; (match c.max_age with | None -> () | Some s -> Buffer.add_string buf ";Max-Age="; Buffer.add_string buf (if s > 0 then string_of_int s else "0"); (* For compatibility with old browsers: *) Buffer.add_string buf ";Expires="; Buffer.add_string buf (if s > 0 then Netdate.mk_mail_date (Unix.time() +. float s) else "Thu, 1 Jan 1970 00:00:00 GMT"); ); if c.comment <> "" then ( Buffer.add_string buf ";Comment="; Buffer.add_string buf (escape c.comment); ); buf let set_set_cookie_ct (http_header:#Netmime.mime_header) cookies = let add_cookie (c1, c2) c = let buf = gen_cookie c in (* In any case, we set a "Set-Cookie" header *) let c1 = (Buffer.contents buf) :: c1 in let c2 = if c.comment_url = "" && c.ports = None then c2 else ( (* When this is relevant, also set a "Set-Cookie2" header *) if c.comment_url <> "" then ( Buffer.add_string buf ";CommentURL="; Buffer.add_string buf (escape c.comment_url)); (match c.ports with | None -> () | Some p -> Buffer.add_string buf ";Port=\""; Buffer.add_string buf (String.concat "," (List.map string_of_int p)); Buffer.add_string buf "\"" ); (Buffer.contents buf) :: c2 ) in (c1, c2) in let cookie, cookie2 = List.fold_left add_cookie ([], []) cookies in http_header#update_multiple_field "Set-Cookie" cookie; (* "Set-Cookie2" must come after in order, when they are understood, to override the "Set-Cookie". *) http_header#update_multiple_field "Set-Cookie2" cookie2 (* Get -------------------------------------------------- *) (* According to RFC 2068: quoted-string = ( <"> *(qdtext) <"> ) qdtext = quoted-pair = "\\" CHAR As there a no details, we decode the usual escapes and treat other "\x" as simply "x". *) let unescape_range s low up = if low >= up then "" else let len = up - low in let b = Bytes.create len in let rec decode i j = if i < len then ( match String.unsafe_get s (i+low) with | '\\' -> let i = i + 1 in if i < len then ( (match String.unsafe_get s (i+low) with | '\"' | '\\' as c -> Bytes.unsafe_set b j c | 'n' -> Bytes.unsafe_set b j '\n' | 'r' -> Bytes.unsafe_set b j '\r' | 't' -> Bytes.unsafe_set b j '\t' | c -> Bytes.unsafe_set b j c ); decode (i + 1) (j + 1) ) else j | c -> Bytes.unsafe_set b j c; decode (i + 1) (j + 1) ) else j in let j = decode 0 0 in Bytes.sub_string b 0 j let ports_of_string s = let l = rev_split (fun c -> c = ',' || c = ' ') s in List.fold_left (fun pl p -> try int_of_string p :: pl with _ -> pl) [] l (* Given a new key-val data, update the list of cookies accordingly (new cookie or update attributes of the current one). *) let add_key_val key value cl = if key <> "" && String.unsafe_get key 0 = '$' then (* Keys starting with '$' are for control; ignore the ones we do not know about. *) (match cl with | [] -> [] | c :: _ -> (if key = "$Path" then c.path <- Some value else if key = "$Domain" then c.domain <- Some value else if key = "$Port" then c.ports <- Some (ports_of_string value)); cl ) else make key value :: cl let decode_range s start _end = Netencoding.Url.decode ~pos:start ~len:(_end - start) s (* The difference between version 0 and version 1 cookies is that the latter start with $Version (present 1st or omitted). Our decoding function can handle both versions transparently, so $Version is ignored. In the absence of "=", the string is treated as the VALUE. *) (* [get_key cs i0 i len] scan the cookie string [cs] and get the key-val pairs. keys and values are stripped of heading and trailing spaces, except for quoted values. *) let rec get_key cs i0 i len cl = if i >= len then let value = decode_range cs i0 len in if value = "" then cl else make "" value :: cl else match String.unsafe_get cs i with | ',' | ';' -> (* No "=", interpret as a value as Mozilla does. We choose this over MSIE which is reported to return just "n" instead of "n=" when the value is empty. *) let cl = make "" (decode_range cs i0 i) :: cl in skip_space_before_key cs (i + 1) len cl | '=' -> let i1 = i + 1 in skip_value_space cs i1 len (decode_range cs i0 i) cl | c -> get_key cs i0 (i + 1) len cl and skip_space_before_key cs i len cl = if i >= len then cl else match String.unsafe_get cs i with | ' ' | '\t' | '\n' | '\r' -> skip_space_before_key cs (i + 1) len cl | _ -> get_key cs i i len cl and skip_value_space cs i len key cl = if i >= len then add_key_val key "" cl (* no value *) else match String.unsafe_get cs i with | ' ' | '\t' | '\n' | '\r' -> (* skip linear white space *) skip_value_space cs (i + 1) len key cl | '\"' -> get_quoted_value cs (i + 1) (i + 1) len key cl | _ -> get_value cs i i len key cl and get_value cs i0 i len key cl = if i >= len then add_key_val key (decode_range cs i0 len) cl else match String.unsafe_get cs i with | ',' | ';' -> let cl = add_key_val key (decode_range cs i0 i) cl in (* Usually there is a space after ';' to skip *) skip_space_before_key cs (i + 1) len cl | _ -> get_value cs i0 (i + 1) len key cl and get_quoted_value cs i0 i len key cl = if i >= len then (* quoted string not closed; try anyway *) add_key_val key (unescape_range cs i0 len) cl else match String.unsafe_get cs i with | '\\' -> get_quoted_value cs i0 (i + 2) len key cl | '\"' -> let cl = add_key_val key (unescape_range cs i0 i) cl in skip_to_next cs (i + 1) len cl | _ -> get_quoted_value cs i0 (i + 1) len key cl and skip_to_next cs i len cl = if i >= len then cl else match String.unsafe_get cs i with | ',' | ';' -> skip_space_before_key cs (i + 1) len cl | _ -> skip_to_next cs (i + 1) len cl let get_cookie_ct (http_header:#http_header_ro) = let cookies = http_header#multiple_field "Cookie" in let cl = List.fold_left (fun cl cs -> get_key cs 0 0 (String.length cs) cl) [] cookies in (* The order of cookies is important for the Netscape ones since "more specific path mapping should be sent before cookies with less specific path mappings" -- for those, there will be only a single "Cookie" line. *) List.rev cl end module Header = struct open Netmime open Netmime_string type param_value = [ `V of string | `Q of string ] type auth_challenge = string * (string * param_value) list type auth_credentials = string * (string * param_value) list (* As scanner we use the scanner for mail header fields from Netmime_string. It * is very configurable. *) let std_special_chars = [ ','; ';'; '=' ] (* CHECK: Maybe we should add more characters, e.g. '@'. They are not * used in HTTP, and including them here would cause that field values * containing them are rejected. Maybe we want that. *) let scan_value ?(specials = std_special_chars) s = let scanner = create_mime_scanner ~specials ~scan_options:[] s in Stream.from (fun _ -> Some (snd (scan_token scanner))) (* ---- Parser combinators for stream parsers: ---- *) let rec parse_comma_separated_list subparser stream = (* The [subparser] is required to return its value when it finds a * comma (i.e. [Special ','], or when it finds [End]. These tokens * must not be swallowed. *) let expr_opt = subparser stream in match expr_opt with | Some expr -> expr :: parse_comma_separated_rest subparser stream | None -> [] and parse_comma_separated_rest subparser stream = match Stream.peek stream with | Some(Special ',') -> Stream.junk stream; ignore(parse_commas stream); parse_comma_separated_list subparser stream | _ -> [] and parse_commas stream = match Stream.peek stream with | Some(Special ',') -> Stream.junk stream; parse_commas stream | _ -> () let parse_end stream = match Stream.peek stream with | Some End -> Stream.junk stream; () | _ -> raise Stream.Failure let merge_lists mh fieldparser fieldname = let fields = mh # multiple_field fieldname in if fields = [] then raise Not_found; List.flatten (List.map fieldparser fields) let parse_field mh fn_name f_parse fieldname = try let field = mh # field fieldname in f_parse (scan_value field) with | Stream.Failure | Stream.Error _ -> raise (Bad_header_field fn_name) let parse_comma_separated_field ?specials mh fn_name f_parse fieldname = let fieldparser field = try let stream = scan_value ?specials field in let r = parse_comma_separated_list f_parse stream in parse_end stream; r with | Stream.Failure | Stream.Error _ -> raise (Bad_header_field fn_name) in merge_lists mh fieldparser fieldname (* ----- Common parsers/printer: ---- *) let parse_token_list mh fn_name fieldname = let parse_token stream = match Stream.peek stream with | Some (Atom tok) -> Stream.junk stream; Some tok | _ -> None in parse_comma_separated_field mh fn_name parse_token fieldname let parse_token_or_qstring stream = match Stream.peek stream with | Some(Atom tok) -> Stream.junk stream; tok | Some(QString v) -> Stream.junk stream; v | _ -> raise Stream.Failure let rec parse_params stream = match Stream.npeek 3 stream with | [ Special ';'; Atom name; Special '=' ] -> for k=1 to 3 do Stream.junk stream done; let v = parse_token_or_qstring stream in (name,v) :: parse_params stream | _ -> [] let parse_extended_token_list mh fn_name fieldname = (* token [ '=' (token|qstring) ( ';' token '=' (token|qstring) ) * ] *) let rec parse_extended_token stream = match Stream.peek stream with | Some(Atom tok) -> Stream.junk stream; let extension = parse_equation stream in ( match extension with | Some (eq_val, params) -> Some (tok, Some eq_val, params) | None -> Some (tok, None, []) ) | _ -> None and parse_equation stream = match Stream.peek stream with | Some(Special '=') -> Stream.junk stream; let v = parse_token_or_qstring stream in let params = parse_params stream in Some (v, params) | _ -> None in parse_comma_separated_field mh fn_name parse_extended_token fieldname let qstring_indicator_re = Netstring_str.regexp "[]\\\"()<>@,;:/[?={} \x00-\x1f\x7f]" (* Netstring_pcre.regexp "[\\\\\"()<>@,;:/[\\]?={} \\x00-\\x1f\\x7f]" *) let qstring_re = Netstring_str.regexp "[\\\"]" (* Netstring_pcre.regexp "[\\\\\\\"]" *) let qstring_of_value s = (* Returns a qstring *) "\"" ^ Netstring_str.global_replace qstring_re "\\\\\\0" s ^ "\"" (* Escape qstring_re with a backslash *) let string_of_value s = (* Returns a token or a qstring, depending on the value of [s] *) try ignore(Netstring_str.search_forward qstring_indicator_re s 0); qstring_of_value s with Not_found -> s let string_of_params l = if l = [] then "" else ";" ^ String.concat ";" (List.map (fun (n,s) -> n ^ "=" ^ string_of_value s) l) let string_of_extended_token fn_name = function | (tok, None, []) -> tok | (tok, None, _) -> invalid_arg fn_name | (tok, Some eq_val, params) -> tok ^ "=" ^ eq_val ^ string_of_params params let parse_parameterized_token_list mh fn_name fieldname = (* token ( ';' token '=' (token|qstring) ) * *) let rec parse_parameterized_token stream = match Stream.peek stream with | Some (Atom tok) -> Stream.junk stream; let params = parse_params stream in Some(tok, params) | _ -> None in parse_comma_separated_field mh fn_name parse_parameterized_token fieldname let string_of_parameterized_token (tok, params) = tok ^ string_of_params params let q_split ( l : (string * (string * string) list) list ) : (string * (string * string) list * (string * string) list) list = (* Find the "q" param, and split [params] at that position *) let rec split params = match params with | [] -> ([], []) | ("q", q) :: rest -> ([], params) | other :: rest -> let before, after = split rest in (other :: before), after in List.map (fun (tok, params) -> let before, after = split params in (tok, before, after)) l let q_merge fn_name (tok, params, q_params) = if List.mem_assoc "q" params then invalid_arg fn_name; ( match q_params with | ( "q", _ ) :: _ | [] -> (tok, (params @ q_params)) | _ -> invalid_arg fn_name ) let date_of_string fn_name s = try Netdate.parse_epoch s with Invalid_argument _ -> raise(Bad_header_field fn_name) let string_of_date f = Netdate.format ~fmt:"%a, %d %b %Y %H:%M:%S GMT" (Netdate.create ~zone:0 f) let sort_by_q ?(default=1.0) toks_with_params = (* Sorts [toks_with_params] such that the highest [q] values come first. * Tokens with a [q] value of 0 are removed. Tokens without [q] value * are assumed to have the [default] value. This is also done with * unparseable [q] values. *) List.map snd (List.stable_sort (fun (q1, tok_param1) (q2, tok_param2) -> Pervasives.compare q2 q1) (List.filter (fun (q, tok_param) -> q > 0.0) (List.map (fun (tok, params) -> try let q_str = List.assoc "q" params in (float_of_string q_str, (tok, params)) with | Not_found -> (default, (tok, params)) | Failure _ -> (default, (tok, params)) ) toks_with_params))) let sort_by_q' ?default tok_with_params_and_qparams = List.map (fun ((tok, tok_params), q_params) -> (tok, tok_params, q_params)) (sort_by_q ?default (List.map (fun (tok, tok_params, q_params) -> ((tok, tok_params), q_params)) tok_with_params_and_qparams)) (* ---- The field accessors: ---- *) let get_accept mh = q_split (parse_parameterized_token_list mh "Nethttp.get_accept" "Accept") let set_accept mh av = let s = String.concat "," (List.map (fun triple -> string_of_parameterized_token (q_merge "Nethttp.set_accept" triple)) av) in mh # update_field "Accept" s let best_media_type mh supp = let match_mime a b = let (main_type, sub_type) = Netmime_string.split_mime_type b in sub_type = "*" (*Ignore non-wildcard types*) && (main_type = "*" || main_type = (fst (Netmime_string.split_mime_type a))) in let filter p l = List.fold_right (fun ((tok, _, _) as e) l -> if p tok then e :: l else l) l [] in let accept = try get_accept mh with Not_found -> [ "*/*",[],[] ] in match sort_by_q' (List.flatten (List.map (fun t -> filter ((=) t) accept @ filter (match_mime t) accept ) supp)) with (tok, params, qparams) :: _ -> (tok, params) | [] -> ("", []) let get_accept_charset mh = parse_parameterized_token_list mh "Nethttp.get_accept_charset" "Accept-Charset" let set_accept_charset mh l = mh # update_field "Accept-Charset" (String.concat "," (List.map string_of_parameterized_token l)) let best_tok_of_list toks supp = let tok = List.find (fun tok -> tok = "*" || List.mem tok supp) toks in if tok = "*" then List.find (fun tok -> not (List.mem tok toks)) supp else tok let best_charset mh supp = try let toks_with_params = get_accept_charset mh in (* or Not_found *) (* Special handling of ISO-8859-1: *) let toks_with_params' = if not(List.mem_assoc "*" toks_with_params) && not(List.exists (fun (tok,_) -> String.lowercase tok = "iso-8859-1") toks_with_params) then toks_with_params @ [ "ISO-8859-1", ["q", "1.0"] ] else toks_with_params in let toks' = List.map fst (sort_by_q toks_with_params') in best_tok_of_list toks' supp with Not_found -> "*" let get_accept_encoding mh = parse_parameterized_token_list mh "Nethttp.get_accept_encoding" "Accept-Encoding" let set_accept_encoding mh l = mh # update_field "Accept-Encoding" (String.concat "," (List.map string_of_parameterized_token l)) let best_encoding mh supp = try let toks_with_params = sort_by_q (get_accept_encoding mh) in best_tok_of_list (List.map fst toks_with_params) supp with Not_found -> "identity" let get_accept_language mh = parse_parameterized_token_list mh "Nethttp.get_accept_language" "Accept-Language" let set_accept_language mh l = mh # update_field "Accept-Language" (String.concat "," (List.map string_of_parameterized_token l)) let get_accept_ranges mh = parse_token_list mh "Nethttp.get_accept_ranges" "Accept-Ranges" let set_accept_ranges mh toks = mh # update_field "Accept-Ranges" (String.concat "," toks) let get_age mh = try float_of_string (mh # field "Age") with Failure _ -> raise(Bad_header_field "Nethttp.get_age") let set_age mh v = mh # update_field "Age" (Printf.sprintf "%.0f" v) let get_allow mh = parse_token_list mh "Nethttp.get_allow" "Allow" let set_allow mh toks = mh # update_field "Allow" (String.concat "," toks) let comma_split_re = Netstring_str.regexp "\\([ \t]*,\\)+[ \t]*" let comma_split = Netstring_str.split comma_split_re let parse_opt_eq_token stream = match Stream.peek stream with | Some(Special '=') -> Stream.junk stream; ( match Stream.peek stream with | Some (Atom v) -> Stream.junk stream; Some v | Some (QString v) -> Stream.junk stream; Some v | _ -> raise Stream.Failure ) | _ -> None let parse_cc_directive_1 stream = match Stream.npeek 3 stream with | (Atom "no-cache") :: _ -> Stream.junk stream; ( match parse_opt_eq_token stream with | None -> `No_cache [] | Some names -> `No_cache(comma_split names) ) | (Atom "no-store") :: _ -> Stream.junk stream; `No_store | [ Atom "max-age"; Special '='; Atom seconds ] -> for k = 1 to 3 do Stream.junk stream done; `Max_age(int_of_string seconds) | (Atom "max-stale") :: _ -> Stream.junk stream; ( match parse_opt_eq_token stream with | None -> `Max_stale None | Some seconds -> `Max_stale(Some(int_of_string seconds)) ) | [ Atom "min-fresh"; Special '='; Atom seconds ] -> for k = 1 to 3 do Stream.junk stream done; `Min_fresh(int_of_string seconds) | ( Atom "no-transform") :: _ -> Stream.junk stream; `No_transform | ( Atom "only-if-cached") :: _ -> Stream.junk stream; `Only_if_cached | ( Atom "public") :: _ -> Stream.junk stream; `Public | ( Atom "private") :: _ -> ( match parse_opt_eq_token stream with | None -> `Private [] | Some names -> `Private(comma_split names) ) | ( Atom "must-revalidate") :: _ -> Stream.junk stream; `Must_revalidate | ( Atom "proxy-revalidate") :: _ -> Stream.junk stream; `Proxy_revalidate | [ Atom "s-maxage"; Special '='; Atom seconds ] -> for k = 1 to 3 do Stream.junk stream done; `S_maxage(int_of_string seconds) | ( Atom extension ) :: _ -> Stream.junk stream; let val_opt = parse_opt_eq_token stream in `Extension(extension, val_opt) | _ -> raise Stream.Failure let parse_cc_directive stream = try Some (parse_cc_directive_1 stream) with Stream.Failure -> None let get_cache_control mh = parse_comma_separated_field mh "Nethttp.get_cache_control" parse_cc_directive "Cache-Control" let set_cache_control mh l = let s = String.concat "," (List.map (function | `No_store -> "no-store" | `Max_age n -> "max-age=" ^ string_of_int n | `Max_stale None -> "max-stale" | `Max_stale(Some n) -> "max-stale=" ^ string_of_int n | `Min_fresh n -> "min-fresh=" ^ string_of_int n | `No_transform -> "no-transform" | `Only_if_cached -> "only-if-cached" | `Public -> "public" | `Private names -> "private=\"" ^ String.concat "," names ^ "\"" | `No_cache [] -> "no-cache" | `No_cache names -> "no-cache=\"" ^ String.concat "," names ^ "\"" | `Must_revalidate -> "must-revalidate" | `Proxy_revalidate -> "proxy-revalidate" | `S_maxage n -> "s-maxage=" ^ string_of_int n | `Extension(tok,None) -> tok | `Extension(tok, Some param) -> tok ^ "=" ^ string_of_value param ) l) in mh # update_field "Cache-Control" s let get_connection mh = parse_token_list mh "Nethttp.get_connection" "Connection" let set_connection mh toks = mh # update_field "Connection" (String.concat "," toks) let get_content_encoding mh = parse_token_list mh "Nethttp.get_content_encoding" "Content-Encoding" let set_content_encoding mh toks = mh # update_field "Content-Encoding" (String.concat "," toks) let get_content_language mh = parse_token_list mh "Nethttp.get_content_language" "Content-Language" let set_content_language mh toks = mh # update_field "Content-Language" (String.concat "," toks) let get_content_length mh = try Int64.of_string (mh # field "Content-Length") with Failure _ -> raise (Bad_header_field "Nethttp.get_content_length") let set_content_length mh n = mh # update_field "Content-Length" (Int64.to_string n) let get_content_location mh = mh # field "Content-Location" let set_content_location mh s = mh # update_field "Content-Location" s let get_content_md5 mh = mh # field "Content-MD5" let set_content_md5 mh s = mh # update_field "Content-MD5" s let parse_byte_range_resp_spec stream = match Stream.npeek 3 stream with | (Special '*') :: _ -> Stream.junk stream; None | [ Atom first; Special '-'; Atom last ] -> for k = 1 to 3 do Stream.junk stream done; Some(Int64.of_string first, Int64.of_string last) | _ -> raise Stream.Failure let parse_byte_range_resp_length stream = match Stream.peek stream with | Some (Special '*') -> Stream.junk stream; None | Some (Atom length) -> Stream.junk stream; Some(Int64.of_string length) | _ -> raise Stream.Failure let parse_content_range_spec stream = if Stream.next stream <> Atom "bytes" then raise Stream.Failure; let br = parse_byte_range_resp_spec stream in if Stream.next stream <> Special '/' then raise Stream.Failure; let l = parse_byte_range_resp_length stream in if Stream.next stream <> End then raise Stream.Failure; `Bytes(br,l) let get_content_range mh = let s = mh # field "Content-Range" in let stream = scan_value ~specials:[ ','; ';'; '='; '*'; '-'; '/' ] s in try parse_content_range_spec stream with | Stream.Failure | Stream.Error _ | Failure _ -> raise (Bad_header_field "Nethttp.get_content_range") let set_content_range mh (`Bytes(range_opt,length_opt)) = let s = ( match range_opt with | Some (first,last) -> Int64.to_string first ^ "-" ^ Int64.to_string last | None -> "*" ) ^ "/" ^ ( match length_opt with | Some length -> Int64.to_string length | None -> "*" ) in mh # update_field "Content-Range" ("bytes " ^ s) let get_content_type mh = try List.hd (parse_parameterized_token_list mh "Nethttp.get_content_type" "Content-Type") with Failure _ -> raise(Bad_header_field "Nethttp.get_content_type") let set_content_type mh (tok,params) = mh # update_field "Content-Type" (string_of_parameterized_token (tok,params)) let get_date mh = date_of_string "Nethttp.get_date" (mh # field "Date") let set_date mh d = mh # update_field "Date" (string_of_date d) let parse_etag_token stream = match Stream.npeek 3 stream with | [ Atom "W"; Special '/'; QString e ] -> for k = 1 to 3 do Stream.junk stream done; `Weak e | (QString e) :: _ -> Stream.junk stream; `Strong e | _ -> raise Stream.Failure let parse_etag stream = let etag = parse_etag_token stream in parse_end stream; etag let get_etag mh = let s = mh # field "ETag" in let stream = scan_value ~specials:[ ','; ';'; '='; '/' ] s in try parse_etag stream with | Stream.Failure | Stream.Error _ | Failure _ -> raise (Bad_header_field "Nethttp.get_etag") let string_of_etag = function | `Weak s -> "W/" ^ qstring_of_value s | `Strong s -> qstring_of_value s let set_etag mh etag = mh # update_field "ETag" (string_of_etag etag) let get_expect mh = parse_extended_token_list mh "Nethttp.get_expect" "Expect" let set_expect mh expectation = mh # update_field "Expect" (String.concat "," (List.map (string_of_extended_token "Nethttp.set_expect") expectation)) let get_expires mh = date_of_string "Nethttp.get_expires" (mh # field "Expires") let set_expires mh d = mh # update_field "Expires" (string_of_date d) let get_from mh = mh # field "From" let set_from mh v = mh # update_field "From" v let get_host mh = let s = mh # field "Host" in try split_host_port s with | Failure _ -> raise(Bad_header_field "Nethttp.get_host") let set_host mh (host,port_opt) = let s = host ^ ( match port_opt with Some p -> ":" ^ string_of_int p | None -> "") in mh # update_field "Host" s let parse_etag_or_star_tok stream = match Stream.peek stream with | Some (Special '*') -> Stream.junk stream; Some None | _ -> try Some(Some(parse_etag_token stream)) with | Stream.Failure -> None let get_etag_list mh fn_name fieldname = let specials = [ ','; ';'; '='; '/'; '*' ] in let l = parse_comma_separated_field ~specials mh fn_name parse_etag_or_star_tok fieldname in if List.mem None l then None else Some(List.map (function Some e -> e | None -> assert false) l) let set_etag_list mh fieldname l_opt = let v = match l_opt with | None -> "*" | Some l -> String.concat "," (List.map string_of_etag l) in mh # update_field fieldname v let get_if_match mh = get_etag_list mh "Nethttp.get_if_match" "If-Match" let set_if_match mh = set_etag_list mh "If-Match" let get_if_modified_since mh = date_of_string "Nethttp.get_if_modified_since" (mh # field "If-Modified-Since") let set_if_modified_since mh d = mh # update_field "If-Modified-Since" (string_of_date d) let get_if_none_match mh = get_etag_list mh "Nethttp.get_if_none_match" "If-None-Match" let set_if_none_match mh = set_etag_list mh "If-None-Match" let get_if_range mh = let s = mh # field "If-Range" in let stream = scan_value ~specials:[ ','; ';'; '='; '/' ] s in try `Etag (parse_etag stream) with | Stream.Failure | Stream.Error _ | Failure _ -> `Date (date_of_string "Nethttp.get_if_range" s) let set_if_range mh v = let s = match v with | `Etag e -> string_of_etag e | `Date d -> string_of_date d in mh # update_field "If-Range" s let get_if_unmodified_since mh = date_of_string "Nethttp.get_if_unmodified_since" (mh # field "If-Unmodified-Since") let set_if_unmodified_since mh d = mh # update_field "If-Unmodified-Since" (string_of_date d) let get_last_modified mh = date_of_string "Nethttp.get_last_modified" (mh # field "Last-Modified") let set_last_modified mh d = mh # update_field "Last-Modified" (string_of_date d) let get_location mh = mh # field "Location" let set_location mh s = mh # update_field "Location" s let get_max_forwards mh = try int_of_string (mh # field "Max-Forwards") with Failure _ -> raise(Bad_header_field "Nethttp.get_max_forwards") let set_max_forwards mh n = mh # update_field "Max-Forwards" (string_of_int n) let parse_pragma_directive stream = match Stream.peek stream with | Some (Atom tok) -> Stream.junk stream; let param_opt = parse_opt_eq_token stream in Some (tok, param_opt) | _ -> None let get_pragma mh = parse_comma_separated_field mh "Nethttp.get_pragma" parse_pragma_directive "Pragma" let set_pragma mh l = let s = String.concat "," (List.map (function | (tok, None) -> tok | (tok, Some param) -> tok ^ "=" ^ string_of_value param) l) in mh # update_field "Pragma" s let parse_opt_last_pos stream = match Stream.peek stream with | Some(Atom last) -> Stream.junk stream; Some(Int64.of_string last) | _ -> None let rec parse_byte_range_spec stream = match Stream.npeek 2 stream with | [ Atom first; Special '-' ] -> Stream.junk stream; Stream.junk stream; let last = parse_opt_last_pos stream in let r = parse_byte_range_spec_rest stream in (Some (Int64.of_string first), last) :: r | [ Special '-'; Atom suffix_length ] -> Stream.junk stream; Stream.junk stream; let r = parse_byte_range_spec_rest stream in (None, Some(Int64.of_string suffix_length)) :: r | _ -> [] and parse_byte_range_spec_rest stream = match Stream.peek stream with | Some (Special ',') -> Stream.junk stream; parse_commas stream; parse_byte_range_spec stream | _ -> [] let parse_ranges_specifier stream = if Stream.next stream <> Atom "bytes" then raise Stream.Failure; if Stream.next stream <> Special '=' then raise Stream.Failure; let r = parse_byte_range_spec stream in if Stream.next stream <> End then raise Stream.Failure; `Bytes r let get_range mh = let s = mh # field "Range" in let stream = scan_value ~specials:[ ','; ';'; '='; '*'; '-'; '/' ] s in try parse_ranges_specifier stream with | Stream.Failure | Stream.Error _ | Failure _ -> raise (Bad_header_field "Nethttp.get_range") let set_range mh (`Bytes l) = let s = "bytes=" ^ String.concat "," (List.map (function | (Some first, Some last) -> Int64.to_string first ^ "-" ^ Int64.to_string last | (Some first, None) -> Int64.to_string first ^ "-" | (None, Some last) -> "-" ^ Int64.to_string last | (None, None) -> invalid_arg "Nethttp.set_range") l) in mh # update_field "Range" s let get_referer mh = mh # field "Referer" let get_referrer = get_referer let set_referer mh s = mh # update_field "Referer" s let set_referrer = set_referer let get_retry_after mh = let s = mh # field "Retry-After" in try `Seconds(int_of_string s) with Failure _ -> `Date(date_of_string "Nethttp.get_retry_after" s) let set_retry_after mh v = let s = match v with | `Seconds n -> string_of_int n | `Date d -> string_of_date d in mh # update_field "Retry-After" s let get_server mh = mh # field "Server" let set_server mh name = mh # update_field "Server" name let get_te mh = q_split (parse_parameterized_token_list mh "Nethttp.get_te" "TE") let set_te mh te = let s = String.concat "," (List.map (fun triple -> string_of_parameterized_token (q_merge "Nethttp.set_te" triple)) te) in mh # update_field "TE" s let get_trailer mh = parse_token_list mh "Nethttp.get_trailer" "Trailer" let set_trailer mh fields = mh # update_field "Trailer" (String.concat "," fields) let get_transfer_encoding mh = parse_parameterized_token_list mh "Nethttp.get_transfer_encoding" "Transfer-Encoding" let set_transfer_encoding mh te = let s = String.concat "," (List.map string_of_parameterized_token te) in mh # update_field "Transfer-Encoding" s let get_upgrade mh = parse_token_list mh "Nethttp.get_upgrade" "Upgrade" let set_upgrade mh fields = mh # update_field "Upgrade" (String.concat "," fields) let get_user_agent mh = mh # field "User-Agent" let set_user_agent mh s = mh # update_field "User-Agent" s let get_vary mh = let l = parse_token_list mh "Nethttp.get_vary" "Vary" in if List.mem "*" l then `Star else `Fields l let set_vary mh v = let s = match v with | `Star -> "*" | `Fields l -> String.concat "," l in mh # update_field "Vary" s (* --- Authentication --- *) let parse_challenges mh fn_name fieldname = let rec parse_auth_params stream = match Stream.npeek 2 stream with | [ Atom ap_name; Special '=' ] -> Stream.junk stream; Stream.junk stream; let ap_val = parse_token_or_qstring stream in let rest = parse_auth_param_rest stream in (ap_name, ap_val) :: rest | _ -> raise Stream.Failure and parse_auth_param_rest stream = match Stream.npeek 3 stream with | [ (Special ','); (Atom ap_name); (Special '=') ] -> Stream.junk stream; Stream.junk stream; Stream.junk stream; let ap_val = parse_token_or_qstring stream in let rest = parse_auth_param_rest stream in (ap_name, ap_val) :: rest | _ -> [] and parse_auth_params_negotiate stream = match Stream.npeek 1 stream with | [ (Atom d1) ] -> Stream.junk stream; let d2 = match Stream.npeek 1 stream with | [ Special '=' ] -> Stream.junk stream; ( match Stream.npeek 1 stream with | [ Special '=' ] -> Stream.junk stream; "==" | _ -> "=" ) | _ -> "" in [ "credentials", d1 ^ d2 ] | _ -> [ "credentials", "" ] and parse_challenge stream = match Stream.peek stream with | Some (Atom auth_scheme) -> Stream.junk stream; let auth_params = match String.lowercase auth_scheme with | "negotiate" -> parse_auth_params_negotiate stream | _ -> parse_auth_params stream in Some(auth_scheme, auth_params) | _ -> None in parse_comma_separated_field mh fn_name parse_challenge fieldname let encode_param p_val = match p_val with | `Q s -> s | `V s -> string_of_value s let mk_challenges fields = String.concat "," (List.map (fun (auth_name, auth_params) -> let pstring = match String.lowercase auth_name with | "negotiate" -> ( match auth_params with | [ "credentials", data ] -> encode_param data | _ -> "" ) | _ -> (String.concat "," (List.map (fun (p_name, p_val) -> p_name ^ "=" ^ encode_param p_val ) auth_params ) ) in auth_name ^ (if pstring <> "" then " " ^ pstring else "") ) fields) let mark_decoded (n,v) = (n, `V v) let mark_params_decoded (mech,params) = (mech, List.map mark_decoded params) let mark_many_decoded l = List.map mark_params_decoded l let get_www_authenticate mh = mark_many_decoded (parse_challenges mh "Nethttp.get_www_authenticate" "WWW-Authenticate") let parse_quoted_parameters s = let u = "dummy " ^ s in let mh = new Netmime.basic_mime_header ["WWW-Authenticate", u ] in try match get_www_authenticate mh with | [] -> [] | [_, params] -> ( List.map (fun (n,v) -> match v with | `Q _ -> assert false | `V s -> (n,s) ) params ) | _ -> assert false with | Bad_header_field _ -> failwith "parse_quoted_parameters" let set_www_authenticate mh fields = mh # update_field "WWW-Authenticate" (mk_challenges fields) let get_proxy_authenticate mh = mark_many_decoded (parse_challenges mh "Nethttp.get_proxy_authenticate" "Proxy-Authenticate") let set_proxy_authenticate mh fields = mh # update_field "Proxy-Authenticate" (mk_challenges fields) let ws_re = Netstring_str.regexp "[ \t\r\n]+";; let parse_credentials mh fn_name fieldname = let rec parse_creds stream = match Stream.peek stream with | Some (Atom auth_name) -> Stream.junk stream; let params = parse_auth_params stream in (auth_name, params) | _ -> raise Stream.Failure and parse_auth_params stream = match Stream.npeek 2 stream with | [ Atom ap_name; Special '=' ] -> Stream.junk stream; Stream.junk stream; let ap_val = parse_token_or_qstring stream in let rest = parse_auth_param_rest stream in (ap_name, ap_val) :: rest | _ -> raise Stream.Failure and parse_auth_param_rest stream = match Stream.npeek 3 stream with | [ Special ','; Atom ap_name; Special '=' ] -> Stream.junk stream; Stream.junk stream; Stream.junk stream; let ap_val = parse_token_or_qstring stream in let rest = parse_auth_param_rest stream in (ap_name, ap_val) :: rest | _ -> [] in (* Basic authentication is a special case! *) let v = mh # field fieldname in (* or Not_found *) match Netstring_str.split ws_re v with | [ name; creds ] when String.lowercase name = "basic" -> (name, ["credentials", creds]) | [ name; creds ] when String.lowercase name = "negotiate" -> (name, ["credentials", creds]) | _ -> parse_field mh fn_name parse_creds fieldname let mk_credentials (auth_name, auth_params) = match String.lowercase auth_name with | "basic" | "negotiate" -> let creds = try List.assoc "credentials" auth_params with Not_found -> failwith "Nethttp.mk_credentials: credentials not found" in auth_name ^ " " ^ encode_param creds | _ -> auth_name ^ " " ^ (String.concat "," (List.map (fun (p_name, p_val) -> p_name ^ "=" ^ encode_param p_val) auth_params)) let get_authorization mh = mark_params_decoded (parse_credentials mh "Nethttp.get_authorization" "authorization") let set_authorization mh v = mh # update_field "Authorization" (mk_credentials v) let get_proxy_authorization mh = mark_params_decoded (parse_credentials mh "Nethttp.get_proxy_authorization" "proxy-authorization") let set_proxy_authorization mh v = mh # update_field "Proxy-Authorization" (mk_credentials v) (* --- Cookies --- *) exception No_equation of string let split_name_is_value s = (* Recognizes a string "name=value" and returns the pair (name,value). * If the string has the wrong format, the function will raise * No_equation, and the argument of the exception is the unparseable * string. *) try let p = String.index s '=' in (String.sub s 0 p, String.sub s (p+1) (String.length s - p - 1)) with Not_found -> raise(No_equation s) let spaces_at_beginning_re = Netstring_str.regexp "^[ \t\r\n]+" let spaces_at_end_re = Netstring_str.regexp "[ \t\r\n]+$" let strip_spaces s = (* Remove leading and trailing spaces: *) Netstring_str.global_replace spaces_at_end_re "" (Netstring_str.global_replace spaces_at_beginning_re "" s) let split_cookies_re = Netstring_str.regexp "[ \t\r\n]*;[ \t\r\n]*" ;; let get_cookie mh = let cstrings = mh # multiple_field "Cookie" in (* Remove leading and trailing spaces: *) let cstrings' = List.map strip_spaces cstrings in let partss = List.map (fun cstring -> Netstring_str.split split_cookies_re cstring ) cstrings' in let parts = List.flatten partss in List.map (fun part -> let n,v = try split_name_is_value part with No_equation _ -> (part, "") (* Because it is reported that MSIE returns just "n" instead * of "n=" when the value v is empty *) in let n_dec = Netencoding.Url.decode n in let v_dec = Netencoding.Url.decode v in (n_dec, v_dec) ) parts let get_cookie_ct = Cookie.get_cookie_ct let set_cookie mh l = let s = String.concat ";" (List.map (fun (n,v) -> Netencoding.Url.encode n ^ "=" ^ Netencoding.Url.encode v) l) in mh # update_field "Cookie" s let nv_re = Netstring_str.regexp "^\\([^=;]+\\)\\(=\\(.*\\)\\)?$" let get_set_cookie_1 s = let nv_list = List.map (fun item -> ( match Netstring_str.string_match nv_re item 0 with | None -> raise(Bad_header_field "Nethttp.Header.get_set_cookie") | Some m -> let name = Netstring_str.matched_group m 1 item in let value = try Netstring_str.matched_group m 3 item with Not_found -> "" in (name, value) ) ) (Netstring_str.split split_cookies_re s) in match nv_list with | (n,v) :: params -> let params = List.map (fun (n,v) -> (String.lowercase n, v)) params in { cookie_name = Netencoding.Url.decode ~plus:false n; cookie_value = Netencoding.Url.decode ~plus:false v; cookie_expires = (try let exp_str = List.assoc "expires" params in Some(Netdate.since_epoch (Netdate.parse exp_str)) with | Not_found -> None); cookie_domain = ( try Some(List.assoc "domain" params) with | Not_found -> None ); cookie_path = ( try Some(List.assoc "path" params) with | Not_found -> None ); cookie_secure = ( try List.mem_assoc "secure" params with | Not_found -> false ) } | _ -> raise(Bad_header_field "Nethttp.Header.get_set_cookie") let get_set_cookie mh = let fields = mh # multiple_field "Set-Cookie" in List.map get_set_cookie_1 fields let set_set_cookie mh l = let cookie_fields = List.map (fun c -> let enc_name = Netencoding.Url.encode ~plus:false c.cookie_name in let enc_value = Netencoding.Url.encode ~plus:false c.cookie_value in enc_name ^ "=" ^ enc_value ^ ( match c.cookie_expires with None -> "" | Some t -> ";EXPIRES=" ^ Netdate.mk_usenet_date t ) ^ (match c.cookie_domain with None -> "" | Some d -> ";DOMAIN=" ^ d ) ^ (match c.cookie_path with None -> "" | Some p -> ";PATH=" ^ p ) ^ if c.cookie_secure then ";SECURE" else "" ) l in mh # update_multiple_field "Set-cookie" cookie_fields let set_set_cookie_ct = Cookie.set_set_cookie_ct end type transport_layer_id = int let new_trans_id () = Oo.id (object end) let http_trans_id = new_trans_id() let https_trans_id = new_trans_id() let spnego_trans_id = new_trans_id() let proxy_only_trans_id = new_trans_id() type match_result = [ `Accept of string * string option | `Reroute of string * int | `Accept_reroute of string * string option * int | `Reject ] module type HTTP_CLIENT_MECHANISM = sig val mechanism_name : string val available : unit -> bool val restart_supported : bool type credentials val init_credentials : (string * string * (string * string) list) list -> credentials val client_match : params:(string * string * bool) list -> Header.auth_challenge -> match_result type client_session val client_state : client_session -> Netsys_sasl_types.client_state val create_client_session : user:string -> creds:credentials -> params:(string * string * bool) list -> unit -> client_session val client_configure_channel_binding : client_session -> Netsys_sasl_types.cb -> client_session val client_restart : params:(string * string * bool) list -> client_session -> client_session val client_process_challenge : client_session -> string -> string -> #http_header_ro -> Header.auth_challenge -> client_session val client_emit_response : client_session -> string -> string -> #http_header_ro -> client_session * Header.auth_credentials * (string * string) list val client_channel_binding : client_session -> Netsys_sasl_types.cb val client_user_name : client_session -> string val client_stash_session : client_session -> string val client_resume_session : string -> client_session val client_session_id : client_session -> string option val client_domain : client_session -> string list val client_prop : client_session -> string -> string val client_gssapi_props : client_session -> Netsys_gssapi.client_props end let qstring_of_value = Header.qstring_of_value ocamlnet-4.1.2/src/netstring/netglob.ml0000644000175000017500000006144012731530350016540 0ustar gerdgerd(* $Id$ *) open Netglob_lex open Printf type glob_expr = glob_expr_atom list and glob_expr_atom = [ `Literal of string | `Star | `Qmark | `Bracket of (bool * glob_set) | `Brace of glob_expr list | `Tilde of string ] and glob_set = < set : (int * int) list > type valid_glob_expr = { pat : glob_expr; encoding : Netconversion.encoding; } exception Bad_glob_expr of string exception Unsupported_expr of string class type user_info = object method path_encoding : Netconversion.encoding option method home_directory : string -> string end class type glob_fsys = object method path_encoding : Netconversion.encoding option method read_dir : string -> string list method file_is_dir : string -> bool method file_exists : string -> bool end type glob_mode = [ `Existing_paths | `All_paths | `All_words ] type pattern = [ `String of string | `Expr of valid_glob_expr ] let literal_glob_expr enc s = { pat = [ `Literal s ]; encoding = enc } let reparse_bracket_expr enc l = (* In order to support multi-byte encodings, reparse the expression now. For simplifying this, we require that ranges (like c-d) are purely ASCII. So only the chars outside ranges need to be reparsed *) let rec collect buf toks = match toks with | Bracket_char c :: toks' -> Buffer.add_char buf c; collect buf toks' | Bracket_range(c1,c2) as tok :: toks' -> let new_toks = reparse buf in new_toks @ [tok] @ collect (Buffer.create 80) toks' | Bracket_code _ :: _ -> assert false | Bracket_end :: _ | [] -> reparse buf and reparse buf = let s = Buffer.contents buf in let codes = ref [] in ( try Netconversion.ustring_iter enc (fun i -> codes := i :: !codes) s with _ -> raise Lexing_Error ); List.rev_map (fun i -> Bracket_code i) !codes in collect (Buffer.create 80) l let parse_glob_expr ?(encoding = `Enc_iso88591) ?(enable_star = true) ?(enable_qmark = true) ?(enable_brackets = true) ?(enable_braces = true) ?(enable_tilde = true) ?(enable_escape = true) s = if not (Netconversion.is_ascii_compatible encoding) then failwith "Netglob.parse_glob_expr: the encoding is not ASCII-compatible"; let feat = { enable_star = enable_star; enable_qmark = enable_qmark; enable_brackets = enable_brackets; enable_braces = enable_braces; enable_tilde = enable_tilde; enable_escape = enable_escape; escaped = false; } in let rec collect_until lexbuf = let tok = glob_expr feat lexbuf in if tok = Glob_end then [] else tok :: (collect_until lexbuf) in let rec process_brace_list current list = match list with | Brace_literal s :: list' -> let gl = collect_until (Lexing.from_string s) in process_brace_list (current @ gl) list' | Brace_braces l :: list' -> process_brace_list (current @ [Glob_braces l]) list' | Brace_comma :: list' -> let ge = process_glob_list [] current in ge :: process_brace_list [] list' | Brace_end :: _ -> assert false | [] -> let ge = process_glob_list [] current in [ ge ] and process_glob_list acc list = match list with | Glob_star :: list' -> ( match acc with | `Star :: acc' -> (* Ignore the second star! *) process_glob_list acc list' | _ -> process_glob_list (`Star :: acc) list' ) | Glob_qmark :: list' -> process_glob_list (`Qmark :: acc) list' | Glob_brackets (neg,btoks) :: list' -> let set = List.map (function | Bracket_char c -> assert false | Bracket_range (c1,c2) -> (* c1, c2 are ASCII *) (Char.code c1, Char.code c2) | Bracket_code i -> (i, i) | Bracket_end -> assert false ) (reparse_bracket_expr encoding btoks) in let set_obj = ( object method set = set end ) in process_glob_list (`Bracket(neg,set_obj) :: acc) list' | Glob_braces btoks :: list' -> let alts = process_brace_list [] btoks in process_glob_list (`Brace alts :: acc) list' | Glob_literal s :: list' -> if s <> "" then ( match acc with | `Literal s' :: acc' -> process_glob_list (`Literal(s' ^ s) :: acc') list' | _ -> process_glob_list (`Literal s :: acc) list' ) else process_glob_list acc list' | Glob_tilde(s,slash) :: list' -> let atoms = if slash then [ `Literal "/"; `Tilde s ] else [ `Tilde s ] in process_glob_list ( atoms @ acc ) list' | Glob_end :: _ -> assert false | [] -> List.rev acc in try let glob_list = collect_until (Lexing.from_string s) in let glob_expr = process_glob_list [] glob_list in { pat = glob_expr; encoding = encoding } with | Bracket_Unsupported -> raise (Unsupported_expr s) | Lexing_Error -> raise (Bad_glob_expr s) let validate_glob_expr enc expr = let checkenc s = try Netconversion.verify enc s with _ -> failwith "Netglob.validate_glob_expr: literal does not conform \ to selected pattern encoding" in let rec validate ge = match ge with | `Literal s :: ge' -> if s = "" then failwith "Netglob.validate_glob_expr: empty literal"; checkenc s; validate ge' | `Bracket(_,set) :: ge' -> List.iter (fun (j,k) -> if j < 0 || k < 0 || j > k then failwith "Netglob.validate_glob_expr: bad bracket set"; ) set#set | `Brace l :: ge' -> List.iter validate l; validate ge' | `Tilde s :: ge' -> checkenc s; validate ge' | _ :: ge' -> validate ge' | [] -> () in if not (Netconversion.is_ascii_compatible enc) then failwith "Netglob.validate_glob_expr: the encoding is not ASCII-compatible"; validate expr; { pat = expr; encoding = enc } let recover_glob_expr expr = expr.pat let encoding_of_glob_expr expr = expr.encoding (* A more efficient representation for sets: *) type eff_set = { ascii : bool array; non_ascii : (int, unit) Hashtbl.t } let to_eset set = let ascii = Array.make 128 false in let non_ascii = Hashtbl.create 13 in List.iter (fun (k0,k1) -> assert(k0 <= k1); for p = k0 to k1 do if p < 128 then ascii.(p) <- true else Hashtbl.replace non_ascii p () done ) set; { ascii = ascii; non_ascii = non_ascii } let rec mem_eset code eset = if code >= 0 && code < 128 then eset.ascii.(code) else Hashtbl.mem eset.non_ascii code let size_eset eset = let n = ref 0 in for k = 0 to 127 do if eset.ascii.(k) then incr n done; !n + Hashtbl.length eset.non_ascii let ascii_ranges eset = let ranges = ref [] in let inrange = ref None in for k = 0 to 127 do let p = eset.ascii.(k) in match !inrange with | None -> if p then inrange := Some k | Some q -> if not p then ( ranges := (q, k-1) :: !ranges; inrange := None; ) done; ( match !inrange with | None -> () | Some q -> ranges := (q, 127) :: !ranges ); List.rev !ranges let rec exclude_set codes set = match set with [] -> [] | (x,y) :: set' -> let x' = if List.mem x codes then x+1 else x in let y' = if List.mem y codes then y-1 else y in if x = x' && y = y' && x <= y then (x,y) :: exclude_set codes set' else if x' <= y' then exclude_set codes ( (x',y') :: set') else exclude_set codes set' let print_set buf encoding neg_char negated set = (* Always produce a portable expression: *) let eset = to_eset set in (* Check for special characters: *) let want_minus = mem_eset (Char.code '-') eset in let want_rbracket = mem_eset (Char.code ']') eset in let want_circum = mem_eset (Char.code '^') eset in let want_exclam = mem_eset (Char.code '!') eset in let size = size_eset eset in (* Check for very special sets: *) if not negated && want_circum && size = 1 then Buffer.add_string buf "^" (* "[^]" would not be portable enough *) else if not negated && want_exclam && size = 1 then Buffer.add_string buf "!" (* "[!]" would not be portable enough *) else if not negated && want_circum && want_exclam && size = 2 then failwith "print_glob_expr" (* There is no portable representation *) else ( (* First create a set expression where the special characters * '-', ']', '^', and '!' do not occur literally. *) let empty = ref true in let buf' = Buffer.create 200 in let ascii_part = ascii_ranges eset in let ascii_part' = exclude_set (List.map Char.code ['-'; ']'; '^'; '!']) ascii_part in let ascii_part'_eset = to_eset ascii_part' in List.iter (fun (x0,x1) -> if x0 = x1 then ( Buffer.add_char buf' (Char.chr x0); empty := false; ) else if x0 <= x1 then ( Buffer.add_char buf' (Char.chr x0); Buffer.add_char buf' '-'; Buffer.add_char buf' (Char.chr x1); empty := false; ) ) ascii_part'; (* The non-ascii part is easy: *) Hashtbl.iter (fun code _ -> let encoded = Netconversion.ustring_of_uarray encoding [| code |] in Buffer.add_string buf' encoded ) eset.non_ascii; (* Check which of the special characters are already covered * by ranges: *) let done_minus = mem_eset (Char.code '-') ascii_part'_eset in let done_rbracket = mem_eset (Char.code ']') ascii_part'_eset in let done_circum = mem_eset (Char.code '^') ascii_part'_eset in let done_exclam = mem_eset (Char.code '!') ascii_part'_eset in (* Begin with printing *) Buffer.add_string buf (if negated then "[" ^ String.make 1 neg_char else "["); (* ']' must always be the first character of the set: *) if want_rbracket && not done_rbracket then ( Buffer.add_string buf "]"; empty := false; ); Buffer.add_buffer buf buf'; (* '-' must be the first or the last character; '^' and '!' must * not be the first character. So we usually print these * characters in the order "^!-". One case is special: We have * not yet printed any character. Then, "-" must be printed * first (if member of the set), or we have one of the very * special cases already tested above. *) if !empty then ( if want_minus && not done_minus then Buffer.add_char buf '-'; if want_circum && not done_circum then Buffer.add_char buf '^'; if want_exclam && not done_exclam then Buffer.add_char buf '!'; ) else ( if want_circum && not done_circum then Buffer.add_char buf '^'; if want_exclam && not done_exclam then Buffer.add_char buf '!'; if want_minus && not done_minus then Buffer.add_char buf '-'; ); Buffer.add_char buf ']'; ) let esc_re = Netstring_str.regexp "[][*?{},\\~]";; let esc_subst m s = "\\" ^ Netstring_str.matched_group m 0 s let print_glob_expr ?(escape_in_literals=true) expr = let buf = Buffer.create 200 in let rec print gl = match gl with | `Literal s :: gl' -> Buffer.add_string buf (if escape_in_literals then Netstring_str.global_substitute esc_re esc_subst s else s ); print gl' | `Star :: gl' -> Buffer.add_string buf "*"; print gl' | `Qmark :: gl' -> Buffer.add_string buf "?"; print gl' | `Bracket (negated,set) :: gl' -> print_set buf expr.encoding '!' negated set#set; print gl' | `Brace ge_list :: gl' -> Buffer.add_string buf "{"; let first = ref true in List.iter (fun ge -> if not !first then Buffer.add_string buf ","; print ge; ) ge_list; Buffer.add_string buf "}"; print gl' | `Tilde s :: gl' -> Buffer.add_char buf '~'; Buffer.add_string buf s; print gl' | [] -> () in print expr.pat; Buffer.contents buf class local_user_info() = let pe = match Sys.os_type with | "Win32" -> Netconversion.user_encoding() | _ -> None in object method path_encoding = pe method home_directory name = (* Win32: only the HOME method works *) try if name = "" then ( try Sys.getenv "HOME" with Not_found -> let pw = Unix.getpwuid(Unix.getuid()) in pw.Unix.pw_dir ) else (Unix.getpwnam name).Unix.pw_dir with | _ -> raise Not_found end let local_user_info = new local_user_info let rec product f l1 l2 = match l1 with [] -> [] | x1 :: l1' -> List.map (fun x2 -> f x1 x2) l2 @ product f l1' l2 let rec expand_braces ge = match ge with | [] -> [ [] ] | `Brace gelist :: ge' -> let gelist' = List.flatten (List.map expand_braces gelist) in let ge_alts' = expand_braces ge' in product ( @ ) gelist' ge_alts' | any :: ge' -> let ge_alts' = expand_braces ge' in List.map (fun ge_alt' -> any :: ge_alt') ge_alts' let rec expand_tildes encoding user_info ge = match ge with | [] -> [] | `Tilde name :: ge' -> let atom = try let dir = user_info#home_directory name in if dir="" then raise Not_found; (* empty literals not allowed *) ( match user_info#path_encoding with | None -> `Literal dir | Some ui_enc -> if ui_enc = encoding then `Literal dir else `Literal (Netconversion.convert ~in_enc:ui_enc ~out_enc:encoding dir) ) with Not_found -> `Literal ("~" ^ name) in atom :: expand_tildes encoding user_info ge' | any :: ge' -> any :: expand_tildes encoding user_info ge' let expand_glob_expr ?(user_info=local_user_info()) ?(expand_brace=true) ?(expand_tilde=true) expr = let pat' = if expand_tilde then expand_tildes expr.encoding user_info expr.pat else expr.pat in let pat_l = if expand_brace then expand_braces pat' else [pat'] in List.map (fun p -> { expr with pat = p }) pat_l let period = Char.code '.' let slash = Char.code '/' let match_glob_expr ?(protect_period=true) ?(protect_slash=true) ?encoding expr s = let esets = Hashtbl.create 5 in let get_eset set = try Hashtbl.find esets set with Not_found -> let eset = to_eset set#set in Hashtbl.add esets set eset; eset in let u = Netconversion.uarray_of_ustring ( match encoding with | None -> expr.encoding | Some e -> e ) s in let n = Array.length u in let leading_period p = u.(p) = period && (p = 0 || (protect_slash && u.(p - 1) = slash)) in let rec match_at c ge = match ge with | `Literal lit :: ge' -> let lit_u = Netconversion.uarray_of_ustring expr.encoding lit in let lit_n = Array.length lit_u in let ok = try for k = 0 to lit_n - 1 do if c+k >= n then raise Not_found; let code = u.(c+k) in if code <> lit_u.(k) then raise Not_found; done; true with | Not_found -> false in ok && match_at (c+lit_n) ge' | `Star :: ge' -> let k = ref 0 in let cont = ref true in let found = ref false in while c + !k <= n && not !found && !cont do found := match_at (c + !k) ge'; if c + !k < n then cont := (not protect_period || not (leading_period (c + !k))) && (not protect_slash || u.(c + !k) <> slash); incr k; done; !found | `Qmark :: ge' -> let ok = c < n && (not protect_period || not (leading_period c)) && (not protect_slash || u.(c) <> slash) in ok && match_at (c+1) ge' | `Bracket(neg,set) :: ge' -> let ok = c < n && ( let code = u.(c) in (not protect_slash || code <> slash) && (not protect_period || not (leading_period c)) && ( let eset = get_eset set in let is_mem = mem_eset code eset in (neg <> is_mem) ) ) in ok && match_at (c+1) ge' | `Brace _ :: _ -> failwith "Netglob.match_glob_expr: found `Brace subpattern" | `Tilde _ :: _ -> failwith "Netglob.match_glob_expr: found `Tilde subpattern" | [] -> c = n in match_at 0 expr.pat let skip_slashes s k = let l = String.length s in let j = ref k in while !j < l && s.[!j] = '/' do incr j done; !j let rev_skip_slashes s k = let j = ref k in while !j >= 0 && s.[!j] = '/' do decr j done; !j let search_slash s = let k = String.index s '/' in let j = skip_slashes s (k+1) in (k, j) let split_glob_expr expr = let rec split_loop is_first acc ge = (* acc: accumulates the current component *) match ge with | [] -> [ List.rev acc ] | (`Literal s as atom) :: ge' -> assert(s <> ""); ( try let (k,j) = search_slash s in (* or Not_found *) let l = String.length s in let s1 = String.sub s 0 k in (* part before '/' *) let s2 = String.sub s j (l - j) in (* part after '/' *) if is_first && k = 0 then ( (* Case: rooted expression *) let ge'' = if s2 <> "" then (`Literal s2) :: ge' else ge' in let comps = split_loop false [] ge'' in (* N.B. comps is a list of lists... *) match comps with | ( (`Literal s3) :: r ) :: l -> ( `Literal("/" ^ s3) :: r) :: l | r :: l -> (`Literal "/" :: r) :: l | [] -> [ [ `Literal "/" ] ] ) else if ge' = [] && s2 = "" then ( (* Case: component matches only directory *) [ List.rev (`Literal (s1 ^ "/") :: acc) ] ) else ( let acc' = if s1 <> "" then (`Literal s1)::acc else acc in let ge'' = if s2 <> "" then (`Literal s2) :: ge' else ge' in (List.rev acc') :: split_loop false [] ge'' ) with | Not_found -> split_loop false (atom::acc) ge' ) | (`Star | `Qmark | `Bracket(_,_) as atom) :: ge' -> split_loop false (atom::acc) ge' | `Brace _ :: _ -> failwith "Netglob.split_glob_expr: brace expression found" | `Tilde _ :: _ -> failwith "Netglob.split_glob_expr: tilde expression found" in List.map (fun p -> { expr with pat = p }) (split_loop true [] expr.pat) let check_rooted_glob_expr expr = match expr.pat with | (`Literal s) :: r -> assert(s <> ""); if s.[0] = '/' then ( let j = skip_slashes s 1 in let l = String.length s in let s' = String.sub s j (l - j) in (* part after '/' *) if s' = "" then Some { expr with pat = r } else Some { expr with pat = `Literal s' :: r } ) else None | _ -> None let check_directory_glob_expr expr = match List.rev expr.pat with | (`Literal s) :: r -> assert(s <> ""); ( try let l = String.length s in if s.[l-1] <> '/' then raise Not_found; let k = rev_skip_slashes s (l-1) + 1 in let s' = String.sub s 0 k in (* the part before '/' *) if s' = "" then Some { expr with pat = List.rev r } else Some { expr with pat = List.rev (`Literal s' :: r) } with Not_found -> None ) | _ -> None class of_dual_stream_fs (abs_fs:Netfs.stream_fs) rel_fs = let is_abs name = name <> "" && name.[0] = '/' in let fix name = if is_abs name then (abs_fs, name) else (rel_fs, "/" ^ name) in object method path_encoding = abs_fs#path_encoding method read_dir name = let (fs,name) = fix name in try fs#readdir [] name with _ -> [] method file_is_dir name = let (fs,name) = fix name in try fs#test [] name `D with _ -> false method file_exists name = let (fs,name) = fix name in try fs#test [] name `E with _ -> false end class of_stream_fs fs0 = let fs = (fs0 : #Netfs.stream_fs :> Netfs.stream_fs) in of_dual_stream_fs fs fs let of_stream_fs = new of_stream_fs class local_fsys ?encoding () = let abs_fs = Netfs.local_fs ?encoding () in let rel_fs = Netfs.local_fs ?encoding ~root:"." () in of_dual_stream_fs abs_fs rel_fs let local_fsys = new local_fsys let fn_concat d f = let l = String.length d in if l = 0 || d.[l-1] = '/' then d ^ f else d ^ "/" ^ f let glob1 ?base_dir ?(protect_period=true) ?(fsys = local_fsys()) ?user_info ?(mode = `Existing_paths) expr = (* File names and paths are encoded as [fsys] demands it. The encoding of the pattern can be different! *) let rec collect_and_match base_dir generated_prefix components = match components with | [] -> if generated_prefix <> "" then [ generated_prefix ] else [] | comp :: components' -> let full_path file = match base_dir with | Some d -> fn_concat d file | None -> file in let dir_ge = check_directory_glob_expr comp in let comp' = match dir_ge with | Some ge' -> ge' | None -> comp in let check_for_match only_dirs e file = (* file is encoded in fsys#path_encoding. For matching, we need to convert it to the encoding of the pattern. *) try let pe = match fsys#path_encoding with | None -> `Enc_iso88591 (* so no conv errors possible *) | Some pe -> pe in match_glob_expr ~protect_period ~encoding:pe e file && (not only_dirs || fsys#file_is_dir (full_path file)) with | Netconversion.Cannot_represent _ -> false in let files = match comp'.pat with | [ `Literal s ] -> (* s is encoded in expr.encoding. We need it here in the fsys#encoding *) ( try let s' = match fsys#path_encoding with | None -> s | Some pe -> Netconversion.convert ~in_enc:expr.encoding ~out_enc:pe s in match mode with | `Existing_paths -> let path = full_path s' in if fsys # file_exists path then [ s' ] else [] | _ -> [ s' ] with Netconversion.Cannot_represent _ when mode = `Existing_paths -> [] ) | _ -> let only_dirs = components' <> [] || dir_ge <> None in let file_list = fsys#read_dir (full_path ".") in (*eprintf "Files in %s: %s\n%!" (full_path ".") (String.concat "," file_list);*) List.filter (check_for_match only_dirs comp') file_list in List.flatten (List.map (fun file -> let prefixed_file = fn_concat generated_prefix file ^ (if dir_ge <> None then "/" else "") in collect_and_match (Some(full_path file)) prefixed_file components' ) files ) in let collect_and_match_0 components = match components with | comp :: components' -> ( match check_rooted_glob_expr comp with | None -> collect_and_match base_dir "" components | Some comp' -> if comp'.pat = [] then (* Special case "/" *) [ "/" ] else collect_and_match (Some "/") "/" (comp' :: components') ) | [] -> [] in let e_list = expand_glob_expr ?user_info expr in List.flatten (List.map (fun e' -> let l = collect_and_match_0 (split_glob_expr e') in if mode = `All_words && l = [] && e'.pat <> [] then [print_glob_expr e'] else l ) e_list ) let glob ?encoding ?base_dir ?protect_period ?fsys ?user_info ?mode pat = match pat with | `Expr e -> glob1 ?base_dir ?protect_period ?fsys ?user_info ?mode e | `String s -> let e = parse_glob_expr ?encoding s in glob1 ?base_dir ?protect_period ?fsys ?user_info ?mode e ocamlnet-4.1.2/src/netstring/netmime.ml0000644000175000017500000003245612731530350016551 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) open Netchannels type store = [ `Memory | `File of string ] exception Immutable of string class type mime_header_ro = object method fields : (string * string) list method field : string -> string method multiple_field : string -> string list end class type mime_header = object inherit mime_header_ro method ro : bool method set_fields : (string * string) list -> unit method update_field : string -> string -> unit method update_multiple_field : string -> string list -> unit method delete_field : string -> unit end class type mime_body_ro = object method value : string method store : store method open_value_rd : unit -> in_obj_channel method finalize : unit -> unit end class type mime_body = object inherit mime_body_ro method ro : bool method set_value : string -> unit method open_value_wr : unit -> out_obj_channel end type complex_mime_message = mime_header * complex_mime_body and complex_mime_body = [ `Body of mime_body | `Parts of complex_mime_message list ] type complex_mime_message_ro = mime_header_ro * complex_mime_body_ro and complex_mime_body_ro = [ `Body of mime_body_ro | `Parts of complex_mime_message_ro list ] (* Check that coercion is possible: *) let _ = fun x -> (x : complex_mime_message :> complex_mime_message_ro) type mime_message = mime_header * [ `Body of mime_body ] type mime_message_ro = mime_header_ro * [ `Body of mime_body_ro ] module CI : sig (* case-insensitive strings *) type t val compare : t -> t -> int val make : string -> t end = struct type t = string let compare (a_ci:t) (b_ci:t) = Pervasives.compare a_ci b_ci let make s = String.lowercase s end module CIMap = Map.Make(CI) (* Maps from case-insensitive strings to any type *) module DL : sig (* doubly-linked lists *) type 'a t type 'a cell val create : unit -> 'a t val is_empty : 'a t -> bool val cell : 'a -> 'a cell val contents : 'a cell -> 'a val first : 'a t -> 'a cell (* or Not_found *) val last : 'a t -> 'a cell (* or Not_found *) val prev : 'a cell -> 'a cell (* or Not_found *) val next : 'a cell -> 'a cell (* or Not_found *) val iter : ('a cell -> unit) -> 'a t -> unit val delete : 'a cell -> unit val insert_after : neo:'a cell -> 'a cell -> unit val add_at_end : neo:'a cell -> 'a t -> unit val replace : neo:'a cell -> 'a cell -> unit val of_list : 'a list -> 'a t val to_list : 'a t -> 'a list end = struct type 'a t = { mutable first : 'a cell option; mutable last : 'a cell option; } and 'a cell = { mutable prev : 'a cell option; mutable next : 'a cell option; mutable list : 'a t option; contents : 'a; } let create() = { first = None; last = None } let is_empty l = l.first = None let cell x = { prev = None; next = None; list = None; contents = x } let contents c = c.contents let first l = match l.first with Some c -> c | None -> raise Not_found let last l = match l.last with Some c -> c | None -> raise Not_found let prev c = match c.prev with Some c' -> c' | None -> raise Not_found let next c = match c.next with Some c' -> c' | None -> raise Not_found let iter f l = match l.first with Some c -> f c; let current = ref c in while (let c0 = ! current in c0.next) <> None do (* Error in camlp4 *) current := next !current; f !current done; () | None -> () let delete c = match c.list with Some l -> ( match c.prev with Some p -> p.next <- c.next | None -> l.first <- c.next ); ( match c.next with Some n -> n.prev <- c.prev | None -> l.last <- c.prev ); c.prev <- None; c.next <- None; c.list <- None | None -> failwith "DL.delete: cannot delete free cell" let insert_after ~neo c = if neo.list <> None then failwith "DL.insert_after: new cell must be free"; match c.list with Some l -> let nx = c.next in c.next <- Some neo; neo.prev <- Some c; ( match nx with Some n -> n.prev <- Some neo; neo.next <- Some n; | None -> l.last <- Some neo; neo.next <- None ); neo.list <- Some l | None -> failwith "DL.insert_after: cannot insert after free cell" let add_at_end ~neo l = if neo.list <> None then failwith "DL.insert_after: new cell must be free"; match l.last with Some n -> n.next <- Some neo; neo.prev <- Some n; neo.next <- None; neo.list <- Some l; l.last <- Some neo | None -> l.last <- Some neo; l.first <- Some neo; neo.prev <- None; neo.next <- None; neo.list <- Some l let replace ~neo c = if neo.list <> None then failwith "DL.replace: new cell must be free"; match c.list with Some l -> ( match c.prev with Some p -> p.next <- Some neo | None -> l.first <- Some neo ); neo.prev <- c.prev; ( match c.next with Some n -> n.prev <- Some neo | None -> l.last <- Some neo ); neo.next <- c.next; neo.list <- Some l; c.prev <- None; c.next <- None; c.list <- None | None -> failwith "DL.replace: cannot replace free cell" let of_list l = let dl = create() in List.iter (fun x -> add_at_end ~neo:(cell x) dl ) l; dl let rec to_list dl = chain_to_list dl.first and chain_to_list chain = match chain with None -> [] | Some c -> c.contents :: chain_to_list c.next end class basic_mime_header h : mime_header = object (self) val mutable hdr_map = lazy (assert false) val mutable hdr_dl = lazy (assert false) initializer self # do_set_fields h method ro = false (* Heirs can redefine [ro] to make this object immutable *) method fields = DL.to_list (Lazy.force hdr_dl) method field n = let m = Lazy.force hdr_map in match CIMap.find (CI.make n) m with [] -> raise Not_found | cell :: _ -> snd (DL.contents cell) method multiple_field n = let m = Lazy.force hdr_map in try List.map (fun cell -> snd (DL.contents cell)) (CIMap.find (CI.make n) m) with Not_found -> [] method set_fields h = if self#ro then raise (Immutable "set_fields"); self # do_set_fields h method private do_set_fields h = hdr_dl <- lazy (DL.of_list h); hdr_map <- lazy begin (* This seems to be expensive (O(n log n)). Because of this we do it only * on demand; maybe nobody accesses the header at all *) let m = ref CIMap.empty in DL.iter (fun cell -> let (n,v) = DL.contents cell in let n_ci = CI.make n in let current = try CIMap.find n_ci !m with Not_found -> [] in m := CIMap.add n_ci (cell :: current) !m; ) (Lazy.force hdr_dl); CIMap.map List.rev !m end method update_field n v = if self#ro then raise (Immutable "update_field"); self # update_multiple_field n [v] method update_multiple_field n vl = if self#ro then raise (Immutable "update_multiple_field"); let n_ci = CI.make n in let m = Lazy.force hdr_map in let dl = Lazy.force hdr_dl in (* Algorithm: First try to replace existing values. * If there are more new values than old values, * at the excess values after the last old value, * or if not possible, at the end. *) let insert_point = ref None in let old_cells = ref(try CIMap.find n_ci m with Not_found -> []) in let new_vals = ref vl in let new_cells = ref [] in while !old_cells <> [] || !new_vals <> [] do match !old_cells, !new_vals with (old_cell :: old_cells'), (new_val :: new_vals') -> (* Only update if the value has changed: *) let (old_n, old_val) = DL.contents old_cell in if old_val = new_val then ( new_cells := old_cell :: !new_cells; insert_point := Some old_cell; ) else ( let new_cell = DL.cell (n, new_val) in DL.replace ~neo:new_cell old_cell; insert_point := Some new_cell; new_cells := new_cell :: !new_cells ); old_cells := old_cells'; new_vals := new_vals'; | [], (new_val :: new_vals') -> let new_cell = DL.cell (n, new_val) in ( match !insert_point with Some p -> DL.insert_after ~neo:new_cell p; | None -> DL.add_at_end ~neo:new_cell dl ); new_vals := new_vals'; insert_point := Some new_cell; new_cells := new_cell :: !new_cells | (old_cell :: old_cells'), [] -> DL.delete old_cell; old_cells := old_cells' | [], [] -> assert false done; let m' = CIMap.add n_ci (List.rev !new_cells) m in hdr_map <- lazy m' method delete_field n = if self#ro then raise (Immutable "delete_field"); let n_ci = CI.make n in let m = Lazy.force hdr_map in let old_cells = try CIMap.find n_ci m with Not_found -> [] in List.iter DL.delete old_cells; let m' = CIMap.remove n_ci m in hdr_map <- lazy m'; end ;; let basic_mime_header = new basic_mime_header class wrap_mime_header hdr : mime_header = object(self) method fields = hdr#fields method field = hdr#field method multiple_field = hdr#multiple_field method ro = hdr#ro (* Heirs can redefine [ro] to make this object immutable *) method set_fields fields = if self#ro then raise(Immutable "set_fields"); hdr#set_fields fields method update_field n v = if self#ro then raise(Immutable "update_field"); hdr#update_field n v method update_multiple_field n v = if self#ro then raise(Immutable "update_multiple_fields"); hdr#update_multiple_field n v method delete_field n = if self#ro then raise(Immutable "delete_field"); hdr#delete_field n end class wrap_mime_header_ro hdr : mime_header = object(self) method fields = hdr#fields method field = hdr#field method multiple_field = hdr#multiple_field method ro = true method set_fields _ = raise (Immutable "set_fields") method update_field _ _ = raise (Immutable "update_field") method update_multiple_field _ _ = raise (Immutable "update_multiple_field") method delete_field _ = raise (Immutable "delete_field") end let wrap_mime_header_ro = new wrap_mime_header_ro class memory_mime_body v : mime_body = object (self) val mutable value = v val mutable finalized = false method value = if finalized then self # finalized(); value method store = `Memory method open_value_rd() = if finalized then self # finalized(); new input_string value method finalize() = finalized <- true method ro = (* Heirs can redefine [ro] to make this object immutable *) false method set_value s = if self#ro then raise (Immutable "set_value"); if finalized then self # finalized(); value <- s; method open_value_wr() = if self#ro then raise (Immutable "open_value_wr"); if finalized then self # finalized(); let b = Netbuffer.create 60 in new output_netbuffer ~onclose:(fun () -> value <- Netbuffer.contents b) b; method private finalized() = failwith "Netmime.memory_mime_body: object is finalized"; end ;; let memory_mime_body = new memory_mime_body class file_mime_body ?(fin=false) f : mime_body = object (self) val mutable finalized = false val fin = fin val filename = f val cached_value = Weak.create 1 method ro = (* Heirs can redefine [ro] to make this object immutable *) false method store = `File filename method value = if finalized then self # finalized(); match Weak.get cached_value 0 with None -> with_in_obj_channel (new input_channel (open_in_bin filename)) (fun objch -> let v = string_of_in_obj_channel objch in Weak.set cached_value 0 (Some v); v ) | Some v -> v method open_value_rd() = if finalized then self # finalized(); new input_channel (open_in_bin filename) method set_value s = if self#ro then raise (Immutable "set_value"); if finalized then self # finalized(); with_out_obj_channel (new output_channel (open_out_bin filename)) (fun ch -> ch # output_string s); method open_value_wr() = if self#ro then raise (Immutable "open_value_wr"); if finalized then self # finalized(); new output_channel (open_out_bin filename) method finalize () = if fin && not finalized then begin try Sys.remove filename with _ -> () end; finalized <- true method private finalized() = failwith "Netmime.file_mime_body: object is finalized"; end ;; let file_mime_body = new file_mime_body class wrap_mime_body bdy : mime_body = object (self) method value = bdy#value method store = bdy#store method open_value_rd = bdy#open_value_rd method finalize = bdy#finalize method ro = bdy#ro method set_value = bdy#set_value method open_value_wr = bdy#open_value_wr end class wrap_mime_body_ro bdy : mime_body = object (self) method value = bdy#value method store = bdy#store method open_value_rd = bdy#open_value_rd method finalize = bdy#finalize method ro = true method set_value _ = raise (Immutable "set_value") method open_value_wr _ = raise (Immutable "open_value_wr") end let wrap_mime_body_ro = new wrap_mime_body_ro let rec wrap_complex_mime_message_ro (h,cb) = (wrap_mime_header_ro h, match cb with `Body b -> `Body(wrap_mime_body_ro b) | `Parts p -> `Parts(List.map wrap_complex_mime_message_ro p) ) ;; ocamlnet-4.1.2/src/netstring/neturl_tut.txt0000644000175000017500000001657212731530350017530 0ustar gerdgerd{1:tutorial Neturl Tutorial} This module is a quite flexible parser for various kinds of URLs occuring in practice. The syntax is configurable such that one URL module can handle a lot of URL types in a generic way. {2 Generic Parsing} In order to parse an absolute URL (beginning with a scheme identifier like "http:...") of unknown type just call {[ let url = parse_url "http://me@server/directory" ]} By default, this function can parse all URL types listed at {!Neturl.common_url_syntax}. However, the default configuration implies also that - relative URLs cannot be parsed - fragment identifiers are rejected (i.e. the part after the hash mark like in "http://server/document#location") - characters are rejected when the most significant bit (MSB) is set The latter two features can be simply enabled by passing the arguments [~enable_fragment:true] and [~accept_8bits:true], respectively. The restriction that relative URLs are rejected has to do with the problem that context information is missing. Because the scheme identifier (like "http") is not available, the function does not know which syntax the relative URL should have. For example, the relative URL [dir/file?x=1] is differently parsed when it is taken relative to an [http] URL and when it is interpreted relative to an [ftp] URL. In the first case, the path component of the URL is ["dir/file"] and the query component is ["?x=1"], but in the latter case the path component is ["dir/file?x=1"], and a query component is not allowed. The solution is that the syntax of the base URL, relative to which the URL is seen, must be passed as additional argument. Under the assumption that [base_url] is the base URL, use {[ let url = parse_url ~base_syntax:(url_syntax_of_url base_url) "/dir/file?x=1" ]} Of course, this assumes that the base URL is known when the url is parsed. {2 Parsing For a Certain Syntax} The function [url_of_string] is also a parser, but you must pass the URL syntax as argument, e.g. {[ let url = url_of_string syntax "ipp://server/printer" ]} Pass as [syntax] one of the elements of {!Neturl.common_url_syntax}, e.g. {[ let syntax = Hashtbl.find common_url_syntax "ipp" ]} or a self-defined syntax. {2 Printing URLs} This is much easier, just call [string_of_url] to convert an URL to a string. It is ensured that every URL always has an unambiguous representation as string. {2 URL Components} Internally, the parsed URL is decomposed into its components. This module supports two ways of decomposition: + [scheme://user;userparams:password@host:port/path;params?query#fragment] + [scheme:other;params?query#fragment] The first form is used for services that directly connect to a certain service running on a certain host. The second form can be used for everything else not falling under this category. Examples: {ul {- [http://me:abrakadabra@server/dir?x=5#section1] scheme=["http"], user=["me"], password=["abrakadabra"], host=["server"], path=["/dir"], query=["x=5"], fragment=["section1"] } {- [pop://you;auth=digest-md5@mail] scheme=["pop"], user=["you"], user_params=[["auth=digest-md5"]], host=["mail"] } {- [mailto:gerd@gerd-stolpmann.de?cc=you@domain.com] scheme=["mailto"], other=["gerd@gerd-stolpmann.de"], query=["cc=you@domain.com"] } } It is important to mention that the decomposition is not fully performed, but only down to a certain level. For example, the query ["x=5"] could be further analysed and be split into the syntactic parts ["x"] and ["5"]. However, this is not done, just because the author seeked a compromise between the depth of analysis and the genericy of application. {2 URL Escaping} In order to represent the so-called unsafe characters, one can use [%]-escaping in URLs. For example, this URL contains a password with [@], an unsafe character encoded as [%40]: {[ http://user:!$%40?@server ]} The question is how this module handles such escapings. It is surprising that the URL parser does not decode these escaped forms (it checks, however, whether they are syntactically correct). Internally, the components are stored as parsed, and one can even retrieve them in their original form. The function [url_password] returns the password component. Applied to the above URL, one can get the password in its original, "encoded" form, or as decoded string: - [url_password ~encoded:true url] returns ["!$%40?"] - [url_password url] returns ["!$@?"] {2 Representation of URL Components} The URL components can be retrieved with the functions - [url_scheme] - [url_user] - [url_user_param] - [url_password] - [url_host] - [url_port] - [url_path] - [url_param] - [url_query] - [url_fragment] - [url_other] Most components are just strings. Of course, the port number is an integer. The path component ([url_path]) has a non-obvious representation. The path is represented as string list, e.g. "a/b/c" is represented as [ ["a";"b";"c"] ]. Note, however, that absolute paths have an empty string at the beginning of the list, e.g. "/a/b/" is [ [""; "a"; "b"; "" ] ]. In most cases, the paths found in URLs are absolute, and because of this it is quite common to find this empty string at the beginning of the path list. The corner cases are: - [ [] ] is used when the path is missing in the URL - [ [ "" ] ] is "/" - [ [ ""; "" ] ] is considered as illegal The last two cases are somewhat arbitrary. There is the helper function [split_path] to convert the string representation of paths into the list representation. The parameters ([url_user_param] and [url_param]) are lists, too. A parameter starts with a semicolon as delimiter and runs until the next component, which can be another parameter. The contents, i.e. the values after the semicolons are put into the list. For example, the parameter ";auth=unix;type=i" is represented as [ ["auth=unix"; "type=i"] ]. {2 Hint: Getting Query Arguments} The query component is represented as a single string. When queries use the standard syntax "name1=value1&name2=value2&...", one can parse this string using {[ let args = Netencoding.Url.dest_url_encoded_parameters (url_query ~encoded:true url) ]} Note that [encoded:true] is needed. {2 Creating and Modifying URLs} In order to create a URL for a certain syntax, call [make_url]: {[ let url = make_url ~scheme:"http" ~user:"user" ~password:"!$@?" ~host:"server" syntax ]} It is checked whether the URL conforms to the passed syntax. By default, the components are passed in decoded form, and [make_url] automatically encodes them if necessary (here, for example, the at sign in the password). Alternatively, one can set [~encoded:true], and pass the already escaped components. In this case, [make_url] checks whether the encoding is sufficient to represent the URL as string. The functions [modify_url], [default_url], [undefault_url], and [remove_from_url] can be used to modify an existing URL. {2 Relative URLs} A URL is relative when the scheme identifier at the beginning is omitted. In this case, the URL can be transformed to an absolute URL when the base URL is known. The algorithm for this is defined in RFC 1808, and quite complicated. It is implemented in [apply_relative_url], but usually {!Neturl.ensure_absolute_url} is the more convenient function. Just call {[ let url' = ensure_absolute_url ~base url ]} to convert [url] to its absolute counterpart [url'] when it is relative, and to pass the URL unchanged when it is already absolute. ocamlnet-4.1.2/src/netstring/netdb.mli0000644000175000017500000000260712731530350016353 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (* This is an internal interface of ocamlnet! Do not use outside! *) (* This module manages persistent values (often lookup tables). These * values can be stored in external files, or they can be initialized * from string values. *) val read_db : string -> string (* Reads the value with the given name, and returns it. * * First it is checked whether there was a set_db call, and if so, * this value is unmarshalled and returned. Otherwise, it is checked * whether there is a loader, and if so, it is called. * * In both cases the checksum is checked. *) val exists_db : string -> bool (* Checks whether the named value is available, i.e. read_db would * be able to find it *) val set_db_checksum : string -> string -> unit (* [set_db_checksum key cksum]: sets the MD5 digest of this key *) val set_db : string -> string -> unit (* Sets the persistent value with the given name (1st arg) to the * passed value (2nd arg). The value must be marshalled as string. *) val set_db_loader : string -> (string -> string) -> unit (* [set_db_loader key loader]: sets a loader for this key, which is called when set_db has not been set for this key. The arg of the loader is the key. *) val enable_db_loaders : bool -> unit (* Whether dynamic loading is enabled *) ocamlnet-4.1.2/src/netstring/netmime_channels.mli0000644000175000017500000002615212731530350020571 0ustar gerdgerd(* $Id$ *) (** MIME: parsing and printing for channels *) open Netmime open Netchannels (** {1:parsing Parsing MIME messages} *) val read_mime_header : ?unfold:bool -> (* default: false *) ?strip:bool -> (* default: true *) ?ro:bool -> (* default: false *) Netstream.in_obj_stream -> mime_header (** Decodes the MIME header that begins at the current position of the * netstream, and returns the header as class [basic_mime_header]. * After returning, the stream is advanced to the byte following the * empty line terminating the header. * * Example: To read the header at the beginning of the file "f", use: * {[ * let ch = new Netchannels.input_channel (open_in "f") in * let stream = new Netstream.input_stream ch in * let h = read_mime_header stream in * ... * stream#close_in(); (* no need to close ch *) * ]} * * Note that although the [stream] position after parsing is exactly * known, the position of [ch] cannot be predicted. * * @param unfold whether linefeeds are replaced by spaces in the values of the * header fields (Note: defaults to [false] here in contrast to * [Netmime_string.scan_header]!) * @param strip whether whitespace at the beginning and at the end of the * header fields is stripped * @param ro whether the returned header is read-only (default: false) *) (** Hint: To write the header [h] into the channel [ch], use * {[ Netmime_string.write_header ch h#fields ]} * * Link: {!Netmime_string.write_header} *) type multipart_style = [ `None | `Flat | `Deep ] (** How to parse multipart messages: * - [`None]: Do not handle multipart messages specially. Multipart bodies * are not further decoded, and returned as [`Body b] where [b] is * the transfer-encoded text representation. * - [`Flat]: If the top-level message is a multipart message, the parts * are separated and returned as list. If the parts are again multipart * messages, these inner multipart messages are not furher decoded * and returned as [`Body b]. * - [`Deep]: Multipart messages are recursively decoded and returned as * tree structure. * * This value determines how far the [complex_mime_message] structure * is created for a parsed MIME message. [`None] means that no parts * are decoded, and messages have always only a simple [`Body b], * even if [b] is in reality a multi-part body. With [`Flat], the * top-level multi-part bodies are decoded (if found), and messages * can have a structured [`Parts [_, `Body b1; _, `Body b1; ...]] * body. Finally, [`Deep] allows that inner multi-part bodies are * recursively decoded, and messages can have an arbitrarily complex * form. *) val decode_mime_body : #mime_header_ro -> out_obj_channel -> out_obj_channel (** [let ch' = decode_mime_body hdr ch]: * According to the value of the Content-transfer-encoding header field * in [hdr] the encoded MIME body written to [ch'] is decoded and transferred * to [ch]. * * Handles 7bit, 8bit, binary, quoted-printable, base64. * * Example: The file "f" contains base64-encoded data, and is to be decoded * and to be stored in "g": * * {[ * let ch_f = new Netchannels.input_channel (open_in "f") in * let ch_g = new Netchannels.output_channel (open_out "g") in * let hdr = new basic_mime_header ["content-transfer-encoding", "base64" ] in * let ch = decode_mime_body hdr ch_g in * ch # output_channel ch_f; * ch # close_out(); * ch_g # close_out(); * ch_f # close_in(); * ]} * * Note: This function is internally used by [read_mime_message] to * decode bodies. There is usually no need to call it directly. *) val storage : ?fin:bool -> store -> (mime_body * out_obj_channel) (** Creates a new storage facility for a mime body according to [store]. * This function can be used to build the [storage_style] argument * of the class [read_mime_message] (below). For example, this is * useful to store large attachments in external files, as in: * * {[ * let storage_style hdr = * let filename = hdr ... (* extract from hdr *) in * storage (`File filename) * ]} * * @param fin whether to finalize bodies stored in files. * Default: false *) val read_mime_message : ?unfold:bool -> (* Default: false *) ?strip:bool -> (* default: true *) ?ro:bool -> (* Default: false *) ?multipart_style:multipart_style -> (* Default: `Deep *) ?storage_style:(mime_header -> (mime_body * out_obj_channel)) -> Netstream.in_obj_stream -> complex_mime_message (** Decodes the MIME message that begins at the current position of the * passed netstream. It is expected that the message continues until * EOF of the netstream. * * Multipart messages are decoded as specified by [multipart_style] (see * above). * * Message bodies with content-transfer-encodings of 7bit, 8bit, binary, * base64, and quoted-printable can be processed. The bodies are stored * without content-transfer-encoding (i.e. in decoded form), but the * content-transfer-encoding header field is not removed from the header. * * The [storage_style] function determines where every message body is * stored. The corresponding header of the body is passed to the function * as argument; the result of the function is a pair of a new [mime_body] * and an [out_obj_channel] writing into this body. You can create such a * pair by calling [storage] (above). * * By default, the [storage_style] is [storage ?ro `Memory] for every header. * Here, the designator [`Memory] means that the body will be stored in an * O'Caml string. The designator [`File fn] would mean that the body will be stored in the * file [fn]. The file would be created if it did not yet exist, and * it would be overwritten if it did already exist. * * Note that the [storage_style] function is called for every non-multipart * body part. * * Large message bodies (> maximum string length) are supported if the * bodies are stored in files. The memory consumption is optimized for * this case, and usually only a small constant amount of memory is needed. * * Example: * * Parse the MIME message stored in the file f: * * {[ * let m = read_mime_message * (new input_stream (new input_channel (open_in f))) * ]} * * @param unfold whether linefeeds are replaced by spaces in the values of the * header fields (Note: defaults to [false] here in contrast to * {!Netmime_string.scan_header}!) * @param strip whether whitespace at the beginning and at the end of the * header fields is stripped * @param ro Whether the created MIME message is read-only * *) (* TODO: what about messages with type "message/*"? It may be possible that * they can be recursively decoded, but it is also legal for some media * types that they are "partial". * Currently the type "message/*" is NOT decoded. *) (** {1:printing Printing MIME Messages} *) val encode_mime_body : ?crlf:bool -> #mime_header_ro -> out_obj_channel -> out_obj_channel (** [let ch' = encode_mime_body hdr ch]: * According to the value of the Content-transfer-encoding header field * in [hdr] the unencoded MIME body written to ch' is encoded and transferred * to ch. * * Handles 7bit, 8bit, binary, quoted-printable, base64. * * For an example, see [decode_mime_body] which works in a similar way * but performs decoding instead of encoding. * * @param crlf if set (this is by default the case) CR/LF will be used for * end-of-line (eol) termination, if not set LF will be used. For 7bit, 8bit and * binary encoding the existing eol delimiters are not rewritten, so this option * has only an effect for quoted-printable and base64. *) val write_mime_message : ?wr_header:bool -> (* default: true *) ?wr_body:bool -> (* default: true *) ?nr:int -> (* default: 0 *) ?ret_boundary:string ref -> (* default: do not return it *) ?crlf:bool -> (* default: true *) Netchannels.out_obj_channel -> complex_mime_message -> unit (** Writes the MIME message to the output channel. The content-transfer- * encoding of the leaves is respected, and their bodies are encoded * accordingly. The content-transfer-encoding of multipart messages is * always "fixed", i.e. set to "7bit", "8bit", or "binary" depending * on the contents. * * The function fails if multipart messages do not have a multipart * content type field (i.e. the content type does not begin with "multipart"). * If only the boundary parameter is missing, a good boundary parameter is * added to the content type. "Good" means here that it is impossible * that the boundary string occurs in the message body if the * content-transfer-encoding is quoted-printable or base64, and that * such an occurrence is very unlikely if the body is not encoded. * If the whole content type field is missing, a "multipart/mixed" type * with a boundary parameter is added to the printed header. * * Note that already existing boundaries are used, no matter whether * they are of good quality or not. * * No other header fields are added, deleted or modified. The mentioned * modifications are _not_ written back to the passed MIME message but * only added to the generated message text. * * It is possible in some cases that the boundary does not work (both * the existing boundary, and the added boundary). This causes that a wrong * and unparseable MIME message is written. In order to ensure a correct * MIME message, it is recommended to parse the written text, and to compare * the structure of the message trees. It is, however, very unlikely that * a problem arises. * * Note that if the passed message is a simple message like (_,`Body _), * and if no content-transfer-encoding is set, the written message might * not end with a linefeed character. * * @param wr_header If true, the outermost header is written. Inner headers * of the message parts are written unless ~wr_body=false. * @param wr_body If true, the body of the whole message is written; if false, * no body is written at all. * @param nr This argument sets the counter that is included in generated * boundaries to a certain minimum value. * @param ret_boundary if passed, the boundary of the outermost multipart * message is written to this reference. (Internally used.) * @param crlf if set (this is by default the case) CR/LF will be used for * end-of-line (eol) termination, if not set LF will be used. The eol * separator is used for the header, the multipart framing, and for * bodies encoded as quoted-printable or base64. Other eol separators are * left untouched. *) ocamlnet-4.1.2/src/netstring/netmech_plain_sasl.mli0000644000175000017500000000161512731530350021105 0ustar gerdgerd(* $Id$ *) module PLAIN : Netsys_sasl_types.SASL_MECHANISM (** The PLAIN SASL mechanism (RFC 4616). Key facts: - This mechanism sends user name, authorization name and password as cleartext - There is no support for channel binding within the mechanism. - It is insecure, and should only be used over channels that are otherwise secured. Parameters: - Both [create_client_session] and [create_server_session] accept the boolean parameter "mutual". If true, however, authentication fails immediately, as mutual authentication cannot be supported. - The same is true for the boolean parameter "secure", because PLAIN is insecure. As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of PLAIN should pass user names and passwords through {!Netsaslprep.saslprep}. *) ocamlnet-4.1.2/src/netstring/unicode_charinfo.txt0000644000175000017500000006161312731530350020616 0ustar gerdgerdU 97-122 65-90 T 97-122 65-90 L 65-90 97-122 L 192-214 224-246 U 181-181 924-924 T 181-181 924-924 U 224-246 192-214 T 224-246 192-214 U 248-254 216-222 T 248-254 216-222 L 216-222 248-254 U 255-255 376-376 T 255-255 376-376 L 256-256 257-257 U 257-257 256-256 T 257-257 256-256 L 258-258 259-259 U 259-259 258-258 T 259-259 258-258 L 260-260 261-261 U 261-261 260-260 T 261-261 260-260 L 262-262 263-263 U 263-263 262-262 T 263-263 262-262 L 264-264 265-265 U 265-265 264-264 T 265-265 264-264 L 266-266 267-267 U 267-267 266-266 T 267-267 266-266 L 268-268 269-269 U 269-269 268-268 T 269-269 268-268 L 270-270 271-271 U 271-271 270-270 T 271-271 270-270 L 272-272 273-273 U 273-273 272-272 T 273-273 272-272 L 274-274 275-275 U 275-275 274-274 T 275-275 274-274 L 276-276 277-277 U 277-277 276-276 T 277-277 276-276 L 278-278 279-279 U 279-279 278-278 T 279-279 278-278 L 280-280 281-281 U 281-281 280-280 T 281-281 280-280 L 282-282 283-283 U 283-283 282-282 T 283-283 282-282 L 284-284 285-285 U 285-285 284-284 T 285-285 284-284 L 286-286 287-287 U 287-287 286-286 T 287-287 286-286 L 288-288 289-289 U 289-289 288-288 T 289-289 288-288 L 290-290 291-291 U 291-291 290-290 T 291-291 290-290 L 292-292 293-293 U 293-293 292-292 T 293-293 292-292 L 294-294 295-295 U 295-295 294-294 T 295-295 294-294 L 296-296 297-297 U 297-297 296-296 T 297-297 296-296 L 298-298 299-299 U 299-299 298-298 T 299-299 298-298 L 300-300 301-301 U 301-301 300-300 T 301-301 300-300 L 302-302 303-303 U 303-303 302-302 T 303-303 302-302 L 304-304 105-105 U 305-305 73-73 T 305-305 73-73 L 306-306 307-307 U 307-307 306-306 T 307-307 306-306 L 308-308 309-309 U 309-309 308-308 T 309-309 308-308 L 310-310 311-311 U 311-311 310-310 T 311-311 310-310 L 313-313 314-314 U 314-314 313-313 T 314-314 313-313 L 315-315 316-316 U 316-316 315-315 T 316-316 315-315 L 317-317 318-318 U 318-318 317-317 T 318-318 317-317 L 319-319 320-320 U 320-320 319-319 T 320-320 319-319 L 321-321 322-322 U 322-322 321-321 T 322-322 321-321 L 323-323 324-324 U 324-324 323-323 T 324-324 323-323 L 325-325 326-326 U 326-326 325-325 T 326-326 325-325 L 327-327 328-328 U 328-328 327-327 T 328-328 327-327 L 330-330 331-331 U 331-331 330-330 T 331-331 330-330 L 332-332 333-333 U 333-333 332-332 T 333-333 332-332 L 334-334 335-335 U 335-335 334-334 T 335-335 334-334 L 336-336 337-337 U 337-337 336-336 T 337-337 336-336 L 338-338 339-339 U 339-339 338-338 T 339-339 338-338 L 340-340 341-341 U 341-341 340-340 T 341-341 340-340 L 342-342 343-343 U 343-343 342-342 T 343-343 342-342 L 344-344 345-345 U 345-345 344-344 T 345-345 344-344 L 346-346 347-347 U 347-347 346-346 T 347-347 346-346 L 348-348 349-349 U 349-349 348-348 T 349-349 348-348 L 350-350 351-351 U 351-351 350-350 T 351-351 350-350 L 352-352 353-353 U 353-353 352-352 T 353-353 352-352 L 354-354 355-355 U 355-355 354-354 T 355-355 354-354 L 356-356 357-357 U 357-357 356-356 T 357-357 356-356 L 358-358 359-359 U 359-359 358-358 T 359-359 358-358 L 360-360 361-361 U 361-361 360-360 T 361-361 360-360 L 362-362 363-363 U 363-363 362-362 T 363-363 362-362 L 364-364 365-365 U 365-365 364-364 T 365-365 364-364 L 366-366 367-367 U 367-367 366-366 T 367-367 366-366 L 368-368 369-369 U 369-369 368-368 T 369-369 368-368 L 370-370 371-371 U 371-371 370-370 T 371-371 370-370 L 372-372 373-373 U 373-373 372-372 T 373-373 372-372 L 374-374 375-375 L 376-376 255-255 U 375-375 374-374 T 375-375 374-374 L 377-377 378-378 U 378-378 377-377 T 378-378 377-377 L 379-379 380-380 U 380-380 379-379 T 380-380 379-379 U 382-382 381-381 T 382-382 381-381 L 381-381 382-382 L 385-385 595-595 U 383-383 83-83 T 383-383 83-83 L 386-386 387-387 U 387-387 386-386 T 387-387 386-386 L 388-388 389-389 L 390-390 596-596 U 389-389 388-388 T 389-389 388-388 L 391-391 392-392 L 393-394 598-599 U 392-392 391-391 T 392-392 391-391 L 395-395 396-396 L 398-398 477-477 L 399-399 601-601 L 400-400 603-603 U 396-396 395-395 T 396-396 395-395 L 401-401 402-402 L 403-403 608-608 U 402-402 401-401 T 402-402 401-401 L 404-404 611-611 L 406-406 617-617 L 407-407 616-616 U 405-405 502-502 T 405-405 502-502 L 408-408 409-409 L 412-412 623-623 U 409-409 408-408 T 409-409 408-408 L 413-413 626-626 L 415-415 629-629 U 414-414 544-544 T 414-414 544-544 L 416-416 417-417 U 417-417 416-416 T 417-417 416-416 L 418-418 419-419 U 419-419 418-418 T 419-419 418-418 L 420-420 421-421 L 422-422 640-640 U 421-421 420-420 T 421-421 420-420 L 423-423 424-424 L 425-425 643-643 U 424-424 423-423 T 424-424 423-423 L 428-428 429-429 L 430-430 648-648 U 429-429 428-428 T 429-429 428-428 L 431-431 432-432 L 433-434 650-651 U 432-432 431-431 T 432-432 431-431 L 435-435 436-436 U 436-436 435-435 T 436-436 435-435 L 437-437 438-438 L 439-439 658-658 U 438-438 437-437 T 438-438 437-437 L 440-440 441-441 U 441-441 440-440 T 441-441 440-440 U 445-445 444-444 T 445-445 444-444 L 444-444 445-445 T 447-447 503-503 L 452-452 454-454 U 447-447 503-503 U 453-453 452-452 T 452-452 453-453 L 453-453 454-454 T 454-454 453-453 L 455-455 457-457 U 454-454 452-452 U 456-456 455-455 T 455-455 456-456 L 456-456 457-457 T 457-457 456-456 L 458-458 460-460 U 457-457 455-455 U 459-459 458-458 T 458-458 459-459 L 459-459 460-460 U 460-460 458-458 T 460-460 459-459 L 461-461 462-462 U 462-462 461-461 T 462-462 461-461 L 463-463 464-464 U 464-464 463-463 T 464-464 463-463 L 465-465 466-466 U 466-466 465-465 T 466-466 465-465 L 467-467 468-468 U 468-468 467-467 T 468-468 467-467 L 469-469 470-470 U 470-470 469-469 T 470-470 469-469 L 471-471 472-472 U 472-472 471-471 T 472-472 471-471 L 473-473 474-474 U 474-474 473-473 T 474-474 473-473 U 476-476 475-475 T 476-476 475-475 L 475-475 476-476 U 477-477 398-398 T 477-477 398-398 L 478-478 479-479 U 479-479 478-478 T 479-479 478-478 L 480-480 481-481 U 481-481 480-480 T 481-481 480-480 L 482-482 483-483 U 483-483 482-482 T 483-483 482-482 L 484-484 485-485 U 485-485 484-484 T 485-485 484-484 L 486-486 487-487 U 487-487 486-486 T 487-487 486-486 L 488-488 489-489 U 489-489 488-488 T 489-489 488-488 L 490-490 491-491 U 491-491 490-490 T 491-491 490-490 L 492-492 493-493 U 493-493 492-492 T 493-493 492-492 L 494-494 495-495 T 495-495 494-494 L 497-497 499-499 U 495-495 494-494 U 498-498 497-497 T 497-497 498-498 L 498-498 499-499 U 499-499 497-497 T 499-499 498-498 L 500-500 501-501 L 502-502 405-405 L 503-503 447-447 U 501-501 500-500 T 501-501 500-500 L 504-504 505-505 U 505-505 504-504 T 505-505 504-504 L 506-506 507-507 U 507-507 506-506 T 507-507 506-506 L 508-508 509-509 U 509-509 508-508 T 509-509 508-508 L 510-510 511-511 U 511-511 510-510 T 511-511 510-510 L 512-512 513-513 U 513-513 512-512 T 513-513 512-512 L 514-514 515-515 U 515-515 514-514 T 515-515 514-514 L 516-516 517-517 U 517-517 516-516 T 517-517 516-516 L 518-518 519-519 U 519-519 518-518 T 519-519 518-518 L 520-520 521-521 U 521-521 520-520 T 521-521 520-520 L 522-522 523-523 U 523-523 522-522 T 523-523 522-522 L 524-524 525-525 U 525-525 524-524 T 525-525 524-524 L 526-526 527-527 U 527-527 526-526 T 527-527 526-526 L 528-528 529-529 U 529-529 528-528 T 529-529 528-528 L 530-530 531-531 U 531-531 530-530 T 531-531 530-530 L 532-532 533-533 U 533-533 532-532 T 533-533 532-532 L 534-534 535-535 U 535-535 534-534 T 535-535 534-534 L 536-536 537-537 U 537-537 536-536 T 537-537 536-536 L 538-538 539-539 U 539-539 538-538 T 539-539 538-538 L 540-540 541-541 U 541-541 540-540 T 541-541 540-540 L 542-542 543-543 L 544-544 414-414 U 543-543 542-542 T 543-543 542-542 L 546-546 547-547 U 547-547 546-546 T 547-547 546-546 L 548-548 549-549 U 549-549 548-548 T 549-549 548-548 L 550-550 551-551 U 551-551 550-550 T 551-551 550-550 L 552-552 553-553 U 553-553 552-552 T 553-553 552-552 L 554-554 555-555 U 555-555 554-554 T 555-555 554-554 L 556-556 557-557 U 557-557 556-556 T 557-557 556-556 L 558-558 559-559 U 559-559 558-558 T 559-559 558-558 L 560-560 561-561 U 561-561 560-560 T 561-561 560-560 U 563-563 562-562 T 563-563 562-562 U 595-595 385-385 T 595-595 385-385 U 596-596 390-390 T 596-596 390-390 U 598-599 393-394 T 598-599 393-394 U 601-601 399-399 T 601-601 399-399 U 603-603 400-400 T 603-603 400-400 U 608-608 403-403 T 608-608 403-403 U 611-611 404-404 T 611-611 404-404 U 616-616 407-407 T 616-616 407-407 U 617-617 406-406 T 617-617 406-406 U 623-623 412-412 T 623-623 412-412 U 626-626 413-413 T 626-626 413-413 U 629-629 415-415 T 629-629 415-415 U 640-640 422-422 T 640-640 422-422 U 643-643 425-425 T 643-643 425-425 U 648-648 430-430 T 648-648 430-430 U 650-651 433-434 T 650-651 433-434 U 658-658 439-439 T 658-658 439-439 L 562-562 563-563 L 902-902 940-940 L 904-906 941-943 L 908-908 972-972 L 910-911 973-974 L 913-929 945-961 U 837-837 921-921 T 837-837 921-921 U 940-940 902-902 T 940-940 902-902 U 941-943 904-906 T 941-943 904-906 U 945-961 913-929 T 945-961 913-929 U 962-962 931-931 T 962-962 931-931 U 963-971 931-939 T 963-971 931-939 U 972-972 908-908 T 972-972 908-908 U 973-974 910-911 T 973-974 910-911 U 976-976 914-914 T 976-976 914-914 U 977-977 920-920 T 977-977 920-920 U 981-981 934-934 T 981-981 934-934 L 931-939 963-971 U 982-982 928-928 T 982-982 928-928 L 984-984 985-985 U 985-985 984-984 T 985-985 984-984 L 986-986 987-987 U 987-987 986-986 T 987-987 986-986 L 988-988 989-989 U 989-989 988-988 T 989-989 988-988 L 990-990 991-991 U 991-991 990-990 T 991-991 990-990 L 992-992 993-993 U 993-993 992-992 T 993-993 992-992 L 994-994 995-995 U 995-995 994-994 T 995-995 994-994 L 996-996 997-997 U 997-997 996-996 T 997-997 996-996 L 998-998 999-999 U 999-999 998-998 T 999-999 998-998 L 1000-1000 1001-1001 U 1001-1001 1000-1000 T 1001-1001 1000-1000 L 1002-1002 1003-1003 U 1003-1003 1002-1002 T 1003-1003 1002-1002 L 1004-1004 1005-1005 U 1005-1005 1004-1004 T 1005-1005 1004-1004 U 1007-1007 1006-1006 T 1007-1007 1006-1006 U 1008-1008 922-922 T 1008-1008 922-922 U 1009-1009 929-929 T 1009-1009 929-929 L 1006-1006 1007-1007 U 1010-1010 931-931 T 1010-1010 931-931 L 1012-1012 952-952 L 1024-1039 1104-1119 U 1013-1013 917-917 T 1013-1013 917-917 U 1072-1103 1040-1071 T 1072-1103 1040-1071 L 1040-1071 1072-1103 U 1104-1119 1024-1039 T 1104-1119 1024-1039 L 1120-1120 1121-1121 U 1121-1121 1120-1120 T 1121-1121 1120-1120 L 1122-1122 1123-1123 U 1123-1123 1122-1122 T 1123-1123 1122-1122 L 1124-1124 1125-1125 U 1125-1125 1124-1124 T 1125-1125 1124-1124 L 1126-1126 1127-1127 U 1127-1127 1126-1126 T 1127-1127 1126-1126 L 1128-1128 1129-1129 U 1129-1129 1128-1128 T 1129-1129 1128-1128 L 1130-1130 1131-1131 U 1131-1131 1130-1130 T 1131-1131 1130-1130 L 1132-1132 1133-1133 U 1133-1133 1132-1132 T 1133-1133 1132-1132 L 1134-1134 1135-1135 U 1135-1135 1134-1134 T 1135-1135 1134-1134 L 1136-1136 1137-1137 U 1137-1137 1136-1136 T 1137-1137 1136-1136 L 1138-1138 1139-1139 U 1139-1139 1138-1138 T 1139-1139 1138-1138 L 1140-1140 1141-1141 U 1141-1141 1140-1140 T 1141-1141 1140-1140 L 1142-1142 1143-1143 U 1143-1143 1142-1142 T 1143-1143 1142-1142 L 1144-1144 1145-1145 U 1145-1145 1144-1144 T 1145-1145 1144-1144 L 1146-1146 1147-1147 U 1147-1147 1146-1146 T 1147-1147 1146-1146 L 1148-1148 1149-1149 U 1149-1149 1148-1148 T 1149-1149 1148-1148 L 1150-1150 1151-1151 U 1151-1151 1150-1150 T 1151-1151 1150-1150 L 1152-1152 1153-1153 U 1153-1153 1152-1152 T 1153-1153 1152-1152 L 1162-1162 1163-1163 U 1163-1163 1162-1162 T 1163-1163 1162-1162 L 1164-1164 1165-1165 U 1165-1165 1164-1164 T 1165-1165 1164-1164 L 1166-1166 1167-1167 U 1167-1167 1166-1166 T 1167-1167 1166-1166 L 1168-1168 1169-1169 U 1169-1169 1168-1168 T 1169-1169 1168-1168 L 1170-1170 1171-1171 U 1171-1171 1170-1170 T 1171-1171 1170-1170 L 1172-1172 1173-1173 U 1173-1173 1172-1172 T 1173-1173 1172-1172 L 1174-1174 1175-1175 U 1175-1175 1174-1174 T 1175-1175 1174-1174 L 1176-1176 1177-1177 U 1177-1177 1176-1176 T 1177-1177 1176-1176 L 1178-1178 1179-1179 U 1179-1179 1178-1178 T 1179-1179 1178-1178 L 1180-1180 1181-1181 U 1181-1181 1180-1180 T 1181-1181 1180-1180 L 1182-1182 1183-1183 U 1183-1183 1182-1182 T 1183-1183 1182-1182 L 1184-1184 1185-1185 U 1185-1185 1184-1184 T 1185-1185 1184-1184 L 1186-1186 1187-1187 U 1187-1187 1186-1186 T 1187-1187 1186-1186 L 1188-1188 1189-1189 U 1189-1189 1188-1188 T 1189-1189 1188-1188 L 1190-1190 1191-1191 U 1191-1191 1190-1190 T 1191-1191 1190-1190 L 1192-1192 1193-1193 U 1193-1193 1192-1192 T 1193-1193 1192-1192 L 1194-1194 1195-1195 U 1195-1195 1194-1194 T 1195-1195 1194-1194 L 1196-1196 1197-1197 U 1197-1197 1196-1196 T 1197-1197 1196-1196 L 1198-1198 1199-1199 U 1199-1199 1198-1198 T 1199-1199 1198-1198 L 1200-1200 1201-1201 U 1201-1201 1200-1200 T 1201-1201 1200-1200 L 1202-1202 1203-1203 U 1203-1203 1202-1202 T 1203-1203 1202-1202 L 1204-1204 1205-1205 U 1205-1205 1204-1204 T 1205-1205 1204-1204 L 1206-1206 1207-1207 U 1207-1207 1206-1206 T 1207-1207 1206-1206 L 1208-1208 1209-1209 U 1209-1209 1208-1208 T 1209-1209 1208-1208 L 1210-1210 1211-1211 U 1211-1211 1210-1210 T 1211-1211 1210-1210 L 1212-1212 1213-1213 U 1213-1213 1212-1212 T 1213-1213 1212-1212 L 1214-1214 1215-1215 U 1215-1215 1214-1214 T 1215-1215 1214-1214 L 1217-1217 1218-1218 U 1218-1218 1217-1217 T 1218-1218 1217-1217 L 1219-1219 1220-1220 U 1220-1220 1219-1219 T 1220-1220 1219-1219 L 1221-1221 1222-1222 U 1222-1222 1221-1221 T 1222-1222 1221-1221 L 1223-1223 1224-1224 U 1224-1224 1223-1223 T 1224-1224 1223-1223 L 1225-1225 1226-1226 U 1226-1226 1225-1225 T 1226-1226 1225-1225 L 1227-1227 1228-1228 U 1228-1228 1227-1227 T 1228-1228 1227-1227 L 1229-1229 1230-1230 U 1230-1230 1229-1229 T 1230-1230 1229-1229 L 1232-1232 1233-1233 U 1233-1233 1232-1232 T 1233-1233 1232-1232 L 1234-1234 1235-1235 U 1235-1235 1234-1234 T 1235-1235 1234-1234 L 1236-1236 1237-1237 U 1237-1237 1236-1236 T 1237-1237 1236-1236 L 1238-1238 1239-1239 U 1239-1239 1238-1238 T 1239-1239 1238-1238 L 1240-1240 1241-1241 U 1241-1241 1240-1240 T 1241-1241 1240-1240 L 1242-1242 1243-1243 U 1243-1243 1242-1242 T 1243-1243 1242-1242 L 1244-1244 1245-1245 U 1245-1245 1244-1244 T 1245-1245 1244-1244 L 1246-1246 1247-1247 U 1247-1247 1246-1246 T 1247-1247 1246-1246 L 1248-1248 1249-1249 U 1249-1249 1248-1248 T 1249-1249 1248-1248 L 1250-1250 1251-1251 U 1251-1251 1250-1250 T 1251-1251 1250-1250 L 1252-1252 1253-1253 U 1253-1253 1252-1252 T 1253-1253 1252-1252 L 1254-1254 1255-1255 U 1255-1255 1254-1254 T 1255-1255 1254-1254 L 1256-1256 1257-1257 U 1257-1257 1256-1256 T 1257-1257 1256-1256 L 1258-1258 1259-1259 U 1259-1259 1258-1258 T 1259-1259 1258-1258 L 1260-1260 1261-1261 U 1261-1261 1260-1260 T 1261-1261 1260-1260 L 1262-1262 1263-1263 U 1263-1263 1262-1262 T 1263-1263 1262-1262 L 1264-1264 1265-1265 U 1265-1265 1264-1264 T 1265-1265 1264-1264 L 1266-1266 1267-1267 U 1267-1267 1266-1266 T 1267-1267 1266-1266 L 1268-1268 1269-1269 U 1269-1269 1268-1268 T 1269-1269 1268-1268 L 1272-1272 1273-1273 U 1273-1273 1272-1272 T 1273-1273 1272-1272 L 1280-1280 1281-1281 U 1281-1281 1280-1280 T 1281-1281 1280-1280 L 1282-1282 1283-1283 U 1283-1283 1282-1282 T 1283-1283 1282-1282 L 1284-1284 1285-1285 U 1285-1285 1284-1284 T 1285-1285 1284-1284 L 1286-1286 1287-1287 U 1287-1287 1286-1286 T 1287-1287 1286-1286 L 1288-1288 1289-1289 U 1289-1289 1288-1288 T 1289-1289 1288-1288 L 1290-1290 1291-1291 U 1291-1291 1290-1290 T 1291-1291 1290-1290 L 1292-1292 1293-1293 U 1293-1293 1292-1292 T 1293-1293 1292-1292 L 1294-1294 1295-1295 U 1295-1295 1294-1294 T 1295-1295 1294-1294 L 1329-1366 1377-1414 U 1377-1414 1329-1366 T 1377-1414 1329-1366 L 7680-7680 7681-7681 U 7681-7681 7680-7680 T 7681-7681 7680-7680 L 7682-7682 7683-7683 U 7683-7683 7682-7682 T 7683-7683 7682-7682 L 7684-7684 7685-7685 U 7685-7685 7684-7684 T 7685-7685 7684-7684 L 7686-7686 7687-7687 U 7687-7687 7686-7686 T 7687-7687 7686-7686 L 7688-7688 7689-7689 U 7689-7689 7688-7688 T 7689-7689 7688-7688 L 7690-7690 7691-7691 U 7691-7691 7690-7690 T 7691-7691 7690-7690 L 7692-7692 7693-7693 U 7693-7693 7692-7692 T 7693-7693 7692-7692 L 7694-7694 7695-7695 U 7695-7695 7694-7694 T 7695-7695 7694-7694 L 7696-7696 7697-7697 U 7697-7697 7696-7696 T 7697-7697 7696-7696 L 7698-7698 7699-7699 U 7699-7699 7698-7698 T 7699-7699 7698-7698 L 7700-7700 7701-7701 U 7701-7701 7700-7700 T 7701-7701 7700-7700 L 7702-7702 7703-7703 U 7703-7703 7702-7702 T 7703-7703 7702-7702 L 7704-7704 7705-7705 U 7705-7705 7704-7704 T 7705-7705 7704-7704 L 7706-7706 7707-7707 U 7707-7707 7706-7706 T 7707-7707 7706-7706 L 7708-7708 7709-7709 U 7709-7709 7708-7708 T 7709-7709 7708-7708 L 7710-7710 7711-7711 U 7711-7711 7710-7710 T 7711-7711 7710-7710 L 7712-7712 7713-7713 U 7713-7713 7712-7712 T 7713-7713 7712-7712 L 7714-7714 7715-7715 U 7715-7715 7714-7714 T 7715-7715 7714-7714 L 7716-7716 7717-7717 U 7717-7717 7716-7716 T 7717-7717 7716-7716 L 7718-7718 7719-7719 U 7719-7719 7718-7718 T 7719-7719 7718-7718 L 7720-7720 7721-7721 U 7721-7721 7720-7720 T 7721-7721 7720-7720 L 7722-7722 7723-7723 U 7723-7723 7722-7722 T 7723-7723 7722-7722 L 7724-7724 7725-7725 U 7725-7725 7724-7724 T 7725-7725 7724-7724 L 7726-7726 7727-7727 U 7727-7727 7726-7726 T 7727-7727 7726-7726 L 7728-7728 7729-7729 U 7729-7729 7728-7728 T 7729-7729 7728-7728 L 7730-7730 7731-7731 U 7731-7731 7730-7730 T 7731-7731 7730-7730 L 7732-7732 7733-7733 U 7733-7733 7732-7732 T 7733-7733 7732-7732 L 7734-7734 7735-7735 U 7735-7735 7734-7734 T 7735-7735 7734-7734 L 7736-7736 7737-7737 U 7737-7737 7736-7736 T 7737-7737 7736-7736 L 7738-7738 7739-7739 U 7739-7739 7738-7738 T 7739-7739 7738-7738 L 7740-7740 7741-7741 U 7741-7741 7740-7740 T 7741-7741 7740-7740 L 7742-7742 7743-7743 U 7743-7743 7742-7742 T 7743-7743 7742-7742 L 7744-7744 7745-7745 U 7745-7745 7744-7744 T 7745-7745 7744-7744 L 7746-7746 7747-7747 U 7747-7747 7746-7746 T 7747-7747 7746-7746 L 7748-7748 7749-7749 U 7749-7749 7748-7748 T 7749-7749 7748-7748 L 7750-7750 7751-7751 U 7751-7751 7750-7750 T 7751-7751 7750-7750 L 7752-7752 7753-7753 U 7753-7753 7752-7752 T 7753-7753 7752-7752 L 7754-7754 7755-7755 U 7755-7755 7754-7754 T 7755-7755 7754-7754 L 7756-7756 7757-7757 U 7757-7757 7756-7756 T 7757-7757 7756-7756 L 7758-7758 7759-7759 U 7759-7759 7758-7758 T 7759-7759 7758-7758 L 7760-7760 7761-7761 U 7761-7761 7760-7760 T 7761-7761 7760-7760 L 7762-7762 7763-7763 U 7763-7763 7762-7762 T 7763-7763 7762-7762 L 7764-7764 7765-7765 U 7765-7765 7764-7764 T 7765-7765 7764-7764 L 7766-7766 7767-7767 U 7767-7767 7766-7766 T 7767-7767 7766-7766 L 7768-7768 7769-7769 U 7769-7769 7768-7768 T 7769-7769 7768-7768 L 7770-7770 7771-7771 U 7771-7771 7770-7770 T 7771-7771 7770-7770 L 7772-7772 7773-7773 U 7773-7773 7772-7772 T 7773-7773 7772-7772 L 7774-7774 7775-7775 U 7775-7775 7774-7774 T 7775-7775 7774-7774 L 7776-7776 7777-7777 U 7777-7777 7776-7776 T 7777-7777 7776-7776 L 7778-7778 7779-7779 U 7779-7779 7778-7778 T 7779-7779 7778-7778 L 7780-7780 7781-7781 U 7781-7781 7780-7780 T 7781-7781 7780-7780 L 7782-7782 7783-7783 U 7783-7783 7782-7782 T 7783-7783 7782-7782 L 7784-7784 7785-7785 U 7785-7785 7784-7784 T 7785-7785 7784-7784 L 7786-7786 7787-7787 U 7787-7787 7786-7786 T 7787-7787 7786-7786 L 7788-7788 7789-7789 U 7789-7789 7788-7788 T 7789-7789 7788-7788 L 7790-7790 7791-7791 U 7791-7791 7790-7790 T 7791-7791 7790-7790 L 7792-7792 7793-7793 U 7793-7793 7792-7792 T 7793-7793 7792-7792 L 7794-7794 7795-7795 U 7795-7795 7794-7794 T 7795-7795 7794-7794 L 7796-7796 7797-7797 U 7797-7797 7796-7796 T 7797-7797 7796-7796 L 7798-7798 7799-7799 U 7799-7799 7798-7798 T 7799-7799 7798-7798 L 7800-7800 7801-7801 U 7801-7801 7800-7800 T 7801-7801 7800-7800 L 7802-7802 7803-7803 U 7803-7803 7802-7802 T 7803-7803 7802-7802 L 7804-7804 7805-7805 U 7805-7805 7804-7804 T 7805-7805 7804-7804 L 7806-7806 7807-7807 U 7807-7807 7806-7806 T 7807-7807 7806-7806 L 7808-7808 7809-7809 U 7809-7809 7808-7808 T 7809-7809 7808-7808 L 7810-7810 7811-7811 U 7811-7811 7810-7810 T 7811-7811 7810-7810 L 7812-7812 7813-7813 U 7813-7813 7812-7812 T 7813-7813 7812-7812 L 7814-7814 7815-7815 U 7815-7815 7814-7814 T 7815-7815 7814-7814 L 7816-7816 7817-7817 U 7817-7817 7816-7816 T 7817-7817 7816-7816 L 7818-7818 7819-7819 U 7819-7819 7818-7818 T 7819-7819 7818-7818 L 7820-7820 7821-7821 U 7821-7821 7820-7820 T 7821-7821 7820-7820 L 7822-7822 7823-7823 U 7823-7823 7822-7822 T 7823-7823 7822-7822 L 7824-7824 7825-7825 U 7825-7825 7824-7824 T 7825-7825 7824-7824 L 7826-7826 7827-7827 U 7827-7827 7826-7826 T 7827-7827 7826-7826 U 7829-7829 7828-7828 T 7829-7829 7828-7828 L 7828-7828 7829-7829 U 7835-7835 7776-7776 T 7835-7835 7776-7776 L 7840-7840 7841-7841 U 7841-7841 7840-7840 T 7841-7841 7840-7840 L 7842-7842 7843-7843 U 7843-7843 7842-7842 T 7843-7843 7842-7842 L 7844-7844 7845-7845 U 7845-7845 7844-7844 T 7845-7845 7844-7844 L 7846-7846 7847-7847 U 7847-7847 7846-7846 T 7847-7847 7846-7846 L 7848-7848 7849-7849 U 7849-7849 7848-7848 T 7849-7849 7848-7848 L 7850-7850 7851-7851 U 7851-7851 7850-7850 T 7851-7851 7850-7850 L 7852-7852 7853-7853 U 7853-7853 7852-7852 T 7853-7853 7852-7852 L 7854-7854 7855-7855 U 7855-7855 7854-7854 T 7855-7855 7854-7854 L 7856-7856 7857-7857 U 7857-7857 7856-7856 T 7857-7857 7856-7856 L 7858-7858 7859-7859 U 7859-7859 7858-7858 T 7859-7859 7858-7858 L 7860-7860 7861-7861 U 7861-7861 7860-7860 T 7861-7861 7860-7860 L 7862-7862 7863-7863 U 7863-7863 7862-7862 T 7863-7863 7862-7862 L 7864-7864 7865-7865 U 7865-7865 7864-7864 T 7865-7865 7864-7864 L 7866-7866 7867-7867 U 7867-7867 7866-7866 T 7867-7867 7866-7866 L 7868-7868 7869-7869 U 7869-7869 7868-7868 T 7869-7869 7868-7868 L 7870-7870 7871-7871 U 7871-7871 7870-7870 T 7871-7871 7870-7870 L 7872-7872 7873-7873 U 7873-7873 7872-7872 T 7873-7873 7872-7872 L 7874-7874 7875-7875 U 7875-7875 7874-7874 T 7875-7875 7874-7874 L 7876-7876 7877-7877 U 7877-7877 7876-7876 T 7877-7877 7876-7876 L 7878-7878 7879-7879 U 7879-7879 7878-7878 T 7879-7879 7878-7878 L 7880-7880 7881-7881 U 7881-7881 7880-7880 T 7881-7881 7880-7880 L 7882-7882 7883-7883 U 7883-7883 7882-7882 T 7883-7883 7882-7882 L 7884-7884 7885-7885 U 7885-7885 7884-7884 T 7885-7885 7884-7884 L 7886-7886 7887-7887 U 7887-7887 7886-7886 T 7887-7887 7886-7886 L 7888-7888 7889-7889 U 7889-7889 7888-7888 T 7889-7889 7888-7888 L 7890-7890 7891-7891 U 7891-7891 7890-7890 T 7891-7891 7890-7890 L 7892-7892 7893-7893 U 7893-7893 7892-7892 T 7893-7893 7892-7892 L 7894-7894 7895-7895 U 7895-7895 7894-7894 T 7895-7895 7894-7894 L 7896-7896 7897-7897 U 7897-7897 7896-7896 T 7897-7897 7896-7896 L 7898-7898 7899-7899 U 7899-7899 7898-7898 T 7899-7899 7898-7898 L 7900-7900 7901-7901 U 7901-7901 7900-7900 T 7901-7901 7900-7900 L 7902-7902 7903-7903 U 7903-7903 7902-7902 T 7903-7903 7902-7902 L 7904-7904 7905-7905 U 7905-7905 7904-7904 T 7905-7905 7904-7904 L 7906-7906 7907-7907 U 7907-7907 7906-7906 T 7907-7907 7906-7906 L 7908-7908 7909-7909 U 7909-7909 7908-7908 T 7909-7909 7908-7908 L 7910-7910 7911-7911 U 7911-7911 7910-7910 T 7911-7911 7910-7910 L 7912-7912 7913-7913 U 7913-7913 7912-7912 T 7913-7913 7912-7912 L 7914-7914 7915-7915 U 7915-7915 7914-7914 T 7915-7915 7914-7914 L 7916-7916 7917-7917 U 7917-7917 7916-7916 T 7917-7917 7916-7916 L 7918-7918 7919-7919 U 7919-7919 7918-7918 T 7919-7919 7918-7918 L 7920-7920 7921-7921 U 7921-7921 7920-7920 T 7921-7921 7920-7920 L 7922-7922 7923-7923 U 7923-7923 7922-7922 T 7923-7923 7922-7922 L 7924-7924 7925-7925 U 7925-7925 7924-7924 T 7925-7925 7924-7924 L 7926-7926 7927-7927 U 7927-7927 7926-7926 T 7927-7927 7926-7926 U 7929-7929 7928-7928 T 7929-7929 7928-7928 L 7928-7928 7929-7929 U 7936-7943 7944-7951 T 7936-7943 7944-7951 L 7944-7951 7936-7943 U 7952-7957 7960-7965 T 7952-7957 7960-7965 L 7960-7965 7952-7957 U 7968-7975 7976-7983 T 7968-7975 7976-7983 L 7976-7983 7968-7975 U 7984-7991 7992-7999 T 7984-7991 7992-7999 L 7992-7999 7984-7991 U 8000-8005 8008-8013 T 8000-8005 8008-8013 U 8017-8017 8025-8025 T 8017-8017 8025-8025 U 8019-8019 8027-8027 T 8019-8019 8027-8027 U 8021-8021 8029-8029 T 8021-8021 8029-8029 L 8008-8013 8000-8005 L 8025-8025 8017-8017 L 8027-8027 8019-8019 L 8029-8029 8021-8021 U 8023-8023 8031-8031 T 8023-8023 8031-8031 L 8031-8031 8023-8023 U 8032-8039 8040-8047 T 8032-8039 8040-8047 U 8048-8049 8122-8123 T 8048-8049 8122-8123 U 8050-8053 8136-8139 T 8050-8053 8136-8139 U 8054-8055 8154-8155 T 8054-8055 8154-8155 U 8056-8057 8184-8185 T 8056-8057 8184-8185 U 8058-8059 8170-8171 T 8058-8059 8170-8171 U 8060-8061 8186-8187 T 8060-8061 8186-8187 L 8040-8047 8032-8039 U 8064-8071 8072-8079 T 8064-8071 8072-8079 L 8072-8079 8064-8071 U 8080-8087 8088-8095 T 8080-8087 8088-8095 L 8088-8095 8080-8087 U 8096-8103 8104-8111 T 8096-8103 8104-8111 U 8112-8113 8120-8121 T 8112-8113 8120-8121 L 8104-8111 8096-8103 L 8120-8121 8112-8113 L 8122-8123 8048-8049 U 8115-8115 8124-8124 T 8115-8115 8124-8124 U 8126-8126 921-921 T 8126-8126 921-921 L 8124-8124 8115-8115 L 8136-8139 8050-8053 U 8131-8131 8140-8140 T 8131-8131 8140-8140 L 8140-8140 8131-8131 L 8152-8153 8144-8145 U 8144-8145 8152-8153 T 8144-8145 8152-8153 U 8160-8161 8168-8169 T 8160-8161 8168-8169 L 8154-8155 8054-8055 L 8168-8169 8160-8161 L 8170-8171 8058-8059 U 8165-8165 8172-8172 T 8165-8165 8172-8172 L 8172-8172 8165-8165 L 8184-8185 8056-8057 L 8186-8187 8060-8061 L 8188-8188 8179-8179 L 8486-8486 969-969 L 8490-8490 107-107 L 8491-8491 229-229 U 8179-8179 8188-8188 T 8179-8179 8188-8188 L 8544-8559 8560-8575 U 8560-8575 8544-8559 T 8560-8575 8544-8559 L 9398-9423 9424-9449 U 9424-9449 9398-9423 T 9424-9449 9398-9423 L 65313-65338 65345-65370 U 65345-65370 65313-65338 T 65345-65370 65313-65338 L 66560-66597 66600-66637 U 66600-66637 66560-66597 T 66600-66637 66560-66597 ocamlnet-4.1.2/src/netstring/netfs.mli0000644000175000017500000004537312731530350016405 0ustar gerdgerd(* $Id$ *) (** Class type [stream_fs] for filesystems with stream access to files *) (** The class type {!Netfs.stream_fs} is an abstraction for both kernel-level and user-level filesystems. It is used as parameter for algorithms (like globbing) that operate on filesystems but do not want to assume any particular filesystem. Only stream access is provided (no seek). {b File paths:} The filesystem supports hierarchical file names. File paths use Unix conventions, i.e. - [/] is the root - Path components are separated by slashes. Several consecutive slashes are allowed but mean the same as a single slash. - [.] is the same directory - [..] is the parent directory All paths need to be absolute (i.e. start with [/]). There can be additional constraints on paths: - Character encoding restriction: A certain ASCII-compatible character encoding is assumed (including UTF-8) - Character exclusion: Certain characters may be excluded Implementations may impose more constraints that cannot be expressed here (case insensitivity, path length, exclusion of special names etc.). {b Virtuality:} There is no assumption that [/] is the real root of the local filesystem. It can actually be anywhere - a local subdirectory, or a remote directory, or a fictive root. There needs not to be any protection against "running beyond root", e.g. with the path [/..]. This class type also supports remote filesystems, and thus there is no concept of file handle (because this would exclude a number of implementations). {b Errors: } Errors should generally be indicated by raising [Unix_error]. For many error codes the interpretation is already given by POSIX. Here are some more special cases: - [EINVAL]: should also be used for invalid paths, or when a flag cannot be supported (and it is non-ignorable) - [ENOSYS]: should also be used if an operation is generally unavailable In case of hard errors (like socket errors when communicating with the remote server) there is no need to stick to [Unix_error], though. {b Subtyping:} The class type {!Netfs.stream_fs} is subtypable, and subtypes can add more features by: - adding more methods - adding more flags to existing methods {b Omitted:} Real filesystems usually provide a lot more features than what is represented here, such as: - Access control and file permissions - Metadata like timestamps - Random access to files This definition here is intentionally minimalistic. In the future this class type will be extended, and more more common filesystem features will be covered. See {!Netfs.empty_fs} for a way how to ensure that your definition of a [stream_fs] can still be built after [stream_fs] has been extended. *) (** {2 The class type [stream_fs]} *) type read_flag = [ `Skip of int64 | `Binary | `Streaming | `Dummy ] type read_file_flag = [ `Binary | `Dummy ] type write_flag = [ `Create | `Exclusive | `Truncate | `Binary | `Streaming | `Dummy ] type write_file_flag = [ `Create | `Exclusive | `Truncate | `Binary | `Link | `Dummy ] type write_common = [ `Create | `Exclusive | `Truncate | `Binary | `Dummy ] (** The intersection of [write_flag] and [write_file_flag] *) type size_flag = [ `Dummy ] type test_flag = [ `Link | `Dummy ] type remove_flag = [ `Recursive | `Dummy ] type rename_flag = [ `Dummy ] type symlink_flag = [ `Dummy ] type readdir_flag = [ `Dummy ] type readlink_flag = [ `Dummy ] type mkdir_flag = [ `Path | `Nonexcl | `Dummy ] type rmdir_flag = [ `Dummy ] type copy_flag = [ `Dummy ] (** Note [`Dummy]: this flag is always ignored. There are two reasons for having it: - Ocaml does not allow empty variants - it is sometimes convenient to have it (e.g. in: [if then `Create else `Dummy]) *) type test_type = [ `N | `E | `D | `F | `H | `R | `W | `X | `S ] (** Tests: - [`N]: the file name exists - [`E]: the file exists - [`D]: the file exists and is a directory - [`F]: the file exists and is regular - [`H]: the file exists and is a symlink (possibly to a non-existing target) - [`R]: the file exists and is readable - [`W]: the file exists and is writable - [`X]: the file exists and is executable - [`S]: the file exists and is non-empty *) class type local_file = object method filename : string (** The filename *) method close : unit -> unit (** Indicate that we are done with the file *) end class type stream_fs = object method path_encoding : Netconversion.encoding option (** The encoding must be ASCII-compatible ({!Netconversion.is_ascii_compatible}). If [None] the ASCII encoding is assumed for codes 0-127, and no meaning is defined for byte codes 128-255. *) method path_exclusions : (int * int) list (** Code points that must not occur in path components between slashes. This is given as ranges [(from,to)]. The code points are interpreted as Unicode code points if an encoding is available, and as byte codes otherwise. For example, for Unix the code points 0 and 47 (slash) are normally the only excluded code points. *) method nominal_dot_dot : bool (** Whether the effect of [..] can be obtained by stripping off the last path component, i.e. whether [Filename.dirname path <=> path ^ "/.."] *) method read : read_flag list -> string -> Netchannels.in_obj_channel (** [read flags filename]: Opens the file [filename] for reading, and returns the input stream. Flags: - [`Skip n]: Skips the first [n] bytes of the file. On many filesystems this is more efficient than reading [n] bytes and dropping them; however, there is no guarantee that this optimization exists. - [`Binary]: Opens the file in binary mode (if there is such a distinction) - [`Streaming] for network filesystems: If possible, open the file in streaming mode, and avoid to copy the whole file to the local disk before returning the {!Netchannels.in_obj_channel}. Streaming mode is faster, but has also downsides. Especially, the implementation of [read] can do less to recover from transient network problems (like retrying the whole download). Support for this flag is optional, and it is ignored if there is no extra streaming mode. *) method read_file : read_file_flag list -> string -> local_file (** [read_file flags filename]: Opens the file [filename] for reading, and returns the contents as a [local_file]. Use the method [filename] to get the file name of the local file. The file may be temporary, but this is not required. The method [close] of the returned object should be called when the file is no longer needed. In case of a temporary file, the file can then be deleted. Flags: - [`Binary]: Opens the file in binary mode (if there is such a distinction) *) method write : write_flag list -> string -> Netchannels.out_obj_channel (** [write flags filename]: Opens (and optionally creates) the [filename] for writing, and returns the output stream. Flags: - [`Create]: If the file does not exist, create it - [`Truncate]: If the file exists, truncate it to zero before writing - [`Exclusive]: The [`Create] is done exclusively - [`Binary]: Opens the file in binary mode (if there is such a distinction) - [`Streaming]: see [read] (above) for explanations Some filesystems refuse this operation if neither [`Create] nor [`Truncate] is specified because overwriting an existing file is not supported. There are also filesystems that cannot even modify files by truncating them first, but only allow to write to new files. It is unspecified whether the file appears in the directory directly after calling [write] or first when the stream is closed. *) method write_file : write_file_flag list -> string -> local_file -> unit (** [write_file flags filename localfile]: Opens the file [filename] for writing, and copies the contents of the [localfile] to it. It is ensured that the method [close] of [localfile] is called once the operation is finished (whether successful or not). Flags: - [`Create]: If the (remote) file does not exist, create it - [`Truncate]: If the file exists, truncate it to zero before writing - [`Exclusive]: The [`Create] is done exclusively - [`Binary]: Opens the file in binary mode (if there is such a distinction) - [`Link]: Allows that the destination file is created as a hard link of the original file. This is tried whatever other mode is specified. If not successful, a copy is done instead. *) method size : size_flag list -> string -> int64 (** Returns the size of a file. Note that there is intentionally no distinction between text and binary mode - implementations must always assume binary mode. *) method test : test_flag list -> string -> test_type -> bool (** Returns whether the test is true. For filesystems that know symbolic links, the test operation normally follows symlinks (except for the [`N] and [`H] tests). By specifying the [`Link] flag symlinks are not followed. *) method test_list : test_flag list -> string -> test_type list -> bool list (** Similar to [test] but this function performs all tests in the list at once, and returns a bool for each test. *) method remove : remove_flag list -> string -> unit (** Removes the file or symlink. Implementation are free to also support the removal of empty directories. Flags: - [`Recursive]: Remove the contents of the non-empty directory recursively. This is an optional feature. There needs not to be any protection against operations done by other processes that affect the directory tree being deleted. *) method rename : rename_flag list -> string -> string -> unit (** Renames the file. There is no guarantee that a rename is atomic *) method symlink : symlink_flag list -> string -> string -> unit (** [symlink flags oldpath newpath]: Creates a symlink. This is an exclusive create, i.e. the operation fails if [newpath] already exists. *) method readdir : readdir_flag list -> string -> string list (** Reads the contents of a directory. Whether "." and ".." are returned is platform-dependent. The entries can be returned in any order. *) method readlink : readlink_flag list -> string -> string (** Reads the target of a symlink *) method mkdir : mkdir_flag list -> string -> unit (** Creates a new directory. Flags: - [`Path]: Creates missing parent directories. This is an optional feature. (If not supported, ENOENT is reported.) - [`Nonexcl]: Non-exclusive create. *) method rmdir : rmdir_flag list -> string -> unit (** Removes an empty directory *) method copy : copy_flag list -> string -> string -> unit (** Copies a file to a new name. This does not descent into directories. Also, symlinks are resolved, and the linked file is copied. *) method cancel : unit -> unit (** Cancels any ongoing [write]. The user must also call the [close_out] method after cancelling. The effect is that after the close no more network activity will occur. *) end class empty_fs : string -> stream_fs (** This is a class where all methods fail with [ENOSYS]. The string argument is the detail in the [Unix_error], normally the module name of the user of this class. [empty_fs] is intended as base class for implementations of [stream_fs] outside Ocamlnet. When [stream_fs] is extended by new methods, these methods are at least defined, and no build error occurs. So the definition should look like {[ class my_fs ... = object inherit Netfs.empty_fs "my_fs" method read flags name = ... (* Add here all methods you can define, and omit the rest *) end ]} *) val local_fs : ?encoding:Netconversion.encoding -> ?root:string -> ?enable_relative_paths:bool -> unit -> stream_fs (** [local_fs()]: Returns a filesystem object for the local filesystem. - [encoding]: Specifies the character encoding of paths. The default is system-dependent. - [root]: the root of the returned object is the directory [root] of the local filesystem. If omitted, the root is the root of the local filesystem (i.e. / for Unix, and see comments for Windows below). Use [root="."] to make the current working directory the root. Note that "." like other relative paths are interpreted at the time when the access method is executed. - [enable_relative_paths]: Normally, only absolute paths can be passed to the access methods like [read]. By setting this option to [true] one can also enable relative paths. These are taken relative to the working directory, and not relative to [root]. Relative names are off by default because there is usually no counterpart in network filesystems. *) (** {2 OS Notes} *) (** {b Unix} in general: There is no notion of character encoding of paths. Paths are just bytes. Because of this, the default encoding is [None]. If a different encoding is passed to [local_fs], these bytes are just interpreted in this encoding. There is no conversion. For desktop programs, though, usually the character encoding of the locale is taken for filenames. You can get this by passing {[ let encoding = Netconversion.user_encoding() ]} as [encoding] argument. *) (** {b Windows}: If the [root] argument is {b not} passed to [local_fs] it is possible to access the whole filesystem: - Paths starting with drive letters like [c:/] are also considered as absolute - Additionally, paths starting with slashes like [/c:/] mean the same - UNC paths starting with two slashes like [//hostname] are supported However, when a [root] directory is passed, these additional notations are not possible anymore - paths must start with [/], and there is neither support for drive letters nor for UNC paths. The [encoding] arg defaults to current ANSI codepage, and it is not supported to request a different encoding. (The difficulty is that the Win32 bindings of the relevant OS functions always assume the ANSI encoding.) There is no support for backslashes as path separators (such paths will be rejected), for better compatibility with other platforms. *) (** {2:links Other impementations of [stream_fs]} *) (** List: - {!Nethttp_fs} allows one to access HTTP-based filesystems - {!Netftp_fs} allows on to access filesystems via FTP - {!Shell_fs} allows one to access filesystems by executing shell commands. This works locally and via ssh. There are even some implementations outside Ocamlnet: - {{:http://projects.camlcity.org/projects/webdav.html} Webdav} provides an extension of {!Nethttp_fs} for the full WebDAV set of filesystem operations *) (** {2 Algorithms} *) val copy : ?replace:bool -> ?streaming:bool -> #stream_fs -> string -> #stream_fs -> string -> unit (** [copy orig_fs orig_name dest_fs dest_name]: Copies the file [orig_name] from [orig_fs] to the file [dest_name] in [dest_fs]. By default, the destination file is truncated and overwritten if it already exists. If [orig_fs] and [dest_fs] are the same object, the [copy] method is called to perform the operation. Otherwise, the data is read chunk by chunk from the file in [orig_fs] and then written to the destination file in [dest_fs]. Symlinks are resolved, and the linked file is copied, not the link as such. The copy does not preserve ownerships, file permissions, or timestamps. (The [stream_fs] object does not represent these.) There is no protection against copying an object to itself. - [replace]: If set, the destination file is removed and created again if it already exists - [streaming]: use streaming mode for reading and writing files *) val copy_into : ?replace:bool -> ?subst:(int->string) -> ?streaming:bool -> #stream_fs -> string -> #stream_fs -> string -> unit (** [copy_into orig_fs orig_name dest_fs dest_name]: Like [copy], but this version also supports recursive copies. The [dest_name] must be an existing directory, and the file or tree at [orig_name] is copied into it. Symlinks are copied as symlinks. If [replace] and the destination file/directory already exists, it is deleted before doing the copy. - [subst]: See {!Netfs.convert_path} - [streaming]: use streaming mode for reading and writing files *) type file_kind = [ `Regular | `Directory | `Symlink | `Other | `None ] val iter : pre:(string -> file_kind -> file_kind -> unit) -> ?post:(string -> unit) -> #stream_fs -> string -> unit (** [iter pre fs start]: Iterates over the file hierarchy at [start]. The function [pre] is called for every filename. The filenames passed to [pre] are relative to [start]. The [start] must be a directory. For directories, the [pre] function is called for the directory before it is called for the members of the directories. The function [post] can additionally be passed. It is only called for directories, but after the members. [pre] is called as [pre rk lk] where [rk] is the file kind after following symlinks and [lk] the file kind without following symlinks (the link itself). Example: [iter pre fs "/foo"] would call - [pre "dir" `Directory `Directory] (meaning the directory "/foo/dir") - [pre "dir/file1" `File `File] - [pre "dir/file2" `File `Symlink] - [post "dir"] Note: symlinks to non-existing files are reported as [pre name `None `Symlink]. *) val convert_path : ?subst:(int -> string) -> #stream_fs -> #stream_fs -> string -> string (** [convert_path oldfs newfs oldpath]: The encoding of [oldpath] (which is assumed to reside in [oldfs]) is converted to the encoding of [newfs] and returned. It is possible that the conversion is not possible, and the function [subst] is then called with the problematic code point as argument (in the encoding of [oldfs]). The default [subst] function just raises {!Netconversion.Cannot_represent}. If one of the filesystem objects does not specify an encoding, the file name is not converted, but simply returned as-is. This may result in errors when [newfs] has an encoding while [oldfs] does not have one because the file name might use byte representations that are illegal in [newfs]. *) ocamlnet-4.1.2/src/netstring/netmech_gs2_sasl.mli0000644000175000017500000001270312731530350020475 0ustar gerdgerd(* $Id$ *) (** The GS2 bridge for using GSSAPI mechanisms as SASL mechanisms *) module type PROFILE = sig val mechanism_name : string (** The GS2 version of the mechanism name (w/o "-PLUS" suffix) *) val announce_channel_binding : bool (** Whether to announce the availability of channel binding by adding "-PLUS" to the mechanism name, and by offering channel bindings in the initial token. *) val mechanism_oid : Netsys_gssapi.oid (** The OID of the mechanism to use *) val client_additional_params : string list (** Additional parameters understood by [create_client_session] *) val server_additional_params : string list (** Additional parameters understood by [create_server_session] *) val client_map_user_name : params:(string * string) list -> string -> string * Netsys_gssapi.oid (** For clients: maps user names to a pair [(name_string,name_type)] that can be used in the GSSAPI for acquiring a name. If the [name_type] is the empty array, no target name is passed to the GSSAPI. The [params] are from the [create_client_session] call. *) val server_map_user_name : params:(string * string) list -> (string * Netsys_gssapi.oid) -> string (** For servers: maps a pair [(name_string,name_type)] coming from the GSSAPI to a user name. The [params] are from the [create_server_session] call. The function may raise [Not_found] in which case the authentication will fail. *) val client_get_target_name : params:(string * string) list -> (string * Netsys_gssapi.oid) (** For clients: get the GSSAPI name of the target to contact as [(name_string,name_type)] pair. If the [name_type] is the empty array, no target name is passed to the GSSAPI. The [params] are from the [create_client_session] call. *) val server_bind_target_name : params:(string * string) list -> (string * Netsys_gssapi.oid) option (** For servers: optionally bind the GSSAPI name of the server. The [params] are from the [create_server_session] call. *) val server_check_target_name : params:(string * string) list -> (string * Netsys_gssapi.oid) -> bool (** For servers: check whether the GSSAPI name the client sent is the right one. This is a more flexible alternative to [server_bind_target_name]: instead of binding to a single name, the client may send any target name, and we check now whether this name is acceptable. [params] are from the [create_server_session] call. *) val client_flags : params:(string * string) list -> ( Netsys_gssapi.req_flag * bool ) list (** Flags for [init_sec_context]. The bool says whether the flag is required (otherwise the feature is only offered). [`Mutual_flag] is always required. *) val server_flags : params:(string * string) list -> Netsys_gssapi.req_flag list (** Required flags for [accept_sec_context]. [`Mutual_flag] is always required. *) val client_credential : exn option (** If set, the client will use a certain credential (and not acquire one). This is intended for passing in delegated credentials (well, not really elegant). This needs to be set to the [Credential] exception of the GSSAPI provider. *) end module GS2(P:PROFILE)(GSS:Netsys_gssapi.GSSAPI) : Netsys_sasl_types.SASL_MECHANISM (** This is an adapter turning any GSSAPI mechanism into a SASL mechanism. This is the "GS2" technique as specified in RFC 5801. (Note that in particular for Kerberos there is the other specification RFC 4752 which is implemented in {!Netmech_krb5_sasl}.) Create the final module like {[ module P = struct let mechanism_name = "FOO" let announce_channel_binding = false let mechanism_oid = [| 1; ... |] let mechanism_acceptable_oid_set = [ [| 1; ... |]; ... ] ... end module S = Netmech_gs2_sasl.GS2(P)(Netgss.System) ]} {b Remarks for clients:} The profile specifies how user name strings are mapped to GSSAPI names. [authz] names are passed to the server as-is. {b Remarks for servers:} The profile specifies how GSSAPI names are mapped to user name strings. The [lookup] callback is then invoked with this user name, and the unaltered [authz] name. If [lookup] returns [Some c] for any [c] the user is accepted. If it returns [None] the user is declined. {b Parameters:} - The parameter [mutual] is understood but ignored. Mutual authentication is always requested from the GSSAPI mechanism. - The parameter [secure] is understood but ignored (GSSAPI is considered as secure method) {b Statefulness:} The GSSAPI is stateful. Our SASL interface is stateless. We cannot hide the statefulness of the GSSAPI, and because of this old versions of sessions are invalidated. E.g. this does not work {[ let s1 = S.server_process_response s0 "some message" let s2 = S.server_process_response s0 "another message" ]} and the second attempt to continue with the old session [s0] will fail. *) ocamlnet-4.1.2/src/netstring/netencoding.ml0000644000175000017500000013703612731530350017410 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) let hexdigit_uc = [| '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; 'A'; 'B'; 'C'; 'D'; 'E'; 'F'; |] let hexdigit_lc = [| '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; 'a'; 'b'; 'c'; 'd'; 'e'; 'f'; |] let to_hex ?(lc=false) s = let hexdigit = if lc then hexdigit_lc else hexdigit_uc in let l = String.length s in let u = Bytes.create (2*l) in for k = 0 to l-1 do let c = String.unsafe_get s k in let j = k lsl 1 in Bytes.unsafe_set u j hexdigit.(Char.code c lsr 4); Bytes.unsafe_set u (j+1) hexdigit.(Char.code c land 15); done; Bytes.unsafe_to_string u module Base64 = struct let alphabet = [| 'A'; 'B'; 'C'; 'D'; 'E'; 'F'; 'G'; 'H'; 'I'; 'J'; 'K'; 'L'; 'M'; 'N'; 'O'; 'P'; 'Q'; 'R'; 'S'; 'T'; 'U'; 'V'; 'W'; 'X'; 'Y'; 'Z'; 'a'; 'b'; 'c'; 'd'; 'e'; 'f'; 'g'; 'h'; 'i'; 'j'; 'k'; 'l'; 'm'; 'n'; 'o'; 'p'; 'q'; 'r'; 's'; 't'; 'u'; 'v'; 'w'; 'x'; 'y'; 'z'; '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; '+'; '/' |];; let mod_alphabet plus slash = if plus <> '+' || slash <> '/' then ( let a = Array.copy alphabet in a.(62) <- plus; a.(63) <- slash; a ) else alphabet let encode_with_options ops b64 equal s pos len linelen first_linelen crlf = (* encode using "base64". * 'b64': The encoding table, created by b64_pattern. * 'equal': The character that should be used instead of '=' in the original * encoding scheme. Pass '=' to get the original encoding scheme. * s, pos, len, linelen: See the interface description of encode_substring. * first_linelen: The length of the first line. * * Returns: (s,last_linelen) where [s] is the encoded string, and * [last_linelen] is the length of the last line *) let open Netstring_tstring in assert (Array.length b64 = 64); if len < 0 || pos < 0 || pos > ops.length s || linelen < 0 then invalid_arg "Netencoding.Base64.encode"; if pos + len > ops.length s then invalid_arg "Netencoding.Base64.encode"; let linelen = (linelen asr 2) lsl 2 in let first_linelen = (first_linelen asr 2) lsl 2 in let l_t = if len = 0 then 0 else ((len - 1) / 3 + 1) * 4 in (* l_t: length of the result without additional line endings *) let factor = if crlf then 2 else 1 in let l_t' = if linelen < 4 then l_t else if l_t <= first_linelen then ( if l_t = 0 then 0 else l_t + factor ) else let n_lines = ((l_t - first_linelen - 1) / linelen) + 2 in l_t + n_lines * factor in (* l_t': length of the result with CRLF or LF characters *) let t = Bytes.make l_t' equal in let j = ref 0 in let q = ref (linelen - first_linelen) in for k = 0 to len / 3 - 1 do let p = pos + 3*k in (* p >= pos >= 0: this is evident * p+2 < pos+len <= String.length s: * Because k <= len/3-1 * 3*k <= 3*(len/3-1) = len - 3 * pos+3*k+2 <= pos + len - 3 + 2 = pos + len - 1 < pos + len * So it is proved that the following unsafe string accesses always * work. *) let bits = ops.unsafe_get3 s p in (* Obviously, 'bits' is a 24 bit entity (i.e. bits < 2**24) *) assert(!j + 3 < l_t'); Bytes.unsafe_set t !j (Array.unsafe_get b64 ( bits lsr 18)); Bytes.unsafe_set t (!j+1) (Array.unsafe_get b64 ((bits lsr 12) land 63)); Bytes.unsafe_set t (!j+2) (Array.unsafe_get b64 ((bits lsr 6) land 63)); Bytes.unsafe_set t (!j+3) (Array.unsafe_get b64 ( bits land 63)); j := !j + 4; if linelen > 3 then begin q := !q + 4; if !q + 4 > linelen then begin (* The next 4 characters won't fit on the current line. So insert * a line ending. *) if crlf then begin Bytes.set t !j '\013'; Bytes.set t (!j+1) '\010'; j := !j + 2; end else begin Bytes.set t !j '\010'; incr j end; q := 0; end; end; done; (* padding if needed: *) let m = len mod 3 in begin match m with 0 -> () | 1 -> let bits = Char.code (ops.get s (pos + len - 1)) in Bytes.set t !j b64.( bits lsr 2); Bytes.set t (!j + 1) b64.( (bits land 0x03) lsl 4); j := !j + 4; q := !q + 4; | 2 -> let bits = (Char.code (ops.get s (pos + len - 2)) lsl 8) lor (Char.code (ops.get s (pos + len - 1))) in Bytes.set t !j b64.( bits lsr 10); Bytes.set t (!j + 1) b64.((bits lsr 4) land 0x3f); Bytes.set t (!j + 2) b64.((bits lsl 2) land 0x3f); j := !j + 4; q := !q + 4; | _ -> assert false end; (* If required, add another line end: *) if linelen > 3 && !q > 0 && len > 0 then begin if crlf then begin Bytes.set t !j '\013'; Bytes.set t (!j+1) '\010'; j := !j + 2; end else begin Bytes.set t !j '\010'; incr j; end; end; (t, !q) ;; let encode_poly ?(pos=0) ?len ?(linelength=0) ?(crlf=false) ?(plus='+') ?(slash='/') ops s = let open Netstring_tstring in let alpha = mod_alphabet plus slash in let l = match len with None -> ops.length s - pos | Some x -> x in let s,_ = encode_with_options ops alpha '=' s pos l linelength linelength crlf in s ;; let encode ?pos ?len ?linelength ?crlf ?plus ?slash s = let ops = Netstring_tstring.string_ops in let s = encode_poly ?pos ?len ?linelength ?crlf ?plus ?slash ops s in Bytes.unsafe_to_string s let encode_tstring ?pos ?len ?linelength ?crlf ?plus ?slash ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> encode_poly ?pos ?len ?linelength ?crlf ?plus ?slash ops s ) } ts let encoding_pipe_conv ?(linelength = 0) ?(crlf = false) ~plus ~slash alpha lastlen incoming incoming_eof outgoing = let ops = Netstring_tstring.bytes_ops in let linelength = (linelength asr 2) lsl 2 in let len = Netbuffer.length incoming in let len' = if incoming_eof then len else len - (len mod 3) (* only process a multiple of three characters *) in let (s,ll) = encode_with_options ops alpha '=' (Netbuffer.unsafe_buffer incoming) 0 len' linelength (linelength - !lastlen) crlf in Netbuffer.delete incoming 0 len'; (* LF/CRLF: Unless s = "", s ends with a LF/CRLF. This is only right * if ll = 0 or at EOF. In the other cases, this additional LF/CRLF * must not be added to [outgoing]. *) if linelength < 3 || ll=0 || Bytes.length s = 0 then begin Netbuffer.add_bytes outgoing s; end else begin let sl = Bytes.length s in assert(Bytes.get s (sl-1) = '\n'); let sl' = if crlf then sl-2 else sl-1 in Netbuffer.add_subbytes outgoing s 0 sl'; end; lastlen := ll; (* Ensure there is a LF/CRLF at the end: *) if incoming_eof && linelength > 3 && ll > 0 then Netbuffer.add_string outgoing (if crlf then "\r\n" else "\n"); (* TODO: Can be improved by using Netbuffer.add_inplace *) class encoding_pipe ?linelength ?crlf ?(plus='+') ?(slash='/') () = let alpha = mod_alphabet plus slash in let lastlen = ref 0 in let conv = encoding_pipe_conv ?linelength ?crlf ~plus ~slash alpha lastlen in Netchannels.pipe ~conv () let decode_prefix ops t pos len plus slash p_spaces p_full p_null = (* Decodes the prefix of a Base64-encoded string. Returns a triple * (s,n,eof) where s is the decoded prefix, and n is the number of * processed characters from t (i.e. the characters pos to pos+n-1 have * been processed), and where eof is the boolean flag whether the * padding '=' characters at the end of the string have been seen. * * p_spaces: accepts spaces in [t] (at the price of reduced speed) * p_full: [t] must be a closed encoded string (i.e. no prefix) * p_null: [t] must be an encoded null string *) let open Netstring_tstring in if len < 0 || pos < 0 || pos > ops.length t then invalid_arg "Netencoding.Base64.decode"; if pos + len > ops.length t then invalid_arg "Netencoding.Base64.decode"; (* Compute the number of effective characters l_t in 't'; * pad_chars: number of '=' characters at the end of the string. *) let l_t, pad_chars = if p_spaces then begin (* Count all non-whitespace characters: *) let c = ref 0 in let p = ref 0 in for i = pos to pos + len - 1 do match ops.unsafe_get t i with (' '|'\t'|'\r'|'\n'|'>') -> () | '=' -> incr c; incr p; if !p > 2 then invalid_arg "Netencoding.Base64.decode"; for j = i+1 to pos + len - 1 do match ops.unsafe_get t j with (' '|'\t'|'\r'|'\n'|'=') -> () | _ -> (* Only another '=' or spaces allowed *) invalid_arg "Netencoding.Base64.decode"; done | _ -> incr c done; !c, !p end else len, ( if len > 0 then ( if ops.substring t (len - 2) 2 = "==" then 2 else if ops.substring t (len - 1) 1 = "=" then 1 else 0 ) else 0 ) in if p_null && l_t <> 0 then invalid_arg "Netencoding.Base64.decode"; (* Compute the number of characters [l_t] that can be processed now * (i.e. the effective prefix) *) let l_t, pad_chars = let m = l_t mod 4 in if m = 0 then ( (l_t, pad_chars) (* a multiple of 4 *) ) else ( if p_full then invalid_arg "Netencoding.Base64.decode"; (l_t - m, 0) (* rounded to a multiple of 4 *) ) in let l_s = (l_t / 4) * 3 - pad_chars in let s = Bytes.create l_s in let decode_char c = match c with 'A' .. 'Z' -> Char.code(c) - 65 (* 65 = Char.code 'A' *) | 'a' .. 'z' -> Char.code(c) - 71 (* 71 = Char.code 'a' - 26 *) | '0' .. '9' -> Char.code(c) + 4 (* -4 = Char.code '0' - 52 *) | _ -> if c = plus then 62 else if c = slash then 63 else invalid_arg "Netencoding.Base64.decode"; in (* Decode all but the last quartet: *) let cursor = ref pos in let rec next_char() = match ops.get t !cursor with (' '|'\t'|'\r'|'\n'|'>') -> if p_spaces then (incr cursor; next_char()) else invalid_arg "Netencoding.Base64.decode" | c -> incr cursor; c in if p_spaces then begin for k = 0 to l_t / 4 - 2 do let q = 3*k in let c0 = next_char() in let c1 = next_char() in let c2 = next_char() in let c3 = next_char() in let n0 = decode_char c0 in let n1 = decode_char c1 in let n2 = decode_char c2 in let n3 = decode_char c3 in let x0 = (n0 lsl 2) lor (n1 lsr 4) in let x1 = ((n1 lsl 4) land 0xf0) lor (n2 lsr 2) in let x2 = ((n2 lsl 6) land 0xc0) lor n3 in Bytes.unsafe_set s q (Char.chr x0); Bytes.unsafe_set s (q+1) (Char.chr x1); Bytes.unsafe_set s (q+2) (Char.chr x2); done; end else begin (* Much faster: *) for k = 0 to l_t / 4 - 2 do let p = pos + 4*k in let q = 3*k in let c012 = ops.unsafe_get3 t p in let c0 = c012 lsr 16 in let c1 = (c012 lsr 8) land 0xff in let c2 = c012 land 0xff in let c3 = ops.unsafe_get t (p + 3) in let n0 = decode_char (Char.unsafe_chr c0) in let n1 = decode_char (Char.unsafe_chr c1) in let n2 = decode_char (Char.unsafe_chr c2) in let n3 = decode_char c3 in let x0 = (n0 lsl 2) lor (n1 lsr 4) in let x1 = ((n1 lsl 4) land 0xf0) lor (n2 lsr 2) in let x2 = ((n2 lsl 6) land 0xc0) lor n3 in Bytes.unsafe_set s q (Char.chr x0); Bytes.unsafe_set s (q+1) (Char.chr x1); Bytes.unsafe_set s (q+2) (Char.chr x2); done; cursor := pos + l_t - 4; end; (* Decode the last quartet: *) if l_t > 0 then begin let q = 3*(l_t / 4 - 1) in let c0 = next_char() in let c1 = next_char() in let c2 = next_char() in let c3 = next_char() in if (c2 = '=' && c3 = '=') then begin let n0 = decode_char c0 in let n1 = decode_char c1 in let x0 = (n0 lsl 2) lor (n1 lsr 4) in Bytes.set s q (Char.chr x0); end else if (c3 = '=') then begin let n0 = decode_char c0 in let n1 = decode_char c1 in let n2 = decode_char c2 in let x0 = (n0 lsl 2) lor (n1 lsr 4) in let x1 = ((n1 lsl 4) land 0xf0) lor (n2 lsr 2) in Bytes.set s q (Char.chr x0); Bytes.set s (q+1) (Char.chr x1); end else begin let n0 = decode_char c0 in let n1 = decode_char c1 in let n2 = decode_char c2 in let n3 = decode_char c3 in let x0 = (n0 lsl 2) lor (n1 lsr 4) in let x1 = ((n1 lsl 4) land 0xf0) lor (n2 lsr 2) in let x2 = ((n2 lsl 6) land 0xc0) lor n3 in Bytes.set s q (Char.chr x0); Bytes.set s (q+1) (Char.chr x1); Bytes.set s (q+2) (Char.chr x2); end end else cursor := 0; (s, !cursor - pos, pad_chars > 0) ;; let decode_poly ?(pos=0) ?len ?(accept_spaces=false) ?(plus='+') ?(slash='/') ops s = let open Netstring_tstring in let l = match len with None -> ops.length s - pos | Some x -> x in let (s,_,_) = decode_prefix ops s pos l plus slash accept_spaces true false in s let decode ?pos ?len ?accept_spaces ?plus ?slash s = let ops = Netstring_tstring.string_ops in let s' = decode_poly ?pos ?len ?accept_spaces ?plus ?slash ops s in Bytes.unsafe_to_string s' let decode_tstring ?pos ?len ?accept_spaces ?plus ?slash ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> decode_poly ?pos ?len ?accept_spaces ?plus ?slash ops s ) } ts (* TODO: Use Netbuffer.add_inplace instead of creating an intermediate * string s in [decoding_pipe_conv]. *) let decoding_pipe_conv plus slash accept_spaces padding_seen incoming incoming_eof outgoing = let ops = Netstring_tstring.bytes_ops in let len = Netbuffer.length incoming in let t = Netbuffer.unsafe_buffer incoming in if !padding_seen then begin (* Only accept the null string: *) let _,_,_ = decode_prefix ops t 0 len plus slash accept_spaces false true in Netbuffer.clear incoming end else begin let (s,n,ps) = decode_prefix ops t 0 len plus slash accept_spaces incoming_eof false in padding_seen := ps; if incoming_eof then Netbuffer.clear incoming else Netbuffer.delete incoming 0 n; Netbuffer.add_bytes outgoing s end; class decoding_pipe ?(accept_spaces=false) ?(plus='+') ?(slash='/') () = let padding_seen = ref false in let conv = decoding_pipe_conv plus slash accept_spaces padding_seen in Netchannels.pipe ~conv () end module QuotedPrintable = struct let encode_sub ?(crlf = true) ?(eot = false) ?(line_length = ref 0) ~pos ~len ops s = (* line_length: * - on input, the length of the line where the encoding starts * - on output, the length of the last written line * eot: * - false: it is known that the chunk is not at the end of text * - true: the chunk may be at the end of the text * eot has only an effect on trailing spaces *) let open Netstring_tstring in if len < 0 || pos < 0 || pos > ops.length s then invalid_arg "Netencoding.QuotedPrintable.encode"; if pos + len > ops.length s then invalid_arg "Netencoding.QuotedPrintable.encode"; let eol_len = if crlf then 2 else 1 in (* length of eol *) (* Note: The [count] algorithm must strictly correspond to the * "for" loop below. *) let rec count l n i = (* l: output line length * n: output byte count * i: input byte count *) if i < len then match ops.unsafe_get s (pos+i) with '\r' -> (* CR is deleted *) count l n (i+1) | '\n' -> (* LF may be expanded to CR/LF *) count 0 (n+eol_len) (i+1) | ('\000'..'\031'|'\127'..'\255'| '!'|'"'|'#'|'$'|'@'|'['|']'|'^'|'\''|'{'|'|'|'}'|'~'|'=') -> if l <= 69 then count (l+3) (n+3) (i+1) else (* Add soft line break after the encoded char: *) count 0 (n+4+eol_len) (i+1) | 'F' when l=0 -> (* Protect 'F' at the beginning of lines *) count (l+3) (n+3) (i+1) | ' ' when (i=len-1 && eot) || (* at end of text *) l>69 || (* line too long *) (i (* Protect spaces only if they occur at the end of a line, * or just before soft line breaks *) if l <= 69 then count (l+3) (n+3) (i+1) else (* Add soft line after the encoded space: *) count 0 (n+4+eol_len) (i+1) | _ -> if l>71 then (* Add soft line break after the char: *) count 0 (n+2+eol_len) (i+1) else count (l+1) (n+1) (i+1) else n in let t_len = count !line_length 0 0 in let t = Bytes.create t_len in let k = ref 0 in let add_quoted c = Bytes.set t !k '='; Bytes.set t (!k+1) (hexdigit_uc.( Char.code c lsr 4 )); Bytes.set t (!k+2) (hexdigit_uc.( Char.code c land 15 )) in let add_soft_break() = Bytes.set t !k '='; if crlf then ( Bytes.set t (!k+1) '\r'; Bytes.set t (!k+2) '\n'; ) else Bytes.set t (!k+1) '\n'; in (* In the following, the soft break criterion is [!l > 72]. Why? * We need to be able to add at least an encoded char (3 bytes) * plus the "=" sign for the soft break. So we are on the safe side * when there are four bytes space on the line. Lines must not be * longer than 76 chars (w/o CRLF), so 76-4=72. *) let l = ref !line_length in for i = 0 to len - 1 do match ops.unsafe_get s i with '\r' -> (* CR is deleted *) () | '\n' -> (* LF is expanded to CR/LF *) if crlf then ( Bytes.set t !k '\r'; Bytes.set t (!k+1) '\n'; k := !k + 2; ) else ( Bytes.set t !k '\n'; k := !k + 1; ); l := 0 | ('\000'..'\031'|'\127'..'\255'| '!'|'"'|'#'|'$'|'@'|'['|']'|'^'|'\''|'{'|'|'|'}'|'~'|'=') as c -> add_quoted c; k := !k + 3; l := !l + 3; if !l > 72 then ( (* Add soft line break: *) add_soft_break(); k := !k + 1 + eol_len; l := 0 ) | 'F' when !l = 0 -> (* Protect 'F' at the beginning of lines *) add_quoted 'F'; k := !k + 3; l := !l + 3; | ' ' when ((i=len-1 && eot) || !l > 69 || (i add_quoted ' '; k := !k + 3; l := !l + 3; if !l > 72 then ( add_soft_break(); k := !k + 1 + eol_len; l := 0; ) | c -> Bytes.unsafe_set t !k c; incr k; incr l; if !l > 72 then ( add_soft_break(); k := !k + 1 + eol_len; l := 0; ) done; assert(!k == t_len); line_length := !l; t ;; let encode_poly ?crlf ?(pos=0) ?len ops s = let open Netstring_tstring in let l = match len with None -> ops.length s - pos | Some x -> x in encode_sub ?crlf ~eot:true ~pos ~len:l ops s;; let encode ?crlf ?pos ?len s = let ops = Netstring_tstring.string_ops in let s' = encode_poly ?crlf ?pos ?len ops s in Bytes.unsafe_to_string s' let encode_tstring ?crlf ?pos ?len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> encode_poly ?crlf ?pos ?len ops s ) } ts let encoding_pipe_conv ?crlf line_length incoming incoming_eof outgoing = (* Problematic case: the incoming buffer ends with a space, but we are * not at EOF. It is possible that a LF immediately follows, and that * the space needs to be quoted. * Solution: Do not convert such spaces, they remain in the buffer. *) let open Netstring_tstring in let ops = Netstring_tstring.bytes_ops in let s = Netbuffer.unsafe_buffer incoming in let len = Netbuffer.length incoming in let (len',eot) = if not incoming_eof && len > 0 && ops.get s (len-1) = ' ' then (len-1, false) else (len, true) in let s' = encode_sub ?crlf ~eot ~line_length ~pos:0 ~len:len' ops s in Netbuffer.add_bytes outgoing s'; Netbuffer.delete incoming 0 len' ;; class encoding_pipe ?crlf () = let line_length = ref 0 in Netchannels.pipe ~conv:(encoding_pipe_conv ?crlf line_length) () let decode_sub ~pos ~len ops s = let open Netstring_tstring in if len < 0 || pos < 0 || pos > ops.length s then invalid_arg "Netencoding.QuotedPrintable.decode"; if pos + len > ops.length s then invalid_arg "Netencoding.QuotedPrintable.decode"; let decode_hex c = match c with '0'..'9' -> Char.code c - 48 | 'A'..'F' -> Char.code c - 55 | 'a'..'f' -> Char.code c - 87 | _ -> invalid_arg "Netencoding.QuotedPrintable.decode"; in let rec count n i = if i < len then match ops.unsafe_get s (pos+i) with '=' -> if i+1 = len then (* A '=' at EOF is ignored *) count n (i+1) else if i+1 < len then match ops.get s (pos+i+1) with '\r' -> (* Official soft break *) if i+2 < len && ops.get s (pos+i+2) = '\n' then count n (i+3) else count n (i+2) | '\n' -> (* Inofficial soft break *) count n (i+2) | _ -> if i+2 >= len then invalid_arg "Netencoding.QuotedPrintable.decode"; let _ = decode_hex (ops.get s (pos+i+1)) in let _ = decode_hex (ops.get s (pos+i+2)) in count (n+1) (i+3) else invalid_arg "Netencoding.QuotedPrintable.decode" | _ -> count (n+1) (i+1) else n in let l = count 0 0 in let t = Bytes.create l in let k = ref pos in let e = pos + len in let i = ref 0 in while !i < l do match ops.unsafe_get s !k with '=' -> if !k+1 = e then (* A '=' at EOF is ignored *) () else if !k+1 < e then match ops.get s (!k+1) with '\r' -> (* Official soft break *) if !k+2 < e && ops.get s (!k+2) = '\n' then k := !k + 3 else k := !k + 2 | '\n' -> (* Inofficial soft break *) k := !k + 2 | _ -> if !k+2 >= e then invalid_arg "Netencoding.QuotedPrintable.decode_substring"; let x1 = decode_hex (ops.get s (!k+1)) in let x2 = decode_hex (ops.get s (!k+2)) in Bytes.set t !i (Char.chr ((x1 lsl 4) lor x2)); k := !k + 3; incr i else invalid_arg "Netencoding.QuotedPrintable.decode_substring" | c -> Bytes.unsafe_set t !i c; incr k; incr i done; t ;; let decode_poly ?(pos=0) ?len ops s = let open Netstring_tstring in let l = match len with None -> ops.length s - pos | Some x -> x in decode_sub ~pos ~len:l ops s;; let decode ?pos ?len s = let ops = Netstring_tstring.string_ops in let s' = decode_poly ?pos ?len ops s in Bytes.unsafe_to_string s' let decode_tstring ?pos ?len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> decode_poly ?pos ?len ops s ) } ts let decoding_pipe_conv incoming incoming_eof outgoing = (* Problematic case: The incoming buffer ends with '=' or '=X'. In this * case these characters remain in the buffer, because they will be * completed to a full hex sequence by the next conversion call. *) let open Netstring_tstring in let ops = Netstring_tstring.bytes_ops in let s = Netbuffer.unsafe_buffer incoming in let len = Netbuffer.length incoming in let len' = if not incoming_eof then begin if len > 0 && ops.get s (len-1) = '=' then len - 1 else if len > 1 && ops.get s (len-2) = '=' then len - 2 else len end else len in let s' = decode_poly ~len:len' ops s in Netbuffer.add_bytes outgoing s'; Netbuffer.delete incoming 0 len' ;; class decoding_pipe () = Netchannels.pipe ~conv:decoding_pipe_conv () end module Q = struct let encode_sub ~pos ~len ops s = let open Netstring_tstring in if len < 0 || pos < 0 || pos > ops.length s then invalid_arg "Netencoding.Q.encode_substring"; if pos + len > ops.length s then invalid_arg "Netencoding.Q.encode_substring"; let rec count n i = if i < len then match ops.unsafe_get s (pos+i) with | ('A'..'Z'|'a'..'z'|'0'..'9') -> count (n+1) (i+1) | _ -> count (n+3) (i+1) else n in let l = count 0 0 in let t = Bytes.create l in let k = ref 0 in let add_quoted c = Bytes.set t !k '='; Bytes.set t (!k+1) (hexdigit_uc.( Char.code c lsr 4 )); Bytes.set t (!k+2) (hexdigit_uc.( Char.code c land 15 )) in for i = 0 to len - 1 do match ops.unsafe_get s i with | ('A'..'Z'|'a'..'z'|'0'..'9') as c -> Bytes.unsafe_set t !k c; incr k | c -> add_quoted c; k := !k + 3 done; t ;; let encode_poly ?(pos=0) ?len ops s = let open Netstring_tstring in let l = match len with None -> ops.length s - pos | Some x -> x in encode_sub ~pos ~len:l ops s;; let encode ?pos ?len s = let ops = Netstring_tstring.string_ops in let s' = encode_poly ?pos ?len ops s in Bytes.unsafe_to_string s' let encode_tstring ?pos ?len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> encode_poly ?pos ?len ops s ) } ts let decode_sub ~pos ~len ops s = let open Netstring_tstring in if len < 0 || pos < 0 || pos > ops.length s then invalid_arg "Netencoding.Q.decode_substring"; if pos + len > ops.length s then invalid_arg "Netencoding.Q.decode_substring"; let decode_hex c = match c with '0'..'9' -> Char.code c - 48 | 'A'..'F' -> Char.code c - 55 | 'a'..'f' -> Char.code c - 87 | _ -> invalid_arg "Netencoding.Q.decode_substring"; in let rec count n i = if i < len then match ops.unsafe_get s (pos+i) with '=' -> if i+2 >= len then invalid_arg "Netencoding.Q.decode_substring"; let _ = decode_hex (ops.get s (pos+i+1)) in let _ = decode_hex (ops.get s (pos+i+2)) in count (n+1) (i+3) | _ -> (* including '_' *) count (n+1) (i+1) else n in let l = count 0 0 in let t = Bytes.create l in let k = ref pos in let e = pos + len in let i = ref 0 in while !i < l do match ops.unsafe_get s !k with '=' -> if !k+2 >= e then invalid_arg "Netencoding.Q.decode_substring"; let x1 = decode_hex (ops.get s (!k+1)) in let x2 = decode_hex (ops.get s (!k+2)) in Bytes.set t !i (Char.chr ((x1 lsl 4) lor x2)); k := !k + 3; incr i | '_' -> Bytes.unsafe_set t !i ' '; incr k; incr i | c -> Bytes.unsafe_set t !i c; incr k; incr i done; t ;; let decode_poly ?(pos=0) ?len ops s = let open Netstring_tstring in let l = match len with None -> ops.length s - pos | Some x -> x in decode_sub ~pos ~len:l ops s;; let decode ?pos ?len s = let ops = Netstring_tstring.string_ops in let s' = decode_poly ?pos ?len ops s in Bytes.unsafe_to_string s' let decode_tstring ?pos ?len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> decode_poly ?pos ?len ops s ) } ts end module Url = struct let hex_digits = [| '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; 'A'; 'B'; 'C'; 'D'; 'E'; 'F' |];; let to_hex2 k = (* Converts k to a 2-digit hex string *) let s = Bytes.create 2 in Bytes.set s 0 (hex_digits.( (k lsr 4) land 15 )); Bytes.set s 1 (hex_digits.( k land 15 )); Bytes.unsafe_to_string s ;; let of_hex1 c = match c with ('0'..'9') -> Char.code c - Char.code '0' | ('A'..'F') -> Char.code c - Char.code 'A' + 10 | ('a'..'f') -> Char.code c - Char.code 'a' + 10 | _ -> raise Not_found ;; let url_encoding_re = Netstring_str.regexp "[^A-Za-z0-9_.!*-]";; let url_decoding_re = Netstring_str.regexp "\\+\\|%..\\|%.\\|%";; let encode ?(plus = true) s = Netstring_str.global_substitute url_encoding_re (fun r _ -> match Netstring_str.matched_string r s with " " when plus -> "+" | x -> let k = Char.code(x.[0]) in "%" ^ to_hex2 k ) s ;; let decode ?(plus = true) ?(pos=0) ?len s = let s_l = String.length s in let s1 = if pos = 0 && len=None then s else let len = match len with Some n -> n | None -> s_l in String.sub s pos len in let l = String.length s1 in Netstring_str.global_substitute url_decoding_re (fun r _ -> match Netstring_str.matched_string r s1 with | "+" -> if plus then " " else "+" | _ -> let i = Netstring_str.match_beginning r in (* Assertion: s1.[i] = '%' *) if i+2 >= l then failwith "Netencoding.Url.decode"; let c1 = s1.[i+1] in let c2 = s1.[i+2] in begin try let k1 = of_hex1 c1 in let k2 = of_hex1 c2 in String.make 1 (Char.chr((k1 lsl 4) lor k2)) with Not_found -> failwith "Netencoding.Url.decode" end ) s1 ;; let url_split_re = Netstring_str.regexp "[&=]";; let mk_url_encoded_parameters nv_pairs = String.concat "&" (List.map (fun (name,value) -> let name_encoded = encode name in let value_encoded = encode value in name_encoded ^ "=" ^ value_encoded ) nv_pairs ) ;; let dest_url_encoded_parameters parstr = let rec parse_after_amp tl = match tl with Netstring_str.Text name :: Netstring_str.Delim "=" :: Netstring_str.Text value :: tl' -> (decode name, decode value) :: parse_next tl' | Netstring_str.Text name :: Netstring_str.Delim "=" :: Netstring_str.Delim "&" :: tl' -> (decode name, "") :: parse_after_amp tl' | Netstring_str.Text name :: Netstring_str.Delim "=" :: [] -> [decode name, ""] | _ -> failwith "Netencoding.Url.dest_url_encoded_parameters" and parse_next tl = match tl with [] -> [] | Netstring_str.Delim "&" :: tl' -> parse_after_amp tl' | _ -> failwith "Netencoding.Url.dest_url_encoded_parameters" in let toklist = Netstring_str.full_split url_split_re parstr in match toklist with [] -> [] | _ -> parse_after_amp toklist ;; let mk_url_encoded_parameters params = String.concat "&" (List.map (fun (name, value) -> encode name ^ "=" ^ encode value) params) end module Html = struct let etable = [ "lt", 60; "gt", 62; "amp", 38; "quot", 34; (* Note: " is new in HTML-4.0, but it has been widely used * much earlier. *) "apos", 39; (* Only used if contained in unsafe_chars *) (* ISO-8859-1: *) "nbsp", 160; "iexcl", 161; "cent", 162; "pound", 163; "curren", 164; "yen", 165; "brvbar", 166; "sect", 167; "uml", 168; "copy", 169; "ordf", 170; "laquo", 171; "not", 172; "shy", 173; "reg", 174; "macr", 175; "deg", 176; "plusmn", 177; "sup2", 178; "sup3", 179; "acute", 180; "micro", 181; "para", 182; "middot", 183; "cedil", 184; "sup1", 185; "ordm", 186; "raquo", 187; "frac14", 188; "frac12", 189; "frac34", 190; "iquest", 191; "Agrave", 192; "Aacute", 193; "Acirc", 194; "Atilde", 195; "Auml", 196; "Aring", 197; "AElig", 198; "Ccedil", 199; "Egrave", 200; "Eacute", 201; "Ecirc", 202; "Euml", 203; "Igrave", 204; "Iacute", 205; "Icirc", 206; "Iuml", 207; "ETH", 208; "Ntilde", 209; "Ograve", 210; "Oacute", 211; "Ocirc", 212; "Otilde", 213; "Ouml", 214; "times", 215; "Oslash", 216; "Ugrave", 217; "Uacute", 218; "Ucirc", 219; "Uuml", 220; "Yacute", 221; "THORN", 222; "szlig", 223; "agrave", 224; "aacute", 225; "acirc", 226; "atilde", 227; "auml", 228; "aring", 229; "aelig", 230; "ccedil", 231; "egrave", 232; "eacute", 233; "ecirc", 234; "euml", 235; "igrave", 236; "iacute", 237; "icirc", 238; "iuml", 239; "eth", 240; "ntilde", 241; "ograve", 242; "oacute", 243; "ocirc", 244; "otilde", 245; "ouml", 246; "divide", 247; "oslash", 248; "ugrave", 249; "uacute", 250; "ucirc", 251; "uuml", 252; "yacute", 253; "thorn", 254; "yuml", 255; (* Other: *) "fnof", 402; "Alpha", 913; "Beta", 914; "Gamma", 915; "Delta", 916; "Epsilon", 917; "Zeta", 918; "Eta", 919; "Theta", 920; "Iota", 921; "Kappa", 922; "Lambda", 923; "Mu", 924; "Nu", 925; "Xi", 926; "Omicron", 927; "Pi", 928; "Rho", 929; "Sigma", 931; "Tau", 932; "Upsilon", 933; "Phi", 934; "Chi", 935; "Psi", 936; "Omega", 937; "alpha", 945; "beta", 946; "gamma", 947; "delta", 948; "epsilon", 949; "zeta", 950; "eta", 951; "theta", 952; "iota", 953; "kappa", 954; "lambda", 955; "mu", 956; "nu", 957; "xi", 958; "omicron", 959; "pi", 960; "rho", 961; "sigmaf", 962; "sigma", 963; "tau", 964; "upsilon", 965; "phi", 966; "chi", 967; "psi", 968; "omega", 969; "thetasym", 977; "upsih", 978; "piv", 982; "bull", 8226; "hellip", 8230; "prime", 8242; "Prime", 8243; "oline", 8254; "frasl", 8260; "weierp", 8472; "image", 8465; "real", 8476; "trade", 8482; "alefsym", 8501; "larr", 8592; "uarr", 8593; "rarr", 8594; "darr", 8595; "harr", 8596; "crarr", 8629; "lArr", 8656; "uArr", 8657; "rArr", 8658; "dArr", 8659; "hArr", 8660; "forall", 8704; "part", 8706; "exist", 8707; "empty", 8709; "nabla", 8711; "isin", 8712; "notin", 8713; "ni", 8715; "prod", 8719; "sum", 8721; "minus", 8722; "lowast", 8727; "radic", 8730; "prop", 8733; "infin", 8734; "ang", 8736; "and", 8743; "or", 8744; "cap", 8745; "cup", 8746; "int", 8747; "there4", 8756; "sim", 8764; "cong", 8773; "asymp", 8776; "ne", 8800; "equiv", 8801; "le", 8804; "ge", 8805; "sub", 8834; "sup", 8835; "nsub", 8836; "sube", 8838; "supe", 8839; "oplus", 8853; "otimes", 8855; "perp", 8869; "sdot", 8901; "lceil", 8968; "rceil", 8969; "lfloor", 8970; "rfloor", 8971; "lang", 9001; "rang", 9002; "loz", 9674; "spades", 9824; "clubs", 9827; "hearts", 9829; "diams", 9830; "OElig", 338; "oelig", 339; "Scaron", 352; "scaron", 353; "Yuml", 376; "circ", 710; "tilde", 732; "ensp", 8194; "emsp", 8195; "thinsp", 8201; "zwnj", 8204; "zwj", 8205; "lrm", 8206; "rlm", 8207; "ndash", 8211; "mdash", 8212; "lsquo", 8216; "rsquo", 8217; "sbquo", 8218; "ldquo", 8220; "rdquo", 8221; "bdquo", 8222; "dagger", 8224; "Dagger", 8225; "permil", 8240; "lsaquo", 8249; "rsaquo", 8250; "euro", 8364; ] ;; let quick_etable_html = let ht = Hashtbl.create 50 in List.iter (fun (name,value) -> Hashtbl.add ht name value ) etable; ht ;; let quick_etable_xml = let ht = Hashtbl.create 5 in List.iter (fun name -> let value = List.assoc name etable in Hashtbl.add ht name value ) [ "lt"; "gt"; "amp"; "quot"; "apos"]; ht ;; let rev_etable = (* Only code points 0 to 255: *) let a = Array.make 256 "" in List.iter (fun (name,value) -> if value <= 255 then a.(value) <- "&" ^ name ^ ";" ) etable; a ;; let rev_etable_rest = (* Only code points >= 256: *) let ht = Hashtbl.create 150 in List.iter (fun (name,value) -> if value >= 256 then Hashtbl.add ht value ("&" ^ name ^ ";") ) etable; ht ;; let unsafe_chars_html4 = "<>\"&\000\001\002\003\004\005\006\007\008\011\012\014\015\016\017\018\019\020\021\022\023\024\025\026\027\028\029\030\031\127" ;; let regexp_ht = Hashtbl.create 7 let regexp_ht_mutex = !Netsys_oothr.provider # create_mutex() let regexp_set s = Netsys_oothr.serialize regexp_ht_mutex (fun () -> try Hashtbl.find regexp_ht s with | Not_found -> let re = Netstring_str.regexp (Netstring_str.quote_set s) in if Hashtbl.length regexp_ht < 100 then (* avoid leak *) Hashtbl.replace regexp_ht s re; re ) () (* The functions [encode_quickly] and [encode_ascii] are special cases of * [encode] that can be implemented by regular expressions. *) let encode_quickly ~prefer_name ~unsafe_chars () = (* Preconditions: in_enc = out_enc, and the encoding must be a single-byte, * ASCII-compatible encoding. *) if unsafe_chars = "" then (fun s -> s) else let unsafe_re = regexp_set unsafe_chars in Netstring_str.global_substitute unsafe_re (fun r s -> let t = Netstring_str.matched_string r s in let p = Char.code (t.[0]) in (* p is an ASCII code point *) let name = rev_etable.(p) in if prefer_name && name <> "" then name else "&#" ^ string_of_int p ^ ";" ) ;; let encode_quickly_poly ~prefer_name ~unsafe_chars ~ops ~out_kind () = Netstring_tstring.polymorph_string_transformation (encode_quickly ~prefer_name ~unsafe_chars ()) ops out_kind let msb_set = ( let s = Bytes.create 128 in for k = 0 to 127 do Bytes.set s k (Char.chr (128+k)) done; Bytes.unsafe_to_string s ) let encode_ascii ~in_enc ~prefer_name ~unsafe_chars () = (* Preconditions: out_enc = `Enc_usascii, and in_enc must be a single-byte, * ASCII-compatible encoding. *) let unsafe_chars1 = unsafe_chars ^ msb_set in let unsafe_re = regexp_set unsafe_chars1 in (* unicode_of.[q] = p: the code point q+128 of in_enc is the same as the * Unicode code point p *) let unicode_of = Array.make 128 (-1) in for i = 0 to 127 do try let s = String.make 1 (Char.chr (i+128)) in let u = Netconversion.uarray_of_ustring in_enc s in match u with [| u0 |] -> unicode_of.(i) <- u0 | _ -> assert false with Netconversion.Malformed_code -> unicode_of.(i) <- (-1) done; Netstring_str.global_substitute unsafe_re (fun r s -> let t = Netstring_str.matched_string r s in (* p is the code point in the encoding ~in_enc; p' is the Unicode * code point: *) let p = Char.code (t.[0]) in let p' = if p < 128 then p else unicode_of.(p - 128) in if p' < 0 then raise Netconversion.Malformed_code; let name = if prefer_name then begin if p' <= 255 then rev_etable.(p') else try Hashtbl.find rev_etable_rest p' with Not_found -> "" end else "" in if name = "" then "&#" ^ string_of_int p' ^ ";" else name ) ;; let encode_ascii_poly ~in_enc ~prefer_name ~unsafe_chars ~ops ~out_kind () = Netstring_tstring.polymorph_string_transformation (encode_ascii ~in_enc ~prefer_name ~unsafe_chars ()) ops out_kind let encode_from_latin1 = (* backwards compatible *) encode_ascii ~in_enc:`Enc_iso88591 ~prefer_name:true ~unsafe_chars:unsafe_chars_html4 () ;; let encode_poly ~in_enc ~in_ops ~out_kind ?(out_enc = `Enc_usascii) ?(prefer_name = true) ?(unsafe_chars = unsafe_chars_html4) () = (* This function implements the general case *) (* Check arguments: *) if not (Netconversion.is_ascii_compatible out_enc) then invalid_arg "Netencoding.Html.encode: out_enc not ASCII-compatible"; for i = 0 to String.length unsafe_chars - 1 do if Char.code(unsafe_chars.[i]) >= 128 then invalid_arg "Netencoding.Html.encode: non-ASCII character in unsafe_chars"; done; (* Are there better implementations than the general one? *) let in_single = Netconversion.is_single_byte in_enc in let in_subset = match in_enc with `Enc_subset(_,_) -> true | _ -> false in if not in_subset && in_enc=out_enc && in_single then encode_quickly_poly ~prefer_name ~unsafe_chars ~ops:in_ops ~out_kind () else if not in_subset && out_enc=`Enc_usascii && in_single then encode_ascii_poly ~in_enc ~prefer_name ~unsafe_chars ~ops:in_ops ~out_kind () else begin (* ... only the general implementation is applicable. *) (* Create the domain function: *) let dom_array = Array.make 128 true in let dom p = p >= 128 || dom_array.(p) in (* Set dom_array from unsafe_chars: *) for i = 0 to String.length unsafe_chars - 1 do let c = Char.code(unsafe_chars.[i]) in dom_array.(c) <- false done; (* Create the substitution function: *) let subst p = let name = if prefer_name then begin if p <= 255 then rev_etable.(p) else try Hashtbl.find rev_etable_rest p with Not_found -> "" end else "" in if name = "" then "&#" ^ string_of_int p ^ ";" else name in (* Recode: *) (fun s -> Netconversion.convert_poly ~in_ops ~out_kind ~subst ~in_enc ~out_enc:(`Enc_subset(out_enc,dom)) s ) end ;; let encode ~in_enc ?out_enc ?prefer_name ?unsafe_chars () = let in_ops = Netstring_tstring.string_ops in let out_kind = Netstring_tstring.String_kind in encode_poly ~in_enc ~in_ops ~out_kind ?out_enc ?prefer_name ?unsafe_chars () let encode_tstring ~in_enc ~out_kind ?out_enc ?prefer_name ?unsafe_chars () = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun in_ops s -> encode_poly ~in_enc ~in_ops ~out_kind ?out_enc ?prefer_name ?unsafe_chars () s ) } type entity_set = [ `Html | `Xml | `Empty ];; let eref_re = Netstring_str.regexp "&\\(\ #\\([0-9]+\\);\\|\ #[xX]\\([0-9a-fA-F]+\\);\\|\ \\([a-zA-Z]+\\);\ \\)" ;; let total_enc = (* every byte must have a corresponding Unicode code point, i.e. the * encoding must be "byte-total" *) function `Enc_iso88591 | `Enc_iso88592 | `Enc_iso88593 | `Enc_iso88594 | `Enc_iso88595 | `Enc_iso88599 | `Enc_iso885910 | `Enc_iso885913 | `Enc_iso885914 | `Enc_iso885915 | `Enc_iso885916 -> true | _ -> false ;; let hex_digit_of_char c = match c with '0'..'9' -> Char.code c - 48 | 'A'..'F' -> Char.code c - 55 | 'a'..'f' -> Char.code c - 87 | _ -> assert false let hex_of_string s = let n = ref 0 in for i = 0 to String.length s - 1 do let d = hex_digit_of_char s.[i] in n := (!n lsl 4) lor d done; !n let search_all re s pos = let rec search p acc = match try Some(Netstring_str.search_forward re s p) with Not_found -> None with | Some (k,r) -> search (k+1) ( (k,r) :: acc ) | None -> List.rev acc in search pos [] let decode_half_poly ~in_enc ~out_kind ~out_enc ?(lookup=fun name -> failwith ("Netencoding.Html.decode: Unknown entity `" ^ name ^ "'")) ?(subst=fun p -> failwith ("Netencoding.Html.decode: Character cannot be represented: " ^ string_of_int p)) ?(entity_base = (`Html : entity_set)) () = (* Argument checks: *) if not (Netconversion.is_ascii_compatible in_enc) then invalid_arg "Netencoding.Html.decode: in_enc not ASCII-compatible"; (* makechar: *) let raw_makechar = Netconversion.makechar out_enc in let makechar p = try raw_makechar p with Not_found -> subst p in (* Entity lookup: *) let lookup_entity = match entity_base with `Html | `Xml -> let ht = if entity_base = `Html then quick_etable_html else quick_etable_xml in ( fun name -> try makechar(Hashtbl.find ht name) with Not_found -> lookup name ) | `Empty -> lookup in (* Recode strings: *) let recode_str = if total_enc in_enc && in_enc = out_enc then (fun s pos len -> if pos=0 && len=(String.length s) then s else String.sub s pos len ) else (fun s range_pos range_len -> Netconversion.convert ~in_enc ~out_enc ~subst ~range_pos ~range_len s) in (fun s -> (* Find all occurrences of &name; or &#num; or &#xnum; *) let occurrences = search_all eref_re s 0 in (* Collect the resulting string in a buffer *) let buf = Netbuffer.create 250 in let n = ref 0 in List.iter (fun (n0,r) -> let n1 = Netstring_str.match_end r in if n0 > !n then Netbuffer.add_string buf (recode_str s !n (n0 - !n)); let replacement = let num = try Netstring_str.matched_group r 2 s with Not_found -> "" in (* Note: Older versions of Pcre return "" when the substring * did not match, newer versions raise Not_found *) if num <> "" then begin let n = int_of_string num in makechar n end else begin let xnum = try Netstring_str.matched_group r 3 s with Not_found -> "" in (* Note: Older versions of Pcre return "" when the substring * did not match, newer versions raise Not_found *) if xnum <> "" then begin let n = hex_of_string xnum in makechar n end else begin let name = try Netstring_str.matched_group r 4 s with Not_found -> "" in (* Note: Older versions of Pcre return "" when the substring * did not match, newer versions raise Not_found *) assert(name <> ""); lookup_entity name end end in Netbuffer.add_string buf replacement; n := n1; ) occurrences; let n0 = String.length s in if n0 > !n then Netbuffer.add_string buf (recode_str s !n (n0 - !n)); (* Return *) Netbuffer.to_tstring_poly buf out_kind ) ;; let decode_poly ~in_enc ~in_ops ~out_kind ~out_enc ?lookup ?subst ?entity_base () s = let open Netstring_tstring in decode_half_poly ~in_enc ~out_kind ~out_enc ?lookup ?subst ?entity_base () (in_ops.string s) let decode ~in_enc ~out_enc ?lookup ?subst ?entity_base () = let out_kind = Netstring_tstring.String_kind in decode_half_poly ~in_enc ~out_kind ~out_enc ?lookup ?subst ?entity_base () let decode_tstring ~in_enc ~out_kind ~out_enc ?lookup ?subst ?entity_base () = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun in_ops s -> decode_poly ~in_enc ~in_ops ~out_kind ~out_enc ?lookup ?subst ?entity_base () s ) } let decode_to_latin1 = decode ~in_enc:`Enc_iso88591 ~out_enc:`Enc_iso88591 ~lookup:(fun s -> "&" ^ s ^ ";") ~subst:(fun p -> "&#" ^ string_of_int p ^ ";") () end ocamlnet-4.1.2/src/netstring/netaux.mli0000644000175000017500000000425012731530350016557 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Internal auxiliary functions * * This is an internal module. *) (* Auxiliary stuff *) module KMP : sig (* An implementation of the Knuth-Morris-Pratt algorithm *) (* Credits go to Alain Frisch who suggested this algorithm *) type pattern val make_pattern : string -> pattern (* Prepares the passed pattern *) val find_pattern : pattern -> ?pos:int -> ?len:int -> Bytes.t -> int (* Searches the position where the pattern or a prefix of the pattern * occurs in the substring from position [pos] to [pos+len-1]. * Possible return values p: * - pos <= p <= pos+len-length(pattern): * The pattern occurs at position p in the string, i.e. * string.[p+k] = pattern.[k], for all 0 <= k < length(pattern). * Furthermore, the returned position p is the first such position. * - pos+len-length(pattern) < p < pos+len * The string ends with a prefix of the pattern, i.e. * string.[p+k] = pattern[k], for all 0 <= k < pos+len-p. * - p = pos+len * Neither does the pattern occur in the string, nor is the * (non-empty) suffix of the string a prefix of the pattern. * * Defaults: * ~pos = 0 * ~len = length(string)-pos = "until the end of the string" *) end module ArrayAux : sig val int_blit : int array -> int -> int array -> int -> int -> unit (** A specialisation of [Array.blit] for int arrays. * (Performance reasons.) *) val int_series : int array -> int -> int array -> int -> int -> int -> unit (** [int_series src srcpos dst dstpos len n]: * Computes for every [i], [0 <= i < len]: * [dst.(dstpos+i) = n + SUM(j=0..(i-1): src.(srcpos+j)) ] * * It is expected that [src == dst] implies [srcpos >= dstpos]. *) (**/**) val int_blit_ref : (int array -> int -> int array -> int -> int -> unit) ref (* Used by [Netaccel] to override the built-in implementation *) val int_series_ref : (int array -> int -> int array -> int -> int -> int -> unit) ref (* Used by [Netaccel] to override the built-in implementation *) end ocamlnet-4.1.2/src/netstring/netx509_pubkey_crypto.ml0000644000175000017500000000701012731530350021272 0ustar gerdgerdopen Netx509_pubkey open Printf exception Unsupported_algorithm of Netoid.t let is_encryption_supported (Encrypt(oid,_)) = let module PK = (val Netsys_crypto.current_pubkey_crypto()) in List.mem oid PK.supported_x509 let is_signing_supported (Sign(oid,_)) = let module PK = (val Netsys_crypto.current_pubkey_crypto()) in List.mem oid PK.supported_x509 let encode_alg_params_to_der alg_id = let Alg_id(_, params) = alg_id in match params with | None -> None | Some v -> let b = Netbuffer.create 80 in ignore(Netasn1_encode.encode_ber b v); Some(Netbuffer.contents b) let encrypt encalg pubkey data = let module PK = (val Netsys_crypto.current_pubkey_crypto()) in let Encrypt(oid,params) = encalg in let Alg_id(puboid,pubparams) = pubkey.pubkey_type in let expected_puboid = Encryption.key_oid_of_encrypt_alg encalg in if expected_puboid <> puboid then failwith "Netx509_pubkey_crypto.encrypt: the algorithm is incompatible \ with the public key"; let effparams = Encryption.alg_id_of_encrypt_alg encalg in let effparams_der = encode_alg_params_to_der effparams in let pk_alg = PK.algorithm_x509 oid effparams_der in let pk_pubkey = PK.import_public_key_x509 (Netx509_pubkey.encode_pubkey_to_der pubkey) in PK.encrypt pk_alg pk_pubkey data let decrypt encalg privkey data = let module PK = (val Netsys_crypto.current_pubkey_crypto()) in let Encrypt(oid,params) = encalg in let Privkey(privformat,privdata) = privkey in let puboid = Encryption.key_oid_of_encrypt_alg encalg in let expected_privformat = Key.private_key_format_of_key puboid in if expected_privformat <> privformat then failwith "Netx509_pubkey_crypto.decrypt: the algorithm is incompatible \ with the private key"; let effparams = Encryption.alg_id_of_encrypt_alg encalg in let effparams_der = encode_alg_params_to_der effparams in let pk_alg = PK.algorithm_x509 oid effparams_der in let pk_privkey = PK.import_private_key_x509 (privformat,privdata) in PK.decrypt pk_alg pk_privkey data let verify signalg pubkey plaintext signature = let module PK = (val Netsys_crypto.current_pubkey_crypto()) in let Sign(oid,params) = signalg in let Alg_id(puboid,pubparams) = pubkey.pubkey_type in let expected_puboid = Signing.key_oid_of_sign_alg signalg in if expected_puboid <> puboid then failwith "Netx509_pubkey_crypto.verify: the algorithm is incompatible \ with the public key"; let effparams = Signing.alg_id_of_sign_alg signalg in let effparams_der = encode_alg_params_to_der effparams in let pk_alg = PK.algorithm_x509 oid effparams_der in let pk_pubkey = PK.import_public_key_x509 (Netx509_pubkey.encode_pubkey_to_der pubkey) in PK.verify pk_alg pk_pubkey plaintext signature let sign signalg privkey plaintext = let module PK = (val Netsys_crypto.current_pubkey_crypto()) in let Sign(oid,params) = signalg in let Privkey(privformat,privdata) = privkey in let puboid = Signing.key_oid_of_sign_alg signalg in let expected_privformat = Key.private_key_format_of_key puboid in if expected_privformat <> privformat then failwith "Netx509_pubkey_crypto.sign: the algorithm is incompatible \ with the private key"; let effparams = Signing.alg_id_of_sign_alg signalg in let effparams_der = encode_alg_params_to_der effparams in let pk_alg = PK.algorithm_x509 oid effparams_der in let pk_privkey = PK.import_private_key_x509 (privformat,privdata) in PK.sign pk_alg pk_privkey plaintext ocamlnet-4.1.2/src/netstring/neturl_ldap.mli0000644000175000017500000000276612731530350017576 0ustar gerdgerd(** LDAP-specific URLs *) (** This is an extension of {!Neturl} for LDAP. Note that you can simply use {!Neturl.parse_url} to parse LDAP URLs. Find useful accessor functions below to get LDAP-specific parts. *) val ldap_url_dn : ?encoded:bool -> Neturl.url -> string val ldap_url_attributes : ?encoded:bool -> Neturl.url -> string list val ldap_url_scope : Neturl.url -> [ `Base | `One | `Sub ] val ldap_url_filter : ?encoded:bool -> Neturl.url -> string val ldap_url_extensions : ?encoded:bool -> Neturl.url -> (bool * string * string option) list (** Return components of the URL. The functions return decoded strings unless [encoded:true] is set. If the component does not exist, the exception [Not_found] is raised. If the component cannot be parsed, [Malformed_URL] is raised. *) val ldap_url_provides : ?dn:bool -> ?attributes:bool -> ?scope:bool -> ?filter:bool -> ?extensions:bool -> Neturl.url -> bool (** Whether all the selected URL components are present and the accessor can return them (even if empty) *) val make_ldap_url : ?encoded:bool -> ?host:string -> ?addr:Unix.inet_addr -> ?port:int -> ?socksymbol: Netsockaddr.socksymbol -> ?dn:string -> ?attributes:string list -> ?scope:[ `Base | `One | `Sub ] -> ?filter:string -> ?extensions:(bool * string * string option) list -> unit -> Neturl.url (** Create an LDAP URL *) ocamlnet-4.1.2/src/netstring/netx509.ml0000644000175000017500000007660112731530350016327 0ustar gerdgerd(* $Id$ *) open Netasn1.Value open Printf type oid = Netoid.t (** OIDs are just integer sequences *) exception Extension_not_found of oid class type directory_name = object method name : (oid * Netasn1.Value.value) list list method eq_name : (oid * Netasn1.Value.value) list list method string : string method eq_string : string end class type x509_certificate = object method subject : directory_name method subject_unique_id : Netasn1.Value.bitstring_value option method issuer : directory_name method issuer_unique_id : Netasn1.Value.bitstring_value option method version : int method serial_number : string method valid_not_before : float method valid_not_after : float method signature : Netasn1.Value.bitstring_value method signature_algorithm : oid * Netasn1.Value.value option method public_key : Netasn1.Value.bitstring_value method public_key_algorithm : oid * Netasn1.Value.value option method extensions : (oid * string * bool) list end module DN_attributes = struct let at k = [| 2; 5; 4; k |] let at_name = at 41 let at_surname = at 4 let at_givenName = at 42 let at_initials = at 43 let at_generationQualifier = at 44 let at_commonName = at 3 let at_localityName = at 7 let at_stateOrProvinceName = at 8 let at_organizationName = at 10 let at_organizationalUnitName = at 11 let at_title = at 12 let at_dnQualifier = at 46 let at_countryName = at 6 let at_serialNumber = at 5 let at_pseudonym = at 65 let at_domainComponent = [| 0; 9; 2342; 19200300; 100; 1; 25 |] let at_uid = [| 0; 9; 2342; 19200300; 100; 1; 1 |] let at_emailAddress = [| 1; 2; 840; 113549; 1; 9; 1 |] let attribute_types = [ at_name, "name", [ "name" ]; at_surname, "surname", [ "sn"; "surname" ]; at_givenName, "givenName", [ "gn"; "givenName" ]; at_initials, "initials", [ "initials" ]; at_generationQualifier, "generationQualifier", [ "generationQualifier" ]; at_commonName, "commonName", [ "cn"; "commonName" ]; at_localityName, "localityName", [ "l"; "localityName" ]; at_stateOrProvinceName, "stateOrProvinceName", [ "st"; "stateOrProvinceName" ]; at_organizationName, "organizationName", [ "o"; "organizationName" ]; at_organizationalUnitName, "organizationalUnitName", [ "ou"; "organizationalUnitName" ]; at_title, "title", [ "title" ]; at_dnQualifier, "dnQualifier", [ "dnQualifier" ]; at_countryName, "countryName", [ "c"; "countryName" ]; at_serialNumber, "serialNumber", [ "serialNumber" ]; at_pseudonym, "pseudonym", [ "pseudonym" ]; at_domainComponent, "domainComponent", [ "dc"; "domainComponent" ]; at_emailAddress, "emailAddress", [ "email"; "emailAddress"; "pkcs9email" ]; at_uid, "userid", [ "uid"; "userid" ]; ] let attribute_types_lc = List.map (fun (oid, name, l) -> (oid, name, List.map String.lowercase l)) attribute_types let lookup_attribute_type_by_oid oid = let (_, n, l) = List.find (fun (o,_,_) -> o = oid) attribute_types in (n,l) let lookup_attribute_type_by_name n = let lc = String.lowercase n in List.find (fun (_,_,l) -> List.mem lc l) attribute_types_lc end module X509_DN_string = Netdn.DN_string_generic(DN_attributes) let list_list_map f l1 = List.map (fun l2 -> List.map f l2) l1 let dn_uppercase = (* both PrintableString and IA5String are ASCII subsets *) function | PrintableString s -> PrintableString (String.uppercase s) | IA5String s -> IA5String (String.uppercase s) | other -> other let eq_normalize name = let name1 = list_list_map (fun (oid, att) -> let to_upper = (match att with | PrintableString _ -> true | IA5String _ -> oid = DN_attributes.at_emailAddress | _ -> false ) in if to_upper then (oid, dn_uppercase att) else (oid, att) ) name in List.map (fun rdn -> List.sort (fun (oid1,_) (oid2,_) -> Netoid.compare oid1 oid2) rdn ) name1 class x509_dn_from_ASN1 v = let name = match v with | Seq dn_l -> List.map (fun rdn -> match rdn with | Set rdn_l -> List.map (fun ava -> match ava with | Seq [ OID oid; any ] -> (oid, any) | _ -> failwith "Netx509.x509_dn_from_ASN1" ) rdn_l | _ -> failwith "Netx509.x509_dn_from_ASN1" ) dn_l | _ -> failwith "Netx509.x509_dn_from_ASN1" in let eq_name_lz = lazy (eq_normalize name) in let string_lz = lazy (X509_DN_string.print name) in let eq_string_lz = lazy (X509_DN_string.print (Lazy.force eq_name_lz)) in object(self) method name = name method eq_name = Lazy.force eq_name_lz method string = Lazy.force string_lz method eq_string = Lazy.force eq_string_lz end class x509_dn_from_string s = let name = X509_DN_string.parse s in let eq_name_lz = lazy (eq_normalize name) in let string_lz = lazy (X509_DN_string.print name) in let eq_string_lz = lazy (X509_DN_string.print (Lazy.force eq_name_lz)) in object(self) method name = name method eq_name = Lazy.force eq_name_lz method string = Lazy.force string_lz method eq_string = Lazy.force eq_string_lz end let lookup_dn_ava (dn:directory_name) oid = let rel_dn = List.find (fun rel_dn -> match rel_dn with | [ oid1, v ] -> oid1 = oid | _ -> false ) dn#name in match rel_dn with | [ _, v ] -> v | _ -> assert false let lookup_dn_ava_utf8 dn oid = let v = lookup_dn_ava dn oid in Netdn.directory_string_from_ASN1 v let map_opt f = function | None -> None | Some x -> Some(f x) class x509_certificate_from_ASN1 asn1 = let fail() = failwith "Netx509.x509_certificate_from_ASN1" in let parse_time asn1 = Netdate.since_epoch (match asn1 with | UTCTime tval -> get_time tval | GeneralizedTime tval -> get_time tval | _ -> fail() ) in let parse_algo_id asn1 = match asn1 with | Seq [ OID oid ] -> (oid, None) | Seq [ OID oid; param ] -> (oid, Some param) | _ -> fail() in let tbs_cert_l0, sig_algo_asn1, sig_value_bits = match asn1 with | Seq [ Seq tbs_cert_l0; sig_algo_asn1; Bitstring sig_value_bits ] -> (tbs_cert_l0, sig_algo_asn1, sig_value_bits) | _ -> fail() in let version_asn1, tbs_cert_l1 = (* explicitly tagged *) match tbs_cert_l0 with | Tag(Context, 0, Constructed, version_asn1) :: tbs_cert_l1 -> (Some version_asn1, tbs_cert_l1) | Tagptr(Context, 0, Constructed, box, pos, len) :: tbs_cert_l1 -> let Netstring_tstring.Tstring_polybox(ops,s) = box in let (k, version_asn1) = Netasn1.decode_ber_poly ~pos ~len ops s in if k <> len then fail(); (Some version_asn1, tbs_cert_l1) | _ -> (None, tbs_cert_l0) in let version = match version_asn1 with | Some (Integer i) -> let version = get_int i in if version < 0 || version > 2 then fail(); version+1 | Some _ -> fail() | None -> 1 in let sig_algo = parse_algo_id sig_algo_asn1 in let cert_serial_int, sigtoo_algo_asn1, issuer_asn1, validity_asn1, subject_asn1, subjectpki_asn1, tbs_cert_l2 = match tbs_cert_l1 with | (Integer cert_serial_int) :: algoIdent_asn1 :: issuer_asn1 :: validity_asn1 :: subject_asn1 :: subjectpki_asn1 :: tbs_cert_l2 -> (cert_serial_int, algoIdent_asn1, issuer_asn1, validity_asn1, subject_asn1, subjectpki_asn1, tbs_cert_l2) | _ -> fail() in let cert_serial_str = get_int_repr cert_serial_int in let sigtoo_algo = parse_algo_id sigtoo_algo_asn1 in let sig_algo_ok = fst sig_algo = fst sigtoo_algo && match snd sig_algo, snd sigtoo_algo with | Some p1, Some p2 -> Netasn1.Value.equal p1 p2 | None, None -> true | _ -> false in let () = if not sig_algo_ok then fail() in let issuer = new x509_dn_from_ASN1 issuer_asn1 in let subject = new x509_dn_from_ASN1 subject_asn1 in let not_before, not_after = match validity_asn1 with | Seq [ not_before_asn1; not_after_asn1 ] -> (parse_time not_before_asn1, parse_time not_after_asn1) | _ -> fail() in let pubkey_algo, pubkey_data = match subjectpki_asn1 with | Seq [ algo_asn1; Bitstring bits ] -> (parse_algo_id algo_asn1, bits) | _ -> fail() in let issuer_uqid_asn1, tbs_cert_l3 = (* implicitly tagged *) match tbs_cert_l2 with | Tagptr(Context, 1, Primitive, box, pos, len) :: tbs_cert_l3 -> let Netstring_tstring.Tstring_polybox(ops, s) = box in let n, issuer_uqid_asn1 = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.Bitstring in if n <> len then fail(); (Some issuer_uqid_asn1, tbs_cert_l3) | Tag(Context, 1, Primitive, issuer_uqid_asn1) :: tbs_cert_l3 -> (Some issuer_uqid_asn1, tbs_cert_l3) | _ -> (None, tbs_cert_l2) in let issuer_uqid_bits = map_opt (function | Bitstring bits -> bits | _ -> fail() ) issuer_uqid_asn1 in let () = if issuer_uqid_bits <> None && version < 2 then fail() in let subject_uqid_asn1, tbs_cert_l4 = (* implicitly tagged *) match tbs_cert_l3 with | Tagptr(Context, 2, Primitive, box, pos, len) :: tbs_cert_l4 -> let Netstring_tstring.Tstring_polybox(ops, s) = box in let n, subject_uqid_asn1 = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.Bitstring in if n <> len then fail(); (Some subject_uqid_asn1, tbs_cert_l4) | Tag(Context, 2, Primitive, subject_uqid_asn1) :: tbs_cert_l4 -> (Some subject_uqid_asn1, tbs_cert_l4) | _ -> (None, tbs_cert_l3) in let subject_uqid_bits = map_opt (function | Bitstring bits -> bits | _ -> fail() ) subject_uqid_asn1 in let () = if subject_uqid_bits <> None && version < 2 then fail() in let exts_asn1 = (* explicitly tagged *) match tbs_cert_l4 with | [ Tag(Context, 3, Constructed, exts_asn1) ] -> Some exts_asn1 | [ Tagptr(Context, 3, Constructed, box, pos, len) ] -> let Netstring_tstring.Tstring_polybox(ops, s) = box in let (k, exts_asn1) = Netasn1.decode_ber_poly ~pos ~len ops s in if k <> len then fail(); Some exts_asn1 | [] -> None | _ -> fail() in let extensions = match exts_asn1 with | Some(Seq l) -> if l = [] then fail(); List.map (fun seq -> match seq with | Seq [ OID oid; Octetstring extval ] -> (oid, extval, false) | Seq [ OID oid; Bool crit; Octetstring extval ] -> (oid, extval, crit) | _ -> fail() ) l | Some _ -> fail() | None -> [] in let () = if extensions <> [] && version < 3 then fail() in ( object(self) method version = version method serial_number = cert_serial_str method issuer = issuer method issuer_unique_id = issuer_uqid_bits method subject = subject method subject_unique_id = subject_uqid_bits method signature = sig_value_bits method signature_algorithm = sig_algo method valid_not_before = not_before method valid_not_after = not_after method public_key = pubkey_data method public_key_algorithm = pubkey_algo method extensions = extensions end ) class x509_certificate_from_DER s = let fail() = failwith "Netx509.x509_certificate_from_DER" in let n, asn1 = try Netasn1.decode_ber s with _ -> fail() in let () = if n <> String.length s then fail() in x509_certificate_from_ASN1 asn1 module CE = struct let ce k = [| 2; 5; 29; k |] let pe k = [| 1; 3; 6; 1; 5; 5; 7; 1; k |] let ce_authority_key_identifier = ce 35 let ce_subject_key_identifier = ce 14 let ce_key_usage = ce 15 let ce_certificate_policies = ce 32 let ce_any_policy = Array.append (ce 32) [| 0 |] let ce_policy_mappings = ce 33 let ce_subject_alt_name = ce 17 let ce_issuer_alt_name = ce 18 let ce_subject_directory_attributes = ce 9 let ce_basic_constraints = ce 19 let ce_name_constraints = ce 30 let ce_policy_constraints = ce 36 let ce_ext_key_usage = ce 37 let ce_crl_distribution_points = ce 31 let ce_inhibit_any_policy = ce 54 let ce_freshest_crl = ce 46 let ce_authority_info_access = pe 1 let ce_subject_info_access = pe 11 let certificate_extensions = [ ce_authority_key_identifier, "authorityKeyIdentifier"; ce_subject_key_identifier, "subjectKeyIdentifier"; ce_key_usage, "keyUsage"; ce_certificate_policies, "certificatePolicies"; ce_any_policy, "anyPolicy"; ce_policy_mappings, "policyMappinggs"; ce_subject_alt_name, "subjectAltName"; ce_issuer_alt_name, "issuerAltName"; ce_subject_directory_attributes, "subjectDirectoryAttributes"; ce_basic_constraints, "basicConstraints"; ce_name_constraints, "nameConstraints"; ce_policy_constraints, "policyConstraints"; ce_ext_key_usage, "extKeyUsage"; ce_crl_distribution_points, "cRLDistributionPoints"; ce_inhibit_any_policy, "inhibitAnyPolicy"; ce_freshest_crl, "freshestCRL"; ce_authority_info_access, "authorityInfoAccess"; ce_subject_info_access, "subjectInfoAccess" ] end type ext_key_usage_flag = [ `Server_auth | `Client_auth | `Code_signing | `Email_protection | `Time_stamping | `OCSP_signing | `Unknown ] module KP = struct let kp k = [| 1; 3; 6; 1; 5; 5; 7; 3; k |] let kp_server_auth = kp 1 let kp_client_auth = kp 2 let kp_code_signing = kp 3 let kp_email_protection = kp 4 let kp_time_stamping = kp 8 let kp_ocsp_signing = kp 9 let ext_key_purposes = [ kp_server_auth, `Server_auth, "serverAuth"; kp_client_auth, `Client_auth, "clientAuth"; kp_code_signing, `Code_signing, "codeSigning"; kp_email_protection, `Email_protection, "emailProtection"; kp_time_stamping, `Time_stamping, "timeStamping"; kp_ocsp_signing, `OCSP_signing, "OCSPSigning"; ] end type authority_access_description_flag = [ `CA_issuers | `OCSP | `Unknown ] type subject_access_description_flag = [ `CA_repository | `Time_stamping | `Unknown ] type access_description_flag = [ authority_access_description_flag | subject_access_description_flag ] module AD = struct let ad k = [| 1; 3; 6; 1; 5; 5; 7; 48; k |] let ad_ca_issuers = ad 2 let ad_ocsp = ad 1 let ad_ca_repository = ad 5 let ad_time_stamping = ad 3 let access_descriptions = [ ad_ca_issuers, `CA_issuers, "caIssuers"; ad_ocsp, `OCSP, "ocsp"; ad_ca_repository, `CA_repository, "caRepository"; ad_time_stamping, `Time_stamping, "timeStamping"; ] end type general_name = [ `Other_name of oid * Netasn1.Value.value | `Rfc822_name of string | `DNS_name of string | `X400_address of Netasn1.Value.value | `Directory_name of directory_name | `Edi_party_name of string option * string | `Uniform_resource_identifier of string | `IP_address of Unix.socket_domain * Unix.inet_addr * Unix.inet_addr | `Registered_ID of oid ] let find_extension oid exts = try let (_, data, critical) = List.find (fun (xoid, _, _) -> xoid = oid) exts in (data, critical) with Not_found -> raise (Extension_not_found oid) let check_critical_exts oids exts = let ht = Hashtbl.create 20 in List.iter (fun oid -> Hashtbl.add ht oid ()) oids; List.for_all (fun (oid, _, critical) -> critical && not(Hashtbl.mem ht oid)) exts let directory_string_from_ASN1 v = Netdn.directory_string_from_ASN1 v let resolve_explicit_tag fail = function | Tag(_,_,_,v) -> v | Tagptr(_,_,_,box,pos,len) -> let Netstring_tstring.Tstring_polybox(ops, s) = box in let (k, inner) = Netasn1.decode_ber_poly ~pos ~len ops s in if k <> len then fail(); inner | _ -> assert false let resolve_implicit_tag fail t = function | Tag(_,_,_,v) -> v | Tagptr(_,_,pc,box,pos,len) -> let Netstring_tstring.Tstring_polybox(ops, s) = box in let (k,inner) = Netasn1.decode_ber_contents_poly ~pos ~len ops s pc t in if k <> len then fail(); inner | _ -> assert false let general_name_from_ASN1 v : general_name = let fail() = failwith "Netx509.general_name_from_ASN1: parse_error" in let parse_other_name v = match v with | Seq [ OID oid; (* explicitly tagged *) ( Tag(Context, 0, Constructed, _) | Tagptr(Context, 0, Constructed, _, _, _) ) as tagged_other_val ] -> let other_val = resolve_explicit_tag fail tagged_other_val in `Other_name(oid, other_val) | _ -> fail() in let parse_rfc822_name v = match v with | IA5String u -> `Rfc822_name u | _ -> fail() in let parse_dns_name v = match v with | IA5String u -> `DNS_name u | _ -> fail() in let parse_url v = match v with | IA5String u -> `Uniform_resource_identifier u | _ -> fail() in let parse_edi_party_name v = match v with | Seq [ ( Tag(Context, 0, Constructed, _) | Tagptr(Context, 0, Constructed, _, _, _)) as tagged_assigner; ( Tag(Context, 1, Constructed, _) | Tagptr(Context, 1, Constructed, _, _, _)) as tagged_party ] -> let v_assigner = resolve_explicit_tag fail tagged_assigner in let v_party = resolve_explicit_tag fail tagged_party in let assigner = directory_string_from_ASN1 v_assigner in let party = directory_string_from_ASN1 v_party in `Edi_party_name(Some assigner, party) | Seq [ ( Tag(Context, 1, Constructed, _) | Tagptr(Context, 1, Constructed, _, _, _) ) as tagged_party ] -> let v_party = resolve_explicit_tag fail tagged_party in let party = directory_string_from_ASN1 v_party in `Edi_party_name(None, party) | _ -> fail() in let parse_ip_address v = match v with | Octetstring u -> if String.length u = 8 then let addr = String.sub u 0 4 in let mask = String.sub u 4 4 in `IP_address(Unix.PF_INET, Netsys.inet_addr_of_protostring addr, Netsys.inet_addr_of_protostring mask) else if String.length u = 32 then let addr = String.sub u 0 16 in let mask = String.sub u 16 16 in `IP_address(Unix.PF_INET6, Netsys.inet_addr_of_protostring addr, Netsys.inet_addr_of_protostring mask) else fail() | _ -> fail() in let parse_registered_id v = match v with | OID oid -> `Registered_ID oid | _ -> fail() in (* implicitly tagged except for directory strings *) match v with | Tagptr(Context, 0, Primitive, box, pos, len) -> (* other_name *) let Netstring_tstring.Tstring_polybox(ops, s) = box in let k, w = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.Seq in if k <> len then fail(); parse_other_name w | Tag(Context, 0, Primitive, w) -> parse_other_name w | Tagptr(Context, 1, Primitive, box, pos, len) -> (* rfc822_name *) let Netstring_tstring.Tstring_polybox(ops, s) = box in let k, w = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.IA5String in if k <> len then fail(); parse_rfc822_name w | Tag(Context, 1, Primitive, w) -> parse_rfc822_name w | Tagptr(Context, 2, Primitive, box, pos, len) -> (* dns_name *) let Netstring_tstring.Tstring_polybox(ops, s) = box in let k, w = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.IA5String in if k <> len then fail(); parse_dns_name w | Tag(Context, 2, Primitive, w) -> parse_dns_name w | Tagptr(Context, 3, Primitive, box, pos, len) -> (* x400_address *) let Netstring_tstring.Tstring_polybox(ops, s) = box in let k, w = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.IA5String in if k <> len then fail(); `X400_address w | Tag(Context, 3, Primitive, w) -> `X400_address w | ( Tag(Context, 4, Constructed, _) | Tagptr(Context, 4, Constructed, _, _, _)) as tagged -> (* directory_name *) (* This is EXPLICIT because a name is an untagged choice type (see section 31.2.7 in X.690 (2008)) *) let w = resolve_explicit_tag fail tagged in `Directory_name(new x509_dn_from_ASN1 w) | Tagptr(Context, 5, Primitive, box, pos, len) -> (* edi_party_name *) let Netstring_tstring.Tstring_polybox(ops, s) = box in let k, w = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.Seq in if k <> len then fail(); parse_edi_party_name w | Tag(Context, 5, Primitive, w) -> parse_edi_party_name w | Tagptr(Context, 6, Primitive, box, pos, len) -> (* uniform_resource_identifier *) let Netstring_tstring.Tstring_polybox(ops, s) = box in let k, w = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.IA5String in if k <> len then fail(); parse_url w | Tag(Context, 6, Primitive, w) -> parse_url w | Tagptr(Context, 7, Primitive, box, pos, len) -> (* ip_address *) let Netstring_tstring.Tstring_polybox(ops, s) = box in let k, w = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.Octetstring in if k <> len then fail(); parse_ip_address w | Tag(Context, 7, Primitive, w) -> parse_ip_address w | Tagptr(Context, 8, Primitive, box, pos, len) -> (* registered_id *) let Netstring_tstring.Tstring_polybox(ops, s) = box in let k, w = Netasn1.decode_ber_contents_poly ~pos ~len ops s Primitive Netasn1.Type_name.OID in if k <> len then fail(); parse_registered_id w | Tag(Context, 8, Primitive, w) -> parse_registered_id w | _ -> fail() let general_names_from_ASN1 v = match v with | Seq l -> List.map general_name_from_ASN1 l | _ -> failwith "Netx509.general_names_from_ASN1: parse error" let parse_subject_alt_name s = let n, v = Netasn1.decode_ber s in if n <> String.length s then failwith "Netx509.parse_subject_alt_name"; general_names_from_ASN1 v let parse_issuer_alt_name s = let n, v = Netasn1.decode_ber s in if n <> String.length s then failwith "Netx509.parse_issuer_alt_name"; general_names_from_ASN1 v type authority_key_identifier = { aki_key_identifier : string option; aki_authority_cert_issuer : general_name list; aki_authority_cert_serial_number : string option; } let parse_authority_key_identifier s = let fail () = failwith "Netx509.parse_authority_key_identifier" in let parse_keyid = function | Octetstring s -> s | _ -> fail() in let parse_serno = function | Integer i -> get_int_repr i | _ -> fail() in let k, v = Netasn1.decode_ber s in if k <> String.length s then fail(); match v with | Seq l1 -> let keyid_opt, l2 = match l1 with (* implicitly tagged *) | ( ( Tagptr(Context, 0, Primitive, _, _, _) | Tag(Context, 0, Primitive, _) ) as tagged_keyid ) :: l2 -> let v_keyid = resolve_implicit_tag fail Netasn1.Type_name.Octetstring tagged_keyid in let keyid = parse_keyid v_keyid in Some keyid, l2 | _ -> None, l1 in let names, l3 = match l2 with (* implicitly tagged *) | ( ( Tagptr(Context, 1, Constructed, _, _, _) | Tag(Context, 1, Constructed, _) ) as tagged_names ) :: l3 -> let v_names = resolve_implicit_tag fail Netasn1.Type_name.Seq tagged_names in let names = general_names_from_ASN1 v_names in names, l3 | _ -> [], l2 in let serno_opt = match l3 with (* implicitly tagged *) | [ ( Tagptr(Context, 2, Primitive, _, _, _) | Tag(Context, 2, Primitive, _) ) as tagged_serno ] -> let v_serno = resolve_implicit_tag fail Netasn1.Type_name.Integer tagged_serno in let serno = parse_serno v_serno in Some serno | [] -> None | _ -> fail() in { aki_key_identifier = keyid_opt; aki_authority_cert_issuer = names; aki_authority_cert_serial_number = serno_opt } | _ -> fail() let parse_subject_key_identifier s = let fail() = failwith "Netx509.parse_subject_key_identifier" in let k, v = Netasn1.decode_ber s in if k <> String.length s then fail(); match v with | Octetstring s -> s | _ -> fail() type key_usage_flag = [ `Digital_signature | `Non_repudiation | `Key_encipherment | `Data_encipherment | `Key_agreement | `Key_cert_sign | `Crl_sign | `Encipher_only | `Decipher_only ] let parse_key_usage s = let fail() = failwith "Netx509.parse_key_usage" in let k, v = Netasn1.decode_ber s in if k <> String.length s then fail(); match v with | Bitstring b -> if get_bitstring_size b <> 9 then fail(); let bits = get_bitstring_bits b in ( match bits with | [| digital_signature; non_repudiation; key_encipherment; data_encipherment; key_agreement; key_cert_sign; crl_sign; encipher_only; decipher_only; |] -> let l = [ `Digital_signature, digital_signature; `Non_repudiation, non_repudiation; `Key_encipherment, key_encipherment; `Data_encipherment, data_encipherment; `Key_agreement, key_agreement; `Key_cert_sign, key_cert_sign; `Crl_sign, crl_sign; `Encipher_only, encipher_only; `Decipher_only, decipher_only ] in List.map fst (List.filter (fun (_, flag) -> flag) l) | _ -> fail() ) | _ -> fail() let attribute_from_ASN1 v = let fail() = failwith "Netx509.attribute_from_ASN1" in match v with | Seq [ OID oid; Seq l ] -> (oid, l) | _ -> fail() let attributes_from_ASN1 v = let fail() = failwith "Netx509.attributes_from_ASN1" in match v with | Seq l -> List.map attribute_from_ASN1 l | _ -> fail() let parse_subject_directory_attributes s = let fail() = failwith "Netx509.parse_subject_directory_attributes" in let n, v = Netasn1.decode_ber s in if n <> String.length s then fail(); attributes_from_ASN1 v let parse_basic_constraints s = let fail() = failwith "Netx509.parse_basic_constraints" in let n, v = Netasn1.decode_ber s in if n <> String.length s then fail(); match v with | Seq [] -> (false, None) | Seq [ Bool ca ] -> (ca, None) | Seq [ Integer path_len ] -> (false, Some(get_int path_len)) | Seq [ Bool ca; Integer path_len ] -> (ca, Some(get_int path_len)) | _ -> fail() let parse_ext_key_usage s = let fail() = failwith "Netx509.parse_ext_key_usage" in let n, v = Netasn1.decode_ber s in if n <> String.length s then fail(); match v with | Seq l -> let oids = List.map (function OID oid -> oid | _ -> fail()) l in List.map (fun oid -> try let (_, flag, _) = List.find (fun (o, _, _) -> o = oid) KP.ext_key_purposes in (oid, flag) with Not_found -> (oid, `Unknown) ) oids | _ -> fail() let parse_info_access s = let fail() = failwith "Netx509.parse_info_access" in let n, v = Netasn1.decode_ber s in if n <> String.length s then fail(); match v with | Seq l -> List.map (fun u -> match u with | Seq [ OID oid; v_gen_name ] -> let gen_name = general_name_from_ASN1 v_gen_name in let flag = try let _, flag, _ = List.find (fun (o,_,_) -> o = oid) AD.access_descriptions in flag with Not_found -> `Unknown in (oid, flag, gen_name) | _ -> fail() ) l | _ -> fail() let parse_authority_info_access s = let l = parse_info_access s in List.map (fun (oid, flag, name) -> match flag with | #authority_access_description_flag as flag' -> (oid, flag', name) | _ -> (oid, `Unknown, name) ) l let parse_subject_info_access s = let l = parse_info_access s in List.map (fun (oid, flag, name) -> match flag with | #subject_access_description_flag as flag' -> (oid, flag', name) | _ -> (oid, `Unknown, name) ) l ocamlnet-4.1.2/src/netstring/netx509_pubkey.ml0000644000175000017500000004176312731530350017707 0ustar gerdgerdtype oid = Netoid.t type alg_id = Alg_id of oid * Netasn1.Value.value option type pubkey = { pubkey_type : alg_id; pubkey_data : Netasn1.Value.bitstring_value; } type hash_function = [ `SHA_1 | `SHA_224 | `SHA_256 | `SHA_384 | `SHA_512 ] type maskgen_function = [ `MGF1 of hash_function ] #ifdef HAVE_EXTENSIVE_VARIANTS type alg_param = .. type alg_param += #else type alg_param = #endif | P_PSS of hash_function * maskgen_function * int | P_OAEP of hash_function * maskgen_function * string type encrypt_alg = Encrypt of oid * alg_param option type sign_alg = Sign of oid * alg_param option type kex_alg = Kex of oid * alg_param option type privkey = Privkey of string * string let decode_pubkey_from_der s = let module V = Netasn1.Value in let n, v = Netasn1.decode_ber s in if n <> String.length s then failwith "Netx509_pubkey.decode_pubkey_from_der"; match v with | V.Seq [ V.Seq s_keytype; V.Bitstring pubkey_data ] -> let pubkey_type = match s_keytype with | [ V.OID oid ] -> Alg_id(oid, None) | [ V.OID oid; params ] -> Alg_id(oid, Some params) | _ -> failwith "Netx509_pubkey.decode_pubkey_from_der" in { pubkey_type; pubkey_data } | _ -> failwith "Netx509_pubkey.decode_pubkey_from_der" let encode_pubkey_to_der pk = let module V = Netasn1.Value in let Alg_id(oid, params) = pk.pubkey_type in let v_params = match params with | None -> [] | Some p -> [p] in let v = V.Seq [ V.Seq (V.OID oid :: v_params); V.Bitstring pk.pubkey_data ] in let b = Netbuffer.create 80 in ignore(Netasn1_encode.encode_ber b v); Netbuffer.contents b let read_pubkey_from_pem ch = let l = Netascii_armor.parse [ "PUBLIC KEY", `Base64 ] ch in match l with | [] -> failwith "Netx509_pubkey.read_pubkey_from_pem: no key found" | [_, `Base64 msg] -> decode_pubkey_from_der msg#value | _ -> failwith "Netx509_pubkey.read_pubkey_from_pem: several keys found" let key_types = [ "RSA"; "DSA"; "DH"; "EC"; "KEA"; "EDDSA" ] let read_privkey_from_pem ch = let suffix = " PRIVATE KEY" in let spec = List.map (fun ty -> (ty ^ suffix, `Base64)) key_types in let l = Netascii_armor.parse spec ch in match l with | [] -> failwith "Netx509_pubkey.read_privkey_from_pem: no key found" | [ty, `Base64 msg] -> let n1 = String.length ty in let n2 = String.length suffix in let fmt = String.sub ty 0 (n1 - n2) in Privkey(fmt, msg#value) | _ -> failwith "Netx509_pubkey.read_privkey_from_pem: several keys found" let hash_functions = let module V = Netasn1.Value in [ `SHA_1, V.Seq [ V.OID [| 1; 3; 14; 3; 2; 26 |]; V.Null ]; `SHA_224, V.Seq [ V.OID [| 2; 16; 840; 1; 101; 3; 4; 2; 4 |]; V.Null ]; `SHA_256, V.Seq [ V.OID [| 2; 16; 840; 1; 101; 3; 4; 2; 1 |]; V.Null ]; `SHA_384, V.Seq [ V.OID [| 2; 16; 840; 1; 101; 3; 4; 2; 2 |]; V.Null ]; `SHA_512, V.Seq [ V.OID [| 2; 16; 840; 1; 101; 3; 4; 2; 3 |]; V.Null ]; ] let hash_size = [ `SHA_1, 20; `SHA_224, 28; `SHA_256, 32; `SHA_384, 48; `SHA_512, 64 ] let maskgen_functions = let module V = Netasn1.Value in let mfg1_oid = [| 1; 2; 840; 113549; 1; 8 |] in List.map (fun (h, h_asn1) -> (`MGF1 h, V.Seq [ V.OID mfg1_oid; h_asn1 ]) ) hash_functions module Key = struct let rsa_key = [| 1; 2; 840; 113549; 1; 1; 1 |] let rsassa_pss_key = [| 1; 2; 840; 113549; 1; 1; 10 |] let rsaes_oaep_key = [| 1; 2; 840; 113549; 1; 1; 7 |] let dsa_key = [| 1; 2; 840; 10040; 4; 1 |] let dh_key = [| 1; 2; 840; 10046; 2; 1 |] let kea_key = [| 2; 16; 840; 1; 101; 2; 1; 1; 22 |] let ec_key = [| 1; 2; 840; 10045; 2; 1 |] let ecdh_key = [| 1; 3; 132; 1; 12 |] let ecmqv_key = [| 1; 3; 132; 1; 13 |] let eddsa_key = [| 1; 3; 101; 100 |] let catalog = [ ( "RSA", [ "RSA"; "PKCS-1"; "RSAES-PKCS1-v1_5" ], "RSA", rsa_key ); ( "RSASSA-PSS", [ "RSASSA-PSS"; "RSASSA-PSS-PKCS1-v2_1" ], "RSA", rsassa_pss_key ); ( "RSAES-OAEP", [ "RSAES-OAEP"; "RSAES-OAEP-PKCS1-v2_1" ], "RSA", rsaes_oaep_key ); ( "DSA", [ "DSA" ], "DSA", dsa_key); ( "DH", [ "DH" ], "DH", dh_key); ( "KEA", [ "KEA" ], "KEA", kea_key); ( "EC", [ "EC" ], "EC", ec_key); ( "ECDH", [ "ECDH" ], "EC", ecdh_key); ( "ECMQV", [ "ECMQV" ], "EC", ecmqv_key); ( "EDDSA", [ "EDDSA" ], "EDDSA", eddsa_key) ] let private_key_format_of_key oid = (* get the private key format for a pubkey OID *) let _, _, format, _ = List.find (fun (_, _, _, o) -> o = oid) catalog in format let pspecified_oid = [| 1; 2; 840; 113549; 1; 1; 9 |] let create_rsassa_pss_alg_id ~hash_function ~maskgen_function ~salt_length ()= let module V = Netasn1.Value in let size = List.assoc hash_function hash_size in let hash_asn1 = if hash_function = `SHA_1 then [] else [ V.ITag(V.Context, 0, List.assoc hash_function hash_functions) ] in let mg_asn1 = if maskgen_function = `MGF1 `SHA_1 then [] else [ V.ITag(V.Context, 1, List.assoc maskgen_function maskgen_functions) ] in let slen_asn1 = if salt_length = size then [] else [ V.ITag(V.Context, 2, V.Integer(V.int salt_length)) ] in let params = V.Seq (hash_asn1 @ mg_asn1 @ slen_asn1) in Alg_id(rsassa_pss_key, Some params) let create_rsassa_pss_key ~hash_function ~maskgen_function ~salt_length key = let Alg_id(oid, _) = key.pubkey_type in if oid <> rsa_key && oid <> rsassa_pss_key then failwith "Netx509_pubkey.Key.create_rsassa_pss_key"; { key with pubkey_type = create_rsassa_pss_alg_id ~hash_function ~maskgen_function ~salt_length () } let parse_rsassa_pss_params v = let module V = Netasn1.Value in try match v with | V.Seq seq -> let seq' = Netasn1.streamline_seq [ (V.Context, 0, Netasn1.Type_name.Seq); (V.Context, 1, Netasn1.Type_name.Seq); (V.Context, 2, Netasn1.Type_name.Integer) ] seq in ( match seq' with | [ v_hf_opt; v_mgf_opt; int_opt ] -> let h = match v_hf_opt with | Some v_hf -> let h, _ = List.find (fun (_, v) -> v_hf = v) hash_functions in h | None -> `SHA_1 in let size = List.assoc h hash_size in let mgf = match v_mgf_opt with | Some v_mgf -> let mgf, _ = List.find (fun (_, v) -> v_mgf = v) maskgen_functions in mgf | None -> `MGF1 `SHA_1 in let salt = match int_opt with | None -> size | Some(V.Integer i) -> V.get_int i | Some _ -> raise Not_found in (h, mgf, salt) | _ -> raise Not_found ) | _ -> raise Not_found with | Not_found | Netasn1.Out_of_range -> failwith "Netx509_pubkey.Key.parse_rsassa_pss_params" let create_rsaes_oaep_alg_id ~hash_function ~maskgen_function ~psource_function () = let module V = Netasn1.Value in let hash_asn1 = if hash_function = `SHA_1 then [] else [ V.ITag(V.Context, 0, List.assoc hash_function hash_functions) ] in let mg_asn1 = if maskgen_function = `MGF1 `SHA_1 then [] else [ V.ITag(V.Context, 1, List.assoc maskgen_function maskgen_functions) ] in let psource_asn1 = if psource_function = "" then [] else [ V.ITag(V.Context, 2, V.Seq [ V.OID pspecified_oid; V.Octetstring psource_function ] ) ] in let params = V.Seq (hash_asn1 @ mg_asn1 @ psource_asn1) in Alg_id(rsaes_oaep_key, Some params) let create_rsaes_oaep_key ~hash_function ~maskgen_function ~psource_function key = let Alg_id(oid, _) = key.pubkey_type in if oid <> rsa_key && oid <> rsaes_oaep_key then failwith "Netx509_pubkey.Key.create_rsaes_oaep_key"; { key with pubkey_type = create_rsaes_oaep_alg_id ~hash_function ~maskgen_function ~psource_function () } let parse_rsaes_oaep_params v = let module V = Netasn1.Value in try match v with | V.Seq seq -> let seq' = Netasn1.streamline_seq [ (V.Context, 0, Netasn1.Type_name.Seq); (V.Context, 1, Netasn1.Type_name.Seq); (V.Context, 2, Netasn1.Type_name.Seq) ] seq in ( match seq' with | [ v_hf_opt; v_mgf_opt; v_psrc_opt ] -> let h = match v_hf_opt with | Some v_hf -> let h, _ = List.find (fun (_, v) -> v_hf = v) hash_functions in h | None -> `SHA_1 in let mgf = match v_mgf_opt with | Some v_mgf -> let mgf, _ = List.find (fun (_, v) -> v_mgf = v) maskgen_functions in mgf | None -> `MGF1 `SHA_1 in let psrc = match v_psrc_opt with | Some (V.Seq [ V.OID oid; V.Octetstring s ]) when oid = pspecified_oid -> s | None -> "" | _ -> raise Not_found in (h, mgf, psrc) | _ -> raise Not_found ) | _ -> raise Not_found with | Not_found | Netasn1.Out_of_range -> failwith "Netx509_pubkey.Key.parse_rsaes_oaep_params" let alg_param_to_asn1 = function | P_PSS(h, mgf, salt) -> let Alg_id(_, p) = create_rsassa_pss_alg_id ~hash_function:h ~maskgen_function:mgf ~salt_length:salt () in p | P_OAEP(h, mgf, psrc) -> let Alg_id(_, p) = create_rsaes_oaep_alg_id ~hash_function:h ~maskgen_function:mgf ~psource_function:psrc () in p end module Encryption = struct let rsa = Encrypt(Key.rsa_key, None) let rsaes_oaep ~hash_function ~maskgen_function ~psource_function = let p = P_OAEP(hash_function, maskgen_function, psource_function) in Encrypt(Key.rsaes_oaep_key,Some p) let catalog = [ ( "RSA", [ "RSA"; "PKCS-1"; "RSAES-PKCS1-v1_5" ], rsa, Key.rsa_key ) ] @ List.map (fun (h,name) -> let full_name = "RSAES-OAEP-MGF1-" ^ name in ( full_name, [ full_name ], rsaes_oaep ~hash_function:h ~maskgen_function:(`MGF1 h) ~psource_function:"", Key.rsaes_oaep_key ) ) [ `SHA_1, "SHA1"; `SHA_224, "SHA224"; `SHA_256, "SHA256"; `SHA_384, "SHA384"; `SHA_512, "SHA512" ] let encrypt_alg_of_pubkey pk = let Alg_id(oid,params) = pk.pubkey_type in if oid = Key.rsa_key then Encrypt(oid, None) else if oid = Key.rsaes_oaep_key then let params' = match params with | Some p -> let (h, mgf, psrc) = Key.parse_rsaes_oaep_params p in Some (P_OAEP(h, mgf, psrc)) | None -> None in Encrypt(oid, params') else failwith "Netx509_pubkey.Encryption.encrypt_alg_of_pubkey: not an \ encryption algorithm" let alg_id_of_encrypt_alg (Encrypt(oid,p_opt)) = let p_opt' = match p_opt with | None -> None | Some p -> Key.alg_param_to_asn1 p in Alg_id(oid, p_opt') let key_oid_of_encrypt_alg alg0 = let _, _, _, pubkey_oid = List.find (fun (_, _, alg, _) -> alg = alg0) catalog in pubkey_oid end module Keyagreement = struct let dh = Kex([| 1; 2; 840; 10046; 2; 1 |], None) let kea = Kex([| 2; 16; 840; 1; 101; 2; 1; 1; 22 |], None) let ec = Kex([| 1; 2; 840; 10045; 2; 1 |], None) let ecdh = Kex([| 1; 3; 132; 1; 12 |], None) let ecmqv = Kex([| 1; 3; 132; 1; 13 |], None) let catalog = [ ( "DH", [ "DH" ], dh, Key.dh_key); ( "KEA", [ "KEA" ], kea, Key.kea_key); ( "EC", [ "EC" ], ec, Key.ec_key); ( "ECDH", [ "ECDH" ], ecdh, Key.ecdh_key); ( "ECMQV", [ "ECMQV" ], ecmqv, Key.ecmqv_key); ] let alg_id_of_kex_alg (Kex(oid,p_opt)) = let p_opt' = match p_opt with | None -> None | Some p -> Key.alg_param_to_asn1 p in Alg_id(oid, p_opt') let key_oid_of_kex_alg alg0 = let _, _, _, pubkey_oid = List.find (fun (_, _, alg, _) -> alg = alg0) catalog in pubkey_oid end module Signing = struct let rsa_with_sha1 = Sign([| 1; 2; 840; 113549; 1; 1; 5 |], None) let rsa_with_sha224 = Sign([| 1; 2; 840; 113549; 1; 1; 14 |], None) let rsa_with_sha256 = Sign([| 1; 2; 840; 113549; 1; 1; 11 |], None) let rsa_with_sha384 = Sign([| 1; 2; 840; 113549; 1; 1; 12 |], None) let rsa_with_sha512 = Sign([| 1; 2; 840; 113549; 1; 1; 13 |], None) let dsa_with_sha1 = Sign([| 1; 2; 840; 10040; 4; 3 |], None) let dsa_with_sha224 = Sign([| 2; 16; 840; 1; 101; 3; 4; 3; 1 |], None) let dsa_with_sha256 = Sign([| 2; 16; 840; 1; 101; 3; 4; 3; 2 |], None) let ecdsa_with_sha1 = Sign([| 1; 2; 840; 10045; 4; 1 |], None) let ecdsa_with_sha224 = Sign([| 1; 2; 840; 10045; 3; 1 |], None) let ecdsa_with_sha256 = Sign([| 1; 2; 840; 10045; 3; 2 |], None) let ecdsa_with_sha384 = Sign([| 1; 2; 840; 10045; 3; 3 |], None) let ecdsa_with_sha512 = Sign([| 1; 2; 840; 10045; 3; 4 |], None) let eddsa = Sign([| 1; 3; 101; 101 |], None) let rsassa_pss ~hash_function ~maskgen_function ~salt_length = Sign([| 1; 2; 840; 113549; 1; 1; 10 |], Some(P_PSS(hash_function, maskgen_function, salt_length))) let catalog = [ ( "RSA-SHA1", [ "RSA-SHA1" ], rsa_with_sha1, Key.rsa_key ); ( "RSA-SHA224", [ "RSA-SHA224" ], rsa_with_sha224, Key.rsa_key ); ( "RSA-SHA256", [ "RSA-SHA256" ], rsa_with_sha256, Key.rsa_key ); ( "RSA-SHA384", [ "RSA-SHA384" ], rsa_with_sha384, Key.rsa_key ); ( "RSA-SHA512", [ "RSA-SHA512" ], rsa_with_sha512, Key.rsa_key ); ( "DSA-SHA1", [ "DSA"; "DSA-SHA1" ], dsa_with_sha1, Key.dsa_key ); ( "DSA-SHA224", [ "DSA-SHA224" ], dsa_with_sha224, Key.dsa_key ); ( "DSA-SHA256", [ "DSA-SHA256" ], dsa_with_sha256, Key.dsa_key ); ( "ECDSA-SHA1", [ "ECDSA-SHA1" ], ecdsa_with_sha1, Key.ec_key ); ( "ECDSA-SHA224", [ "ECDSA-SHA224" ], ecdsa_with_sha224, Key.ec_key ); ( "ECDSA-SHA256", [ "ECDSA-SHA256" ], ecdsa_with_sha256, Key.ec_key ); ( "ECDSA-SHA384", [ "ECDSA-SHA384" ], ecdsa_with_sha384, Key.ec_key ); ( "ECDSA-SHA512", [ "ECDSA-SHA512" ], ecdsa_with_sha512, Key.ec_key ); ( "EDDSA", [ "EDDSA" ], eddsa, Key.eddsa_key ) ] @ List.map (fun (h,name) -> let full_name = "RSASSA-PSS-MGF1-" ^ name in ( full_name, [ full_name ], rsassa_pss ~hash_function:h ~maskgen_function:(`MGF1 h) ~salt_length:(List.assoc h hash_size), Key.rsassa_pss_key ) ) [ `SHA_1, "SHA1"; `SHA_224, "SHA224"; `SHA_256, "SHA256"; `SHA_384, "SHA384"; `SHA_512, "SHA512" ] let alg_id_of_sign_alg (Sign(oid,p_opt)) = let p_opt' = match p_opt with | None -> None | Some p -> Key.alg_param_to_asn1 p in Alg_id(oid, p_opt') let key_oid_of_sign_alg alg0 = let _, _, _, pubkey_oid = List.find (fun (_, _, alg, _) -> alg = alg0) catalog in pubkey_oid end ocamlnet-4.1.2/src/netstring/netascii_armor.ml0000644000175000017500000001260312731530350020102 0ustar gerdgerd(* $Id$ *) type armor_type = [ `Plain | `Base64 | `OpenPGP ] type armored_message = [ `Plain of Netmime.mime_body | `Base64 of Netmime.mime_body | `OpenPGP of Netmime.mime_header * Netmime.mime_body * int ] type armored_message_ro = [ `Plain of Netmime.mime_body_ro | `Base64 of Netmime.mime_body_ro | `OpenPGP of Netmime.mime_header_ro * Netmime.mime_body_ro * int ] type armor_spec = (string * armor_type) list let begin_re = Netstring_str.regexp "^-----BEGIN \\(.*\\)-----[ \t\r]*$" let end_re = Netstring_str.regexp "^-----END \\(.*\\)-----[ \t\r]*$" let cksum_re = Netstring_str.regexp "^=\\([A-Za-z0-9+/=]+\\)[ \t\r]*$" let parse spec (ch : Netchannels.in_obj_channel) = let rec next_begin_boundary() = let line_opt = try Some(ch # input_line()) with End_of_file -> None in match line_opt with | None -> [] | Some line -> if line <> "" && line.[0] = '-' then match Netstring_str.string_match begin_re line 0 with | None -> next_begin_boundary() | Some m -> let tag = Netstring_str.matched_group m 1 line in let armor_type_opt = try Some(List.assoc tag spec) with Not_found -> None in ( match armor_type_opt with | None -> next_begin_boundary() | Some armor_type -> read_message tag armor_type ) else next_begin_boundary() and read_message tag armor_type = let body = new Netmime.memory_mime_body "" in let body_ch = body # open_value_wr() in match armor_type with | `Plain -> let followup code = body_ch # close_out(); match code with | `Error -> [] | `End -> let body_ro = (body :> Netmime.mime_body_ro) in (tag, `Plain body_ro) :: next_begin_boundary() | `End_cksum _ -> assert false in parse_message_body ~enable_checksum:false ~followup tag armor_type body_ch | `Base64 -> let filter = new Netencoding.Base64.decoding_pipe ~accept_spaces:true () in let base64_ch = new Netchannels.output_filter filter body_ch in let followup code = base64_ch # close_out(); body_ch # close_out(); match code with | `Error -> [] | `End -> let body_ro = (body :> Netmime.mime_body_ro) in (tag, `Base64 body_ro) :: next_begin_boundary() | `End_cksum _ -> assert false in parse_message_body ~enable_checksum:false ~followup tag armor_type base64_ch | `OpenPGP -> assert false (* TODO *) and is_expected_end_boundary line tag = match Netstring_str.string_match end_re line 0 with | None -> false | Some m -> let real_tag = Netstring_str.matched_group m 1 line in real_tag = tag and parse_message_body ~enable_checksum ~followup tag armor_type out_ch = let rec parse() = let line_opt = try Some(ch # input_line()) with End_of_file -> None in match line_opt with | None -> followup `Error | Some line -> let checksum_opt = if enable_checksum && line <> "" && line.[0] = '=' then match Netstring_str.string_match cksum_re line 0 with | Some m -> let sum = Netstring_str.matched_group m 1 line in if String.length sum = 4 then try Some(Netencoding.Base64.decode sum) with _ -> None else None | None -> None else None in match checksum_opt with | None -> if is_expected_end_boundary line tag then followup `End else ( out_ch # output_string line; out_ch # output_string "\n"; parse() ) | Some checksum -> assert(String.length checksum = 3); let v = ((Char.code checksum.[0]) lsl 16) lor ((Char.code checksum.[1]) lsl 8) lor (Char.code checksum.[2]) in let line_opt = try Some(ch # input_line()) with End_of_file -> None in ( match line_opt with | None -> followup `Error | Some line -> if is_expected_end_boundary line tag then followup (`End_cksum v) else followup `Error ) in parse() in next_begin_boundary() ocamlnet-4.1.2/src/netstring/netmech_scram_gssapi.ml0000644000175000017500000012474712731530350021276 0ustar gerdgerd(* $Id$ *) (* FIXME: - export_sec_context: the token does not include the sequence numbers, and it does not include the flags *) open Netsys_gssapi open Netgssapi_support open Printf class scram_name (name_string:string) (name_type:oid) = object method otype = ( `Name : [`Name] ) method name_string = name_string method name_type = name_type end type cred = | Cred_server (* there are no server credentials! *) | Cred_client of string * string (* user name, password *) | Cred_none class scram_cred (name:scram_name) (cred:cred) = object method otype = ( `Credential : [`Credential] ) method name = name method cred = cred end type ctx = | Ctx_client of Netmech_scram.client_session | Ctx_server of Netmech_scram.server_session class scram_context ctx (init_flags : ret_flag list) = let valid = ref true in let server_cb = ref "" in let specific_keys = ref None in let seq_nr = ref 0L in let exp_seq_nr = ref None in let flags = ref init_flags in let ctx = ref ctx in object method otype = ( `Context : [ `Context ] ) method valid = !valid method ctx = ctx method delete() = valid := false method server_cb = server_cb method is_acceptor = match !ctx with | Ctx_client _ -> false | Ctx_server _ -> true method specific_keys = match !specific_keys with | Some(k_mic_c,k_mic_s,k_wrap_c,k_wrap_s) -> Some(k_mic_c,k_mic_s,k_wrap_c,k_wrap_s) | None -> let proto_key_opt = match !ctx with | Ctx_client sess -> Netmech_scram.client_protocol_key sess | Ctx_server sess -> Netmech_scram.server_protocol_key sess in (* The usage numbers are defined in RFC 4121 *) (match proto_key_opt with | None -> None | Some proto_key -> let k_mic_c = Netmech_scram.Cryptosystem.derive_keys proto_key 25 in let k_mic_s = Netmech_scram.Cryptosystem.derive_keys proto_key 23 in let k_wrap_c = Netmech_scram.Cryptosystem.derive_keys proto_key 24 in let k_wrap_s = Netmech_scram.Cryptosystem.derive_keys proto_key 22 in (* eprintf "protocol key: %S\n" proto_key; eprintf "k_mic_c.kc: %S\n" k_mic_c.Netmech_scram.kc; eprintf "k_mic_s.kc: %S\n" k_mic_s.Netmech_scram.kc; eprintf "k_wrap_c.ke: %S\n" k_wrap_c.Netmech_scram.ke; eprintf "k_wrap_c.ki: %S\n" k_wrap_c.Netmech_scram.ki; eprintf "k_wrap_s.ke: %S\n" k_wrap_s.Netmech_scram.ke; eprintf "k_wrap_s.ki: %S\n%!" k_wrap_s.Netmech_scram.ki; *) specific_keys := Some(k_mic_c,k_mic_s,k_wrap_c,k_wrap_s); !specific_keys ) method seq_nr = let n = !seq_nr in seq_nr := Int64.succ !seq_nr; n method is_peer_seq_nr_ok n : suppl_status list = match !exp_seq_nr with | None -> exp_seq_nr := Some n; [] | Some e -> if n = e then ( exp_seq_nr := Some (Int64.succ e); [] ) else ( if n < e then [ `Unseq_token ] else [ `Gap_token ] ) method flags = flags end class type client_key_ring = object method password_of_user_name : string -> string method default_user_name : string option end let empty_client_key_ring : client_key_ring = object method password_of_user_name _ = raise Not_found method default_user_name = None end class type server_key_verifier = object method scram_credentials : string -> Netmech_scram.credentials end let empty_server_key_verifier : server_key_verifier = object method scram_credentials _ = raise Not_found end let scram_mech = [| 1; 3; 6; 1; 5; 5; 14 |] (* let as_string (sm,pos,len) = match sm with | `String s -> if pos=0 && len=String.length s then s else String.sub s pos len | `Memory m -> let s = String.create len in Netsys_mem.blit_memory_to_string m pos s 0 len; s *) (* let empty_msg = (`String "",0,0) *) exception Calling_error of calling_error exception Routine_error of routine_error module type PROFILE = sig val client_key_ring : client_key_ring val server_key_verifier : server_key_verifier val scram_profile : Netmech_scram.profile end module Make(P:PROFILE) : Netsys_gssapi.GSSAPI = struct type credential = scram_cred type context = scram_context type name = scram_name exception Credential of credential exception Context of context exception Name of name class type gss_api = [credential, name, context] Netsys_gssapi.poly_gss_api let scram_ret_flags = [ `Mutual_flag; `Conf_flag; `Integ_flag; `Replay_flag; `Sequence_flag ] let no_cred = ( object method otype = `Credential method name = assert false method cred = Cred_none end ) let no_name = ( object method otype = `Name method name_type = [| |] method name_string = "" end ) let interface = object(self) method provider = "Netmech_scram_gssapi.scram_gss_api" method no_credential = no_cred method no_name = no_name method is_no_credential cred = cred#cred = Cred_none method is_no_name name = name#name_type = [| |] method accept_sec_context : 't . context:context option -> acceptor_cred:credential -> input_token:token -> chan_bindings:channel_bindings option -> out:( src_name:name -> mech_type:oid -> output_context:context option -> output_token:token -> ret_flags:ret_flag list -> time_rec:time -> delegated_cred:credential -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~acceptor_cred ~input_token ~chan_bindings ~out () -> let acc_name = new scram_name "@" nt_hostbased_service in let src_name = acc_name in try let cb_data = match chan_bindings with | None -> "" | Some (init_addr, acc_addr, cb_data) -> cb_data in (* We ignore init_addr and acc_addr... CHECK *) if acceptor_cred <> no_cred && acceptor_cred#cred <> Cred_server then raise(Routine_error `No_cred); let context, sess, is_first = match context with | None -> let sess = Netmech_scram.create_server_session P.scram_profile P.server_key_verifier#scram_credentials in let ctx = Ctx_server sess in let context = new scram_context ctx scram_ret_flags in (context # server_cb) := cb_data; (context, sess, true) | Some context -> if not context#valid then raise (Routine_error `No_context); let sess = match !(context#ctx) with | Ctx_server sess -> sess | Ctx_client _ -> raise (Routine_error `No_context) in (context, sess, false) in let eff_input_token = if is_first then (* There is a header *) try let k = ref 0 in let (oid, tok) = Netgssapi_support.wire_decode_token input_token k in if !k <> String.length input_token then raise(Routine_error `Defective_token); if oid <> scram_mech then raise(Routine_error `Bad_mech); tok with | Failure _ -> raise(Routine_error `Defective_token); else input_token in (* The following call usually does not raise exceptions. Error codes are stored inside sess *) let sess = Netmech_scram.server_recv_message sess eff_input_token in let output_context = Some context in let sess, output_token = Netmech_scram.server_emit_message sess in context # ctx := Ctx_server sess; if Netmech_scram.server_error_flag sess then ( out ~src_name ~mech_type:scram_mech ~output_context ~output_token ~ret_flags:scram_ret_flags ~time_rec:`Indefinite ~delegated_cred:no_cred ~minor_status:0l ~major_status:(`None,`Failure,[]) () ) else if Netmech_scram.server_finish_flag sess then ( (* Finally check channel bindings: *) let scram_cb = match Netmech_scram.server_channel_binding sess with | `GSSAPI d -> d | _ -> assert false in if scram_cb <> !(context # server_cb) then raise(Routine_error `Bad_bindings); let ret_flags = [`Prot_ready_flag; `Trans_flag] @ scram_ret_flags in context # flags := ret_flags; out ~src_name ~mech_type:scram_mech ~output_context ~output_token ~ret_flags ~time_rec:`Indefinite ~delegated_cred:no_cred ~minor_status:0l ~major_status:(`None,`None,[]) () ) else ( out ~src_name ~mech_type:scram_mech ~output_context ~output_token ~ret_flags:scram_ret_flags ~time_rec:`Indefinite ~delegated_cred:no_cred ~minor_status:0l ~major_status:(`None,`None,[`Continue_needed]) () ) with | Calling_error code -> out ~src_name ~mech_type:scram_mech ~output_context:None ~output_token:"" ~ret_flags:scram_ret_flags ~time_rec:`Indefinite ~delegated_cred:no_cred ~minor_status:0l ~major_status:(code,`None,[]) () | Routine_error code -> out ~src_name ~mech_type:scram_mech ~output_context:None ~output_token:"" ~ret_flags:scram_ret_flags ~time_rec:`Indefinite ~delegated_cred:no_cred ~minor_status:0l ~major_status:(`None,code,[]) () method private get_client_cred user = (* or Not_found *) let pw = P.client_key_ring # password_of_user_name user in let name = new scram_name user nt_user_name in let cred = new scram_cred (name:>name) (Cred_client(user,pw)) in cred method private get_default_client_cred() = (* or Not_found *) match P.client_key_ring # default_user_name with | None -> raise Not_found | Some user -> self # get_client_cred user method acquire_cred : 't . desired_name:name -> time_req:time -> desired_mechs:oid_set -> cred_usage:cred_usage -> out:( cred:credential -> actual_mechs:oid_set -> time_rec:time -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~desired_name ~time_req ~desired_mechs ~cred_usage ~out () -> let error code = out ~cred:no_cred ~actual_mechs:[] ~time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,code,[]) () in match cred_usage with | `Initiate -> (* For clients *) if List.mem scram_mech desired_mechs then ( let out_client_cred user = try let cred = self#get_client_cred user in out ~cred:(cred :> credential) ~actual_mechs:[ scram_mech ] ~time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,`None,[]) () with | Not_found -> error `No_cred in (* Expect nt_user_name: *) if desired_name # name_type = Netsys_gssapi.nt_user_name then ( let user = desired_name # name_string in out_client_cred user ) else ( if desired_name = no_name then ( (* maybe we have a default: *) match P.client_key_ring # default_user_name with | None -> error `No_cred | Some user -> out_client_cred user ) else error `Bad_nametype ) ) else error `Bad_mech | `Accept -> (* For server: Effectively there are no credentials. So we accept any desired_name. *) if List.mem scram_mech desired_mechs then ( let server_name = new scram_name "@" nt_hostbased_service in let cred = new scram_cred (server_name :> name) Cred_server in out ~cred:(cred :> credential) ~actual_mechs:[ scram_mech ] ~time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,`None,[]) () ) else error `Bad_mech | `Both -> (* Not supported - credentials are either for the client or for the server *) out ~cred:no_cred ~actual_mechs:[] ~time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,`Bad_nametype,[]) () method add_cred : 't . input_cred:credential -> desired_name:name -> desired_mech:oid -> cred_usage:cred_usage -> initiator_time_req:time -> acceptor_time_req:time -> out:( output_cred:credential -> actual_mechs:oid_set -> initiator_time_rec:time -> acceptor_time_rec:time -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~input_cred ~desired_name ~desired_mech ~cred_usage ~initiator_time_req ~acceptor_time_req ~out () -> (* More or less it is not possible to add to credentials - we have here only one mechanism. So, the only thing to do here is to create the right error message. *) let error code = out ~output_cred:no_cred ~actual_mechs:[] ~initiator_time_rec:`Indefinite ~acceptor_time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,code,[]) () in let add cred = if scram_mech = desired_mech then error `Duplicate_element else error `Bad_mech in if input_cred = no_cred then ( self # acquire_cred ~desired_name:(desired_name :> name) ~time_req:`Indefinite ~desired_mechs:[desired_mech] ~cred_usage ~out:( fun ~cred ~actual_mechs ~time_rec ~minor_status ~major_status () -> let (_,code,_) = major_status in if code = `None then add cred else error code ) () ) else add input_cred method canonicalize_name : 't . input_name:name -> mech_type:oid -> out:( output_name:name -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~input_name ~mech_type ~out () -> let error code = out ~output_name:no_name ~minor_status:0l ~major_status:(`None,code,[]) () in if mech_type <> scram_mech then error `Bad_mech else out ~output_name:(input_name :> name) ~minor_status:0l ~major_status:(`None,`None,[]) () method compare_name : 't . name1:name -> name2:name -> out:( name_equal:bool -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~name1 ~name2 ~out () -> let equal = name1 # name_type <> nt_anonymous && name2 # name_type <> nt_anonymous && (name1 = name2 || (name1#name_type = name2#name_type && name1#name_string = name2#name_string)) in out ~name_equal:equal ~minor_status:0l ~major_status:(`None,`None,[]) () method context_time : 't . context:context -> out:( time_rec:[ `Indefinite | `This of float] -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~out () -> if not context#valid then out ~time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,`No_context,[]) () else out ~time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,`None,[]) () method delete_sec_context : 't . context:context -> out:( minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~out () -> context#delete(); out ~minor_status:0l ~major_status:(`None,`None,[]) () method display_name : 't . input_name:name -> out:( output_name:string -> output_name_type:oid -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~input_name ~out () -> (* We just return the name_string *) out ~output_name:input_name#name_string ~output_name_type:input_name#name_type ~minor_status:0l ~major_status:(`None,`None,[]) () method display_minor_status : 't . status_value:minor_status -> mech_type: oid -> out:( status_strings: string list -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~status_value ~mech_type ~out () -> out ~status_strings:[""] ~minor_status:0l ~major_status:(`None,`None,[]) () method export_name : 't . name:name -> out:( exported_name:string -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~name ~out () -> let s1 = encode_exported_name name#name_type name#name_string in let s2 = encode_exported_name scram_mech s1 in out ~exported_name:s2 ~minor_status:0l ~major_status:(`None,`None,[]) () method export_sec_context : 't . context:context -> out:( interprocess_token:interprocess_token -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~out () -> (* FIXME: Maybe we should also export the seq_nr *) if not context#valid then out ~interprocess_token:"" ~minor_status:0l ~major_status:(`None,`No_context,[]) () else ( try let interprocess_token = match !(context#ctx) with | Ctx_client sess -> "C" ^ Netmech_scram.client_export sess | Ctx_server sess -> "S" ^ Netmech_scram.server_export sess in out ~interprocess_token ~minor_status:0l ~major_status:(`None,`None,[]) () with | Failure _ -> out ~interprocess_token:"" ~minor_status:0l ~major_status:(`None,`Unavailable,[]) () ) method get_mic : 't . context:context -> qop_req:qop -> message:message -> out:( msg_token:token -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~qop_req ~message ~out () -> if not context#valid then out ~msg_token:"" ~minor_status:0l ~major_status:(`None,`No_context,[]) () else ( (* Reject any QOP: *) if qop_req <> 0l then out ~msg_token:"" ~minor_status:0l ~major_status:(`None,`Bad_QOP,[]) () else ( let sk_opt = context # specific_keys in match sk_opt with | None -> out ~msg_token:"" ~minor_status:0l ~major_status:(`None,`No_context,[]) () | Some (k_mic_c,k_mic_s,k_wrap_c,k_wrap_s) -> let sk_mic = if context#is_acceptor then k_mic_s else k_mic_c in let sequence_number = context # seq_nr in let sent_by_acceptor = context # is_acceptor in let token = Netgssapi_support.create_mic_token ~sent_by_acceptor ~acceptor_subkey:false ~sequence_number ~get_mic:( Netmech_scram.Cryptosystem.get_mic_mstrings sk_mic) ~message in out ~msg_token:token ~minor_status:0l ~major_status:(`None,`None,[]) () ) ) method import_name : 't . input_name:string -> input_name_type:oid -> out:( output_name:name -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~input_name ~input_name_type ~out () -> let out_name name_string name_type = let n = new scram_name name_string name_type in out ~output_name:(n :> name) ~minor_status:0l ~major_status:(`None,`None,[]) () in if input_name_type = nt_hostbased_service then try let (_service,_host) = parse_hostbased_service input_name in out_name input_name nt_hostbased_service with | _ -> out ~output_name:no_name ~minor_status:0l ~major_status:(`None,`Bad_name,[]) () else if input_name_type = nt_user_name then out_name input_name nt_user_name else if input_name_type = nt_export_name then try let k = ref 0 in let (mech_oid,s1) = decode_exported_name input_name k in if !k <> String.length input_name then failwith "too short"; if mech_oid <> scram_mech then out ~output_name:no_name ~minor_status:0l ~major_status:(`None,`Bad_name,[]) () else ( k := 0; let (name_oid,s2) = decode_exported_name s1 k in if !k <> String.length input_name then failwith "too short"; out_name s2 name_oid ) with | Failure _ -> out ~output_name:no_name ~minor_status:0l ~major_status:(`None,`Bad_name,[]) () else if input_name_type = [||] then out_name input_name nt_user_name else out ~output_name:no_name ~minor_status:0l ~major_status:(`None,`Bad_nametype,[]) () method import_sec_context : 't . interprocess_token:interprocess_token -> out:( context:context option -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~interprocess_token ~out () -> let error code = out ~context:None ~minor_status:0l ~major_status:(`None,code,[]) () in let l = String.length interprocess_token in if interprocess_token = "" then error `Defective_token else match interprocess_token.[0] with | 'C' -> let t = String.sub interprocess_token 1 (l-1) in let sess = Netmech_scram.client_import t in let context = new scram_context (Ctx_client sess) scram_ret_flags in out ~context:(Some (context :> context)) ~minor_status:0l ~major_status:(`None,`None,[]) () | 'S' -> let t = String.sub interprocess_token 1 (l-1) in let sess = Netmech_scram.server_import t in let context = new scram_context (Ctx_server sess) scram_ret_flags in out ~context:(Some (context :> context)) ~minor_status:0l ~major_status:(`None,`None,[]) () | _ -> error `Defective_token method indicate_mechs : 't . out:( mech_set:oid_set -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~out () -> out ~mech_set:[ scram_mech ] ~minor_status:0l ~major_status:(`None, `None, []) () method init_sec_context : 't . initiator_cred:credential -> context:context option -> target_name:name -> mech_type:oid -> req_flags:req_flag list -> time_req:float option -> chan_bindings:channel_bindings option -> input_token:token option -> out:( actual_mech_type:oid -> output_context:context option -> output_token:token -> ret_flags:ret_flag list -> time_rec:[ `Indefinite | `This of float ] -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~initiator_cred ~context ~target_name ~mech_type ~req_flags ~time_req ~chan_bindings ~input_token ~out () -> let actual_mech_type = scram_mech in try let cb_data = match chan_bindings with | None -> "" | Some (init_addr, acc_addr, cb_data) -> cb_data in (* We ignore init_addr and acc_addr... CHECK *) let eff_init_cred = if initiator_cred = no_cred then try self # get_default_client_cred() with | Not_found -> raise(Routine_error `No_cred); (* No default *) else initiator_cred in let user, pw = match eff_init_cred # cred with | Cred_client(user,pw) -> (user,pw) | _ -> raise(Routine_error `No_cred) in let context, sess, continuation = match context with | None -> let sess = Netmech_scram.create_client_session P.scram_profile user pw in let ctx = Ctx_client sess in let context = new scram_context ctx scram_ret_flags in Netmech_scram.client_configure_channel_binding sess (`GSSAPI cb_data); (context, sess, false) | Some context -> if not context#valid then raise(Routine_error `No_context); let sess = match !(context#ctx) with | Ctx_client sess -> sess | Ctx_server _ -> raise (Routine_error `No_context) in (context, sess, true) in if mech_type <> [||] && mech_type <> scram_mech then raise(Routine_error `Bad_mech); (* Note that we ignore target_name entirely. It is not needed for SCRAM. *) let sess = if continuation then ( (* this may raise exceptions *) try match input_token with | Some intok -> Netmech_scram.client_recv_message sess intok | None -> raise(Calling_error `Bad_structure) with | Netmech_scram.Invalid_encoding(_,_) -> raise(Routine_error `Defective_token) | Netmech_scram.Invalid_username_encoding(_,_) -> raise(Routine_error `Defective_token) | Netmech_scram.Extensions_not_supported(_,_) -> raise(Routine_error `Failure) | Netmech_scram.Protocol_error _ -> raise(Routine_error `Failure) | Netmech_scram.Invalid_server_signature -> raise(Routine_error `Bad_mic) | Netmech_scram.Server_error e -> ( match e with | `Invalid_encoding | `Extensions_not_supported | `Invalid_proof | `Channel_bindings_dont_match | `Server_does_support_channel_binding | `Channel_binding_not_supported | `Unsupported_channel_binding_type | `Unknown_user | `Invalid_username_encoding | `No_resources | `Other_error | `Extension _ -> raise(Routine_error `Failure) ) ) else sess in if Netmech_scram.client_finish_flag sess then ( context # ctx := Ctx_client sess; let ret_flags = [`Trans_flag; `Prot_ready_flag ] @ scram_ret_flags in context # flags := ret_flags; out ~actual_mech_type ~output_context:(Some (context :> context)) ~output_token:"" ~ret_flags ~time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,`None,[]) () ) else ( let sess, output_token_1 = Netmech_scram.client_emit_message sess in context # ctx := Ctx_client sess; let output_token = if continuation then output_token_1 else Netgssapi_support.wire_encode_token scram_mech output_token_1 in let ret_flags = if Netmech_scram.client_protocol_key sess <> None then `Prot_ready_flag :: scram_ret_flags else scram_ret_flags in context # flags := ret_flags; out ~actual_mech_type ~output_context:(Some (context :> context)) ~output_token ~ret_flags ~time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,`None,[`Continue_needed]) () ) with | Calling_error code -> out ~actual_mech_type ~output_context:None ~output_token:"" ~ret_flags:scram_ret_flags ~time_rec:`Indefinite ~minor_status:0l ~major_status:(code,`None,[]) () | Routine_error code -> out ~actual_mech_type ~output_context:None ~output_token:"" ~ret_flags:scram_ret_flags ~time_rec:`Indefinite ~minor_status:0l ~major_status:(`None,code,[]) () method inquire_context : 't . context:context -> out:( src_name:name -> targ_name:name -> lifetime_req : time -> mech_type:oid -> ctx_flags:ret_flag list -> locally_initiated:bool -> is_open:bool -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~out () -> let error code = out ~src_name:no_name ~targ_name:no_name ~lifetime_req:`Indefinite ~mech_type:scram_mech ~ctx_flags:scram_ret_flags ~locally_initiated:false ~is_open:false ~minor_status:0l ~major_status:(`None, code, []) () in if context # valid then match !(context # ctx) with | Ctx_client sess -> let src_name = new scram_name (Netmech_scram.client_user_name sess) nt_user_name in let src_name = (src_name :> name) in let targ_name = new scram_name "@" nt_hostbased_service in let targ_name = (targ_name :> name) in let is_open = Netmech_scram.client_finish_flag sess in out ~src_name ~targ_name ~lifetime_req:`Indefinite ~mech_type:scram_mech ~ctx_flags:!(context # flags) ~locally_initiated:true ~is_open ~minor_status:0l ~major_status:(`None, `None, []) () | Ctx_server sess -> let src_name = match Netmech_scram.server_user_name sess with | None -> no_name | Some u -> new scram_name u nt_user_name in let src_name = (src_name :> name) in let targ_name = new scram_name "@" nt_hostbased_service in let targ_name = (targ_name :> name) in let is_open = Netmech_scram.server_finish_flag sess in out ~src_name ~targ_name ~lifetime_req:`Indefinite ~mech_type:scram_mech ~ctx_flags:!(context # flags) ~locally_initiated:true ~is_open ~minor_status:0l ~major_status:(`None, `None, []) () else error `No_context method inquire_cred : 't . cred:credential -> out:( name:name -> lifetime: [ `Indefinite | `This of float ] -> cred_usage:cred_usage -> mechanisms:oid_set -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~cred ~out () -> let eff_cred = if cred = no_cred then try self # get_default_client_cred() with | Not_found -> no_cred (* We do not support a default initiator credential *) else cred in if eff_cred = no_cred then out ~name:no_name ~lifetime:`Indefinite ~cred_usage:`Initiate ~mechanisms:[] ~minor_status:0l ~major_status:(`None, `No_cred, []) () else out ~name:eff_cred#name ~lifetime:`Indefinite ~cred_usage:( match eff_cred#cred with | Cred_server -> `Accept | Cred_client _ -> `Initiate | _ -> assert false ) ~mechanisms:[ scram_mech ] ~minor_status:0l ~major_status:(`None, `None, []) () method inquire_cred_by_mech : 't . cred:credential -> mech_type:oid -> out:( name:name -> initiator_lifetime: [ `Indefinite | `This of float ] -> acceptor_lifetime: [ `Indefinite | `This of float ] -> cred_usage:cred_usage -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~cred ~mech_type ~out () -> let error code = out ~name:no_name ~initiator_lifetime:`Indefinite ~acceptor_lifetime:`Indefinite ~cred_usage:`Initiate ~minor_status:0l ~major_status:(`None,code,[]) () in if mech_type <> scram_mech then error `Bad_mech (* CHECK: not documented in RFC 2744 for this function *) else let eff_cred_opt = if cred = no_cred then try Some(self # get_default_client_cred()) with Not_found -> None else Some cred in match eff_cred_opt with | Some eff_cred -> out ~name:eff_cred#name ~initiator_lifetime:`Indefinite ~acceptor_lifetime:`Indefinite ~cred_usage:( match eff_cred#cred with | Cred_server -> `Accept | Cred_client _ -> `Initiate | _ -> assert false ) ~minor_status:0l ~major_status:(`None, `None, []) () | None -> error `No_cred (* No default initiator credentials *) method inquire_mechs_for_name : 't . name:name -> out:( mech_types:oid_set -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~name ~out () -> let l = if name#name_type = nt_hostbased_service || name#name_type = nt_user_name then [ scram_mech ] else [] in out ~mech_types:l ~minor_status:0l ~major_status:(`None,`None,[]) () method inquire_names_for_mech : 't . mechanism:oid -> out:( name_types:oid_set -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~mechanism ~out () -> let l = if mechanism = scram_mech then [ nt_hostbased_service; nt_user_name ] else [] in out ~name_types:l ~minor_status:0l ~major_status:(`None, `None, []) () method process_context_token : 't . context:context -> token:token -> out:( minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~token ~out () -> (* There are no context tokens... *) out ~minor_status:0l ~major_status:(`None,`Defective_token,[]) () method unwrap : 't . context:context -> input_message:message -> output_message_preferred_type:[ `Bytes | `Memory ] -> out:( output_message:message -> conf_state:bool -> qop_state:qop -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~input_message ~output_message_preferred_type ~out () -> let sk_opt = context # specific_keys in let error code = out ~output_message:[] ~conf_state:false ~qop_state:0l ~minor_status:0l ~major_status:(`None,code,[]) () in if not context#valid then error `No_context else match sk_opt with | None -> error `No_context | Some (k_mic_c,k_mic_s,k_wrap_c,k_wrap_s) -> let sk_wrap = if context#is_acceptor then k_wrap_c else k_wrap_s in ( try let (sent_by_acceptor, _, _, tok_seq_nr) = Netgssapi_support.parse_wrap_token_header input_message in if sent_by_acceptor = context#is_acceptor then raise Netmech_scram.Cryptosystem.Integrity_error; let flags = context#is_peer_seq_nr_ok tok_seq_nr in let s = Netgssapi_support.unwrap_wrap_token_conf ~decrypt_and_verify:( Netmech_scram.Cryptosystem.decrypt_and_verify_mstrings sk_wrap) ~token:input_message in out ~output_message:s ~conf_state:true ~qop_state:0l ~minor_status:0l ~major_status:(`None,`None,flags) () with | Netmech_scram.Cryptosystem.Integrity_error -> error `Bad_mic | _ -> (* probable Invalid_argument *) error `Defective_token ) method verify_mic : 't . context:context -> message:message -> token:token -> out:( qop_state:qop -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~message ~token ~out () -> let sk_opt = context # specific_keys in if not context#valid then out ~qop_state:0l ~minor_status:0l ~major_status:(`None,`No_context,[]) () else match sk_opt with | None -> out ~qop_state:0l ~minor_status:0l ~major_status:(`None,`No_context,[]) () | Some (k_mic_c,k_mic_s,k_wrap_c,k_wrap_s) -> let sk_mic = if context#is_acceptor then k_mic_c else k_mic_s in let (sent_by_acceptor,_,tok_seq_nr) = Netgssapi_support.parse_mic_token_header token in let flags = context#is_peer_seq_nr_ok tok_seq_nr in let ok = sent_by_acceptor <> context#is_acceptor && (Netgssapi_support.verify_mic_token ~get_mic:(Netmech_scram.Cryptosystem.get_mic_mstrings sk_mic) ~message ~token) in if ok then out ~qop_state:0l ~minor_status:0l ~major_status:(`None,`None,flags) () else out ~qop_state:0l ~minor_status:0l ~major_status:(`None,`Bad_mic,[]) () method wrap : 't . context:context -> conf_req:bool -> qop_req:qop -> input_message:message -> output_message_preferred_type:[ `Bytes | `Memory ] -> out:( conf_state:bool -> output_message:message -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~conf_req ~qop_req ~input_message ~output_message_preferred_type ~out () -> if not context#valid then out ~conf_state:false ~output_message:[] ~minor_status:0l ~major_status:(`None,`No_context,[]) () else let sk_opt = context # specific_keys in (* Reject any QOP: *) if qop_req <> 0l then out ~conf_state:false ~output_message:[] ~minor_status:0l ~major_status:(`None,`Bad_QOP,[]) () else ( match sk_opt with | None -> out ~conf_state:false ~output_message:[] ~minor_status:0l ~major_status:(`None,`No_context,[]) () | Some (k_mic_c,k_mic_s,k_wrap_c,k_wrap_s) -> let sk_wrap = if context#is_acceptor then k_wrap_s else k_wrap_c in let token = Netgssapi_support.create_wrap_token_conf ~sent_by_acceptor:context#is_acceptor ~acceptor_subkey:false ~sequence_number:context#seq_nr ~get_ec:( Netmech_scram.Cryptosystem.get_ec sk_wrap) ~encrypt_and_sign:( Netmech_scram.Cryptosystem.encrypt_and_sign_mstrings sk_wrap) ~message:input_message in out ~conf_state:true ~output_message:token ~minor_status:0l ~major_status:(`None,`None,[]) () ) method wrap_size_limit : 't . context:context -> conf_req:bool -> qop_req:qop -> req_output_size:int -> out:( max_input_size:int -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~context ~conf_req ~qop_req ~req_output_size ~out () -> (* We have: - 12 bytes for the MIC - the message is padded to a multiple of 16 bytes - the message includes a 16 bytes random header *) let p_size = (req_output_size - 12) / 16 * 16 in let m_size = max 0 (p_size - 16) in out ~max_input_size:m_size ~minor_status:0l ~major_status:(`None,`None,[]) () method duplicate_name : 't . name:'name -> out:( dest_name:'name -> minor_status:minor_status -> major_status:major_status -> unit -> 't ) -> unit -> 't = fun ~name ~out () -> let dest_name = new scram_name name#name_string name#name_type in out ~dest_name ~minor_status:0l ~major_status:(`None,`None,[]) () end end let scram_gss_api ?(client_key_ring = empty_client_key_ring) ?(server_key_verifier = empty_server_key_verifier) profile = let module P = struct let client_key_ring = client_key_ring let server_key_verifier = server_key_verifier let scram_profile = profile end in let module G = Make(P) in (module G : Netsys_gssapi.GSSAPI) ocamlnet-4.1.2/src/netstring/netaddress.ml0000644000175000017500000001371012731530350017237 0ustar gerdgerd(* Addresses indicate the senders and recipients of messages and * correspond to either an individual mailbox or a group of * mailboxes. *) type local_part = string type domain = string type addr_spec = local_part * domain option class mailbox ?(name : string option) (route : string list) (spec : addr_spec) = object method name = match name with Some s -> s | _ -> raise Not_found method route = route method spec = spec end class group (name : string) (mailboxes : mailbox list) = object method name = name method mailboxes = mailboxes end type t = [ `Mailbox of mailbox | `Group of group ] let mbox_addr_spec spec = `Mailbox (new mailbox [] spec) let mbox_route_addr personal (route, spec) = `Mailbox (new mailbox ?name:personal route spec) open Netmime_string let rev = List.rev exception Parse_error of int * string let parse string = let scanner = create_mime_scanner ~specials:specials_rfc822 ~scan_options:[] string in (* manage lookahead token *) let lookahead_et, lookahead = let et, t = Netmime_string.scan_token scanner in ref et, ref t in let next () = let et, t = Netmime_string.scan_token scanner in lookahead_et := et; lookahead := t in let peek () = !lookahead in (* parsing error - some kind of location/error recovery? *) let error s = let pos = Netmime_string.get_pos !lookahead_et in raise (Parse_error (pos, s)) in (* parse a list of elements *) let list elem next acc = next (elem () :: acc) in (* match a special token for a character *) let special c = match peek () with | Special c' when c = c' -> next () | _ -> error (Printf.sprintf "expecting '%c'" c) in (* main entry point *) let rec address_list acc = match peek () with | End -> rev acc | _ -> list address next_address acc and next_address acc = match peek () with | End -> rev acc | Special ',' -> next (); address_list acc | _ -> error "expecting ','" (* RFC-1123 section 5.2.15: syntax definition of "mailbox" is changed to allow route address with no phrase *) and address () = match peek () with | (Atom _ | QString _) -> address1 () | Special '<' -> mbox_route_addr None (route_addr ()) | Special ',' -> next (); address () (* RFC 2822 section 4.4: support for "null" members *) | _ -> error "expecting address" and address1 () = let w0 = word () in match peek () with | Special '@' -> mbox_addr_spec (w0, Some (at_domain ())) | Special ('<'|':') -> address2 (w0) | Special '.' -> next (); mbox_addr_spec (addr_spec [w0]) | (Atom _ | QString _) -> address2 (phrase [w0]) | _ -> error "syntax error" and address2 name = match peek () with | Special '<' -> mbox_route_addr (Some name) (route_addr ()) | Special ':' -> next (); group name | _ -> error "expecting '<' or ':'" and group name = let mboxes = mailbox_list_opt () in special ';'; `Group (new group name mboxes) and mailbox_list_opt () = match peek () with | Special ';' -> [] | _ -> list mailbox next_mailbox [] and next_mailbox acc = match peek () with | Special ',' -> next (); list mailbox next_mailbox acc | _ -> rev acc (* reuse parsing code for address () and filter out group response *) and mailbox () = match address () with | `Mailbox m -> m | _ -> error "expecting mailbox" and route_addr () = special '<'; let x = match peek () with | (Atom _ | QString _) -> let spec = addr_spec [] in ([], spec) | Special '@' -> let r = route () in let spec = addr_spec [] in (r, spec) | _ -> error "expecting local part or route address" in special '>'; x and route () = let r = at_domain_list [] in special ':'; r and addr_spec acc = let lp = local_part acc in match peek () with | Special '@' -> (lp, Some (at_domain ())) | _ -> (lp, None) and local_part acc = list word next_local_part acc and next_local_part acc = match peek () with | Special '.' -> next (); local_part acc | _ -> String.concat "." (rev acc) and at_domain_list acc = list at_domain next_at_domain_list acc and next_at_domain_list acc = match peek () with | Special ',' -> next (); at_domain_list acc | _ -> rev acc and at_domain () = special '@'; domain [] and domain acc = list subdomain next_subdomain acc and next_subdomain acc = match peek () with | Special '.' -> next (); domain acc | _ -> String.concat "." (rev acc) and subdomain () = match peek () with | Atom s -> next (); s | DomainLiteral s -> next (); s | _ -> error "expecting atom or domain" and phrase acc = list word_or_dot next_phrase acc and next_phrase acc = match peek() with | (Atom _ | QString _ | Special '.') -> phrase acc | _ -> String.concat " " (rev acc) (* RFC 2822 section 4.1: support for '.' often used for initials in names *) and word_or_dot () = match peek () with | Atom s -> next (); s | QString s -> next (); s | Special '.' -> next (); "." | _ -> error "expecting atom or quoted-string" and word () = match peek () with | Atom s -> next (); s | QString s -> next (); s | _ -> error "expecting atom or quoted-string" in address_list [] ocamlnet-4.1.2/src/netstring/netchannels_crypto.mli0000644000175000017500000000577412731530350021171 0ustar gerdgerd(* $Id$ *) (** Crypto extensions for {!Netchannels} *) (** {1:tls TLS} *) (** A TLS channel is a layer on top of a bidirectional channel that adds the TLS protocol. *) class type tls_channel = object inherit Netchannels.raw_io_channel method tls_endpoint : Netsys_crypto_types.tls_endpoint end class tls_layer : ?start_pos_in:int -> ?start_pos_out:int -> ?resume:string -> role:[ `Client | `Server ] -> rd:Netchannels.raw_in_channel -> wr:Netchannels.raw_out_channel -> peer_name:string option -> Netsys_crypto_types.tls_config -> tls_channel (** Adds TLS security to an already established connection, here made available as separate channels for input and output. The TLS handshake is done on the first I/O activity (call [flush] to enforce it). [resume]: see {!Netsys_tls.create_file_endpoint}. *) class tls_endpoint : ?start_pos_in:int -> ?start_pos_out:int -> ?resume:string -> role:[ `Client | `Server ] -> peer_name:string option -> Unix.file_descr -> Netsys_crypto_types.tls_config -> tls_channel (** This class is slightly more efficient than [tls_layer], and to preferred if you have direct access to the file descriptors. *) (** {1:symmetric Symmetric Cryptography} *) (** Encrypt or decrypt data while writing to a channel *) class type crypto_out_filter = object inherit Netchannels.out_obj_channel method supports_aead : bool (** Whether the cipher supports authentication, and will provide a MAC *) method mac : unit -> string (** Get the MAC of the processed data *) end (** Encrypt or decrypt data while reading from a channel *) class type crypto_in_filter = object inherit Netchannels.in_obj_channel method supports_aead : bool (** Whether the cipher supports authentication, and will provide a MAC *) method mac : unit -> string (** Get the MAC of the processed data *) end val encrypt_out : Netsys_ciphers.cipher_ctx -> Netchannels.out_obj_channel -> crypto_out_filter (** [let ch2 = encrypt_out ctx ch1]: Writing to [ch2] encrypts the data and writes the ciphertext to [ch1]. Closing [ch2] will flush data and close [ch1]. *) val encrypt_in : Netsys_ciphers.cipher_ctx -> Netchannels.in_obj_channel -> crypto_in_filter (** [let ch2 = encrypt_in ctx ch1]: Reading from [ch2] encrypts the data from [ch1]. Closing [ch2] will close [ch1]. *) val decrypt_out : Netsys_ciphers.cipher_ctx -> Netchannels.out_obj_channel -> crypto_out_filter (** [let ch2 = decrypt_out ctx ch1]: Writing to [ch2] decrypts the data and writes the plaintext to [ch1]. Closing [ch2] will flush data and close [ch1]. *) val decrypt_in : Netsys_ciphers.cipher_ctx -> Netchannels.in_obj_channel -> crypto_in_filter (** [let ch2 = decrypt_in ctx ch1]: Reading from [ch2] decrypts the data from [ch1]. Closing [ch2] will close [ch1]. *) ocamlnet-4.1.2/src/netstring/netx509.mli0000644000175000017500000003046112731530350016472 0ustar gerdgerd(* $Id$ *) (** X.509 certificates *) (** This module defines a parser for X.509 certificates in Internet context (RFC 5280). The basic structure is implemented, and there are also parsers for the most needed extensions. There are several involved formats: - [ASN.1] is the language in which the certificate format is described. When we refer here to ASN.1 we mean tagged values as defined by {!Netasn1.Value.value}. - [DER] is the common binary encoding for ASN.1 values in this context. [DER] is a subset of [BER] (which is implemented by {!Netasn1.decode_ber}). The encoding of ASN.1 values in [BER] is ambiguous, and [DER] specifies the variant to use in order to get a "distinguished" encoding (that's what the "D" stands for), which is needed to get unique digital signatures. - [PEM] is a set of standards for "privacy enhanced mail". The "PEM encoding" of certificates is simply BASE-64 of [DER]. *) type oid = Netoid.t (** OIDs are just integer sequences *) (** Directory names are also known as distinguished names. These are the o=foo,ou=foounit,c=country strings that are used to name certificates. *) class type directory_name = object method name : (oid * Netasn1.Value.value) list list (** This is the raw version of the DN: a sequence of relative DNs, and a relative DN is a set of (type,value) pairs. The types are things like cn, country, organization, ... *) method eq_name : (oid * Netasn1.Value.value) list list (** The name normalized for equality comparisons. In particular, PrintableString values are converted to uppercase, as well as emailAddress attributes. Also, the inner list is sorted by [oid]. *) method string : string (** The DN as string (RFC 4514) *) method eq_string : string (** The [eq_name] converted to string *) end (** An X.509 certificate in decoded form. The is only the public part, i.e. it includes only the various descriptive fields, the public key, and the signature by the issuer. *) class type x509_certificate = object method subject : directory_name (** The DN of the subject *) method subject_unique_id : Netasn1.Value.bitstring_value option (** The unique ID of the subject *) method issuer : directory_name (** The DN of the issuer *) method issuer_unique_id : Netasn1.Value.bitstring_value option (** The unique ID of the issuer *) method version : int (** The "version" field, 1 to 3 *) method serial_number : string (** The "serialNumber" field *) method valid_not_before : float (** Activation time as seconds since the epoch ("notBefore" field) *) method valid_not_after : float (** Expiration time as seconds since the epoch ("notAfter" field) *) method signature : Netasn1.Value.bitstring_value (** The signature *) method signature_algorithm : oid * Netasn1.Value.value option (** The algorithm of the signature (OID, and algorithm-specific parameters) *) method public_key : Netasn1.Value.bitstring_value (** The subject's public key *) method public_key_algorithm : oid * Netasn1.Value.value option (** The algorithm of the public key (OID, and algorithm-specific parameters) *) method extensions : (oid * string * bool) list (** Extensions (version 3 certificates) as triples [(oid, data, critical)]. OIDs can occur several times. *) end (** {2 OIDs for DN attribute types} *) module DN_attributes : sig (** Object identifiers used in distinguished names *) (** This module is an implementation of {!Netdn.AT_LOOKUP}, and can be used with the parser/printer in {!Netdn}. *) (** Attibute types *) val at_name : oid val at_surname : oid val at_givenName : oid val at_initials : oid val at_generationQualifier : oid val at_commonName : oid val at_localityName : oid val at_stateOrProvinceName : oid val at_organizationName : oid val at_organizationalUnitName : oid val at_title : oid val at_dnQualifier : oid val at_countryName : oid val at_serialNumber : oid val at_pseudonym : oid val at_domainComponent : oid val at_emailAddress : oid val at_uid : oid val attribute_types : (oid * string * string list) list (** The above types in the format [(oid, full_name, short_names)] *) val lookup_attribute_type_by_oid : oid -> string * string list (** Looks the OID up, and returns [(full_name, short_names)]. May raise [Not_found]. *) val lookup_attribute_type_by_name : string -> oid * string * string list (** Looks the name up, which can either be a full name or a short name. Returns the whole triple [(oid, full_name, short_names)], or raises [Not_found]. *) end (** {2 Distinguished names} *) module X509_DN_string : Netdn.DN_string (** Parser/printer for distnguished names as they may occur in X.509 certificates *) val lookup_dn_ava : directory_name -> oid -> Netasn1.Value.value (** Find the first relative DN setting this OID (or [Not_found]) *) val lookup_dn_ava_utf8 : directory_name -> oid -> string (** Same as [lookup_dn_ava], but additionally converts the value to UTF-8 *) (** {2 Parsers} *) class x509_dn_from_ASN1 : Netasn1.Value.value -> directory_name (** Returns the DN object for a [Name] entity *) class x509_dn_from_string : string -> directory_name (** Returns the DN object for an RFC 4514-encoded string *) class x509_certificate_from_ASN1 : Netasn1.Value.value -> x509_certificate (** Parses the passed ASN.1 value and returns the certificate object *) class x509_certificate_from_DER : string -> x509_certificate (** Parses the passed DER string and returns the certificate object *) (** {2 Extensions} *) (** Extensions are identified by an OID (found in the following [CE] module), and the value is a DER-encoded ASN.1 value. The parse_* functions take this DER-encoded value and decode them. E.g. get the "authority key identifier": {[ let _, aki_der, _ = List.find (fun (oid,_,_) -> oid = CE.ce_authority_key_identifier) cert#extensions in let aki = parse_authority_key_identifier aki_der ]} Or use [find_extension], as defined below. Note that we don't have parsers for all extensions. *) module CE : sig (** The OIDs of the extensions in RFC 5280 *) val ce_authority_key_identifier : oid val ce_subject_key_identifier : oid val ce_key_usage : oid val ce_certificate_policies : oid val ce_any_policy : oid val ce_policy_mappings : oid val ce_subject_alt_name : oid val ce_issuer_alt_name : oid val ce_subject_directory_attributes : oid val ce_basic_constraints : oid val ce_name_constraints : oid val ce_policy_constraints : oid val ce_ext_key_usage : oid val ce_crl_distribution_points : oid val ce_inhibit_any_policy : oid val ce_freshest_crl : oid val ce_authority_info_access : oid val ce_subject_info_access : oid val certificate_extensions : (oid * string) list (** All the above listed OIDs with their string names (useful for displaying extension types) *) end exception Extension_not_found of oid val find_extension : oid -> (oid * string * bool) list -> string * bool (** [find_extension] is designed to be applied to the result of the [extensions] method of {!Netx509.x509_certificate}: {[ let (data, critical) = find_extension CE.ce:authority_key_identifier cert#extensions ]} It returns the undecoded data string, and the critical flag. Raises [Extension_not_found] if there is no such extension. *) val check_critical_exts : oid list -> (oid * string * bool) list -> bool (** [check_critical_exts list exts]: When an extension is flagged as critical, it must be processed by the communication endpoint. If there is a critical extension that cannot be processed, this is an error. This function checks whether there are any critical extensions in [exts] beyond those in [list], and returns [true] in this case. Use this in software as: {[ let unprocessed_critical = check_critical_exts [ CE.ce_basic_constraints ] cert#extensions ]} and pass the list of all extension OIDs you actually process. You should raise an error if [unprocessed_critical] is true. *) type general_name = [ `Other_name of oid * Netasn1.Value.value | `Rfc822_name of string | `DNS_name of string | `X400_address of Netasn1.Value.value | `Directory_name of directory_name | `Edi_party_name of string option * string | `Uniform_resource_identifier of string | `IP_address of Unix.socket_domain * Unix.inet_addr * Unix.inet_addr | `Registered_ID of oid ] (** General names: - [`Other_name(oid, value)]: the [oid] determines the extension name format - [`Rfc822_name n]: an email address [n] (ASCII encoded) - [`DNS_name n]: an Internet domain [n] (ASCII encoded - no internationalization) - [`X400_address v]: an X.400 address, which is not decoded here and just given as unparsed ASN.1 value [v] - [`Directory_name n]: a directory name [n] (i.e. a name using the syntax of distinguished names) - [`Edi_party_name(assigner,party)], both names as UTF-8 - [`Uniform_resource_identifier uri]: this [uri] (ASCII-encoded, no internationalization) - [`IP_address(dom,addr,mask)]: the address with mask - [`Registered oid]: a symbolical pre-registered name known under [oid] *) type authority_key_identifier = { aki_key_identifier : string option; aki_authority_cert_issuer : general_name list; aki_authority_cert_serial_number : string option; } val parse_authority_key_identifier : string -> authority_key_identifier val parse_subject_key_identifier : string -> string (** Returns the key identifier directly *) type key_usage_flag = [ `Digital_signature | `Non_repudiation | `Key_encipherment | `Data_encipherment | `Key_agreement | `Key_cert_sign | `Crl_sign | `Encipher_only | `Decipher_only ] val parse_key_usage : string -> key_usage_flag list val parse_subject_alt_name : string -> general_name list val parse_issuer_alt_name : string -> general_name list val parse_subject_directory_attributes : string -> (oid * Netasn1.Value.value list) list val parse_basic_constraints : string -> bool * int option type ext_key_usage_flag = [ `Server_auth | `Client_auth | `Code_signing | `Email_protection | `Time_stamping | `OCSP_signing | `Unknown ] val parse_ext_key_usage : string -> (oid * ext_key_usage_flag) list (** Returns the OID as array, and as decoded flag *) (** Key purpose IDs as returned by [parse_ext_key_usage] *) module KP : sig val kp_server_auth : oid val kp_client_auth : oid val kp_code_signing : oid val kp_email_protection : oid val kp_time_stamping : oid val kp_ocsp_signing : oid val ext_key_purposes : (oid * ext_key_usage_flag * string) list end type authority_access_description_flag = [ `CA_issuers | `OCSP | `Unknown ] type subject_access_description_flag = [ `CA_repository | `Time_stamping | `Unknown ] type access_description_flag = [ authority_access_description_flag | subject_access_description_flag ] val parse_authority_info_access : string -> (oid * authority_access_description_flag * general_name) list val parse_subject_info_access : string -> (oid * subject_access_description_flag * general_name) list module AD : sig val ad_ca_issuers : oid val ad_ocsp : oid val ad_ca_repository : oid val ad_time_stamping : oid val access_descriptions : (oid * access_description_flag * string) list end (** Generic parsers *) val general_name_from_ASN1 : Netasn1.Value.value -> general_name (** Parses the general_name structure *) val general_names_from_ASN1 : Netasn1.Value.value -> general_name list (** Parse a sequence of general names *) val directory_string_from_ASN1 : Netasn1.Value.value -> string (** Returns the directory_string as UTF-8 *) val attribute_from_ASN1 : Netasn1.Value.value -> oid * Netasn1.Value.value list (** Parses an attribute *) val attributes_from_ASN1 : Netasn1.Value.value -> (oid * Netasn1.Value.value list) list (** Parses a sequence of attributes *) ocamlnet-4.1.2/src/netstring/netconversion.ml0000644000175000017500000036031612731530350020006 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- *) open Netsys_types open Netaux.ArrayAux exception Malformed_code exception Cannot_represent of int let multibyte_limit = (* 6 *) 50;; (* The longest multibyte character of all supported encodings, * and the longest substitution string. *) let big_slice = (* 3 *) 250;; (* The typical length of slices *) (* Seems to be a good source: ftp://dkuug.dk/i18n/charmaps *) type encoding = [ `Enc_utf8 (* UTF-8 *) | `Enc_utf8_opt_bom | `Enc_java | `Enc_utf16 (* UTF-16 with unspecified endianess (restricted usage) *) | `Enc_utf16_le (* UTF-16 little endian *) | `Enc_utf16_be (* UTF-16 big endian *) | `Enc_utf32 (* UTF-32 with unspecified endianess (restricted usage) *) | `Enc_utf32_le (* UTF-32 little endian *) | `Enc_utf32_be (* UTF-32 big endian *) | `Enc_usascii (* US-ASCII (only 7 bit) *) | `Enc_iso88591 (* ISO-8859-1 *) | `Enc_iso88592 (* ISO-8859-2 *) | `Enc_iso88593 (* ISO-8859-3 *) | `Enc_iso88594 (* ISO-8859-4 *) | `Enc_iso88595 (* ISO-8859-5 *) | `Enc_iso88596 (* ISO-8859-6 *) | `Enc_iso88597 (* ISO-8859-7 *) | `Enc_iso88598 (* ISO-8859-8 *) | `Enc_iso88599 (* ISO-8859-9 *) | `Enc_iso885910 (* ISO-8859-10 *) | `Enc_iso885911 (* ISO-8859-11 *) | `Enc_iso885913 (* ISO-8859-13 *) | `Enc_iso885914 (* ISO-8859-14 *) | `Enc_iso885915 (* ISO-8859-15 *) | `Enc_iso885916 (* ISO-8859-16 *) | `Enc_koi8r (* KOI8-R *) (* http://koi8.pp.ru *) (*| `Enc_koi8u (* KOI8-U *) (* http://www.net.ua/KOI8-U/index.html *)*) | `Enc_jis0201 (* JIS-X-0201 *) (* | `Enc_jis0201_roman (* JIS-X-0201 only roman half *) | `Enc_jis0201_kana (* JIS-X-0201 katakana half remapped to 0x21..XXX *) | `Enc_jis0208_94x94 (* JIS-X-0208 in ISO-2022-style two byte encoding *) | `Enc_jis0212_94x94 (* JIS-X-0212 in ISO-2022-style two byte encoding *) *) | `Enc_eucjp (* EUC-JP *) | `Enc_euckr (* EUC-KR *) (* | `Enc_iso2022 of iso2022_state | `Enc_iso2022jp of iso2022jp_state *) (* Older standards: *) | `Enc_asn1_iso646 (* only the language-neutral subset *) | `Enc_asn1_T61 (* ITU T.61 ("Teletex") *) | `Enc_asn1_printable (* Microsoft: *) | `Enc_windows1250 (* WINDOWS-1250 *) | `Enc_windows1251 (* WINDOWS-1251 *) | `Enc_windows1252 (* WINDOWS-1252 *) | `Enc_windows1253 (* WINDOWS-1253 *) | `Enc_windows1254 (* WINDOWS-1254 *) | `Enc_windows1255 (* WINDOWS-1255 *) | `Enc_windows1256 (* WINDOWS-1256 *) | `Enc_windows1257 (* WINDOWS-1257 *) | `Enc_windows1258 (* WINDOWS-1258 *) (* IBM, ASCII-based: *) | `Enc_cp437 | `Enc_cp737 | `Enc_cp775 | `Enc_cp850 | `Enc_cp852 | `Enc_cp855 | `Enc_cp856 | `Enc_cp857 | `Enc_cp860 | `Enc_cp861 | `Enc_cp862 | `Enc_cp863 | `Enc_cp864 | `Enc_cp865 | `Enc_cp866 (* Russian *) | `Enc_cp869 | `Enc_cp874 | `Enc_cp1006 (* IBM, EBCDIC-based: *) | `Enc_cp037 (* EBCDIC USA Canada *) (* 273: EBCDIC Germany, Austria, * 277: Denmark, Norway, * 278: Finland, Sweden, * 280: Italy, * 284: Spain, Latin America, * 285: United Kingdom, * 297: France, * 871: Iceland, *) | `Enc_cp424 | `Enc_cp500 (* EBCDIC International *) | `Enc_cp875 (* EBCDIC Modern Greek *) | `Enc_cp1026 (* EBCDIC Turkish *) | `Enc_cp1047 (* EBCDIC Latin1, OS 390 System Services *) (* Adobe: *) | `Enc_adobe_standard_encoding | `Enc_adobe_symbol_encoding | `Enc_adobe_zapf_dingbats_encoding (* Apple: *) | `Enc_macroman (* Encoding subset: *) | `Enc_subset of (encoding * (int -> bool)) | `Enc_empty ] ;; type charset = [ `Set_unicode (* The full Unicode repertoire *) | `Set_usascii (* US-ASCII (only 7 bit) *) | `Set_iso88591 (* ISO-8859-1 *) | `Set_iso88592 (* ISO-8859-2 *) | `Set_iso88593 (* ISO-8859-3 *) | `Set_iso88594 (* ISO-8859-4 *) | `Set_iso88595 (* ISO-8859-5 *) | `Set_iso88596 (* ISO-8859-6 *) | `Set_iso88597 (* ISO-8859-7 *) | `Set_iso88598 (* ISO-8859-8 *) | `Set_iso88599 (* ISO-8859-9 *) | `Set_iso885910 (* ISO-8859-10 *) | `Set_iso885911 (* ISO-8859-11 *) | `Set_iso885913 (* ISO-8859-13 *) | `Set_iso885914 (* ISO-8859-14 *) | `Set_iso885915 (* ISO-8859-15 *) | `Set_iso885916 (* ISO-8859-16 *) | `Set_koi8r (* KOI8-R *) | `Set_jis0201 (* JIS-X-0201 *) | `Set_jis0208 (* JIS-X-0208 *) | `Set_jis0212 (* JIS-X-0212 *) | `Set_ks1001 (* KS-X-1001 *) | `Set_asn1_iso646 | `Set_asn1_T61 | `Set_asn1_printable (* Microsoft: *) | `Set_windows1250 (* WINDOWS-1250 *) | `Set_windows1251 (* WINDOWS-1251 *) | `Set_windows1252 (* WINDOWS-1252 *) | `Set_windows1253 (* WINDOWS-1253 *) | `Set_windows1254 (* WINDOWS-1254 *) | `Set_windows1255 (* WINDOWS-1255 *) | `Set_windows1256 (* WINDOWS-1256 *) | `Set_windows1257 (* WINDOWS-1257 *) | `Set_windows1258 (* WINDOWS-1258 *) (* IBM, ASCII-based: *) | `Set_cp437 | `Set_cp737 | `Set_cp775 | `Set_cp850 | `Set_cp852 | `Set_cp855 | `Set_cp856 | `Set_cp857 | `Set_cp860 | `Set_cp861 | `Set_cp862 | `Set_cp863 | `Set_cp864 | `Set_cp865 | `Set_cp866 | `Set_cp869 | `Set_cp874 | `Set_cp1006 (* IBM, EBCDIC-based: *) | `Set_cp037 | `Set_cp424 | `Set_cp500 | `Set_cp875 | `Set_cp1026 | `Set_cp1047 (* Adobe: *) | `Set_adobe_standard_encoding | `Set_adobe_symbol_encoding | `Set_adobe_zapf_dingbats_encoding (* Apple: *) | `Set_macroman ] ;; let ascii_compat_encodings = [ `Enc_utf8; `Enc_utf8_opt_bom; `Enc_java; `Enc_usascii; `Enc_iso88591; `Enc_iso88592; `Enc_iso88593; `Enc_iso88594; `Enc_iso88595; `Enc_iso88596; `Enc_iso88597; `Enc_iso88598; `Enc_iso88599; `Enc_iso885910; `Enc_iso885911; `Enc_iso885913; `Enc_iso885914; `Enc_iso885915; `Enc_iso885916; `Enc_koi8r; `Enc_windows1250; `Enc_windows1251; `Enc_windows1252; `Enc_windows1253; `Enc_windows1254; `Enc_windows1255; `Enc_windows1256; `Enc_windows1257; `Enc_windows1258; `Enc_cp437; `Enc_cp737; `Enc_cp775; `Enc_cp850; `Enc_cp852; `Enc_cp855; `Enc_cp856; `Enc_cp857; `Enc_cp860; `Enc_cp861; `Enc_cp862; `Enc_cp863; `Enc_cp864; `Enc_cp865; `Enc_cp866; `Enc_cp869; `Enc_cp874; `Enc_cp1006; `Enc_eucjp; `Enc_euckr; `Enc_macroman; ] ;; let rec is_ascii_compatible = function | `Enc_subset(e,_) -> is_ascii_compatible e | e -> List.mem e ascii_compat_encodings ;; let rec is_single_byte = function `Enc_utf8 | `Enc_utf8_opt_bom | `Enc_java | `Enc_utf16 | `Enc_utf16_le | `Enc_utf16_be | `Enc_utf32 | `Enc_utf32_le | `Enc_utf32_be -> false | `Enc_eucjp -> false | `Enc_euckr -> false | `Enc_subset(e,_) -> is_single_byte e | _ -> true ;; let punct_re = Netstring_str.regexp "[-_.]";; let ibm_re = Netstring_str.regexp "^IBM\\([0-9]+\\)$";; let year_re = Netstring_str.regexp ":[0-9][0-9][0-9][0-9]$";; let norm_enc_name e = (* Removes some punctuation characters from e; uppercase; * converts "IBM#" to "CP#"; drops ":YEAR" suffixes *) let e1 = String.uppercase e in let e2 = Netstring_str.global_replace punct_re "" e1 in let e3 = Netstring_str.global_replace year_re "" e2 in match Netstring_str.string_match ibm_re e3 0 with Some r -> "CP" ^ Netstring_str.matched_group r 1 e3 | None -> e3 ;; let names = (* The first name is the official name, the other are aliases. * The aliases must not contain any of the punctuation characters * - _ . * `Enc_subset is missing in this list, of course. * * http://www.iana.org/assignments/character-sets * * A good reference is also: * http://www.firstobject.com/character-set-name-alias-code-page.htm *) [ `Enc_utf16, [ "UTF-16"; "UTF16"; "UCS2"; "ISO10646UCS2" ]; `Enc_utf16_be, [ "UTF-16BE"; "UTF16BE" ]; `Enc_utf16_le, [ "UTF-16LE"; "UTF16LE" ]; `Enc_utf32, [ "UTF-32"; "UTF32"; "UCS4"; "ISO10646UCS4" ]; `Enc_utf32_be, [ "UTF-32BE"; "UTF32BE" ]; `Enc_utf32_le, [ "UTF-32LE"; "UTF32LE" ]; `Enc_utf8, [ "UTF-8"; "UTF8" ]; `Enc_utf8_opt_bom, [ "UTF-8"; "UTF8" ]; `Enc_java, [ "UTF-8-JAVA"; "UTF8JAVA"; "JAVA" ]; `Enc_usascii, [ "US-ASCII"; "USASCII"; "ASCII"; "ISO646US"; "CP367"; "ISOIR6"; "ANSIX341968" ]; `Enc_iso88591, [ "ISO-8859-1"; "ISO88591"; "LATIN1"; "CP819"; "ISOIR100" ]; `Enc_iso88592, [ "ISO-8859-2"; "ISO88592"; "LATIN2"; "ISOIR101"; "CP912" ]; `Enc_iso88593, [ "ISO-8859-3"; "ISO88593"; "LATIN3"; "ISOIR109" ]; `Enc_iso88594, [ "ISO-8859-4"; "ISO88594"; "LATIN4"; "ISOIR110" ]; `Enc_iso88595, [ "ISO-8859-5"; "ISO88595"; "CYRILLIC"; "ISOIR144"; "CP915" ]; `Enc_iso88596, [ "ISO-8859-6"; "ISO88596"; "ARABIC"; "ECMA114"; "ASMO708"; "ISOIR127"; "CP1089" ]; `Enc_iso88597, [ "ISO-8859-7"; "ISO88597"; "GREEK"; "GREEK8"; "ELOT928"; "ECMA118"; "ISOIR126"; "CP813" ]; `Enc_iso88598, [ "ISO-8859-8"; "ISO88598"; "HEBREW"; "ISOIR138"; "CP916" ]; `Enc_iso88599, [ "ISO-8859-9"; "ISO88599"; "LATIN5"; "ISOIR148"; "CP920" ]; `Enc_iso885910, [ "ISO-8859-10"; "ISO885910"; "LATIN6"; "ISOIR157" ]; `Enc_iso885911, [ "ISO-8859-11"; "ISO885911"; ]; `Enc_iso885913, [ "ISO-8859-13"; "ISO885913"; "LATIN7" ]; `Enc_iso885914, [ "ISO-8859-14"; "ISO885914"; "LATIN8"; "ISOIR199"; "ISOCELTIC" ]; `Enc_iso885915, [ "ISO-8859-15"; "ISO885915"; "LATIN9"; "ISOIR203" ]; `Enc_iso885916, [ "ISO-8859-16"; "ISO885916"; "LATIN10"; "SR14111"; "ROMANIAN"; "ISOIR226" ]; `Enc_koi8r, [ "KOI8-R"; "KOI8R"; "CP878" ]; `Enc_jis0201, [ "JIS_X0201"; "JIS0201"; "JISX0201"; "X0201" ]; `Enc_eucjp, [ "EUC-JP"; "EUCJP"; ]; `Enc_euckr, [ "EUC-KR"; "EUCKR"; ]; `Enc_windows1250, [ "WINDOWS-1250"; "WINDOWS1250" ]; `Enc_windows1251, [ "WINDOWS-1251"; "WINDOWS1251" ]; `Enc_windows1252, [ "WINDOWS-1252"; "WINDOWS1252" ]; `Enc_windows1253, [ "WINDOWS-1253"; "WINDOWS1253" ]; `Enc_windows1254, [ "WINDOWS-1254"; "WINDOWS1254" ]; `Enc_windows1255, [ "WINDOWS-1255"; "WINDOWS1255" ]; `Enc_windows1256, [ "WINDOWS-1256"; "WINDOWS1256" ]; `Enc_windows1257, [ "WINDOWS-1257"; "WINDOWS1257" ]; `Enc_windows1258, [ "WINDOWS-1258"; "WINDOWS1258" ]; `Enc_cp437, [ "IBM437"; "CP437" ]; `Enc_cp737, [ "IBM737"; "CP737" ]; `Enc_cp775, [ "IBM775"; "CP775" ]; `Enc_cp850, [ "IBM850"; "CP850" ]; `Enc_cp852, [ "IBM852"; "CP852" ]; `Enc_cp855, [ "IBM855"; "CP855" ]; `Enc_cp856, [ "IBM856"; "CP856" ]; `Enc_cp857, [ "IBM857"; "CP857" ]; `Enc_cp860, [ "IBM860"; "CP860" ]; `Enc_cp861, [ "IBM861"; "CP861"; "CPIS" ]; `Enc_cp862, [ "IBM862"; "CP862" ]; `Enc_cp863, [ "IBM863"; "CP863" ]; `Enc_cp864, [ "IBM864"; "CP864" ]; `Enc_cp865, [ "IBM865"; "CP865" ]; `Enc_cp866, [ "IBM866"; "CP866" ]; `Enc_cp869, [ "IBM869"; "CP869"; "CPGR" ]; `Enc_cp874, [ "IBM874"; "CP874" ]; `Enc_cp1006, [ "IBM1006"; "CP1006" ]; `Enc_cp037, [ "IBM037"; "CP037"; "EBCDICCPUS"; "EBCDICCPCA"; "EBCDICCPWT"; "EBCDICCPNL" ]; `Enc_cp424, [ "IBM424"; "CP424"; "EBCDICCPHE" ]; `Enc_cp500, [ "IBM500"; "CP500"; "EBCDICCPBE"; "EBCDICCPCH" ]; `Enc_cp875, [ "IBM875"; "CP875" ]; `Enc_cp1026, [ "IBM1026"; "CP1026" ]; `Enc_cp1047, [ "IBM1047"; "CP1047"; ]; `Enc_adobe_standard_encoding, [ "ADOBE-STANDARD-ENCODING"; "ADOBESTANDARDENCODING" ]; `Enc_adobe_symbol_encoding, [ "ADOBE-SYMBOL-ENCODING"; "ADOBESYMBOLENCODING" ]; `Enc_adobe_zapf_dingbats_encoding, [ "ADOBE-ZAPF-DINGBATS-ENCODING"; "ADOBEZAPFDINGBATSENCODING" ]; `Enc_macroman, [ "MACINTOSH"; "MACINTOSH"; "MACROMAN"; "MAC" ]; (* The ASN.1 encodings are intentionally not member of this list *) ] ;; let encoding_of_string e = let ne = norm_enc_name e in try fst (List.find (fun (enc, nlist) -> List.mem ne (List.tl nlist)) names ) with Not_found -> failwith "Netconversion.encoding_of_string: unknown encoding" ;; let rec string_of_encoding (e : encoding) = (* If there is a "preferred MIME name", this name is returned (see IANA). *) match e with | `Enc_subset(e,_) -> string_of_encoding e | _ -> try let l = List.assoc e names in List.hd l with Not_found -> assert false (* Because [names] must be complete *) ;; let internal_name (cs : charset) = (* The name used for netdb lookups *) match cs with | `Set_unicode -> "unicode" | `Set_usascii -> "usascii" | `Set_iso88591 -> "iso88591" | `Set_iso88592 -> "iso88592" | `Set_iso88593 -> "iso88593" | `Set_iso88594 -> "iso88594" | `Set_iso88595 -> "iso88595" | `Set_iso88596 -> "iso88596" | `Set_iso88597 -> "iso88597" | `Set_iso88598 -> "iso88598" | `Set_iso88599 -> "iso88599" | `Set_iso885910 -> "iso885910" | `Set_iso885911 -> "iso885911" | `Set_iso885913 -> "iso885913" | `Set_iso885914 -> "iso885914" | `Set_iso885915 -> "iso885915" | `Set_iso885916 -> "iso885916" | `Set_koi8r -> "koi8r" | `Set_jis0201 -> "jis0201" | `Set_jis0208 -> "jis0208" | `Set_jis0212 -> "jis0212" | `Set_ks1001 -> "ks1001" | `Set_asn1_iso646 -> "asn1_iso646" | `Set_asn1_T61 -> "asn1_t61" | `Set_asn1_printable -> "asn1_printable" | `Set_windows1250 -> "windows1250" | `Set_windows1251 -> "windows1251" | `Set_windows1252 -> "windows1252" | `Set_windows1253 -> "windows1253" | `Set_windows1254 -> "windows1254" | `Set_windows1255 -> "windows1255" | `Set_windows1256 -> "windows1256" | `Set_windows1257 -> "windows1257" | `Set_windows1258 -> "windows1258" | `Set_cp437 -> "cp437" | `Set_cp737 -> "cp737" | `Set_cp775 -> "cp775" | `Set_cp850 -> "cp850" | `Set_cp852 -> "cp852" | `Set_cp855 -> "cp855" | `Set_cp856 -> "cp856" | `Set_cp857 -> "cp857" | `Set_cp860 -> "cp860" | `Set_cp861 -> "cp861" | `Set_cp862 -> "cp862" | `Set_cp863 -> "cp863" | `Set_cp864 -> "cp864" | `Set_cp865 -> "cp865" | `Set_cp866 -> "cp866" | `Set_cp869 -> "cp869" | `Set_cp874 -> "cp874" | `Set_cp1006 -> "cp1006" | `Set_cp037 -> "cp037" | `Set_cp424 -> "cp424" | `Set_cp500 -> "cp500" | `Set_cp875 -> "cp875" | `Set_cp1026 -> "cp1026" | `Set_cp1047 -> "cp1047" | `Set_adobe_standard_encoding -> "adobe_standard_encoding" | `Set_adobe_symbol_encoding -> "adobe_symbol_encoding" | `Set_adobe_zapf_dingbats_encoding -> "adobe_zapf_dingbats_encoding" | `Set_macroman -> "macroman" ;; let rec required_charsets (e : encoding) = (* The name is a bit misleading. The function returns the charsets that * correspond to the conversion tables that are required to support the * encoding. *) match e with | `Enc_utf8 | `Enc_utf8_opt_bom | `Enc_java | `Enc_utf16 | `Enc_utf16_le | `Enc_utf16_be | `Enc_utf32 | `Enc_utf32_le | `Enc_utf32_be -> [] | `Enc_usascii -> [] | `Enc_iso88591 -> [] | `Enc_iso88592 -> [ `Set_iso88592 ] | `Enc_iso88593 -> [ `Set_iso88593 ] | `Enc_iso88594 -> [ `Set_iso88594 ] | `Enc_iso88595 -> [ `Set_iso88595 ] | `Enc_iso88596 -> [ `Set_iso88596 ] | `Enc_iso88597 -> [ `Set_iso88597 ] | `Enc_iso88598 -> [ `Set_iso88598 ] | `Enc_iso88599 -> [ `Set_iso88599 ] | `Enc_iso885910 -> [ `Set_iso885910 ] | `Enc_iso885911 -> [ `Set_iso885911 ] | `Enc_iso885913 -> [ `Set_iso885913 ] | `Enc_iso885914 -> [ `Set_iso885914 ] | `Enc_iso885915 -> [ `Set_iso885915 ] | `Enc_iso885916 -> [ `Set_iso885916 ] | `Enc_koi8r -> [ `Set_koi8r ] | `Enc_jis0201 -> [ `Set_jis0201 ] | `Enc_eucjp -> [ `Set_jis0201; `Set_jis0208; `Set_jis0212 ] | `Enc_euckr -> [ `Set_ks1001 ] | `Enc_asn1_iso646 -> [ `Set_asn1_iso646 ] | `Enc_asn1_T61 -> [ `Set_asn1_T61 ] | `Enc_asn1_printable -> [ `Set_asn1_printable ] | `Enc_windows1250 -> [ `Set_windows1250 ] | `Enc_windows1251 -> [ `Set_windows1251 ] | `Enc_windows1252 -> [ `Set_windows1252 ] | `Enc_windows1253 -> [ `Set_windows1253 ] | `Enc_windows1254 -> [ `Set_windows1254 ] | `Enc_windows1255 -> [ `Set_windows1255 ] | `Enc_windows1256 -> [ `Set_windows1256 ] | `Enc_windows1257 -> [ `Set_windows1257 ] | `Enc_windows1258 -> [ `Set_windows1258 ] | `Enc_cp437 -> [ `Set_cp437 ] | `Enc_cp737 -> [ `Set_cp737 ] | `Enc_cp775 -> [ `Set_cp775 ] | `Enc_cp850 -> [ `Set_cp850 ] | `Enc_cp852 -> [ `Set_cp852 ] | `Enc_cp855 -> [ `Set_cp855 ] | `Enc_cp856 -> [ `Set_cp856 ] | `Enc_cp857 -> [ `Set_cp857 ] | `Enc_cp860 -> [ `Set_cp860 ] | `Enc_cp861 -> [ `Set_cp861 ] | `Enc_cp862 -> [ `Set_cp862 ] | `Enc_cp863 -> [ `Set_cp863 ] | `Enc_cp864 -> [ `Set_cp864 ] | `Enc_cp865 -> [ `Set_cp865 ] | `Enc_cp866 -> [ `Set_cp866 ] | `Enc_cp869 -> [ `Set_cp869 ] | `Enc_cp874 -> [ `Set_cp874 ] | `Enc_cp1006 -> [ `Set_cp1006 ] | `Enc_cp037 -> [ `Set_cp037 ] | `Enc_cp424 -> [ `Set_cp424 ] | `Enc_cp500 -> [ `Set_cp500 ] | `Enc_cp875 -> [ `Set_cp875 ] | `Enc_cp1026 -> [ `Set_cp1026 ] | `Enc_cp1047 -> [ `Set_cp1047 ] | `Enc_adobe_standard_encoding -> [ `Set_adobe_standard_encoding ] | `Enc_adobe_symbol_encoding -> [ `Set_adobe_symbol_encoding ] | `Enc_adobe_zapf_dingbats_encoding -> [ `Set_adobe_zapf_dingbats_encoding ] | `Enc_macroman -> [ `Set_macroman ] | `Enc_subset(e',_) -> required_charsets e' | `Enc_empty -> [] ;; let rec same_encoding e1 e2 = match (e1,e2) with (`Enc_subset(e1_sub, f1), `Enc_subset(e2_sub, f2)) -> same_encoding e1_sub e2_sub && f1 == f2 | (_,_) -> e1 = e2 ;; let rec byte_order_mark = function `Enc_utf16_le -> "\255\254" | `Enc_utf16_be -> "\254\255" | `Enc_utf32_le -> "\255\254\000\000" | `Enc_utf32_be -> "\000\000\254\255" | `Enc_subset(e,_) -> byte_order_mark e | _ -> "" ;; let available_input_encodings() = let l = ref [] in List.iter (fun (e,_) -> let charsets = required_charsets e in if List.for_all (fun cs -> Netdb.exists_db ("cmapf." ^ internal_name cs)) charsets then l := e :: !l ) names; !l ;; let available_output_encodings() = let exclude = [ `Enc_utf16; `Enc_utf32 ] in let l = ref [] in List.iter (fun (e,_) -> if not (List.mem e exclude) then begin let charsets = required_charsets e in if List.for_all (fun cs -> Netdb.exists_db ("cmapr." ^ internal_name cs)) charsets then l := e :: !l end ) names; !l ;; let (win32_code_pages : (_ * encoding) list) = [ 65001, `Enc_utf8; 1200, `Enc_utf16_le; 1201, `Enc_utf16_be; 20127, `Enc_usascii; 28591, `Enc_iso88591; 28592, `Enc_iso88592; 28593, `Enc_iso88593; 28594, `Enc_iso88594; 28595, `Enc_iso88595; 28596, `Enc_iso88596; 28597, `Enc_iso88597; 28598, `Enc_iso88598; 28599, `Enc_iso88599; (* `Enc_iso885910 *) (* `Enc_iso885911 *) 28603, `Enc_iso885913; (* `Enc_iso885914 *) 28605, `Enc_iso885915; (* `Enc_iso885916 *) 20866, `Enc_koi8r; (* `Enc_jis0201 *) 20932, `Enc_eucjp; 51949, `Enc_euckr; 1250, `Enc_windows1250; 1251, `Enc_windows1251; 1252, `Enc_windows1252; 1253, `Enc_windows1253; 1254, `Enc_windows1254; 1255, `Enc_windows1255; 1256, `Enc_windows1256; 1257, `Enc_windows1257; 1258, `Enc_windows1258; 437, `Enc_cp437; 737, `Enc_cp737; 775, `Enc_cp775; 850, `Enc_cp850; 852, `Enc_cp852; 855, `Enc_cp855; (* `Enc_cp856 *) 857, `Enc_cp857; 860, `Enc_cp860; 861, `Enc_cp861; 862, `Enc_cp862; 863, `Enc_cp863; 864, `Enc_cp864; 865, `Enc_cp865; 866, `Enc_cp866; 869, `Enc_cp869; 874, `Enc_cp874; (* `Enc_cp1006 *) 37, `Enc_cp037; 20424, `Enc_cp424; 500, `Enc_cp500; 875, `Enc_cp875; 1026, `Enc_cp1026; 1047, `Enc_cp1047; (* `Enc_adobe_standard_encoding *) (* `Enc_adobe_symbol_encoding *) (* `Enc_adobe_zapf_dingbats_encoding *) 10000, `Enc_macroman; ] let user_encoding() = match Sys.os_type with | "Win32" -> let cp = Netsys_win32.get_active_code_page() in ( try Some(List.assoc cp win32_code_pages) with Not_found -> None ) | _ -> ( try let codeset = (Netsys_posix.query_langinfo "").Netsys_posix.nl_CODESET in Some(encoding_of_string codeset) with | _ -> None ) (* Internal conversion interface: * * let (n_char, n_byte, enc') = read_XXX slice_char slice_blen s_in p_in l_in: * * - Scans the bytes from position p_in until the slice is decoded, but at * most until the last position p_in+l_in-1 of the input string s_in, and * decodes the character for the selected encoding. * - "slice_char" is a preallocated array of ints storing the code points * of the characters. It is allowed that "slice_char" is only partially * filled with characters. In this case, there must be a -1 after the * last valid code point. * - "slice_blen" is another "int array" with the same size as "slice_char". * It contains the byte length of every character. It is initialized with * a sequence of ones, so single-byte readers don't have to worry about * this array. * - Returns: * * n_char: the number of decoded characters * * n_byte: the number of scanned bytes ( <= l_in ) * * enc': the new encoding * - In the case of multi-byte encodings it is possible that * the last byte to read at position p_in+l_in-1 is the beginning of * a character. This character is excluded from being decoded. * - Errors: If an invalid byte sequence is found, the exception * Malformed_code_read(_,_,_) is raised. The exception returns the * triple (n_char, n_byte, enc') describing how much could be read * before the reader ran into the bad sequence. slice_char and slice_blen * are only partially initialized, with a (-1) at the end of slice_char. * * let (n_char, n_byte) = * write_XXX slice_char slice_pos slice_length s_out p_out l_out subst * * - Writes the characters found in slice_char to s_out. Only the elements * from slice_pos to slice_pos + slice_length -1 are written. The resulting * bytes are written to s_out from byte position p_out to p_out+l_out-1. * - There must not be a -1 (EOF mark) in the first slice_length characters * of slice_char. * - Only whole characters must be written. * - For code points p that cannot be represented in the output * encoding, the function subst is called. The function must return * the (already encoded) string to substitute. This must be a small string. * - Of course, p >= 0. As special case, p >= 0x110000 may be used to force * that subst is called (it is assumed that max_int can be never * represented). * - Returns: * * n_char: the number of processed characters * * n_byte: the number of written bytes ( <= l_in ) * * let (n_char, n_byte) = * back_XXX s_in range_in range_in_len p_in n_char: * * - The substring of s_in beginning at range_in and with length * range_in_len is considered as the valid range * - The cursor is at byte position p_in and goes n_char characters back * - The routine returns: * * n_char: the characters the cursor was actually moved backwards * * n_byte: the bytes the cursor was actually moved backwards * - The validity of the input encoding needs not to be checked *) exception Malformed_code_read of (int * int * encoding);; (* not exported! *) Callback.register_exception "Netconversion.Malformed_code_read" (Malformed_code_read(0,0,`Enc_empty));; (* Needed by netaccel_c.c *) (* UNSAFE_OPT: A number of functions have been optimized by using * unsafe features of O'Caml (unsafe_get, unsafe_set, unsafe_chr). * These functions have been checked very carefully, and there are * a lot of comments arguing about the correctness of the array * and string accesses. *) type poly_reader = { read : 's . 's Netstring_tstring.tstring_ops -> int array -> int array -> 's -> int -> int -> (int * int * encoding) } let read_iso88591 maxcode enc = (* UNSAFE_OPT *) let read ops slice_char slice_blen s_in p_in l_in = let open Netstring_tstring in assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); let m = min l_in (Array.length slice_char) in let m3 = m/3 in for k3 = 0 to m3-1 do let k = 3*k3 in (* let ch = Char.code s_in.[ p_in + k ] in *) let chars = ops.unsafe_get3 s_in (p_in + k) in let c0 = chars lsr 16 in let c1 = (chars lsr 8) land 0xff in let c2 = chars land 0xff in if c0 > maxcode then ( slice_char.(k) <- (-1); raise(Malformed_code_read(k,k,enc)) ); Array.unsafe_set slice_char k c0; if c1 > maxcode then ( slice_char.(k+1) <- (-1); raise(Malformed_code_read(k+1,k+1,enc)) ); Array.unsafe_set slice_char (k+1) c1; if c2 > maxcode then ( slice_char.(k+2) <- (-1); raise(Malformed_code_read(k+2,k+2,enc)) ); Array.unsafe_set slice_char (k+2) c2; done; for k = 3*m3 to m-1 do let c0 = Char.code (ops.unsafe_get s_in (p_in + k)) in if c0 > maxcode then ( slice_char.(k) <- (-1); raise(Malformed_code_read(k,k,enc)) ); Array.unsafe_set slice_char k c0; done; if m < Array.length slice_char then ( slice_char.(m) <- (-1); ); (m,m,enc) in { read } ;; let read_iso88591_ref = ref read_iso88591;; let get_8bit_to_unicode_map enc = let cs = match required_charsets enc with [ cs ] -> cs | _ -> failwith "get_8bit_to_unicode_map" in let to_unicode = Netmappings.get_to_unicode (internal_name cs) in assert(Array.length to_unicode = 256); to_unicode ;; let read_8bit enc = let m_to_unicode = get_8bit_to_unicode_map enc in (* the 256-byte array mapping the character set to unicode *) let read ops slice_char slice_blen s_in p_in l_in = (* UNSAFE_OPT *) let open Netstring_tstring in assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); let m = min l_in (Array.length slice_char) in let m3 = m/3 in for k3 = 0 to m3-1 do let k = 3*k3 in let chars = ops.unsafe_get3 s_in k in let c0 = chars lsr 16 in let c1 = (chars lsr 8) land 0xff in let c2 = chars land 0xff in let c0_uni = Array.unsafe_get m_to_unicode c0 in if c0_uni < 0 then ( slice_char.(k) <- (-1); raise(Malformed_code_read(k,k,enc)); ); Array.unsafe_set slice_char k c0_uni; let c1_uni = Array.unsafe_get m_to_unicode c1 in if c1_uni < 0 then ( slice_char.(k+1) <- (-1); raise(Malformed_code_read(k+1,k+1,enc)); ); Array.unsafe_set slice_char (k+1) c1_uni; let c2_uni = Array.unsafe_get m_to_unicode c2 in if c2_uni < 0 then ( slice_char.(k+2) <- (-1); raise(Malformed_code_read(k+2,k+2,enc)); ); Array.unsafe_set slice_char (k+2) c2_uni; done; for k = 3*m3 to m-1 do let c0 = Char.code (ops.get s_in k) in let c0_uni = Array.unsafe_get m_to_unicode c0 in if c0_uni < 0 then ( slice_char.(k) <- (-1); raise(Malformed_code_read(k,k,enc)); ); Array.unsafe_set slice_char k c0_uni; done; if m < Array.length slice_char then ( slice_char.(m) <- (-1); ); (m,m,enc) in { read } ;; let read_utf8 is_java = (* UNSAFE_OPT *) let read ops slice_char slice_blen s_in p_in l_in = let open Netstring_tstring in assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); (* k: counts the bytes * n: counts the characters *) let p = ref p_in in let p_max = p_in + l_in in let n = ref 0 in let n_ret = ref (-1) in let malformed_code() = slice_char.( !n ) <- (-1); raise(Malformed_code_read(!n, !p - p_in, `Enc_utf8)); in let slice_length = Array.length slice_char in while !p < p_max && !n < slice_length do let k_inc = (* length of the character in bytes; 0 means: stop *) (* We know: * (1) p_in >= 0 ==> !p >= 0 * (2) !p < p_max = p_in + l_in <= String.length s_in * ==> unsafe get ok *) (* match s_in.[k_in + k] with *) match ops.unsafe_get s_in !p with '\000' -> if is_java then malformed_code(); (* slice_char.(n) <- 0; *) Array.unsafe_set slice_char !n 0; (* ok *) 1 | ('\001'..'\127' as x) -> (* slice_char.(n) <- Char.code x; *) Array.unsafe_set slice_char !n (Char.code x); (* ok *) 1 | ('\128'..'\223' as x) -> if !p+1 >= p_max then 0 else begin (* ==> !p+1 < p_max = p_in + l_in <= String.length s_in * ==> unsafe get ok *) let n1 = Char.code x in let n2 = (* Char.code (s_in.[!p + 1]) *) Char.code(ops.unsafe_get s_in (!p + 1)) in if is_java && (n1 = 0x80 && n2 = 0xc0) then begin (* slice_char.(n) <- 0; *) Array.unsafe_set slice_char !n 0; (* ok *) 2 end else begin if n2 < 128 || n2 > 191 then malformed_code(); let p = ((n1 land 0b11111) lsl 6) lor (n2 land 0b111111) in if p < 128 then malformed_code(); (* slice_char.(n) <- p; *) Array.unsafe_set slice_char !n p; (* ok *) 2 end end | ('\224'..'\239' as x) -> if !p + 2 >= p_max then 0 else begin (* ==> !p+2 < p_max = p_in + l_in <= String.length s_in * ==> unsafe get ok *) let n1 = Char.code x in let n2 = (* Char.code (s_in.[!p + 1]) *) Char.code(ops.unsafe_get s_in (!p + 1)) in let n3 = (* Char.code (s_in.[!p + 2]) *) Char.code(ops.unsafe_get s_in (!p + 2)) in if n2 < 128 || n2 > 191 then malformed_code(); if n3 < 128 || n3 > 191 then malformed_code(); let p = ((n1 land 0b1111) lsl 12) lor ((n2 land 0b111111) lsl 6) lor (n3 land 0b111111) in if p < 0x800 then malformed_code(); if (p >= 0xd800 && p < 0xe000) then (* Surrogate pairs are not supported in UTF-8 *) malformed_code(); if (p >= 0xfffe && p <= 0xffff) then malformed_code(); (* slice_char.(n) <- p; *) Array.unsafe_set slice_char !n p; (* ok *) 3 end | ('\240'..'\247' as x) -> if !p + 3 >= p_max then 0 else begin (* ==> !p+3 < p_max = p_in + l_in <= String.length s_in * ==> unsafe get ok *) let n1 = Char.code x in let chars = ops.unsafe_get3 s_in (!p + 1) in let n2 = chars lsr 16 in let n3 = (chars lsr 8) land 0xff in let n4 = chars land 0xff in if n2 < 128 || n2 > 191 then malformed_code(); if n3 < 128 || n3 > 191 then malformed_code(); if n4 < 128 || n4 > 191 then malformed_code(); let p = ((n1 land 0b111) lsl 18) lor ((n2 land 0b111111) lsl 12) lor ((n3 land 0b111111) lsl 6) lor (n4 land 0b111111) in if p < 0x10000 then malformed_code(); if p >= 0x110000 then (* These code points are not supported. *) malformed_code(); (* slice_char.(n) <- p; *) Array.unsafe_set slice_char !n p; (* ok *) 4 end | _ -> (* Outside the valid range of XML characters *) malformed_code(); in (* If k_inc = 0, the character was partially outside the processed * range of the string, and could not be decoded. *) if k_inc > 0 then begin (* We know: * (1) n >= 0, because n starts with 0 and is only increased * (2) n < Array.length slice_char = Array.length slice_blen * ==> unsafe set ok *) (* slice_blen.(n) <- k_inc; *) Array.unsafe_set slice_blen !n k_inc; (* next iteration: *) p := !p + k_inc; incr n; end else begin (* Stop loop: *) n_ret := !n; n := slice_length; end done; if (!n_ret = (-1)) then n_ret := !n; if !n_ret < slice_length then ( (* EOF marker *) slice_char.(!n_ret) <- (-1); ); (!n_ret,!p-p_in,`Enc_utf8) in { read } ;; let read_utf8_ref = ref read_utf8;; let have_utf8_bom ops s p = let open Netstring_tstring in let c0 = ops.get s (p + 0) in let c1 = ops.get s (p + 1) in let c2 = ops.get s (p + 2) in c0 = '\xEF' && c1 = '\xBB' && c2 = '\xBF' let read_utf8_opt_bom expose_bom = let read ops slice_char slice_blen s_in p_in l_in = let open Netstring_tstring in assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); (* Expect a BOM at the beginning of the text *) if l_in >= 3 then ( if have_utf8_bom ops s_in p_in then ( let p_in1, l_in1 = if expose_bom then p_in, l_in else p_in+3, l_in-3 in let (n_ret, p_ret, enc) = (!read_utf8_ref false).read ops slice_char slice_blen s_in p_in1 l_in1 in let p_ret1 = if expose_bom then p_ret else p_ret+3 in if expose_bom && n_ret >= 1 then slice_char.(0) <- (-3); (n_ret, p_ret1, enc) ) else (!read_utf8_ref false).read ops slice_char slice_blen s_in p_in l_in ) else ( let bom_possible = l_in=0 || (l_in=1 && ops.get s_in 0 = '\xEF') || (l_in=2 && ops.get s_in 0 = '\xEF' && ops.get s_in 1 = '\xBB') in if bom_possible then (0, 0, `Enc_utf8_opt_bom) else (!read_utf8_ref false).read ops slice_char slice_blen s_in p_in l_in ) in { read } ;; let surrogate_offset = 0x10000 - (0xD800 lsl 10) - 0xDC00;; let read_utf16_lebe lo hi n_start enc = (* lo=0, hi=1: little endian * lo=1, hi=0: big endian * n_start: First cell in slice to use *) let read ops slice_char slice_blen s_in p_in l_in = let open Netstring_tstring in assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); let malformed_code k n = slice_char.(n) <- (-1); raise(Malformed_code_read(n,k,enc)) in (* k: counts the bytes * n: counts the characters *) let rec put_loop k n = if k+1 < l_in && n < Array.length slice_char then begin let p = (Char.code (ops.get s_in (p_in + k + lo))) lor ((Char.code (ops.get s_in (p_in + k + hi))) lsl 8) in if p >= 0xd800 && p < 0xe000 then begin (* This is a surrogate pair. *) if k+3 < l_in then begin if p <= 0xdbff then begin let q = (Char.code (ops.get s_in (p_in + k + 2 + lo))) lor ((Char.code (ops.get s_in (p_in + k + 2 + hi))) lsl 8) in if q < 0xdc00 || q > 0xdfff then malformed_code k n; let eff_p = (p lsl 10) + q + surrogate_offset in slice_char.(n) <- eff_p; slice_blen.(n) <- 4; put_loop (k+4) (n+1) end else (* Malformed pair: *) malformed_code k n; end else (n,k) end else (* Normal 2-byte character *) if p = 0xfffe then (* Wrong byte order mark: It is illegal here *) malformed_code k n else begin (* A regular code point *) slice_char.(n) <- p; slice_blen.(n) <- 2; put_loop (k+2) (n+1) end end else (n,k) in let (n,k) = put_loop 0 n_start in if n < Array.length slice_char then ( (* EOF marker *) slice_char.(n) <- (-1); ); (n,k,enc) in { read } ;; let get_endianess ops s_in p_in = let open Netstring_tstring in let c0 = ops.get s_in (p_in + 0) in let c1 = ops.get s_in (p_in + 1) in if c0 = '\254' && c1 = '\255' then `Big_endian else if c0 = '\255' && c1 = '\254' then `Little_endian else `No_BOM ;; (* expose_bom: when true, the BOM is considered as a character and * put as value (-3) into slice_char *) let read_utf16 expose_bom = let read ops slice_char slice_blen s_in p_in l_in = let open Netstring_tstring in assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); (* Expect a BOM at the beginning of the text *) if l_in >= 2 then begin if expose_bom then ( slice_char.(0) <- (-3); slice_blen.(0) <- 0; (* Later corrected *) ); match get_endianess ops s_in p_in with `Big_endian -> let n_start = if expose_bom then 1 else 0 in let (n, k, enc') = (read_utf16_lebe 1 0 n_start `Enc_utf16_be).read ops slice_char slice_blen s_in (p_in+2) (l_in-2) in if n > 0 then slice_blen.(0) <- slice_blen.(0) + 2; (n, k+2, enc') | `Little_endian -> let n_start = if expose_bom then 1 else 0 in let (n, k, enc') = (read_utf16_lebe 0 1 n_start `Enc_utf16_le).read ops slice_char slice_blen s_in (p_in+2) (l_in-2) in if n > 0 then slice_blen.(0) <- slice_blen.(0) + 2; (n, k+2, enc') | `No_BOM -> (* byte order mark missing *) slice_char.(0) <- (-1); raise(Malformed_code_read(0,0,`Enc_utf16)) end else ( slice_char.(0) <- (-1); (0, 0, `Enc_utf16) ) in { read } ;; let read_utf32_lebe little n_start enc = (* little: whether little endian * n_start: First cell in slice to use *) let read ops slice_char slice_blen s_in p_in l_in = let open Netstring_tstring in assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); let malformed_code k n = slice_char.(n) <- (-1); raise(Malformed_code_read(n,k,enc)) in let b0 = if little then 0 else 3 in let b1 = if little then 1 else 2 in let b2 = if little then 2 else 1 in let b3 = if little then 3 else 0 in (* k: counts the bytes * n: counts the characters *) let rec put_loop k n = if k+3 < l_in && n < Array.length slice_char then begin let p3 = Char.code (ops.get s_in (p_in + k + b3)) in if p3 <> 0 then malformed_code k n; let p = (Char.code (ops.get s_in (p_in + k + b0))) lor ((Char.code (ops.get s_in (p_in + k + b1))) lsl 8) lor ((Char.code (ops.get s_in (p_in + k + b2))) lsl 16) in if (p >= 0xD800 && p <= 0xDFFF) || p >= 0x10FFFF then malformed_code k n; if p = 0xfffe then (* Wrong byte order mark: It is illegal here *) malformed_code k n; slice_char.(n) <- p; slice_blen.(n) <- 4; put_loop (k+4) (n+1) end else (n,k) in let (n,k) = put_loop 0 n_start in if n < Array.length slice_char then ( (* EOF marker *) slice_char.(n) <- (-1); ); (n,k,enc) in { read } ;; let get_endianess32 ops s_in p_in = let open Netstring_tstring in let c0 = ops.get s_in (p_in + 0) in let c1 = ops.get s_in (p_in + 1) in let c2 = ops.get s_in (p_in + 2) in let c3 = ops.get s_in (p_in + 3) in if c0 = '\000' && c1 = '\000' && c2 = '\254' && c3 = '\255' then `Big_endian else if c0 = '\255' && c1 = '\254' && c2 = '\000' && c3 = '\000' then `Little_endian else `No_BOM ;; let read_utf32 expose_bom = let read ops slice_char slice_blen s_in p_in l_in = let open Netstring_tstring in assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); (* Expect a BOM at the beginning of the text *) if l_in >= 4 then begin if expose_bom then ( slice_char.(0) <- (-3); slice_blen.(0) <- 0; (* Later corrected *) ); match get_endianess32 ops s_in p_in with `Big_endian -> let n_start = if expose_bom then 1 else 0 in let (n, k, enc') = (read_utf32_lebe false n_start `Enc_utf32_be).read ops slice_char slice_blen s_in (p_in+4) (l_in-4) in if n > 0 then slice_blen.(0) <- slice_blen.(0) + 4; (n, k+4, enc') | `Little_endian -> let n_start = if expose_bom then 1 else 0 in let (n, k, enc') = (read_utf32_lebe true n_start `Enc_utf32_le).read ops slice_char slice_blen s_in (p_in+4) (l_in-4) in if n > 0 then slice_blen.(0) <- slice_blen.(0) + 4; (n, k+4, enc') | `No_BOM -> (* byte order mark missing *) slice_char.(0) <- (-1); raise(Malformed_code_read(0,0,`Enc_utf32)) end else ( slice_char.(0) <- (-1); (0, 0, `Enc_utf32) ) in { read } ;; let read_euc len1 len2 len3 map1 map2 map3 enc = (* Code set 0 is US-ASCII. * Code sets 1, 2, 3 may be anything. lenX = 0: code set is not supported. * lenX is either 0, 1, or 2. *) (* UNSAFE_OPT *) let open Netstring_tstring in assert(len1 >= 0 && len1 <= 2); assert(len2 >= 0 && len2 <= 2); assert(len3 >= 0 && len3 <= 2); let read ops slice_char slice_blen s_in p_in l_in = assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); (* k: counts the bytes * n: counts the characters *) let p = ref p_in in let p_max = p_in + l_in in let n = ref 0 in let n_ret = ref (-1) in let malformed_code() = slice_char.( !n ) <- (-1); raise(Malformed_code_read(!n, !p - p_in, enc)); in let slice_length = Array.length slice_char in while !p < p_max && !n < slice_length do let k_inc = (* length of the character in bytes; 0 means: stop *) (* We know: * (1) p_in >= 0 ==> !p >= 0 * (2) !p < p_max = p_in + l_in <= String.length s_in * ==> unsafe get ok *) (* match s_in.[k_in + k] with *) match ops.unsafe_get s_in !p with '\000'..'\127' as x -> (* US-ASCII *) Array.unsafe_set slice_char !n (Char.code x); (* ok *) 1 | '\142' -> (* Code set 2 *) if len2 = 0 then malformed_code(); if !p+len2 >= p_max then 0 else begin let x1 = Char.code (ops.get s_in (!p + 1)) in let x2 = if len2=1 then 256 else Char.code (ops.get s_in (!p + 2)) in if x1 < 160 || x2 < 160 then malformed_code(); let uni = map2 x1 x2 in Array.unsafe_set slice_char !n uni; (* ok *) len2+1 end | '\143' -> (* Code set 3 *) if len3 = 0 then malformed_code(); if !p+len3 >= p_max then 0 else begin let x1 = Char.code (ops.get s_in (!p + 1)) in let x2 = if len3=1 then 256 else Char.code (ops.get s_in (!p + 2)) in if x1 < 160 || x2 < 160 then malformed_code(); let uni = map3 x1 x2 in Array.unsafe_set slice_char !n uni; (* ok *) len3+1 end | '\160'..'\255' as x1_code -> (* Code set 1 *) if !p+len1 > p_max then 0 else begin let x1 = Char.code x1_code in let x2 = if len1=1 then 256 else Char.code (ops.get s_in (!p + 1)) in if x2 < 160 then malformed_code(); let uni = map1 x1 x2 in Array.unsafe_set slice_char !n uni; (* ok *) len1 end | _ -> (* illegal *) malformed_code() in (* If k_inc = 0, the character was partially outside the processed * range of the string, and could not be decoded. *) if k_inc > 0 then begin (* We know: * (1) n >= 0, because n starts with 0 and is only increased * (2) n < Array.length slice_char = Array.length slice_blen * ==> unsafe set ok *) (* slice_blen.(n) <- k_inc; *) Array.unsafe_set slice_blen !n k_inc; (* next iteration: *) p := !p + k_inc; incr n; end else begin (* Stop loop: *) n_ret := !n; n := slice_length; end done; if (!n_ret = (-1)) then n_ret := !n; if !n_ret < slice_length then ( (* EOF marker *) slice_char.(!n_ret) <- (-1); ); (!n_ret,!p-p_in,enc) in { read } ;; let read_eucjp () = let jis0201 = Netmappings.get_to_unicode "jis0201" in let jis0208 = Netmappings.get_to_unicode "jis0208" in let jis0212 = lazy (Netmappings.get_to_unicode "jis0212") in (* seldom *) let map1 x1 x2 = jis0208.( (x1-160) * 96 + x2 - 160 ) in let map2 x1 _ = jis0201.( x1 ) in let map3 x1 x2 = (Lazy.force jis0212).( (x1-160) * 96 + x2 - 160 ) in read_euc 2 1 2 map1 map2 map3 `Enc_eucjp ;; let read_euckr () = let ks1001 = Netmappings.get_to_unicode "ks1001" in let map x1 x2 = ks1001.( (x1-160) * 96 + x2 - 160 ) in read_euc 2 0 0 map map map `Enc_euckr ;; let read_subset inner_read def = let read ops slice_char slice_blen s_in p_in l_in = let open Netstring_tstring in assert(Array.length slice_char = Array.length slice_blen); assert(p_in >= 0 && p_in + l_in <= ops.length s_in && l_in >= 0); let (n,k,enc') = inner_read.read ops slice_char slice_blen s_in p_in l_in in (* check codepoints: *) for j = 0 to n-1 do if not(def(slice_char.(j))) then ( (* raise Malformed_code_read... *) (* to get enc'' read again: *) let slice_char' = Array.make j (-1) in let slice_blen' = Array.make j 1 in let (n', k', enc'') = try inner_read.read ops slice_char' slice_blen' s_in p_in l_in with Malformed_code_read(_,_,_) -> assert false in assert(n' = j); int_blit slice_char' 0 slice_char 0 j; int_blit slice_blen' 0 slice_blen 0 j; slice_char.(j) <- (-1); raise (Malformed_code_read(j, k', enc'')) ); done; (n,k,enc') in { read } ;; (* * let (n_char, b_byte) = * write_XXX slice_char slice_length s_out p_out l_out subst *) let write_iso88591 maxcode slice_char slice_pos slice_length s_out p_out l_out subst = (* UNSAFE_OPT *) (* Use maxcode=255 for ISO-8859-1, and maxcode=127 for US-ASCII, * and maxcode=(-1) for `Enc_empty. *) assert(p_out >= 0 && p_out + l_out <= Bytes.length s_out && l_out >= 0); assert(slice_pos >= 0 && slice_pos+slice_length <= Array.length slice_char); assert(maxcode <= 255); let n = ref slice_pos in (* index of slice *) let n_ret = ref (-1) in (* returned number of characters *) let n_max = slice_pos + slice_length in let p = ref p_out in (* current output position *) let p_max = p_out + l_out in (* maximum output position *) while ( !n < n_max ) && ( !p < p_max ) do (* We know: * (1) !n >= 0, because it starts with 0 and is only increased * (2) !n < n_max = slice_pos + slice_length <= Array.length slice_char * ==> unsafe get ok *) let ch = Array.unsafe_get slice_char !n in if ch >= 0 && ch <= maxcode then begin (* Because !p < p_max: * !p < p_max = p_out + l_out <= String.length s_out * Furthermore, p_out >= 0, !p >= 0. * ==> unsafe set ok *) (* s_out.[ !p ] <- Char.chr ch; *) Bytes.unsafe_set s_out !p (Char.unsafe_chr ch); incr n; incr p; end else begin assert(ch >= 0); let replacement = subst ch in let l_repl = String.length replacement in if l_repl > multibyte_limit then failwith "Netconversion.write_iso88591: Substitution string too long"; if !p + l_repl <= p_max then begin (* Enough space to store 'replacement': *) Bytes.blit_string replacement 0 s_out !p l_repl; p := !p + l_repl; incr n end else begin (* Exit whole conversion *) n_ret := !n; n := n_max; end end done; if !n_ret >= 0 then (!n_ret - slice_pos, !p - p_out) else (!n - slice_pos, !p - p_out) ;; let get_8bit_from_unicode_map enc = let cs = match required_charsets enc with [ cs ] -> cs | _ -> failwith "get_8bit_from_unicode_map" in let from_unicode = Netmappings.get_from_unicode (internal_name cs) in assert(Array.length from_unicode = 256); from_unicode ;; let write_8bit enc = (* UNSAFE_OPT *) let m_from_unicode = get_8bit_from_unicode_map enc in let m_mask = Array.length m_from_unicode - 1 in fun slice_char slice_pos slice_length s_out p_out l_out subst -> assert(p_out >= 0 && p_out + l_out <= Bytes.length s_out && l_out >= 0); assert(slice_pos >= 0 && slice_pos+slice_length <= Array.length slice_char); let n = ref slice_pos in (* index of slice *) let n_max = slice_pos + slice_length in let k = ref 0 in (* written bytes *) let n_ret = ref (-1) in (* returned number of characters *) while ( !n < n_max ) && ( !k < l_out ) do (* We know: * (1) !n >= 0, because it starts with 0 and is only increased * (2) !n < n_max = slice_pos + slice_length <= Array.length slice * ==> unsafe get ok *) let p = (* slice_char.( !n ) *) Array.unsafe_get slice_char !n in let p' = match Array.unsafe_get m_from_unicode (p land m_mask) with Netmappings.U_nil -> -1 | Netmappings.U_single (p0,q0) -> if p0 = p then q0 else -1 | Netmappings.U_double (p0,q0,p1,q1) -> if p0 = p then q0 else if p1 = p then q1 else -1 | Netmappings.U_array pq -> let r = ref (-1) in let h = ref 0 in while !r < 0 && !h < Array.length pq do if pq.( !h ) = p then r := pq.( !h+1 ) else h := !h + 2 done; !r in (* If p=-1 ==> p'=-1, because -1 is never mapped to any code point *) if p' < 0 then begin if p < 0 then assert false (* EOF mark found *) else begin let replacement = subst p in let l_repl = String.length replacement in if l_repl > multibyte_limit then failwith "Netconversion.write_8bit: Substitution string too long"; if !k + l_repl <= l_out then begin (* Enough space to store 'replacement': *) Bytes.blit_string replacement 0 s_out (p_out + !k) l_repl; k := !k + l_repl; incr n end else begin (* Exit whole conversion *) n_ret := !n; n := n_max; end end end else begin (* Because !k < l_out: * p_out + !k < p_out + l_out <= String.length s_out * Furthermore, p_out >= 0, !k >= 0. * ==> unsafe set ok *) (* s_out.[ p_out + !k ] <- Char.chr p'; *) Bytes.unsafe_set s_out (p_out + !k) (Char.unsafe_chr(p' land 0xff)); incr n; incr k end; done; if !n_ret >= 0 then (!n_ret - slice_pos, !k) else (!n - slice_pos, !k) ;; let write_utf8 is_java slice_char slice_pos slice_length s_out p_out l_out subst = (* UNSAFE_OPT *) assert(p_out >= 0 && p_out + l_out <= Bytes.length s_out && l_out >= 0); assert(slice_pos >= 0 && slice_pos+slice_length <= Array.length slice_char); let n = ref slice_pos in (* index of slice *) let n_max = slice_pos + slice_length in let k = ref 0 in (* written bytes *) let n_ret = ref (-1) in (* returned number of characters *) while ( !n < n_max ) do (* We know: * (1) !n >= 0, because it starts with 0 and is only increased * (2) !n < n_max = slice_pos + slice_length <= Array.length slice * ==> unsafe get ok *) let p = (* slice.( !n ) *) Array.unsafe_get slice_char !n in let index = p_out + !k in let k_inc = (* k_inc: how many bytes are written. (-1) means: stop *) if p <= 127 && (not is_java || p <> 0) then begin if p < 0 then assert false; (* EOF mark *) if !k < l_out then begin (* (1) index = p_out + !k < p_out + l_out <= * String.length s_out * (2) p_out, !n >= 0 * ==> unsafe set ok * * 0 <= p <= 127 ==> unsafe_chr ok *) (* s_out.[index] <- Char.chr p; *) Bytes.unsafe_set s_out index (Char.unsafe_chr p); 1 end else (-1) end else if p <= 0x7ff then begin if !k + 1 < l_out then begin (* (1) index+1 = p_out + !k + 1 < p_out + l_out <= * String.length s_out * (2) p_out, !k >= 0 * ==> unsafe set ok * * p <= 0x7ff ==> p lsr 6 <= 0x1f * ==> 0xc0 lor (p lsr 6) <= df * p land 0x3f <= 0x3f ==> 0x80 lor (p land 0x3f) <= 0xbf * ==> unsafe_chr ok *) (* s_out.[index] <- Char.chr (0xc0 lor (p lsr 6)); *) (* s_out.[index + 1] <- Char.chr (0x80 lor (p land 0x3f)); *) Bytes.unsafe_set s_out index (Char.unsafe_chr (0xc0 lor (p lsr 6))); Bytes.unsafe_set s_out (index+1) (Char.unsafe_chr (0x80 lor (p land 0x3f))); 2 end else (-1) end else if p <= 0xffff then begin (* Refuse writing surrogate pairs, and fffe, ffff *) if (p >= 0xd800 && p < 0xe000) || (p >= 0xfffe) then failwith "Netconversion.write_utf8"; if !k + 2 < l_out then begin (* (1) index+2 = p_out + !k + 2 < p_out + l_out <= * String.length s_out * (2) p_out, !k >= 0 * ==> unsafe set ok * * Well, and it can be proven that unsafe_chr is ok, too... *) (* s_out.[index] <- Char.chr (0xe0 lor (p lsr 12)); *) (* s_out.[index + 1] <- Char.chr (0x80 lor ((p lsr 6) land 0x3f)); *) (* s_out.[index + 2] <- Char.chr (0x80 lor (p land 0x3f)); *) Bytes.unsafe_set s_out index (Char.unsafe_chr (0xe0 lor (p lsr 12))); Bytes.unsafe_set s_out (index+1) (Char.unsafe_chr (0x80 lor ((p lsr 6) land 0x3f))); Bytes.unsafe_set s_out (index+2) (Char.unsafe_chr (0x80 lor (p land 0x3f))); 3 end else (-1) end else if p <= 0x10ffff then begin if !k + 3 < l_out then begin (* No such characters are defined... *) Bytes.set s_out index (Char.chr (0xf0 lor (p lsr 18))); Bytes.set s_out (index + 1) (Char.chr (0x80 lor ((p lsr 12) land 0x3f))); Bytes.set s_out (index + 2) (Char.chr (0x80 lor ((p lsr 6) land 0x3f))); Bytes.set s_out (index + 3) (Char.chr (0x80 lor (p land 0x3f))); 4 end else (-1) end else begin (* Higher code points are not possible in XML; call subst *) let replacement = subst p in let l_repl = String.length replacement in if l_repl > multibyte_limit then failwith "Netconversion.write_utf8: Substitution string too long"; if !k + l_repl <= l_out then begin (* Enough space to store 'replacement': *) Bytes.blit_string replacement 0 s_out (p_out + !k) l_repl; l_repl (* may be 0! *) end else (-1) (* Exit whole conversion *) end in if k_inc >= 0 then ( k := !k + k_inc; incr n ) else ( n_ret := !n; n := n_max ); done; if !n_ret >= 0 then (!n_ret - slice_pos, !k) else (!n - slice_pos, !k) ;; let write_utf16_lebe lo hi slice_char slice_pos slice_length s_out p_out l_out subst = (* lo=0, hi=1: little endian * lo=1, hi=0: big endian *) assert(p_out >= 0 && p_out + l_out <= Bytes.length s_out && l_out >= 0); assert(slice_pos >= 0 && slice_pos+slice_length <= Array.length slice_char); let n = ref slice_pos in (* index of slice *) let n_max = slice_pos + slice_length in let k = ref 0 in (* written bytes *) let n_ret = ref (-1) in (* returned number of characters *) while ( !n < n_max ) do let p = slice_char.( !n ) in let index = p_out + !k in let k_inc = if p >= 0xfffe then begin if p <= 0x10ffff then begin if p <= 0xffff then failwith "Netconversion.write_utf16_le"; (* Must be written as surrogate pair *) if !k + 3 < l_out then begin let high = ((p - 0x10000) lsr 10) + 0xd800 in let low = (p land 0x3ff) + 0xdc00 in Bytes.set s_out (index + lo) (Char.chr (high land 0xff)); Bytes.set s_out (index + hi) (Char.chr (high lsr 8)); Bytes.set s_out (index + 2 + lo) (Char.chr (low land 0xff)); Bytes.set s_out (index + 2 + hi) (Char.chr (low lsr 8)); 4 end else (-1) end else begin (* Higher code points are not possible in XML; call subst *) let replacement = subst p in let l_repl = String.length replacement in if l_repl > multibyte_limit then failwith "Netconversion.write_utf16_le: Substitution string too long"; if !k + l_repl <= l_out then begin (* Enough space to store 'replacement': *) Bytes.blit_string replacement 0 s_out (p_out + !k) l_repl; l_repl (* may be 0! *) end else (-1) (* Exit whole conversion *) end end else begin (* 2-byte character *) if !k + 1 < l_out then begin Bytes.set s_out (index + lo) (Char.unsafe_chr (p land 0xff)); Bytes.set s_out (index + hi) (Char.unsafe_chr ((p lsr 8) land 0xff)); 2 end else (-1) end in if k_inc >= 0 then ( k := !k + k_inc; incr n ) else ( n_ret := !n; n := n_max ); done; if !n_ret >= 0 then (!n_ret - slice_pos, !k) else (!n - slice_pos, !k) ;; let write_utf32_lebe little slice_char slice_pos slice_length s_out p_out l_out subst = assert(p_out >= 0 && p_out + l_out <= Bytes.length s_out && l_out >= 0); assert(slice_pos >= 0 && slice_pos+slice_length <= Array.length slice_char); let n = ref slice_pos in (* index of slice *) let n_max = slice_pos + slice_length in let k = ref 0 in (* written bytes *) let n_ret = ref (-1) in (* returned number of characters *) let b0 = if little then 0 else 3 in let b1 = if little then 1 else 2 in let b2 = if little then 2 else 1 in let b3 = if little then 3 else 0 in while ( !n < n_max ) do let p = slice_char.( !n ) in let index = p_out + !k in let k_inc = if p <= 0x10ffff then ( if !k + 3 < l_out then ( Bytes.set s_out (index + b0) (Char.unsafe_chr (p land 0xff)); Bytes.set s_out (index + b1) (Char.unsafe_chr ((p lsr 8) land 0xff)); Bytes.set s_out (index + b2) (Char.unsafe_chr ((p lsr 16) land 0xff)); Bytes.set s_out (index + b3) (Char.unsafe_chr 0); 4 ) else (-1) ) else ( (* Higher code points are not possible in XML; call subst *) let replacement = subst p in let l_repl = String.length replacement in if l_repl > multibyte_limit then failwith "Netconversion.write_utf32: Substitution string too long"; if !k + l_repl <= l_out then begin (* Enough space to store 'replacement': *) Bytes.blit_string replacement 0 s_out (p_out + !k) l_repl; l_repl (* may be 0! *) end else (-1) (* Exit whole conversion *) ) in if k_inc >= 0 then ( k := !k + k_inc; incr n ) else ( n_ret := !n; n := n_max ); done; if !n_ret >= 0 then (!n_ret - slice_pos, !k) else (!n - slice_pos, !k) ;; let write_euc map enc = (* Code set 0 is US-ASCII. * let (set, byte1, byte2) = map unicode: * - set is 1, 2, 3, or 4. 4 means that the code point cannot be mapped. * - byte1 >= 160, <= 255 * - byte2 >= 160, <= 255, or byte2=256 meaning that it is not used *) (* UNSAFE_OPT *) fun slice_char slice_pos slice_length s_out p_out l_out subst -> assert(p_out >= 0 && p_out + l_out <= Bytes.length s_out && l_out >= 0); assert(slice_pos >= 0 && slice_pos+slice_length <= Array.length slice_char); let n = ref slice_pos in (* index of slice *) let n_max = slice_pos + slice_length in let k = ref 0 in (* written bytes *) let n_ret = ref (-1) in (* returned number of characters *) while ( !n < n_max ) do (* We know: * (1) !n >= 0, because it starts with 0 and is only increased * (2) !n < n_max = slice_pos + slice_length <= Array.length slice * ==> unsafe get ok *) let p = (* slice.( !n ) *) Array.unsafe_get slice_char !n in assert (p >= 0); let index = p_out + !k in let (set, b1, b2) = if p <= 127 then (0, p, 256) else map p in let k_inc = (* k_inc: how many bytes are written *) match set with 0 -> if !k < l_out then begin (* s_out.[index] <- Char.chr p; *) Bytes.unsafe_set s_out index (Char.unsafe_chr (b1 land 127)); 1 end else (-1) | 1 -> let bl = if b2 = 256 then 1 else 2 in if !k + bl < l_out then begin assert(b1 >= 160 && b1 <= 255 && b2 >= 160 && b2 <= 256); Bytes.set s_out (index) (Char.chr b1); if b2 <> 256 then Bytes.set s_out (index+1) (Char.chr b2); bl end else (-1) | 2 -> let bl = if b2 = 256 then 2 else 3 in if !k + bl < l_out then begin assert(b1 >= 160 && b1 <= 255 && b2 >= 160 && b2 <= 256); Bytes.set s_out index '\142'; Bytes.set s_out (index+1) (Char.chr b1); if b2 <> 256 then Bytes.set s_out (index+2) (Char.chr b2); bl end else (-1) | 3 -> let bl = if b2 = 256 then 2 else 3 in if !k + bl < l_out then begin assert(b1 >= 160 && b1 <= 255 && b2 >= 160 && b2 <= 256); Bytes.set s_out index '\143'; Bytes.set s_out (index+1) (Char.chr b1); if b2 <> 256 then Bytes.set s_out (index+2) (Char.chr b2); bl end else (-1) | 4 -> let replacement = subst p in let l_repl = String.length replacement in if l_repl > multibyte_limit then failwith "Netconversion.write_euc: Substitution string too long"; if !k + l_repl <= l_out then begin (* Enough space to store 'replacement': *) Bytes.blit_string replacement 0 s_out (p_out + !k) l_repl; l_repl end else (-1) (* Exit whole conversion *) | _ -> assert false in if k_inc >= 0 then ( k := !k + k_inc; incr n ) else ( n_ret := !n; n := n_max ); done; if !n_ret >= 0 then (!n_ret - slice_pos, !k) else (!n - slice_pos, !k) ;; let write_eucjp () = let jis0201 = Netmappings.get_from_unicode "jis0201" in let jis0208 = Netmappings.get_from_unicode "jis0208" in let jis0212 = Netmappings.get_from_unicode "jis0212" in let jis0201_mask = Array.length jis0201 - 1 in let jis0208_mask = Array.length jis0208 - 1 in let jis0212_mask = Array.length jis0212 - 1 in let map p = (* Try in order: jis0208, jis0201, jis0212 *) let map_tbl jistbl jistbl_mask = match jistbl.(p land jistbl_mask) with Netmappings.U_nil -> -1 | Netmappings.U_single (p0,q0) -> if p0 = p then q0 else -1 | Netmappings.U_double (p0,q0,p1,q1) -> if p0 = p then q0 else if p1 = p then q1 else -1 | Netmappings.U_array pq -> let r = ref (-1) in let h = ref 0 in while !r < 0 && !h < Array.length pq do if pq.( !h ) = p then r := pq.( !h+1 ) else h := !h + 2 done; !r in let cp_0208 = map_tbl jis0208 jis0208_mask in if cp_0208 >= 0 then let row = cp_0208 / 96 in let col = cp_0208 - row * 96 in (1, row + 160, col + 160) else let cp_0201 = map_tbl jis0201 jis0201_mask in if cp_0201 >= 128 then (* Ignore especially 0x5c, 0x7e *) (2, cp_0201, 256) else let cp_0212 = map_tbl jis0212 jis0212_mask in if cp_0212 >= 0 then let row = cp_0212 / 96 in let col = cp_0212 - row * 96 in (3, row + 160, col + 160) else (4,256,256) in write_euc map `Enc_eucjp ;; let write_euckr () = let ks1001 = Netmappings.get_from_unicode "ks1001" in let ks1001_mask = Array.length ks1001 - 1 in let map p = let map_tbl kstbl kstbl_mask = match kstbl.(p land kstbl_mask) with Netmappings.U_nil -> -1 | Netmappings.U_single (p0,q0) -> if p0 = p then q0 else -1 | Netmappings.U_double (p0,q0,p1,q1) -> if p0 = p then q0 else if p1 = p then q1 else -1 | Netmappings.U_array pq -> let r = ref (-1) in let h = ref 0 in while !r < 0 && !h < Array.length pq do if pq.( !h ) = p then r := pq.( !h+1 ) else h := !h + 2 done; !r in let cp_1001 = map_tbl ks1001 ks1001_mask in if cp_1001 >= 0 then let row = cp_1001 / 96 in let col = cp_1001 - row * 96 in (1, row + 160, col + 160) else (4,256,256) in write_euc map `Enc_euckr ;; let special_cpoint = 0x110000;; let write_subset inner_writer def slice_char slice_pos slice_length s_out p_out l_out subst = assert(p_out >= 0 && p_out + l_out <= Bytes.length s_out && l_out >= 0); assert(slice_pos >= 0 && slice_pos+slice_length <= Array.length slice_char); (* Force that the subst' function is called for all undefined code * points *) let slice_char' = Array.sub slice_char slice_pos slice_length in for n = 0 to slice_length - 1 do let ch = slice_char'.(n) in if ch >= special_cpoint || not (def ch) then slice_char'.(n) <- special_cpoint + n done; let subst' ch = if ch >= special_cpoint then subst (slice_char.(slice_pos + ch - special_cpoint)) else subst ch in inner_writer slice_char' 0 slice_length s_out p_out l_out subst' ;; let back_8bit ops s_in range_in p_in n_char = let p_rel = p_in - range_in in let n = min p_rel n_char in (n,n) ;; let back_utf8 ops s_in range_in p_in n_char = let open Netstring_tstring in let n = ref 0 in let k = ref 0 in let k_out = ref 0 in while p_in - !k > range_in && !n < n_char do incr k; let ch = Char.code (ops.get s_in (p_in - !k)) in if ch < 0x80 || ( ch >= 0xc0 && ch <=0xfd) then ( incr n; k_out := !k ) done; ( !n, !k_out ) ;; let back_utf16_lebe lo hi ops s_in range_in p_in n_char = (* lo=0, hi=1: little endian * lo=1, hi=0: big endian *) let open Netstring_tstring in let n = ref 0 in let k = ref 0 in let k_out = ref 0 in while p_in - !k > range_in + 1 && !n < n_char do incr k; incr k; let ch = (Char.code (ops.get s_in (p_in - !k + lo))) lor ((Char.code (ops.get s_in (p_in - !k + hi))) lsl 8) in if ch < 0xdc00 || ch >= 0xe000 then ( incr n; k_out := !k ); (* else: ch is the second half of a surrogate pair *) done; ( !n, !k_out ) ;; let back_utf32 ops s_in range_in p_in n_char = let open Netstring_tstring in let p_rel = p_in - range_in in let n = min p_rel (n_char lsl 2) in (n asr 2,n) ;; let back_euc ops s_in range_in p_in n_char = (* Works for 1-byte and 2-byte encodings *) let open Netstring_tstring in let n = ref 0 in let k = ref 0 in let k_out = ref 0 in while p_in - !k > range_in && !n < n_char do incr k; let ch1 = Char.code (ops.get s_in (p_in - !k)) in if ch1 < 0x80 then ( incr n; k_out := !k ) else if p_in - !k > range_in then ( incr k; let ch2 = Char.code (ops.get s_in (p_in - !k)) in (* ch2 < 0x80: wrong, but we do not report errors here *) if ch2 < 0x80 then ( incr n; k_out := !k ) else if ch2 = 142 || ch2 = 143 then ( incr n; k_out := !k ) else if p_in - !k > range_in then ( let ch3 = Char.code (ops.get s_in (p_in - !k - 1)) in if ch3 = 142 || ch3 = 143 then ( incr k; incr n; k_out := !k ) else ( incr n; k_out := !k ) ) else ( (* At the beginning of the string *) incr n; k_out := !k ) ) done; ( !n, !k_out ) ;; let check_unicode p = if p < 0 || (p > 0xd7ff && p < 0xe000) || p = 0xfffe || p = 0xffff || p > 0x10ffff then raise Malformed_code ;; let rec to_unicode cs = match cs with `Set_iso88591 -> (fun p -> if p < 0 || p > 255 then raise Malformed_code; p) | `Set_usascii -> (fun p -> if p < 0 || p > 127 then raise Malformed_code; p) | `Set_unicode -> (fun p -> check_unicode p; p) | _ -> let m_to_uni = Netmappings.get_to_unicode (internal_name cs) in (fun p -> if p < 0 || p >= Array.length m_to_uni then raise Malformed_code; let uni = m_to_uni.(p) in if uni < 0 then raise Malformed_code; uni ) ;; let rec from_unicode cs = match cs with `Set_iso88591 -> (fun p -> check_unicode p; if p > 255 then raise (Cannot_represent p); p) | `Set_usascii -> (fun p -> check_unicode p; if p > 127 then raise (Cannot_represent p); p) | `Set_unicode -> (fun p -> check_unicode p; p) | _ -> let m_from_unicode = Netmappings.get_from_unicode (internal_name cs) in let m_mask = Array.length m_from_unicode - 1 in (fun p -> check_unicode p; let p' = match Array.unsafe_get m_from_unicode (p land m_mask) with Netmappings.U_nil -> -1 | Netmappings.U_single (p0,q0) -> if p0 = p then q0 else -1 | Netmappings.U_double (p0,q0,p1,q1) -> if p0 = p then q0 else if p1 = p then q1 else -1 | Netmappings.U_array pq -> let r = ref (-1) in let h = ref 0 in while !r < 0 && !h < Array.length pq do if pq.( !h ) = p then r := pq.( !h+1 ) else h := !h + 2 done; !r in if p' < 0 then raise(Cannot_represent p); p' ) ;; type encoding1 = [ encoding | `Enc_utf16_bom | `Enc_utf32_bom | `Enc_utf8_bom ] ;; (* `Enc_*_bom considers the BOM as a character with code point -3. * This encoding is only internally used. *) let rec get_reader1 (enc : encoding1) = (* get_reader1 supports the additional internal encodings of * encoding1. get_reader (below) only supports the exported * encodings. *) match enc with `Enc_iso88591 -> !read_iso88591_ref 255 `Enc_iso88591 | `Enc_usascii -> !read_iso88591_ref 127 `Enc_usascii | `Enc_empty -> !read_iso88591_ref (-1) `Enc_empty | `Enc_utf8 -> !read_utf8_ref false | `Enc_java -> !read_utf8_ref true | `Enc_utf8_opt_bom -> read_utf8_opt_bom false | `Enc_utf8_bom -> read_utf8_opt_bom true | `Enc_utf16 -> read_utf16 false | `Enc_utf16_bom -> read_utf16 true | `Enc_utf16_le -> read_utf16_lebe 0 1 0 `Enc_utf16_le | `Enc_utf16_be -> read_utf16_lebe 1 0 0 `Enc_utf16_be | `Enc_utf32 -> read_utf32 false | `Enc_utf32_bom -> read_utf32 true | `Enc_utf32_le -> read_utf32_lebe true 0 `Enc_utf32_le | `Enc_utf32_be -> read_utf32_lebe false 0 `Enc_utf32_be | `Enc_eucjp -> read_eucjp () | `Enc_euckr -> read_euckr () | `Enc_subset(e,def) -> let reader' = get_reader1 (e :> encoding1) in read_subset reader' def | #encoding as e -> read_8bit (e :> encoding) ;; let get_reader = (get_reader1 : encoding1 -> 'a :> encoding -> 'a);; let rec get_writer enc = match enc with `Enc_iso88591 -> write_iso88591 255 | `Enc_usascii -> write_iso88591 127 | `Enc_empty -> write_iso88591 (-1) | `Enc_utf8 -> write_utf8 false | `Enc_java -> write_utf8 true | `Enc_utf16 -> failwith "Netconversion: Cannot output text as `Enc_utf16, use `Enc_utf16_le or `Enc_utf16_be" | `Enc_utf16_le -> write_utf16_lebe 0 1 | `Enc_utf16_be -> write_utf16_lebe 1 0 | `Enc_utf32 -> failwith "Netconversion: Cannot output text as `Enc_utf32, use `Enc_utf32_le or `Enc_utf32_be" | `Enc_utf32_le -> write_utf32_lebe true | `Enc_utf32_be -> write_utf32_lebe false | `Enc_eucjp -> write_eucjp () | `Enc_euckr -> write_euckr () | `Enc_subset(e,def) -> let writer' = get_writer e in write_subset writer' def | _ -> write_8bit enc ;; let rec get_back_fn enc = match enc with | `Enc_utf8 | `Enc_java -> back_utf8 | `Enc_utf16 -> failwith "Netconversion: Cannot go back in text encoded as `Enc_utf16, use `Enc_utf16_le or `Enc_utf16_be" | `Enc_utf16_le -> back_utf16_lebe 0 1 | `Enc_utf16_be -> back_utf16_lebe 1 0 | `Enc_utf32 | `Enc_utf32_le | `Enc_utf32_be -> back_utf32 | `Enc_eucjp -> back_euc | `Enc_euckr -> back_euc | `Enc_subset(e,def) -> get_back_fn e | _ -> back_8bit ;; let recode_poly ~in_ops ~in_enc ~in_buf ~in_pos ~in_len ~out_enc ~out_buf ~out_pos ~out_len ~max_chars ~subst = let open Netstring_tstring in if (in_pos < 0 || in_len < 0 || in_pos + in_len > in_ops.length in_buf || out_pos < 0 || out_len < 0 || out_pos + out_len > Bytes.length out_buf) then invalid_arg "Netconversion.recode"; (* An array with 250 elements can be allocated in the minor heap. *) let slice_length = big_slice in let slice_char = Array.make slice_length (-1) in let slice_blen = Array.make slice_length 1 in let in_k = ref 0 in (* read bytes *) let in_n = ref 0 in (* read characters *) let in_eof = ref (!in_k >= in_len) in let out_k = ref 0 in (* written bytes *) let out_n = ref 0 in (* written characters *) let out_eof = ref (!out_k >= out_len || !out_n >= max_chars) in let rd_enc = ref in_enc in let reader = ref (get_reader in_enc) in let writer = get_writer out_enc in while not !in_eof && not !out_eof do let in_n_inc, in_k_inc, rd_enc' = try !reader.read in_ops slice_char slice_blen in_buf (in_pos + !in_k) (in_len - !in_k) with Malformed_code_read(in_n_inc, in_k_inc, rd_enc') -> if in_n_inc = 0 then raise Malformed_code; (in_n_inc, in_k_inc, rd_enc') in let out_n_inc_max = min in_n_inc (max_chars - !out_n) in (* do not write more than max_chars *) let out_n_inc, out_k_inc = if out_n_inc_max > 0 then writer slice_char 0 out_n_inc_max out_buf (out_pos + !out_k) (out_len - !out_k) subst else (0,0) in let in_n_inc', in_k_inc' = if in_n_inc > out_n_inc then begin (* Not all read characters could be written *) let sum = ref 0 in for j = 0 to out_n_inc - 1 do sum := !sum + slice_blen.(j) done; (out_n_inc, !sum) end else (in_n_inc, in_k_inc) in in_k := !in_k + in_k_inc'; in_n := !in_n + in_n_inc'; out_k := !out_k + out_k_inc; out_n := !out_n + out_n_inc; (* Detect change of input encoding: *) if rd_enc' <> !rd_enc then begin rd_enc := rd_enc'; reader := get_reader rd_enc'; Array.fill slice_blen 0 slice_length 1; end; (* EOF criteria: * - It is possible that !in_k never reaches in_len because there is a * multibyte character at the end that is partially outside the input * range * - For the same reason it is possible that !out_k never reaches out_len * - It is accepted as reader EOF if not even one character can be * scanned * - It is accepted as writer EOF if fewer than in_n_inc characters * could be written *) in_eof := (!in_k >= in_len || in_n_inc = 0); out_eof := (!out_k >= out_len || !out_n >= max_chars || out_n_inc < in_n_inc); done; ( !in_k, !out_k, !rd_enc ) ;; let recode = recode_poly ~in_ops:Netstring_tstring.string_ops let recode_bytes = recode_poly ~in_ops:Netstring_tstring.bytes_ops let recode_tstring ~in_enc ~in_buf ~in_pos ~in_len ~out_enc ~out_buf ~out_pos ~out_len ~max_chars ~subst = let f = { Netstring_tstring.with_fun = (fun in_ops in_buf -> recode_poly ~in_ops ~in_enc ~in_buf ~in_pos ~in_len ~out_enc ~out_buf ~out_pos ~out_len ~max_chars ~subst ) } in Netstring_tstring.with_tstring f in_buf let rec ustring_of_uchar enc = let multi_byte writer n p = let s = Bytes.create n in let _,n_act = writer [|p|] 0 1 s 0 n (fun _ -> raise (Cannot_represent p)) in Bytes.sub_string s 0 n_act in match enc with `Enc_iso88591 -> (fun p -> if p > 255 then raise (Cannot_represent p); String.make 1 (Char.chr p)) | `Enc_usascii -> (fun p ->if p > 127 then raise (Cannot_represent p); String.make 1 (Char.chr p)) | `Enc_utf8 | `Enc_utf8_opt_bom -> multi_byte (write_utf8 false) 4 | `Enc_java -> multi_byte (write_utf8 true) 4 | `Enc_utf16_le -> multi_byte (write_utf16_lebe 0 1) 4 | `Enc_utf16_be -> multi_byte (write_utf16_lebe 1 0) 4 | `Enc_utf16 -> invalid_arg "Netconversion.ustring_of_uchar: UTF-16 not possible" | `Enc_utf32_le -> multi_byte (write_utf32_lebe true) 4 | `Enc_utf32_be -> multi_byte (write_utf32_lebe false) 4 | `Enc_utf32 -> invalid_arg "Netconversion.ustring_of_uchar: UTF-32 not possible" | `Enc_eucjp -> multi_byte (write_eucjp()) 3 | `Enc_euckr -> multi_byte (write_euckr()) 2 | `Enc_subset(e,def) -> (fun p -> if def p then ustring_of_uchar e p else raise (Cannot_represent p)) | _ -> let writer = write_8bit enc in multi_byte writer 1 ;; let makechar enc = let us = ustring_of_uchar enc in (fun p -> try us p with Cannot_represent _ -> raise Not_found) ;; (* The following algorithms assume that there is an upper limit of the length * of a multibyte character. Currently, UTF8 is the encoding with the longest * multibyte characters (6 bytes). * Because of this limit, it is allowed to allocate a buffer that is "large * enough" in order to ensure that at least one character is recoded in every * loop cycle. If the buffer was not large enough, no character would be * processed in a cycle, and the algorithm would hang. *) let convert_poly : type s t . in_ops:s Netstring_tstring.tstring_ops -> out_kind:t Netstring_tstring.tstring_kind -> ?subst:(int -> string) -> in_enc:encoding -> out_enc:encoding -> ?range_pos:int -> ?range_len:int -> s -> t = fun ~in_ops ~out_kind ?(subst = (fun p -> raise (Cannot_represent p))) ~in_enc ~out_enc ?(range_pos=0) ?range_len s -> let open Netstring_tstring in let range_len = match range_len with Some l -> l | None -> in_ops.length s - range_pos in if range_pos < 0 || range_len < 0 || range_pos+range_len > in_ops.length s then invalid_arg "Netconversion.convert"; (* Estimate the size of the output string: * length * 2 is just guessed. It is assumed that this number is usually * too large, and to avoid that too much memory is wasted, the buffer is * limited by 10000. *) let size = ref (max multibyte_limit (min 10000 (range_len * 2))) in let out_buf = ref (Bytes.create !size) in let k_in = ref 0 in let k_out = ref 0 in while !k_in < range_len do let in_len = range_len - !k_in in let out_len = !size - !k_out in assert (out_len >= multibyte_limit); (* space for at least one char *) let k_in_inc, k_out_inc, in_enc' = recode_poly ~in_ops ~in_enc ~in_buf:s ~in_pos:(range_pos + !k_in) ~in_len ~out_enc ~out_buf:(!out_buf) ~out_pos:(!k_out) ~out_len ~max_chars:max_int ~subst in if k_in_inc = 0 then raise Malformed_code; (* Reasons for k_in_inc = 0: * (1) There is not enough space in out_buf to add a single character * (2) in_buf ends with a prefix of a multi-byte character * Because there is always space for at least one character * ( = multibyte_limit ), reason (1) can be excluded. So it must * be (2), and we can raise Malformed_code. *) k_in := !k_in + k_in_inc; k_out := !k_out + k_out_inc; (* double the size of out_buf: *) let size' = min Sys.max_string_length (!size + !size) in if size' < !size + multibyte_limit then failwith "Netconversion.convert: string too long"; let out_buf' = Bytes.create size' in Bytes.blit !out_buf 0 out_buf' 0 !k_out; out_buf := out_buf'; size := size'; done; match out_kind with | Netstring_tstring.String_kind -> Bytes.sub_string !out_buf 0 !k_out | Netstring_tstring.Bytes_kind -> Bytes.sub !out_buf 0 !k_out | Netstring_tstring.Memory_kind -> let m = Bigarray.Array1.create Bigarray.char Bigarray.c_layout !k_out in Netsys_mem.blit_bytes_to_memory !out_buf 0 m 0 !k_out; m ;; let convert ?subst ~in_enc ~out_enc ?range_pos ?range_len s = convert_poly ?subst ~in_ops:Netstring_tstring.string_ops ~out_kind:Netstring_tstring.String_kind ~in_enc ~out_enc ?range_pos ?range_len s let convert_bytes ?subst ~in_enc ~out_enc ?range_pos ?range_len s = convert_poly ?subst ~in_ops:Netstring_tstring.bytes_ops ~out_kind:Netstring_tstring.Bytes_kind ~in_enc ~out_enc ?range_pos ?range_len s let convert_tstring ?subst ~in_enc ~out_enc ~out_kind ?range_pos ?range_len ts = let f = { Netstring_tstring.with_fun = (fun in_ops s -> convert_poly ?subst ~in_ops ~out_kind ~in_enc ~out_enc ?range_pos ?range_len s ) } in Netstring_tstring.with_tstring f ts class conversion_pipe ?(subst = (fun p -> raise (Cannot_represent p))) ~in_enc ~out_enc () = let current_in_enc = ref in_enc in let conv in_netbuf at_eof out_netbuf = if at_eof then (* TODO: avoid the extra allocations *) let s = convert_bytes ~subst ~in_enc:!current_in_enc ~out_enc (Netbuffer.unsafe_buffer in_netbuf) in Netbuffer.add_bytes out_netbuf s else let in_buf = Netbuffer.unsafe_buffer in_netbuf in let in_pos = 0 in let in_len = Netbuffer.length in_netbuf in let n = Netbuffer.add_inplace out_netbuf (fun out_buf out_pos out_len -> let (in_n,out_n,in_enc') = recode_bytes ~in_enc:!current_in_enc ~in_buf ~in_pos ~in_len ~out_enc ~out_buf ~out_pos ~out_len ~max_chars:out_len ~subst in Netbuffer.delete in_netbuf 0 in_n; current_in_enc := in_enc'; out_n ) in if n = 0 && in_len > 0 then begin (* To avoid endless loops, ensure here that there is enough space * in out_netbuf *) ignore(Netbuffer.add_inplace ~len:multibyte_limit out_netbuf (fun _ _ _ -> 0)); end; () in Netchannels.pipe ~conv () ;; (**********************************************************************) (* Cursors *) (**********************************************************************) (* The "read_*" functions are used to scan the string, and to move * the cursor forward. The slice array stores the scanned characters. * If the read call raises Malformed_code, the size of the slice * is decreased to 1, so the exact position can be calculated. *) (* Notes UTF-8/16/32 with BOM handling: * * cursor_enc is updated after the first slice has been read. This * usually changes this field to either the big or little endian * encoding variant. No update is needed when previous slices are * scanned, because the BOM is only allowed at the beginning of the * string, so can at most go back to exactly the BOM. * * cursor_encoding returns `Enc_utf16 when the cursor is over the * BOM, and cursor_enc otherwise. *) exception End_of_string;; exception Cursor_out_of_range;; exception Partial_character;; exception Byte_order_mark;; type 's poly_cursor = { (* configuration: *) cursor_ops : 's Netstring_tstring.tstring_ops; mutable cursor_target : 's; mutable cursor_range_pos : int; mutable cursor_range_len : int; mutable cursor_offset : int; mutable cursor_enc : encoding; (* `Enc_utf16: Only used if the slice or string is too short to * recognize the endianess. Otherwise, the encoding is set * to the endian-aware variant. * `Enc_utf32: same *) mutable cursor_has_bom : bool; (* Whether there is a BOM. Only when initially cursor_enc=`Enc_utf16 or utf32 *) (* conversion: *) mutable cursor_slice_char : int array; (* Contains the characters of the slice. Special values: * -1: EOF * -2: Incomplete multi-byte character at end * -3: BOM at the beginning *) mutable cursor_slice_blen : int array; (* Contains the byte length of the characters. * Recall that this array must contain 1s when single-byte * encodings are scanned, and must not be modified. The * "reader" does not fill this array for single-byte encodings, * so modifications would persist! *) mutable cursor_imbchar_len : int; (* This is always 0, except in the special case when the first * character of this slice is EOF, and EOF is preceded by an * incomplete multi-byte character (imbchar). In this case, * the length of the imbchar is stored here. *) mutable cursor_slice_char_pos : int; (* char pos of the beginning of the slice *) mutable cursor_slice_byte_pos : int; (* byte pos of the beginning of the slice *) mutable cursor_slice_length : int; (* number of characters *) mutable cursor_slice_bytes : int; (* number of bytes *) (* bookkeeping: *) mutable cursor_char_pos : int; mutable cursor_byte_pos : int; mutable cursor_index : int; (* index in the slice array *) mutable cursor_problem_range_start : int; mutable cursor_problem_range_end : int; (* The character positions >= range_start and < range_end are * considered as problem range. It is known that there is a * coding error (Malformed_code), so slices with length 1 must * be used. *) (* methods: *) mutable load_next_slice : unit -> unit; (* Precondition: cursor is one char right of the end of the slice * Action: load the next slice * Postcondition: cursor is at the beginning of the new slice *) mutable load_prev_slice : unit -> unit; (* Precondition: cursor is at the beginning of current slice * Action: load the previous slice * Postcondition: the cursor is at the end of the new slice * or the function raises Cursor_out_of_range * Note that this function actually moves the cursor one character * back (in contrast to load_next_slice that only reloads the * slice array, but does not move the cursor). The function may * choose to allocate a new, shorter slice array. *) } ;; type cursor = string poly_cursor let cursor_target cs = cs.cursor_target;; let cursor_range cs = (cs.cursor_range_pos, cs.cursor_range_len);; let cursor_initial_rel_pos cs = cs.cursor_offset;; let cursor_char_count cs = cs.cursor_char_pos;; let cursor_pos cs = cs.cursor_byte_pos;; let cursor_encoding cs = let enc = cs.cursor_enc in match enc with ( `Enc_utf16_le | `Enc_utf16_be ) when cs.cursor_has_bom -> if cs.cursor_byte_pos = cs.cursor_range_pos then `Enc_utf16 else enc | ( `Enc_utf32_le | `Enc_utf32_be ) when cs.cursor_has_bom -> if cs.cursor_byte_pos = cs.cursor_range_pos then `Enc_utf32 else enc | (`Enc_utf8 | `Enc_utf8_opt_bom) when cs.cursor_has_bom -> if cs.cursor_byte_pos = cs.cursor_range_pos then `Enc_utf8_opt_bom else enc | _ -> enc ;; exception Failing_in_Netconversion_uchar_at let uchar_at cs = let ch = cs.cursor_slice_char.(cs.cursor_index) in if ch < 0 then match ch with -1 -> raise End_of_string | -2 -> raise Partial_character | -3 -> raise Byte_order_mark | _ -> (* assert false *) raise Failing_in_Netconversion_uchar_at (* "assert false" isn't inlined! *) else ch ;; let cursor_byte_length cs = let ch = cs.cursor_slice_char.(cs.cursor_index) in if ch = -1 then raise End_of_string else cs.cursor_slice_blen.(cs.cursor_index) ;; let cursor_at_end cs = let ch = cs.cursor_slice_char.(cs.cursor_index) in ch = (-1) ;; let move_right num cs = let rec go num = let sl = Array.length cs.cursor_slice_char in if num >= sl - cs.cursor_index then begin (* Case: go at least to the next slice *) (* If the current slice is not completely filled, we will be * definitely outside of the valid range *) if cs.cursor_slice_length < sl then begin (* move to rightmost position, and raise the approriate exception *) cs.cursor_byte_pos <- cs.cursor_slice_byte_pos + cs.cursor_slice_bytes; cs.cursor_char_pos <- cs.cursor_slice_char_pos + cs.cursor_slice_length; cs.cursor_index <- cs.cursor_slice_length; assert(cs.cursor_slice_char.(cs.cursor_index) = (-1)); raise Cursor_out_of_range; end; assert(cs.cursor_slice_length = sl); let n = sl - cs.cursor_index in cs.cursor_byte_pos <- cs.cursor_slice_byte_pos + cs.cursor_slice_bytes; cs.cursor_char_pos <- cs.cursor_slice_char_pos + cs.cursor_slice_length; cs.cursor_index <- sl; cs.load_next_slice(); (* may raise Malformed_code *) go (num - n); end else begin (* Case: do not leave this slice *) let bl_sum = ref 0 in for k = cs.cursor_index to cs.cursor_index + num - 1 do let bl = cs.cursor_slice_blen.(k) in if k >= cs.cursor_slice_length then begin (* Cursor is beyond EOF *) cs.cursor_byte_pos <- cs.cursor_byte_pos + !bl_sum; cs.cursor_char_pos <- cs.cursor_char_pos + (k - cs.cursor_index); cs.cursor_index <- k; raise Cursor_out_of_range end; bl_sum := !bl_sum + bl done; cs.cursor_byte_pos <- cs.cursor_byte_pos + !bl_sum; cs.cursor_char_pos <- cs.cursor_char_pos + num; cs.cursor_index <- cs.cursor_index + num; end in assert(num >= 0); try go num with Malformed_code -> (* This happens when load_next_slice fails to decode the next slice * of length 1. In this case, load_next_slice keeps the state of * the cursor, so we have the chance to correct it now. *) cs.cursor_index <- cs.cursor_index - 1; cs.cursor_char_pos <- cs.cursor_char_pos - 1; cs.cursor_byte_pos <- cs.cursor_byte_pos - cs.cursor_slice_blen.(cs.cursor_index); raise Malformed_code ;; let move_left num cs = let rec go num = if num > cs.cursor_index then begin let n = cs.cursor_index in cs.cursor_byte_pos <- cs.cursor_slice_byte_pos; cs.cursor_char_pos <- cs.cursor_slice_char_pos; cs.cursor_index <- 0; (* cursor is now at the beginning of the slice *) cs.load_prev_slice(); (* go another character back *) go (num-n-1) (* so we went n+1 characters in this round *) end else begin (* num <= cs.cursor_index *) let bl_sum = ref 0 in let n = cs.cursor_index - num in for k = cs.cursor_index - 1 downto n do bl_sum := !bl_sum + cs.cursor_slice_blen.(k) done; cs.cursor_byte_pos <- cs.cursor_byte_pos - !bl_sum; cs.cursor_char_pos <- cs.cursor_char_pos - num; cs.cursor_index <- n; end in assert(num < 0); go (-num) ;; let move ?(num = 1) cs = if num >= 0 then move_right num cs else move_left num cs ;; let init_load_slice cs enc = let open Netstring_tstring in let ops = cs.cursor_ops in let reader0 = (get_reader enc).read ops in let back0 = lazy(get_back_fn enc ops) in (* For most encodings, [reader] and [back] never change. * For UTF-16, there may be refinements, however. *) let reader() = match cs.cursor_enc with ( `Enc_utf16 | `Enc_utf16_le | `Enc_utf16_be ) when cs.cursor_has_bom -> (* Ensure we use `Enc_utf16_bom when we read the beginning * of the range *) (fun slice_char slice_blen s bp bl -> if bp = cs.cursor_range_pos then (get_reader1 `Enc_utf16_bom).read ops slice_char slice_blen s bp bl else (get_reader cs.cursor_enc).read ops slice_char slice_blen s bp bl ) | ( `Enc_utf32 | `Enc_utf32_le | `Enc_utf32_be ) when cs.cursor_has_bom -> (* Ensure we use `Enc_utf32_bom when we read the beginning * of the range *) (fun slice_char slice_blen s bp bl -> if bp = cs.cursor_range_pos then (get_reader1 `Enc_utf32_bom).read ops slice_char slice_blen s bp bl else (get_reader cs.cursor_enc).read ops slice_char slice_blen s bp bl ) | ( `Enc_utf8 | `Enc_utf8_opt_bom ) when cs.cursor_has_bom -> (fun slice_char slice_blen s bp bl -> if bp = cs.cursor_range_pos then (get_reader1 `Enc_utf8_bom).read ops slice_char slice_blen s bp bl else (get_reader cs.cursor_enc).read ops slice_char slice_blen s bp bl ) | _ -> reader0 in let back() = match cs.cursor_enc with ( `Enc_utf16 | `Enc_utf16_le | `Enc_utf16_be ) when cs.cursor_has_bom -> get_back_fn cs.cursor_enc ops | ( `Enc_utf32 | `Enc_utf32_le | `Enc_utf32_be ) when cs.cursor_has_bom -> get_back_fn cs.cursor_enc ops | ( `Enc_utf8 | `Enc_utf8_opt_bom ) when cs.cursor_has_bom -> get_back_fn cs.cursor_enc ops | _ -> Lazy.force back0 in let record_imbchar rd_chars rd_bytes scan_bytes = (* Put a (-2) at position rd_chars of the current slice *) cs.cursor_slice_char.(rd_chars) <- (-2); cs.cursor_slice_blen.(rd_chars) <- scan_bytes - rd_bytes; if rd_chars+1 < Array.length cs.cursor_slice_char then ( cs.cursor_slice_char.(rd_chars+1) <- (-1); ); cs.cursor_slice_length <- rd_chars+1; cs.cursor_slice_bytes <- scan_bytes; in let repair_slice slice_size = (* When the reader raises Malformed_code, the slice has been * modified. This function reloads the old slice again. * * This function repairs these fields from the other fields: * - cursor_slice_char * - cursor_slice_blen * - cursor_slice_length * - cursor_slice_bytes *) let bp = cs.cursor_slice_byte_pos in let ep = cs.cursor_range_pos + cs.cursor_range_len in let (slice_char, slice_blen) = (Array.make slice_size (-1), Array.make slice_size 1) in let rd_chars, rd_bytes, _ = try reader () slice_char slice_blen cs.cursor_target bp (ep-bp) with (* should not happen: *) Malformed_code_read(_,_,_) -> raise Malformed_code in cs.cursor_slice_length <- rd_chars; cs.cursor_slice_bytes <- rd_bytes; cs.cursor_slice_char <- slice_char; cs.cursor_slice_blen <- slice_blen; (* Check for imbchars: *) if rd_chars < slice_size && rd_bytes < ep-bp then ( record_imbchar rd_chars rd_bytes (ep-bp); ); in let load_next_slice() = let cp = cs.cursor_char_pos in let bp = cs.cursor_byte_pos in let ep = cs.cursor_range_pos + cs.cursor_range_len in let load slice_size = let old_partial_len = (* Handle the case that the last character is (-2), and thus the first * character of the next slice will be (-1). Then, cursor_imbchar_len * must be set to the length of the (-2) character. *) if cs.cursor_slice_char.(cs.cursor_slice_length-1) = (-2) then cs.cursor_slice_blen.(cs.cursor_slice_length-1) else 0 in (* Check if the current array can be reused, or if we need new * arrays with different sizes *) let (slice_char, slice_blen) = if slice_size = Array.length cs.cursor_slice_char then (cs.cursor_slice_char, cs.cursor_slice_blen) (* use old arrays again *) else (Array.make slice_size (-1), Array.make slice_size 1) (* create new arrays with different size *) in (* Use the reader to decode the bytes and to put the characters into * slice_char. *) let rd_chars, rd_bytes, enc' = reader () slice_char slice_blen cs.cursor_target bp (ep-bp) in (* may raise Malformed_code_read *) (* Update cursor record: *) cs.cursor_index <- 0; cs.cursor_slice_char <- slice_char; cs.cursor_slice_blen <- slice_blen; cs.cursor_slice_length <- rd_chars; cs.cursor_slice_bytes <- rd_bytes; cs.cursor_slice_char_pos <- cp; cs.cursor_slice_byte_pos <- bp; cs.cursor_imbchar_len <- old_partial_len; cs.cursor_enc <- enc'; (* Check for imbchars: *) if rd_chars < slice_size && rd_bytes < ep-bp then ( record_imbchar rd_chars rd_bytes (ep-bp); ); in (* Is the cursor positioned in a problem range? If yes, decode only * one character. If not, try to decode a block of characters. * If the latter fails, the current position turns out to be * problematic, and is remembered as such. *) let old_slice_size = Array.length cs.cursor_slice_char in if cp >= cs.cursor_problem_range_start && cp < cs.cursor_problem_range_end then begin try load 1 with Malformed_code_read(_,_,_) -> repair_slice old_slice_size; raise Malformed_code end else begin try load big_slice with Malformed_code_read(_,_,_) -> cs.cursor_problem_range_start <- cp; cs.cursor_problem_range_end <- cp+big_slice; try load 1 with Malformed_code_read(_,_,_) -> repair_slice old_slice_size; raise Malformed_code end in let load_prev_slice() = let cp = cs.cursor_char_pos in let bp = cs.cursor_byte_pos in let ep = cs.cursor_range_pos + cs.cursor_range_len in let load slice_size = (* Check if the current array can be reused, or if we need new * arrays with different sizes *) let (slice_char, slice_blen) = if slice_size = Array.length cs.cursor_slice_char then (cs.cursor_slice_char, cs.cursor_slice_blen) (* use old arrays again *) else (Array.make slice_size (-1), Array.make slice_size 1) (* create new arrays with different size *) in (* Go back 1 character (must always succeed): *) if bp = cs.cursor_range_pos then raise Cursor_out_of_range; let bk1_chars, bk1_bytes = if cs.cursor_imbchar_len > 0 then (* Special case: the last character of this slice is an imbchar. * Assume imbchar_len *) (1, cs.cursor_imbchar_len) else back () cs.cursor_target cs.cursor_range_pos bp 1 in if bk1_chars = 0 then raise Malformed_code; (* bk1_chars = 0: this means there is a multi-byte suffix at the * beginning of the range * ==> bk1_chars = 1 *) (* Go back further slice_size-1 characters (or less): *) let bk_chars, bk_bytes = back () cs.cursor_target cs.cursor_range_pos (bp-bk1_bytes) (slice_size-1) in let bp' = bp - bk1_bytes - bk_bytes in (* Use the reader to decode the bytes and to put the characters into * slice_char. *) let rd_chars, rd_bytes, _ = reader () slice_char slice_blen cs.cursor_target bp' (ep-bp') in (* may raise Malformed_code_read *) assert(rd_chars >= bk_chars); (* Update cursor record: *) cs.cursor_index <- bk_chars; cs.cursor_slice_char <- slice_char; cs.cursor_slice_blen <- slice_blen; cs.cursor_slice_length <- rd_chars; cs.cursor_slice_bytes <- rd_bytes; cs.cursor_slice_char_pos <- cp - bk_chars - 1; cs.cursor_slice_byte_pos <- bp'; cs.cursor_imbchar_len <- 0; (* Cannot happen *) (* Don't need to update cursor_enc! *) (* Check for imbchars: *) if rd_chars < slice_size && rd_bytes < ep-bp' then ( record_imbchar rd_chars rd_bytes (ep-bp'); ); (* Implicitly go one character back: *) cs.cursor_char_pos <- cp - 1; cs.cursor_byte_pos <- bp - bk1_bytes; in (* Is the cursor positioned in a problem range? If yes, decode only * one character. If not, try to decode a block of characters. * If the latter fails, the current position turns out to be * problematic, and is remembered as such. *) let old_slice_size = Array.length cs.cursor_slice_char in if cp > cs.cursor_problem_range_start && cp <= cs.cursor_problem_range_end then begin try load 1 with Malformed_code_read(_,_,_) -> repair_slice old_slice_size; raise Malformed_code end else begin try load big_slice with Malformed_code_read(_,_,_) -> cs.cursor_problem_range_start <- cp-big_slice; cs.cursor_problem_range_end <- cp; try load 1 with Malformed_code_read(_,_,_) -> repair_slice old_slice_size; raise Malformed_code end in (* Important note: These two functions either modify the cursor state * as requested, or they raise an exception, and keep the cursor state * as before. Considered exceptions are Malformed_code, and * Cursor_out_of_range. *) cs.load_next_slice <- load_next_slice; cs.load_prev_slice <- load_prev_slice ;; let create_poly_cursor ?(range_pos = 0) ?range_len ?(initial_rel_pos = 0) enc ops s = let open Netstring_tstring in if range_pos < 0 || range_pos > ops.length s then invalid_arg "Netconversion.create_cursor"; let range_len = match range_len with Some l -> l | None -> ops.length s - range_pos in if range_len < 0 || range_pos + range_len > ops.length s then invalid_arg "Netconversion.create_cursor"; if initial_rel_pos < 0 || initial_rel_pos > range_len then invalid_arg "Netconversion.create_cursor"; if enc = `Enc_utf16 && initial_rel_pos <> 0 then failwith "Netconversion.create_cursor: The encoding `Enc_utf16 only supported when initial_rel_pos=0"; if enc = `Enc_utf32 && initial_rel_pos <> 0 then failwith "Netconversion.create_cursor: The encoding `Enc_utf32 only supported when initial_rel_pos=0"; let cs = { cursor_ops = ops; cursor_target = s; cursor_range_pos = range_pos; cursor_range_len = range_len; cursor_offset = initial_rel_pos; cursor_enc = enc; cursor_has_bom = (enc = `Enc_utf16 || enc = `Enc_utf32 || enc = `Enc_utf8_opt_bom); cursor_slice_char = [| 1 |]; cursor_slice_blen = [| 1 |]; cursor_imbchar_len = 0; cursor_slice_char_pos = 0; cursor_slice_byte_pos = range_pos + initial_rel_pos; cursor_slice_length = 1; cursor_slice_bytes = 0; cursor_char_pos = 0; cursor_byte_pos = range_pos + initial_rel_pos; cursor_index = 1; cursor_problem_range_start = max_int; cursor_problem_range_end = max_int; load_next_slice = (fun () -> assert false); load_prev_slice = (fun () -> assert false); } in init_load_slice cs enc; (* load the next slice to do the rest of the initialization: *) cs.load_next_slice(); cs ;; let create_cursor ?range_pos ?range_len ?initial_rel_pos enc s = let ops = Netstring_tstring.string_ops in create_poly_cursor ?range_pos ?range_len ?initial_rel_pos enc ops s type 'a with_cursor_fun = { with_cursor_fun : 's . 's Netstring_tstring.tstring_ops -> 's poly_cursor -> 'a } let with_tstring_cursor ?range_pos ?range_len ?initial_rel_pos enc ts f = let f = { Netstring_tstring.with_fun = (fun ops s -> f.with_cursor_fun ops (create_poly_cursor ?range_pos ?range_len ?initial_rel_pos enc ops s) ) } in Netstring_tstring.with_tstring f ts let reinit_cursor ?(range_pos = 0) ?range_len ?(initial_rel_pos = 0) ?enc s cs = let open Netstring_tstring in let ops = cs.cursor_ops in if range_pos < 0 || range_pos > ops.length s then invalid_arg "Netconversion.reinit_cursor"; let range_len = match range_len with Some l -> l | None -> ops.length s - range_pos in if range_len < 0 || range_pos + range_len > ops.length s then invalid_arg "Netconversion.reinit_cursor"; if initial_rel_pos < 0 || initial_rel_pos > range_len then invalid_arg "Netconversion.reinit_cursor"; let enc = match enc with None -> cs.cursor_enc | Some e -> e in if enc = `Enc_utf16 && initial_rel_pos <> 0 then failwith "Netconversion.reinit_cursor: The encoding `Enc_utf16 only supported when initial_rel_pos=0"; if enc = `Enc_utf32 && initial_rel_pos <> 0 then failwith "Netconversion.reinit_cursor: The encoding `Enc_utf32 only supported when initial_rel_pos=0"; let old_enc = cs.cursor_enc in cs.cursor_target <- s; cs.cursor_range_pos <- range_pos; cs.cursor_range_len <- range_len; cs.cursor_offset <- initial_rel_pos; cs.cursor_enc <- enc; cs.cursor_has_bom <- (enc = `Enc_utf16 || enc = `Enc_utf32 || enc = `Enc_utf8_opt_bom); cs.cursor_imbchar_len <- 0; cs.cursor_slice_char_pos <- 0; cs.cursor_slice_byte_pos <- range_pos + initial_rel_pos; cs.cursor_slice_length <- 1; cs.cursor_slice_bytes <- 0; cs.cursor_char_pos <- 0; cs.cursor_byte_pos <- range_pos + initial_rel_pos; cs.cursor_index <- 1; cs.cursor_problem_range_start <- max_int; cs.cursor_problem_range_end <- max_int; cs.load_next_slice <- (fun () -> assert false); cs.load_prev_slice <- (fun () -> assert false); cs.cursor_slice_char.(0) <- 1; if not (same_encoding enc old_enc) then (* slice_blen: It might have happened that the new encoding is an * 8 bit charset, but the old was not. Re-initialize this array * to ensure it contains only "1" in this case. *) Array.fill cs.cursor_slice_blen 0 (Array.length cs.cursor_slice_blen) 1; init_load_slice cs enc; (* load the next slice to do the rest of the initialization: *) cs.load_next_slice(); ;; let copy_cursor ?enc cs = let enc = match enc with None -> cs.cursor_enc | Some e -> e in if same_encoding enc cs.cursor_enc then { cs with cursor_slice_char = Array.copy cs.cursor_slice_char; cursor_slice_blen = Array.copy cs.cursor_slice_blen; } else begin if enc = `Enc_utf16 then failwith "Netconversion.copy_cursor: The encoding `Enc_utf16 is not supported"; if enc = `Enc_utf32 then failwith "Netconversion.copy_cursor: The encoding `Enc_utf32 is not supported"; let cs' = { cs with cursor_enc = enc; cursor_slice_char = [| 1 |]; cursor_slice_blen = [| 1 |]; cursor_slice_length = 1; cursor_problem_range_start = max_int; cursor_problem_range_end = max_int; } in init_load_slice cs' enc; (* load the next slice to do the rest of the initialization: *) cs'.load_next_slice(); cs' end ;; let cursor_blit_maxlen cs = let l = cs.cursor_slice_length - cs.cursor_index in (* Test on special situations: *) match cs.cursor_slice_char.(cs.cursor_index) with -1 -> (* EOF *) raise End_of_string | -3 -> (* BOM *) 0 | _ -> if cs.cursor_slice_char.(cs.cursor_slice_length - 1) = (-2) then (* Partial character *) l-1 else l ;; let cursor_blit cs ua pos len = if pos < 0 || len < 0 || pos+len > Array.length ua then invalid_arg "Netconversion.cursor_blit"; let cs_len = cursor_blit_maxlen cs in let l = min cs_len len in int_blit cs.cursor_slice_char cs.cursor_index ua pos l; l ;; let cursor_blit_positions cs ua pos len = if pos < 0 || len < 0 || pos+len > Array.length ua then invalid_arg "Netconversion.cursor_blit_positions"; let cs_len = cursor_blit_maxlen cs in let l = min cs_len len in let p = cs.cursor_byte_pos in let blen = cs.cursor_slice_blen in let cidx = cs.cursor_index in assert(pos+l <= Array.length ua); assert(cidx+l <= Array.length cs.cursor_slice_blen); Netaux.ArrayAux.int_series blen cidx ua pos l p; l ;; (**********************************************************************) (* String functions *) (**********************************************************************) (* CHECK * - ustring_length: Count imbchars? No! * * DOC: * - imbchar handling (additional exceptions) *) let ustring_length_poly ops enc = let open Netstring_tstring in if is_single_byte enc then fun ?(range_pos=0) ?range_len s -> let range_len = match range_len with None -> ops.length s - range_pos | Some l -> l in if range_pos < 0 || range_len < 0 || range_pos+range_len > ops.length s then invalid_arg "Netconversion.ustring_length"; range_len else fun ?range_pos ?range_len s -> (* Assumption: There is no string that has more than max_int * characters *) let cs = create_poly_cursor ?range_pos ?range_len enc ops s in ( try move ~num:max_int cs with Cursor_out_of_range -> ()); let n = cursor_char_count cs in (* Check that the last char is not an imbchar *) ( try move ~num:(-1) cs; let _ = uchar_at cs in () with Cursor_out_of_range -> () | Partial_character -> raise Malformed_code ); n ;; let ustring_length enc = ustring_length_poly Netstring_tstring.string_ops enc let ustring_length_ts enc ?range_pos ?range_len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> ustring_length_poly ops enc ?range_pos ?range_len s ) } ts exception Malformed_code_at of int;; let verify_poly ops enc ?range_pos ?range_len s = let cs = try create_poly_cursor ?range_pos ?range_len enc ops s with Malformed_code -> raise (Malformed_code_at 0) | _ -> assert false in ( try move ~num:max_int cs with Cursor_out_of_range -> () | Malformed_code -> (* Now cursor_pos is the byte position of the last valid * character. Add the length of this character. *) let n = cs.cursor_slice_blen.(cs.cursor_index) in raise (Malformed_code_at (cs.cursor_byte_pos + n)) ); (* Now we are at EOF. Check this. Furthermore, check whether there is * an imbchar just before EOF: *) ( try let _ = uchar_at cs in assert false with End_of_string -> () ); ( try move ~num:(-1) cs; let _ = uchar_at cs in () with Cursor_out_of_range -> () (* empty string *) | Partial_character -> raise (Malformed_code_at (cs.cursor_byte_pos)) ); () ;; let verify enc = verify_poly Netstring_tstring.string_ops enc let verify_ts enc ?range_pos ?range_len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> verify_poly ops enc ?range_pos ?range_len s ) } ts let ustring_iter_poly ops enc f ?range_pos ?range_len s = let cs = create_poly_cursor ?range_pos ?range_len enc ops s in try while true do let ch = uchar_at cs in (* or End_of_string *) f ch; move cs done; assert false with End_of_string -> () | Partial_character -> raise Malformed_code ;; let ustring_iter enc = ustring_iter_poly Netstring_tstring.string_ops enc let ustring_iter_ts enc f ?range_pos ?range_len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> ustring_iter_poly ops enc f ?range_pos ?range_len s ) } ts let ustring_map_poly ops out_kind enc f ?range_pos ?range_len s = (* The following algorithm works only if the mapped lists are short: let mkch = ustring_of_uchar enc in let subst p = let p' = f p in String.concat "" (List.map mkch p') in convert ~subst ~in_enc:enc ~out_enc:`Enc_empty ?range_pos ?range_len s *) let buf = Netbuffer.create 250 in ustring_iter_poly ops enc (fun p -> let l = f p in Netbuffer.add_string buf (String.concat "" (List.map (ustring_of_uchar enc) l)) ) ?range_pos ?range_len s; Netbuffer.to_tstring_poly buf out_kind ;; let ustring_map enc = ustring_map_poly Netstring_tstring.string_ops Netstring_tstring.String_kind enc let ustring_map_ts enc f ?range_pos ?range_len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> match ts with | `String _ -> let kind = Netstring_tstring.String_kind in `String( ustring_map_poly ops kind enc f ?range_pos ?range_len s) | `Bytes _ -> let kind = Netstring_tstring.Bytes_kind in `Bytes( ustring_map_poly ops kind enc f ?range_pos ?range_len s) | `Memory _ -> let kind = Netstring_tstring.Memory_kind in `Memory( ustring_map_poly ops kind enc f ?range_pos ?range_len s) ) } ts let ustring_to_lower enc ?range_pos ?range_len s = let f x = [ Netunichar.to_lower x ] in ustring_map enc f ?range_pos ?range_len s ;; let ustring_to_lower_ts enc ?range_pos ?range_len ts = let f x = [ Netunichar.to_lower x ] in ustring_map_ts enc f ?range_pos ?range_len ts ;; let ustring_to_lower_poly ops kind enc ?range_pos ?range_len ts = let f x = [ Netunichar.to_lower x ] in ustring_map_poly ops kind enc f ?range_pos ?range_len ts ;; let ustring_to_upper enc ?range_pos ?range_len s = let f x = [ Netunichar.to_upper x ] in ustring_map enc f ?range_pos ?range_len s ;; let ustring_to_upper_ts enc ?range_pos ?range_len ts = let f x = [ Netunichar.to_upper x ] in ustring_map_ts enc f ?range_pos ?range_len ts ;; let ustring_to_upper_poly ops kind enc ?range_pos ?range_len ts = let f x = [ Netunichar.to_upper x ] in ustring_map_poly ops kind enc f ?range_pos ?range_len ts ;; let ustring_to_title enc ?range_pos ?range_len s = let f x = [ Netunichar.to_title x ] in ustring_map enc f ?range_pos ?range_len s ;; let ustring_to_title_ts enc ?range_pos ?range_len ts = let f x = [ Netunichar.to_title x ] in ustring_map_ts enc f ?range_pos ?range_len ts ;; let ustring_to_title_poly ops kind enc ?range_pos ?range_len s = let f x = [ Netunichar.to_title x ] in ustring_map_poly ops kind enc f ?range_pos ?range_len s ;; let ustring_sub_poly ops out_kind enc pos len ?range_pos ?range_len s = let open Netstring_tstring in try if pos < 0 || len < 0 then raise Cursor_out_of_range; let cs = create_poly_cursor ?range_pos ?range_len enc ops s in move ~num:pos cs; let byte_pos_0 = cursor_pos cs in move ~num:len cs; let byte_pos_1 = cursor_pos cs in (* Check: The last character of the string must not be an imbchar *) if len > 0 then ( move ~num:(-1) cs; let _ = uchar_at cs in (); (* or Partial_character *) ); ops.subpoly out_kind s byte_pos_0 (byte_pos_1 - byte_pos_0) with Cursor_out_of_range -> invalid_arg "Netconversion.ustring_sub" | Partial_character -> raise Malformed_code ;; let ustring_sub enc = ustring_sub_poly Netstring_tstring.string_ops Netstring_tstring.String_kind enc let ustring_sub_ts enc pos len ?range_pos ?range_len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> match ts with | `String _ -> let kind = Netstring_tstring.String_kind in `String( ustring_sub_poly ops kind enc pos len ?range_pos ?range_len s) | `Bytes _ -> let kind = Netstring_tstring.Bytes_kind in `Bytes( ustring_sub_poly ops kind enc pos len ?range_pos ?range_len s) | `Memory _ -> let kind = Netstring_tstring.Memory_kind in `Memory( ustring_sub_poly ops kind enc pos len ?range_pos ?range_len s) ) } ts let ustring_compare_poly ops1 ops2 enc f ?range_pos:rp1 ?range_len:rl1 s1 ?range_pos:rp2 ?range_len:rl2 s2 = let cs1 = create_poly_cursor ?range_pos:rp1 ?range_len:rl1 enc ops1 s1 in let cs2 = create_poly_cursor ?range_pos:rp2 ?range_len:rl2 enc ops2 s2 in let r = ref 0 in try while !r = 0 do let ch1 = uchar_at cs1 in (* or End_of_string *) let ch2 = uchar_at cs2 in (* or End_of_string *) r := f ch1 ch2 done; !r with End_of_string -> ( match cursor_at_end cs1, cursor_at_end cs2 with true, false -> (-1) | false, true -> 1 | true, true -> 0 | _ -> assert false ) | Partial_character -> raise Malformed_code ;; let ustring_compare enc = ustring_compare_poly Netstring_tstring.string_ops Netstring_tstring.string_ops enc let ustring_compare_ts enc f ?range_pos:rp1 ?range_len:rl1 ts1 ?range_pos:rp2 ?range_len:rl2 ts2 = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops1 s1 -> Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops2 s2 -> ustring_compare_poly ops1 ops2 enc f ?range_pos:rp1 ?range_len:rl1 s1 ?range_pos:rp2 ?range_len:rl2 s2 ) } ts2 ) } ts1 let uarray_of_ustring_poly ops enc ?(range_pos=0) ?range_len s = let open Netstring_tstring in let range_len = match range_len with Some l -> l | None -> ops.length s - range_pos in if range_pos < 0 || range_len < 0 || range_pos+range_len > ops.length s then invalid_arg "Netconversion.uarray_of_ustring"; let slice_length = big_slice in let slice_char = Array.make slice_length (-1) in let slice_blen = Array.make slice_length 1 in let k = ref 0 in let e = ref enc in let reader = ref (get_reader enc) in let buf = ref [] in while !k < range_len do let (n_inc, k_inc, enc') = try (!reader).read ops slice_char slice_blen s (range_pos + !k) (range_len - !k) with Malformed_code_read(_,_,_) -> raise Malformed_code in k := !k + k_inc; buf := (Array.sub slice_char 0 n_inc) :: !buf ; if enc' <> !e then begin e := enc'; reader := get_reader enc'; Array.fill slice_blen 0 slice_length 1; end; if n_inc < slice_length then ( (* EOF *) if !k < range_len then raise Malformed_code; (* s ends with multi-byte prefix*) k := range_len; ); done; Array.concat (List.rev !buf) ;; let uarray_of_ustring enc = uarray_of_ustring_poly Netstring_tstring.string_ops enc let uarray_of_ustring_ts enc ?range_pos ?range_len ts = Netstring_tstring.with_tstring { Netstring_tstring.with_fun = (fun ops s -> uarray_of_ustring_poly ops enc ?range_pos ?range_len s ) } ts let ustring_of_uarray_poly out_kind ?(subst = fun code -> raise (Cannot_represent code)) enc ?(pos=0) ?len ua = let len = match len with Some l -> l | None -> Array.length ua - pos in if pos < 0 || len < 0 || pos+len > Array.length ua then invalid_arg "Netconversion.ustring_of_uarray"; (* Estimate the size of the output string: * length * 2 is just guessed. It is assumed that this number is usually * too large, and to avoid that too much memory is wasted, the buffer is * limited by 10000. *) let size = ref (max multibyte_limit (min 10000 (len * 2))) in let out_buf = ref (Bytes.create !size) in let writer = get_writer enc in let k_in = ref 0 in let k_out = ref 0 in while !k_in < len do let k_in_inc, k_out_inc = writer ua (pos + !k_in) (len - !k_in) !out_buf !k_out (!size - !k_out) subst in k_in := !k_in + k_in_inc; k_out := !k_out + k_out_inc; (* double the size of out_buf: *) let size' = min Sys.max_string_length (!size + !size) in if size' < !size + multibyte_limit then failwith "Netconversion.ustring_of_uarray: string too long"; let out_buf' = Bytes.create size' in Bytes.blit !out_buf 0 out_buf' 0 !k_out; out_buf := out_buf'; size := size'; done; Netstring_tstring.bytes_subpoly out_kind !out_buf 0 !k_out ;; let ustring_of_uarray ?subst = ustring_of_uarray_poly Netstring_tstring.String_kind ?subst let ustring_of_uarray_ts : type t . t Netstring_tstring.tstring_kind -> ?subst:(int->string) -> encoding -> ?pos:int -> ?len:int -> int array -> tstring = fun out_kind ?subst enc ?pos ?len ua -> let s = ustring_of_uarray_poly out_kind ?subst enc ?pos ?len ua in match out_kind with | Netstring_tstring.String_kind -> `String s | Netstring_tstring.Bytes_kind -> `Bytes s | Netstring_tstring.Memory_kind -> `Memory s let code_cmp x1 x2 = x1-x2 let ci_code_cmp x1 x2 = let x1_lc = Netunichar.to_lower x1 in let x2_lc = Netunichar.to_lower x2 in x1_lc - x2_lc ocamlnet-4.1.2/src/netstring/netmech_crammd5_sasl.mli0000644000175000017500000000306112731530350021327 0ustar gerdgerd(* $Id$ *) module CRAM_MD5 : Netsys_sasl_types.SASL_MECHANISM (** The CRAM-MD5 SASL mechanism (RFC 2195), which is obsolete and only provided for completeness. Key facts: - The password is checked with a challenge-response mechanism, and does not appear in the clear. - The mechanism is vulnerable to man-in-the-middle attacks. - The client does not authenticate the server in any way. - The hash function MD5 counts as broken. - There is no support for channel binding within the mechanism. - There is no support for authorization names. - The mechanism provides at best medium security, and should only be used over channels that are otherwise secured. This implementation checks whether the server receives user names and passwords in UTF-8 encoding. Note that the mechanism predates the widespread use of Unicode, so this may cause interoperability issues with old implementations. Parameters: - Both [create_client_session] and [create_server_session] accept the boolean parameter "mutual". If true, however, authentication fails immediately, as mutual authentication cannot be supported. - The boolean parameter "secure" is ignored (i.e. we regard this mechanism as secure) As for all SASL mechanisms in OCamlnet, SASLprep is not automatically called. Users of CRAM-MD5 should pass user names and passwords through {!Netsaslprep.saslprep}. *) (**/**) val override_challenge : string -> unit (* debug *) ocamlnet-4.1.2/src/netstring/netx509_pubkey_crypto.mli0000644000175000017500000000504112731530350021445 0ustar gerdgerd(** X.509 public key cryptography - wrappers *) (** This module uses the current cryptography provider to actually run operations. Note that typically not all encryption and signing schemes are implemented. For instance, GnuTLS only provides those schemes that are needed for TLS (so far RSA for encryption, and RSA/DSA/ECDSA for signing). Also note that we require GnuTLS-3.0 or newer for public key cryptography. *) exception Unsupported_algorithm of Netoid.t (** Raises if the crypto backend does not support an algorithm *) val is_encryption_supported : Netx509_pubkey.encrypt_alg -> bool (** Whether this algorithm is supported *) val is_signing_supported : Netx509_pubkey.sign_alg -> bool (** Whether this algorithm is supported *) val encrypt : Netx509_pubkey.encrypt_alg -> Netx509_pubkey.pubkey -> string -> string (** Encrypt the string. Note that length restrictions apply, depending on the algorithm and the bit size of the key. For instance, with a 2048-bit RSA key you can at most encrypt 245 bytes. *) val decrypt : Netx509_pubkey.encrypt_alg -> Netx509_pubkey.privkey -> string -> string (** Decrypt the string *) val verify : Netx509_pubkey.sign_alg -> Netx509_pubkey.pubkey -> string -> string -> bool (** [verify alg key plaintext signature]: Checks the signature, and returns [true] on success. *) val sign : Netx509_pubkey.sign_alg -> Netx509_pubkey.privkey -> string -> string (** [let signature = sign alg key plaintext]: Creates a signature. Unlike for encryption there is no length restriction. *) (** Example: Using RSA for encryption First create RSA keys: {[ openssl genrsa -out rsa.key 2048 openssl rsa -in rsa.key -pubout -out rsa.pub ]} Read the keys in: {[ let priv_ch = Netchannels.input_channel(open_in "rsa.key") let priv = Netx509_pubkey.read_privkey_from_pem priv_ch let () = priv_ch#close_in() let pub_ch = Netchannels.input_channel(open_in "rsa.pub") let pub = Netx509_pubkey.read_pubkey_from_pem pub_ch let () = pub_ch#close_in() ]} Encrypt something: {[ let () = Nettls_gnutls.init() let e = encrypt Netx509_pubkey.Encryption.rsa pub "secret" ]} Decrypt: {[ let d = decrypt Netx509_pubkey.Encryption.rsa priv e ]} Note that encryption with public keys is restricted to very short messages (e.g. 245 bytes for a 2048 bits RSA key). Typically, only a random second key is encrypted, and the second key is used with a symmetric cipher. *) ocamlnet-4.1.2/src/netstring/nethtml.ml0000644000175000017500000005471712731530350016572 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) open Nethtml_scanner;; type document = Element of (string * (string*string) list * document list) | Data of string ;; exception End_of_scan;; exception Found;; type element_class = (* What is the class of an element? *) [ `Inline | `Block | `Essential_block | `None | `Everywhere ] ;; type model_constraint = (* The constraint the subelements must fulfill *) [ `Inline | `Block | `Flow (* = `Inline or `Block *) | `Empty | `Any | `Special | `Elements of string list (* Enumeration of allowed elements *) | `Or of (model_constraint * model_constraint) | `Except of (model_constraint * model_constraint) | `Sub_exclusions of (string list * model_constraint) ] ;; type simplified_dtd = (string * (element_class * model_constraint)) list let ( |. ) a b = `Or(a,b);; let ( -. ) a b = `Except(a,b);; let block_elements = (* Only used for exclusions *) [ "p"; "dl"; "div"; "center"; "noscript"; "noframes"; "blockquote"; "form"; "isindex"; "hr"; "table"; "fieldset"; "address"; "h1"; "h2"; "h3"; "h4"; "h5"; "h6"; "pre"; "ul"; "ol"; "dir"; "menu" ];; let html40_dtd = [ (* --------- INLINE ELEMENTS ------------ *) (* %fontstyle; *) "tt", (`Inline, `Inline); "i", (`Inline, `Inline); "b", (`Inline, `Inline); "big", (`Inline, `Inline); "small", (`Inline, `Inline); (* transitional: *) "u", (`Inline, `Inline); "s", (`Inline, `Inline); "strike", (`Inline, `Inline); (* %phrase; *) "em", (`Inline, `Inline); "strong", (`Inline, `Inline); "dfn", (`Inline, `Inline); "code", (`Inline, `Inline); "samp", (`Inline, `Inline); "kbd", (`Inline, `Inline); "var", (`Inline, `Inline); "cite", (`Inline, `Inline); "abbr", (`Inline, `Inline); "acronym", (`Inline, `Inline); (* %special; *) "sup", (`Inline, `Inline); "sub", (`Inline, `Inline); "span", (`Inline, `Inline); "bdo", (`Inline, `Inline); "br", (`Inline, `Empty); "a", (`Inline, `Sub_exclusions(["a"],`Inline)); "img", (`Inline, `Empty); "object", (`Inline, (`Flow |. `Elements ["param"])); "script", (`Inline, `Special); "map", (`Inline, (`Flow |. `Elements ["area"])); "q", (`Inline, `Inline); (* transitional: *) "applet", (`Inline, (`Flow |. `Elements ["param"])); "font", (`Inline, `Inline); "basefont", (`Inline, `Empty); "iframe", (`Inline, `Flow); (* %formctrl; *) "input", (`Inline, `Empty); "select", (`Inline, `Elements ["optgroup"; "option"]); "textarea", (`Inline, `Elements []); (* #PCDATA *) "label", (`Inline, `Sub_exclusions( ["label"], `Inline)); "button", (`Inline, `Sub_exclusions( ["a"; "input"; "select"; "textarea"; "label"; "button"; "form"; "fieldset"; "isindex"; "iframe"], `Flow)); (* ------------ BLOCK ELEMENTS ----------*) "p", (`Block, `Inline); (* %heading; *) "h1", (`Block, `Inline); "h2", (`Block, `Inline); "h3", (`Block, `Inline); "h4", (`Block, `Inline); "h5", (`Block, `Inline); "h6", (`Block, `Inline); (* %list; *) "ul", (`Block, `Elements ["li"]); "ol", (`Block, `Elements ["li"]); (* transitional: *) "dir", (`Block, `Sub_exclusions( block_elements, `Elements ["li"])); "menu", (`Block, `Sub_exclusions( block_elements, `Elements ["li"])); (* %preformatted; *) "pre", (`Block, `Sub_exclusions( [ "img"; "object"; "applet"; "big"; "small"; "sub"; "sup"; "font"; "basefont"], `Inline )); (* other: *) "dl", (`Block, `Elements ["dt"; "dd"]); "div", (`Block, `Flow); "noscript", (`Block, `Flow); "blockquote", (`Block, (`Flow |. `Elements ["script"])); (* strict DTD has `Block here *) "form", (`Block, `Sub_exclusions( ["form"], `Flow |. `Elements ["script"])); (* strict DTD has `Block here *) "hr", (`Block, `Empty); "table", (`Block, `Elements ["caption"; "col"; "colgroup"; "thead"; "tfoot"; "tbody"; "tr"]); "fieldset", (`Block, (`Flow |. `Elements ["legend"])); "address", (`Block, `Inline); (* transitional: *) "center", (`Block, `Flow); "noframes", (`Block, `Flow); "isindex", (`Block, `Empty); (* ------------ OTHER ELEMENTS ----------*) "body", (`None, (`Flow |. `Elements ["script"])); (* strict DTD has `Block here *) "area", (`None, `Empty); "link", (`None, `Empty); "param", (`None, `Empty); "ins", (`Everywhere, `Flow); "del", (`Everywhere, `Flow); "dt", (`None, `Inline); "dd", (`None, `Flow); "li", (`None, `Flow); "optgroup", (`None, `Elements ["option"]); "option", (`None, `Elements []); (* #PCDATA *) "legend", (`None, `Inline); "caption", (`None, `Inline); "thead", (`None, `Elements ["tr"]); "tbody", (`None, `Elements ["tr"]); "tfoot", (`None, `Elements ["tr"]); "colgroup", (`None, `Elements ["col"]); "col", (`None, `Empty); "tr", (`None, `Elements ["th"; "td"]); "th", (`None, `Flow); "td", (`None, `Flow); "head", (`None, `Elements ["title"; "base"; "script"; "style"; "meta"; "link"; "object"]); "title", (`None, `Elements []); (* #PCDATA *) "base", (`None, `Empty); "meta", (`None, `Empty); "style", (`None, `Special); "html", (`None, (`Flow |. `Elements ["head"; "title"; "base"; "script"; "style"; "meta"; "link"; "object"; "body"; "frameset"])); (* transitional: *) "frameset", (`None, `Elements ["frameset"; "frame"; "noframes"]); "frame", (`None, `Empty); ] ;; let relax_dtd dtd = (* Changes (`Inline, `Inline) constraints into (`Inline, `Flow). *) let rec relax_model m = match m with `Inline -> `Flow | `Sub_exclusions(l,m') -> `Sub_exclusions(l,relax_model m') | other -> other in List.map (fun (name, (elclass, elconstr)) -> match elclass with `Inline -> (name, (elclass, relax_model elconstr)) | other -> (name, (elclass, elconstr)) ) dtd ;; let essential_blocks dtd elements = (* Changes the passed block elements into essential block elements *) List.map (fun (name, (elclass, elconstr)) -> match elclass with `Block when List.mem name elements -> (name, ( `Essential_block, elconstr)) | other -> (name, (elclass, elconstr)) ) dtd ;; let relaxed_html40_dtd = essential_blocks (relax_dtd html40_dtd) [ "body"; "table"; "ol"; "ul"; "dl" ] ;; let rec parse_comment buf = let t = scan_comment buf in match t with Mcomment -> let s = Lexing.lexeme buf in s ^ parse_comment buf | Eof -> raise End_of_scan | _ -> (* must be Rcomment *) "" ;; let rec parse_doctype buf = let t = scan_doctype buf in match t with Mdoctype -> let s = Lexing.lexeme buf in s ^ parse_doctype buf | Eof -> raise End_of_scan | _ -> (* must be Rdoctype *) "" ;; let rec parse_pi buf = let t = scan_pi buf in match t with Mpi -> let s = Lexing.lexeme buf in s ^ parse_pi buf | Eof -> raise End_of_scan | _ -> (* must be Rpi *) "" ;; let hashtbl_from_alist l = let ht = Hashtbl.create (List.length l) in List.iter (fun (k, v) -> Hashtbl.add ht k v) l; ht ;; module S = struct type t = string let compare = (Pervasives.compare : string -> string -> int) end module Strset = Set.Make(S);; let parse_document ?(dtd = html40_dtd) ?(return_declarations = false) ?(return_pis = false) ?(return_comments = false) ?(case_sensitive = false) buf = let current_name = ref "" in let current_atts = ref [] in let current_subs = ref [] in let current_excl = ref Strset.empty in (* current exclusions *) let stack = Stack.create() in let dtd_hash = hashtbl_from_alist dtd in let maybe_lowercase = if case_sensitive then (fun s -> s) else String.lowercase in let model_of element_name = if element_name = "" then (`Everywhere, `Any) else let extract = function (eclass, `Sub_exclusions(_,m)) -> eclass, m | m -> m in try extract(Hashtbl.find dtd_hash element_name) with Not_found -> (`Everywhere, `Any) in let exclusions_of element_name = if element_name = "" then [] else let extract = function (eclass, `Sub_exclusions(l,_)) -> l | _ -> [] in try extract(Hashtbl.find dtd_hash element_name) with Not_found -> [] in let is_possible_subelement parent_element parent_exclusions sub_element = let (sub_class, _) = model_of sub_element in let rec eval m = match m with `Inline -> sub_class = `Inline | `Block -> sub_class = `Block || sub_class = `Essential_block | `Flow -> sub_class = `Inline || sub_class = `Block || sub_class = `Essential_block | `Elements l -> List.mem sub_element l | `Any -> true | `Or(m1,m2) -> eval m1 || eval m2 | `Except(m1,m2) -> eval m1 && not (eval m2) | `Empty -> false | `Special -> false | `Sub_exclusions(_,_) -> assert false in (sub_class = `Everywhere) || ( (not (Strset.mem sub_element parent_exclusions)) && let (_, parent_model) = model_of parent_element in eval parent_model ) in let unwind_stack sub_name = (* If the current element is not a possible parent element for sub_name, * search the parent element in the stack. * Either the new current element is the parent, or there was no * possible parent. In the latter case, the current element is the * same element as before. *) let backup = Stack.create() in let backup_name = !current_name in let backup_atts = !current_atts in let backup_subs = !current_subs in let backup_excl = !current_excl in try while not (is_possible_subelement !current_name !current_excl sub_name) do (* Maybe we are not allowed to end the current element: *) let (current_class, _) = model_of !current_name in if current_class = `Essential_block then raise Stack.Empty; (* End the current element and remove it from the stack: *) let grant_parent = Stack.pop stack in Stack.push grant_parent backup; (* Save it; may we need it *) let (gp_name, gp_atts, gp_subs, gp_excl) = grant_parent in (* If gp_name is an essential element, we are not allowed to close * it implicitly, even if that violates the DTD. *) let current = Element (!current_name, !current_atts, List.rev !current_subs) in current_name := gp_name; current_atts := gp_atts; current_excl := gp_excl; current_subs := current :: gp_subs done; with Stack.Empty -> (* It did not work! Push everything back to the stack, and * resume the old state. *) while Stack.length backup > 0 do Stack.push (Stack.pop backup) stack done; current_name := backup_name; current_atts := backup_atts; current_subs := backup_subs; current_excl := backup_excl in let parse_atts() = let rec next_no_space p_string = (* p_string: whether string literals in quotation marks are allowed *) let tok = if p_string then scan_element_after_Is buf else scan_element buf in match tok with Space _ -> next_no_space p_string | t -> t in let rec parse_atts_lookahead next = match next with | Relement -> ( [], false ) | Relement_empty -> ( [], true ) | Name n -> ( match next_no_space false with Is -> ( match next_no_space true with Name v -> let toks, is_empty = parse_atts_lookahead (next_no_space false) in ( (maybe_lowercase n, v) :: toks, is_empty ) | Literal v -> let toks, is_empty = parse_atts_lookahead (next_no_space false) in ( (maybe_lowercase n,v) :: toks, is_empty ) | Eof -> raise End_of_scan | Relement -> (* Illegal *) ( [], false ) | Relement_empty -> (* Illegal *) ( [], true ) | _ -> (* Illegal *) parse_atts_lookahead (next_no_space false) ) | Eof -> raise End_of_scan | Relement -> (* <==> *) ( [ maybe_lowercase n, maybe_lowercase n ], false) | Relement_empty -> (* <==> *) ( [ maybe_lowercase n, maybe_lowercase n ], true) | next' -> (* assume <==> *) let toks, is_empty = parse_atts_lookahead next' in ( ( maybe_lowercase n, maybe_lowercase n ) :: toks, is_empty) ) | Eof -> raise End_of_scan | _ -> (* Illegal *) parse_atts_lookahead (next_no_space false) in parse_atts_lookahead (next_no_space false) in let rec parse_special name = (* Parse until
*) match scan_special buf with | Lelementend n -> if maybe_lowercase n = name then "" else " raise End_of_scan | Cdata s -> s ^ parse_special name | _ -> (* Illegal *) parse_special name in let rec skip_element() = (* Skip until ">" (or "/>") *) match scan_element buf with | Relement | Relement_empty -> () | Eof -> raise End_of_scan | _ -> skip_element() in let rec parse_next() = let t = scan_document buf in match t with | Lcomment -> let comment = parse_comment buf in if return_comments then current_subs := (Element("--",["contents",comment],[])) :: !current_subs; parse_next() | Ldoctype -> let decl = parse_doctype buf in if return_declarations then current_subs := (Element("!",["contents",decl],[])) :: !current_subs; parse_next() | Lpi -> let pi = parse_pi buf in if return_pis then current_subs := (Element("?",["contents",pi],[])) :: !current_subs; parse_next() | Lelement name -> let name = maybe_lowercase name in let (_, model) = model_of name in ( match model with `Empty -> let atts, _ = parse_atts() in unwind_stack name; current_subs := (Element(name, atts, [])) :: !current_subs; parse_next() | `Special -> let atts, is_empty = parse_atts() in unwind_stack name; let data = if is_empty then "" else ( let d = parse_special name in (* Read until ">" *) skip_element(); d ) in current_subs := (Element(name, atts, [Data data])) :: !current_subs; parse_next() | _ -> let atts, is_empty = parse_atts() in (* Unwind the stack until we find an element which can be * the parent of the new element: *) unwind_stack name; if is_empty then ( (* Simple case *) current_subs := (Element(name, atts, [])) :: !current_subs; ) else ( (* Push the current element on the stack, and this element * becomes the new current element: *) let new_excl = exclusions_of name in Stack.push (!current_name, !current_atts, !current_subs, !current_excl) stack; current_name := name; current_atts := atts; current_subs := []; List.iter (fun xel -> current_excl := Strset.add xel !current_excl) new_excl; ); parse_next() ) | Cdata data -> current_subs := (Data data) :: !current_subs; parse_next() | Lelementend name -> let name = maybe_lowercase name in (* Read until ">" *) skip_element(); (* Search the element to close on the stack: *) let found = (name = !current_name) || try Stack.iter (fun (old_name, _, _, _) -> if name = old_name then raise Found; match model_of old_name with `Essential_block, _ -> raise Not_found; (* Don't close essential blocks implicitly *) | _ -> ()) stack; false with Found -> true | Not_found -> false in (* If not found, the end tag is wrong. Simply ignore it. *) if not found then parse_next() else begin (* If found: Remove the elements from the stack, and append * them to the previous element as sub elements *) while !current_name <> name do let old_name, old_atts, old_subs, old_excl = Stack.pop stack in current_subs := (Element (!current_name, !current_atts, List.rev !current_subs)) :: old_subs; current_name := old_name; current_atts := old_atts; current_excl := old_excl done; (* Remove one more element: the element containing the element * currently being closed. *) let old_name, old_atts, old_subs, old_excl = Stack.pop stack in current_subs := (Element (!current_name, !current_atts, List.rev !current_subs)) :: old_subs; current_name := old_name; current_atts := old_atts; current_excl := old_excl; (* Go on *) parse_next() end | Eof -> raise End_of_scan | _ -> parse_next() in try parse_next(); (* never returns. Will get a warning X *) assert false with End_of_scan -> (* Close all remaining elements: *) while Stack.length stack > 0 do let old_name, old_atts, old_subs, old_excl = Stack.pop stack in current_subs := Element (!current_name, !current_atts, List.rev !current_subs) :: old_subs; current_name := old_name; current_atts := old_atts; current_excl := old_excl done; List.rev !current_subs ;; let parse ?dtd ?return_declarations ?return_pis ?return_comments ?case_sensitive ch = let buf = Netchannels.lexbuf_of_in_obj_channel ch in parse_document ?dtd ?return_declarations ?return_comments ?return_pis ?case_sensitive buf ;; type xmap_value = | Xmap_attribute of string * string * string (* elname, attname, attval *) | Xmap_data of string option * string (* elname, pcdata *) let rec xmap f surelem doc = (* surdoc: surrounding element *) match doc with | Element(name,atts,subdocs) -> (match name with | "!" | "?" | "--" -> Element(name,atts,xmap_list f None subdocs) | _ -> let atts' = List.map (fun (aname,aval) -> aname, f (Xmap_attribute(name, aname, aval)) ) atts in let subdocs' = xmap_list f (Some name) subdocs in Element(name,atts',subdocs') ) | Data s -> Data(f (Xmap_data(surelem,s))) and xmap_list f surelem l = List.map (xmap f surelem) l;; let map_list f l = xmap_list (function | Xmap_attribute(_, _, v) -> f v | Xmap_data(_, v) -> f v ) None l let encode ?(enc = `Enc_iso88591) ?(prefer_name = true) ?(dtd = html40_dtd) dl = let enc_string = Netencoding.Html.encode ~in_enc:enc ~out_enc:`Enc_usascii ~prefer_name () in let dtd_hash = hashtbl_from_alist dtd in let enc_node = function | Xmap_attribute(_, _, v) -> enc_string v | Xmap_data(None, v) -> enc_string v | Xmap_data(Some el, v) -> let is_special = try snd(Hashtbl.find dtd_hash el) = `Special with Not_found -> false in if is_special then v else enc_string v in xmap_list enc_node None dl ;; let decode ?(enc = `Enc_iso88591) ?subst ?entity_base ?lookup ?(dtd = html40_dtd) dl = let dec_string = Netencoding.Html.decode ~in_enc:enc ~out_enc:enc ?subst ?entity_base ?lookup () in let dtd_hash = hashtbl_from_alist dtd in let dec_node = function | Xmap_attribute(_, _, v) -> dec_string v | Xmap_data(None, v) -> dec_string v | Xmap_data(Some el, v) -> let is_special = try snd(Hashtbl.find dtd_hash el) = `Special with Not_found -> false in if is_special then v else dec_string v in xmap_list dec_node None dl ;; let quote_quot_re = Netstring_str.regexp "\"";; let write_ ~dtd ~xhtml write_os doc = let quote_quot s = Netstring_str.global_substitute quote_quot_re (fun _ _ -> """) s in let rec trav doc = match doc with Element(name,atts,subdocs) -> ( match name with "!" -> write_os ""; | "?" -> write_os ""; | "--" -> write_os ""; | _ -> let is_empty = try let _, constr = List.assoc name dtd in constr = `Empty with Not_found -> false in write_os "<"; write_os name; List.iter (fun (aname,aval) -> write_os " "; write_os aname; write_os "=\""; write_os (quote_quot aval); write_os "\""; ) atts; if is_empty then (* Ignore subdocs (even if <> []) because they should not be there. *) write_os (if xhtml then "/>" else ">") else begin write_os ">"; List.iter trav subdocs; write_os ""; end ) | Data s -> write_os s in try List.iter trav doc with Not_found -> failwith "write" ;; let write ?(dtd = html40_dtd) ?(xhtml = true) ch doc = write_ ~dtd ~xhtml (ch # output_string) doc ocamlnet-4.1.2/src/netstring/netdb.ml0000644000175000017500000000234712731530350016203 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) let values = Hashtbl.create 13 let loaders = Hashtbl.create 13 let cksums = Hashtbl.create 13 let enabled = ref true let read_db name = let v = try Hashtbl.find values name with | Not_found -> if not !enabled then failwith ("Ocamlnet: The lookup table `" ^ name ^ "' is not compiled into the program, and access to " ^ "the external file database is disabled"); let loader = try Hashtbl.find loaders name with | Not_found -> failwith ("Ocamlnet: No such lookup table: " ^ name) in loader name in try let cksum = Hashtbl.find cksums name in if Digest.string v <> cksum then failwith ("Netdb: checksum error for table: " ^ name); v with | Not_found -> v let exists_db name = Hashtbl.mem values name || (!enabled && Hashtbl.mem loaders name) let set_db name value = Hashtbl.replace values name value let set_db_checksum name cksum = Hashtbl.replace cksums name cksum let set_db_loader name loader = Hashtbl.replace loaders name loader let enable_db_loaders b = enabled := b ocamlnet-4.1.2/src/netstring/netmime_tut.txt0000644000175000017500000003646012731530350017653 0ustar gerdgerd{1:tutorial Netmime Tutorial} {2 Structure of Mail Messages} Nowadays mail messages are in MIME format. This format allows us to attach files to messages, and to encode the main text in markup languages like HTML. In principle, mail messages have only one header block (with fields like "Subject", sender and receiver addresses, etc.) and one body block. However, this is only one view on the mail format, e.g. as seen by MTAs (mail transfer agents). The MIME format adds the possibility to structure the body block into "parts" by additional encoding sequences. The MTAs can simply ignore this additional stuff, but software creating and analyzing mails can usually not. In [Netmime], one can control whether one wants to see the parts or not. Logically, the parts of the mail body are small mail messages themselves. This means that every part has again a header and a body. The header can, in principal, contain any number of fields, and any kind of field, but in practice only a small subset of the possible fields are used, in particular only those fields that are necessary to describe the body of the part. The body can be a normal text or data block, but it is explicitly also allowed that the body is again structured into a sequence of parts. Thus complex mail messages are recursive data structures (to be exact, they are trees). For example, a message with two attachments usually looks like: {[ (mail_header, mail_body) | +-- (main_text_header, main_text_body) +-- (att1_header, att1_body) +-- (att2_header, att2_body) ]} The headers contains two crucial fields that control the structure of the message: - The [Content-type] describes the kind of data found in the body, e.g. "text/html". When the [Content-type] has the major type "multipart" (e.g. "multipart/mixed"), the body is composed of subparts. For all other types, the body is a leaf of the message tree. (To be exact, there is another major type that opens a further dimension of "message-in-message" composition: "message". This type is usually used when it is not clear whether the inner message is syntactically correct. [Netmime] handles this type always as leaf, but users of [Netmime] can try to parse these inner messages themselves.) - The [Content-transfer-encoding] describes how the body data is encoded as ASCII text. It is usually only set for leaves. Recommended values are ["quoted-printable"] for bodies that contain some kind of ASCII text, and ["base64"] for binary data. {2 Messages in [Netmime]} In [Netmime], the types of mail headers and mail bodies are defined before and independent of their implementations: We have the types - [class type mime_header]: Specification of possible header implementations - [class type mime_body]: Specification of possible body implementations - [type complex_mime_message]: The type of a message tree and the implementations - [class basic_mime_header]: A basic header implementation - [class memory_mime_body]: A body implementation storing the contents in an O'Caml string in-memory - [class file_mime_body]: A second body implementation storing the contents in an external file Of course, the implementation classes fulfill the specifications of the corresponding class types. For completeness, there are also reduced read-only class types that maybe helpful for signatures to indicate that a function does not modify a header or body. In principal, one can also define further implementations provided they fit to the class types. The type [complex_mime_message] represents the message as a tree. We have: {[ type complex_mime_message = mime_header * complex_mime_body and complex_mime_body = [ `Body of mime_body | `Parts of complex_mime_message list ] ]} For example, the above mentioned mail with two attachments has the following representation: {[ let tree = (mail_header, `Parts [ (main_text_header, `Body main_text_body); (att1_header, `Body att1_body); (att2_header, `Body att2_body) ] ) ]} Here, [*_header] are objects of type [mime_header], and [*_body] are objects of type [mime_body]. It is obvious how to create the tree once one has these objects: Just use the syntax in this expression. Beginners of O'Caml should recall that it is as easy to decompose such structured values by using the pattern matching feature of the language. For example, to get the [main_text_header] of [tree], use {[ let main_text_header = match tree with (_, `Parts ( (mth, _) :: _ )) -> mth | _ -> failwith "Message has unexpected structure" ]} (Note that [ [x1;x2;...] ] is just an abbreviation for [ x1 :: x2 :: ... :: [] ]; by switching to the "::" syntax the message may have any number of parts in order to be matching.) At the first glance, it looks a bit strange to access the inner parts of mail messages in this way, but pattern matching is a very powerful sword once one gets accustomed to it. Another hint: Because [complex_mime_message] is a quite challanging type for the compiler, it is often necessary to give type annotations, such as [ (tree : complex_mime_message) ] before passing such values to functions, otherwise you get compiler errors. {2 Accessing Headers} It is easy to get and set the fields of headers, e.g. [ mail_header # field "subject" ] returns the "Subject" header field as string (or raises [Not_found]). The names of header fields are case-insensitive. To set a field, use [update_field], e.g. [ mail_header # update_field "subject" "Ocamlnet is great" ]. The methods [field] and [update_field] process the field value as unparsed string (the parsers do only very little preprocessing, e.g. one can configure to remove all linefeeds). The module {!Netmime_string} has a lot functions to parse and generate field values with a certain syntax. For example, "Subject" may contain so-called encoded words to express text written in a character set other than ASCII. To parse this, use {[ let subject = mail_header # field "subject" in let word_list = Netmime_string.scan_encoded_text_value subject in ]} Now, the words contained in [word_list] can be accessed with a number of functions, e.g. {[ let word_val = Netmime_string.get_decoded_word word in let word_cset = Netmime_string.get_charset word ]} Here, the string [word_val] is the word written in the character set [word_cset]. For example, for the "Subject" field [=?iso-8859-1?q?this=20is=20some=20text?=] this method returns a [word_list] with one word, and for this word [word_val = "this is some text"] and [word_cset = "iso-8859-1"]. To create such structured header values, there is the function [write_value] in {!Netmime_string}. This function requires some more background beyond the scope of this tutorial. As this function also supports folding of header fields, we explain only this particular application. Folding means that long header values must be split into several lines. There is a soft limit of 78 bytes and a hard limit of 998 bytes (not counting the end-of-line sequence). The soft limit only ensures that values can be displayed in usual terminals or windows without needing horizontal scrolling. Values exceeding the hard limit may be truncated in mail transport, however. To fold a string [s] composed of words, first split it into its [words], make atoms of them, format them with [write_value], and put the result into the header field (note: this example can be programmed better, see below): {[ let name = "Subject" in let words = Str.split (Str.regexp "[ \t]+") s in let atoms = List.map (fun w -> Netmime_string.Atom w) in let buf = Buffer.create 100 in let ch = new Netchannels.output_buffer buf in Netmime_string.write_value ~maxlen1:(78 - String.length name - 2) ~maxlen:78 ~hardmaxlen1:(998 - String.length name - 2) ~hardmaxlen:998 ch; mail_header # update_field name (Buffer.contents buf) ]} Unfortunately, there is no general method that can fold any kind of string. The problem is that folding is only allowed at certain places in the string, but this depends on the type of the header field. The shown method works only for informational texts like "Subject". For other fields, like "Received", the method would have to be varied, especially how the list [atoms] is determined. The syntax of the field must be known to compute [atoms]. In the module {!Netsendmail} you can find formatting and folding functions for informational texts like "Subject", and for mail addresses. With these functions, the "Subject" field could also be set by {[ let atoms = Netsendmail.create_text_tokens s in mail_header # update_field name (Netsendmail.format_field_value name atoms) ]} {2 Accessing Bodies} Both types of bodies (in-memory, and file) support the following two ways of accessing: - Get/set the value as O'Caml string - Read/write the value as object channel (see {!Netchannels}) Note that when the value of a file-based body is changed, the file is overwritten, independently of which of the two ways is taken. The [string] access is very simple: To get the value, just call [value]: [ let s = body # value ] To set the value, just call [set_value]: [ body # set_value s ] The string returned by [value] is not transfer-encoded, or better, all such encodings (e.g. BASE-64) are decoded. Of course, [set_value] expects that the passed string is not decoded, too. Note that using [value] may be dangerous (or even fail) when the body is stored in a file and is very large. [value] forces that the file is completely read into memory. You may run into serious problems when there is not enough memory, or when the value is larger than [Sys.max_string_length] (16MB on 32 bit platforms). Fortunately, there is the channel-based access method. It does not need much memory, even when large bodies are accessed. However, one does not get access to the completely body at once, but only chunk by chunk. For example, to read a body line by line, use: {[ let ch = body # open_value_rd() in let line1 = ch # input_line() in let line2 = ch # input_line() in ... ch # close_in() ]} As for [value], there are no transfer encodings in the returned lines. The channel [ch] can be used whereever an Ocamlnet function allows it, i.e. it is a full implementation. For example, one can pass it to the HTML parser: {[ let ch = body # open_value_rd() in let html_doc = Nethtml.parse ch in ch # close_in() ]} To set the value using a channel, a body can also be opened for writing: {[ let ch = body # open_value_wr() in ch # output_string "First line\n"; ch # output_string "Second line\n"; ... ch # close_out() ]} {2 Parsing mail messages} The message to parse must be available as an object channel. Recall that you can create an object channel from a string with [ let ch = new Netchannels.input_string s ] and from a file with [ let ch = new Netchannels.input_channel (open_in "filename") ] so one can parse mail messages coming from any source. As only sequential access is needed, it is even possible to read directly from a Unix pipe. Now, it is required to create a so-called netstream from [ch]: [ let nstr = new Netstream.input_stream ch ] A netstream is an object channel with additional look-ahead features. We need it here because the parser can then recognize certain patterns in the message in a simpler manner, for example the escape sequences separating the parts of a structured body. Finally, one can invoke the parser: [ let tree = Netmime_channels.read_mime_message nstr ] There are a number of optional arguments for this function that can modify the way the message tree is generated. By default, all bodies are created in memory, and the tree is deeply parsed (i.e. inner multipart bodies are represented in tree form). When bodies should be written to disk, the argument [storage_style] can be passed: It is a function that is called whenever a header has been parsed, but before the corresponding body. The function must return the body object for representation and the output channel connected to the body object. For example, to write the bodies into numbered files: {[ let n = ref 1 let ext_storage_style header = let body = new file_mime_body ("file" ^ string_of_int !n) in incr n; (body, body#open_out_wr()) let tree = read_mime_message ~storage_style:ext_storage_style nstr ]} There is also the auxiliary function [storage] to create such a storage style argument. The [header] can be used to generate the file name from it. Often, the [filename] argument of the [Content-disposition] field is the original file name before the attachment was appended to the mail message. To get this name: {[ let filename = try let disp, disp_params = header # content_disposition() in (* disp is usually "attachment", but we don't check *) List.assoc "filename" disp_params with Not_found -> ... (* No such paramater, use other method to gen filename *) ]} It is usually a good idea to check for dangerous characters in this name ("/", "..") before constructing the name of the disk file. A final remark: Don't forget to close [nstr] after parsing (this implicitly closes [ch]). {2 Creating Mail Messages} For simple applications, the {!Netsendmail} module has a {!Netsendmail.compose} function. It can create a mail message with attachments, and performs all the encoding details. This function is well explained in its module mli. Of course, you can also do this yourself: Create the required headers and bodies, and put them together to the resulting [tree]. Example: {[ let date = Netdate.mk_mail_date ~zone:Netdate.localzone (Unix.time()) in let mail_header = new basic_mime_header [ "MIME-version", "1.0"; "Subject", "Sample mail"; "To", "recipient\@domain.net"; "From", "sender\@domain.net"; "Date", date; "Content-type", "multipart/mixed" ] in let main_text_header = new basic_mime_header [ "Content-type", "text/plain;charset=ISO-8859-1"; "Content-transfer-encoding", "quoted-printable"; ] in let main_text_body = new memory_mime_body "Hello world!\nThis is a sample mail.\n" in let att_header = new basic_mime_header [ "Content-type", "image/jpeg"; "Content-transfer-encoding", "base64"; "Content-disposition", "inline;description=\"My photo\""; ] in let att_body = new file_mime_body "photo.jpeg" in let tree = (mail_header, `Parts [ (main_text_header, `Body main_text_body); (att_header, `Body att_body) ] ) ]} {2 Printing Mail Messages} In order to print [tree] to the object channel [ch], simply call [ Netmime_channels.write_mime_message ch tree ] Before invoking this function, ensure the following: - The [Content-type] field of all leaves should be set - The [Content-transfer-encoding] field of all leaves should be set (in doubt use "base64"; if missing, the default is "7bit" - probably not what you want) - The [Content-type] field of multipart nodes should be set (it defaults to "multipart/mixed" if missing) - The [Content-transfer-encoding] fields of multipart nodes should {b not} be set - this is done by the function If the [boundary] parameter is missing, the function will invent one; you don't need to deal with this. The MIME message is written according to the found transfer encodings and the multi-part boundaries. Don't forget to close [ch] after writing! ocamlnet-4.1.2/src/netstring/netconst.mli0000644000175000017500000000013212731530350017103 0ustar gerdgerd(* $Id$ *) val ocamlnet_version : string (* Returns the version string of Ocamlnet *) ocamlnet-4.1.2/src/netstring/netmech_digest_http.ml0000644000175000017500000001233712731530350021130 0ustar gerdgerd(* $Id$ *) open Netmech_digest open Printf module type PROFILE = sig val mutual : bool val hash_functions : Netsys_digests.iana_hash_fn list end module Make_digest(P:PROFILE) : Nethttp.HTTP_CLIENT_MECHANISM = struct let profile = { ptype = `HTTP; hash_functions = List.filter hash_available P.hash_functions; mutual = P.mutual } let mechanism_name = "Digest" let available() = profile.hash_functions <> [] let restart_supported = true type credentials = (string * string * (string * string) list) list type client_session = Netmech_digest.client_session let format_kv l = List.map (fun (k,v) -> k ^ "=" ^ v) l let init_credentials l = (l:credentials) let client_state cs = cs.cstate let create_client_session ~user ~creds ~params () = let params = Netsys_sasl_util.preprocess_params "Netmech_digest_http.create_client_session:" [ "realm"; "cnonce"; ] params in let pw = try Netsys_sasl_util.extract_password creds with Not_found -> failwith "Netmech_digest_http.create_client_session: no password \ found in credentials" in { cstate = `Wait; cresp = None; cprofile = profile; cdigest_uri = ""; cmethod = ""; crealm = (try Some(List.assoc "realm" params) with Not_found -> None); cuser = user; cauthz = ""; cpasswd = pw; cnonce = (try List.assoc "cnonce" params with Not_found -> create_nonce()); } let client_configure_channel_binding cs cb = if cb <> `None then failwith "Netmech_digest_http.client_configure_channel_binding: \ not supported" else cs let client_restart ~params cs = if cs.cstate <> `OK then failwith "Netmech_digest_http.client_restart: unfinished auth"; client_restart_i cs let decode_params l = List.map (function | (n, `Q _) -> assert false | (n, `V v) -> (n,v) ) l let client_process_challenge cs method_name uri hdr challenge = match cs.cresp with | None -> let (_, msg_params) = challenge in let msg_params = decode_params msg_params in let cs = client_process_initial_challenge_kv cs msg_params in ( match cs.cresp with | None -> cs | Some rp -> let rp' = { rp with r_digest_uri = uri; r_method = method_name } in { cs with cresp = Some rp' } ) | Some rp -> (* There must be an Authorization-Info header *) ( try let info = hdr # field "authentication-info" in let info_params = Nethttp.Header.parse_quoted_parameters info in client_process_final_challenge_kv cs info_params (* NB. This function ignores cnonce and nc. They are actually not needed for verification. *) with | Not_found | Failure _ -> { cs with cstate = `Auth_error "bad Authentication-info header" } ) let client_emit_response cs method_name uri hdr = if cs.cstate <> `Emit && cs.cstate <> `Stale then failwith "Netmech_digest_http.client_emit_response: bad state"; let cs = client_modify ~mod_method:method_name ~mod_uri:uri cs in let cs, l1 = client_emit_response_kv ~quote:true cs in let l2 = List.map (fun (n,v) -> (n, `Q v)) l1 in (cs, ("Digest", l2), []) let client_user_name cs = cs.cuser let client_stash_session cs = client_stash_session_i cs let client_resume_session s = client_resume_session_i s let client_session_id cs = None let client_prop cs key = client_prop_i cs key let client_gssapi_props cs = raise Not_found let client_channel_binding cs = `None let client_domain cs = match cs.cresp with | None -> [] | Some r -> let d = r.r_domain in if d <> [] then d else [ "/" ] (* whole server *) (* NB. the uri's are passed through Nethttp_client.normalize_domain, so server-relative paths can be interpreted *) let client_match ~params (ch_name, ch_params) = try if String.lowercase ch_name <> "digest" then raise Not_found; let cs = create_client_session ~user:"user" ~creds:["password","",[]] ~params () in let hdr = new Netmime.basic_mime_header [] in let cs = client_process_challenge cs "DUMMY" "dummy" hdr (ch_name, ch_params) in if cs.cstate = `Emit then match cs.cresp with | Some rp -> `Accept(rp.r_realm, None) | None -> `Reject else `Reject with | Not_found | Failure _ -> `Reject end module Digest = Make_digest( struct let mutual = false let hash_functions = [ `SHA_256; `MD5 ] end ) module Digest_mutual = Make_digest( struct let mutual = true let hash_functions = [ `SHA_256; `MD5 ] end ) ocamlnet-4.1.2/src/netstring/netsendmail.ml0000644000175000017500000002506112731530350017410 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) open Netchannels open Netmime open Netmime_string let sendmail_program = "/usr/lib/sendmail" ;; let only_usascii_re = Netstring_str.regexp "^[\001-\127]*$";; let specials_re = Netstring_str.regexp "[]<>\"\\,()@;:.[/=?]" (* PCRE: "[\\<\\>\\\"\\\\\\,\\(\\)\\@\\;\\:\\.\\[\\]\\/\\=\\?]" *) let exists rex s = try ignore(Netstring_str.search_forward rex s 0); true with Not_found -> false ;; let ws_re = Netstring_str.regexp "[ \t\r\n]+" let create_address_tokens ?(in_charset = `Enc_iso88591) ?(out_charset = `Enc_iso88591) (hr_addr, formal_addr)= (* Generates addresses like "Gerd Stolpmann ". * hr_addr is the "human readable" part, and formal_addr is the formal * address. hr_addr must be encoded by [charset]. *) let hr_addr = Netconversion.convert ~in_enc:in_charset ~out_enc:out_charset hr_addr in let hr_words = if Netstring_str.string_match only_usascii_re hr_addr 0 <> None then begin (* Use double quotes to protect meta characters *) if exists specials_re hr_addr then [Netmime_string.QString hr_addr] else List.map (fun s -> Netmime_string.Atom s) (Netstring_str.split ws_re hr_addr) end else [Netmime_string.EncodedWord((Netconversion.string_of_encoding out_charset,""), "Q", hr_addr)] in (* TODO: Check syntax of formal_addr *) let formal_words = [ Netmime_string.Special '<'; Netmime_string.Atom formal_addr; Netmime_string.Special '>' ] in (hr_words @ [ Netmime_string.Special ' ' ] @ formal_words) ;; let create_address_list_tokens ?in_charset ?out_charset addrs = let rec map addrs = match addrs with [] -> [] | addr :: (addr' :: _ as addrs') -> create_address_tokens ?in_charset ?out_charset addr @ [ Netmime_string.Special ','; Netmime_string.Special ' ' ] @ map addrs' | [ addr ] -> create_address_tokens ?in_charset ?out_charset addr in map addrs ;; let format_field_value fieldname tokens = let val_buf = Buffer.create 80 in let val_ch = new output_buffer val_buf in let maxlen = 78 in let hardmaxlen = 998 in let initlen = String.length fieldname + 2 in (* String.length ": " = 2 *) Netmime_string.write_value ~maxlen1:(maxlen - initlen) ~maxlen ~hardmaxlen1:(hardmaxlen - initlen) ~hardmaxlen val_ch tokens; Buffer.contents val_buf ;; let create_text_tokens ?(in_charset = `Enc_iso88591) ?(out_charset = `Enc_iso88591) value = let value = Netconversion.convert ~in_enc:in_charset ~out_enc:out_charset value in let words = if Netstring_str.string_match only_usascii_re value 0 <> None then List.map (fun s -> Atom s) (Netstring_str.split ws_re value) else [ Netmime_string.EncodedWord((Netconversion.string_of_encoding out_charset,""), "Q", value) ] in words ;; (* Criterions for fields in [fields_to_remove]: * * We want that the message appears as a new message. Because of this * all delivery and transport-related fields are removed. This also * includes delivery and error notifications, transfer priorities, * mailing list information, and local status fields. * * We keep all content-related fields. Sometimes it is difficult to * distinguish between content and transfer fields, especially for * the non-standard fields. * * Sources: * - RFC 2822 * - http://www.dsv.su.se/~jpalme/ietf/mail-headers/mail-headers.html * (former IETF draft, now expired) * - http://www.cs.tut.fi/~jkorpela/headers.html *) let fields_to_remove = [ "date"; "from"; "sender"; "reply-to"; "to"; "cc"; "bcc"; "message-id"; "in-reply-to"; "references"; (* but not subject, comments, keywords *) "resent-date"; "resent-from"; "resent-sender"; "resent-to"; "resent-cc"; "resent-bcc"; "resent-message-id"; "return-path"; "received"; (* non-standard, or other RFCs but frequently used: *) "alternate-recipient"; "x-rcpt-to"; "x-sender"; "x-x-sender"; "envelope-to"; "x-envelope-to"; "envelope-from"; "x-envelope-from"; "errors-to"; "return-receipt-to"; "read-receipt-to"; "x-confirm-reading-to"; "return-receipt-requested"; "registered-mail-reply-requested-by"; "delivery-date"; "delivered-to"; "x-loop"; "precedence"; "priority"; (* but not "importance" *) "x-msmail-priority"; "x-priority"; "apparently-to"; "posted-to"; "content-return"; "x400-content-return"; "disposition-notification-options"; "disposition-notification-to"; "generate-delivery-report"; "original-recipient"; "prevent-nondelivery-report"; "mail-reply-to"; "x-uidl"; "x-imap"; "x-mime-autoconverted"; "list-archive"; "list-digest"; "list-help"; "list-id"; "mailing-list"; "x-mailing-list"; "list-owner"; "list-post"; "list-software"; "list-subscribe"; "list-unsubscribe"; "list-url"; "x-listserver"; "x-list-host"; "status"; ] ;; let wrap_mail ?(in_charset = `Enc_iso88591) ?(out_charset = `Enc_iso88591) ?from_addr ?(cc_addrs = []) ?(bcc_addrs = []) ~to_addrs ~subject (msg : complex_mime_message) : complex_mime_message = let (main_hdr, main_body) = msg in let main_hdr' = new basic_mime_header main_hdr#fields in List.iter main_hdr'#delete_field fields_to_remove; let set_field_toks f toks = main_hdr' # update_field f (format_field_value f toks) in ( match from_addr with None -> () | Some a -> set_field_toks "From" (create_address_list_tokens ~in_charset ~out_charset [ a ]) ); set_field_toks "To" (create_address_list_tokens ~in_charset ~out_charset to_addrs); if cc_addrs <> [] then set_field_toks "Cc" (create_address_list_tokens ~in_charset ~out_charset cc_addrs); if bcc_addrs <> [] then set_field_toks "Bcc" (create_address_list_tokens ~in_charset ~out_charset bcc_addrs); set_field_toks "Subject" (create_text_tokens ~in_charset ~out_charset subject); main_hdr' # update_field "MIME-Version" "1.0"; main_hdr' # update_field "X-Mailer" "OcamlNet (ocamlnet.sourceforge.net)"; main_hdr' # update_field "Date" (Netdate.mk_mail_date ~zone:Netdate.localzone (Unix.time())); (main_hdr', main_body) ;; let create_header ?(in_charset = `Enc_iso88591) ?(out_charset = `Enc_iso88591) ?content_id ?content_description ?content_location ?content_disposition (ct_type, params) = let hdr = new basic_mime_header [] in let set_field_toks f toks = hdr # update_field f (format_field_value f toks) in let toks = Atom ct_type :: param_tokens ~maxlen:60 params in set_field_toks "Content-type" toks; (* Set Content-ID: *) ( match content_id with None -> () | Some cid -> set_field_toks "Content-ID" [Atom ("<" ^ cid ^ ">")] ); (* Set Content-Description: *) ( match content_description with None -> () | Some d -> set_field_toks "Content-Description" (create_text_tokens ~in_charset ~out_charset d); ); (* Set Content-Location: *) ( match content_location with None -> () | Some loc -> set_field_toks "Content-Location" (split_uri loc) ); (* Set Content-Disposition: *) ( match content_disposition with None -> () | Some (d_main, d_params) -> set_field_toks "Content-Disposition" (Atom d_main :: param_tokens ~maxlen:60 d_params) ); hdr ;; let wrap_parts ?(in_charset = `Enc_iso88591) ?(out_charset = `Enc_iso88591) ?(content_type = ("multipart/mixed", [])) ?content_id ?content_description ?content_location ?content_disposition elements = if elements = [] then failwith "Netsendmail.wrap_parts"; (* Check Content-type: *) let (ct_type, params) = content_type in let (main_type, sub_type) = split_mime_type ct_type in if main_type <> "multipart" && main_type <> "message" then failwith "Netsendmail.wrap_parts"; let hdr = create_header ~in_charset ~out_charset ?content_id ?content_description ?content_location ?content_disposition (ct_type, params) in (hdr, `Parts elements) ;; let wrap_attachment ?(in_charset = `Enc_iso88591) ?(out_charset = `Enc_iso88591) ?content_id ?content_description ?content_location ?content_disposition ~content_type body = let hdr = create_header ~in_charset ~out_charset ?content_id ?content_description ?content_location ?content_disposition content_type in (* Set Content-transfer-encoding: *) let (ct_type, params) = content_type in let (main_type, sub_type) = split_mime_type ct_type in let cte = match main_type with "text" -> "quoted-printable" | "multipart" | "message" -> "binary" (* Don't know better *) | _ -> "base64" in hdr # update_field "Content-transfer-encoding" cte; (hdr, `Body body) ;; let compose ?(in_charset = `Enc_iso88591) ?(out_charset = `Enc_iso88591) ?from_addr ?(cc_addrs = []) ?(bcc_addrs = []) ?content_type ?(container_type = ("multipart/mixed" , [])) ?(attachments = ([] : complex_mime_message list)) ~to_addrs ~subject body : complex_mime_message = (* First generate/cleanup (hdr,body) for the main text of the message: *) let body = if content_type = None then Netconversion.convert ~in_enc:in_charset ~out_enc:out_charset body else body in (* Set Content-type: *) let (ct_type, params) = ( match content_type with None -> ("text/plain", [ "charset", mk_param (Netconversion.string_of_encoding out_charset) ]) | Some (ct_type, params) -> (ct_type, params) ) in let (main_hdr, main_body) = wrap_attachment ~in_charset ~out_charset ~content_type:(ct_type, params) (new memory_mime_body body) in (* Generate the container for attachments: *) let mail_hdr, mail_body = if attachments = [] then (main_hdr, main_body) else ( wrap_parts ~in_charset ~out_charset ~content_type:container_type ( (main_hdr, main_body) :: attachments ) ) in wrap_mail ~in_charset ~out_charset ?from_addr ~to_addrs ~cc_addrs ~bcc_addrs ~subject (mail_hdr, mail_body) ;; let sendmail ?(mailer = sendmail_program) ?(crlf = false) message = let cmd = mailer ^ " -B8BITMIME -t -i" in with_out_obj_channel (new output_command cmd) (fun ch -> Netmime_channels.write_mime_message ~crlf ch message; ) ;; ocamlnet-4.1.2/src/netstring/netpagebuffer.mli0000644000175000017500000001136212731530350020072 0ustar gerdgerd(* $Id$ *) (** Buffer for page-aligned I/O *) (** This kind of buffer uses page-aligned bigarrays. Data can only be added to the end, or deleted at the beginning of the buffer. The idea of this buffer is that input data is added to the last page of the buffer only (with [add_inplace]). If then all previous input was already a multiple of the page size, it is ensured that the new input is added at a page boundary. This kind of input operation can often be accelerated by the OS ("zero copy network I/O"). *) open Netsys_types type t val create : int -> t (** create [blocksize]: creates new buffer with this [blocksize], which must be a whole multiple of the page size of the OS The [blocksize] is normally either - {!Netsys_mem.default_block_size}, or - {!Netsys_mem.small_block_size} These cases are optimized, and the buffer is allocated in a shared pool. *) val contents : t -> string (** Returns the contents as string *) val to_bytes : t -> Bytes.t (** Returns the contents of the buffer as fresh string. *) val to_tstring_poly : t -> 's Netstring_tstring.tstring_kind -> 's (** Return the buffer in the format as selected by the arg *) val to_tstring : t -> _ Netstring_tstring.tstring_kind -> tstring (** Returns the buffer as tagged string, selecting the chosen representation *) val length : t -> int (** The length *) val sub : t -> int -> int -> string (** Returns a substring *) val sub_bytes : t -> int -> int -> Bytes.t (** Same for bytes *) val blit_to_bytes : t -> int -> Bytes.t -> int -> int -> unit (** Blits contents to a string *) val blit_to_string : t -> int -> Bytes.t -> int -> int -> unit DEPRECATED("Use blit_to_bytes instead.") val blit_to_memory : t -> int -> Netsys_mem.memory -> int -> int -> unit (** Blits contents to another memory buffer *) val blit_to_tbuffer : t -> int -> tbuffer -> int -> int -> unit (** Blits contents to a tagged buffer *) val blit : t -> int -> Bytes.t -> int -> int -> unit (** Compatibility name for [blit_to_bytes] *) val add_string : t -> string -> unit (** Adds a string to the end of the buffer *) val add_bytes : t -> Bytes.t -> unit (** Same for bytes *) val add_tstring : t -> tstring -> unit (** Same for tagged string *) val add_substring : t -> string -> int -> int -> unit (** Adds a sub string to the end of the buffer *) val add_sub_string : t -> string -> int -> int -> unit DEPRECATED("Use add_substring instead.") val add_subbytes : t -> Bytes.t -> int -> int -> unit (** Adds a sub string to the end of the buffer *) val add_submemory : t -> Netsys_mem.memory -> int -> int -> unit (** Adds a sub memory buffer to the end of the buffer *) val add_sub_memory : t -> Netsys_mem.memory -> int -> int -> unit DEPRECATED("Use add_submemory instead.") val add_subtstring : t -> tstring -> int -> int -> unit (** Adds a sub tstring to the end of the buffer *) val add_inplace : t -> (Netsys_mem.memory -> int -> int -> int) -> int (** [add_inplace b f]: Calls [f m pos len] where [m] is the last page of the buffer, and [pos] is the first free byte on the page, and [len] is the number of free bytes on the page. The function [f] is expected to store new data in [m] from [pos] to [pos+n-1] and to return [n]. The number [n] is also returned as final result. It is ensured that [f] is called with a value of [len>=1]. *) val page_for_additions : t -> (Netsys_mem.memory * int * int) (** [let (m,pos,len) = page_for_additions b]: Returns the last page in [m], the first free byte on the page in [pos], and the number of free bytes on the page in [len]. (The same values the function [f] would have got as arguments in [add_inplace].) *) val advance : t -> int -> unit (** [advance b n]: Marks further [n] bytes in the last page of the buffer as used. These bytes are not modified in any way - it is expected that the user calls [page_for_additions] first, and sets these [n] bytes to new values directly. *) val page_for_consumption : t -> (Netsys_mem.memory * int * int) (** [let (m,pos,len) = page_for_consumption b]: Returns the first page in [m], the first used byte on the page in [pos], and the number of used bytes on the page in [len]. *) val delete_hd : t -> int -> unit (** [delete_hd b n]: Deletes [n] bytes from the beginning of the buffer *) val clear : t -> unit (** Deletes all contents of the buffer *) (** {2 Searching} *) val index_from : t -> int -> char -> int (** [index_from nb k c]: Searches the character [c] in the buffer beginning * at position [k]. If found, the position of the left-most occurence is * returned. Otherwise, [Not_found] is raised. *) ocamlnet-4.1.2/src/netstring/nethttp.mli0000644000175000017500000013501412731530350016744 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * Nethttp: Basic definitions for the HTTP protocol *) (** {1 Basic definitions for the HTTP protocol} *) (** These definitions can be used by both HTTP clients and servers, and by * protocols in the middle, e.g. CGI. *) type protocol_version = int * int (* (major,minor) number *) (** A pair of a major and minor version number *) type protocol_attribute = [ `Secure_https ] type protocol = [ `Http of (protocol_version * protocol_attribute list) | `Other ] (** The base protocol. RFC 2145 defines how to interpret major and * minor numbers. In particular, we have: * - [`Http((0,9),_)] is the ancient HTTP version 0.9 * - [`Http((1,n),_)] is the HTTP protocol 1.n. It is expected that * all these versions are compatible to each other * except negotiable features. * - [`Http((m,_),_)] for m>1 is regarded as unknown protocol, * incompatible to any [`Http((1,n),_)] * - [`Other] is anything else (unrecognizes protocol) *) val string_of_protocol : protocol -> string (** Returns the string representation, e.g. "HTTP/1.0". Fails for [`Other] *) val protocol_of_string : string -> protocol (** Parses the protocol string, e.g. "HTTP/1.0". Returns [`Other] * for unrecognized strings *) type http_status = (* Status codes from RFC 2616 *) (* 1xx: (informational) *) [ `Continue | `Switching_protocols (* 2xx: (successful) *) | `Ok | `Created | `Accepted | `Non_authoritative | `No_content | `Reset_content | `Partial_content (* 3xx: (redirection) *) | `Multiple_choices | `Moved_permanently | `Found | `See_other | `Not_modified | `Use_proxy | `Temporary_redirect (* 4xx: (client error) *) | `Bad_request | `Unauthorized | `Payment_required | `Forbidden | `Not_found | `Method_not_allowed | `Not_acceptable | `Proxy_auth_required | `Request_timeout | `Conflict | `Gone | `Length_required | `Precondition_failed | `Request_entity_too_large | `Request_uri_too_long | `Unsupported_media_type | `Requested_range_not_satisfiable | `Expectation_failed (* 5xx: (server error) *) | `Internal_server_error | `Not_implemented | `Bad_gateway | `Service_unavailable | `Gateway_timeout | `Http_version_not_supported ] (** HTTP response status: * * {b Informational (1xx):} * - [`Continue] * - [`Switching_protocols] * * {b Successful (2xx):} * - [`Ok] * - [`Created] * - [`Accepted] * - [`Non_authoritative] * - [`No_content] * - [`Reset_content] * - [`Partial_content] * * {b Redirection (3xx):} * - [`Multiple_choices] * - [`Moved_permanently] * - [`Found] * - [`See_other] * - [`Not_modified] * - [`Use_proxy] * - [`Temporary_redirect] * * {b Client error (4xx):} * - [`Bad_request] * - [`Unauthorized] * - [`Payment_required] * - [`Forbidden] * - [`Not_found] * - [`Method_not_allowed] * - [`Not_acceptable] * - [`Proxy_auth_required] * - [`Request_timeout] * - [`Conflict] * - [`Gone] * - [`Length_required] * - [`Precondition_failed] * - [`Request_entity_too_large] * - [`Request_uri_too_long] * - [`Unsupported_media_type] * - [`Request_range_not_satisfiable] * - [`Expectation_failed] * * {b Server Error (5xx):} * - [`Internal_server_error] * - [`Not_implemented] * - [`Bad_gateway] * - [`Service_unavailable] * - [`Gateway_timeout] * - [`Http_version_not_supported] *) val int_of_http_status : http_status -> int (** Returns the integer code for a status value *) val http_status_of_int : int -> http_status (** Returns the status value for an integer code, or raises [Not_found] *) val string_of_http_status : http_status -> string (** Returns the informational text for a status value *) (* See also Netcgi.status_line *) val base_code : int -> int (** Allows to handle unknown status codes that are untranslatable by [http_status_of_int]: - for a code 100 to 199 the value 100 is returned - for a code 200 to 299 the value 200 is returned - for a code 300 to 399 the value 300 is returned - for a code 400 to 499 the value 400 is returned - for all other codes 500 is returned E.g. {[ let st = try Nethttp.http_status_of_int code with Not_found -> Nethttp.http_status_of_int (Nethttp.base_code code) ]} *) type http_method = string * string (** Method name, URI *) type cache_control_token = [ `No_store | `Max_age of int | `Max_stale of int option | `Min_fresh of int | `No_transform | `Only_if_cached | `Public | `Private of string list | `No_cache of string list | `Must_revalidate | `Proxy_revalidate | `S_maxage of int | `Extension of string * string option ] (** The cache control token for the [Cache-control] header *) type etag = [ `Weak of string | `Strong of string ] (** Entity tags can be weak or strong *) val weak_validator_match : etag -> etag -> bool (** Whether the tags match weakly (see RFC 2616 for definition) *) val strong_validator_match : etag -> etag -> bool (** Whether the tags match strongly (see RFC 2616 for definition) *) exception Bad_header_field of string (** Raised when a header field cannot be parsed. The string argument * is the name of the failing function *) class type http_header = Netmime.mime_header class type http_header_ro = Netmime.mime_header_ro (** The HTTP header is represented as MIME header *) class type http_trailer = Netmime.mime_header class type http_trailer_ro = Netmime.mime_header_ro (** The HTTP trailer is represented as MIME header *) val status_of_cgi_header : http_header -> (int * string) (** Returns the status code and the status text corresponding to the * [Status] header *) type netscape_cookie = { cookie_name : string; (** The name of the cookie *) cookie_value : string; (** The value of the cookie. There are no restrictions on the * value of the cookie *) cookie_expires : float option; (** Expiration: * - [None]: the cookie expires when the browser session ends. * - [Some t]: the cookie expires at the time [t] (seconds since * the epoch) *) cookie_domain : string option; (** Cookies are bound to a certain domain, i.e. the browser sends * them only when web pages of the domain are requested: * * - [None]: the domain is the hostname of the server * - [Some domain]: the domain is [domain] *) cookie_path : string option; (** Cookies are also bound to certain path prefixes, i.e. the browser * sends them only when web pages at the path or below are requested. * * - [None]: the path is script name + path_info * - [Some p]: the path is [p]. With [Some "/"] you can disable the * path restriction completely. *) cookie_secure : bool; (** Cookies are also bound to the type of the web server: * [false] means servers without SSL, [true] means servers with * activated SSL ("https"). *) } (** These are old-style cookies, as introduced by Netscape. For a better representation of cookies see the {!Nethttp.Cookie} module. This type is kept for now (and is also not considered as deprecated), as the access functions in the {!Nethttp.Header} module are more complete than those for {!Nethttp.Cookie}. *) type cookie = netscape_cookie (** Compatibility name. {b Deprecated} *) val decode_query : string -> (string * string) (** Splits the URI into a "script name" and a "query string" *) val split_host_port : string -> (string * int option) (** Splits the [Host] header in hostname and optional port number. * Fails on syntax error *) val uripath_encode : string -> string (** Encodes unsafe characters in URI paths. The slash character is not encoded. * This function should only be applied to the part before '?'. *) val uripath_decode : string -> string (** Decodes %XX sequences in URI paths. %2F is forbidden (failure). * This function should only be applied to the part before '?'. *) (**********************************************************************) (** {2 Parsing and Printing of Headers} *) module Cookie : sig (* This module has been written by Christophe Troestler. See the header of netcgi.mli for full copyright message. *) (** Functions to manipulate cookies. You should know that besides the [name] and [value] attribute, user agents will send at most the [path], [domain] and [port] and usually will not send them at all. For interoperability, cookies are set using version 0 (by Netscape) unless version 1 (RFC 2965 and the older RFC 2109) fields are set. While version 0 is well supported by browsers, RFC 2109 requires a recent browser and RFC 2965 is usually not supported. You do not have to worry however, cookies are always sent in such a way older browsers understand them -- albeit not all attributes of course -- so your application can be ready for the time RFC 2965 will be the norm. This cookie representation is preferred over the Netscape-only type {!Nethttp.netscape_cookie}. N.B. This module appears also as {!Netcgi.Cookie}. *) type t (** Mutable cookie type *) val make : ?max_age:int -> ?domain:string -> ?path:string -> ?secure:bool -> ?comment:string -> ?comment_url:string -> ?ports:int list -> string -> string -> t (** [make ?expires ?domain ?path ?secure name value] creates a new cookie with name [name] holding [value]. @param max_age see {!Netcgi.Cookie.set_max_age}. Default: when user agent exits. @param domain see {!Netcgi.Cookie.set_domain}. Default: hostname of the server. @param path see {!Netcgi.Cookie.set_path}. Default: script name + path_info. @param secure see {!Netcgi.Cookie.set_secure}. Default: [false]. @param comment see {!Netcgi.Cookie.set_comment}. Default: [""]. @param comment_url see {!Netcgi.Cookie.set_comment_url}. Default: [""]. @param ports see {!Netcgi.Cookie.set_ports}. Default: same port the cookie was sent. *) val name : t -> string (** The name of the cookie. *) val value : t -> string (** The value of the cookie. *) val domain : t -> string option (** The domain of the cookie, if set. *) val path : t -> string option (** The path of the cookie, if set. *) val ports : t -> int list option (** [port c] the ports to which the cookie may be returned or [[]] if not set. *) val max_age : t -> int option (** The expiration time of the cookie, in seconds. [None] means that the cookie will be discarded when the browser exits. This information is not returned by the browser. *) val secure : t -> bool (** Tells whether the cookie is secure. This information is not returned by the browser. *) val comment : t -> string (** Returns the comment associated to the cookie or [""] if it does not exists. This information is not returned by the browser. *) val comment_url : t -> string (** Returns the comment URL associated to the cookie or [""] if it does not exists. This information is not returned by the browser. *) val set_value : t -> string -> unit (** [set_value c v] sets the value of the cookie [c] to [v]. *) val set_max_age : t -> int option -> unit (** [set_max_age c (Some t)] sets the lifetime of the cookie [c] to [t] seconds. If [t <= 0], it means that the cookie should be discarded immediately. [set_expires c None] tells the cookie to be discarded when the user agent exits. (Despite the fact that the name is borrowed from the version 1 of the specification, it works transparently with version 0.) *) val set_domain : t -> string option -> unit (** Cookies are bound to a certain domain, i.e. the browser sends them only when web pages of the domain are requested: - [None]: the domain is the hostname of the server. - [Some domain]: the domain is [domain]. *) val set_path : t -> string option -> unit (** Cookies are also bound to certain path prefixes, i.e. the browser sends them only when web pages at the path or below are requested. - [None]: the path is script name + path_info - [Some p]: the path is [p]. With [Some "/"] you can disable the path restriction completely. *) val set_secure : t -> bool -> unit (** Cookies are also bound to the type of the web server: [set_secure false] means servers without SSL, [set_secure true] means servers with activated SSL ("https"). *) val set_comment : t -> string -> unit (** [set_comment c s] sets the comment of the cookie [c] to [s] which must be UTF-8 encoded (RFC 2279). Because cookies can store personal information, the comment should describe how the cookie will be used so the client can decide whether to allow the cookie or not. To cancel a comment, set it to [""]. Cookie version 1 (RFC 2109). *) val set_comment_url : t -> string -> unit (** [set_comment_url c url] same as {!Netcgi.Cookie.set_comment} except that the cookie comment is available on the page pointed by [url]. To cancel, set it to [""]. Cookie version 1 (RFC 2965). *) val set_ports : t -> int list option -> unit (** [set ports c (Some p)] says that the cookie [c] must only be returned if the server request comes from one of the listed ports. If [p = []], the cookie will only be sent to the request-port it was received from. [set_ports c None] says that the cookie may be sent to any port. Cookie version 1 (RFC 2965). *) val of_netscape_cookie : netscape_cookie -> t (** Convert a Netscape cookie to the new representation *) val to_netscape_cookie : t -> netscape_cookie (** Convert to Netscape cookie (with information loss) *) end module Header : sig (** This module is a parser/printer for the header fields used in HTTP/1.1. * The [get_*] functions generally raise [Not_found] when the queried header * is not present. If the syntax of the field is a comma-separated list of * multiple values, the [get_*] functions generally merge all headers of * the same type. The order is preserved in this case. The list [[]] means * that the header exists, but only with empty value. For example, * * {[ * Accept: text/html * Accept: text/plain * ]} * * would be returned as [["text/html",[],[]; "text/plain", [],[]]] * by [get_accept]. The header * * {[Accept:]} * * would be returned as [[]]. * * The [set_*] functions generally produce only a single header with comma- * separated values. Existing header are overwritten/removed. * * To remove a header, simply use the [delete_field] method of [http_header]. * * Error behaviour: The [get_*] functions raise [Bad_header_field] * when they cannot parse a header field. The [set_*] functions * raise [Invalid_argument] when an invalid value is passed to them * (only very few functions do that). The argument of both * exceptions is the function name. *) type param_value = [ `V of string | `Q of string ] (** Parameters may occur quoted ([`Q]) or as already decoded values ([`V]) *) type auth_challenge = string * (string * param_value) list (** The type of a single challenge, used during authentication. It is interpreted as [(mechanism_name, params)]. The headers [www-authenticate] and [proxy-authenticate] use this. See RFC 7235 for general information. *) type auth_credentials = string * (string * param_value) list (** The type of a single credentials response, used during authentication. It is interpreted as [(mechanism_name, params)]. The headers [authorize] and [proxy-authorize] use this. See RFC 7235 for general information. *) val parse_quoted_parameters : string -> (string * string) list (** A generic parser for comma-separated parameters in the form key=value or key="value". Fails if the string cannot be parsed. *) val get_accept : #http_header_ro -> (string * (string * string) list * (string * string) list) list (** Returns the [Accept] header as list of triples [(media_range, * media_range_params, accept_params)]. If there are * [accept_params], the first such parameter is always ["q"]. * * All present [Accept] headers are merged. The function returns * [[]] when there is at least one [Accept] header, but none of * the headers has a non-empty value. The function raises * [Not_found] if there no such headers at all (which should be * interpreted as [ ["*/*",[],[] ] ]). *) val best_media_type : #http_header_ro -> string list -> ( string * (string * string) list ) (** Returns the best media type for a header and a list of supported types. * If any type is acceptable, "*/*" will be returned. If no type is * acceptable, "" will be returned. * The supported media types should be sorted such that the best type * is mentioned first. * Of several media types with equal quality the one mentioned first in the * list of supported types is chosen. In case several types in the Accept: * header match the same type in the list of supported types, the most * specific type is chosen. *) val set_accept : #http_header -> (string * (string * string) list * (string * string) list) list -> unit (** Sets the [Accept] header *) val get_accept_charset : #http_header_ro -> (string * (string * string) list) list (** Returns the [Accept-charset] header as list of pairs [(charset,params)]. * The only mentioned parameter in RFC 2616 is ["q"]. * * All present [Accept-charset] headers are merged. The function * raises [Not_found] when there is no [Accept-charset] header * (which should be interpreted as [ ["*",[]] ]). *) val best_charset : #http_header_ro -> string list -> string (** Returns the best charset for a header and a list of supported charsets. * If any charset is acceptable, "*" will be returned. * The supported charsets should be sorted such that the best charset * is mentioned first. * * This function already implements the special handling of ISO-8859-1 * mentioned in RFC 2616. *) val set_accept_charset : #http_header -> (string * (string * string) list) list -> unit (** Sets the [Accept-charset] header *) val get_accept_encoding : #http_header_ro -> (string * (string * string) list) list (** Returns the [Accept-encoding] header as list of pairs [(coding,params)]. * The only mentioned parameter in RFC 2616 is ["q"]. The RFC describes * compatibility problems with the "q" parameter. * * All present [Accept-encoding] headers are merged. The function * raises [Not_found] when there is no [Accept-encoding] header * (which should be interpreted as [ ["identity",[]] ]). The * return value [[]] must be interpreted as [ ["identity",[]] ]. *) val best_encoding : #http_header_ro -> string list -> string (** Returns the best encoding for a header and a list of supported * encodings. If anything else fails, "identity" will be * returned. The supported encodings should be sorted such that * the best encoding is mentioned first. *) val set_accept_encoding : #http_header -> (string * (string * string) list) list -> unit (** Sets the [Accept-encoding] header *) val get_accept_language : #http_header_ro -> (string * (string * string) list) list (** Returns the [Accept-language] header as list of pairs * [(lang_range,params)]. The only mentioned parameter in RFC * 2616 is ["q"]. * * All present [Accept-language] headers are merged. The function * raises [Not_found] when there is no [Accept-language] header * (which should be interpreted as [ ["*",[]] ]). *) val set_accept_language : #http_header -> (string * (string * string) list) list -> unit (** Sets the [Accept-language] header *) val get_accept_ranges : #http_header_ro -> string list (** Returns the [Accept-ranges] header as list of tokens. * * All present [Accept-ranges] headers are merged. The function * raises [Not_found] when there is no [Accept-ranges] * header. The RFC leaves it open how this is to be interpreted * in general. *) val set_accept_ranges : #http_header -> string list -> unit (** Sets the [Accept-ranges] header *) val get_age : #http_header_ro -> float (** Returns the [Age] header as number *) val set_age : #http_header -> float -> unit (** Sets the [Age] header *) val get_allow : #http_header_ro -> string list (** Returns the [Allow] header as list of tokens. * * All present [Allow] headers are merged. The function raises [Not_found] * when there is no [Allow] header. The RFC leaves it open how this is * to be interpreted in general. *) val set_allow : #http_header -> string list -> unit (** Sets the [Allow] header *) val get_authorization : #http_header_ro -> auth_credentials (** Returns the [Authorization] header as pair [(auth_scheme,auth_params)], * or raises [Not_found] if not present. * * The "Basic" authentication scheme is represented specially as * [("basic", [ "credentials", creds ])] where [creds] are the * Base64-encoded credentials. * * At present, parameters are always decoded ([`V]). *) val set_authorization : #http_header -> auth_credentials -> unit (** Sets the [Authorization] header. * The "Basic" authentication scheme is represented as explained for * [get_authorization]. *) val get_cache_control : #http_header_ro -> cache_control_token list (** Returns the [Cache-control] header as list of tokens. * * All present [Cache-control] headers are merged. The function * raises [Not_found] when there is no [Cache-control] header. *) val set_cache_control : #http_header -> cache_control_token list -> unit (** Sets the [Cache-control] header *) val get_connection : #http_header_ro -> string list (** Returns the [Connection] header as list of tokens. * * All present [Connection] headers are merged. The function * raises [Not_found] when there is no [Connection] header. * * The Connection header must be ignored when received from a * HTTP/1.0 client. *) val set_connection : #http_header -> string list -> unit (** Sets the [Connection] header *) val get_content_encoding : #http_header_ro -> string list (** Returns the [Content-encoding] header as list of tokens. * * All present [Content-encoding] headers are merged. * @raise Not_found when there is no [Content-encoding] header. *) val set_content_encoding : #http_header -> string list -> unit (** Sets the [Content-encoding] header *) val get_content_language : #http_header_ro -> string list (** Returns the [Content-language] header as list of tokens. * * All present [Content-language] headers are merged. * @raise Not_found when there is no [Content-language] header. *) val set_content_language : #http_header -> string list -> unit (** Sets the [Content-language] header *) val get_content_length : #http_header_ro -> int64 (** Returns the [Content-length] header as number. If the number * is too big for int64, the exception [Bad_header_field * "Content-length"] will be raised. * @raise Not_found when the header is missing. *) val set_content_length : #http_header -> int64 -> unit (** Sets the [Content-length] header *) val get_content_location : #http_header_ro -> string (** Returns the [Content-location] header as string. * @raise Not_found when the header is missing. *) val set_content_location : #http_header -> string -> unit (** Sets the [Content-location] header *) val get_content_md5 : #http_header_ro -> string (** Returns the [Content-MD5] header as string. The Base64 encoding * has not been touched. * @raise Not_found when the header is missing. *) val set_content_md5 : #http_header -> string -> unit (** Sets the [Content-MD5] header *) val get_content_range : #http_header_ro -> [ `Bytes of (int64*int64) option * int64 option ] (** Returns the [Content-range] header as * [`Bytes(byte_range_resp_spec, instance_length)]. The option value * [None] corresponds to "*" in the RFC. * @raise Not_found when the header is missing. *) val set_content_range : #http_header -> [ `Bytes of (int64*int64) option * int64 option ] -> unit (** Sets the [Content-range] header *) val get_content_type : #http_header_ro -> string * (string * string) list (** Returns the [Content-type] header as pair [(media_type, params)]. * @raise Not_found when the header is missing. *) val set_content_type : #http_header -> string * (string * string) list -> unit (** Sets the [Content-type] header *) val get_date : #http_header_ro -> float (** Returns the [Date] header as number (seconds since the Epoch). * @raise Not_found when the header is missing. *) val set_date : #http_header -> float -> unit (** Sets the [Date] header *) val get_etag : #http_header_ro -> etag (** Returns the [Etag] header. * @raise Not_found when the header is missing. *) val set_etag : #http_header -> etag -> unit (** Sets the [Etag] header *) val get_expect : #http_header_ro -> (string * string option * (string * string) list) list (** Returns the [Expect] header as list of triples [(token,value,params)]. * * All present [Expect] headers are merged. * @raise Not_found when there is no [Expect] header. *) val set_expect : #http_header -> (string * string option * (string * string) list) list -> unit (** Sets the [Expect] header *) val get_expires : #http_header_ro -> float (** Returns the [Expires] header as number (seconds since the Epoch). * @raise Not_found when the header is missing. *) val set_expires : #http_header -> float -> unit (** Sets the [Expires] header *) val get_from : #http_header_ro -> string (** Returns the [From] header as string. * @raise Not_found when the header is missing. *) val set_from : #http_header -> string -> unit (** Sets the [From] header *) val get_host : #http_header_ro -> string * int option (** Returns the [Host] header as pair [(host,port)]. * @raise Not_found when the header is missing. *) val set_host : #http_header -> string * int option -> unit (** Sets the [Host] header *) val get_if_match : #http_header_ro -> etag list option (** Returns the [If-match] header. The value [None] means "*". * @raise Not_found when the header is missing. *) val set_if_match : #http_header -> etag list option -> unit (** Sets the [If-match] header *) val get_if_modified_since : #http_header_ro -> float (** Returns the [If-modified-since] header as number (seconds * since the Epoch). * @raise Not_found when the header is missing. *) val set_if_modified_since : #http_header -> float -> unit (** Sets the [If-modified-since] header *) val get_if_none_match : #http_header_ro -> etag list option (** Returns the [If-none-match] header. The value [None] means "*". * @raise Not_found when the header is missing. *) val set_if_none_match : #http_header -> etag list option -> unit (** Sets the [If-none-match] header *) val get_if_range : #http_header_ro -> [ `Etag of etag | `Date of float ] (** Returns the [If-range] header. * @raise Not_found when the header is missing. *) val set_if_range : #http_header -> [ `Etag of etag | `Date of float ] -> unit (** Sets the [If-range] header *) val get_if_unmodified_since : #http_header_ro -> float (** Returns the [If-unmodified-since] header as number (seconds * since the Epoch). * @raise Not_found when the header is missing. *) val set_if_unmodified_since : #http_header -> float -> unit (** Sets the [If-unmodified-since] header *) val get_last_modified : #http_header_ro -> float (** Returns the [Last-modified] header as number (seconds since the Epoch). * @raise Not_found when the header is missing. *) val set_last_modified : #http_header -> float -> unit (** Sets the [Last-modified] header *) val get_location : #http_header_ro -> string (** Returns the [Location] header as string. * @raise Not_found when the header is missing. *) val set_location : #http_header -> string -> unit (** Sets the [Location] header *) val get_max_forwards : #http_header_ro -> int (** Returns the [Max-forwards] header as number. * @raise Not_found when the header is missing. *) val set_max_forwards : #http_header -> int -> unit (** Sets the [Max-forwards] header *) val get_pragma : #http_header_ro -> (string * string option) list (** Returns the [Pragma] header as list of pairs [(token,value)]. * * All present [Pragma] headers are merged. * @raise Not_found when there is no [Pragma] header. *) val set_pragma : #http_header -> (string * string option) list -> unit (** Sets the [Pragma] header *) val get_proxy_authenticate : #http_header_ro -> auth_challenge list (** Returns the [Proxy-authenticate] header as list of challenges * [(auth_scheme,auth_params)]. See also [get_www_authenticate]. * * All present [Proxy-authenticate] headers are merged. * @raise Not_found when there is no [Proxy-authenticate] header. * * At present, parameters are always decoded ([`V]). *) val set_proxy_authenticate : #http_header -> auth_challenge list -> unit (** Sets the [Proxy-authenticate] header *) val get_proxy_authorization : #http_header_ro -> auth_credentials (** Returns the [Proxy-authorization] header as pair * [(auth_scheme,auth_params)]. @raise Not_found when the header is * missing. * * The "Basic" authentication scheme is represented specially as * [("basic", [ "credentials", creds ])] where [creds] are the * Base64-encoded credentials. * * At present, parameters are always decoded ([`V]). *) val set_proxy_authorization : #http_header -> auth_credentials -> unit (** Sets the [Proxy-authorization] header * The "Basic" authentication scheme is represented as explained for * [get_proxy_authorization]. *) val get_range : #http_header_ro -> [`Bytes of (int64 option * int64 option) list ] (** Returns the [Range] header as [`Bytes ranges], where the list [ranges] * has elements of the form [(Some first_pos, Some last_pos)], * [(Some first_pos, None)] (prefix range), or [(None, Some * last_pos)] (suffix range). * @raise Not_found when the header is missing. *) val set_range : #http_header -> [`Bytes of (int64 option * int64 option) list ] -> unit (** Sets the [Range] header *) val get_referer : #http_header_ro -> string (** Returns the [Referer] header as string. * @raise Not_found when the header is missing. *) val get_referrer : #http_header_ro -> string (** Same, for addicts of correct orthography *) val set_referer : #http_header -> string -> unit (** Sets the [Referer] header *) val set_referrer : #http_header -> string -> unit (** Same, for addicts of correct orthography *) val get_retry_after : #http_header_ro -> [ `Date of float | `Seconds of int ] (** Returns the [Retry-after] header. * @raise Not_found when the header is missing. *) val set_retry_after : #http_header -> [ `Date of float | `Seconds of int ] -> unit (** Sets the [Retry-after] header *) val get_server : #http_header_ro -> string (** Returns the [Server] header as uninterpreted string (including * comments). * @raise Not_found when the header is missing. *) val set_server : #http_header -> string -> unit (** Sets the [Server] header *) val get_te : #http_header_ro -> (string * (string * string) list * (string * string) list) list (** Returns the [TE] header as list of triples * [(te_token, te_params, accept_params)]. * If there are [accept_params], the first such parameter is always ["q"]. * * All present [TE] headers are merged. The function returns [[]] when * there is at least one [TE] header, but none of the headers has a * non-empty value. * @raise Not_found if there no such headers at all. *) val set_te : #http_header -> (string * (string * string) list * (string * string) list) list -> unit (** Sets the [TE] header *) val get_trailer : #http_header_ro -> string list (** Returns the [Trailer] header as list of field names. * * All present [Trailer] headers are merged. The function returns * [[]] when there is at least one [Trailer] header, but none of * the headers has a non-empty value. * @raise Not_found if there no such headers at all. *) val set_trailer : #http_header -> string list -> unit (** Sets the [Trailer] header *) val get_transfer_encoding : #http_header_ro -> (string * (string * string) list) list (** Returns the [Transfer-encoding] header as list of pairs * [(token, params)]. * * All present [Transfer-encoding] headers are merged. The * function returns [[]] when there is at least one * [Transfer-encoding] header, but none of the headers has a * non-empty value. * @raise Not_found if there no such headers at all. *) val set_transfer_encoding : #http_header -> (string * (string * string) list) list -> unit (** Sets the [Transfer-encoding] header *) val get_upgrade : #http_header_ro -> string list (** Returns the [Upgrade] header as list of products. * * All present [Upgrade] headers are merged. The function returns * [[]] when there is at least one [Upgrade] header, but none of * the headers has a non-empty value. * @raise Not_found if there no such headers at all. *) val set_upgrade : #http_header -> string list -> unit (** Sets the [Upgrade] header *) val get_user_agent : #http_header_ro -> string (** Returns the [User-agent] header as uninterpreted string * (including comments). * @raise Not_found if the header is missing. *) val set_user_agent : #http_header -> string -> unit (** Sets the [User-agent] header *) val get_vary : #http_header_ro -> [ `Star | `Fields of string list ] (** Returns the [Vary] header. * @raise Not_found if the header is missing. *) val set_vary : #http_header -> [ `Star | `Fields of string list ] -> unit (** Sets the [Vary] header *) (* val get_via : #http_header_ro -> (string option * string * string * string option) list (** Returns the [Via] header as list of tuples * [(proto_name, proto_version, received_by, comment)]. * * All present [Via] headers are merged. * @raise Not_found if the header is missing. *) *) (* val set_via : #http_header -> (string option * string * string * string option) list -> unit (** Sets the [Via] header *) *) (* val get_warning : #http_header_ro -> (int * string * string * float option) list (** Returns the [Warning] header as list of tuples * [(code, agent, text, date)]. * * All present [Warning] headers are merged. * @raise Not_found if the header is missing. *) *) (* val set_warning : #http_header -> (int * string * string * float option) list -> unit (** Sets the [Warning] header *) *) val get_www_authenticate : #http_header_ro -> auth_challenge list (** Returns the [WWW-Authenticate] header as list of challenges * [(auth_scheme,auth_params)]. * * All present [WWW-Authenticate] headers are merged. * * The scheme "negotiate" uses a deviating header format. * This data is returned as e.g. [("negotiate", ["credentials", data])]. * * At present, parameters are always decoded ([`V]). * @raise Not_found if the header is missing. *) val set_www_authenticate : #http_header -> auth_challenge list -> unit (** Sets the [WWW-Authenticate] header *) val get_cookie : #http_header_ro -> (string * string) list (** Get the (Netscape) cookies as (name,value) pairs (or Not_found). *) val get_cookie_ct : #http_header_ro -> Cookie.t list (** Get the cookies in the {!Nethttp.Cookie.t} representation (the suffix "_ct" reminds of [Cookie.t]). This function also supports version 1 cookies. Returns the empty list if there are no cookies. *) val set_cookie : #http_header -> (string * string) list -> unit (** Set the [Cookie] header. Note: This does not set cookies in the client, * use [set_set_cookie] instead! *) val get_set_cookie : #http_header_ro -> netscape_cookie list (** Get the [Set-Cookie] header *) val set_set_cookie : #http_header -> netscape_cookie list -> unit (** Set the [Set-Cookie] header *) val set_set_cookie_ct : #http_header -> Cookie.t list -> unit (** Set the [Set-Cookie] and [Set-Cookie2] headers: [set_set_cookie_ct header cookies] sets the [cookies] in [header] using version 0 or version 1 depending on whether version 1 fields are used. For better browser compatibility, if "Set-cookie2" (RFC 2965) is issued, then a "Set-cookie" precedes (declaring the same cookie with a limited number of options). *) end (** {2 HTTP transport registry} *) type transport_layer_id = int (** see {!Nethttp_client.transport_layer_id} *) val new_trans_id : unit -> transport_layer_id (** Allocates and returns a new ID *) val http_trans_id : transport_layer_id (** Identifies the pure HTTP transport (without SSL), with or without web proxies *) val https_trans_id : transport_layer_id (** Identifies anonymous HTTPS transport (i.e. no client certificates), with or without web proxies. *) val spnego_trans_id : transport_layer_id (** Identifies an anonymous HTTPS transport that is additionally authenticated via SPNEGO (as described in RFC 4559) *) val proxy_only_trans_id : transport_layer_id (** Identifies web proxy connections. Use this to e.g. send an FTP URL to a web proxy via HTTP *) (** {2 Types for authentication} *) (** See also {!Netsys_sasl_types.SASL_MECHANISM}. This is very similar, only that - the messages are encapsulated as HTTP headers, and - the "realm" parameter is commonly supported by mechanisms In SASL terms, HTTP authentication is normally "server first". There is only one exception: re-authentication, which is "client first". *) type match_result = [ `Accept of string * string option | `Reroute of string * transport_layer_id | `Accept_reroute of string * string option * transport_layer_id | `Reject ] (** See {!Nethttp.HTTP_CLIENT_MECHANISM.client_match} *) module type HTTP_CLIENT_MECHANISM = sig val mechanism_name : string val available : unit -> bool (** Whether the mechanism is available, in particular whether the required crypto support is linked in *) val restart_supported : bool (** Whether the mechanism supports quick restarts (re-authentication) *) type credentials val init_credentials : (string * string * (string * string) list) list -> credentials (** Supply the mechanism with credentials. These are given as list [(type,value,params)]. The mechanism may pick any element of this list which are considered as equivalent. Types are defined per mechanism. All mechanisms understand the "password" type, which is just the cleartext password, e.g. {[ [ "password", "ThE sEcReT", [] ] ]} The password is encoded in UTF-8. However, note that not all protocols are able to transmit all of UTF-8. If a non-transmittable character is found, the authentication will fail. The password can have parameters: - "realm": the password is only applicable to this realm. The realm parameter should only occur once. - "domain-uri": the password is only applicable to this URI space. The URI must include the protocol scheme, the host name, and "/" as path. The port number is optional. Example: "http://localhost/". The domain-uri parameter can occur several times. *) val client_match : params:(string * string * bool) list -> Header.auth_challenge -> match_result (** Checks whether this mechanism can accept the initial authentication challenge (i.e. the first challenge sent from the server to the client. The [params] are as for [create_client_session]. On success, returns [`Accept(realm,id_opt)]. On failure, returns [`Reject]. This function usually does not raise exceptions. If the mechanism does not support the notion of realms, a dummy realm should be returned. The [id_opt] is the session ID (if supported). Session IDs can be used to bind reauthentications to the original session. The challenge is from a [www-authenticate] or a [proxy-authenticate] header. There is also the result [`Reroute(realm, trans_id)], meaning that the request would be acceptable if it came over the transport identified by [trans_id]. [`Accept_reroute] is the combination of accepting and rerouting, i.e. the auth protocol can start, but the second request should go over the other transport. Both [`Reroute] and [`Accept_reroute] are only allowed for initial challenges. *) type client_session val client_state : client_session -> Netsys_sasl_types.client_state val create_client_session : user:string -> creds:credentials -> params:(string * string * bool) list -> unit -> client_session (** The new client session authenticate as [user]. The credentials are [creds]. [user] must be encoded in UTF-8. The parameters are given as list [(name,value,critical)]. Critical parameters must be interpreted by the mechanism, and unknown critical parameters must be rejected by a [Failure] exception. Non-critical parameters are ignored if they are unknown to the mechanism. Available parameters: - "realm" - "id" (if [client_match] returns a session ID) - "trans_id": the {!Nethttp_client.transport_layer_id} of the current HTTP request - "conn_id": an identifier for the TCP connection - "https": is set to "true" if the current connection is TLS-secured - "target-host": the hostname from the HTTP request - "target-uri": the URL from the HTTP request *) val client_configure_channel_binding : client_session -> Netsys_sasl_types.cb -> client_session (** Configure GS2-style channel binding *) val client_restart : params:(string * string * bool) list -> client_session -> client_session (** Restart the session for another authentication round. The session must be in state [`OK]. After the restart the session will be in state [`Emit]. The params are the same as for [create_client_session], but updated where needed. *) val client_process_challenge : client_session -> string -> string -> #http_header_ro -> Header.auth_challenge -> client_session (** [client_process_challenge cs method uri header challenge]: Process the challenge from the server. The state must be [`Wait]. As an exception, this function can also be called for the initial challenge from the server, even if the state is [`Emit]. [method] is the request method. [uri] is the request URI *) val client_emit_response : client_session -> string -> string -> #http_header_ro -> client_session * Header.auth_credentials * (string * string) list (** [let (creds,new_headers) = client_emit_response cs method uri header]: Emit a new response as a pair [(creds,new_headers)]. The state must be [`Emit]. The [creds] either go into the [authorization] or [proxy-authorization] header. The [new_headers] are additional headers to modify. *) val client_channel_binding : client_session -> Netsys_sasl_types.cb (** Whether the client suggests or demands channel binding *) val client_user_name : client_session -> string (** The user name *) val client_stash_session : client_session -> string (** Serializes the session as string *) val client_resume_session : string -> client_session (** Unserializes the session *) val client_session_id : client_session -> string option (** Optionally return a string that can be used to identify the client session. Not all mechanisms support this. *) val client_domain : client_session -> string list (** After successful authentication, this function may return the URIs defining the authentication space. *) val client_prop : client_session -> string -> string (** Get a mechanism-specific property of the session. Commonly supported keys: - "realm" - "domain-uri" *) val client_gssapi_props : client_session -> Netsys_gssapi.client_props (** Returns the GSSAPI props if available, or raise [Not_found] *) end (**/**) val rev_split : (char -> bool) -> string -> string list (* See netcgi_common.mli *) val qstring_of_value : string -> string (* quoted string *) ocamlnet-4.1.2/src/netstring/netgssapi_auth.mli0000644000175000017500000000574212731530350020300 0ustar gerdgerd(* $Id$ *) (** Authentication helpers for GSSAPI *) open Netsys_gssapi module type CONFIG = sig val raise_error : string -> 'a end module Manage(G:GSSAPI) : sig (** General management *) val delete_context : G.context option -> unit -> unit (** Deletes the context, ignoring any error *) val format_status : ?fn:string -> ?minor_status:int32 -> major_status -> string end module Auth (G:GSSAPI)(C:CONFIG) : sig (** Status *) val check_status : ?fn:string -> ?minor_status:int32 -> major_status -> unit (** If the [major_status] indicates an error, an error string is formed, optionally including the function name [fn] and the detailed information derived from [minor_status]. Then, the function [C.raise_error] is called with the string as argument. *) (** Client configuration *) val get_initiator_name : client_config -> G.name val get_initiator_cred : initiator_name:G.name -> client_config -> G.credential val acquire_initiator_cred : initiator_name:G.name -> client_config -> G.credential val get_target_name : ?default:(string * oid) -> client_config -> G.name val get_client_flags : client_config -> req_flag list val check_client_flags : client_config -> ret_flag list -> unit val init_sec_context : initiator_cred:G.credential -> context:G.context option -> target_name:G.name -> req_flags:req_flag list -> chan_bindings:channel_bindings option -> input_token:token option -> client_config -> (G.context * token * ret_flag list * client_props option) (** Calls [G.init_sec_context], and returns [(out_context,out_token,flags,props_opt)]. If [props_opt] is returned the context setup is done. Checks already for errors, and client flags. *) (** Server configuration *) val get_acceptor_name : server_config -> G.name val get_acceptor_cred : acceptor_name:G.name -> server_config -> G.credential val get_server_flags : server_config -> req_flag list val check_server_flags : server_config -> ret_flag list -> unit val accept_sec_context : acceptor_cred:G.credential -> context:G.context option -> chan_bindings:channel_bindings option -> input_token:token -> server_config -> (G.context * token * ret_flag list * server_props option) (** Calls [G.accept_sec_context], and returns [(out_context,out_token,flags,props_opt)]. If [props_opt] is returned the context setup is done. Checks already for errors, and server flags. *) (** Helpers *) val get_display_name : G.name -> string * oid val get_exported_name : G.name -> string end ocamlnet-4.1.2/src/netstring/netauth.mli0000644000175000017500000000544312731530350016730 0ustar gerdgerd(* $Id$ *) (** Some primitives for authentication *) val hmac : h:(string->string) -> b:int -> l:int -> k:string -> message:string -> string (** The HMAC algorithm of RFC 2104. The function [h] is the hash function. [b] and [l] are properties of [h] (see the RFC or below). The string [k] is the key, up to [b] bytes. The [message] is authenticated. The key [k] should ideally have length [l]. If this cannot be ensured by other means, one should pass [k = h any_k]. Common values of [b] and [l]: - For [h=MD5]: [b=64], [l=16] - For [h=SHA-1]: [b=64], [l=20] See also {!Netsys_digests.hmac} for a better implementation. *) type key_type = [ `Kc | `Ke | `Ki ] (** Key types: - [`Kc] is used for computing checksums - [`Ke] is used for encrypting confidential messages - [`Ki] is used for computing integrity checksums for encrypted messages *) val derive_key_rfc3961_simplified : encrypt:(string -> string) -> random_to_key:(string -> string) -> block_size:int -> k:int -> usage:int -> key_type:key_type -> string (** Derives a special key from a base key, as described in RFC 3961. - [encrypt]: Encrypts the argument with the base key and the initial cipher state. - [random_to_key]: Converts a random string of size [k] to a key - [block_size]: The block size of the cipher underlying [encrypt]. It is ensured that [encrypt] is called with strings having exactly this many bits. (The [c] parameter in the RFC text.) Minimum: 40. - [k]: The input size for [random_to_key] in bits. Must be divisible by 8. - [usage]: The usage number (here restricted to 0-255, although the RFC would allow 32 bits). Examples for usage numbers can be found in RFC 4121 section 2. - [key_type]: Which key type to derive The output is a key as produced by [random_to_key]. *) (** {2 Bitstring operations} *) val xor_s : string -> string -> string (** Performs the bitwise XOR of these strings (which must have the same length) *) val add_1_complement : string -> string -> string (** The addition algorithm for 1's-complement numbers. The two numbers to add are given as bitstrings (big endian), and must have the same length *) val rotate_right : int -> string -> string (** Rotate the (big-endian) bitstring to the right by n bits. This also works for negative n (left rotation), and for n whose absolute value is greater or equal than the bit length of the string. *) val n_fold : int -> string -> string (** Blumenthal's n-fold algorithm for an n that is divisible by 8. (RFC 3961, section 5.1) *) ocamlnet-4.1.2/src/netstring/netsockaddr.ml0000644000175000017500000000520012731530350017377 0ustar gerdgerd(* $Id$ *) type socksymbol = [ `Inet of Unix.inet_addr * int | `Inet_byname of string * int | `Unix of string ] let sa_re1 = Netstring_str.regexp "\\([^:]*\\):\\([0-9]+\\)$" let sa_re2 = Netstring_str.regexp "\\[\\([^]]*\\)\\]:\\([0-9]+\\)$" let socksymbol_of_string s = try if (s <> "" && s.[0] = '/') || (String.length s >= 2 && s.[0] = '.' && s.[1] = '/') then `Unix s else if s <> "" && s.[0] = '[' then ( match Netstring_str.string_match sa_re2 s 0 with | None -> raise Not_found | Some m -> let ip_s = Netstring_str.matched_group m 1 s in let port_s = Netstring_str.matched_group m 2 s in let ip = Unix.inet_addr_of_string ip_s in let port = int_of_string port_s in if port < 0 || port > 65535 then raise Not_found; `Inet(ip,port) ) else ( match Netstring_str.string_match sa_re1 s 0 with | None -> raise Not_found | Some m -> let name_s = Netstring_str.matched_group m 1 s in let port_s = Netstring_str.matched_group m 2 s in let port = int_of_string port_s in if port < 0 || port > 65535 then raise Not_found; ( try let ip = Unix.inet_addr_of_string name_s in `Inet(ip,port) with _ -> `Inet_byname(name_s,port) ) ) with | _ -> failwith ("Cannot parse socket address: " ^ s) let string_of_socksymbol = function | `Inet(ip,port) -> let n = Unix.string_of_inet_addr ip in ( match Netsys.domain_of_inet_addr ip with | Unix.PF_INET -> n ^ ":" ^ string_of_int port | Unix.PF_INET6 -> "[" ^ n ^ "]:" ^ string_of_int port | _ -> assert false ) | `Inet_byname(n,port) -> n ^ ":" ^ string_of_int port | `Unix p -> if p <> "" && p.[0] = '/' then p else if String.length p >= 2 && p.[0] = '.' && p.[1] = '/' then p else "./" ^ p let norm_socksymbol = function | `Inet(ip,port) -> `Inet(Netsys.norm_inet_addr ip, port) | `Inet_byname(n, port) -> ( try let ip1 = Unix.inet_addr_of_string n in let ip2 = Netsys.norm_inet_addr ip1 in `Inet_byname(Unix.string_of_inet_addr ip2, port) with | Failure _ -> `Inet_byname(n,port) ) | `Unix p -> `Unix p let ipv6_socksymbol = function | `Inet(ip,port) -> `Inet(Netsys.ipv6_inet_addr ip, port) | `Inet_byname(n, port) -> ( try let ip1 = Unix.inet_addr_of_string n in let ip2 = Netsys.ipv6_inet_addr ip1 in `Inet_byname(Unix.string_of_inet_addr ip2, port) with | Failure _ -> `Inet_byname(n,port) ) | `Unix p -> `Unix p ocamlnet-4.1.2/src/netstring/netnumber.ml0000644000175000017500000007477312731530350017122 0ustar gerdgerd(* $Id$ *) (* NOTE: Parts of this implementation depend very much of representation * details of O'Caml 3.xx. It is not guaranteed that this works in future * versions of O'Caml as well. *) (* representation types *) #ifdef WORDSIZE_64 type int4 = int (* faster on 64 bit platforms! *) type uint4 = int (* Note that values >= 0x8000_0000 are represented as negative ints, i.e. the bits 32-62 are all set to 1. *) #else type int4 = int32 type uint4 = int32 #endif type int8 = int64 type uint8 = int64 type fp4 = int32 (* string;; *) (* IEEE representation of fp numbers *) type fp8 = int64 exception Cannot_represent of string (* raised if numbers are too big to map them to other type *) exception Out_of_range module type ENCDEC = sig val read_int4 : Bytes.t -> int -> int4 val read_int8 : Bytes.t -> int -> int8 val read_uint4 : Bytes.t -> int -> uint4 val read_uint8 : Bytes.t -> int -> uint8 val read_int4_unsafe : Bytes.t -> int -> int4 val read_int8_unsafe : Bytes.t -> int -> int8 val read_uint4_unsafe : Bytes.t -> int -> uint4 val read_uint8_unsafe : Bytes.t -> int -> uint8 val read_string_int4 : string -> int -> int4 val read_string_int8 : string -> int -> int8 val read_string_uint4 : string -> int -> uint4 val read_string_uint8 : string -> int -> uint8 val read_string_int4_unsafe : string -> int -> int4 val read_string_int8_unsafe : string -> int -> int8 val read_string_uint4_unsafe : string -> int -> uint4 val read_string_uint8_unsafe : string -> int -> uint8 val write_int4 : Bytes.t -> int -> int4 -> unit val write_int8 : Bytes.t -> int -> int8 -> unit val write_uint4 : Bytes.t -> int -> uint4 -> unit val write_uint8 : Bytes.t -> int -> uint8 -> unit val write_int4_unsafe : Bytes.t -> int -> int4 -> unit val write_int8_unsafe : Bytes.t -> int -> int8 -> unit val write_uint4_unsafe : Bytes.t -> int -> uint4 -> unit val write_uint8_unsafe : Bytes.t -> int -> uint8 -> unit val int4_as_bytes : int4 -> Bytes.t val int8_as_bytes : int8 -> Bytes.t val uint4_as_bytes : uint4 -> Bytes.t val uint8_as_bytes : uint8 -> Bytes.t val int4_as_string : int4 -> string val int8_as_string : int8 -> string val uint4_as_string : uint4 -> string val uint8_as_string : uint8 -> string val write_fp4 : Bytes.t -> int -> fp4 -> unit val write_fp8 : Bytes.t -> int -> fp8 -> unit val fp4_as_string : fp4 -> string val fp8_as_string : fp8 -> string val fp4_as_bytes : fp4 -> Bytes.t val fp8_as_bytes : fp8 -> Bytes.t val read_fp4 : Bytes.t -> int -> fp4 val read_fp8 : Bytes.t -> int -> fp8 val read_string_fp4 : string -> int -> fp4 val read_string_fp8 : string -> int -> fp8 end let rec cannot_represent s = (* "rec" because this prevents this function from being inlined *) raise (Cannot_represent s) (**********************************************************************) (* cmp *) (**********************************************************************) #ifdef WORDSIZE_64 let lt_uint4 x y = if x < y then x >= 0 || y < 0 else x >= 0 && y < 0 #else let lt_uint4 x y = if x < y then x >= 0l (* because: - if x < 0 && y < 0 ==> x >u y - if x < 0 && y >= 0 ==> x >u y - if x >= 0 && y => 0 ==> x y <= x *) y < x && y < 0l (* because: - if y < 0 && x < 0 ==> x = 0 ==> x = 0 && x >= 0 ==> x >u y *) #endif let le_uint4 x y = not(lt_uint4 y x) let gt_uint4 x y = lt_uint4 y x let ge_uint4 x y = not(lt_uint4 x y) let lt_uint8 x y = if x < y then x >= 0L || y <= 0L else x >= 0L && y < 0L let le_uint8 x y = not(lt_uint8 y x) let gt_uint8 x y = lt_uint8 y x let ge_uint8 x y = not(lt_uint8 x y) (**********************************************************************) (* mk_[u]intn *) (**********************************************************************) (* compatibility interface *) #ifdef WORDSIZE_64 let mk_int4 (c3,c2,c1,c0) = let n3 = (Char.code c3) in let n2 = (Char.code c2) in let n1 = (Char.code c1) in let n0 = (Char.code c0) in (* be careful to set the sign correctly: *) ((n3 lsl 55) asr 31) lor (n2 lsl 16) lor (n1 lsl 8) lor n0 #else let mk_int4 (c3,c2,c1,c0) = let n3 = Int32.of_int (Char.code c3) in let n2 = Int32.of_int (Char.code c2) in let n1 = Int32.of_int (Char.code c1) in let n0 = Int32.of_int (Char.code c0) in Int32.logor (Int32.shift_left n3 24) (Int32.logor (Int32.shift_left n2 16) (Int32.logor (Int32.shift_left n1 8) n0)) #endif let mk_int8 (c7,c6,c5,c4,c3,c2,c1,c0) = let n7 = Int64.of_int (Char.code c7) in let n6 = Int64.of_int (Char.code c6) in let n5 = Int64.of_int (Char.code c5) in let n4 = Int64.of_int (Char.code c4) in let n3 = Int64.of_int (Char.code c3) in let n2 = Int64.of_int (Char.code c2) in let n1 = Int64.of_int (Char.code c1) in let n0 = Int64.of_int (Char.code c0) in Int64.logor (Int64.shift_left n7 56) (Int64.logor (Int64.shift_left n6 48) (Int64.logor (Int64.shift_left n5 40) (Int64.logor (Int64.shift_left n4 32) (Int64.logor (Int64.shift_left n3 24) (Int64.logor (Int64.shift_left n2 16) (Int64.logor (Int64.shift_left n1 8) n0)))))) let mk_uint4 = mk_int4 let mk_uint8 = mk_int8 (**********************************************************************) (* dest_[u]intn *) (**********************************************************************) (* compatibility interface *) #ifdef WORDSIZE_64 let dest_int4 x = let n3 = (x lsr 24) land 0xff in let n2 = (x lsr 16) land 0xff in let n1 = (x lsr 8) land 0xff in let n0 = x land 0xff in (Char.chr n3, Char.chr n2, Char.chr n1, Char.chr n0) #else let dest_int4 x = let n3 = Int32.to_int (Int32.shift_right_logical x 24) land 0xff in let n2 = Int32.to_int (Int32.shift_right_logical x 16) land 0xff in let n1 = Int32.to_int (Int32.shift_right_logical x 8) land 0xff in let n0 = Int32.to_int (Int32.logand x 0xffl) in (Char.chr n3, Char.chr n2, Char.chr n1, Char.chr n0) #endif let dest_int8 x = let n7 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 56) 0xffL) in let n6 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 48) 0xffL) in let n5 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 40) 0xffL) in let n4 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 32) 0xffL) in let n3 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 24) 0xffL) in let n2 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 16) 0xffL) in let n1 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 8) 0xffL) in let n0 = Int64.to_int (Int64.logand x 0xffL) in (Char.chr n7, Char.chr n6, Char.chr n5, Char.chr n4, Char.chr n3, Char.chr n2, Char.chr n1, Char.chr n0) let dest_uint4 = dest_int4 let dest_uint8 = dest_int8 (**********************************************************************) (* int_of_[u]intn *) (**********************************************************************) let c_max_int_64 = Int64.of_int max_int let c_min_int_64 = Int64.of_int min_int let name_int_of_int4 = "int_of_int4" #ifdef WORDSIZE_64 let int_of_int4 x = x #else let int_of_int4 x = if x < (-0x4000_0000l) || x > 0x3fff_ffffl then cannot_represent name_int_of_int4; Int32.to_int x #endif let name_int_of_uint4 = "int_of_uint4" #ifdef WORDSIZE_64 let int_of_uint4 x = (* x land 0xffff_ffff - "Integer literal exceeds the range..." grrrmpf *) (x lsl 31) lsr 31 #else let int_of_uint4 x = if x >= 0l && x <= 0x3fff_ffffl then Int32.to_int x else cannot_represent name_int_of_uint4 #endif let name_int_of_int8 = "int_of_int8" let int_of_int8 x = if x >= c_min_int_64 && x <= c_max_int_64 then Int64.to_int x else cannot_represent name_int_of_int8 let name_int_of_uint8 = "int_of_uint8" let int_of_uint8 x = if x >= Int64.zero && x <= c_max_int_64 then Int64.to_int x else cannot_represent name_int_of_uint8 (**********************************************************************) (* intn_of_int *) (**********************************************************************) let name_int4_of_int = "int4_of_int" #ifdef WORDSIZE_64 let int4_of_int i = let j = i asr 31 in if j = 0 || j = (-1) then i else cannot_represent name_int4_of_int #else let int4_of_int i = Int32.of_int i #endif let name_uint4_of_int = "uint4_of_int" #ifdef WORDSIZE_64 let uint4_of_int i = let j = i asr 32 in if j = 0 then (i lsl 31) asr 31 (* fix sign *) else cannot_represent name_uint4_of_int #else let uint4_of_int i = if i >= 0 then Int32.of_int i else cannot_represent name_uint4_of_int #endif let int8_of_int = Int64.of_int let name_uint8_of_int = "uint8_of_int" let uint8_of_int i = if i >= 0 then Int64.of_int i else cannot_represent name_uint8_of_int (**********************************************************************) (* Int32 and Int64 support: int[32|64]_of_[u]intn *) (**********************************************************************) #ifdef WORDSIZE_64 let int32_of_int4 x = Int32.of_int x #else let int32_of_int4 x = x #endif let name_int32_of_uint4 = "int32_of_uint4" #ifdef WORDSIZE_64 let int32_of_uint4 x = if x >= 0 then Int32.of_int x else cannot_represent name_int32_of_uint4 #else let int32_of_uint4 x = if x >= 0l then x else cannot_represent name_int32_of_uint4 #endif let c_int32_min_int_64 = Int64.of_int32 Int32.min_int let c_int32_max_int_64 = Int64.of_int32 Int32.max_int let name_int32_of_int8 = "int32_of_int8" let int32_of_int8 x = if x >= (-0x8000_0000L) && x <= 0x7fff_0000L then Int64.to_int32 x else cannot_represent name_int32_of_int8 let name_int32_of_uint8 = "int32_of_uint8" let int32_of_uint8 x = if x >= 0L && x <= 0x7fff_0000L then Int64.to_int32 x else cannot_represent name_int32_of_uint8 #ifdef WORDSIZE_64 let int64_of_int4 = Int64.of_int #else let int64_of_int4 = Int64.of_int32 #endif #ifdef WORDSIZE_64 let int64_of_uint4 x = if x >= 0 then Int64.of_int x else Int64.add (Int64.of_int x) 0x1_0000_0000L #else let int64_of_uint4 x = if x >= 0l then Int64.of_int32 x else Int64.add (Int64.of_int32 x) 0x1_0000_0000L #endif let int64_of_int8 x = x let name_int64_of_uint8 = "int64_of_uint8" let int64_of_uint8 x = if x >= 0L then x else cannot_represent name_int64_of_uint8 (**********************************************************************) (* Int32 and Int64 support: [u]intn_of_int[32|64] *) (**********************************************************************) #ifdef WORDSIZE_64 let int4_of_int32 = Int32.to_int #else let int4_of_int32 x = x #endif let name_uint4_of_int32 = "uint4_of_int32" let uint4_of_int32 i = if i < 0l then cannot_represent name_uint4_of_int32; int4_of_int32 i let int8_of_int32 = Int64.of_int32 let name_uint8_of_int32 = "uint8_of_int32" let uint8_of_int32 i = if i < 0l then cannot_represent name_uint8_of_int32; Int64.of_int32 i let name_int4_of_int64 = "int4_of_int64" #ifdef WORDSIZE_64 let int4_of_int64 i = if i >= (-0x8000_0000L) && i <= 0x7fff_ffffL then Int64.to_int i else cannot_represent name_int4_of_int64 #else let int4_of_int64 i = if i >= (-0x8000_0000L) && i <= 0x7fff_ffffL then Int64.to_int32 i else cannot_represent name_int4_of_int64 #endif let name_uint4_of_int64 = "uint4_of_int64" let uint4_of_int64 i = if i < 0L || i > 0xffff_ffffL then cannot_represent name_uint4_of_int64; #ifdef WORDSIZE_64 Int64.to_int(Int64.shift_right (Int64.shift_left i 32) 32) (* sign! *) #else Int64.to_int32 i #endif let int8_of_int64 i = i let name_uint8_of_int64 = "uint8_of_int64" let uint8_of_int64 i = if i < 0L then cannot_represent name_uint8_of_int64; i (**********************************************************************) (* logical_xxx_of_xxx *) (**********************************************************************) #ifdef WORDSIZE_64 let logical_uint4_of_int32 x = Int32.to_int x let logical_int32_of_uint4 x = Int32.of_int x #else let logical_uint4_of_int32 x = x let logical_int32_of_uint4 x = x #endif let logical_uint8_of_int64 x = x let logical_int64_of_uint8 x = x (**********************************************************************) (* min/max *) (**********************************************************************) let min_int4 = int4_of_int32 Int32.min_int let min_uint4 = uint4_of_int 0 let min_int8 = int8_of_int64 Int64.min_int let min_uint8 = uint8_of_int 0 let max_int4 = int4_of_int32 Int32.max_int let max_uint4 = logical_uint4_of_int32 (-1l) let max_int8 = int8_of_int64 Int64.max_int let max_uint8 = logical_uint8_of_int64 (-1L) (**********************************************************************) (* floating point *) (**********************************************************************) let fp8_of_fp4 x = (* Requires O'Caml >= 3.08 *) Int64.bits_of_float (Int32.float_of_bits x) let fp4_of_fp8 x = (* Requires O'Caml >= 3.08 *) Int32.bits_of_float (Int64.float_of_bits x) let float_of_fp8 x = (* Requires O'Caml >= 3.01 *) Int64.float_of_bits x let float_of_fp4 x = (* Requires O'Caml >= 3.08 *) Int32.float_of_bits x (* Old: * float_of_fp8 (fp8_of_fp4 x) *) let fp8_of_float x = (* Requires O'Caml >= 3.01 *) Int64.bits_of_float x let fp4_of_float x = (* Requires O'Caml >= 3.08 *) Int32.bits_of_float x (* Old: * fp4_of_fp8 (fp8_of_float x) *) let mk_fp4 x = int32_of_int4 (mk_int4 x) let mk_fp8 = mk_int8 let dest_fp4 x = dest_int4 (int4_of_int32 x) let dest_fp8 = dest_int8 module BE : ENCDEC = struct (**********************************************************************) (* read_[u]intn *) (**********************************************************************) #ifdef WORDSIZE_64 #ifdef USE_NETSYS_XDR let read_int4_unsafe = Netsys_xdr.s_read_int4_64_unsafe #else let read_int4_unsafe s pos = let n3 = Char.code (Bytes.unsafe_get s pos) in let x = (n3 lsl 55) asr 31 in (* sign! *) let n2 = Char.code (Bytes.unsafe_get s (pos+1)) in let x = x lor (n2 lsl 16) in let n1 = Char.code (Bytes.unsafe_get s (pos+2)) in let x = x lor (n1 lsl 8) in let n0 = Char.code (Bytes.unsafe_get s (pos+3)) in x lor n0 #endif #else let read_int4_unsafe s pos = let n3 = Int32.of_int (Char.code (Bytes.unsafe_get s pos)) in let x = Int32.shift_left n3 24 in let n2 = Int32.of_int (Char.code (Bytes.unsafe_get s (pos+1))) in let x = Int32.logor x (Int32.shift_left n2 16) in let n1 = Int32.of_int (Char.code (Bytes.unsafe_get s (pos+2))) in let x = Int32.logor x (Int32.shift_left n1 8) in let n0 = Int32.of_int (Char.code (Bytes.unsafe_get s (pos+3))) in Int32.logor x n0 #endif (* seems to be slightly better than Int32.logor (Int32.shift_left n3 24) (Int32.logor (Int32.shift_left n2 16) (Int32.logor (Int32.shift_left n1 8) n0)) *) let read_int4 s pos = if pos < 0 || pos + 4 > Bytes.length s then raise Out_of_range; read_int4_unsafe s pos #ifdef WORDSIZE_64 #ifdef USE_NETSYS_XDR #define FAST_READ_INT8 defined #endif #endif #ifdef FAST_READ_INT8 let read_int8_unsafe s pos = let x1 = Netsys_xdr.s_read_int4_64_unsafe s pos in let x0 = Netsys_xdr.s_read_int4_64_unsafe s (pos+4) in Int64.logor (Int64.logand (Int64.of_int x0) 0xFFFF_FFFFL) (Int64.shift_left (Int64.of_int x1) 32) #else let read_int8_unsafe s pos = let n7 = Int64.of_int (Char.code (Bytes.unsafe_get s pos)) in let x = Int64.shift_left n7 56 in let n6 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+1))) in let x = Int64.logor x (Int64.shift_left n6 48) in let n5 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+2))) in let x = Int64.logor x (Int64.shift_left n5 40) in let n4 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+3))) in let x = Int64.logor x (Int64.shift_left n4 32) in let n3 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+4))) in let x = Int64.logor x (Int64.shift_left n3 24) in let n2 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+5))) in let x = Int64.logor x (Int64.shift_left n2 16) in let n1 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+6))) in let x = Int64.logor x (Int64.shift_left n1 8) in let n0 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+7))) in Int64.logor x n0 #endif let read_int8 s pos = if pos < 0 || pos + 8 > Bytes.length s then raise Out_of_range; read_int8_unsafe s pos let read_uint4 = read_int4 let read_uint8 = read_int8 let read_uint4_unsafe = read_int4_unsafe let read_uint8_unsafe = read_int8_unsafe;; let read_string_int4 s p = read_int4 (Bytes.unsafe_of_string s) p let read_string_int8 s p = read_int8 (Bytes.unsafe_of_string s) p let read_string_uint4 s p = read_uint4 (Bytes.unsafe_of_string s) p let read_string_uint8 s p = read_uint8 (Bytes.unsafe_of_string s) p let read_string_int4_unsafe s p = read_int4_unsafe (Bytes.unsafe_of_string s) p let read_string_int8_unsafe s p = read_int8_unsafe (Bytes.unsafe_of_string s) p let read_string_uint4_unsafe s p = read_uint4_unsafe (Bytes.unsafe_of_string s) p let read_string_uint8_unsafe s p = read_uint8_unsafe (Bytes.unsafe_of_string s) p (**********************************************************************) (* write_[u]intn *) (**********************************************************************) #ifdef WORDSIZE_64 #ifdef USE_NETSYS_XDR let write_int4_unsafe = Netsys_xdr.s_write_int4_64_unsafe #else let write_int4_unsafe s pos x = let n3 = (x lsr 24) land 0xff in Bytes.unsafe_set s pos (Char.unsafe_chr n3); let n2 = (x lsr 16) land 0xff in Bytes.unsafe_set s (pos+1) (Char.unsafe_chr n2); let n1 = (x lsr 8) land 0xff in Bytes.unsafe_set s (pos+2) (Char.unsafe_chr n1); let n0 = x land 0xff in Bytes.unsafe_set s (pos+3) (Char.unsafe_chr n0); () #endif #else let write_int4_unsafe s pos x = let n3 = Int32.to_int (Int32.shift_right_logical x 24) land 0xff in Bytes.unsafe_set s pos (Char.unsafe_chr n3); let n2 = Int32.to_int (Int32.shift_right_logical x 16) land 0xff in Bytes.unsafe_set s (pos+1) (Char.unsafe_chr n2); let n1 = Int32.to_int (Int32.shift_right_logical x 8) land 0xff in Bytes.unsafe_set s (pos+2) (Char.unsafe_chr n1); let n0 = Int32.to_int (Int32.logand x 0xffl) in Bytes.unsafe_set s (pos+3) (Char.unsafe_chr n0); () #endif ;; let write_int4 s pos x = if pos < 0 || pos + 4 > Bytes.length s then raise Out_of_range; write_int4_unsafe s pos x #ifdef WORDSIZE_64 #ifdef USE_NETSYS_XDR #define FAST_WRITE_INT8 defined #endif #endif #ifdef FAST_WRITE_INT8 let write_int8_unsafe s pos x = Netsys_xdr.s_write_int4_64_unsafe s pos (Int64.to_int (Int64.shift_right x 32)); Netsys_xdr.s_write_int4_64_unsafe s (pos+4) (Int64.to_int (Int64.logand x 0xFFFF_FFFFL)) #else let write_int8_unsafe s pos x = let n7 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 56) 0xffL) in Bytes.unsafe_set s pos (Char.unsafe_chr n7); let n6 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 48) 0xffL) in Bytes.unsafe_set s (pos+1) (Char.unsafe_chr n6); let n5 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 40) 0xffL) in Bytes.unsafe_set s (pos+2) (Char.unsafe_chr n5); let n4 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 32) 0xffL) in Bytes.unsafe_set s (pos+3) (Char.unsafe_chr n4); let n3 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 24) 0xffL) in Bytes.unsafe_set s (pos+4) (Char.unsafe_chr n3); let n2 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 16) 0xffL) in Bytes.unsafe_set s (pos+5) (Char.unsafe_chr n2); let n1 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 8) 0xffL) in Bytes.unsafe_set s (pos+6) (Char.unsafe_chr n1); let n0 = Int64.to_int (Int64.logand x 0xffL) in Bytes.unsafe_set s (pos+7) (Char.unsafe_chr n0); () #endif let write_int8 s pos x = if pos < 0 || pos + 8 > Bytes.length s then raise Out_of_range; write_int8_unsafe s pos x let write_uint4 = write_int4 let write_uint8 = write_int8 let write_uint4_unsafe = write_int4_unsafe let write_uint8_unsafe = write_int8_unsafe (**********************************************************************) (* [u]intn_as_string *) (**********************************************************************) let int4_as_bytes x = let s = Bytes.create 4 in write_int4 s 0 x; s let uint4_as_bytes x = let s = Bytes.create 4 in write_uint4 s 0 x; s let int8_as_bytes x = let s = Bytes.create 8 in write_int8 s 0 x; s let uint8_as_bytes x = let s = Bytes.create 8 in write_int8 s 0 x; s let int4_as_string x = Bytes.unsafe_to_string(int4_as_bytes x) let int8_as_string x = Bytes.unsafe_to_string(int8_as_bytes x) let uint4_as_string x = Bytes.unsafe_to_string(uint4_as_bytes x) let uint8_as_string x = Bytes.unsafe_to_string(uint8_as_bytes x) (**********************************************************************) (* floating-point numbers *) (**********************************************************************) let fp4_as_string x = int4_as_string (int4_of_int32 x) let fp8_as_string x = int8_as_string (int8_of_int64 x) let fp4_as_bytes x = int4_as_bytes (int4_of_int32 x) let fp8_as_bytes x = int8_as_bytes (int8_of_int64 x) let read_fp4 s pos = int32_of_int4(read_int4 s pos) let read_string_fp4 s pos = int32_of_int4(read_string_int4 s pos) let read_fp8 s pos = int64_of_int8(read_int8 s pos) let read_string_fp8 s pos = int64_of_int8(read_string_int8 s pos) let write_fp4 s pos x = write_int4 s pos (int4_of_int32 x) let write_fp8 s pos x = write_int8 s pos (int8_of_int64 x) end module LE : ENCDEC = struct (**********************************************************************) (* read_[u]intn *) (**********************************************************************) #ifdef WORDSIZE_64 (* IFDEF USE_NETSYS_XDR THEN let read_int4_unsafe = Netsys_xdr.s_read_int4_64_unsafe (* FIXME *) ELSE *) let read_int4_unsafe s pos = let n3 = Char.code (Bytes.unsafe_get s (pos+3)) in let x = (n3 lsl 55) asr 31 in (* sign! *) let n2 = Char.code (Bytes.unsafe_get s (pos+2)) in let x = x lor (n2 lsl 16) in let n1 = Char.code (Bytes.unsafe_get s (pos+1)) in let x = x lor (n1 lsl 8) in let n0 = Char.code (Bytes.unsafe_get s pos) in x lor n0 (* END *) #else let read_int4_unsafe s pos = let n3 = Int32.of_int (Char.code (Bytes.unsafe_get s (pos+3))) in let x = Int32.shift_left n3 24 in let n2 = Int32.of_int (Char.code (Bytes.unsafe_get s (pos+2))) in let x = Int32.logor x (Int32.shift_left n2 16) in let n1 = Int32.of_int (Char.code (Bytes.unsafe_get s (pos+1))) in let x = Int32.logor x (Int32.shift_left n1 8) in let n0 = Int32.of_int (Char.code (Bytes.unsafe_get s pos)) in Int32.logor x n0 #endif let read_int4 s pos = if pos < 0 || pos + 4 > Bytes.length s then raise Out_of_range; read_int4_unsafe s pos let read_int8_unsafe s pos = let n7 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+7))) in let x = Int64.shift_left n7 56 in let n6 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+6))) in let x = Int64.logor x (Int64.shift_left n6 48) in let n5 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+5))) in let x = Int64.logor x (Int64.shift_left n5 40) in let n4 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+4))) in let x = Int64.logor x (Int64.shift_left n4 32) in let n3 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+3))) in let x = Int64.logor x (Int64.shift_left n3 24) in let n2 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+2))) in let x = Int64.logor x (Int64.shift_left n2 16) in let n1 = Int64.of_int (Char.code (Bytes.unsafe_get s (pos+1))) in let x = Int64.logor x (Int64.shift_left n1 8) in let n0 = Int64.of_int (Char.code (Bytes.unsafe_get s pos)) in Int64.logor x n0 let read_int8 s pos = if pos < 0 || pos + 8 > Bytes.length s then raise Out_of_range; read_int8_unsafe s pos let read_uint4 = read_int4 let read_uint8 = read_int8 let read_uint4_unsafe = read_int4_unsafe let read_uint8_unsafe = read_int8_unsafe;; let read_string_int4 s p = read_int4 (Bytes.unsafe_of_string s) p let read_string_int8 s p = read_int8 (Bytes.unsafe_of_string s) p let read_string_uint4 s p = read_uint4 (Bytes.unsafe_of_string s) p let read_string_uint8 s p = read_uint8 (Bytes.unsafe_of_string s) p let read_string_int4_unsafe s p = read_int4_unsafe (Bytes.unsafe_of_string s) p let read_string_int8_unsafe s p = read_int8_unsafe (Bytes.unsafe_of_string s) p let read_string_uint4_unsafe s p = read_uint4_unsafe (Bytes.unsafe_of_string s) p let read_string_uint8_unsafe s p = read_uint8_unsafe (Bytes.unsafe_of_string s) p (**********************************************************************) (* write_[u]intn *) (**********************************************************************) #ifdef WORDSIZE_64 (* IFDEF USE_NETSYS_XDR THEN let write_int4_unsafe = Netsys_xdr.s_write_int4_64_unsafe ELSE *) let write_int4_unsafe s pos x = let n3 = (x lsr 24) land 0xff in Bytes.unsafe_set s (pos+3) (Char.unsafe_chr n3); let n2 = (x lsr 16) land 0xff in Bytes.unsafe_set s (pos+2) (Char.unsafe_chr n2); let n1 = (x lsr 8) land 0xff in Bytes.unsafe_set s (pos+1) (Char.unsafe_chr n1); let n0 = x land 0xff in Bytes.unsafe_set s pos (Char.unsafe_chr n0); () (* END *) #else let write_int4_unsafe s pos x = let n3 = Int32.to_int (Int32.shift_right_logical x 24) land 0xff in Bytes.unsafe_set s (pos+3) (Char.unsafe_chr n3); let n2 = Int32.to_int (Int32.shift_right_logical x 16) land 0xff in Bytes.unsafe_set s (pos+2) (Char.unsafe_chr n2); let n1 = Int32.to_int (Int32.shift_right_logical x 8) land 0xff in Bytes.unsafe_set s (pos+1) (Char.unsafe_chr n1); let n0 = Int32.to_int (Int32.logand x 0xffl) in Bytes.unsafe_set s pos (Char.unsafe_chr n0); () #endif ;; let write_int4 s pos x = if pos < 0 || pos + 4 > Bytes.length s then raise Out_of_range; write_int4_unsafe s pos x let write_int8_unsafe s pos x = let n7 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 56) 0xffL) in Bytes.unsafe_set s (pos+7) (Char.unsafe_chr n7); let n6 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 48) 0xffL) in Bytes.unsafe_set s (pos+6) (Char.unsafe_chr n6); let n5 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 40) 0xffL) in Bytes.unsafe_set s (pos+5) (Char.unsafe_chr n5); let n4 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 32) 0xffL) in Bytes.unsafe_set s (pos+4) (Char.unsafe_chr n4); let n3 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 24) 0xffL) in Bytes.unsafe_set s (pos+3) (Char.unsafe_chr n3); let n2 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 16) 0xffL) in Bytes.unsafe_set s (pos+2) (Char.unsafe_chr n2); let n1 = Int64.to_int (Int64.logand (Int64.shift_right_logical x 8) 0xffL) in Bytes.unsafe_set s (pos+1) (Char.unsafe_chr n1); let n0 = Int64.to_int (Int64.logand x 0xffL) in Bytes.unsafe_set s pos (Char.unsafe_chr n0); () let write_int8 s pos x = if pos < 0 || pos + 8 > Bytes.length s then raise Out_of_range; write_int8_unsafe s pos x let write_uint4 = write_int4 let write_uint8 = write_int8 let write_uint4_unsafe = write_int4_unsafe let write_uint8_unsafe = write_int8_unsafe (**********************************************************************) (* [u]intn_as_string *) (**********************************************************************) let int4_as_bytes x = let s = Bytes.create 4 in write_int4 s 0 x; s let uint4_as_bytes x = let s = Bytes.create 4 in write_uint4 s 0 x; s let int8_as_bytes x = let s = Bytes.create 8 in write_int8 s 0 x; s let uint8_as_bytes x = let s = Bytes.create 8 in write_int8 s 0 x; s let int4_as_string x = Bytes.unsafe_to_string(int4_as_bytes x) let int8_as_string x = Bytes.unsafe_to_string(int8_as_bytes x) let uint4_as_string x = Bytes.unsafe_to_string(uint4_as_bytes x) let uint8_as_string x = Bytes.unsafe_to_string(uint8_as_bytes x) (**********************************************************************) (* floating-point numbers *) (**********************************************************************) let fp4_as_string x = int4_as_string (int4_of_int32 x) let fp8_as_string x = int8_as_string (int8_of_int64 x) let fp4_as_bytes x = int4_as_bytes (int4_of_int32 x) let fp8_as_bytes x = int8_as_bytes (int8_of_int64 x) let read_fp4 s pos = int32_of_int4(read_int4 s pos) let read_string_fp4 s pos = int32_of_int4(read_string_int4 s pos) let read_fp8 s pos = int64_of_int8(read_int8 s pos) let read_string_fp8 s pos = int64_of_int8(read_string_int8 s pos) let write_fp4 s pos x = write_int4 s pos (int4_of_int32 x) let write_fp8 s pos x = write_int8 s pos (int8_of_int64 x) end #ifdef HOST_IS_BIG_ENDIAN module HO = BE #else module HO = LE #endif ;; ocamlnet-4.1.2/src/netstring/netx509_pubkey.mli0000644000175000017500000002210212731530350020042 0ustar gerdgerd(** X.509 public key cryptography - keys and naming *) (** Support for reading in public keys and retrieving the type of the key. This module is mostly about naming key types and algorithms. In the X.509 standard a public key is often part of a certificate and there stored in the [subjectPublicKeyInfo] field. However, "raw" public keys (i.e. outside certificates) are also known. In this case, the same representation as for [subjectPublicKeyInfo] field is chosen and just stored separately in a file. Like certificates, public keys are described by an ASN.1 syntax and are normally stored by applying the DER encoding rules. If stored in files, PEM headers for the DER encoding are common. Such files have a PEM header of "BEGIN PUBLIC KEY". Note that the header - unlike for private keys - does not indicate the type of key. The type is already a member of the [subjectPublicKeyInfo] field. A public key consists of three parts: - the OID of the type of the key - the parameters of the algorithm - the key data A certain type of public key can only be used with certain algorithms. Often, the OID for the type of the key is simply set to the OID for the simplest algorithm that can be used with the key. For example, RSA keys have the OID of the PKCS-1 encryption algorithm. However, you can use the same keys also with the slightly more complicated PKCS-1 signing algorithms. It depends on the algorithm whether the parameters can be changed while keeping the key data. See {!Netx509_pubkey_crypto} for functions that actually encrypt or sign data with the current crypto provider. *) type oid = Netoid.t (** OIDs are just integer sequences *) (* TODO: type pubkey_params = Pubkey_params of Netasn1.Value.value option *) type alg_id = Alg_id of oid * Netasn1.Value.value option (** Algorithms are identified by an OID and OID-specific parameters. *) type pubkey = { pubkey_type : alg_id; pubkey_data : Netasn1.Value.bitstring_value; } (** Public key info: the key as such plus the algorithm. This combination is stored in PEM files tagged with "PUBLIC KEY", and also part of X.509 certificates. *) type hash_function = [ `SHA_1 | `SHA_224 | `SHA_256 | `SHA_384 | `SHA_512 ] type maskgen_function = [ `MGF1 of hash_function ] #ifdef HAVE_EXTENSIVE_VARIANTS type alg_param = .. type alg_param += #else type alg_param = #endif | P_PSS of hash_function * maskgen_function * int | P_OAEP of hash_function * maskgen_function * string type encrypt_alg = Encrypt of oid * alg_param option (** An algorithm that can be used for encryption. Same format as [Alg_id] *) type sign_alg = Sign of oid * alg_param option (** An algorithm that can be used for signing. Same format as [Alg_id] *) type kex_alg = Kex of oid * alg_param option (** An algorithm that can be used for key agreement. Same format as [Alg_id] Remember that you can use any key agreement protocol also as public key mechanism: if Alice sends Bob message A based on a secret a, and Bob replies with message B based on a secret b, and both agree on a key K=f(a,b), you can consider A as the public key and Alices's secret a as the private key. The message B is a parameter of the ciphertext (comparable to the IV in symmetric cryptography), and K is used as transport key (for a symmetric cipher). That's why the key agreement algorithms appear here. *) val decode_pubkey_from_der : string -> pubkey (** Decodes a DER-encoded public key info structure. Note that this function performs only a partial check on the integrity of the data. *) val encode_pubkey_to_der : pubkey -> string (** Encodes a public key info structure as DER *) val read_pubkey_from_pem : Netchannels.in_obj_channel -> pubkey (** Reads a PEM file tagged as "PUBLIC KEY". Note that this function performs only a partial check on the integrity of the data. *) type privkey = Privkey of string * string (** [(format,data)], using the formats: "RSA", "DSA", "DH", "EC". The [data] string is for the mentioned formats DER-encoded. *) val read_privkey_from_pem : Netchannels.in_obj_channel -> privkey (** Reads a PEM file tagged as "... PRIVATE KEY". This function cannot handle encrypted private keys. Note that this function performs only a partial check on the integrity of the data. *) module Key : sig (** These OIDs are used when storing public keys *) val rsa_key : oid (** alias PKCS-1. RFC-3279, RFC-3447 *) val rsassa_pss_key : oid (** RSASSA-PSS. RFC-4055, RFC-3447 *) val rsaes_oaep_key : oid (** RSAES-OAEP. RFC-4055, RFC-3447 *) val dsa_key : oid (** DSA. RFC-3279 *) val dh_key : oid (** DH. RFC-3279 *) val ec_key : oid (** All EC variants (ECDSA, ECDH, ECMQV). RFC-3279 *) val ecdh_key : oid (** EC restricted to ECDH (RFC-5480) *) val ecmqv_key : oid (** EC restricted to ECMQV (RFC-5480) *) val kea_key : oid (** KEA. RFC-3279 *) val eddsa_key : oid (** EDDSA. draft-josefsson-pkix-eddsa *) val catalog : (string * string list * string * oid) list (** [(name, aliases, privkey_name, oid)] *) val private_key_format_of_key : oid -> string (** Get the type of private key for a public key OID *) (** It is possible to derive public keys from [rsa_key] format so that they can be used with the RSASSA-PSS and RSAES-OAEP algorithms: *) val create_rsassa_pss_alg_id : hash_function:hash_function -> maskgen_function:maskgen_function -> salt_length:int -> unit -> alg_id (** [create_rsassa_pss_alg_id ... ]: Creates an algorithm identifier for RSASSA-PSS. *) val create_rsassa_pss_key : hash_function:hash_function -> maskgen_function:maskgen_function -> salt_length:int -> pubkey -> pubkey (** Derives a public key that is specific for RSASSA-PSS from an RSA public key. *) val create_rsaes_oaep_alg_id : hash_function:hash_function -> maskgen_function:maskgen_function -> psource_function:string -> unit -> alg_id (** [create_rsaep_oaep_alg_id ... ]: Creates an algorithm identifier for RSAES-OAEP. *) val create_rsaes_oaep_key : hash_function:hash_function -> maskgen_function:maskgen_function -> psource_function:string -> pubkey -> pubkey (** Derives a public key that is specific for RSAES-OAEP from an RSA public key. *) end module Encryption : sig (** These algorithms are used for encryption/decryption *) val rsa : encrypt_alg (** alias RSAES-PKCS1-v1_5 *) val rsaes_oaep : hash_function:hash_function -> maskgen_function:maskgen_function -> psource_function:string -> encrypt_alg (** RSAES-OAEP *) val catalog : (string * string list * encrypt_alg * oid) list (** [(name, aliases, oid, pubkey_oid)] *) val encrypt_alg_of_pubkey : pubkey -> encrypt_alg (** Normally use the algorithm that is present in the public key *) val alg_id_of_encrypt_alg : encrypt_alg -> alg_id (** Get the alg_id of an encryption alg *) val key_oid_of_encrypt_alg : encrypt_alg -> oid (** The OID public keys need to have *) end module Keyagreement : sig val dh : kex_alg (** DH *) val ec : kex_alg (** ECDH using unrestricted keys *) val ecdh : kex_alg (** ECDH *) val ecmqv : kex_alg (** ECMQV *) val kea : kex_alg (** KEA *) val catalog : (string * string list * kex_alg * oid) list (** [(name, aliases, oid, pubkey_oid)] *) val alg_id_of_kex_alg : kex_alg -> alg_id (** Get the alg_id of a key agreement alg *) val key_oid_of_kex_alg : kex_alg -> oid (** The OID public keys need to have *) end module Signing : sig (** These algorithms are used for signing *) val rsa_with_sha1 : sign_alg (** RSASSA-PKCS1-v1_5 *) val rsa_with_sha224 : sign_alg val rsa_with_sha256 : sign_alg val rsa_with_sha384 : sign_alg val rsa_with_sha512 : sign_alg val rsassa_pss: hash_function:hash_function -> maskgen_function:maskgen_function -> salt_length:int -> sign_alg (** RSASSA-PSS *) val dsa_with_sha1 : sign_alg (** DSA *) val dsa_with_sha224 : sign_alg val dsa_with_sha256 : sign_alg val ecdsa_with_sha1 : sign_alg (** ECDSA *) val ecdsa_with_sha224 : sign_alg val ecdsa_with_sha256 : sign_alg val ecdsa_with_sha384 : sign_alg val ecdsa_with_sha512 : sign_alg val eddsa : sign_alg (** EDDSA. draft-josefsson-pkix-eddsa *) val catalog : (string * string list * sign_alg * oid) list (** [(name, aliases, oid, container_oid)] *) val alg_id_of_sign_alg : sign_alg -> alg_id (** Get the alg_id of a sign alg *) val key_oid_of_sign_alg : sign_alg -> oid (** The OID public keys need to have *) end ocamlnet-4.1.2/src/netstring/netdate.mli0000644000175000017500000003072112731530350016701 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Support for common date/time parsing and formatting. * Many routines refer to the epoch, which for Unix is * 00:00:00 UTC, January 1, 1970. Timestamps given as * "seconds since the epoch" ignore leap seconds. *) type t = { year : int; (** complete year *) month : int; (** 1..12 *) day : int; (** 1..31 *) hour : int; (** 0..23 *) minute : int; (** 0..59 *) second : int; (** 0..60 (60=leapsecond) *) nanos : int; (** nanoseconds, new since Ocamlnet-3.5 *) zone : int; (** in minutes; 60 = UTC+0100 *) week_day : int (** 0 = sunday; -1 if not given *) } val localzone : int (** The offset in minutes for the local time zone from the UTC. This is the zone from the time when the program was started. For long-running programs, it is possible that the zone changes when daylight savings become effective or non-effective. *) val localzone_nodst : int (** Returns the offset for the local time zone for the case that daylight savings are not effective. *) val get_localzone : unit -> int (** Retrieves the current offset for the local time zone, taking daylight savings into account. *) val create : ?localzone:bool -> ?zone:int -> ?nanos:int -> float -> t (** Convert the time (seconds since the epoch) to a date/time record The [nanos] are added to the float as nanoseconds. If [zone] is set this zone is taken. Otherwise, if [localzone] is set, the local timezone is used that is valid at the requested time. Otherwise, UTC is used. Note that [create ~localzone:true t] is different from [create ~zone:(get_localzone()) t] because the latter assumes the timezone that is in effect when the function is called, and not the timezone at the time [t]. *) type localization = { full_day_names : string array; (** Element [k] contains the name of the week day [k] (0=Sunday) *) abbr_day_names : string array; (** Element [k] contains the abbreviated name of the week day [k] (0=Sunday) *) parsed_day_names : string list array; (** Element [k] contains a list of all possible names of the week day [k]. The list includes full and abbreviated names, but can also contain any other allowed name (aliases). The names here are in lowercase characters. *) full_month_names : string array; (** Element [k] contains the name of the month day [k] (0=January) *) abbr_month_names : string array; (** Element [k] contains the abbreviated name of the month day [k] (0=January) *) parsed_month_names : string list array; (** Element [k] contains a list of all possible names of the month [k]. The list includes full and abbreviated names, but can also contain any other allowed name (aliases). The names here are in lowercase characters. *) timezone_names : (string * int * bool) list; (** A list of pairs [(name,offset,isdst)] of timezones. The offset is in minutes. *) am_particle : string; (** A particle for "AM" *) pm_particle : string; (** A particle for "PM" *) d_format : string; (** Format string for date according to the locale *) t_format : string; (** Format string for time according to the locale *) d_t_format : string; (** Format string for date and time according to the locale *) t_format_ampm : string; (** Format string for time, using am and pm, according to the locale *) char_encoding : string; (** The character encoding of this locale *) } type compiled_localization val posix_l9n : localization (** The standard POSIX localization (English names) *) val l9n_from_locale : string -> localization (** Retrieves the localization from the passed locale (use "" for the standard locale). Timezone names are not provided by the locale This function is not available on Windows (the POSIX localization is always returned). *) val compile_l9n : localization -> compiled_localization (** Preprocess the localization data for faster parsing and printing *) val parse : ?localzone:bool -> ?zone:int -> ?l9n:compiled_localization -> string -> t (** Parse a string and return a date/time record. The following particles are recognized (by example): - Date: [1971/06/22] - Date: [06/22/1971] - Date: [1971-06-22] - Date: [22-June-1971] - Date: [22.06.1971] - Date: [June 22, 1971] - Date: [22 June 1971] - Date (2 digit year): [06/22/71] - Date (2 digit year): [22.06.71] - Date (2 digit year): [71-06-22] - Date (2 digit year): [22-June-71] - Month names ([June], [Jun]) - Weekday names ([Monday], [Mon]) - Time: [14:55] - Time: [14:55:28] - Time: [14:55:28.6754] (the fractional part is not returned) - Time may be preceded by [T] - Time zone: identifiers like [UTC], [CET], or [Z] - Time zone: [+01:00], [-01:00], only following time - Time zone: [+0100], [-0100], only following time Years must have 2 or 4 digits. 2-digit years >= 70 are interpreted as [1900+x]. 2-digit years < 70 are interpreted as [2000+x]. Support for 2-digit years will be removed in a future version of Ocamlnet. (Support for 3-digit years is already removed in Ocamlnet 3.0.) The names of months and weekdays are recognized that are configured with the [l9n] argument. By default, English names are recognized. A date must be given. Time, time zones, and weekdays are optional. A missing time is reported as "00:00:00". A missing weekday is reported by setting [week_day=(-1)]. A missing time zone is reported by setting [zone] to the passed default (which is determined from the [zone] and [localzone] arguments as for [create]). It is not checked whether the parsed numbers make sense (e.g. whether months are between 1 and 12). Date/time strings as defined in RFC 3339 are supported since Ocamlnet 3.0. *) val since_epoch : t -> float (** Convert a date/time record into the time (seconds since the epoch), rounded down to the next integral number. *) val since_epoch_timespec : t -> (float * int) (** Returns the seconds since the epoch as pair [(seconds,nanos)] *) val since_epoch_approx : t -> float (** Same, but the nanos are added to the seconds. The precision of floats is not sufficient to represent this precisely, so the result is only an approximation. *) val week_day : t -> int (** Returns the week day. If the [week_day] field is (-1) the week day is computed. *) val year_day : t -> int (** Returns the year day (range 0 to 365) *) val iso8601_week_pair : t -> int * int (** Returns [(week_number, year)] for the ISO-8601 definition of weeks. The week starts with Monday, and has numbers 1-53. A week is considered to be part of the year into which four or more days fall. *) val parse_epoch : ?l9n:compiled_localization -> ?localzone:bool -> ?zone:int -> string -> float (** Parse a string and return the time (integral seconds since the epoch) *) val parse_epoch_timespec : ?l9n:compiled_localization -> ?localzone:bool -> ?zone:int -> string -> float * int (** Parse a string and return the time (seconds and nanos since the epoch) *) val parse_epoch_approx : ?l9n:compiled_localization -> ?localzone:bool -> ?zone:int -> string -> float (** Parse a string and return the time (approximate seconds since the epoch) *) val format_to : ?l9n:compiled_localization -> Netchannels.out_obj_channel -> fmt:string -> t -> unit (** Format a date/time record according to the format string and outputs * the resulting string to the channel. * * The format string consists of zero or more conversion specifications * and ordinary characters. All ordinary characters are output directly * to the channel. A conversion specification consists of the '%' * character and one other character. * * The conversion specifications are: * * - [%A]: full weekday name. * - [%a]: abbreviated weekday name. * - [%B]: full month name. * - [%b]: abbreviated month name. * - [%C]: (year / 100) as an integer; single digits are preceded by a zero. * - [%c]: the preferred date+time representation of [l9n] * - [%D]: equivalent to ["%m/%d/%y"]. * - [%d]: day of the month as an integer (01-31); single digits are * preceded by a zero. * - [%e]: day of the month as an integer (1-31). * - [%F]: equivalent to ["%Y-%m-%d"] (ISO 8601) * - [%G]: the year of the week according to the ISO-8601 week definition * - [%g]: same as %G but uses a two-digit year * - [%H]: hour (24-hour clock) as an integer (00-23). * - [%h]: the same as %b. * - [%I]: hour (12-hour clock) as an integer (01-12). * - [%j]: day of the year as an integer (001-366). * - [%k]: hour (24-hour clock) as an integer (0-23); * single digits are preceded by a blank. * - [%l]: hour (12-hour clock) as an integer (1-12); * single digits are preceded by a blank. * - [%M]: minute as an integer (00-59). * - [%m]: month as an integer (01-12). * - [%n]: a newline. * - [%p]: "AM" or "PM" as defined in [l9n], in uppercase * - [%P]: "am" or "pm" as defined in [l9n], in lowercase * - [%R]: equivalent to ["%H:%M"]. * - [%r]: the time in am/pm notation according to [l9n] * - [%S]: second as an integer (00-60). This format accepts a precision argument, e.g. [%.3S] to print the second with three digits after the dot. * - [%s]: number of seconds since the epoch * - [%T]: equivalent to ["%H:%M:%S"]. * - [%t]: a tab. * - [%U]: week number of the year (Sunday as the first day * of the week) as an integer (00-53). * - [%u] weekday (Monday as the first day of the week) as * an integer (1-7). * - [%V]: week number of the year (ISO-8601 definition, use together with * [%G] or [%g] * - [%W]: week number of the year (Monday as the first day * of the week) as an integer (00-53). * - [%w]: weekday (Sunday as the first day of the week) as * an integer (0-6). * - [%X]: representation of the time according to [l9n] * - [%x]: representation of the date according to [l9n] * - [%Y]: year with century as an integer. * - [%y]: year without century as an integer (00-99). * - [%z]: time zone offset from UTC; a leading plus sign * stands for east of UTC, a minus sign for west of UTC, hours and * minutes follow with two digits each and no delimiter between them * (common form for RFC 822 date headers). * - [%Z]: same as [%z] * - [%:z]: time zone with colon, e.g. +05:00 (new since Ocamlnet 3) * - [%%]: a `%' character. * * If [l9n] is not passed, the default is the POSIX localization * (English names). *) val format : ?l9n:compiled_localization -> fmt:string -> t -> string (** Format a date/time record as a string *) val mk_date : ?localzone:bool -> ?zone:int -> ?nanos:int -> fmt:string -> float -> string (** Format the seconds (plus nanos if present) as a string *) val mk_mail_date : ?localzone:bool -> ?zone:int -> float -> string (** Convert the time (seconds since the epoch) to a date string that * conforms to RFC 1123 (which updates RFC 822). * * Example: ["Sun, 06 Nov 1994 08:49:37 -0500"]. *) val mk_usenet_date : ?localzone:bool -> ?zone:int -> float -> string (** Convert the time (seconds since the epoch) to a date string that * conforms to RFC 1036 (which obsoletes RFC 850). * * Example: ["Sunday, 06-Nov-94 08:49:37 -0500"]. * * Note that this format has only two digits for the year. *) val mk_internet_date : ?localzone:bool -> ?zone:int -> ?digits:int -> float -> string (** Convert the time (seconds since the epoch) to a date string that * conforms to RFC 3339. This is the most modern format, and should * be used if permitted by the network protocol. Pass in [digits] the * number of digits for the fractional part of seconds. * * Example: ["1996-12-19T16:39:57.89-08:00"]. *) ocamlnet-4.1.2/src/netstring/netaccel.mli0000644000175000017500000000132512731530350017031 0ustar gerdgerd(* $Id$ *) (** Accelerators for bytecode * * This module can be linked with executables to accelerate * certain functions. In particular, the following functions * will run faster: * * - {!Netaux.ArrayAux.int_blit} * - All conversion functions in {!Netconversion} when they * must read an ISO-8859-1 or UTF-8 encoded string * * It is not recommended to install the accelerators for native * code, however (and with the distributed build rules, this * is not done). * * To link this module, you must name both [netaccel.cma] and * [netaccel_link.cmo] explicitly on the ocamlc command line * (after [netstring.cma]). * If you use [findlib], this is done automatically. *) (**/**) val init : unit -> unit ocamlnet-4.1.2/src/netstring/netasn1.mli0000644000175000017500000005023612731530350016631 0ustar gerdgerd(* $Id$ *) (** ASN.1 support functions *) (** See below for a little intro into ASN.1: {!Netasn1.intro} *) open Netsys_types exception Out_of_range exception Parse_error of int (** Byte position in string *) exception Header_too_short module Type_name : sig type type_name = | Bool | Integer | Enum | Real | Bitstring | Octetstring | Null | Seq | Set | OID | ROID | ObjectDescriptor | External | Embedded_PDV | NumericString | PrintableString | TeletexString | VideotexString | VisibleString | IA5String | GraphicString | GeneralString | UniversalString | BMPString | UTF8String | CharString | UTCTime | GeneralizedTime end module Value : sig type pc = Primitive | Constructed type value = | Bool of bool (** Boolean (primitive) *) | Integer of int_value (** Integer (primitive) *) | Enum of int_value (** Enumeration (primitive) *) | Real of real_value (** Floating-point number, using either base 2 or base 10 (primitive) *) | Bitstring of bitstring_value (** Bit strings (primitive or constructed) *) | Octetstring of string (** Octet strings (primitive or constructed) *) | Null (** Null (primitive) *) | Seq of value list (** Sequences (records or arrays) (constructed) *) | Set of value list (** Sets (constructed) *) | Tagptr of tag_class * int * pc * Netstring_tstring.tstring_polybox * int * int (** Pointer to an undecoded value that was implicitly tagged. The [tag_class] can be [Application], [Context], or [Private]. *) | Tag of tag_class * int * pc * value (** Explicit tag (primitive or constructed depending on inner value) *) | ITag of tag_class * int * value (** Implicit tag (never returned by the decoder, but needed for encoding such tags) *) | OID of int array (* Object IDs (primitive) *) | ROID of int array (* Relative Object IDs (primitive) *) | ObjectDescriptor of string (** A placeholder with a comment (primitive) *) | External of value list (** Something complex I don't understand (constructed) *) | Embedded_PDV of value list (** Something complex I don't understand (constructed) *) | NumericString of string (** String made of digits and spaces (primitive or constructed) *) | PrintableString of string (** A small subset of ASCII (primitive or constructed) *) | TeletexString of string | VideotexString of string | VisibleString of string (** 7 bit ASCII w/o control characters (primitive or constructed) *) | IA5String of string (** 7 bit ASCII (primitive or constructed) *) | GraphicString of string (** ISO-2022-encoded string w/o control characters *) | GeneralString of string (** ISO-2022-encoded string *) | UniversalString of string (** Any ISO-10646-1 character string represented as UTF-32-BE (primitive or constructed). Roughly, ISO-10646-1 equals to Unicode. *) | BMPString of string (** Any ISO-10646-1 character string from only the basic multilingual plane, i.e. with code points <= 65535, represented as UTF-16-BE (primitive or constructed) *) | UTF8String of string (** Any ISO-10646-1 character string represented as UTF-8 (primitive or constructed) *) | CharString of string (** A complicated description of an arbitrary charset encoding (primitive or constructed) *) | UTCTime of time_value (** Like GeneralizedTime but less precise, and with 2-digit year *) | GeneralizedTime of time_value (** Calendar date with time of day, including timezone (primitive) *) and tag_class = | Universal | Application | Context | Private and int_value and real_value and bitstring_value and time_value type time_subtype = [ `U | `G ] val type_of_value : value -> Type_name.type_name option (** Returns the type, or [None] for [Tag], [ITag] and [Tagptr] *) (** {3 Integer} *) val get_int_repr : int_value -> string (** Get an integer as bytes *) val get_int_b256 : int_value -> int array (** Get an integer in base 256 notation, big endian. Negative values are represented using two's complement (i.e. the first array element is >= 128). The empty array means 0. *) val get_int : int_value -> int (** Get an integer as [int] if representable, or raise [Out_of_range] *) val get_int32 : int_value -> int32 (** Get an integer as [int32] if representable, or raise [Out_of_range] *) val get_int64 : int_value -> int64 (** Get an integer as [int64] if representable, or raise [Out_of_range] *) val int : int -> int_value (** Create an int *) val int32 : int32 -> int_value (** Create an int *) val int64 : int64 -> int_value (** Create an int *) val int_b256 : int array -> int_value (** Create an int from a base 256 number, big endian, signed *) (** {3 Real} *) (** Reals are not really supported ;-( *) val get_real_repr : real_value -> string (** Get the byte representation of the real *) (** {3 Bitstring} *) (** In some contexts it is usual that trailing zero bits are truncated. *) val get_bitstring_size : bitstring_value -> int (** Get the number of bits *) val get_bitstring_data : bitstring_value -> string (** Get the data. The last byte may be partial. The order of the bits in every byte: bit 7 (MSB) contains the first bit *) val get_bitstring_bits : ?size:int -> bitstring_value -> bool array (** Get the bitstring as bool array. If [size] is specified the array will have exactly this number of bits (by dropping exceeding data, or by adding [false] at the end) *) val get_bitstring_repr : bitstring_value -> string (** Get the representation *) val bitstring_of_bits : bool array -> bitstring_value (** Get the bitstring from a bool array *) val bitstring_of_string : string -> int -> bitstring_value (** Get the bitstring from a string and the total number of bits. The bits are taken from the beginning of the string (MSB first). If the string is shorter than the number of bits suggests, the remaining bits are assumed to be zero. If the string is longer than the number of bits suggests, the exceeding data is ignored. *) val truncate_trailing_zero_bits : bitstring_value -> bitstring_value (** Truncates the biggest trailing part that only consist of 0 bits *) (** {3 Time} *) (** Time values referring to the local time zone are not supported *) val get_time_subtype : time_value -> time_subtype (** Whether this is for UTCTime ([`U]) or GeneralizedTime ([`G]) *) val get_time_repr : time_value -> string (** Get the raw time string *) val get_time : time_value -> Netdate.t (** Get the time. Notes: - UTCTime years are two-digit years, and interpreted so that 0-49 is understood as 2000-2049, and 50-99 is understood as 1950-1999 (as required by X.509). - This function is restricted to the time formats occurring in DER (string terminates with "Z", i.e. UTC time zone) *) val utctime : Netdate.t -> time_value (** Create a time value for UTCTime. This function is restricted to years between 1950 and 2049. *) val gentime : digits:int -> Netdate.t -> time_value (** Create a time value for GeneralizedTime. [digits] is the number of fractional (subsecond) digits *) (** {3 Equality} *) val equal : value -> value -> bool (** Checks for equality. Notes: - [Tag] and [Tagptr] are considered different - [Tagptr] is checked by comparing the equality of the substring - [Set] is so far not compared as set, but as sequence (i.e. order matters) *) end val decode_ber : ?pos:int -> ?len:int -> string -> int * Value.value (** Decodes a BER-encoded ASN.1 value. Note that DER is a subset of BER, and can also be decoded. [pos] and [len] may select a substring for the decoder. By default, [pos=0], and [len] as large as necessary to reach to the end of the string. The function returns the number of interpreted bytes, and the value. It is not considered as an error if less than [len] bytes are consumed. The returned value represents implicitly tagged values as [Tagptr(class,tag,pc,pos,len)]. [pos] and [len] denote the substring containting the contents. Use {!Netasn1.decode_ber_contents} to further decode the value. You can use [ITag] to put the decoded value back into the tree. A number of values are not verified (i.e. nonsense values can be returned): - for all string types it is not checked whether the constraints are satisfied (e.g. whether an UTF8String really contains UTF-8). - [External], [Embedded_PDV] and [Real] are unchecked - Other values may first be checked on first access (e.g. [GeneralizedTime]). *) val decode_ber_tstring : ?pos:int -> ?len:int -> tstring -> int * Value.value (** Same for tagged strings *) val decode_ber_poly : ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> int * Value.value (** polymorphic version *) val decode_ber_contents : ?pos:int -> ?len:int -> ?indefinite:bool -> string -> Value.pc -> Type_name.type_name -> int * Value.value (** Decodes the BER-encoded contents of a data field. The contents are assumed to have the type denoted by [type_name]. [pos] and [len] may select a substring for the decoder. By default, [pos=0], and [len] as large as necessary to reach to the end of the string. If [indefinite], the extent of the contents region is considered as indefinite, and the special end marker is required. This is only allowed when [pc = Constructed]. The function returns the number of interpreted bytes, and the value. It is not considered as an error if less than [len] bytes are consumed. You need to use this function to recursively decode tagged values. If you get a [Tagptr(class,tag,pc,s,pos,len)] value, it depends on the kind of the tag how to proceed: - For explicit tags just invoke {!Netasn1.decode_ber} again with the given [pos] and [len] parameters. - For implicit tags you need to know the type of the field. Now call {!Netasn1.decode_ber_contents} with the right type name. The BER encoding doesn't include whether the tag is implicit or explicit, so the decode cannot do by itself the right thing here. *) val decode_ber_contents_tstring : ?pos:int -> ?len:int -> ?indefinite:bool -> tstring -> Value.pc -> Type_name.type_name -> int * Value.value (** Same for tagged strings *) val decode_ber_contents_poly : ?pos:int -> ?len:int -> ?indefinite:bool -> 's Netstring_tstring.tstring_ops -> 's -> Value.pc -> Type_name.type_name -> int * Value.value (** Polymorphic version *) val decode_ber_length : ?pos:int -> ?len:int -> string -> int (** Like [decode_ber], but returns only the length. This function skips many consistency checks. *) val decode_ber_length_tstring : ?pos:int -> ?len:int -> tstring -> int (** Same for tagged strings *) val decode_ber_length_poly : ?pos:int -> ?len:int -> 's Netstring_tstring.tstring_ops -> 's -> int (** Polymorphic version *) val decode_ber_header : ?pos:int -> ?len:int -> ?skip_length_check:bool -> string -> (int * Value.tag_class * Value.pc * int * int option) (** [let (hdr_len, tc, pc, tag, len_opt) = decode_ber_header s]: Decodes only the header: - [hdr_len] will be the length of the header in bytes - [tc] is the tag class - [pc] whether primitive or constructed - [tag] is the numeric tag value - [len_opt] is the length field, or [None] if the header selects indefinite length If [skip_length_check] is set, the function does not check whether the string is long enough to hold the whole data part. If the string is a valid beginning of a header, the special exception [Header_too_short] is raised (instead of [Parse_error]). *) val decode_ber_header_tstring : ?pos:int -> ?len:int -> ?skip_length_check:bool -> tstring -> (int * Value.tag_class * Value.pc * int * int option) (** Same for tagged strings *) val decode_ber_header_poly : ?pos:int -> ?len:int -> ?skip_length_check:bool -> 's Netstring_tstring.tstring_ops -> 's -> (int * Value.tag_class * Value.pc * int * int option) (** Polymorphic version *) val streamline_seq : (Value.tag_class * int * Type_name.type_name) list -> Value.value list -> Value.value option list (** [streamline_seq expected seq]: This function can be called for a list of values [Value.Seq seq], and will compare the list [seq] with the [expected] list, and will mark missing elements in the sequence, and will recursively decode the occurring elements with the type information from [expected]. For example, if [expected] is {[ [Context,0,Integer; Context,1,Octetstring; Context,2,IA5String] ]} and the passed [seq] is just {[ [Tagptr(Context,1,...)] ]} the function assumes that the elements with tags 0 and 2 are optional and it assumes that the element with tag 1 is decoded as [Octetstring], leading to {[ None; Some(Octetstring ...); None ]} It is allowed to put [Universal] tags into the [expected] list. The tag number is ignored in this case (for simplicity). *) val streamline_set : (Value.tag_class * int * Type_name.type_name) list -> Value.value list -> Value.value list (** [streamline_set typeinfo set]: This function can be called for a list of values [Value.Set seq], and decodes the list with the type information from [typeinfo]. For example, if [typeinfo] is {[ [Context,0,Integer; Context,1,Octetstring; Context,2,IA5String] ]} and the passed [set] is just {[ [Tagptr(Context,1,...); Tagptr(Context 0,...)] ]} the function decodes the elements as {[ [ Octetstring ...; Integer ... ] ]} *) (** {1:intro The Abstract Syntax Notation 1 (ASN.1)} ASN.1 allows you to represent structured values as octet streams. The values can be composed from a wide range of base types (e.g. numbers and many different kinds of strings) and can be arranged as sequences (records and arrays), sets, and tagged values (a concept fairly close to OCaml variant types). There is a definition language allowing you to define types and values. This language is not covered here (and there is no IDL compiler). Look for ITU X.680 standard if you want to know more. We focus here on the octet representation, which is sufficient for parsing and printing ASN.1 values. {2 Encoding rules} There are three variants on the representation level: - BER: Basic Encoding Rules - CER: Canonical Encoding Rules - DER: Distinguished Encoding Rules BER describes the basic way how the octets are obtained, but leaves several details up to the sender of an ASN.1 message. CER and DER use stricter rules that are subsets of BER so that a given value can only be represented in a single way. CER targets at large messages, whereas DER is optimized for small messages. This module includes a generic decoder for all BER messages, and {!Netasn1_encode} supports DER encoding. The ASN.1 octet representations are described in ITU X.690. {2 The TLV representation} ASN.1 uses a type-length-value (TLV) style representation, i.e. there is a header containing type information and the length of the data, followed by the payload data. The data can be primitive (e.g. a number) or "constructed" (i.e. a composition of further values). For certain data types the user can choose whether to prefer a primitive representation or a construction from several part values (e.g. a very long string can be given as a sequence of string chunks). Because of this, there is a {!Netasn1.Value.pc} bit in the representation so that this choice is available at runtime. The type is given as a numeric tag (a small number), and a tag class ({!Netasn1.Value.tag_class}). There are four tag classes: - Universal: These tags are used for types defined by the ASN.1 standard, and should not be used for anything else. For example the type OctetString gets the universal tag 3. - Application: These tags are intended for marking newly defined types. E.g. if you have a definition [type filename = string] and you would like to have filenames specially tagged to distinguish them from other uses of strings, the runtime representation of filenames could get an application tag (e.g. the number 8). In ASN.1 syntax: {[ Filename ::= [APPLICATION 8] IA5String ]} - Context-specific: These tags are intended for marking variants, i.e. tags that are local to a specific use. An example in ASN.1 syntax: {[ CustomerRecord ::= SET { name [0] VisibleString, mailingAddress [1] VisibleString, accountNumber [2] INTEGER, balanceDue [3] INTEGER } ]} The numbers in brackets are the context-specific tags. - Private: These are reserved for site-specific extensions of standardized message formats. Conceptionally, universal and application tags identify types, whereas context-specific tags identify variants (local cases). Both concepts are not cleanly separated, though. If you e.g. define a set of values, and one value variant is a string and another variant is an integer, there is no strict need to use context-specific tags, because the tags for the type "string" and for the type "integer" are already different. In ASN.1 syntax: {[ Example ::= SET { x VisibleString, y INTEGER } ]} A VisibleString has universal tag 26, and an INTEGER has universal tag 3. Note that the bracket notation includes a keyword "UNIVERSAL", "APPLICATION", or "PRIVATE" for these three classes, and that a plain number indicates context-specific tags. Finally, there are two ways of applying tags: Explicit and implicit. Explicit tagging is used when the binary values should retain the complete type information: If a tag is applied to an existing value, another header with tag and length field is created, and the value is seen as the contents of this construction. In other words, tagging is an explicit construction like others (e.g. like a record). Implicit tagging means that the tag of the existing value is replaced by the new tag. As tags also encode the types, this means that type information is lost, and you need apriori knowledge about the possible tags to decode such values (e.g. that an application tag 8 always means an IA5String). {2 How to decode values} The function {!Netasn1.decode_ber} will happily decode any BER data and return a complex {!Netasn1.Value.value} unless implicit tagging is used. Implicit tags cannot be decoded in one go because the type information is missing. Instead of completely decoding such tags, only a marker [Tagptr(tag_class,tag,pc,data,pos,len)] is created. Here, [tag_class] and [tag] describe the tag. The value to which the tag is applied is not yet parsed, but only a "pointer" in form of the string [data], the position [pos] and the byte length [len] is returned. This range inside [data] represents the inner value. After determining the type of this value (by knowing which type is applicable for [tag] and [tag_class]), you can call {!Netasn1.decode_ber_contents} to decode the value. This function is different from {!Netasn1.decode_ber} because it doesn't start at the header of the BER representation but after the header. The type needs to be passed explicitly because it isn't retrieved from the header. *) ocamlnet-4.1.2/src/netstring/nethtml.mli0000644000175000017500000003771312731530350016740 0ustar gerdgerd(* $Id$ * ---------------------------------------------------------------------- * *) (** Parsing of HTML *) (** The type [document] represents parsed HTML documents: * * {ul * {- [Element (name, args, subnodes)] is an element node for an element of * type [name] (i.e. written [...]) with arguments [args] * and subnodes [subnodes] (the material within the element). The arguments * are simply name/value pairs. Entity references (something like [&xy;]) * occuring in the values are {b not} resolved. * * Arguments without values (e.g. [