| 1 | \# This file is so named for tradition's sake: it contains what we |
| 2 | \# always used to refer to, before they were written down, as |
| 3 | \# PuTTY's `unwritten design principles'. It has nothing to do with |
| 4 | \# the User Datagram Protocol. |
| 5 | |
| 6 | \define{versionidudp} \versionid $Id$ |
| 7 | |
| 8 | \A{udp} PuTTY hacking guide |
| 9 | |
| 10 | This appendix lists a selection of the design principles applying to |
| 11 | the PuTTY source code. If you are planning to send code |
| 12 | contributions, you should read this first. |
| 13 | |
| 14 | \H{udp-portability} Cross-OS portability |
| 15 | |
| 16 | Despite Windows being its main area of fame, PuTTY is no longer a |
| 17 | Windows-only application suite. It has a working Unix port; a Mac |
| 18 | port is in progress; more ports may or may not happen at a later |
| 19 | date. |
| 20 | |
| 21 | Therefore, embedding Windows-specific code in core modules such as |
| 22 | \cw{ssh.c} is not acceptable. We went to great lengths to \e{remove} |
| 23 | all the Windows-specific stuff from our core modules, and to shift |
| 24 | it out into Windows-specific modules. Adding large amounts of |
| 25 | Windows-specific stuff in parts of the code that should be portable |
| 26 | is almost guaranteed to make us reject a contribution. |
| 27 | |
| 28 | The PuTTY source base is divided into platform-specific modules and |
| 29 | platform-generic modules. The Unix-specific modules are all in the |
| 30 | \c{unix} subdirectory; the Mac-specific modules are in the \c{mac} |
| 31 | subdirectory; the Windows-specific modules are in the \c{windows} |
| 32 | subdirectory. |
| 33 | |
| 34 | All the modules in the main source directory - notably \e{all} of |
| 35 | the code for the various back ends - are platform-generic. We want |
| 36 | to keep them that way. |
| 37 | |
| 38 | This also means you should stick to what you are guaranteed by |
| 39 | ANSI/ISO C (that is, the original C89/C90 standard, not C99). Try |
| 40 | not to make assumptions about the precise size of basic types such |
| 41 | as \c{int} and \c{long int}; don't use pointer casts to do |
| 42 | endianness-dependent operations, and so on. |
| 43 | |
| 44 | (There are one or two aspects of ANSI C portability which we |
| 45 | \e{don't} care about. In particular, we expect PuTTY to be compiled |
| 46 | on 32-bit architectures \e{or bigger}; so it's safe to assume that |
| 47 | \c{int} is at least 32 bits wide, not just the 16 you are guaranteed |
| 48 | by ANSI C. Similarly, we assume that the execution character encoding |
| 49 | is a superset of the printable characters of ASCII, though we don't |
| 50 | assume the numeric values of control characters, particularly \cw{'\n'} |
| 51 | and \cw{'\r'}.) |
| 52 | |
| 53 | \H{udp-multi-backend} Multiple backends treated equally |
| 54 | |
| 55 | PuTTY is not an SSH client with some other stuff tacked on the side. |
| 56 | PuTTY is a generic, multiple-backend, remote VT-terminal client |
| 57 | which happens to support one backend which is larger, more popular |
| 58 | and more useful than the rest. Any extra feature which can possibly |
| 59 | be general across all backends should be so: localising features |
| 60 | unnecessarily into the SSH back end is a design error. (For example, |
| 61 | we had several code submissions for proxy support which worked by |
| 62 | hacking \cw{ssh.c}. Clearly this is completely wrong: the |
| 63 | \cw{network.h} abstraction is the place to put it, so that it will |
| 64 | apply to all back ends equally, and indeed we eventually put it |
| 65 | there after another contributor sent a better patch.) |
| 66 | |
| 67 | The rest of PuTTY should try to avoid knowing anything about |
| 68 | specific back ends if at all possible. To support a feature which is |
| 69 | only available in one network protocol, for example, the back end |
| 70 | interface should be extended in a general manner such that \e{any} |
| 71 | back end which is able to provide that feature can do so. If it so |
| 72 | happens that only one back end actually does, that's just the way it |
| 73 | is, but it shouldn't be relied upon by any code. |
| 74 | |
| 75 | \H{udp-globals} Multiple sessions per process on some platforms |
| 76 | |
| 77 | Some ports of PuTTY - notably the in-progress Mac port - are |
| 78 | constrained by the operating system to run as a single process |
| 79 | potentially managing multiple sessions. |
| 80 | |
| 81 | Therefore, the platform-independent parts of PuTTY never use global |
| 82 | variables to store per-session data. The global variables that do |
| 83 | exist are tolerated because they are not specific to a particular |
| 84 | login session: \c{flags} defines properties that are expected to |
| 85 | apply equally to \e{all} the sessions run by a single PuTTY process, |
| 86 | the random number state in \cw{sshrand.c} and the timer list in |
| 87 | \cw{timing.c} serve all sessions equally, and so on. But most data |
| 88 | is specific to a particular network session, and is therefore stored |
| 89 | in dynamically allocated data structures, and pointers to these |
| 90 | structures are passed around between functions. |
| 91 | |
| 92 | Platform-specific code can reverse this decision if it likes. The |
| 93 | Windows code, for historical reasons, stores most of its data as |
| 94 | global variables. That's OK, because \e{on Windows} we know there is |
| 95 | only one session per PuTTY process, so it's safe to do that. But |
| 96 | changes to the platform-independent code should avoid introducing |
| 97 | global variables, unless they are genuinely cross-session. |
| 98 | |
| 99 | \H{udp-pure-c} C, not C++ |
| 100 | |
| 101 | PuTTY is written entirely in C, not in C++. |
| 102 | |
| 103 | We have made \e{some} effort to make it easy to compile our code |
| 104 | using a C++ compiler: notably, our \c{snew}, \c{snewn} and |
| 105 | \c{sresize} macros explicitly cast the return values of \cw{malloc} |
| 106 | and \cw{realloc} to the target type. (This has type checking |
| 107 | advantages even in C: it means you never accidentally allocate the |
| 108 | wrong size piece of memory for the pointer type you're assigning it |
| 109 | to. C++ friendliness is really a side benefit.) |
| 110 | |
| 111 | We want PuTTY to continue being pure C, at least in the |
| 112 | platform-independent parts and the currently existing ports. Patches |
| 113 | which switch the Makefiles to compile it as C++ and start using |
| 114 | classes will not be accepted. Also, in particular, we disapprove of |
| 115 | \cw{//} comments, at least for the moment. (Perhaps once C99 becomes |
| 116 | genuinely widespread we might be more lenient.) |
| 117 | |
| 118 | The one exception: a port to a new platform may use languages other |
| 119 | than C if they are necessary to code on that platform. If your |
| 120 | favourite PDA has a GUI with a C++ API, then there's no way you can |
| 121 | do a port of PuTTY without using C++, so go ahead and use it. But |
| 122 | keep the C++ restricted to that platform's subdirectory; if your |
| 123 | changes force the Unix or Windows ports to be compiled as C++, they |
| 124 | will be unacceptable to us. |
| 125 | |
| 126 | \H{udp-security} Security-conscious coding |
| 127 | |
| 128 | PuTTY is a network application and a security application. Assume |
| 129 | your code will end up being fed deliberately malicious data by |
| 130 | attackers, and try to code in a way that makes it unlikely to be a |
| 131 | security risk. |
| 132 | |
| 133 | In particular, try not to use fixed-size buffers for variable-size |
| 134 | data such as strings received from the network (or even the user). |
| 135 | We provide functions such as \cw{dupcat} and \cw{dupprintf}, which |
| 136 | dynamically allocate buffers of the right size for the string they |
| 137 | construct. Use these wherever possible. |
| 138 | |
| 139 | \H{udp-multi-compiler} Independence of specific compiler |
| 140 | |
| 141 | Windows PuTTY can currently be compiled with any of four Windows |
| 142 | compilers: MS Visual C, Borland's freely downloadable C compiler, |
| 143 | the Cygwin / \cw{mingw32} GNU tools, and \cw{lcc-win32}. |
| 144 | |
| 145 | This is a really useful property of PuTTY, because it means people |
| 146 | who want to contribute to the coding don't depend on having a |
| 147 | specific compiler; so they don't have to fork out money for MSVC if |
| 148 | they don't already have it, but on the other hand if they \e{do} |
| 149 | have it they also don't have to spend effort installing \cw{gcc} |
| 150 | alongside it. They can use whichever compiler they happen to have |
| 151 | available, or install whichever is cheapest and easiest if they |
| 152 | don't have one. |
| 153 | |
| 154 | Therefore, we don't want PuTTY to start depending on which compiler |
| 155 | you're using. Using GNU extensions to the C language, for example, |
| 156 | would ruin this useful property (not that anyone's ever tried it!); |
| 157 | and more realistically, depending on an MS-specific library function |
| 158 | supplied by the MSVC C library (\cw{_snprintf}, for example) is a |
| 159 | mistake, because that function won't be available under the other |
| 160 | compilers. Any function supplied in an official Windows DLL as part |
| 161 | of the Windows API is fine, and anything defined in the C library |
| 162 | standard is also fine, because those should be available |
| 163 | irrespective of compilation environment. But things in between, |
| 164 | available as non-standard library and language extensions in only |
| 165 | one compiler, are disallowed. |
| 166 | |
| 167 | (\cw{_snprintf} in particular should be unnecessary, since we |
| 168 | provide \cw{dupprintf}; see \k{udp-security}.) |
| 169 | |
| 170 | Compiler independence should apply on all platforms, of course, not |
| 171 | just on Windows. |
| 172 | |
| 173 | \H{udp-small} Small code size |
| 174 | |
| 175 | PuTTY is tiny, compared to many other Windows applications. And it's |
| 176 | easy to install: it depends on no DLLs, no other applications, no |
| 177 | service packs or system upgrades. It's just one executable. You |
| 178 | install that executable wherever you want to, and run it. |
| 179 | |
| 180 | We want to keep both these properties - the small size, and the ease |
| 181 | of installation - if at all possible. So code contributions that |
| 182 | depend critically on external DLLs, or that add a huge amount to the |
| 183 | code size for a feature which is only useful to a small minority of |
| 184 | users, are likely to be thrown out immediately. |
| 185 | |
| 186 | We do vaguely intend to introduce a DLL plugin interface for PuTTY, |
| 187 | whereby seriously large extra features can be implemented in plugin |
| 188 | modules. The important thing, though, is that those DLLs will be |
| 189 | \e{optional}; if PuTTY can't find them on startup, it should run |
| 190 | perfectly happily and just won't provide those particular features. |
| 191 | A full installation of PuTTY might one day contain ten or twenty |
| 192 | little DLL plugins, which would cut down a little on the ease of |
| 193 | installation - but if you really needed ease of installation you |
| 194 | \e{could} still just install the one PuTTY binary, or just the DLLs |
| 195 | you really needed, and it would still work fine. |
| 196 | |
| 197 | Depending on \e{external} DLLs is something we'd like to avoid if at |
| 198 | all possible (though for some purposes, such as complex SSH |
| 199 | authentication mechanisms, it may be unavoidable). If it can't be |
| 200 | avoided, the important thing is to follow the same principle of |
| 201 | graceful degradation: if a DLL can't be found, then PuTTY should run |
| 202 | happily and just not supply the feature that depended on it. |
| 203 | |
| 204 | \H{udp-single-threaded} Single-threaded code |
| 205 | |
| 206 | PuTTY and its supporting tools, or at least the vast majority of |
| 207 | them, run in only one OS thread. |
| 208 | |
| 209 | This means that if you're devising some piece of internal mechanism, |
| 210 | there's no need to use locks to make sure it doesn't get called by |
| 211 | two threads at once. The only way code can be called re-entrantly is |
| 212 | by recursion. |
| 213 | |
| 214 | That said, most of Windows PuTTY's network handling is triggered off |
| 215 | Windows messages requested by \cw{WSAAsyncSelect()}, so if you call |
| 216 | \cw{MessageBox()} deep within some network event handling code you |
| 217 | should be aware that you might be re-entered if a network event |
| 218 | comes in and is passed on to our window procedure by the |
| 219 | \cw{MessageBox()} message loop. |
| 220 | |
| 221 | Also, the front ends (in particular Windows Plink) can use multiple |
| 222 | threads if they like. However, Windows Plink keeps \e{very} tight |
| 223 | control of its auxiliary threads, and uses them pretty much |
| 224 | exclusively as a form of \cw{select()}. Pretty much all the code |
| 225 | outside \cw{windows/winplink.c} is \e{only} ever called from the one |
| 226 | primary thread; the others just loop round blocking on file handles |
| 227 | and send messages to the main thread when some real work needs |
| 228 | doing. This is not considered a portability hazard because that bit |
| 229 | of \cw{windows/winplink.c} will need rewriting on other platforms in |
| 230 | any case. |
| 231 | |
| 232 | One important consequence of this: PuTTY has only one thread in |
| 233 | which to do everything. That \q{everything} may include managing |
| 234 | more than one login session (\k{udp-globals}), managing multiple |
| 235 | data channels within an SSH session, responding to GUI events even |
| 236 | when nothing is happening on the network, and responding to network |
| 237 | requests from the server (such as repeat key exchange) even when the |
| 238 | program is dealing with complex user interaction such as the |
| 239 | re-configuration dialog box. This means that \e{almost none} of the |
| 240 | PuTTY code can safely block. |
| 241 | |
| 242 | \H{udp-keystrokes} Keystrokes sent to the server wherever possible |
| 243 | |
| 244 | In almost all cases, PuTTY sends keystrokes to the server. Even |
| 245 | weird keystrokes that you think should be hot keys controlling |
| 246 | PuTTY. Even Alt-F4 or Alt-Space, for example. If a keystroke has a |
| 247 | well-defined escape sequence that it could usefully be sending to |
| 248 | the server, then it should do so, or at the very least it should be |
| 249 | configurably able to do so. |
| 250 | |
| 251 | To unconditionally turn a key combination into a hot key to control |
| 252 | PuTTY is almost always a design error. If a hot key is really truly |
| 253 | required, then try to find a key combination for it which \e{isn't} |
| 254 | already used in existing PuTTYs (either it sends nothing to the |
| 255 | server, or it sends the same thing as some other combination). Even |
| 256 | then, be prepared for the possibility that one day that key |
| 257 | combination might end up being needed to send something to the |
| 258 | server - so make sure that there's an alternative way to invoke |
| 259 | whatever PuTTY feature it controls. |
| 260 | |
| 261 | \H{udp-640x480} 640\u00D7{x}480 friendliness in configuration panels |
| 262 | |
| 263 | There's a reason we have lots of tiny configuration panels instead |
| 264 | of a few huge ones, and that reason is that not everyone has a |
| 265 | 1600\u00D7{x}1200 desktop. 640\u00D7{x}480 is still a viable |
| 266 | resolution for running Windows (and indeed it's still the default if |
| 267 | you start up in safe mode), so it's still a resolution we care |
| 268 | about. |
| 269 | |
| 270 | Accordingly, the PuTTY configuration box, and the PuTTYgen control |
| 271 | window, are deliberately kept just small enough to fit comfortably |
| 272 | on a 640\u00D7{x}480 display. If you're adding controls to either of |
| 273 | these boxes and you find yourself wanting to increase the size of |
| 274 | the whole box, \e{don't}. Split it into more panels instead. |
| 275 | |
| 276 | \H{udp-makefiles-auto} Automatically generated \cw{Makefile}s |
| 277 | |
| 278 | PuTTY is intended to compile on multiple platforms, and with |
| 279 | multiple compilers. It would be horrifying to try to maintain a |
| 280 | single \cw{Makefile} which handled all possible situations, and just |
| 281 | as painful to try to directly maintain a set of matching |
| 282 | \cw{Makefile}s for each different compilation environment. |
| 283 | |
| 284 | Therefore, we have moved the problem up by one level. In the PuTTY |
| 285 | source archive is a file called \c{Recipe}, which lists which source |
| 286 | files combine to produce which binaries; and there is also a script |
| 287 | called \cw{mkfiles.pl}, which reads \c{Recipe} and writes out the |
| 288 | real \cw{Makefile}s. (The script also reads all the source files and |
| 289 | analyses their dependencies on header files, so we get an extra |
| 290 | benefit from doing it this way, which is that we can supply correct |
| 291 | dependency information even in environments where it's difficult to |
| 292 | set up an automated \c{make depend} phase.) |
| 293 | |
| 294 | You should \e{never} edit any of the PuTTY \cw{Makefile}s directly. |
| 295 | They are not stored in our source repository at all. They are |
| 296 | automatically generated by \cw{mkfiles.pl} from the file \c{Recipe}. |
| 297 | |
| 298 | If you need to add a new object file to a particular binary, the |
| 299 | right thing to do is to edit \c{Recipe} and re-run \cw{mkfiles.pl}. |
| 300 | This will cause the new object file to be added in every tool that |
| 301 | requires it, on every platform where it matters, in every |
| 302 | \cw{Makefile} to which it is relevant, \e{and} to get all the |
| 303 | dependency data right. |
| 304 | |
| 305 | If you send us a patch that modifies one of the \cw{Makefile}s, you |
| 306 | just waste our time, because we will have to convert it into a |
| 307 | change to \c{Recipe}. If you send us a patch that modifies \e{all} |
| 308 | of the \cw{Makefile}s, you will have wasted a lot of \e{your} time |
| 309 | as well! |
| 310 | |
| 311 | (There is a comment at the top of every \cw{Makefile} in the PuTTY |
| 312 | source archive saying this, but many people don't seem to read it, |
| 313 | so it's worth repeating here.) |
| 314 | |
| 315 | \H{udp-ssh-coroutines} Coroutines in \cw{ssh.c} |
| 316 | |
| 317 | Large parts of the code in \cw{ssh.c} are structured using a set of |
| 318 | macros that implement (something close to) Donald Knuth's |
| 319 | \q{coroutines} concept in C. |
| 320 | |
| 321 | Essentially, the purpose of these macros are to arrange that a |
| 322 | function can call \cw{crReturn()} to return to its caller, and the |
| 323 | next time it is called control will resume from just after that |
| 324 | \cw{crReturn} statement. |
| 325 | |
| 326 | This means that any local (automatic) variables declared in such a |
| 327 | function will be corrupted every time you call \cw{crReturn}. If you |
| 328 | need a variable to persist for longer than that, you \e{must} make |
| 329 | it a field in one of the persistent state structures: either the |
| 330 | local state structures \c{s} or \c{st} in each function, or the |
| 331 | backend-wide structure \c{ssh}. |
| 332 | |
| 333 | See |
| 334 | \W{http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html}\c{http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html} |
| 335 | for a more in-depth discussion of what these macros are for and how |
| 336 | they work. |
| 337 | |
| 338 | \H{udp-compile-once} Single compilation of each source file |
| 339 | |
| 340 | The PuTTY build system for any given platform works on the following |
| 341 | very simple model: |
| 342 | |
| 343 | \b Each source file is compiled precisely once, to produce a single |
| 344 | object file. |
| 345 | |
| 346 | \b Each binary is created by linking together some combination of |
| 347 | those object files. |
| 348 | |
| 349 | Therefore, if you need to introduce functionality to a particular |
| 350 | module which is only available in some of the tool binaries (for |
| 351 | example, a cryptographic proxy authentication mechanism which needs |
| 352 | to be left out of PuTTYtel to maintain its usability in |
| 353 | crypto-hostile jurisdictions), the \e{wrong} way to do it is by |
| 354 | adding \cw{#ifdef}s in (say) \cw{proxy.c}. This would require |
| 355 | separate compilation of \cw{proxy.c} for PuTTY and PuTTYtel, which |
| 356 | means that the entire \cw{Makefile}-generation architecture (see |
| 357 | \k{udp-makefiles-auto}) would have to be significantly redesigned. |
| 358 | Unless you are prepared to do that redesign yourself, \e{and} |
| 359 | guarantee that it will still port to any future platforms we might |
| 360 | decide to run on, you should not attempt this! |
| 361 | |
| 362 | The \e{right} way to introduce a feature like this is to put the new |
| 363 | code in a separate source file, and (if necessary) introduce a |
| 364 | second new source file defining the same set of functions, but |
| 365 | defining them as stubs which don't provide the feature. Then the |
| 366 | module whose behaviour needs to vary (\cw{proxy.c} in this example) |
| 367 | can call the functions defined in these two modules, and it will |
| 368 | either provide the new feature or not provide it according to which |
| 369 | of your new modules it is linked with. |
| 370 | |
| 371 | Of course, object files are never shared \e{between} platforms; so |
| 372 | it is allowable to use \cw{#ifdef} to select between platforms. This |
| 373 | happens in \cw{puttyps.h} (choosing which of the platform-specific |
| 374 | include files to use), and also in \cw{misc.c} (the Windows-specific |
| 375 | \q{Minefield} memory diagnostic system). It should be used |
| 376 | sparingly, though, if at all. |
| 377 | |
| 378 | \H{udp-perfection} Do as we say, not as we do |
| 379 | |
| 380 | The current PuTTY code probably does not conform strictly to \e{all} |
| 381 | of the principles listed above. There may be the occasional |
| 382 | SSH-specific piece of code in what should be a backend-independent |
| 383 | module, or the occasional dependence on a non-standard X library |
| 384 | function under Unix. |
| 385 | |
| 386 | This should not be taken as a licence to go ahead and violate the |
| 387 | rules. Where we violate them ourselves, we're not happy about it, |
| 388 | and we would welcome patches that fix any existing problems. Please |
| 389 | try to help us make our code better, not worse! |