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