PreviousUpNext

15.4.1179  src/lib/std/src/socket/socket-guts.pkg

## socket-guts.pkg

# Compiled by:
#     src/lib/std/src/standard-core.sublib


stipulate
    package int =  int_guts;                                            # int_guts                              is from   src/lib/std/src/bind-int-32.pkg
    package wg  =  winix_guts;                                          # winix_guts                            is from   src/lib/std/src/posix/winix-guts.pkg
    package ci  =  mythryl_callable_c_library_interface;                # mythryl_callable_c_library_interface  is from   src/lib/std/src/unsafe/mythryl-callable-c-library-interface.pkg
    package w8a =  rw_vector_of_one_byte_unts;                          # rw_vector_of_one_byte_unts            is from   src/lib/std/src/rw-vector-of-one-byte-unts.pkg
    package w8v =  vector_of_one_byte_unts;                             # vector_of_one_byte_unts               is from   src/lib/std/src/vector-of-one-byte-unts.pkg
    package ps  =  pre_socket;                                          # pre_socket                            is from   src/lib/std/src/socket/pre-socket.pkg
herein

    package   socket_guts
    : (weak)  Socket                                                    # Socket                                is from   src/lib/std/src/socket/socket.api
    {
        fun socket_fn  fun_name
            =
            ci::find_c_function { lib_name => "socket", fun_name };     # socket                                is in     src/c/lib/socket/cfun-list.h


        Wy8Vector = w8v::Vector;
        Wy8Array  = w8a::Rw_Vector;

        # The system's representation of a socket:
        #
        Socket_Fd
            =
            ps::Socket_Fd;

        # Import the various socket related types:
        #
        include pre_socket;

        # Bind socket C functions 
        #
        fun netdb_fun  fun_name
            =
            ci::find_c_function { lib_name => "socket", fun_name };

    #     dummyAddr = ADDRESS (w8v::from_list[]) 

        # Address families 
        #
        package af {

            include af;                         # af                    is from   src/lib/std/src/socket/pre-socket.pkg
                                                #                       via above 'include pre_socket'.

            my  list_addr_families:  Void -> List( ci::System_Constant )
                =
                socket_fn "listAddrFamilies";

            fun list ()
                =
                list::map
                    (fn arg =  (#2 arg, ADDRESS_FAMILY arg))
                    (list_addr_families ());

            fun to_string (ADDRESS_FAMILY (_, name))
                =
                name;

            fun from_string name
                =
                case (ci::find_system_constant (name, list_addr_families ()))
                    #
                    THE af =>  THE (ADDRESS_FAMILY af);
                    NULL   =>  NULL;
                esac;

        };

        # Socket types:
        #
        package socket {

            include pre_socket;

            Socket_Type
                =
                ps::socket::Socket_Type;

            my list_socket_types:  Void -> List( ci::System_Constant )
                =
                socket_fn "listSockTypes";                                      # listSockTypes def in    src/c/lib/socket/list-socket-types.c

                                                                                # socket        is from   src/lib/std/src/socket/pre-socket.pkg

            stream    =  socket::SOCKET_TYPE (ci::bind_system_constant ("STREAM", list_socket_types ()));
            datagram  =  socket::SOCKET_TYPE (ci::bind_system_constant ("DGRAM",  list_socket_types ()));

            fun list ()
                =
                list::map
                    (fn arg =  (#2 arg, socket::SOCKET_TYPE arg))
                    (list_socket_types ());

            fun to_string (socket::SOCKET_TYPE(_, name))
                =
                name;

            fun from_string name
                =
                case (ci::find_system_constant (name, list_socket_types ()))
                    #
                    THE ty =>  THE (socket::SOCKET_TYPE ty);
                    NULL   =>  NULL;
                esac;

        };

        # Socket control operations:
        #
        package control {
            #
            stipulate
                #
                fun the_else  control_fn (ps::SOCKET { file_descriptor, ... } )
                    =
                    control_fn( file_descriptor, NULL );


                fun set_opt  control_fn (ps::SOCKET { file_descriptor, ... }, value)
                    =
                    ignore (control_fn (file_descriptor, THE value));


                my ctl_debug:      (Socket_Fd, Null_Or(Bool)) -> Bool =         socket_fn "get_or_set_socket_debug_option";     # "get_or_set_socket_debug_option"              def in    src/c/lib/socket/get-or-set-socket-debug-option.c
                my ctl_reuseaddr:  (Socket_Fd, Null_Or(Bool)) -> Bool =         socket_fn "get_or_set_socket_reuseaddr_option";         # "get_or_set_socket_reuseaddr_option"          def in    src/c/lib/socket/get-or-set-socket-reuseaddr-option.c
                my ctl_keepalive:  (Socket_Fd, Null_Or(Bool)) -> Bool =         socket_fn "get_or_set_socket_keepalive_option";         # "get_or_set_socket_keepalive_option"          def in    src/c/lib/socket/get-or-set-socket-keepalive-option.c
                my ctl_dontroute:  (Socket_Fd, Null_Or(Bool)) -> Bool =         socket_fn "get_or_set_socket_dontroute_option";         # "get_or_set_socket_dontroute_option"          def in    src/c/lib/socket/get-or-set-socket-dontroute-option.c
                my ctl_broadcast:  (Socket_Fd, Null_Or(Bool)) -> Bool =         socket_fn "get_or_set_socket_broadcast_option";         # "get_or_set_socket_broadcast_option"          def in    src/c/lib/socket/get-or-set-socket-broadcast-option.c
                my ctl_oobinline:  (Socket_Fd, Null_Or(Bool)) -> Bool =         socket_fn "get_or_set_socket_oobinline_option";         # "get_or_set_socket_oobinline_option"          def in    src/c/lib/socket/get-or-set-socket-oobinline-option.c
                my ctl_sndbuf:     (Socket_Fd, Null_Or(Int )) -> Int  =         socket_fn "get_or_set_socket_sndbuf_option";                    # "get_or_set_socket_sndbuf_option"             def in    src/c/lib/socket/get-or-set-socket-sndbuf-option.c
                my ctl_rcvbuf:     (Socket_Fd, Null_Or(Int )) -> Int  =         socket_fn "get_or_set_socket_rcvbuf_option";                    # "get_or_set_socket_rcvbuf_option"             def in    src/c/lib/socket/get-or-set-socket-rcvbuf-option.c

                my ctl_linger:
                       (Socket_Fd,  Null_Or( Null_Or(Int) )) -> Null_Or(Int) =  socket_fn "get_or_set_socket_linger_option";                    # "get_or_set_socket_linger_option"             def in    src/c/lib/socket/get-or-set-socket-linger-option.c

            herein

                # Get/set socket options 

                fun get_debug x = the_else ctl_debug x;
                fun set_debug x = set_opt  ctl_debug x;

                fun get_reuseaddr x = the_else ctl_reuseaddr x;
                fun set_reuseaddr x = set_opt  ctl_reuseaddr x;
                fun get_keepalive x = the_else ctl_keepalive x;
                fun set_keepalive x = set_opt  ctl_keepalive x;
                fun get_dontroute x = the_else ctl_dontroute x;
                fun set_dontroute x = set_opt  ctl_dontroute x;

                fun get_linger socket
                    =
                    case (the_else ctl_linger socket)
                        #
                        THE t => THE (time_guts::from_seconds (int::to_multiword_int t));
                        NULL  => NULL;
                    esac;

                # NOTE: Should probably do some
                # range checking on the argument:       XXX BUGGO FIXME 

                fun set_linger (socket, THE t)
                        =>
                        set_opt ctl_linger (socket, THE (int::from_multiword_int (time_guts::to_seconds t)));

                    set_linger (socket, NULL)
                        =>
                        set_opt ctl_linger (socket, NULL);
                end;

                fun get_broadcast x = the_else ctl_broadcast x;
                fun set_broadcast x = set_opt  ctl_broadcast x;

                fun get_oobinline x = the_else ctl_oobinline x;
                fun set_oobinline x = set_opt ctl_oobinline x;

                fun get_sndbuf x = the_else ctl_sndbuf x;


                # NOTE: Should probably do some
                # range checking on the argument:       XXX BUGGO FIXME 

                fun set_sndbuf x = set_opt ctl_sndbuf x;
                fun get_rcvbuf x = the_else ctl_rcvbuf x;

                # NOTE: Should probably do some
                # range checking on the argument:       XXX BUGGO FIXME 

                fun set_rcvbuf x
                    =
                    set_opt ctl_rcvbuf x;

                stipulate

                    my get_type'  : Socket_Fd -> ci::System_Constant
                        =
                        socket_fn "getTYPE";                                                    # getTYPE                       def in    src/c/lib/socket/getTYPE.c

                    my get_error' : Socket_Fd -> Bool
                        =
                        socket_fn "getERROR";                                                   # getERROR                      def in    src/c/lib/socket/getERROR.c
                herein

                    fun get_type  (SOCKET { file_descriptor, ... } )
                        =
                        ps::socket::SOCKET_TYPE (get_type' file_descriptor);

                    fun get_error (SOCKET { file_descriptor, ... } )
                        =
                        get_error' file_descriptor;
                end;

                stipulate

                    my get_peer_name' : Socket_Fd -> Internet_Address
                        =
                        socket_fn "getPeerName";                                                                                        # getPeerName                   def in    src/c/lib/socket/getpeername.c

                    my get_sock_name' : Socket_Fd -> Internet_Address
                        =
                        socket_fn "getSockName";                                                                                        # getSockName                   def in    src/c/lib/socket/getsockname.c

                    fun get_name f (SOCKET { file_descriptor, ... } )
                        =
                        ADDRESS (f file_descriptor);

                herein

                    fun get_peer_name  socket =  get_name  get_peer_name'  socket;
                    fun get_sock_name  socket =  get_name  get_sock_name'  socket;

                end;

                stipulate

                    my get_nread'  : Socket_Fd -> Int
                        =
                        socket_fn "getNREAD";                                                                                           # getNREAD                      def in    src/c/lib/socket/getNREAD.c

                    my get_atmark' : Socket_Fd -> Bool
                        =
                        socket_fn "getATMARK";                                                                                          # getATMARK                     def in    src/c/lib/socket/getATMARK.c

                herein

                    fun get_nread  (SOCKET { file_descriptor, ... } ) = get_nread'  file_descriptor;
                    fun get_atmark (SOCKET { file_descriptor, ... } ) = get_atmark' file_descriptor;

                end;

            end;                        # stipulate
        };                              # package control 


        my set_nbio': (Socket_Fd, Bool) -> Void         # "nbio" == "non-blocking I/O"
            =
            socket_fn "setNBIO";                                                                # setNBIO       def in    src/c/lib/socket/setNBIO.c

#       fun setNBIO (SOCKET fd, flag) = setNBIO'(fd, flag)


        # Extract a blocking file descriptor;           # "nbr" == "nonblocking ref"
        # implicitly set socket to                      # "nb"  == "nonblocking"
        # blocking mode if necessary:                   # "fd"  == "file descriptor"
        #
        fun to_blocking_fd (SOCKET { file_descriptor, nonblocking => nbr as REF nonblocking } )
            =
            if nonblocking
                #
                set_nbio' (file_descriptor, FALSE);
                nbr := FALSE;
                file_descriptor;
            else
                file_descriptor;
            fi;

        # Same for non-blocking:
        #
        fun to_nonblocking_fd (SOCKET { file_descriptor, nonblocking => nbr as REF nonblocking } )
            =
            {   if (not nonblocking)
                    #   
                    set_nbio' (file_descriptor, TRUE);
                    nbr := TRUE;
                fi;

                file_descriptor;
            };

                                                        # nonblocking_socket_junk               is from   src/lib/std/src/socket/nonblocking-socket-junk.pkg

        # These two fns wrap an "f(x)" evaluation,      # "nb" is "nonblocking":
        # while trapping some exceptions:
        #
        wrap_nb_o =  nonblocking_socket_junk::wrap_nb_o;                # Traps EWOULDBLOCK/EINPROGRESS/EAGAIN and returns NULL.
        wrap_nb_b =  nonblocking_socket_junk::wrap_nb_b;                # Traps EWOULDBLOCK/EINPROGRESS/EAGAIN and returns FALSE.

        fun sock_b  file_descriptor =  SOCKET { file_descriptor, nonblocking => REF FALSE };
        fun sock_nb file_descriptor =  SOCKET { file_descriptor, nonblocking => REF TRUE };

        # Socket address operations:
        #
        fun same_address (ADDRESS a1, ADDRESS a2)
            =
            (a1 == a2);

        stipulate
            my  get_address_family:  Internet_Address -> Raw_Address_Family
                =
                socket_fn "getAddrFamily";                                                      # getAddrFamily def in    src/c/lib/socket/getaddrfamily.c
        herein
            fun family_of_address (ADDRESS a)
                =
                af::ADDRESS_FAMILY (get_address_family a);
        end;

        # Socket management:
        #
        stipulate
            my accept'  : Int -> (Int, Internet_Address)        = socket_fn  "accept";          # accept        def in    src/c/lib/socket/accept.c
            my bind'    : (Int, Internet_Address) -> Void       = socket_fn  "bind";            # bind          def in    src/c/lib/socket/bind.c
            my connect' : (Int, Internet_Address) -> Void       = socket_fn  "connect";         # connect       def in    src/c/lib/socket/connect.c
            my listen'  : (Int, Int) -> Void                    = socket_fn  "listen";          # listen        def in    src/c/lib/socket/listen.c
            my close'   : Int -> Void                           = socket_fn  "close";           # close         def in    src/c/lib/socket/close.c
        herein

            fun bind (SOCKET { file_descriptor, ... }, ADDRESS address)
                =
                bind' (file_descriptor, address);


            fun listen (SOCKET { file_descriptor, ... }, back_log)
                =
                listen' (file_descriptor, back_log);            # Should do some range checking on back_log  XXX BUGGO FIXME


            stipulate
                fun accept0 (socket, coerce_blocking_status) s
                    =
                    {   my (new_fd, address)
                            =
                            accept' (coerce_blocking_status s);

                        ( socket new_fd,
                          ADDRESS address
                        );
                    };
            herein

                fun accept s
                    =
                    accept0 (sock_b, to_blocking_fd) s;


                fun accept_nonblocking s
                    =
                    wrap_nb_o (accept0 (sock_nb, to_nonblocking_fd)) s;
            end;


            stipulate
                fun connect0  coerce_blocking_status  (s, ADDRESS address)
                    =
                    connect' (coerce_blocking_status s, address);
            herein

                fun connect arg
                    =
                    connect0  to_blocking_fd  arg;


                fun connect_nonblocking arg
                    =
                    wrap_nb_b (connect0 to_nonblocking_fd) arg;
            end;


            fun close (SOCKET { file_descriptor, ... } )
                =
                close' file_descriptor;
        end;                                                    # stipulate


        stipulate
            my  shutdown' : (Int, Int) -> Void
                =
                socket_fn "shutdown";                                                           # shutdown      def in    src/c/lib/socket/shutdown.c

            fun how NO_RECVS          => 0;
                how NO_SENDS          => 1;
                how NO_RECVS_OR_SENDS => 2;
            end;
        herein

            fun shutdown (SOCKET { file_descriptor, ... }, mode)
                =
                shutdown' (file_descriptor, how mode);
        end;


                                                                                    # nonblocking_socket_junk           is from   src/lib/std/src/socket/nonblocking-socket-junk.pkg

        fun io_descriptor (SOCKET { file_descriptor, ... } )
            =
            nonblocking_socket_junk::make_io_descriptor  file_descriptor;


        fun make_wait_request    { socket, readable, writable, oobdable }
            =
            { io_descriptor => io_descriptor socket, readable, writable, oobdable };



        # For now we implement 'wait_for_io_opportunity' in terms of 'poll':
        #
        # The C side of 'poll' is in
        #     src/c/lib/posix-os/poll.c
        # The Mythryl side is in
        #     src/lib/std/src/winix/winix-io.api
        #     src/lib/std/src/posix/winix-io.pkg
        #
        # For an alternate convenience wrapper see: 
        #     src/lib/src/when.api
        #     src/lib/src/when.pkg
        #
        socket_descriptor
            =
            io_descriptor;


        fun same_descriptor (d1, d2)
            =
            wg::io::compare (d1, d2) == EQUAL;


        fun wait_for_io_opportunity { readable, writable, oobdable, timeout }
            =
            split3 (reverse result_list, [], [], [])
            where 

                fun is_readable d
                    =
                    { io_descriptor => d,
                      readable      => TRUE,
                      writable      => FALSE,
                      oobdable      => FALSE
                    };


                fun is_writable d
                    =
                    { io_descriptor => d,
                      readable      => FALSE,
                      writable      => TRUE,
                      oobdable      => FALSE
                    };

                fun is_oobdable d
                    =
                    { io_descriptor => d,
                      readable      => FALSE,
                      writable      => TRUE,
                      oobdable      => FALSE
                    };

                wait_requests
                    =
                    map  is_readable  readable
                    @
                    map  is_writable  writable
                    @
                    map  is_oobdable  oobdable;


                result_list
                    =
                    wg::io::wait_for_io_opportunity  { wait_requests, timeout };


                fun split3 ([], readable, writable, oobdable)
                        =>
                        { readable, writable, oobdable };

                    split3  ((i: wg::io::Wait_Result) ! is,  readable,  writable,  oobdable)
                        =>
                        {   readable =   i.readable   ??   i.io_descriptor ! readable   ::   readable;
                            writable =   i.writable   ??   i.io_descriptor ! writable   ::   writable;
                            oobdable =   i.oobdable   ??   i.io_descriptor ! oobdable   ::   oobdable;

                            split3 (is, readable, writable, oobdable);
                        };
                end;
            end;

        select = wait_for_io_opportunity;
            #
            # Deprecated synonym, mainly so that unix folks
            # looking for 'select' in the function index
            # will be led here.


        vbuf = vector_slice_of_one_byte_unts::base;
        abuf = rw_vector_slice_of_one_byte_unts::base;

        # Default flags 
        #
        default_don't_route =  FALSE;
        default_oob         =  FALSE;
        default_peek        =  FALSE;

        # Socket output operations 
        #
        stipulate
            my send_v:  (Int, Wy8Vector, Int, Int, Bool, Bool) -> Int   = socket_fn "sendBuf";          # "sendBuf"     is in   src/c/lib/socket/sendbuf.c
            my send_a:  (Int, Wy8Array,  Int, Int, Bool, Bool) -> Int   = socket_fn "sendBuf";
        herein

            fun send_vec0  coerce_blocking_status  (s, buffer)
                =
                {   fd = coerce_blocking_status s;

                    my (vec, i, len)
                        =
                        vbuf buffer;

                    if (len > 0)
                        send_v
                          ( fd,
                            vec,
                            i,
                            len,
                            default_don't_route,
                            default_oob
                          );
                    else
                        0;
                    fi;
                };


            fun send_vector arg
                =
                send_vec0  to_blocking_fd  arg;


            fun send_vector_nonblocking arg
                =
                wrap_nb_o (send_vec0 to_nonblocking_fd) arg;

            fun send_vector'0  coerce_blocking_status  (socket, buffer, { don't_route, oob } )
                =
                {   fd = coerce_blocking_status socket;

                    my (vec, i, len)
                        =
                        vbuf buffer;

                    if (len > 0)   send_v (fd, vec, i, len, don't_route, oob);
                    else           0;
                    fi;
                };

            fun send_vector' arg
                =
                send_vector'0  to_blocking_fd  arg;

            fun send_vector_nonblocking' arg
                =
                wrap_nb_o (send_vector'0 to_nonblocking_fd) arg;

            fun send_arr0  coerce_blocking_status  (socket, buffer)
                =
                {   fd = coerce_blocking_status socket;

                    my (arr, i, len) =  abuf buffer;

                    if (len > 0)  send_a (fd, arr, i, len, default_don't_route, default_oob);
                    else          0;
                    fi;
                };

            fun send_rw_vector arg
                =
                send_arr0  to_blocking_fd  arg;

            fun send_rw_vector_nonblocking arg
                =
                wrap_nb_o (send_arr0 to_nonblocking_fd) arg;

            fun send_rw_vector'0  coerce_blocking_status  (socket, buffer, { don't_route, oob } )
                =
                {   fd =  coerce_blocking_status  socket;

                    my (arr, i, len)
                        =
                        abuf buffer;

                    if (len > 0)  send_a (fd, arr, i, len, don't_route, oob);
                    else          0;
                    fi;
                };

            fun send_rw_vector' arg
                =
                send_rw_vector'0  to_blocking_fd  arg;

            fun send_rw_vector_nonblocking' arg
                =
                wrap_nb_o (send_rw_vector'0 to_nonblocking_fd) arg;

        end;                                    # stipulate

        stipulate
            my send_to_v:  (Int, Wy8Vector, Int, Int, Bool, Bool, Internet_Address) -> Int   = socket_fn "sendBufTo";           # sendBufTo     is in   src/c/lib/socket/sendbufto.c
            my send_to_a:  (Int, Wy8Array,  Int, Int, Bool, Bool, Internet_Address) -> Int   = socket_fn "sendBufTo";
        herein

            fun send_vec_to0  coerce_blocking_status  (socket, ADDRESS address, buffer)
                =
                {   fd =  coerce_blocking_status  socket;

                    my (vec, i, len)
                        =
                        vbuf buffer;

                    if (len > 0)   send_to_v (fd, vec, i, len, default_don't_route, default_oob, address);
                    else           0;
                    fi;

                    ();
                };


            fun send_vector_to arg
                =
                send_vec_to0  to_blocking_fd  arg;


            fun send_vector_to_nonblocking arg
                =
                wrap_nb_b (send_vec_to0 to_nonblocking_fd) arg;


            fun send_vector_to'0  coerce_blocking_status  (socket, ADDRESS address, buffer, { don't_route, oob } )
                =
                {   fd =  coerce_blocking_status  socket;

                    my (vec, i, len)
                        =
                        vbuf buffer;

                    if (len > 0)   send_to_v (fd, vec, i, len, don't_route, oob, address);
                    else           0;
                    fi;

                    ();
                };


            fun send_vector_to' arg
                =
                send_vector_to'0  to_blocking_fd  arg;


            fun send_vector_to_nonblocking' arg
                =
                wrap_nb_b (send_vector_to'0 to_nonblocking_fd) arg;


            fun send_arr_to0  coerce_blocking_status  (socket, ADDRESS address, buffer)
                =
                {   fd =  coerce_blocking_status  socket;

                    my (arr, i, len)
                        =
                        abuf buffer;

                    if (len > 0)   send_to_a (fd, arr, i, len, default_don't_route, default_oob, address);
                    else           0;
                    fi;

                    ();
                };

            fun send_rw_vector_to arg
                =
                send_arr_to0  to_blocking_fd  arg;


            fun send_rw_vector_to_nonblocking arg
                =
                wrap_nb_b (send_arr_to0 to_nonblocking_fd) arg;


            fun send_rw_vector_to'0  coerce_blocking_status  (socket, ADDRESS address, buffer, { don't_route, oob } )
                =
                {   fd =  coerce_blocking_status  socket;

                    my (arr, i, len)
                        =
                        abuf buffer;

                    if (len > 0)   send_to_a (fd, arr, i, len, don't_route, oob, address);
                    else           0;
                    fi;

                    ();
                };


            fun send_rw_vector_to' arg
                =
                send_rw_vector_to'0  to_blocking_fd  arg;


            fun send_rw_vector_to_nonblocking' arg
                =
                wrap_nb_b (send_rw_vector_to'0 to_nonblocking_fd) arg;

        end;                                            # stipulate


        # Socket input operations 
        #
        stipulate

            my  recv_v' : (Int, Int, Bool, Bool) -> Wy8Vector
                =
                socket_fn "recv";                                                       # recv          def in    src/c/lib/socket/recv.c

            fun recv_v _ (_, 0, _, _)
                    =>
                    w8v::from_list [];

                recv_v  coerce_blocking_status  (socket, nbytes, peek, oob)
                    =>
                    if (nbytes < 0)  raise exception SIZE;
                    else             recv_v' (coerce_blocking_status socket, nbytes, peek, oob);
                    fi;
            end;

            my recv_a:  (Int, Wy8Array, Int, Int, Bool, Bool) -> Int
                =
                socket_fn "recvBuf";                                                    # recvBuf       def in    src/c/lib/socket/recvbuf.c

        herein

            stipulate   
                fun recv_vec0  coerce_blocking_status  (socket, size)
                    =
                    recv_v  coerce_blocking_status  (socket, size, default_peek, default_oob);
            herein

                # Set socket to blocking if not already blocking
                # and read given number of bytes from given socket.
                #
                # Return resulting bytevector.
                # 
                fun receive_vector  arg
                    =
                    recv_vec0  to_blocking_fd  arg;


                # Set socket to nonblocking if not already nonblocking
                # and read given number of bytes from given socket.
                #
                # Return                               THE result_bytevector.
                # If no input was available return     NULL.
                # 
                fun receive_vector_nonblocking  arg
                    =
                    wrap_nb_o  (recv_vec0 to_nonblocking_fd)  arg;
            end;


            stipulate
                fun receive_vector'0  coerce_blocking_status  (socket, size, { peek, oob } )
                    =
                    recv_v  coerce_blocking_status  (socket, size, peek, oob);
            herein

                # Same as receive_vector above,
                # but with explicit PEEK and OOB flags:
                #
                fun receive_vector'  arg
                    =
                    receive_vector'0  to_blocking_fd  arg;


                # Same as receive_vector_nonblokcing above,
                # but with explicit PEEK and OOB flags:
                #
                fun receive_vector_nonblocking' arg
                    =
                    wrap_nb_o (receive_vector'0 to_nonblocking_fd)  arg;
            end;


            stipulate
                fun recv_arr0  coerce_blocking_status  (socket, buffer)
                    =
                    {   fd =  coerce_blocking_status  socket;

                        my (buf, i, size)
                            =
                            abuf buffer;

                        if (size > 0)   recv_a (fd, buf, i, size, default_peek, default_oob);
                        else            0;
                        fi;
                    };
            herein

                fun receive_rw_vector    arg
                    =
                    recv_arr0  to_blocking_fd  arg;


                fun receive_rw_vector_nonblocking arg
                    =
                    wrap_nb_o (recv_arr0 to_nonblocking_fd) arg;
            end;


            stipulate
                fun receive_rw_vector'0  coerce_blocking_status  (socket, buffer, { peek, oob } )
                    =
                    {   fd =  coerce_blocking_status  socket;

                        my (buf, i, size)
                            =
                            abuf buffer;

                        if (size > 0)   recv_a (fd, buf, i, size, peek, oob);
                        else            0;
                        fi;
                    };
            herein
                fun receive_rw_vector' arg
                    =
                    receive_rw_vector'0  to_blocking_fd  arg;


                fun receive_rw_vector_nonblocking' arg
                    =
                    wrap_nb_o (receive_rw_vector'0 to_nonblocking_fd) arg;
            end;

        end;                                    # stipulate


        stipulate

            my recv_from_v' : (Int, Int, Bool, Bool) -> (Wy8Vector, Internet_Address)
                =
                socket_fn "recvFrom";                                                           # recvFrom      def in    src/c/lib/socket/recvfrom.c


            fun recv_from_v _ (_, 0, _, _)
                    =>
                    (w8v::from_list [], (ADDRESS (w8v::from_list [])));

                recv_from_v  coerce_blocking_status  (socket, size, peek, oob)
                    =>
                    if (size < 0)
                        raise exception SIZE;
                    else
                        fd =  coerce_blocking_status  socket;

                        my (data, address)
                            =
                            recv_from_v' (fd, size, peek, oob);

                        (data, ADDRESS address);
                    fi;
            end;


            my recv_from_a:   ((Int, Wy8Array, Int, Int, Bool, Bool)) -> ((Int, Internet_Address))
                =
                socket_fn "recvBufFrom";                                                                # "recvBufFrom"         def in    src/c/lib/socket/recvbuffrom.c

        herein

            stipulate
                fun recv_vec_from0  coerce_blocking_status  (socket, size)
                    =
                    recv_from_v  coerce_blocking_status  (socket, size, default_peek, default_oob);
            herein

                fun receive_vector_from arg
                    =
                    recv_vec_from0  to_blocking_fd  arg;


                fun receive_vector_from_nonblocking arg
                    =
                    wrap_nb_o (recv_vec_from0 to_nonblocking_fd) arg;

            end;

            stipulate
                fun receive_vector_from'0  coerce_blocking_status  (socket, size, { peek, oob } )
                    =
                    recv_from_v  coerce_blocking_status  (socket, size, peek, oob);
            herein

                fun receive_vector_from' arg
                    =
                    receive_vector_from'0  to_blocking_fd  arg;


                fun receive_vector_from_nonblocking' arg
                    =
                    wrap_nb_o (receive_vector_from'0 to_nonblocking_fd) arg;
            end;


            stipulate
                fun recv_arr_from0  coerce_blocking_status  (socket, asl)
                    =
                    {   fd =  coerce_blocking_status  socket;

                        my (buf, i, size)
                            =
                            abuf asl;

                        if (size > 0)

                            my (n, address)
                                =
                                recv_from_a (fd, buf, i, size, default_peek, default_oob);

                            (n, ADDRESS address);
                        else
                            (0, ADDRESS (w8v::from_list [] ));
                        fi;
                    };
            herein

                fun receive_rw_vector_from arg
                    =
                    recv_arr_from0  to_blocking_fd  arg;


                fun receive_rw_vector_from_nonblocking arg
                    =
                    wrap_nb_o (recv_arr_from0 to_nonblocking_fd) arg;
            end;

            stipulate
                fun receive_rw_vector_from'0  coerce_blocking_status  (socket, asl, { peek, oob } )
                    =
                    {   fd =  coerce_blocking_status  socket;

                        my (buf, i, size)
                            =
                            abuf asl;

                        if (size > 0)

                            my (n, address)
                                =
                                recv_from_a (fd, buf, i, size, peek, oob);

                            (n, ADDRESS address);
                        else
                            (0, (ADDRESS (w8v::from_list [])));
                        fi;
                    };
            herein

                fun receive_rw_vector_from'    arg
                    =
                    receive_rw_vector_from'0  to_blocking_fd  arg;


                fun receive_rw_vector_from_nonblocking' arg
                    =
                    wrap_nb_o (receive_rw_vector_from'0 to_nonblocking_fd) arg;
            end;        

        end;                    # stipulate
    };                          # package socket 
end;                            # stipulate


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext