1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

Replace method-dispatch #defines with inline functions.

This replaces all the macros like ssh_key_sign() and win_draw_text()
which take an object containing a vtable pointer and do the
dereferencing to find the actual concrete method to call. Now they're
all inline functions, which means more sensible type-checking and more
comprehensible error reports when the types go wrong, and also means
that there's no risk of double-evaluating the object argument.
This commit is contained in:
Simon Tatham 2019-02-27 19:44:15 +00:00
parent 07ebd88c3a
commit 1b4a08a953
7 changed files with 556 additions and 365 deletions

View File

@ -148,23 +148,31 @@ Socket *sk_new(SockAddr *addr, int port, bool privport, bool oobinline,
Socket *sk_newlistener(const char *srcaddr, int port, Plug *plug,
bool local_host_only, int address_family);
#define sk_plug(s,p) (((s)->vt->plug) (s, p))
#define sk_close(s) (((s)->vt->close) (s))
#define sk_write(s,buf,len) (((s)->vt->write) (s, buf, len))
#define sk_write_oob(s,buf,len) (((s)->vt->write_oob) (s, buf, len))
#define sk_write_eof(s) (((s)->vt->write_eof) (s))
#define sk_flush(s) (((s)->vt->flush) (s))
static inline Plug *sk_plug(Socket *s, Plug *p)
{ return s->vt->plug(s, p); }
static inline void sk_close(Socket *s)
{ s->vt->close(s); }
static inline size_t sk_write(Socket *s, const void *data, size_t len)
{ return s->vt->write(s, data, len); }
static inline size_t sk_write_oob(Socket *s, const void *data, size_t len)
{ return s->vt->write_oob(s, data, len); }
static inline void sk_write_eof(Socket *s)
{ s->vt->write_eof(s); }
static inline void sk_flush(Socket *s)
{ s->vt->flush(s); }
#define plug_log(p,type,addr,port,msg,code) \
(((p)->vt->log) (p, type, addr, port, msg, code))
#define plug_closing(p,msg,code,callback) \
(((p)->vt->closing) (p, msg, code, callback))
#define plug_receive(p,urgent,buf,len) \
(((p)->vt->receive) (p, urgent, buf, len))
#define plug_sent(p,bufsize) \
(((p)->vt->sent) (p, bufsize))
#define plug_accepting(p, constructor, ctx) \
(((p)->vt->accepting)(p, constructor, ctx))
static inline void plug_log(
Plug *p, int type, SockAddr *addr, int port, const char *msg, int code)
{ return p->vt->log(p, type, addr, port, msg, code); }
static inline void plug_closing(
Plug *p, const char *msg, int code, bool calling_back)
{ return p->vt->closing(p, msg, code, calling_back); }
static inline void plug_receive(Plug *p, int urg, const char *data, size_t len)
{ return p->vt->receive(p, urg, data, len); }
static inline void plug_sent (Plug *p, size_t bufsize)
{ return p->vt->sent(p, bufsize); }
static inline int plug_accepting(Plug *p, accept_fn_t cons, accept_ctx_t ctx)
{ return p->vt->accepting(p, cons, ctx); }
/*
* Special error values are returned from sk_namelookup and sk_new
@ -172,7 +180,8 @@ Socket *sk_newlistener(const char *srcaddr, int port, Plug *plug,
* or return NULL if there's no problem.
*/
const char *sk_addr_error(SockAddr *addr);
#define sk_socket_error(s) (((s)->vt->socket_error) (s))
static inline const char *sk_socket_error(Socket *s)
{ return s->vt->socket_error(s); }
/*
* Set the `frozen' flag on a socket. A frozen socket is one in
@ -191,7 +200,8 @@ const char *sk_addr_error(SockAddr *addr);
* associated local socket in order to avoid unbounded buffer
* growth.
*/
#define sk_set_frozen(s, is_frozen) (((s)->vt->set_frozen) (s, is_frozen))
static inline void sk_set_frozen(Socket *s, bool is_frozen)
{ s->vt->set_frozen(s, is_frozen); }
/*
* Return a structure giving some information about the other end of
@ -199,7 +209,8 @@ const char *sk_addr_error(SockAddr *addr);
* not NULL, then it is dynamically allocated, and should be freed by
* a call to sk_free_peer_info(). See below for the definition.
*/
#define sk_peer_info(s) (((s)->vt->peer_info) (s))
static inline SocketPeerInfo *sk_peer_info(Socket *s)
{ return s->vt->peer_info(s); }
/*
* The structure returned from sk_peer_info, and a function to free

252
putty.h
View File

@ -530,23 +530,39 @@ struct BackendVtable {
int default_port;
};
#define backend_init(vt, seat, out, logctx, conf, host, port, rhost, nd, ka) \
((vt)->init(seat, out, logctx, conf, host, port, rhost, nd, ka))
#define backend_free(be) ((be)->vt->free(be))
#define backend_reconfig(be, conf) ((be)->vt->reconfig(be, conf))
#define backend_send(be, buf, len) ((be)->vt->send(be, buf, len))
#define backend_sendbuffer(be) ((be)->vt->sendbuffer(be))
#define backend_size(be, w, h) ((be)->vt->size(be, w, h))
#define backend_special(be, code, arg) ((be)->vt->special(be, code, arg))
#define backend_get_specials(be) ((be)->vt->get_specials(be))
#define backend_connected(be) ((be)->vt->connected(be))
#define backend_exitcode(be) ((be)->vt->exitcode(be))
#define backend_sendok(be) ((be)->vt->sendok(be))
#define backend_ldisc_option_state(be, opt) \
((be)->vt->ldisc_option_state(be, opt))
#define backend_provide_ldisc(be, ldisc) ((be)->vt->provide_ldisc(be, ldisc))
#define backend_unthrottle(be, bufsize) ((be)->vt->unthrottle(be, bufsize))
#define backend_cfg_info(be) ((be)->vt->cfg_info(be))
static inline const char *backend_init(
const BackendVtable *vt, Seat *seat, Backend **out, LogContext *logctx,
Conf *conf, const char *host, int port, char **rhost, bool nd, bool ka)
{ return vt->init(seat, out, logctx, conf, host, port, rhost, nd, ka); }
static inline void backend_free(Backend *be)
{ be->vt->free(be); }
static inline void backend_reconfig(Backend *be, Conf *conf)
{ be->vt->reconfig(be, conf); }
static inline size_t backend_send(Backend *be, const char *buf, size_t len)
{ return be->vt->send(be, buf, len); }
static inline size_t backend_sendbuffer(Backend *be)
{ return be->vt->sendbuffer(be); }
static inline void backend_size(Backend *be, int width, int height)
{ be->vt->size(be, width, height); }
static inline void backend_special(
Backend *be, SessionSpecialCode code, int arg)
{ be->vt->special(be, code, arg); }
static inline const SessionSpecial *backend_get_specials(Backend *be)
{ return be->vt->get_specials(be); }
static inline bool backend_connected(Backend *be)
{ return be->vt->connected(be); }
static inline int backend_exitcode(Backend *be)
{ return be->vt->exitcode(be); }
static inline bool backend_sendok(Backend *be)
{ return be->vt->sendok(be); }
static inline bool backend_ldisc_option_state(Backend *be, int state)
{ return be->vt->ldisc_option_state(be, state); }
static inline void backend_provide_ldisc(Backend *be, Ldisc *ldisc)
{ be->vt->provide_ldisc(be, ldisc); }
static inline void backend_unthrottle(Backend *be, size_t bufsize)
{ be->vt->unthrottle(be, bufsize); }
static inline int backend_cfg_info(Backend *be)
{ return be->vt->cfg_info(be); }
extern const struct BackendVtable *const backends[];
@ -915,36 +931,44 @@ struct SeatVtable {
bool (*get_window_pixel_size)(Seat *seat, int *width, int *height);
};
#define seat_output(seat, is_stderr, data, len) \
((seat)->vt->output(seat, is_stderr, data, len))
#define seat_eof(seat) \
((seat)->vt->eof(seat))
#define seat_get_userpass_input(seat, p, input) \
((seat)->vt->get_userpass_input(seat, p, input))
#define seat_notify_remote_exit(seat) \
((seat)->vt->notify_remote_exit(seat))
#define seat_update_specials_menu(seat) \
((seat)->vt->update_specials_menu(seat))
#define seat_get_ttymode(seat, mode) \
((seat)->vt->get_ttymode(seat, mode))
#define seat_set_busy_status(seat, status) \
((seat)->vt->set_busy_status(seat, status))
#define seat_verify_ssh_host_key(seat, h, p, typ, str, fp, cb, ctx) \
((seat)->vt->verify_ssh_host_key(seat, h, p, typ, str, fp, cb, ctx))
#define seat_confirm_weak_crypto_primitive(seat, typ, alg, cb, ctx) \
((seat)->vt->confirm_weak_crypto_primitive(seat, typ, alg, cb, ctx))
#define seat_confirm_weak_cached_hostkey(seat, alg, better, cb, ctx) \
((seat)->vt->confirm_weak_cached_hostkey(seat, alg, better, cb, ctx))
#define seat_is_utf8(seat) \
((seat)->vt->is_utf8(seat))
#define seat_echoedit_update(seat, echoing, editing) \
((seat)->vt->echoedit_update(seat, echoing, editing))
#define seat_get_x_display(seat) \
((seat)->vt->get_x_display(seat))
#define seat_get_windowid(seat, out) \
((seat)->vt->get_windowid(seat, out))
#define seat_get_window_pixel_size(seat, width, height) \
((seat)->vt->get_window_pixel_size(seat, width, height))
static inline size_t seat_output(
Seat *seat, bool err, const void *data, size_t len)
{ return seat->vt->output(seat, err, data, len); }
static inline bool seat_eof(Seat *seat)
{ return seat->vt->eof(seat); }
static inline int seat_get_userpass_input(
Seat *seat, prompts_t *p, bufchain *input)
{ return seat->vt->get_userpass_input(seat, p, input); }
static inline void seat_notify_remote_exit(Seat *seat)
{ seat->vt->notify_remote_exit(seat); }
static inline void seat_update_specials_menu(Seat *seat)
{ seat->vt->update_specials_menu(seat); }
static inline char *seat_get_ttymode(Seat *seat, const char *mode)
{ return seat->vt->get_ttymode(seat, mode); }
static inline void seat_set_busy_status(Seat *seat, BusyStatus status)
{ seat->vt->set_busy_status(seat, status); }
static inline int seat_verify_ssh_host_key(
Seat *seat, const char *h, int p, const char *ktyp, char *kstr,
char *fp, void (*cb)(void *ctx, int result), void *ctx)
{ return seat->vt->verify_ssh_host_key(seat, h, p, ktyp, kstr, fp, cb, ctx); }
static inline int seat_confirm_weak_crypto_primitive(
Seat *seat, const char *atyp, const char *aname,
void (*cb)(void *ctx, int result), void *ctx)
{ return seat->vt->confirm_weak_crypto_primitive(seat, atyp, aname, cb, ctx); }
static inline int seat_confirm_weak_cached_hostkey(
Seat *seat, const char *aname, const char *better,
void (*cb)(void *ctx, int result), void *ctx)
{ return seat->vt->confirm_weak_cached_hostkey(seat, aname, better, cb, ctx); }
static inline bool seat_is_utf8(Seat *seat)
{ return seat->vt->is_utf8(seat); }
static inline void seat_echoedit_update(Seat *seat, bool ec, bool ed)
{ seat->vt->echoedit_update(seat, ec, ed); }
static inline const char *seat_get_x_display(Seat *seat)
{ return seat->vt->get_x_display(seat); }
static inline bool seat_get_windowid(Seat *seat, long *id_out)
{ return seat->vt->get_windowid(seat, id_out); }
static inline bool seat_get_window_pixel_size(Seat *seat, int *w, int *h)
{ return seat->vt->get_window_pixel_size(seat, w, h); }
/* Unlike the seat's actual method, the public entry point
* seat_connection_fatal is a wrapper function with a printf-like API,
@ -952,10 +976,10 @@ struct SeatVtable {
void seat_connection_fatal(Seat *seat, const char *fmt, ...);
/* Handy aliases for seat_output which set is_stderr to a fixed value. */
#define seat_stdout(seat, data, len) \
seat_output(seat, false, data, len)
#define seat_stderr(seat, data, len) \
seat_output(seat, true, data, len)
static inline size_t seat_stdout(Seat *seat, const void *data, size_t len)
{ return seat_output(seat, false, data, len); }
static inline size_t seat_stderr(Seat *seat, const void *data, size_t len)
{ return seat_output(seat, true, data, len); }
/*
* Stub methods for seat implementations that want to use the obvious
@ -1083,60 +1107,66 @@ struct TermWinVtable {
bool (*is_utf8)(TermWin *);
};
#define win_setup_draw_ctx(win) \
((win)->vt->setup_draw_ctx(win))
#define win_draw_text(win, x, y, text, len, attrs, lattrs, tc) \
((win)->vt->draw_text(win, x, y, text, len, attrs, lattrs, tc))
#define win_draw_cursor(win, x, y, text, len, attrs, lattrs, tc) \
((win)->vt->draw_cursor(win, x, y, text, len, attrs, lattrs, tc))
#define win_char_width(win, uc) \
((win)->vt->char_width(win, uc))
#define win_free_draw_ctx(win) \
((win)->vt->free_draw_ctx(win))
#define win_set_cursor_pos(win, x, y) \
((win)->vt->set_cursor_pos(win, x, y))
#define win_set_raw_mouse_mode(win, enable) \
((win)->vt->set_raw_mouse_mode(win, enable))
#define win_set_scrollbar(win, total, start, page) \
((win)->vt->set_scrollbar(win, total, start, page))
#define win_bell(win, mode) \
((win)->vt->bell(win, mode))
#define win_clip_write(win, clipboard, text, attrs, colours, len, desel) \
((win)->vt->clip_write(win, clipboard, text, attrs, colours, len, desel))
#define win_clip_request_paste(win, clipboard) \
((win)->vt->clip_request_paste(win, clipboard))
#define win_refresh(win) \
((win)->vt->refresh(win))
#define win_request_resize(win, w, h) \
((win)->vt->request_resize(win, w, h))
#define win_set_title(win, title) \
((win)->vt->set_title(win, title))
#define win_set_icon_title(win, ititle) \
((win)->vt->set_icon_title(win, ititle))
#define win_set_minimised(win, minimised) \
((win)->vt->set_minimised(win, minimised))
#define win_is_minimised(win) \
((win)->vt->is_minimised(win))
#define win_set_maximised(win, maximised) \
((win)->vt->set_maximised(win, maximised))
#define win_move(win, x, y) \
((win)->vt->move(win, x, y))
#define win_set_zorder(win, top) \
((win)->vt->set_zorder(win, top))
#define win_palette_get(win, n, r, g, b) \
((win)->vt->palette_get(win, n, r, g, b))
#define win_palette_set(win, n, r, g, b) \
((win)->vt->palette_set(win, n, r, g, b))
#define win_palette_reset(win) \
((win)->vt->palette_reset(win))
#define win_get_pos(win, x, y) \
((win)->vt->get_pos(win, x, y))
#define win_get_pixels(win, x, y) \
((win)->vt->get_pixels(win, x, y))
#define win_get_title(win, icon) \
((win)->vt->get_title(win, icon))
#define win_is_utf8(win) \
((win)->vt->is_utf8(win))
static inline bool win_setup_draw_ctx(TermWin *win)
{ return win->vt->setup_draw_ctx(win); }
static inline void win_draw_text(
TermWin *win, int x, int y, wchar_t *text, int len,
unsigned long attrs, int line_attrs, truecolour tc)
{ win->vt->draw_text(win, x, y, text, len, attrs, line_attrs, tc); }
static inline void win_draw_cursor(
TermWin *win, int x, int y, wchar_t *text, int len,
unsigned long attrs, int line_attrs, truecolour tc)
{ win->vt->draw_cursor(win, x, y, text, len, attrs, line_attrs, tc); }
static inline int win_char_width(TermWin *win, int uc)
{ return win->vt->char_width(win, uc); }
static inline void win_free_draw_ctx(TermWin *win)
{ win->vt->free_draw_ctx(win); }
static inline void win_set_cursor_pos(TermWin *win, int x, int y)
{ win->vt->set_cursor_pos(win, x, y); }
static inline void win_set_raw_mouse_mode(TermWin *win, bool enable)
{ win->vt->set_raw_mouse_mode(win, enable); }
static inline void win_set_scrollbar(TermWin *win, int t, int s, int p)
{ win->vt->set_scrollbar(win, t, s, p); }
static inline void win_bell(TermWin *win, int mode)
{ win->vt->bell(win, mode); }
static inline void win_clip_write(
TermWin *win, int clipboard, wchar_t *text, int *attrs,
truecolour *colours, int len, bool deselect)
{ win->vt->clip_write(win, clipboard, text, attrs, colours, len, deselect); }
static inline void win_clip_request_paste(TermWin *win, int clipboard)
{ win->vt->clip_request_paste(win, clipboard); }
static inline void win_refresh(TermWin *win)
{ win->vt->refresh(win); }
static inline void win_request_resize(TermWin *win, int w, int h)
{ win->vt->request_resize(win, w, h); }
static inline void win_set_title(TermWin *win, const char *title)
{ win->vt->set_title(win, title); }
static inline void win_set_icon_title(TermWin *win, const char *icontitle)
{ win->vt->set_icon_title(win, icontitle); }
static inline void win_set_minimised(TermWin *win, bool minimised)
{ win->vt->set_minimised(win, minimised); }
static inline bool win_is_minimised(TermWin *win)
{ return win->vt->is_minimised(win); }
static inline void win_set_maximised(TermWin *win, bool maximised)
{ win->vt->set_maximised(win, maximised); }
static inline void win_move(TermWin *win, int x, int y)
{ win->vt->move(win, x, y); }
static inline void win_set_zorder(TermWin *win, bool top)
{ win->vt->set_zorder(win, top); }
static inline bool win_palette_get(TermWin *win, int n, int *r, int *g, int *b)
{ return win->vt->palette_get(win, n, r, g, b); }
static inline void win_palette_set(TermWin *win, int n, int r, int g, int b)
{ win->vt->palette_set(win, n, r, g, b); }
static inline void win_palette_reset(TermWin *win)
{ win->vt->palette_reset(win); }
static inline void win_get_pos(TermWin *win, int *x, int *y)
{ win->vt->get_pos(win, x, y); }
static inline void win_get_pixels(TermWin *win, int *x, int *y)
{ win->vt->get_pixels(win, x, y); }
static inline const char *win_get_title(TermWin *win, bool icon)
{ return win->vt->get_title(win, icon); }
static inline bool win_is_utf8(TermWin *win)
{ return win->vt->is_utf8(win); }
/*
* Global functions not specific to a connection instance.
@ -1606,9 +1636,15 @@ struct LogPolicyVtable {
struct LogPolicy {
const LogPolicyVtable *vt;
};
#define lp_eventlog(lp, event) ((lp)->vt->eventlog(lp, event))
#define lp_askappend(lp, fn, cb, ctx) ((lp)->vt->askappend(lp, fn, cb, ctx))
#define lp_logging_error(lp, event) ((lp)->vt->logging_error(lp, event))
static inline void lp_eventlog(LogPolicy *lp, const char *event)
{ lp->vt->eventlog(lp, event); }
static inline int lp_askappend(
LogPolicy *lp, Filename *filename,
void (*callback)(void *ctx, int result), void *ctx)
{ return lp->vt->askappend(lp, filename, callback, ctx); }
static inline void lp_logging_error(LogPolicy *lp, const char *event)
{ lp->vt->logging_error(lp, event); }
LogContext *log_init(LogPolicy *lp, Conf *conf);
void log_free(LogContext *logctx);

134
sftp.h
View File

@ -390,40 +390,58 @@ struct SftpServerVtable {
int max_entries, bool omit_longname);
};
#define sftpsrv_new(vt) \
((vt)->new(vt))
#define sftpsrv_free(srv) \
((srv)->vt->free(srv))
#define sftpsrv_realpath(srv, reply, path) \
((srv)->vt->realpath(srv, reply, path))
#define sftpsrv_open(srv, reply, path, flags, attrs) \
((srv)->vt->open(srv, reply, path, flags, attrs))
#define sftpsrv_opendir(srv, reply, path) \
((srv)->vt->opendir(srv, reply, path))
#define sftpsrv_close(srv, reply, handle) \
((srv)->vt->close(srv, reply, handle))
#define sftpsrv_mkdir(srv, reply, path, attrs) \
((srv)->vt->mkdir(srv, reply, path, attrs))
#define sftpsrv_rmdir(srv, reply, path) \
((srv)->vt->rmdir(srv, reply, path))
#define sftpsrv_remove(srv, reply, path) \
((srv)->vt->remove(srv, reply, path))
#define sftpsrv_rename(srv, reply, srcpath, dstpath) \
((srv)->vt->rename(srv, reply, srcpath, dstpath))
#define sftpsrv_stat(srv, reply, path, follow) \
((srv)->vt->stat(srv, reply, path, follow))
#define sftpsrv_fstat(srv, reply, handle) \
((srv)->vt->fstat(srv, reply, handle))
#define sftpsrv_setstat(srv, reply, path, attrs) \
((srv)->vt->setstat(srv, reply, path, attrs))
#define sftpsrv_fsetstat(srv, reply, handle, attrs) \
((srv)->vt->fsetstat(srv, reply, handle, attrs))
#define sftpsrv_read(srv, reply, handle, offset, length) \
((srv)->vt->read(srv, reply, handle, offset, length))
#define sftpsrv_write(srv, reply, handle, offset, data) \
((srv)->vt->write(srv, reply, handle, offset, data))
#define sftpsrv_readdir(srv, reply, handle, max, nolongname) \
((srv)->vt->readdir(srv, reply, handle, max, nolongname))
static inline SftpServer *sftpsrv_new(const SftpServerVtable *vt)
{ return vt->new(vt); }
static inline void sftpsrv_free(SftpServer *srv)
{ srv->vt->free(srv); }
static inline void sftpsrv_realpath(SftpServer *srv, SftpReplyBuilder *reply,
ptrlen path)
{ srv->vt->realpath(srv, reply, path); }
static inline void sftpsrv_open(
SftpServer *srv, SftpReplyBuilder *reply,
ptrlen path, unsigned flags, struct fxp_attrs attrs)
{ srv->vt->open(srv, reply, path, flags, attrs); }
static inline void sftpsrv_opendir(
SftpServer *srv, SftpReplyBuilder *reply, ptrlen path)
{ srv->vt->opendir(srv, reply, path); }
static inline void sftpsrv_close(
SftpServer *srv, SftpReplyBuilder *reply, ptrlen handle)
{ srv->vt->close(srv, reply, handle); }
static inline void sftpsrv_mkdir(SftpServer *srv, SftpReplyBuilder *reply,
ptrlen path, struct fxp_attrs attrs)
{ srv->vt->mkdir(srv, reply, path, attrs); }
static inline void sftpsrv_rmdir(
SftpServer *srv, SftpReplyBuilder *reply, ptrlen path)
{ srv->vt->rmdir(srv, reply, path); }
static inline void sftpsrv_remove(
SftpServer *srv, SftpReplyBuilder *reply, ptrlen path)
{ srv->vt->remove(srv, reply, path); }
static inline void sftpsrv_rename(SftpServer *srv, SftpReplyBuilder *reply,
ptrlen srcpath, ptrlen dstpath)
{ srv->vt->rename(srv, reply, srcpath, dstpath); }
static inline void sftpsrv_stat(
SftpServer *srv, SftpReplyBuilder *reply, ptrlen path, bool follow)
{ srv->vt->stat(srv, reply, path, follow); }
static inline void sftpsrv_fstat(
SftpServer *srv, SftpReplyBuilder *reply, ptrlen handle)
{ srv->vt->fstat(srv, reply, handle); }
static inline void sftpsrv_setstat(SftpServer *srv, SftpReplyBuilder *reply,
ptrlen path, struct fxp_attrs attrs)
{ srv->vt->setstat(srv, reply, path, attrs); }
static inline void sftpsrv_fsetstat(SftpServer *srv, SftpReplyBuilder *reply,
ptrlen handle, struct fxp_attrs attrs)
{ srv->vt->fsetstat(srv, reply, handle, attrs); }
static inline void sftpsrv_read(
SftpServer *srv, SftpReplyBuilder *reply,
ptrlen handle, uint64_t offset, unsigned length)
{ srv->vt->read(srv, reply, handle, offset, length); }
static inline void sftpsrv_write(SftpServer *srv, SftpReplyBuilder *reply,
ptrlen handle, uint64_t offset, ptrlen data)
{ srv->vt->write(srv, reply, handle, offset, data); }
static inline void sftpsrv_readdir(
SftpServer *srv, SftpReplyBuilder *reply, ptrlen handle,
int max_entries, bool omit_longname)
{ srv->vt->readdir(srv, reply, handle, max_entries, omit_longname); }
typedef struct SftpReplyBuilderVtable SftpReplyBuilderVtable;
struct SftpReplyBuilder {
@ -442,22 +460,26 @@ struct SftpReplyBuilderVtable {
void (*reply_attrs)(SftpReplyBuilder *reply, struct fxp_attrs attrs);
};
#define fxp_reply_ok(reply) \
((reply)->vt->reply_ok(reply))
#define fxp_reply_error(reply, code, msg) \
((reply)->vt->reply_error(reply, code, msg))
#define fxp_reply_simple_name(reply, name) \
((reply)->vt->reply_simple_name(reply, name))
#define fxp_reply_name_count(reply, count) \
((reply)->vt->reply_name_count(reply, count))
#define fxp_reply_full_name(reply, name, longname, attrs) \
((reply)->vt->reply_full_name(reply, name, longname, attrs))
#define fxp_reply_handle(reply, handle) \
((reply)->vt->reply_handle(reply, handle))
#define fxp_reply_data(reply, data) \
((reply)->vt->reply_data(reply, data))
#define fxp_reply_attrs(reply, attrs) \
((reply)->vt->reply_attrs(reply, attrs))
static inline void fxp_reply_ok(SftpReplyBuilder *reply)
{ reply->vt->reply_ok(reply); }
static inline void fxp_reply_error(SftpReplyBuilder *reply, unsigned code,
const char *msg)
{ reply->vt->reply_error(reply, code, msg); }
static inline void fxp_reply_simple_name(SftpReplyBuilder *reply, ptrlen name)
{ reply->vt->reply_simple_name(reply, name); }
static inline void fxp_reply_name_count(
SftpReplyBuilder *reply, unsigned count)
{ reply->vt->reply_name_count(reply, count); }
static inline void fxp_reply_full_name(SftpReplyBuilder *reply, ptrlen name,
ptrlen longname, struct fxp_attrs attrs)
{ reply->vt->reply_full_name(reply, name, longname, attrs); }
static inline void fxp_reply_handle(SftpReplyBuilder *reply, ptrlen handle)
{ reply->vt->reply_handle(reply, handle); }
static inline void fxp_reply_data(SftpReplyBuilder *reply, ptrlen data)
{ reply->vt->reply_data(reply, data); }
static inline void fxp_reply_attrs(
SftpReplyBuilder *reply, struct fxp_attrs attrs)
{ reply->vt->reply_attrs(reply, attrs); }
/*
* The usual implementation of an SftpReplyBuilder, containing a
@ -499,10 +521,14 @@ struct ScpServerVtable {
void (*eof)(ScpServer *s);
};
#define scp_free(s) ((s)->vt->free(s))
#define scp_send(s, data, len) ((s)->vt->send(s, data, len))
#define scp_throttle(s, th) ((s)->vt->throttle(s, th))
#define scp_eof(s) ((s)->vt->eof(s))
static inline void scp_free(ScpServer *s)
{ s->vt->free(s); }
static inline size_t scp_send(ScpServer *s, const void *data, size_t length)
{ return s->vt->send(s, data, length); }
static inline void scp_throttle(ScpServer *s, bool throttled)
{ s->vt->throttle(s, throttled); }
static inline void scp_eof(ScpServer *s)
{ s->vt->eof(s); }
/*
* Create an ScpServer by calling this function, giving it the command

262
ssh.h
View File

@ -306,50 +306,70 @@ struct ConnectionLayer {
const struct ConnectionLayerVtable *vt;
};
#define ssh_rportfwd_alloc(cl, sh, sp, dh, dp, af, ld, pfr, share) \
((cl)->vt->rportfwd_alloc(cl, sh, sp, dh, dp, af, ld, pfr, share))
#define ssh_rportfwd_remove(cl, rpf) ((cl)->vt->rportfwd_remove(cl, rpf))
#define ssh_lportfwd_open(cl, h, p, desc, pi, chan) \
((cl)->vt->lportfwd_open(cl, h, p, desc, pi, chan))
#define ssh_serverside_x11_open(cl, chan, pi) \
((cl)->vt->serverside_x11_open(cl, chan, pi))
#define ssh_serverside_agent_open(cl, chan) \
((cl)->vt->serverside_agent_open(cl, chan))
#define ssh_session_open(cl, chan) \
((cl)->vt->session_open(cl, chan))
#define ssh_add_x11_display(cl, auth, disp) \
((cl)->vt->add_x11_display(cl, auth, disp))
#define ssh_add_sharing_x11_display(cl, auth, cs, ch) \
((cl)->vt->add_sharing_x11_display(cl, auth, cs, ch))
#define ssh_remove_sharing_x11_display(cl, fa) \
((cl)->vt->remove_sharing_x11_display(cl, fa))
#define ssh_send_packet_from_downstream(cl, id, type, pkt, len, log) \
((cl)->vt->send_packet_from_downstream(cl, id, type, pkt, len, log))
#define ssh_alloc_sharing_channel(cl, cs) \
((cl)->vt->alloc_sharing_channel(cl, cs))
#define ssh_delete_sharing_channel(cl, ch) \
((cl)->vt->delete_sharing_channel(cl, ch))
#define ssh_sharing_queue_global_request(cl, cs) \
((cl)->vt->sharing_queue_global_request(cl, cs))
#define ssh_sharing_no_more_downstreams(cl) \
((cl)->vt->sharing_no_more_downstreams(cl))
#define ssh_agent_forwarding_permitted(cl) \
((cl)->vt->agent_forwarding_permitted(cl))
#define ssh_terminal_size(cl, w, h) ((cl)->vt->terminal_size(cl, w, h))
#define ssh_stdout_unthrottle(cl, bufsize) \
((cl)->vt->stdout_unthrottle(cl, bufsize))
#define ssh_stdin_backlog(cl) ((cl)->vt->stdin_backlog(cl))
#define ssh_throttle_all_channels(cl, throttled) \
((cl)->vt->throttle_all_channels(cl, throttled))
#define ssh_ldisc_option(cl, option) ((cl)->vt->ldisc_option(cl, option))
#define ssh_set_ldisc_option(cl, opt, val) \
((cl)->vt->set_ldisc_option(cl, opt, val))
#define ssh_enable_x_fwd(cl) ((cl)->vt->enable_x_fwd(cl))
#define ssh_enable_agent_fwd(cl) ((cl)->vt->enable_agent_fwd(cl))
#define ssh_set_wants_user_input(cl, wanted) \
((cl)->vt->set_wants_user_input(cl, wanted))
#define ssh_setup_server_x_forwarding(cl, conf, ap, ad, scr) \
((cl)->vt->setup_server_x_forwarding(cl, conf, ap, ad, scr))
static inline struct ssh_rportfwd *ssh_rportfwd_alloc(
ConnectionLayer *cl, const char *sh, int sp, const char *dh, int dp,
int af, const char *log, PortFwdRecord *pfr, ssh_sharing_connstate *cs)
{ return cl->vt->rportfwd_alloc(cl, sh, sp, dh, dp, af, log, pfr, cs); }
static inline void ssh_rportfwd_remove(
ConnectionLayer *cl, struct ssh_rportfwd *rpf)
{ cl->vt->rportfwd_remove(cl, rpf); }
static inline SshChannel *ssh_lportfwd_open(
ConnectionLayer *cl, const char *host, int port,
const char *desc, const SocketPeerInfo *pi, Channel *chan)
{ return cl->vt->lportfwd_open(cl, host, port, desc, pi, chan); }
static inline SshChannel *ssh_session_open(ConnectionLayer *cl, Channel *chan)
{ return cl->vt->session_open(cl, chan); }
static inline SshChannel *ssh_serverside_x11_open(
ConnectionLayer *cl, Channel *chan, const SocketPeerInfo *pi)
{ return cl->vt->serverside_x11_open(cl, chan, pi); }
static inline SshChannel *ssh_serverside_agent_open(
ConnectionLayer *cl, Channel *chan)
{ return cl->vt->serverside_agent_open(cl, chan); }
static inline struct X11FakeAuth *ssh_add_x11_display(
ConnectionLayer *cl, int authtype, struct X11Display *x11disp)
{ return cl->vt->add_x11_display(cl, authtype, x11disp); }
static inline struct X11FakeAuth *ssh_add_sharing_x11_display(
ConnectionLayer *cl, int authtype, ssh_sharing_connstate *share_cs,
share_channel *share_chan)
{ return cl->vt->add_sharing_x11_display(cl, authtype, share_cs, share_chan); }
static inline void ssh_remove_sharing_x11_display(
ConnectionLayer *cl, struct X11FakeAuth *auth)
{ cl->vt->remove_sharing_x11_display(cl, auth); }
static inline void ssh_send_packet_from_downstream(
ConnectionLayer *cl, unsigned id, int type,
const void *pkt, int len, const char *log)
{ cl->vt->send_packet_from_downstream(cl, id, type, pkt, len, log); }
static inline unsigned ssh_alloc_sharing_channel(
ConnectionLayer *cl, ssh_sharing_connstate *connstate)
{ return cl->vt->alloc_sharing_channel(cl, connstate); }
static inline void ssh_delete_sharing_channel(
ConnectionLayer *cl, unsigned localid)
{ cl->vt->delete_sharing_channel(cl, localid); }
static inline void ssh_sharing_queue_global_request(
ConnectionLayer *cl, ssh_sharing_connstate *connstate)
{ cl->vt->sharing_queue_global_request(cl, connstate); }
static inline void ssh_sharing_no_more_downstreams(ConnectionLayer *cl)
{ cl->vt->sharing_no_more_downstreams(cl); }
static inline bool ssh_agent_forwarding_permitted(ConnectionLayer *cl)
{ return cl->vt->agent_forwarding_permitted(cl); }
static inline void ssh_terminal_size(ConnectionLayer *cl, int w, int h)
{ cl->vt->terminal_size(cl, w, h); }
static inline void ssh_stdout_unthrottle(ConnectionLayer *cl, size_t bufsize)
{ cl->vt->stdout_unthrottle(cl, bufsize); }
static inline size_t ssh_stdin_backlog(ConnectionLayer *cl)
{ return cl->vt->stdin_backlog(cl); }
static inline void ssh_throttle_all_channels(ConnectionLayer *cl, bool thr)
{ cl->vt->throttle_all_channels(cl, thr); }
static inline bool ssh_ldisc_option(ConnectionLayer *cl, int option)
{ return cl->vt->ldisc_option(cl, option); }
static inline void ssh_set_ldisc_option(ConnectionLayer *cl, int opt, bool val)
{ cl->vt->set_ldisc_option(cl, opt, val); }
static inline void ssh_enable_x_fwd(ConnectionLayer *cl)
{ cl->vt->enable_x_fwd(cl); }
static inline void ssh_enable_agent_fwd(ConnectionLayer *cl)
{ cl->vt->enable_agent_fwd(cl); }
static inline void ssh_set_wants_user_input(ConnectionLayer *cl, bool wanted)
{ cl->vt->set_wants_user_input(cl, wanted); }
/* Exports from portfwd.c */
PortFwdManager *portfwdmgr_new(ConnectionLayer *cl);
@ -600,17 +620,26 @@ struct ssh_cipheralg {
const void *extra;
};
#define ssh_cipher_new(alg) ((alg)->new(alg))
#define ssh_cipher_free(ctx) ((ctx)->vt->free(ctx))
#define ssh_cipher_setiv(ctx, iv) ((ctx)->vt->setiv(ctx, iv))
#define ssh_cipher_setkey(ctx, key) ((ctx)->vt->setkey(ctx, key))
#define ssh_cipher_encrypt(ctx, blk, len) ((ctx)->vt->encrypt(ctx, blk, len))
#define ssh_cipher_decrypt(ctx, blk, len) ((ctx)->vt->decrypt(ctx, blk, len))
#define ssh_cipher_encrypt_length(ctx, blk, len, seq) \
((ctx)->vt->encrypt_length(ctx, blk, len, seq))
#define ssh_cipher_decrypt_length(ctx, blk, len, seq) \
((ctx)->vt->decrypt_length(ctx, blk, len, seq))
#define ssh_cipher_alg(ctx) ((ctx)->vt)
static inline ssh_cipher *ssh_cipher_new(const ssh_cipheralg *alg)
{ return alg->new(alg); }
static inline void ssh_cipher_free(ssh_cipher *c)
{ c->vt->free(c); }
static inline void ssh_cipher_setiv(ssh_cipher *c, const void *iv)
{ c->vt->setiv(c, iv); }
static inline void ssh_cipher_setkey(ssh_cipher *c, const void *key)
{ c->vt->setkey(c, key); }
static inline void ssh_cipher_encrypt(ssh_cipher *c, void *blk, int len)
{ c->vt->encrypt(c, blk, len); }
static inline void ssh_cipher_decrypt(ssh_cipher *c, void *blk, int len)
{ c->vt->decrypt(c, blk, len); }
static inline void ssh_cipher_encrypt_length(
ssh_cipher *c, void *blk, int len, unsigned long seq)
{ return c->vt->encrypt_length(c, blk, len, seq); }
static inline void ssh_cipher_decrypt_length(
ssh_cipher *c, void *blk, int len, unsigned long seq)
{ return c->vt->decrypt_length(c, blk, len, seq); }
static inline const struct ssh_cipheralg *ssh_cipher_alg(ssh_cipher *c)
{ return c->vt; }
struct ssh2_ciphers {
int nciphers;
@ -637,13 +666,21 @@ struct ssh2_macalg {
const void *extra;
};
#define ssh2_mac_new(alg, cipher) ((alg)->new(alg, cipher))
#define ssh2_mac_free(ctx) ((ctx)->vt->free(ctx))
#define ssh2_mac_setkey(ctx, key) ((ctx)->vt->setkey(ctx, key))
#define ssh2_mac_start(ctx) ((ctx)->vt->start(ctx))
#define ssh2_mac_genresult(ctx, out) ((ctx)->vt->genresult(ctx, out))
#define ssh2_mac_text_name(ctx) ((ctx)->vt->text_name(ctx))
#define ssh2_mac_alg(ctx) ((ctx)->vt)
static inline ssh2_mac *ssh2_mac_new(
const ssh2_macalg *alg, ssh_cipher *cipher)
{ return alg->new(alg, cipher); }
static inline void ssh2_mac_free(ssh2_mac *m)
{ m->vt->free(m); }
static inline void ssh2_mac_setkey(ssh2_mac *m, ptrlen key)
{ m->vt->setkey(m, key); }
static inline void ssh2_mac_start(ssh2_mac *m)
{ m->vt->start(m); }
static inline void ssh2_mac_genresult(ssh2_mac *m, unsigned char *out)
{ m->vt->genresult(m, out); }
static inline const char *ssh2_mac_text_name(ssh2_mac *m)
{ return m->vt->text_name(m); }
static inline const ssh2_macalg *ssh2_mac_alg(ssh2_mac *m)
{ return m->vt; }
/* Centralised 'methods' for ssh2_mac, defined in sshmac.c. These run
* the MAC in a specifically SSH-2 style, i.e. taking account of a
@ -673,11 +710,16 @@ struct ssh_hashalg {
const char *text_name; /* both combined, e.g. "SHA-n (unaccelerated)" */
};
#define ssh_hash_new(alg) ((alg)->new(alg))
#define ssh_hash_copy(ctx) ((ctx)->vt->copy(ctx))
#define ssh_hash_final(ctx, out) ((ctx)->vt->final(ctx, out))
#define ssh_hash_free(ctx) ((ctx)->vt->free(ctx))
#define ssh_hash_alg(ctx) ((ctx)->vt)
static inline ssh_hash *ssh_hash_new(const ssh_hashalg *alg)
{ return alg->new(alg); }
static inline ssh_hash *ssh_hash_copy(ssh_hash *h)
{ return h->vt->copy(h); }
static inline void ssh_hash_final(ssh_hash *h, unsigned char *out)
{ return h->vt->final(h, out); }
static inline void ssh_hash_free(ssh_hash *h)
{ return h->vt->free(h); }
static inline const ssh_hashalg *ssh_hash_alg(ssh_hash *h)
{ return h->vt; }
/* Handy macros for defining all those text-name fields at once */
#define HASHALG_NAMES_BARE(base) \
@ -725,25 +767,39 @@ struct ssh_keyalg {
const unsigned supported_flags; /* signature-type flags we understand */
};
#define ssh_key_new_pub(alg, data) ((alg)->new_pub(alg, data))
#define ssh_key_new_priv(alg, pub, priv) ((alg)->new_priv(alg, pub, priv))
#define ssh_key_new_priv_openssh(alg, bs) ((alg)->new_priv_openssh(alg, bs))
#define ssh_key_free(key) ((key)->vt->freekey(key))
#define ssh_key_invalid(key, flags) ((key)->vt->invalid(key, flags))
#define ssh_key_sign(key, data, flags, bs) \
((key)->vt->sign(key, data, flags, bs))
#define ssh_key_verify(key, sig, data) ((key)->vt->verify(key, sig, data))
#define ssh_key_public_blob(key, bs) ((key)->vt->public_blob(key, bs))
#define ssh_key_private_blob(key, bs) ((key)->vt->private_blob(key, bs))
#define ssh_key_openssh_blob(key, bs) ((key)->vt->openssh_blob(key, bs))
#define ssh_key_cache_str(key) ((key)->vt->cache_str(key))
#define ssh_key_public_bits(alg, blob) ((alg)->pubkey_bits(alg, blob))
#define ssh_key_alg(key) (key)->vt
#define ssh_key_ssh_id(key) ((key)->vt->ssh_id)
#define ssh_key_cache_id(key) ((key)->vt->cache_id)
static inline ssh_key *ssh_key_new_pub(const ssh_keyalg *self, ptrlen pub)
{ return self->new_pub(self, pub); }
static inline ssh_key *ssh_key_new_priv(
const ssh_keyalg *self, ptrlen pub, ptrlen priv)
{ return self->new_priv(self, pub, priv); }
static inline ssh_key *ssh_key_new_priv_openssh(
const ssh_keyalg *self, BinarySource *src)
{ return self->new_priv_openssh(self, src); }
static inline void ssh_key_free(ssh_key *key)
{ key->vt->freekey(key); }
static inline char *ssh_key_invalid(ssh_key *key, unsigned flags)
{ return key->vt->invalid(key, flags); }
static inline void ssh_key_sign(
ssh_key *key, ptrlen data, unsigned flags, BinarySink *bs)
{ key->vt->sign(key, data, flags, bs); }
static inline bool ssh_key_verify(ssh_key *key, ptrlen sig, ptrlen data)
{ return key->vt->verify(key, sig, data); }
static inline void ssh_key_public_blob(ssh_key *key, BinarySink *bs)
{ key->vt->public_blob(key, bs); }
static inline void ssh_key_private_blob(ssh_key *key, BinarySink *bs)
{ key->vt->private_blob(key, bs); }
static inline void ssh_key_openssh_blob(ssh_key *key, BinarySink *bs)
{ key->vt->openssh_blob(key, bs); }
static inline char *ssh_key_cache_str(ssh_key *key)
{ return key->vt->cache_str(key); }
static inline int ssh_key_public_bits(const ssh_keyalg *self, ptrlen blob)
{ return self->pubkey_bits(self, blob); }
static inline const ssh_keyalg *ssh_key_alg(ssh_key *key)
{ return key->vt; }
static inline const char *ssh_key_ssh_id(ssh_key *key)
{ return key->vt->ssh_id; }
static inline const char *ssh_key_cache_id(ssh_key *key)
{ return key->vt->cache_id; }
/*
* Enumeration of signature flags from draft-miller-ssh-agent-02
@ -775,16 +831,30 @@ struct ssh_compression_alg {
const char *text_name;
};
#define ssh_compressor_new(alg) ((alg)->compress_new())
#define ssh_compressor_free(comp) ((comp)->vt->compress_free(comp))
#define ssh_compressor_compress(comp, in, inlen, out, outlen, minlen) \
((comp)->vt->compress(comp, in, inlen, out, outlen, minlen))
#define ssh_compressor_alg(comp) ((comp)->vt)
#define ssh_decompressor_new(alg) ((alg)->decompress_new())
#define ssh_decompressor_free(comp) ((comp)->vt->decompress_free(comp))
#define ssh_decompressor_decompress(comp, in, inlen, out, outlen) \
((comp)->vt->decompress(comp, in, inlen, out, outlen))
#define ssh_decompressor_alg(comp) ((comp)->vt)
static inline ssh_compressor *ssh_compressor_new(
const ssh_compression_alg *alg)
{ return alg->compress_new(); }
static inline ssh_decompressor *ssh_decompressor_new(
const ssh_compression_alg *alg)
{ return alg->decompress_new(); }
static inline void ssh_compressor_free(ssh_compressor *c)
{ c->vt->compress_free(c); }
static inline void ssh_decompressor_free(ssh_decompressor *d)
{ d->vt->decompress_free(d); }
static inline void ssh_compressor_compress(
ssh_compressor *c, const unsigned char *block, int len,
unsigned char **outblock, int *outlen, int minlen)
{ c->vt->compress(c, block, len, outblock, outlen, minlen); }
static inline bool ssh_decompressor_decompress(
ssh_decompressor *d, const unsigned char *block, int len,
unsigned char **outblock, int *outlen)
{ return d->vt->decompress(d, block, len, outblock, outlen); }
static inline const ssh_compression_alg *ssh_compressor_alg(
ssh_compressor *c)
{ return c->vt; }
static inline const ssh_compression_alg *ssh_decompressor_alg(
ssh_decompressor *d)
{ return d->vt; }
struct ssh2_userkey {
ssh_key *key; /* the key itself */

View File

@ -42,11 +42,15 @@ struct BinaryPacketProtocol {
bool expect_close;
};
#define ssh_bpp_handle_input(bpp) ((bpp)->vt->handle_input(bpp))
#define ssh_bpp_handle_output(bpp) ((bpp)->vt->handle_output(bpp))
#define ssh_bpp_new_pktout(bpp, type) ((bpp)->vt->new_pktout(type))
#define ssh_bpp_queue_disconnect(bpp, msg, cat) \
((bpp)->vt->queue_disconnect(bpp, msg, cat))
static inline void ssh_bpp_handle_input(BinaryPacketProtocol *bpp)
{ bpp->vt->handle_input(bpp); }
static inline void ssh_bpp_handle_output(BinaryPacketProtocol *bpp)
{ bpp->vt->handle_output(bpp); }
static inline PktOut *ssh_bpp_new_pktout(BinaryPacketProtocol *bpp, int type)
{ return bpp->vt->new_pktout(type); }
static inline void ssh_bpp_queue_disconnect(BinaryPacketProtocol *bpp,
const char *msg, int category)
{ bpp->vt->queue_disconnect(bpp, msg, category); }
/* ssh_bpp_free is more than just a macro wrapper on the vtable; it
* does centralised parts of the freeing too. */

188
sshchan.h
View File

@ -62,43 +62,57 @@ struct Channel {
unsigned initial_fixed_window_size;
};
#define chan_free(ch) ((ch)->vt->free(ch))
#define chan_open_confirmation(ch) ((ch)->vt->open_confirmation(ch))
#define chan_open_failed(ch, err) ((ch)->vt->open_failed(ch, err))
#define chan_send(ch, err, buf, len) ((ch)->vt->send(ch, err, buf, len))
#define chan_send_eof(ch) ((ch)->vt->send_eof(ch))
#define chan_set_input_wanted(ch, wanted) \
((ch)->vt->set_input_wanted(ch, wanted))
#define chan_log_close_msg(ch) ((ch)->vt->log_close_msg(ch))
#define chan_want_close(ch, leof, reof) ((ch)->vt->want_close(ch, leof, reof))
#define chan_rcvd_exit_status(ch, status) \
((ch)->vt->rcvd_exit_status(ch, status))
#define chan_rcvd_exit_signal(ch, sig, core, msg) \
((ch)->vt->rcvd_exit_signal(ch, sig, core, msg))
#define chan_rcvd_exit_signal_numeric(ch, sig, core, msg) \
((ch)->vt->rcvd_exit_signal_numeric(ch, sig, core, msg))
#define chan_run_shell(ch) \
((ch)->vt->run_shell(ch))
#define chan_run_command(ch, cmd) \
((ch)->vt->run_command(ch, cmd))
#define chan_run_subsystem(ch, subsys) \
((ch)->vt->run_subsystem(ch, subsys))
#define chan_enable_x11_forwarding(ch, oneshot, ap, ad, scr) \
((ch)->vt->enable_x11_forwarding(ch, oneshot, ap, ad, scr))
#define chan_enable_agent_forwarding(ch) \
((ch)->vt->enable_agent_forwarding(ch))
#define chan_allocate_pty(ch, termtype, w, h, pw, ph, modes) \
((ch)->vt->allocate_pty(ch, termtype, w, h, pw, ph, modes))
#define chan_set_env(ch, var, value) \
((ch)->vt->set_env(ch, var, value))
#define chan_send_break(ch, length) \
((ch)->vt->send_break(ch, length))
#define chan_send_signal(ch, signame) \
((ch)->vt->send_signal(ch, signame))
#define chan_change_window_size(ch, w, h, pw, ph) \
((ch)->vt->change_window_size(ch, w, h, pw, ph))
#define chan_request_response(ch, success) \
((ch)->vt->request_response(ch, success))
static inline void chan_free(Channel *ch)
{ ch->vt->free(ch); }
static inline void chan_open_confirmation(Channel *ch)
{ ch->vt->open_confirmation(ch); }
static inline void chan_open_failed(Channel *ch, const char *err)
{ ch->vt->open_failed(ch, err); }
static inline size_t chan_send(
Channel *ch, bool err, const void *buf, size_t len)
{ return ch->vt->send(ch, err, buf, len); }
static inline void chan_send_eof(Channel *ch)
{ ch->vt->send_eof(ch); }
static inline void chan_set_input_wanted(Channel *ch, bool wanted)
{ ch->vt->set_input_wanted(ch, wanted); }
static inline char *chan_log_close_msg(Channel *ch)
{ return ch->vt->log_close_msg(ch); }
static inline bool chan_want_close(Channel *ch, bool leof, bool reof)
{ return ch->vt->want_close(ch, leof, reof); }
static inline bool chan_rcvd_exit_status(Channel *ch, int status)
{ return ch->vt->rcvd_exit_status(ch, status); }
static inline bool chan_rcvd_exit_signal(
Channel *ch, ptrlen sig, bool core, ptrlen msg)
{ return ch->vt->rcvd_exit_signal(ch, sig, core, msg); }
static inline bool chan_rcvd_exit_signal_numeric(
Channel *ch, int sig, bool core, ptrlen msg)
{ return ch->vt->rcvd_exit_signal_numeric(ch, sig, core, msg); }
static inline bool chan_run_shell(Channel *ch)
{ return ch->vt->run_shell(ch); }
static inline bool chan_run_command(Channel *ch, ptrlen cmd)
{ return ch->vt->run_command(ch, cmd); }
static inline bool chan_run_subsystem(Channel *ch, ptrlen subsys)
{ return ch->vt->run_subsystem(ch, subsys); }
static inline bool chan_enable_x11_forwarding(
Channel *ch, bool oneshot, ptrlen ap, ptrlen ad, unsigned scr)
{ return ch->vt->enable_x11_forwarding(ch, oneshot, ap, ad, scr); }
static inline bool chan_enable_agent_forwarding(Channel *ch)
{ return ch->vt->enable_agent_forwarding(ch); }
static inline bool chan_allocate_pty(
Channel *ch, ptrlen termtype, unsigned w, unsigned h,
unsigned pw, unsigned ph, struct ssh_ttymodes modes)
{ return ch->vt->allocate_pty(ch, termtype, w, h, pw, ph, modes); }
static inline bool chan_set_env(Channel *ch, ptrlen var, ptrlen value)
{ return ch->vt->set_env(ch, var, value); }
static inline bool chan_send_break(Channel *ch, unsigned length)
{ return ch->vt->send_break(ch, length); }
static inline bool chan_send_signal(Channel *ch, ptrlen signame)
{ return ch->vt->send_signal(ch, signame); }
static inline bool chan_change_window_size(
Channel *ch, unsigned w, unsigned h, unsigned pw, unsigned ph)
{ return ch->vt->change_window_size(ch, w, h, pw, ph); }
static inline void chan_request_response(Channel *ch, bool success)
{ ch->vt->request_response(ch, success); }
/*
* Reusable methods you can put in vtables to give default handling of
@ -217,44 +231,68 @@ struct SshChannel {
ConnectionLayer *cl;
};
#define sshfwd_write(c, buf, len) ((c)->vt->write(c, false, buf, len))
#define sshfwd_write_ext(c, stderr, buf, len) \
((c)->vt->write(c, stderr, buf, len))
#define sshfwd_write_eof(c) ((c)->vt->write_eof(c))
#define sshfwd_initiate_close(c, err) ((c)->vt->initiate_close(c, err))
#define sshfwd_unthrottle(c, bufsize) ((c)->vt->unthrottle(c, bufsize))
#define sshfwd_get_conf(c) ((c)->vt->get_conf(c))
#define sshfwd_window_override_removed(c) ((c)->vt->window_override_removed(c))
#define sshfwd_x11_sharing_handover(c, cs, ch, pa, pp, e, pmaj, pmin, d, l) \
((c)->vt->x11_sharing_handover(c, cs, ch, pa, pp, e, pmaj, pmin, d, l))
#define sshfwd_send_exit_status(c, status) \
((c)->vt->send_exit_status(c, status))
#define sshfwd_send_exit_signal(c, sig, core, msg) \
((c)->vt->send_exit_signal(c, sig, core, msg))
#define sshfwd_send_exit_signal_numeric(c, sig, core, msg) \
((c)->vt->send_exit_signal_numeric(c, sig, core, msg))
#define sshfwd_request_x11_forwarding(c, wr, ap, ad, scr, oneshot) \
((c)->vt->request_x11_forwarding(c, wr, ap, ad, scr, oneshot))
#define sshfwd_request_agent_forwarding(c, wr) \
((c)->vt->request_agent_forwarding(c, wr))
#define sshfwd_request_pty(c, wr, conf, w, h) \
((c)->vt->request_pty(c, wr, conf, w, h))
#define sshfwd_send_env_var(c, wr, var, value) \
((c)->vt->send_env_var(c, wr, var, value))
#define sshfwd_start_shell(c, wr) \
((c)->vt->start_shell(c, wr))
#define sshfwd_start_command(c, wr, cmd) \
((c)->vt->start_command(c, wr, cmd))
#define sshfwd_start_subsystem(c, wr, subsys) \
((c)->vt->start_subsystem(c, wr, subsys))
#define sshfwd_send_serial_break(c, wr, length) \
((c)->vt->send_serial_break(c, wr, length))
#define sshfwd_send_signal(c, wr, sig) \
((c)->vt->send_signal(c, wr, sig))
#define sshfwd_send_terminal_size_change(c, w, h) \
((c)->vt->send_terminal_size_change(c, w, h))
#define sshfwd_hint_channel_is_simple(c) \
((c)->vt->hint_channel_is_simple(c))
static inline size_t sshfwd_write_ext(
SshChannel *c, bool is_stderr, const void *data, size_t len)
{ return c->vt->write(c, is_stderr, data, len); }
static inline size_t sshfwd_write(SshChannel *c, const void *data, size_t len)
{ return sshfwd_write_ext(c, false, data, len); }
static inline void sshfwd_write_eof(SshChannel *c)
{ c->vt->write_eof(c); }
static inline void sshfwd_initiate_close(SshChannel *c, const char *err)
{ c->vt->initiate_close(c, err); }
static inline void sshfwd_unthrottle(SshChannel *c, size_t bufsize)
{ c->vt->unthrottle(c, bufsize); }
static inline Conf *sshfwd_get_conf(SshChannel *c)
{ return c->vt->get_conf(c); }
static inline void sshfwd_window_override_removed(SshChannel *c)
{ c->vt->window_override_removed(c); }
static inline void sshfwd_x11_sharing_handover(
SshChannel *c, ssh_sharing_connstate *cs, share_channel *sch,
const char *addr, int port, int endian, int maj, int min,
const void *idata, int ilen)
{ return c->vt->x11_sharing_handover(c, cs, sch, addr, port, endian,
maj, min, idata, ilen); }
static inline void sshfwd_send_exit_status(SshChannel *c, int status)
{ c->vt->send_exit_status(c, status); }
static inline void sshfwd_send_exit_signal(
SshChannel *c, ptrlen signame, bool core_dumped, ptrlen msg)
{ c->vt->send_exit_signal(c, signame, core_dumped, msg); }
static inline void sshfwd_send_exit_signal_numeric(
SshChannel *c, int signum, bool core_dumped, ptrlen msg)
{ c->vt->send_exit_signal_numeric(c, signum, core_dumped, msg); }
static inline void sshfwd_request_x11_forwarding(
SshChannel *c, bool want_reply, const char *proto,
const char *data, int scr, bool once)
{ c->vt->request_x11_forwarding(c, want_reply, proto, data, scr, once); }
static inline void sshfwd_request_agent_forwarding(
SshChannel *c, bool want_reply)
{ c->vt->request_agent_forwarding(c, want_reply); }
static inline void sshfwd_request_pty(
SshChannel *c, bool want_reply, Conf *conf, int w, int h)
{ c->vt->request_pty(c, want_reply, conf, w, h); }
static inline bool sshfwd_send_env_var(
SshChannel *c, bool want_reply, const char *var, const char *value)
{ return c->vt->send_env_var(c, want_reply, var, value); }
static inline void sshfwd_start_shell(
SshChannel *c, bool want_reply)
{ c->vt->start_shell(c, want_reply); }
static inline void sshfwd_start_command(
SshChannel *c, bool want_reply, const char *command)
{ c->vt->start_command(c, want_reply, command); }
static inline bool sshfwd_start_subsystem(
SshChannel *c, bool want_reply, const char *subsystem)
{ return c->vt->start_subsystem(c, want_reply, subsystem); }
static inline bool sshfwd_send_serial_break(
SshChannel *c, bool want_reply, int length)
{ return c->vt->send_serial_break(c, want_reply, length); }
static inline bool sshfwd_send_signal(
SshChannel *c, bool want_reply, const char *signame)
{ return c->vt->send_signal(c, want_reply, signame); }
static inline void sshfwd_send_terminal_size_change(
SshChannel *c, int w, int h)
{ c->vt->send_terminal_size_change(c, w, h); }
static inline void sshfwd_hint_channel_is_simple(SshChannel *c)
{ c->vt->hint_channel_is_simple(c); }
/* ----------------------------------------------------------------------
* The 'main' or primary channel of the SSH connection is special,

View File

@ -59,14 +59,20 @@ struct PacketProtocolLayer {
unsigned remote_bugs;
};
#define ssh_ppl_process_queue(ppl) ((ppl)->vt->process_queue(ppl))
#define ssh_ppl_get_specials(ppl, add, ctx) \
((ppl)->vt->get_specials(ppl, add, ctx))
#define ssh_ppl_special_cmd(ppl, code, arg) \
((ppl)->vt->special_cmd(ppl, code, arg))
#define ssh_ppl_want_user_input(ppl) ((ppl)->vt->want_user_input(ppl))
#define ssh_ppl_got_user_input(ppl) ((ppl)->vt->got_user_input(ppl))
#define ssh_ppl_reconfigure(ppl, conf) ((ppl)->vt->reconfigure(ppl, conf))
static inline void ssh_ppl_process_queue(PacketProtocolLayer *ppl)
{ ppl->vt->process_queue(ppl); }
static inline bool ssh_ppl_get_specials(
PacketProtocolLayer *ppl, add_special_fn_t add_special, void *ctx)
{ return ppl->vt->get_specials(ppl, add_special, ctx); }
static inline void ssh_ppl_special_cmd(
PacketProtocolLayer *ppl, SessionSpecialCode code, int arg)
{ ppl->vt->special_cmd(ppl, code, arg); }
static inline bool ssh_ppl_want_user_input(PacketProtocolLayer *ppl)
{ return ppl->vt->want_user_input(ppl); }
static inline void ssh_ppl_got_user_input(PacketProtocolLayer *ppl)
{ ppl->vt->got_user_input(ppl); }
static inline void ssh_ppl_reconfigure(PacketProtocolLayer *ppl, Conf *conf)
{ ppl->vt->reconfigure(ppl, conf); }
/* ssh_ppl_free is more than just a macro wrapper on the vtable; it
* does centralised parts of the freeing too. */