Back to libut API Reference


SYNOPSIS

    #include "libut/ut.h"
    int UT_net_request( char *name, UT_net_request_cb *cb, void *data, UT_iob *io[2], int flags, ...);


DESCRIPTION

This is a generic network request/response function.

It is a higher-level function than UT_net_connect(3) in that it performs the connect, sends the request, optionally gathers the response, and closes the socket. Finally it invokes the callback. (It is not an HTTP request, but could be used to implement one. The outgoing request is an arbitrary buffer).

The name argument is a descriptive name for the request (which will be copied, and silently truncated if too long). This name is only used in the output of the fds control port command and in log messages.

The cb argument specifies the callback to be invoked after the request succeeds or fails. See the CALLBACK section below.

The data argument is an opaque pointer that is passed back to the callback.

The io argument points to an array of two UT_iob pointers; the first points to the UT_iob containing the outgoing request, and the second (if non-NULL) points to the UT_iob where the gathered response will be stored. (If however the second pointer is NULL, the function will not await a response and will simply close the socket after sending the outgoing request).

There is no limit on the size of the response from the remote side (see NOTES). The response is accumulated until the remote side closes the connection.

The flags argument is a bitwise-OR of these pre-defined constants:

UT_CONNECT_FROM_IPPORT
If this flag is specified, the following argument is an IP:port string (e.g., ``127.0.0.1:4444'') specifying the source IP address and port number to use. The port number can be 0, in which case the choice is left to the kernel. This flag may be omitted in which case the source IP address and port are automatically chosen by the kernel.

UT_CONNECT_TO_IPPORT
This flag is mandatory. The last argument to the function is an IP:port string (e.g., ``127.0.0.1:5555'') specifying the destination IP address and port number to which the connection should be made.


THE CALLBACK

The callback must have this prototype:

    int (UT_net_request_cb)(char *name, void *data, int status, 
                            UT_iob *io[2]);

The name and data arguments are passed to the callback exactly as they were passed to UT_net_request(). The status argument informs the callback whether the request succeeded or failed, by setting one of these bit flags (other bits may be set and must be ignored):

UTFD_IS_REQSUCCESS
The request has completed successfully.

UTFD_IS_REQFAILURE
The request failed. The reason is indicated in the log.

The io argument is the same pointer to an array of two UT_iob pointers that was passed to UT_net_request(3). The callback must dispose of these using UT_iob_free(3) on both pointers when they're no longer needed. (That is, excepting io[1] if it was specified as NULL). Disposal is required regardless of whether the request succeeded or failed.

The callback's return value is ignored.


RETURN VALUE

If an error occurs, -1 is returned and the reason is logged. A non-negative return value indicates that a connection attempt has been initiated; it may or may not succeed. The callback will be invoked after the request has either completed successfully or failed.


RELATED CONTROL PORT COMMANDS

The fds control port command displays connecting sockets, and other file descriptors.


NOTES

No maximum length is imposed on the response from the remote side, therefore this function should only be used if the remote side is trusted not to send so large a response as to exhaust memory. Eventually this function may support an additional flag and argument to specify a maximum byte size for the response.


EXAMPLE

First, define the callback that will be invoked after the request.

    int rqst_cb(char *name, void *data, int status, UT_iob*io[2]) {
        char *response;
    
        if (status & UTFD_IS_REQSUCCESS) {
    
            /* log response. (note, log truncates long lines). */
    
            response = UT_iob_flatten( io[1], NULL);
            UT_LOG(Info, "received: %s", response);
            free( response );
    
        } else UT_LOG(Info, "failure!");  /* UTFD_IS_REQFAILURE */
    
        UT_iob_free(io[0]);     
        UT_iob_free(io[1]);
    }

The following code makes the request. It could reside in a timer callback, for example.

    UT_iob *io[2];
    int rc;
    
    io[0] = UT_iob_create();
    io[1] = UT_iob_create();
    
    UT_iob_printf( io[0], "this is the outgoing request\r\n");
    rc = UT_net_request( "demo", rqst_cb, NULL, io, UT_CONNECT_TO_IPPORT,
                    "127.0.0.1:2000");
    if (rc < 0) UT_LOG(Error, "request failed");


SEE ALSO

UT_net_connect(3), UT_net_resolve(3), UT_net_listen(3), UT_iob_create(3), UT_iob_printf(3), UT_iob_flatten(3), UT_iob_append(3)


AUTHOR

Troy D. Hanson <thanson@users.sourceforge.net>