Where is the definition for this function?

I had to take mos of the links off because new users can only post 2 links. So put github dot com in front of the ones without link

I’m trying to understand this line of code from Mirage TCP/IP stack: github.com/mirage/mirage-tcpip/blob/master/test/test_connect.ml#L49

V.Stackv4.TCPV4.read flow >>= function

Here is where Stackv4 is defined: mirage/mirage-tcpip/blob/master/test/vnetif_common.ml#L72

and here’s where the TCPV4 part is defined: mirage/mirage-tcpip/blob/master/src/stack-direct/tcpip_stack_direct.ml#L43

as you can see, all of this resolves to a module that comes from Mirage_protocols.TCP, which is here mirage/mirage-protocols/blob/master/src/mirage_protocols.ml#L143

module type TCP = sig
  type error = private [> Tcp.error]
  type write_error = private [> Tcp.write_error]
  type ipaddr
  type ipinput
  type flow
  include Mirage_device.S
  include Mirage_flow.S with
      type flow   := flow
  and type error  := error
  and type write_error := write_error

  val dst: flow -> ipaddr * int
  val write_nodelay: flow -> Cstruct.t -> (unit, write_error) result Lwt.t
  val writev_nodelay: flow -> Cstruct.t list -> (unit, write_error) result Lwt.t
  val create_connection: ?keepalive:Keepalive.t -> t -> ipaddr * int -> (flow, error) result Lwt.t
  type listener = {
    process: flow -> unit Lwt.t;
    keepalive: Keepalive.t option;
  }
  val input: t -> listeners:(int -> listener option) -> ipinput
end

first of all, this is a type module, not an implementation. Even if read were here, it wouldn’t make sense because its just a declaration, not a definition.

Ok, so looks like read comes from the include Mirage_flow.S from here: https://github.com/mirage/mirage-flow/blob/master/src/mirage_flow.ml#L36

module type S = sig
  type error
  val pp_error: error Fmt.t
  type nonrec write_error = private [> write_error ]
  val pp_write_error: write_error Fmt.t
  type flow
  val read: flow -> (Cstruct.t or_eof, error) result Lwt.t
  val write: flow -> Cstruct.t -> (unit, write_error) result Lwt.t
  val writev: flow -> Cstruct.t list -> (unit, write_error) result Lwt.t
  val close: flow -> unit Lwt.t
end

but there’s no defintion for read, only a declaration. So where is the read definition?

By the way, see lots of flow named variables. Anyone know what this name suggests in the context of a tcp/ip stack?

It’s defined here.

You were close to finding it. You found that the Stackv4 module comes from vnetif_common.ml (after constructing a VNETIF_STACK). Here’s how to get from there to the definition:

  • Stackv4 is built by Tcp_ip_stack_direct.Make (ventif_common.ml#73);
  • Tcp_ip_stack_direct.Make says that its TCPV4 module is equal to the one that is passed to construct it – its last argument. (tcpip_stack_direct#L39).
  • Looking back at the last argument, we see that it comes from Tcp.Flow.Make (vnetif_common.ml#71).
  • Taking a look at src/tcp/flow.ml, we find the definition of read inside the Make functor. (flow.ml#572).

By the way, see lots of flow named variables. Anyone know what this name suggests in the context of a tcp/ip stack?

In Mirage terminology, a “flow” is a bidirectional stream of data to/from a particular endpoint (see documentation for mirage-flow). For this specific read function, the “flow” is an abstraction over a TCP socket.

1 Like

I’ve mistaken

Tcpv4 : TCPV4_DIRECT

as being like a default value or something, so I was looking as Tcpv4 actually being TCPV4_DIRECT

thanks!