X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/d57f70afa40c24426e5f936c86f7640801d43f7a..76347f46fb70138ad34af07b2ab00625600931f1:/putty.h diff --git a/putty.h b/putty.h index 4b0e3fef..0b49dfa8 100644 --- a/putty.h +++ b/putty.h @@ -314,6 +314,16 @@ enum { FUNKY_SCO }; +enum { + /* + * Network address types. Used for specifying choice of IPv4/v6 + * in config; also used in proxy.c to indicate whether a given + * host name has already been resolved or will be resolved at + * the proxy end. + */ + ADDRTYPE_UNSPEC, ADDRTYPE_IPV4, ADDRTYPE_IPV6, ADDRTYPE_NAME +}; + struct backend_tag { const char *(*init) (void *frontend_handle, void **backend_handle, Config *cfg, @@ -340,6 +350,7 @@ struct backend_tag { * buffer is clearing. */ void (*unthrottle) (void *handle, int); + int (*cfg_info) (void *handle); int default_port; }; @@ -374,6 +385,7 @@ struct config_tag { char host[512]; int port; int protocol; + int addressfamily; int close_on_exit; int warn_on_close; int ping_interval; /* in seconds */ @@ -528,7 +540,7 @@ struct config_tag { /* SSH bug compatibility modes */ int sshbug_ignore1, sshbug_plainpw1, sshbug_rsa1, sshbug_hmac2, sshbug_derivekey2, sshbug_rsapad2, - sshbug_pksessid2; + sshbug_pksessid2, sshbug_rekey2; /* Options for pterm. Should split out into platform-dependent part. */ int stamp_utmp; int login_shell; @@ -635,6 +647,16 @@ int is_iconic(void *frontend); void get_window_pos(void *frontend, int *x, int *y); void get_window_pixels(void *frontend, int *x, int *y); char *get_window_title(void *frontend, int icon); +/* Hint from backend to frontend about time-consuming operations. + * Initial state is assumed to be BUSY_NOT. */ +enum { + BUSY_NOT, /* Not busy, all user interaction OK */ + BUSY_WAITING, /* Waiting for something; local event loops still running + so some local interaction (e.g. menus) OK, but network + stuff is suspended */ + BUSY_CPU /* Locally busy (e.g. crypto); user interaction suspended */ +}; +void set_busy_status(void *frontend, int status); void cleanup_exit(int); @@ -920,7 +942,7 @@ void cmdline_error(char *, ...); */ struct controlbox; void setup_config_box(struct controlbox *b, struct sesslist *sesslist, - int midsession, int protocol); + int midsession, int protocol, int protcfginfo); /* * Exports from minibidi.c. @@ -981,6 +1003,67 @@ char *get_random_data(int bytes); /* used in cmdgen.c */ * notifies the front end that a new timer has been added to the * list which is sooner than any existing ones. It provides the * time when that timer needs to go off. + * + * *** FRONT END IMPLEMENTORS NOTE: + * + * There's an important subtlety in the front-end implementation of + * the timer interface. When a front end is given a `next' value, + * either returned from run_timers() or via timer_change_notify(), + * it should ensure that it really passes _that value_ as the `now' + * parameter to its next run_timers call. It should _not_ simply + * call GETTICKCOUNT() to get the `now' parameter when invoking + * run_timers(). + * + * The reason for this is that an OS's system clock might not agree + * exactly with the timing mechanisms it supplies to wait for a + * given interval. I'll illustrate this by the simple example of + * Unix Plink, which uses timeouts to select() in a way which for + * these purposes can simply be considered to be a wait() function. + * Suppose, for the sake of argument, that this wait() function + * tends to return early by 1%. Then a possible sequence of actions + * is: + * + * - run_timers() tells the front end that the next timer firing + * is 10000ms from now. + * - Front end calls wait(10000ms), but according to + * GETTICKCOUNT() it has only waited for 9900ms. + * - Front end calls run_timers() again, passing time T-100ms as + * `now'. + * - run_timers() does nothing, and says the next timer firing is + * still 100ms from now. + * - Front end calls wait(100ms), which only waits for 99ms. + * - Front end calls run_timers() yet again, passing time T-1ms. + * - run_timers() says there's still 1ms to wait. + * - Front end calls wait(1ms). + * + * If you're _lucky_ at this point, wait(1ms) will actually wait + * for 1ms and you'll only have woken the program up three times. + * If you're unlucky, wait(1ms) might do nothing at all due to + * being below some minimum threshold, and you might find your + * program spends the whole of the last millisecond tight-looping + * between wait() and run_timers(). + * + * Instead, what you should do is to _save_ the precise `next' + * value provided by run_timers() or via timer_change_notify(), and + * use that precise value as the input to the next run_timers() + * call. So: + * + * - run_timers() tells the front end that the next timer firing + * is at time T, 10000ms from now. + * - Front end calls wait(10000ms). + * - Front end then immediately calls run_timers() and passes it + * time T, without stopping to check GETTICKCOUNT() at all. + * + * This guarantees that the program wakes up only as many times as + * there are actual timer actions to be taken, and that the timing + * mechanism will never send it into a tight loop. + * + * (It does also mean that the timer action in the above example + * will occur 100ms early, but this is not generally critical. And + * the hypothetical 1% error in wait() will be partially corrected + * for anyway when, _after_ run_timers() returns, you call + * GETTICKCOUNT() and compare the result with the returned `next' + * value to find out how long you have to make your next wait().) */ typedef void (*timer_fn_t)(void *ctx, long now); long schedule_timer(int ticks, timer_fn_t fn, void *ctx);