#ifndef _CHANNELS_H_16c66b7e_ #define _CHANNELS_H_16c66b7e_ /* This file is in the public domain. */ #include typedef struct chanops CHANOPS; typedef struct nonchanops NONCHANOPS; typedef struct chanopen_ret CHANOPEN_RET; #include "bpp.h" #include "str.h" /* * Operations on a channel. * * These have a void * "arg". This is an arbitrary callback argument, * passed in when the channel is created, to keep the channel client * from having to constantly look things up by channel number. It is * omitted from the individual descriptions of the callbacks. */ struct chanops { /* * Called if the open succeeds. Arglist: * (void *arg, int channel_number, ROSTR rest) * The rest argument is the additional data from the * OPEN_CONFIRMATION packet. This callback may call other channel * functions on the channel. The channel's send window has already * been set to the value from the packet; no (*morewin)() call will * be made for this first window. If the send window value is * needed, it can be obtained with chan_get_wwin. * * This may be a nil pointer in CHANOPS structs used only for * channels opened by the remote side. */ void (*opensucc)(void *, int, ROSTR); /* * Called if the open fails. Arglist: * (void *arg, int channel_number, unsigned int rcode, ROSTR reason, ROSTR lang) * The channel is not functional and has already been destroyed; the * channel number argument is no longer a valid channel number. * rcode, reason, and lang are the values from the failure packet. * The strings must not be assumed valid after the callback returns. * * This may be a nil pointer in CHANOPS structs used only for * channels opened by the remote side. */ void (*openfail)(void *, int, unsigned int, ROSTR, ROSTR); /* * Called to handle received data. Arglist: * (void *arg, int chan, int ext, unsigned int code, const void *buf, int len) * chan is the channel number. For normal data, ext is zero and * code is meaningless; for extended data, ext is nonzero and code * is the data type code. buf and len describe the data itself. * * len will never be zero in normal operation. When EOF is received, * this is called once with all but the first argument 0. */ void (*gotdata)(void *, int, int, unsigned int, const void *, int); /* * Called when a window adjustment is received. Arglist: * (void *arg, int chan, unsigned int addl, unsigned int newwin) * chan is the channel number. addl is the number of bytes of * window added; newwin is the new send window. On a successful * open this is not called for the initial send window. Note that * addl may occasionally be zero (and the window unchanged). * * This may be a nil pointer, in which case no call is made. */ void (*morewin)(void *, int, unsigned int, unsigned int); /* * Called when a CHANNEL_REQUEST is received. Arglist: * (void *arg, int chan, ROSTR req, int wantreply, const void *rest, int restlen) * chan is the channel number. req is a ROSTR giving the request * string. wantreply is nonzero if a reply is requested, or zero if * no specific reply is requested. rest and restlen describe the * request-specific portion of the packet, suitable for passing to * parse_data(). * * The storage areas pointed to by the second and fourth arguments * are owned by the caller and must not be modified; they must be * considered to go invalid once the function returns - they must be * copied if they are to be saved. * * Return value is one of the CHANREQRET_* values. * * This may be a nil pointer, in which case it is as if it were a * function which ignores its arguments and returns CHANREQRET_UNK. */ int (*chanreq)(void *, int, ROSTR, int, const void *, int); /* Request completely processed, including sending any reply. */ #define CHANREQRET_DONE 1 /* Request successful, no reply yet sent. */ #define CHANREQRET_OK 2 /* Request failed, no reply yet sent. */ #define CHANREQRET_FAIL 3 /* Request not recognized. */ #define CHANREQRET_UNK 4 /* * Called when a CHANNEL_CLOSE is received. Arglist: * (void *arg, int chan, int final) * chan is the channel number. If chan_close() has already been * called on the channel, final will be nonzero, and the channel has * finally been destroyed; if not, final will be zero, and the * channel remains active for output until chan_close() is called on * it (which may be done from within this routine). */ void (*closed)(void *, int, int); } ; /* * Operations that are not channel-specific. */ struct nonchanops { /* * Called when a CHANNEL_OPEN packet is received. Arglist: * (ROSTR type, int chan, const void *rest, int restlen) * type is the type string from the request; rest and restlen are * the type-specific data blob, suitable for passing to parse_data. * chan is the local channel number which has been assigned for this * channel. * * This call returns nothing itself. To complete the open * transaction, a call to chan_open_ok or chan_open_fail must be * made (which may be done from within this routine). */ void (*chanopen)(ROSTR, int, const void *, int); /* * Called when a GLOBAL_REQUEST packet is received. Arglist: * (ROSTR name, int wantrepl, const void *rest, int restlen) * where name is the request name, wantrepl is the want-reply * boolean, and rest and restlen are the request-specific part of * the packet, suitable for passing to parse_data. * * The return value is one of the GLOBALREQ_* values. */ int (*globalreq)(ROSTR, int, const void *, int); /* Completely processed, including sending any reply called for. */ #define GLOBALREQ_DONE 1 /* Request OK, no reply sent; if want-reply is true, send an empty success. */ #define GLOBALREQ_OK 2 /* Request failed, no reply sent. */ #define GLOBALREQ_FAIL 3 /* Request unrecognized. */ #define GLOBALREQ_UNK 4 } ; #define CHAN_NO_CHANNEL (-1) /* * Open a channel to the peer. * * First call chan_open_hdr, which constructs the invariant part of the * channel-open message and returns a pointer to just after the * header. After appending the rest of the message, call * chan_open_send, which returns the new channel's number. */ extern void *chan_open_hdr(ROSTR); extern int chan_open_send(void *, const CHANOPS *, void *); /* * Full-detail all-in-one channel open, for use by connection sharing. * * Arguments: * ROSTR type channel type * int maxpkt max packet size * unsigned int rwin initial receive window * const void *data additional packet data blob * int datalen length of additional packet data * const CHANOPS *ops channel operations vector * void *arg argument to ops callbacks * * Return value is the new channel's number. */ extern int chan_open_detail(ROSTR, int, unsigned int, const void *, int, const CHANOPS *, void *); /* Complete a remote channel-open request successfully. Arguments: channel number, type-specific body data, and the ops vector and callback arg for the new channel. */ extern void chan_open_ok(int, ROSTR, const CHANOPS *, void *); /* Full-detail version of chan_open_ok, for connection sharing. Just like chan_open_ok except the initial window size and max packet size are inserted just after the channel number. */ extern void chan_open_ok_detail(int, unsigned int, unsigned int, ROSTR, const CHANOPS *, void *); /* Complete a remote channel-open request unsuccessfully. Arguments: channel number, result code, additional text string, and language tag string. */ extern void chan_open_fail(int, unsigned int, ROSTR, ROSTR); /* Change the CHANOPS pointer and/or callback argument for an existing, established channel. */ extern void chan_set_ops(int, const CHANOPS *, void *); /* * Calls to manipulate an established channel. It is an error to call * these before the channel's open has succeeded. */ /* Query window space. Returns the number of bytes receivable before window enlargement. Argument: channel number. */ extern unsigned int chan_get_rwin(int); /* Query maximum send packet size. Returns the maximum packet size declared by the peer at channel open. Argument: channel number. */ extern unsigned int chan_get_maxpkt(int); /* Add window space. Channels start with zero window advertised. Arguments: (int chan_no, unsigned int additional_space) It is an error to call this such as to increase the abstract window-available value above 0xffffffff. It is also an error to call this after receiving EOF. */ extern void chan_add_rwin(int, unsigned int); /* Query window space. Returns the number of bytes sendable before window enlargement. Argument: channel number. It is not an error to call this after sending EOF, but it always returns zero then. */ extern unsigned int chan_get_wwin(int); /* Construct the beginning of a CHANNEL_REQUEST message. Returns a pointer to just after the request-independent part of the message. The ROSTR is the request type. The want-reply boolean is not specified here, but rather by the choice of send routine. */ extern unsigned char *chan_req_hdr(int, ROSTR); /* Send a CHANNEL_REQUEST message, with reply expected. First arg is channel number. Second arg points at end of message. Third arg is a callback, called when the request succeeds (with arg CREQ_OK) or fails (with arg CREQ_FAIL), or, if the channel is destroyed before either happens, with arg CREQ_CLOSE. The fourth arg to chan_send_req_reply is the second arg to the callback. */ extern void chan_send_req_reply(int, unsigned char *, void (*)(int, void *), void *); #define CREQ_OK 1 #define CREQ_FAIL 2 #define CREQ_CLOSE 3 /* Send a CHANNEL_REQUEST message, with no reply expected. First arg is channel number. Second arg points at end of message. */ extern void chan_send_req_blind(int, unsigned char *); /* Send data on a channel. Args are as for the data callback argument to chan_open(), above, except that the void * callback argument is absent. It is an error to try to send more data than the peer has window space for (see chan_get_wwin(), above). Sending zero bytes is not an error and does not send anything (in particular, does not send EOF). It is an error to call this after sending EOF. */ extern void chan_send_data(int, int, unsigned int, const void *, int); /* Declare EOF for sending on a channel. Arg is channel number. */ extern void chan_send_eof(int); /* Send a CHANNEL_SUCCESS (second arg nonzero) or CHANNEL_FAILURE (zero) on a channel. (First arg is channel number.) */ extern void chan_reqrep(int, int); /* Send a close on a channel. If a close has been received on the channel (indicated by a call through the closed member of the ops vector), this does final channel teardown and returns nonzero; otherwise, this initiates the process, the channel remains valid until the peer's close arrives (at which point teardown occurs), and this call returns zero. (Either way, no further output calls on the channel may be done.) */ extern int chan_close(int); /* * Calls not related to specific channels. */ /* Return the LAYER pointer for the channels layer. */ extern LAYER *chan_layer(void); /* Set the non-channel-specific ops vector. */ extern void set_globalops(const NONCHANOPS *); /* Construct the beginning of a GLOBAL_REQUEST message. Returns a pointer to just after the header. First arg is the request name. want-reply is always true, to ensure we can tell which reply goes with which request. */ extern unsigned char *global_req_hdr(ROSTR); /* Send a GLOBAL_REQUEST message. First arg points at end of message. Second arg is a callback, called when the request succeeds (with first arg GREQ_OK) or fails (GREQ_FAIL) and second arg equal to the third arg to global_send_req(). In the GREQ_OK case, the request-specific data from the reply are passed in the third and fourth callback args; in the GREQ_FAIL case, those arguments are meaningless. The fourth callback arg is the third arg to global_send_req(). In the GREQ_OK case, the memory pointed to by the third argument may not be valid after the callback returns. */ extern void global_send_req(unsigned char *, void (*)(int, void *, const void *, int), void *); #define GREQ_OK 1 #define GREQ_FAIL 2 /* Start to send a reply to a GLOBAL_REQUEST message. Calling paradigm is similar to global_req_hdr/global_send_req; differences: - global_rep_hdr takes just an argument GREQ_OK or GREQ_FAIL, not a ROSTR; and if it's GREQ_FAIL, the reply is sent then. - global_send_rep doesn't take the callback function and argument (and is to be called only when GREQ_OK is passed to global_rep_hdr). */ extern unsigned char *global_rep_hdr(int); extern void global_send_rep(unsigned char *); /* * Print a short text form of the rcode from an open failure. */ extern void print_openfail_rcode(FILE *, unsigned int); extern LAYERDESC layer_channels; #endif