diff options
Diffstat (limited to 'DOC/UDP.BUT')
-rw-r--r-- | DOC/UDP.BUT | 135 |
1 files changed, 27 insertions, 108 deletions
diff --git a/DOC/UDP.BUT b/DOC/UDP.BUT index b3570d5d..12b3392b 100644 --- a/DOC/UDP.BUT +++ b/DOC/UDP.BUT @@ -28,9 +28,9 @@ platform-generic modules. The Unix-specific modules are all in the \c{unix} subdirectory; the Windows-specific modules are in the \c{windows} subdirectory. -All the modules in the main source directory - notably \e{all} of -the code for the various back ends - are platform-generic. We want -to keep them that way. +All the modules in the main source directory and other +subdirectories - notably \e{all} of the code for the various back +ends - are platform-generic. We want to keep them that way. This also means you should stick to the C semantics guaranteed by the C standard: try not to make assumptions about the precise size of @@ -171,9 +171,7 @@ to. C++ friendliness is really a side benefit.) We want PuTTY to continue being pure C, at least in the platform-independent parts and the currently existing ports. Patches which switch the Makefiles to compile it as C++ and start using -classes will not be accepted. Also, in particular, we disapprove of -\cw{//} comments, at least for the moment. (Perhaps once C99 becomes -genuinely widespread we might be more lenient.) +classes will not be accepted. The one exception: a port to a new platform may use languages other than C if they are necessary to code on that platform. If your @@ -278,16 +276,17 @@ should be aware that you might be re-entered if a network event comes in and is passed on to our window procedure by the \cw{MessageBox()} message loop. -Also, the front ends (in particular Windows Plink) can use multiple -threads if they like. However, Windows Plink keeps \e{very} tight -control of its auxiliary threads, and uses them pretty much -exclusively as a form of \cw{select()}. Pretty much all the code -outside \cw{windows/winplink.c} is \e{only} ever called from the one -primary thread; the others just loop round blocking on file handles -and send messages to the main thread when some real work needs -doing. This is not considered a portability hazard because that bit -of \cw{windows/winplink.c} will need rewriting on other platforms in -any case. +Also, the front ends can use multiple threads if they like. For +example, the Windows front-end code spawns subthreads to deal with +bidirectional blocking I/O on non-network streams such as Windows +pipes. However, it keeps tight control of its auxiliary threads, and +uses them only for that one purpose, as a form of \cw{select()}. +Pretty much all the code outside \cw{windows/handle-io.c} is \e{only} +ever called from the one primary thread; the others just loop round +blocking on file handles, and signal the main thread (via Windows +event objects) when some real work needs doing. This is not considered +a portability hazard because that code is already Windows-specific and +needs rewriting on other platforms. One important consequence of this: PuTTY has only one thread in which to do everything. That \q{everything} may include managing @@ -333,51 +332,11 @@ on a 640\u00D7{x}480 display. If you're adding controls to either of these boxes and you find yourself wanting to increase the size of the whole box, \e{don't}. Split it into more panels instead. -\H{udp-makefiles-auto} Automatically generated \cw{Makefile}s - -PuTTY is intended to compile on multiple platforms, and with -multiple compilers. It would be horrifying to try to maintain a -single \cw{Makefile} which handled all possible situations, and just -as painful to try to directly maintain a set of matching -\cw{Makefile}s for each different compilation environment. - -Therefore, we have moved the problem up by one level. In the PuTTY -source archive is a file called \c{Recipe}, which lists which source -files combine to produce which binaries; and there is also a script -called \cw{mkfiles.pl}, which reads \c{Recipe} and writes out the -real \cw{Makefile}s. (The script also reads all the source files and -analyses their dependencies on header files, so we get an extra -benefit from doing it this way, which is that we can supply correct -dependency information even in environments where it's difficult to -set up an automated \c{make depend} phase.) - -You should \e{never} edit any of the PuTTY \cw{Makefile}s directly. -They are not stored in our source repository at all. They are -automatically generated by \cw{mkfiles.pl} from the file \c{Recipe}. - -If you need to add a new object file to a particular binary, the -right thing to do is to edit \c{Recipe} and re-run \cw{mkfiles.pl}. -This will cause the new object file to be added in every tool that -requires it, on every platform where it matters, in every -\cw{Makefile} to which it is relevant, \e{and} to get all the -dependency data right. - -If you send us a patch that modifies one of the \cw{Makefile}s, you -just waste our time, because we will have to convert it into a -change to \c{Recipe}. If you send us a patch that modifies \e{all} -of the \cw{Makefile}s, you will have wasted a lot of \e{your} time -as well! - -(There is a comment at the top of every \cw{Makefile} in the PuTTY -source archive saying this, but many people don't seem to read it, -so it's worth repeating here.) - -\H{udp-ssh-coroutines} Coroutines in the SSH code - -Large parts of the code in the various SSH modules (in fact most of -the protocol layers) are structured using a set of macros that -implement (something close to) Donald Knuth's \q{coroutines} concept -in C. +\H{udp-ssh-coroutines} Coroutines in protocol code + +Large parts of the code in modules implementing wire protocols +(mainly SSH) are structured using a set of macros that implement +(something close to) Donald Knuth's \q{coroutines} concept in C. Essentially, the purpose of these macros are to arrange that a function can call \cw{crReturn()} to return to its caller, and the @@ -388,7 +347,7 @@ This means that any local (automatic) variables declared in such a function will be corrupted every time you call \cw{crReturn}. If you need a variable to persist for longer than that, you \e{must} make it a field in some appropriate structure containing the persistent state -of the coroutine \dash typically the main state structure for an SSH +of the coroutine \dash typically the main state structure for a protocol layer. See @@ -544,13 +503,13 @@ call sites. Instead, what we generally do in this code base is to write a set of \cw{static inline} wrapper functions in the same header file that defined the \cw{MyAbstraction} structure types, like this: -\c static MyAbstraction *myabs_new(const MyAbstractionVtable *vt) +\c static inline MyAbstraction *myabs_new(const MyAbstractionVtable *vt) \c { return vt->new(vt); } -\c static void myabs_free(MyAbstraction *myabs) +\c static inline void myabs_free(MyAbstraction *myabs) \c { myabs->vt->free(myabs); } -\c static void myimpl_modify(MyAbstraction *myabs, unsigned param) +\c static inline void myimpl_modify(MyAbstraction *myabs, unsigned param) \c { myabs->vt->modify(myabs, param); } -\c static unsigned myimpl_query(MyAbstraction *myabs, unsigned param) +\c static inline unsigned myimpl_query(MyAbstraction *myabs, unsigned param) \c { return myabs->vt->query(myabs, param); } And now call sites can use those reasonably clean-looking wrapper @@ -598,8 +557,8 @@ based on the offset within that structure of the field called This system is flexible enough to permit \q{multiple inheritance}, or rather, multiple \e{implementation}: having one object type implement -more than one trait. For example, the \cw{Proxy} type implements both -the \cw{Socket} trait and the \cw{Plug} trait that connects to it, +more than one trait. For example, the \cw{ProxySocket} type implements +both the \cw{Socket} trait and the \cw{Plug} trait that connects to it, because it has to act as an adapter between another instance of each of those types. @@ -791,46 +750,6 @@ other two full implementation vtables. } -\H{udp-compile-once} Single compilation of each source file - -The PuTTY build system for any given platform works on the following -very simple model: - -\b Each source file is compiled precisely once, to produce a single -object file. - -\b Each binary is created by linking together some combination of -those object files. - -Therefore, if you need to introduce functionality to a particular -module which is only available in some of the tool binaries (for -example, a cryptographic proxy authentication mechanism which needs -to be left out of PuTTYtel to maintain its usability in -crypto-hostile jurisdictions), the \e{wrong} way to do it is by -adding \cw{#ifdef}s in (say) \cw{proxy.c}. This would require -separate compilation of \cw{proxy.c} for PuTTY and PuTTYtel, which -means that the entire \cw{Makefile}-generation architecture (see -\k{udp-makefiles-auto}) would have to be significantly redesigned. -Unless you are prepared to do that redesign yourself, \e{and} -guarantee that it will still port to any future platforms we might -decide to run on, you should not attempt this! - -The \e{right} way to introduce a feature like this is to put the new -code in a separate source file, and (if necessary) introduce a -second new source file defining the same set of functions, but -defining them as stubs which don't provide the feature. Then the -module whose behaviour needs to vary (\cw{proxy.c} in this example) -can call the functions defined in these two modules, and it will -either provide the new feature or not provide it according to which -of your new modules it is linked with. - -Of course, object files are never shared \e{between} platforms; so -it is allowable to use \cw{#ifdef} to select between platforms. This -happens in \cw{puttyps.h} (choosing which of the platform-specific -include files to use), and also in \cw{misc.c} (the Windows-specific -\q{Minefield} memory diagnostic system). It should be used -sparingly, though, if at all. - \H{udp-perfection} Do as we say, not as we do The current PuTTY code probably does not conform strictly to \e{all} |