1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +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, Socket *sk_newlistener(const char *srcaddr, int port, Plug *plug,
bool local_host_only, int address_family); bool local_host_only, int address_family);
#define sk_plug(s,p) (((s)->vt->plug) (s, p)) static inline Plug *sk_plug(Socket *s, Plug *p)
#define sk_close(s) (((s)->vt->close) (s)) { return s->vt->plug(s, p); }
#define sk_write(s,buf,len) (((s)->vt->write) (s, buf, len)) static inline void sk_close(Socket *s)
#define sk_write_oob(s,buf,len) (((s)->vt->write_oob) (s, buf, len)) { s->vt->close(s); }
#define sk_write_eof(s) (((s)->vt->write_eof) (s)) static inline size_t sk_write(Socket *s, const void *data, size_t len)
#define sk_flush(s) (((s)->vt->flush) (s)) { 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) \ static inline void plug_log(
(((p)->vt->log) (p, type, addr, port, msg, code)) Plug *p, int type, SockAddr *addr, int port, const char *msg, int code)
#define plug_closing(p,msg,code,callback) \ { return p->vt->log(p, type, addr, port, msg, code); }
(((p)->vt->closing) (p, msg, code, callback)) static inline void plug_closing(
#define plug_receive(p,urgent,buf,len) \ Plug *p, const char *msg, int code, bool calling_back)
(((p)->vt->receive) (p, urgent, buf, len)) { return p->vt->closing(p, msg, code, calling_back); }
#define plug_sent(p,bufsize) \ static inline void plug_receive(Plug *p, int urg, const char *data, size_t len)
(((p)->vt->sent) (p, bufsize)) { return p->vt->receive(p, urg, data, len); }
#define plug_accepting(p, constructor, ctx) \ static inline void plug_sent (Plug *p, size_t bufsize)
(((p)->vt->accepting)(p, constructor, ctx)) { 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 * 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. * or return NULL if there's no problem.
*/ */
const char *sk_addr_error(SockAddr *addr); 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 * 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 * associated local socket in order to avoid unbounded buffer
* growth. * 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 * 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 * not NULL, then it is dynamically allocated, and should be freed by
* a call to sk_free_peer_info(). See below for the definition. * 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 * 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; int default_port;
}; };
#define backend_init(vt, seat, out, logctx, conf, host, port, rhost, nd, ka) \ static inline const char *backend_init(
((vt)->init(seat, out, logctx, conf, host, port, rhost, nd, ka)) const BackendVtable *vt, Seat *seat, Backend **out, LogContext *logctx,
#define backend_free(be) ((be)->vt->free(be)) Conf *conf, const char *host, int port, char **rhost, bool nd, bool ka)
#define backend_reconfig(be, conf) ((be)->vt->reconfig(be, conf)) { return vt->init(seat, out, logctx, conf, host, port, rhost, nd, ka); }
#define backend_send(be, buf, len) ((be)->vt->send(be, buf, len)) static inline void backend_free(Backend *be)
#define backend_sendbuffer(be) ((be)->vt->sendbuffer(be)) { be->vt->free(be); }
#define backend_size(be, w, h) ((be)->vt->size(be, w, h)) static inline void backend_reconfig(Backend *be, Conf *conf)
#define backend_special(be, code, arg) ((be)->vt->special(be, code, arg)) { be->vt->reconfig(be, conf); }
#define backend_get_specials(be) ((be)->vt->get_specials(be)) static inline size_t backend_send(Backend *be, const char *buf, size_t len)
#define backend_connected(be) ((be)->vt->connected(be)) { return be->vt->send(be, buf, len); }
#define backend_exitcode(be) ((be)->vt->exitcode(be)) static inline size_t backend_sendbuffer(Backend *be)
#define backend_sendok(be) ((be)->vt->sendok(be)) { return be->vt->sendbuffer(be); }
#define backend_ldisc_option_state(be, opt) \ static inline void backend_size(Backend *be, int width, int height)
((be)->vt->ldisc_option_state(be, opt)) { be->vt->size(be, width, height); }
#define backend_provide_ldisc(be, ldisc) ((be)->vt->provide_ldisc(be, ldisc)) static inline void backend_special(
#define backend_unthrottle(be, bufsize) ((be)->vt->unthrottle(be, bufsize)) Backend *be, SessionSpecialCode code, int arg)
#define backend_cfg_info(be) ((be)->vt->cfg_info(be)) { 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[]; extern const struct BackendVtable *const backends[];
@ -915,36 +931,44 @@ struct SeatVtable {
bool (*get_window_pixel_size)(Seat *seat, int *width, int *height); bool (*get_window_pixel_size)(Seat *seat, int *width, int *height);
}; };
#define seat_output(seat, is_stderr, data, len) \ static inline size_t seat_output(
((seat)->vt->output(seat, is_stderr, data, len)) Seat *seat, bool err, const void *data, size_t len)
#define seat_eof(seat) \ { return seat->vt->output(seat, err, data, len); }
((seat)->vt->eof(seat)) static inline bool seat_eof(Seat *seat)
#define seat_get_userpass_input(seat, p, input) \ { return seat->vt->eof(seat); }
((seat)->vt->get_userpass_input(seat, p, input)) static inline int seat_get_userpass_input(
#define seat_notify_remote_exit(seat) \ Seat *seat, prompts_t *p, bufchain *input)
((seat)->vt->notify_remote_exit(seat)) { return seat->vt->get_userpass_input(seat, p, input); }
#define seat_update_specials_menu(seat) \ static inline void seat_notify_remote_exit(Seat *seat)
((seat)->vt->update_specials_menu(seat)) { seat->vt->notify_remote_exit(seat); }
#define seat_get_ttymode(seat, mode) \ static inline void seat_update_specials_menu(Seat *seat)
((seat)->vt->get_ttymode(seat, mode)) { seat->vt->update_specials_menu(seat); }
#define seat_set_busy_status(seat, status) \ static inline char *seat_get_ttymode(Seat *seat, const char *mode)
((seat)->vt->set_busy_status(seat, status)) { return seat->vt->get_ttymode(seat, mode); }
#define seat_verify_ssh_host_key(seat, h, p, typ, str, fp, cb, ctx) \ static inline void seat_set_busy_status(Seat *seat, BusyStatus status)
((seat)->vt->verify_ssh_host_key(seat, h, p, typ, str, fp, cb, ctx)) { seat->vt->set_busy_status(seat, status); }
#define seat_confirm_weak_crypto_primitive(seat, typ, alg, cb, ctx) \ static inline int seat_verify_ssh_host_key(
((seat)->vt->confirm_weak_crypto_primitive(seat, typ, alg, cb, ctx)) Seat *seat, const char *h, int p, const char *ktyp, char *kstr,
#define seat_confirm_weak_cached_hostkey(seat, alg, better, cb, ctx) \ char *fp, void (*cb)(void *ctx, int result), void *ctx)
((seat)->vt->confirm_weak_cached_hostkey(seat, alg, better, cb, ctx)) { return seat->vt->verify_ssh_host_key(seat, h, p, ktyp, kstr, fp, cb, ctx); }
#define seat_is_utf8(seat) \ static inline int seat_confirm_weak_crypto_primitive(
((seat)->vt->is_utf8(seat)) Seat *seat, const char *atyp, const char *aname,
#define seat_echoedit_update(seat, echoing, editing) \ void (*cb)(void *ctx, int result), void *ctx)
((seat)->vt->echoedit_update(seat, echoing, editing)) { return seat->vt->confirm_weak_crypto_primitive(seat, atyp, aname, cb, ctx); }
#define seat_get_x_display(seat) \ static inline int seat_confirm_weak_cached_hostkey(
((seat)->vt->get_x_display(seat)) Seat *seat, const char *aname, const char *better,
#define seat_get_windowid(seat, out) \ void (*cb)(void *ctx, int result), void *ctx)
((seat)->vt->get_windowid(seat, out)) { return seat->vt->confirm_weak_cached_hostkey(seat, aname, better, cb, ctx); }
#define seat_get_window_pixel_size(seat, width, height) \ static inline bool seat_is_utf8(Seat *seat)
((seat)->vt->get_window_pixel_size(seat, width, height)) { 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 /* Unlike the seat's actual method, the public entry point
* seat_connection_fatal is a wrapper function with a printf-like API, * 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, ...); void seat_connection_fatal(Seat *seat, const char *fmt, ...);
/* Handy aliases for seat_output which set is_stderr to a fixed value. */ /* Handy aliases for seat_output which set is_stderr to a fixed value. */
#define seat_stdout(seat, data, len) \ static inline size_t seat_stdout(Seat *seat, const void *data, size_t len)
seat_output(seat, false, data, len) { return seat_output(seat, false, data, len); }
#define seat_stderr(seat, data, len) \ static inline size_t seat_stderr(Seat *seat, const void *data, size_t len)
seat_output(seat, true, data, len) { return seat_output(seat, true, data, len); }
/* /*
* Stub methods for seat implementations that want to use the obvious * Stub methods for seat implementations that want to use the obvious
@ -1083,60 +1107,66 @@ struct TermWinVtable {
bool (*is_utf8)(TermWin *); bool (*is_utf8)(TermWin *);
}; };
#define win_setup_draw_ctx(win) \ static inline bool win_setup_draw_ctx(TermWin *win)
((win)->vt->setup_draw_ctx(win)) { return win->vt->setup_draw_ctx(win); }
#define win_draw_text(win, x, y, text, len, attrs, lattrs, tc) \ static inline void win_draw_text(
((win)->vt->draw_text(win, x, y, text, len, attrs, lattrs, tc)) TermWin *win, int x, int y, wchar_t *text, int len,
#define win_draw_cursor(win, x, y, text, len, attrs, lattrs, tc) \ unsigned long attrs, int line_attrs, truecolour tc)
((win)->vt->draw_cursor(win, x, y, text, len, attrs, lattrs, tc)) { win->vt->draw_text(win, x, y, text, len, attrs, line_attrs, tc); }
#define win_char_width(win, uc) \ static inline void win_draw_cursor(
((win)->vt->char_width(win, uc)) TermWin *win, int x, int y, wchar_t *text, int len,
#define win_free_draw_ctx(win) \ unsigned long attrs, int line_attrs, truecolour tc)
((win)->vt->free_draw_ctx(win)) { win->vt->draw_cursor(win, x, y, text, len, attrs, line_attrs, tc); }
#define win_set_cursor_pos(win, x, y) \ static inline int win_char_width(TermWin *win, int uc)
((win)->vt->set_cursor_pos(win, x, y)) { return win->vt->char_width(win, uc); }
#define win_set_raw_mouse_mode(win, enable) \ static inline void win_free_draw_ctx(TermWin *win)
((win)->vt->set_raw_mouse_mode(win, enable)) { win->vt->free_draw_ctx(win); }
#define win_set_scrollbar(win, total, start, page) \ static inline void win_set_cursor_pos(TermWin *win, int x, int y)
((win)->vt->set_scrollbar(win, total, start, page)) { win->vt->set_cursor_pos(win, x, y); }
#define win_bell(win, mode) \ static inline void win_set_raw_mouse_mode(TermWin *win, bool enable)
((win)->vt->bell(win, mode)) { win->vt->set_raw_mouse_mode(win, enable); }
#define win_clip_write(win, clipboard, text, attrs, colours, len, desel) \ static inline void win_set_scrollbar(TermWin *win, int t, int s, int p)
((win)->vt->clip_write(win, clipboard, text, attrs, colours, len, desel)) { win->vt->set_scrollbar(win, t, s, p); }
#define win_clip_request_paste(win, clipboard) \ static inline void win_bell(TermWin *win, int mode)
((win)->vt->clip_request_paste(win, clipboard)) { win->vt->bell(win, mode); }
#define win_refresh(win) \ static inline void win_clip_write(
((win)->vt->refresh(win)) TermWin *win, int clipboard, wchar_t *text, int *attrs,
#define win_request_resize(win, w, h) \ truecolour *colours, int len, bool deselect)
((win)->vt->request_resize(win, w, h)) { win->vt->clip_write(win, clipboard, text, attrs, colours, len, deselect); }
#define win_set_title(win, title) \ static inline void win_clip_request_paste(TermWin *win, int clipboard)
((win)->vt->set_title(win, title)) { win->vt->clip_request_paste(win, clipboard); }
#define win_set_icon_title(win, ititle) \ static inline void win_refresh(TermWin *win)
((win)->vt->set_icon_title(win, ititle)) { win->vt->refresh(win); }
#define win_set_minimised(win, minimised) \ static inline void win_request_resize(TermWin *win, int w, int h)
((win)->vt->set_minimised(win, minimised)) { win->vt->request_resize(win, w, h); }
#define win_is_minimised(win) \ static inline void win_set_title(TermWin *win, const char *title)
((win)->vt->is_minimised(win)) { win->vt->set_title(win, title); }
#define win_set_maximised(win, maximised) \ static inline void win_set_icon_title(TermWin *win, const char *icontitle)
((win)->vt->set_maximised(win, maximised)) { win->vt->set_icon_title(win, icontitle); }
#define win_move(win, x, y) \ static inline void win_set_minimised(TermWin *win, bool minimised)
((win)->vt->move(win, x, y)) { win->vt->set_minimised(win, minimised); }
#define win_set_zorder(win, top) \ static inline bool win_is_minimised(TermWin *win)
((win)->vt->set_zorder(win, top)) { return win->vt->is_minimised(win); }
#define win_palette_get(win, n, r, g, b) \ static inline void win_set_maximised(TermWin *win, bool maximised)
((win)->vt->palette_get(win, n, r, g, b)) { win->vt->set_maximised(win, maximised); }
#define win_palette_set(win, n, r, g, b) \ static inline void win_move(TermWin *win, int x, int y)
((win)->vt->palette_set(win, n, r, g, b)) { win->vt->move(win, x, y); }
#define win_palette_reset(win) \ static inline void win_set_zorder(TermWin *win, bool top)
((win)->vt->palette_reset(win)) { win->vt->set_zorder(win, top); }
#define win_get_pos(win, x, y) \ static inline bool win_palette_get(TermWin *win, int n, int *r, int *g, int *b)
((win)->vt->get_pos(win, x, y)) { return win->vt->palette_get(win, n, r, g, b); }
#define win_get_pixels(win, x, y) \ static inline void win_palette_set(TermWin *win, int n, int r, int g, int b)
((win)->vt->get_pixels(win, x, y)) { win->vt->palette_set(win, n, r, g, b); }
#define win_get_title(win, icon) \ static inline void win_palette_reset(TermWin *win)
((win)->vt->get_title(win, icon)) { win->vt->palette_reset(win); }
#define win_is_utf8(win) \ static inline void win_get_pos(TermWin *win, int *x, int *y)
((win)->vt->is_utf8(win)) { 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. * Global functions not specific to a connection instance.
@ -1606,9 +1636,15 @@ struct LogPolicyVtable {
struct LogPolicy { struct LogPolicy {
const LogPolicyVtable *vt; 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)) static inline void lp_eventlog(LogPolicy *lp, const char *event)
#define lp_logging_error(lp, event) ((lp)->vt->logging_error(lp, 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); LogContext *log_init(LogPolicy *lp, Conf *conf);
void log_free(LogContext *logctx); void log_free(LogContext *logctx);

134
sftp.h
View File

@ -390,40 +390,58 @@ struct SftpServerVtable {
int max_entries, bool omit_longname); int max_entries, bool omit_longname);
}; };
#define sftpsrv_new(vt) \ static inline SftpServer *sftpsrv_new(const SftpServerVtable *vt)
((vt)->new(vt)) { return vt->new(vt); }
#define sftpsrv_free(srv) \ static inline void sftpsrv_free(SftpServer *srv)
((srv)->vt->free(srv)) { srv->vt->free(srv); }
#define sftpsrv_realpath(srv, reply, path) \ static inline void sftpsrv_realpath(SftpServer *srv, SftpReplyBuilder *reply,
((srv)->vt->realpath(srv, reply, path)) ptrlen path)
#define sftpsrv_open(srv, reply, path, flags, attrs) \ { srv->vt->realpath(srv, reply, path); }
((srv)->vt->open(srv, reply, path, flags, attrs)) static inline void sftpsrv_open(
#define sftpsrv_opendir(srv, reply, path) \ SftpServer *srv, SftpReplyBuilder *reply,
((srv)->vt->opendir(srv, reply, path)) ptrlen path, unsigned flags, struct fxp_attrs attrs)
#define sftpsrv_close(srv, reply, handle) \ { srv->vt->open(srv, reply, path, flags, attrs); }
((srv)->vt->close(srv, reply, handle)) static inline void sftpsrv_opendir(
#define sftpsrv_mkdir(srv, reply, path, attrs) \ SftpServer *srv, SftpReplyBuilder *reply, ptrlen path)
((srv)->vt->mkdir(srv, reply, path, attrs)) { srv->vt->opendir(srv, reply, path); }
#define sftpsrv_rmdir(srv, reply, path) \ static inline void sftpsrv_close(
((srv)->vt->rmdir(srv, reply, path)) SftpServer *srv, SftpReplyBuilder *reply, ptrlen handle)
#define sftpsrv_remove(srv, reply, path) \ { srv->vt->close(srv, reply, handle); }
((srv)->vt->remove(srv, reply, path)) static inline void sftpsrv_mkdir(SftpServer *srv, SftpReplyBuilder *reply,
#define sftpsrv_rename(srv, reply, srcpath, dstpath) \ ptrlen path, struct fxp_attrs attrs)
((srv)->vt->rename(srv, reply, srcpath, dstpath)) { srv->vt->mkdir(srv, reply, path, attrs); }
#define sftpsrv_stat(srv, reply, path, follow) \ static inline void sftpsrv_rmdir(
((srv)->vt->stat(srv, reply, path, follow)) SftpServer *srv, SftpReplyBuilder *reply, ptrlen path)
#define sftpsrv_fstat(srv, reply, handle) \ { srv->vt->rmdir(srv, reply, path); }
((srv)->vt->fstat(srv, reply, handle)) static inline void sftpsrv_remove(
#define sftpsrv_setstat(srv, reply, path, attrs) \ SftpServer *srv, SftpReplyBuilder *reply, ptrlen path)
((srv)->vt->setstat(srv, reply, path, attrs)) { srv->vt->remove(srv, reply, path); }
#define sftpsrv_fsetstat(srv, reply, handle, attrs) \ static inline void sftpsrv_rename(SftpServer *srv, SftpReplyBuilder *reply,
((srv)->vt->fsetstat(srv, reply, handle, attrs)) ptrlen srcpath, ptrlen dstpath)
#define sftpsrv_read(srv, reply, handle, offset, length) \ { srv->vt->rename(srv, reply, srcpath, dstpath); }
((srv)->vt->read(srv, reply, handle, offset, length)) static inline void sftpsrv_stat(
#define sftpsrv_write(srv, reply, handle, offset, data) \ SftpServer *srv, SftpReplyBuilder *reply, ptrlen path, bool follow)
((srv)->vt->write(srv, reply, handle, offset, data)) { srv->vt->stat(srv, reply, path, follow); }
#define sftpsrv_readdir(srv, reply, handle, max, nolongname) \ static inline void sftpsrv_fstat(
((srv)->vt->readdir(srv, reply, handle, max, nolongname)) 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; typedef struct SftpReplyBuilderVtable SftpReplyBuilderVtable;
struct SftpReplyBuilder { struct SftpReplyBuilder {
@ -442,22 +460,26 @@ struct SftpReplyBuilderVtable {
void (*reply_attrs)(SftpReplyBuilder *reply, struct fxp_attrs attrs); void (*reply_attrs)(SftpReplyBuilder *reply, struct fxp_attrs attrs);
}; };
#define fxp_reply_ok(reply) \ static inline void fxp_reply_ok(SftpReplyBuilder *reply)
((reply)->vt->reply_ok(reply)) { reply->vt->reply_ok(reply); }
#define fxp_reply_error(reply, code, msg) \ static inline void fxp_reply_error(SftpReplyBuilder *reply, unsigned code,
((reply)->vt->reply_error(reply, code, msg)) const char *msg)
#define fxp_reply_simple_name(reply, name) \ { reply->vt->reply_error(reply, code, msg); }
((reply)->vt->reply_simple_name(reply, name)) static inline void fxp_reply_simple_name(SftpReplyBuilder *reply, ptrlen name)
#define fxp_reply_name_count(reply, count) \ { reply->vt->reply_simple_name(reply, name); }
((reply)->vt->reply_name_count(reply, count)) static inline void fxp_reply_name_count(
#define fxp_reply_full_name(reply, name, longname, attrs) \ SftpReplyBuilder *reply, unsigned count)
((reply)->vt->reply_full_name(reply, name, longname, attrs)) { reply->vt->reply_name_count(reply, count); }
#define fxp_reply_handle(reply, handle) \ static inline void fxp_reply_full_name(SftpReplyBuilder *reply, ptrlen name,
((reply)->vt->reply_handle(reply, handle)) ptrlen longname, struct fxp_attrs attrs)
#define fxp_reply_data(reply, data) \ { reply->vt->reply_full_name(reply, name, longname, attrs); }
((reply)->vt->reply_data(reply, data)) static inline void fxp_reply_handle(SftpReplyBuilder *reply, ptrlen handle)
#define fxp_reply_attrs(reply, attrs) \ { reply->vt->reply_handle(reply, handle); }
((reply)->vt->reply_attrs(reply, attrs)) 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 * The usual implementation of an SftpReplyBuilder, containing a
@ -499,10 +521,14 @@ struct ScpServerVtable {
void (*eof)(ScpServer *s); void (*eof)(ScpServer *s);
}; };
#define scp_free(s) ((s)->vt->free(s)) static inline void scp_free(ScpServer *s)
#define scp_send(s, data, len) ((s)->vt->send(s, data, len)) { s->vt->free(s); }
#define scp_throttle(s, th) ((s)->vt->throttle(s, th)) static inline size_t scp_send(ScpServer *s, const void *data, size_t length)
#define scp_eof(s) ((s)->vt->eof(s)) { 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 * 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; const struct ConnectionLayerVtable *vt;
}; };
#define ssh_rportfwd_alloc(cl, sh, sp, dh, dp, af, ld, pfr, share) \ static inline struct ssh_rportfwd *ssh_rportfwd_alloc(
((cl)->vt->rportfwd_alloc(cl, sh, sp, dh, dp, af, ld, pfr, share)) ConnectionLayer *cl, const char *sh, int sp, const char *dh, int dp,
#define ssh_rportfwd_remove(cl, rpf) ((cl)->vt->rportfwd_remove(cl, rpf)) int af, const char *log, PortFwdRecord *pfr, ssh_sharing_connstate *cs)
#define ssh_lportfwd_open(cl, h, p, desc, pi, chan) \ { return cl->vt->rportfwd_alloc(cl, sh, sp, dh, dp, af, log, pfr, cs); }
((cl)->vt->lportfwd_open(cl, h, p, desc, pi, chan)) static inline void ssh_rportfwd_remove(
#define ssh_serverside_x11_open(cl, chan, pi) \ ConnectionLayer *cl, struct ssh_rportfwd *rpf)
((cl)->vt->serverside_x11_open(cl, chan, pi)) { cl->vt->rportfwd_remove(cl, rpf); }
#define ssh_serverside_agent_open(cl, chan) \ static inline SshChannel *ssh_lportfwd_open(
((cl)->vt->serverside_agent_open(cl, chan)) ConnectionLayer *cl, const char *host, int port,
#define ssh_session_open(cl, chan) \ const char *desc, const SocketPeerInfo *pi, Channel *chan)
((cl)->vt->session_open(cl, chan)) { return cl->vt->lportfwd_open(cl, host, port, desc, pi, chan); }
#define ssh_add_x11_display(cl, auth, disp) \ static inline SshChannel *ssh_session_open(ConnectionLayer *cl, Channel *chan)
((cl)->vt->add_x11_display(cl, auth, disp)) { return cl->vt->session_open(cl, chan); }
#define ssh_add_sharing_x11_display(cl, auth, cs, ch) \ static inline SshChannel *ssh_serverside_x11_open(
((cl)->vt->add_sharing_x11_display(cl, auth, cs, ch)) ConnectionLayer *cl, Channel *chan, const SocketPeerInfo *pi)
#define ssh_remove_sharing_x11_display(cl, fa) \ { return cl->vt->serverside_x11_open(cl, chan, pi); }
((cl)->vt->remove_sharing_x11_display(cl, fa)) static inline SshChannel *ssh_serverside_agent_open(
#define ssh_send_packet_from_downstream(cl, id, type, pkt, len, log) \ ConnectionLayer *cl, Channel *chan)
((cl)->vt->send_packet_from_downstream(cl, id, type, pkt, len, log)) { return cl->vt->serverside_agent_open(cl, chan); }
#define ssh_alloc_sharing_channel(cl, cs) \ static inline struct X11FakeAuth *ssh_add_x11_display(
((cl)->vt->alloc_sharing_channel(cl, cs)) ConnectionLayer *cl, int authtype, struct X11Display *x11disp)
#define ssh_delete_sharing_channel(cl, ch) \ { return cl->vt->add_x11_display(cl, authtype, x11disp); }
((cl)->vt->delete_sharing_channel(cl, ch)) static inline struct X11FakeAuth *ssh_add_sharing_x11_display(
#define ssh_sharing_queue_global_request(cl, cs) \ ConnectionLayer *cl, int authtype, ssh_sharing_connstate *share_cs,
((cl)->vt->sharing_queue_global_request(cl, cs)) share_channel *share_chan)
#define ssh_sharing_no_more_downstreams(cl) \ { return cl->vt->add_sharing_x11_display(cl, authtype, share_cs, share_chan); }
((cl)->vt->sharing_no_more_downstreams(cl)) static inline void ssh_remove_sharing_x11_display(
#define ssh_agent_forwarding_permitted(cl) \ ConnectionLayer *cl, struct X11FakeAuth *auth)
((cl)->vt->agent_forwarding_permitted(cl)) { cl->vt->remove_sharing_x11_display(cl, auth); }
#define ssh_terminal_size(cl, w, h) ((cl)->vt->terminal_size(cl, w, h)) static inline void ssh_send_packet_from_downstream(
#define ssh_stdout_unthrottle(cl, bufsize) \ ConnectionLayer *cl, unsigned id, int type,
((cl)->vt->stdout_unthrottle(cl, bufsize)) const void *pkt, int len, const char *log)
#define ssh_stdin_backlog(cl) ((cl)->vt->stdin_backlog(cl)) { cl->vt->send_packet_from_downstream(cl, id, type, pkt, len, log); }
#define ssh_throttle_all_channels(cl, throttled) \ static inline unsigned ssh_alloc_sharing_channel(
((cl)->vt->throttle_all_channels(cl, throttled)) ConnectionLayer *cl, ssh_sharing_connstate *connstate)
#define ssh_ldisc_option(cl, option) ((cl)->vt->ldisc_option(cl, option)) { return cl->vt->alloc_sharing_channel(cl, connstate); }
#define ssh_set_ldisc_option(cl, opt, val) \ static inline void ssh_delete_sharing_channel(
((cl)->vt->set_ldisc_option(cl, opt, val)) ConnectionLayer *cl, unsigned localid)
#define ssh_enable_x_fwd(cl) ((cl)->vt->enable_x_fwd(cl)) { cl->vt->delete_sharing_channel(cl, localid); }
#define ssh_enable_agent_fwd(cl) ((cl)->vt->enable_agent_fwd(cl)) static inline void ssh_sharing_queue_global_request(
#define ssh_set_wants_user_input(cl, wanted) \ ConnectionLayer *cl, ssh_sharing_connstate *connstate)
((cl)->vt->set_wants_user_input(cl, wanted)) { cl->vt->sharing_queue_global_request(cl, connstate); }
#define ssh_setup_server_x_forwarding(cl, conf, ap, ad, scr) \ static inline void ssh_sharing_no_more_downstreams(ConnectionLayer *cl)
((cl)->vt->setup_server_x_forwarding(cl, conf, ap, ad, scr)) { 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 */ /* Exports from portfwd.c */
PortFwdManager *portfwdmgr_new(ConnectionLayer *cl); PortFwdManager *portfwdmgr_new(ConnectionLayer *cl);
@ -600,17 +620,26 @@ struct ssh_cipheralg {
const void *extra; const void *extra;
}; };
#define ssh_cipher_new(alg) ((alg)->new(alg)) static inline ssh_cipher *ssh_cipher_new(const ssh_cipheralg *alg)
#define ssh_cipher_free(ctx) ((ctx)->vt->free(ctx)) { return alg->new(alg); }
#define ssh_cipher_setiv(ctx, iv) ((ctx)->vt->setiv(ctx, iv)) static inline void ssh_cipher_free(ssh_cipher *c)
#define ssh_cipher_setkey(ctx, key) ((ctx)->vt->setkey(ctx, key)) { c->vt->free(c); }
#define ssh_cipher_encrypt(ctx, blk, len) ((ctx)->vt->encrypt(ctx, blk, len)) static inline void ssh_cipher_setiv(ssh_cipher *c, const void *iv)
#define ssh_cipher_decrypt(ctx, blk, len) ((ctx)->vt->decrypt(ctx, blk, len)) { c->vt->setiv(c, iv); }
#define ssh_cipher_encrypt_length(ctx, blk, len, seq) \ static inline void ssh_cipher_setkey(ssh_cipher *c, const void *key)
((ctx)->vt->encrypt_length(ctx, blk, len, seq)) { c->vt->setkey(c, key); }
#define ssh_cipher_decrypt_length(ctx, blk, len, seq) \ static inline void ssh_cipher_encrypt(ssh_cipher *c, void *blk, int len)
((ctx)->vt->decrypt_length(ctx, blk, len, seq)) { c->vt->encrypt(c, blk, len); }
#define ssh_cipher_alg(ctx) ((ctx)->vt) 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 { struct ssh2_ciphers {
int nciphers; int nciphers;
@ -637,13 +666,21 @@ struct ssh2_macalg {
const void *extra; const void *extra;
}; };
#define ssh2_mac_new(alg, cipher) ((alg)->new(alg, cipher)) static inline ssh2_mac *ssh2_mac_new(
#define ssh2_mac_free(ctx) ((ctx)->vt->free(ctx)) const ssh2_macalg *alg, ssh_cipher *cipher)
#define ssh2_mac_setkey(ctx, key) ((ctx)->vt->setkey(ctx, key)) { return alg->new(alg, cipher); }
#define ssh2_mac_start(ctx) ((ctx)->vt->start(ctx)) static inline void ssh2_mac_free(ssh2_mac *m)
#define ssh2_mac_genresult(ctx, out) ((ctx)->vt->genresult(ctx, out)) { m->vt->free(m); }
#define ssh2_mac_text_name(ctx) ((ctx)->vt->text_name(ctx)) static inline void ssh2_mac_setkey(ssh2_mac *m, ptrlen key)
#define ssh2_mac_alg(ctx) ((ctx)->vt) { 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 /* 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 * 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)" */ const char *text_name; /* both combined, e.g. "SHA-n (unaccelerated)" */
}; };
#define ssh_hash_new(alg) ((alg)->new(alg)) static inline ssh_hash *ssh_hash_new(const ssh_hashalg *alg)
#define ssh_hash_copy(ctx) ((ctx)->vt->copy(ctx)) { return alg->new(alg); }
#define ssh_hash_final(ctx, out) ((ctx)->vt->final(ctx, out)) static inline ssh_hash *ssh_hash_copy(ssh_hash *h)
#define ssh_hash_free(ctx) ((ctx)->vt->free(ctx)) { return h->vt->copy(h); }
#define ssh_hash_alg(ctx) ((ctx)->vt) 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 */ /* Handy macros for defining all those text-name fields at once */
#define HASHALG_NAMES_BARE(base) \ #define HASHALG_NAMES_BARE(base) \
@ -725,25 +767,39 @@ struct ssh_keyalg {
const unsigned supported_flags; /* signature-type flags we understand */ const unsigned supported_flags; /* signature-type flags we understand */
}; };
#define ssh_key_new_pub(alg, data) ((alg)->new_pub(alg, data)) static inline ssh_key *ssh_key_new_pub(const ssh_keyalg *self, ptrlen pub)
#define ssh_key_new_priv(alg, pub, priv) ((alg)->new_priv(alg, pub, priv)) { return self->new_pub(self, pub); }
#define ssh_key_new_priv_openssh(alg, bs) ((alg)->new_priv_openssh(alg, bs)) static inline ssh_key *ssh_key_new_priv(
const ssh_keyalg *self, ptrlen pub, ptrlen priv)
#define ssh_key_free(key) ((key)->vt->freekey(key)) { return self->new_priv(self, pub, priv); }
#define ssh_key_invalid(key, flags) ((key)->vt->invalid(key, flags)) static inline ssh_key *ssh_key_new_priv_openssh(
#define ssh_key_sign(key, data, flags, bs) \ const ssh_keyalg *self, BinarySource *src)
((key)->vt->sign(key, data, flags, bs)) { return self->new_priv_openssh(self, src); }
#define ssh_key_verify(key, sig, data) ((key)->vt->verify(key, sig, data)) static inline void ssh_key_free(ssh_key *key)
#define ssh_key_public_blob(key, bs) ((key)->vt->public_blob(key, bs)) { key->vt->freekey(key); }
#define ssh_key_private_blob(key, bs) ((key)->vt->private_blob(key, bs)) static inline char *ssh_key_invalid(ssh_key *key, unsigned flags)
#define ssh_key_openssh_blob(key, bs) ((key)->vt->openssh_blob(key, bs)) { return key->vt->invalid(key, flags); }
#define ssh_key_cache_str(key) ((key)->vt->cache_str(key)) static inline void ssh_key_sign(
ssh_key *key, ptrlen data, unsigned flags, BinarySink *bs)
#define ssh_key_public_bits(alg, blob) ((alg)->pubkey_bits(alg, blob)) { key->vt->sign(key, data, flags, bs); }
static inline bool ssh_key_verify(ssh_key *key, ptrlen sig, ptrlen data)
#define ssh_key_alg(key) (key)->vt { return key->vt->verify(key, sig, data); }
#define ssh_key_ssh_id(key) ((key)->vt->ssh_id) static inline void ssh_key_public_blob(ssh_key *key, BinarySink *bs)
#define ssh_key_cache_id(key) ((key)->vt->cache_id) { 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 * Enumeration of signature flags from draft-miller-ssh-agent-02
@ -775,16 +831,30 @@ struct ssh_compression_alg {
const char *text_name; const char *text_name;
}; };
#define ssh_compressor_new(alg) ((alg)->compress_new()) static inline ssh_compressor *ssh_compressor_new(
#define ssh_compressor_free(comp) ((comp)->vt->compress_free(comp)) const ssh_compression_alg *alg)
#define ssh_compressor_compress(comp, in, inlen, out, outlen, minlen) \ { return alg->compress_new(); }
((comp)->vt->compress(comp, in, inlen, out, outlen, minlen)) static inline ssh_decompressor *ssh_decompressor_new(
#define ssh_compressor_alg(comp) ((comp)->vt) const ssh_compression_alg *alg)
#define ssh_decompressor_new(alg) ((alg)->decompress_new()) { return alg->decompress_new(); }
#define ssh_decompressor_free(comp) ((comp)->vt->decompress_free(comp)) static inline void ssh_compressor_free(ssh_compressor *c)
#define ssh_decompressor_decompress(comp, in, inlen, out, outlen) \ { c->vt->compress_free(c); }
((comp)->vt->decompress(comp, in, inlen, out, outlen)) static inline void ssh_decompressor_free(ssh_decompressor *d)
#define ssh_decompressor_alg(comp) ((comp)->vt) { 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 { struct ssh2_userkey {
ssh_key *key; /* the key itself */ ssh_key *key; /* the key itself */

View File

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

188
sshchan.h
View File

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

View File

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