~ubuntu-branches/ubuntu/quantal/curl/quantal

« back to all changes in this revision

Viewing changes to docs/INTERNALS

  • Committer: Bazaar Package Importer
  • Author(s): Domenico Andreoli
  • Date: 2002-03-12 19:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20020312190621-iqx7k9cipo5d0ifr
Tags: upstream-7.9.5
ImportĀ upstreamĀ versionĀ 7.9.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
                                    Updated for curl 7.9.1 on November 2, 2001
 
2
                                  _   _ ____  _     
 
3
                              ___| | | |  _ \| |    
 
4
                             / __| | | | |_) | |    
 
5
                            | (__| |_| |  _ <| |___ 
 
6
                             \___|\___/|_| \_\_____|
 
7
 
 
8
INTERNALS
 
9
 
 
10
 The project is split in two. The library and the client. The client part uses
 
11
 the library, but the library is designed to allow other applications to use
 
12
 it.
 
13
 
 
14
 The largest amount of code and complexity is in the library part.
 
15
 
 
16
CVS
 
17
===
 
18
 All changes to the sources are committed to the CVS repository as soon as
 
19
 they're somewhat verified to work. Changes shall be commited as independently
 
20
 as possible so that individual changes can be easier spotted and tracked
 
21
 afterwards.
 
22
 
 
23
 Tagging shall be used extensively, and by the time we release new archives we
 
24
 should tag the sources with a name similar to the released version number.
 
25
 
 
26
Windows vs Unix
 
27
===============
 
28
 
 
29
 There are a few differences in how to program curl the unix way compared to
 
30
 the Windows way. The four perhaps most notable details are:
 
31
 
 
32
 1. Different function names for socket operations.
 
33
 
 
34
   In curl, this is solved with defines and macros, so that the source looks
 
35
   the same at all places except for the header file that defines them. The
 
36
   macros in use are sclose(), sread() and swrite().
 
37
 
 
38
 2. Windows requires a couple of init calls for the socket stuff.
 
39
 
 
40
   Those must be made by the application that uses libcurl, in curl that means
 
41
   src/main.c has some code #ifdef'ed to do just that.
 
42
 
 
43
 3. The file descriptors for network communication and file operations are
 
44
    not easily interchangable as in unix.
 
45
 
 
46
   We avoid this by not trying any funny tricks on file descriptors.
 
47
 
 
48
 4. When writing data to stdout, Windows makes end-of-lines the DOS way, thus
 
49
    destroying binary data, although you do want that conversion if it is
 
50
    text coming through... (sigh)
 
51
 
 
52
   We set stdout to binary under windows
 
53
 
 
54
 Inside the source code, We make an effort to avoid '#ifdef [Your OS]'. All
 
55
 conditionals that deal with features *should* instead be in the format
 
56
 '#ifdef HAVE_THAT_WEIRD_FUNCTION'. Since Windows can't run configure scripts,
 
57
 we maintain two config-win32.h files (one in lib/ and one in src/) that are
 
58
 supposed to look exactly as a config.h file would have looked like on a
 
59
 Windows machine!
 
60
 
 
61
 Generally speaking: always remember that this will be compiled on dozens of
 
62
 operating systems. Don't walk on the edge.
 
63
 
 
64
Library
 
65
=======
 
66
 
 
67
 There are plenty of entry points to the library, namely each publicly defined
 
68
 function that libcurl offers to applications. All of those functions are
 
69
 rather small and easy-to-follow. All the ones prefixed with 'curl_easy' are
 
70
 put in the lib/easy.c file.
 
71
 
 
72
 curl_global_init_() and curl_global_cleanup() should be called by the
 
73
 application to initialize and clean up global stuff in the library. As of
 
74
 today, it can handle the global SSL initing if SSL is enabled and it can init
 
75
 the socket layer on windows machines. libcurl itself has no "global" scope.
 
76
 
 
77
 All printf()-style functions use the supplied clones in lib/mprintf.c. This
 
78
 makes sure we stay absolutely platform independent.
 
79
 
 
80
 curl_easy_init() allocates an internal struct and makes some initializations.
 
81
 The returned handle does not reveal internals. This is the 'SessionHandle'
 
82
 struct which works as an "anchor" struct for all curl_easy functions. All
 
83
 connections performed will get connect-specific data allocated that should be
 
84
 used for things related to particular connections/requests.
 
85
 
 
86
 curl_easy_setopt() takes three arguments, where the option stuff must be
 
87
 passed in pairs: the parameter-ID and the parameter-value. The list of
 
88
 options is documented in the man page. This function mainly sets things in
 
89
 the 'SessionHandle' struct.
 
90
 
 
91
 curl_easy_perform() does a whole lot of things:
 
92
 
 
93
 It starts off in the lib/easy.c file by calling Curl_perform() and the main
 
94
 work then continues in lib/url.c. The flow continues with a call to
 
95
 Curl_connect() to connect to the remote site.
 
96
 
 
97
 o Curl_connect()
 
98
 
 
99
   ... analyzes the URL, it separates the different components and connects to
 
100
   the remote host. This may involve using a proxy and/or using SSL. The
 
101
   Curl_gethost() function in lib/hostip.c is used for looking up host names.
 
102
 
 
103
   When Curl_connect is done, we are connected to the remote site. Then it is
 
104
   time to tell the server to get a document/file. Curl_do() arranges this.
 
105
 
 
106
   This function makes sure there's an allocated and initiated 'connectdata'
 
107
   struct that is used for this particular connection only (although there may
 
108
   be several requests performed on the same connect). A bunch of things are
 
109
   inited/inherited from the SessionHandle struct.
 
110
 
 
111
 o Curl_do()
 
112
 
 
113
   Curl_do() makes sure the proper protocol-specific function is called. The
 
114
   functions are named after the protocols they handle. Curl_ftp(),
 
115
   Curl_http(), Curl_dict(), etc. They all reside in their respective files
 
116
   (ftp.c, http.c and dict.c). HTTPS is handled by Curl_http() and FTPS by
 
117
   Curl_ftp().
 
118
 
 
119
   The protocol-specific functions of course deal with protocol-specific
 
120
   negotiations and setup. They have access to the Curl_sendf() (from
 
121
   lib/sendf.c) function to send printf-style formatted data to the remote
 
122
   host and when they're ready to make the actual file transfer they call the
 
123
   Curl_Transfer() function (in lib/transfer.c) to setup the transfer and
 
124
   returns.
 
125
 
 
126
   Starting in 7.9.1, if this DO function fails and the connection is being
 
127
   re-used, libcurl will then close this connection, setup a new connection
 
128
   and re-issue the DO request on that. This is because there is no way to be
 
129
   perfectly sure that we have discovered a dead connection before the DO
 
130
   function and thus we might wrongly be re-using a connection that was closed
 
131
   by the remote peer.
 
132
 
 
133
 o Transfer()
 
134
 
 
135
   Curl_perform() then calls Transfer() in lib/transfer.c that performs
 
136
   the entire file transfer.
 
137
 
 
138
   During transfer, the progress functions in lib/progress.c are called at a
 
139
   frequent interval (or at the user's choice, a specified callback might get
 
140
   called). The speedcheck functions in lib/speedcheck.c are also used to
 
141
   verify that the transfer is as fast as required.
 
142
 
 
143
 o Curl_done()
 
144
 
 
145
   Called after a transfer is done. This function takes care of everything
 
146
   that has to be done after a transfer. This function attempts to leave
 
147
   matters in a state so that Curl_do() should be possible to call again on
 
148
   the same connection (in a persistent connection case). It might also soon
 
149
   be closed with Curl_disconnect().
 
150
 
 
151
 o Curl_disconnect()
 
152
 
 
153
   When doing normal connections and transfers, no one ever tries to close any
 
154
   connections so this is not normally called when curl_easy_perform() is
 
155
   used. This function is only used when we are certain that no more transfers
 
156
   is going to be made on the connection. It can be also closed by force, or
 
157
   it can be called to make sure that libcurl doesn't keep too many
 
158
   connections alive at the same time (there's a default amount of 5 but that
 
159
   can be changed with the CURLOPT_MAXCONNECTS option).
 
160
 
 
161
   This function cleans up all resources that are associated with a single
 
162
   connection.
 
163
 
 
164
 Curl_perform() is the function that does the main "connect - do - transfer -
 
165
 done" loop. It loops if there's a Location: to follow.
 
166
 
 
167
 When completed, the curl_easy_cleanup() should be called to free up used
 
168
 resources. It runs Curl_disconnect() on all open connectons.
 
169
 
 
170
 A quick roundup on internal function sequences (many of these call
 
171
 protocol-specific function-pointers):
 
172
 
 
173
  curl_connect - connects to a remote site and does initial connect fluff
 
174
   This also checks for an existing connection to the requested site and uses
 
175
   that one if it is possible.
 
176
 
 
177
   curl_do - starts a transfer
 
178
    curl_transfer() - transfers data
 
179
   curl_done - ends a transfer
 
180
 
 
181
  curl_disconnect - disconnects from a remote site. This is called when the
 
182
   disconnect is really requested, which doesn't necessarily have to be
 
183
   exactly after curl_done in case we want to keep the connection open for
 
184
   a while.
 
185
 
 
186
 HTTP(S)
 
187
 
 
188
 HTTP offers a lot and is the protocol in curl that uses the most lines of
 
189
 code. There is a special file (lib/formdata.c) that offers all the multipart
 
190
 post functions.
 
191
 
 
192
 base64-functions for user+password stuff (and more) is in (lib/base64.c) and
 
193
 all functions for parsing and sending cookies are found in (lib/cookie.c).
 
194
 
 
195
 HTTPS uses in almost every means the same procedure as HTTP, with only two
 
196
 exceptions: the connect procedure is different and the function used to read
 
197
 or write from the socket is different, although the latter fact is hidden in
 
198
 the source by the use of curl_read() for reading and curl_write() for writing
 
199
 data to the remote server.
 
200
 
 
201
 http_chunks.c contains functions that understands HTTP 1.1 chunked transfer
 
202
 encoding.
 
203
 
 
204
 An interesting detail with the HTTP(S) request, is the add_buffer() series of
 
205
 functions we use. They append data to one single buffer, and when the
 
206
 building is done the entire request is sent off in one single write. This is
 
207
 done this way to overcome problems with flawed firewalls and lame servers.
 
208
 
 
209
 FTP
 
210
 
 
211
 The Curl_if2ip() function can be used for getting the IP number of a
 
212
 specified network interface, and it resides in lib/if2ip.c.
 
213
 
 
214
 Curl_ftpsendf() is used for sending FTP commands to the remote server. It was
 
215
 made a separate function to prevent us programmers from forgetting that they
 
216
 must be CRLF terminated. They must also be sent in one single write() to make
 
217
 firewalls and similar happy.
 
218
 
 
219
 Kerberos
 
220
 
 
221
 The kerberos support is mainly in lib/krb4.c and lib/security.c.
 
222
 
 
223
 TELNET
 
224
 
 
225
 Telnet is implemented in lib/telnet.c.
 
226
 
 
227
 FILE
 
228
 
 
229
 The file:// protocol is dealt with in lib/file.c.
 
230
 
 
231
 LDAP
 
232
 
 
233
 Everything LDAP is in lib/ldap.c.
 
234
 
 
235
 GENERAL
 
236
 
 
237
 URL encoding and decoding, called escaping and unescaping in the source code,
 
238
 is found in lib/escape.c.
 
239
 
 
240
 While transfering data in Transfer() a few functions might get
 
241
 used. curl_getdate() in lib/getdate.c is for HTTP date comparisons (and
 
242
 more).
 
243
 
 
244
 lib/getenv.c offers curl_getenv() which is for reading environment variables
 
245
 in a neat platform independent way. That's used in the client, but also in
 
246
 lib/url.c when checking the proxy environment variables. Note that contrary
 
247
 to the normal unix getenv(), this returns an allocated buffer that must be
 
248
 free()ed after use.
 
249
 
 
250
 lib/netrc.c holds the .netrc parser
 
251
 
 
252
 lib/timeval.c features replacement functions for systems that don't have
 
253
 gettimeofday() and a few support functions for timeval convertions.
 
254
 
 
255
 A function named curl_version() that returns the full curl version string is
 
256
 found in lib/version.c.
 
257
 
 
258
 If authentication is requested but no password is given, a getpass_r() clone
 
259
 exists in lib/getpass.c. libcurl offers a custom callback that can be used
 
260
 instead of this, but it doesn't change much to us.
 
261
 
 
262
Persistent Connections
 
263
======================
 
264
 
 
265
 The persistent connection support in libcurl requires some considerations on
 
266
 how to do things inside of the library.
 
267
 
 
268
 o The 'SessionHandle' struct returned in the curl_easy_init() call must never
 
269
   hold connection-oriented data. It is meant to hold the root data as well as
 
270
   all the options etc that the library-user may choose.
 
271
 o The 'SessionHandle' struct holds the "connection cache" (an array of
 
272
   pointers to 'connectdata' structs). There's one connectdata struct
 
273
   allocated for each connection that libcurl knows about.
 
274
 o This also enables the 'curl handle' to be reused on subsequent transfers,
 
275
   something that was illegal before libcurl 7.7.
 
276
 o When we are about to perform a transfer with curl_easy_perform(), we first
 
277
   check for an already existing connection in the cache that we can use,
 
278
   otherwise we create a new one and add to the cache. If the cache is full
 
279
   already when we add a new connection, we close one of the present ones. We
 
280
   select which one to close dependent on the close policy that may have been
 
281
   previously set.
 
282
 o When the transfer operation is complete, we try to leave the connection
 
283
   open. Particular options may tell us not to, and protocols may signal
 
284
   closure on connections and then we don't keep it open of course.
 
285
 o When curl_easy_cleanup() is called, we close all still opened connections.
 
286
 
 
287
 You do realize that the curl handle must be re-used in order for the
 
288
 persistent connections to work.
 
289
 
 
290
Library Symbols
 
291
===============
 
292
 
 
293
 All symbols used internally in libcurl must use a 'Curl_' prefix if they're
 
294
 used in more than a single file. Single-file symbols must be made static.
 
295
 Public ("exported") symbols must use a 'curl_' prefix. (There are exceptions,
 
296
 but they are to be changed to follow this pattern in future versions.)
 
297
 
 
298
Return Codes and Informationals
 
299
===============================
 
300
 
 
301
 I've made things simple. Almost every function in libcurl returns a CURLcode,
 
302
 that must be CURLE_OK if everything is OK or otherwise a suitable error code
 
303
 as the curl/curl.h include file defines. The very spot that detects an error
 
304
 must use the Curl_failf() function to set the human-readable error
 
305
 description.
 
306
 
 
307
 In aiding the user to understand what's happening and to debug curl usage, we
 
308
 must supply a fair amount of informational messages by using the Curl_infof()
 
309
 function. Those messages are only displayed when the user explicitly asks for
 
310
 them. They are best used when revealing information that isn't otherwise
 
311
 obvious.
 
312
 
 
313
Client
 
314
======
 
315
 
 
316
 main() resides in src/main.c together with most of the client code.
 
317
 
 
318
 src/hugehelp.c is automatically generated by the mkhelp.pl perl script to
 
319
 display the complete "manual" and the src/urlglob.c file holds the functions
 
320
 used for the URL-"globbing" support. Globbing in the sense that the {} and []
 
321
 expansion stuff is there.
 
322
 
 
323
 The client mostly messes around to setup its 'config' struct properly, then
 
324
 it calls the curl_easy_*() functions of the library and when it gets back
 
325
 control after the curl_easy_perform() it cleans up the library, checks status
 
326
 and exits.
 
327
 
 
328
 When the operation is done, the ourWriteOut() function in src/writeout.c may
 
329
 be called to report about the operation. That function is using the
 
330
 curl_easy_getinfo() function to extract useful information from the curl
 
331
 session.
 
332
 
 
333
 Recent versions may loop and do all this several times if many URLs were
 
334
 specified on the command line or config file.
 
335
 
 
336
Memory Debugging
 
337
================
 
338
 
 
339
 The file lib/memdebug.c contains debug-versions of a few functions. Functions
 
340
 such as malloc, free, fopen, fclose, etc that somehow deal with resources
 
341
 that might give us problems if we "leak" them. The functions in the memdebug
 
342
 system do nothing fancy, they do their normal function and then log
 
343
 information about what they just did. The logged data can then be analyzed
 
344
 after a complete session,
 
345
 
 
346
 memanalyze.pl is the perl script present only present in CVS (not part of the
 
347
 release archives) that analyzes a log file generated by the memdebug
 
348
 system. It detects if resources are allocated but never freed and other kinds
 
349
 of errors related to resource management.
 
350
 
 
351
 Use -DMALLOCDEBUG when compiling to enable memory debugging, this is also
 
352
 switched on by running configure with --enable-debug.
 
353
 
 
354
Test Suite
 
355
==========
 
356
 
 
357
 Since November 2000, a test suite has evolved. It is placed in its own
 
358
 subdirectory directly off the root in the curl archive tree, and it contains
 
359
 a bunch of scripts and a lot of test case data.
 
360
 
 
361
 The main test script is runtests.pl that will invoke the two servers
 
362
 httpserver.pl and ftpserver.pl before all the test cases are performed. The
 
363
 test suite currently only runs on unix-like platforms.
 
364
 
 
365
 You'll find a complete description of the test case data files in the
 
366
 tests/README file.
 
367
 
 
368
 The test suite automatically detects if curl was built with the memory
 
369
 debugging enabled, and if it was it will detect memory leaks too.
 
370
 
 
371
Building Releases
 
372
=================
 
373
 
 
374
 There's no magic to this. When you consider everything stable enough to be
 
375
 released, run the 'maketgz' script (using 'make distcheck' will give you a
 
376
 pretty good view on the status of the current sources). maketgz prompts for
 
377
 version number of the client and the library before it creates a release
 
378
 archive. maketgz uses 'make dist' for the actual archive building, why you
 
379
 need to fill in the Makefile.am files properly for which files that should
 
380
 be included in the release archives.
 
381