6f3bdded |
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 |
28feb9ef |
48 | by ANSI C. Similarly, we assume that the execution character |
49 | encoding is a superset of the printable characters of ASCII, though |
50 | we don't assume the numeric values of control characters, |
51 | particularly \cw{'\\n'} and \cw{'\\r'}.) |
6f3bdded |
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 | |
39934deb |
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. |
6f3bdded |
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 |
39934deb |
97 | global variables, unless they are genuinely cross-session. |
6f3bdded |
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! |