Skip to content
INTERNALS.md 42.4 KiB
Newer Older
Daniel Stenberg's avatar
Daniel Stenberg committed
curl internals
==============
 - [Intro](#intro)
 - [git](#git)
 - [Portability](#Portability)
 - [Windows vs Unix](#winvsunix)
 - [Library](#Library)
   - [`Curl_connect`](#Curl_connect)
   - [`Curl_do`](#Curl_do)
   - [`Curl_readwrite`](#Curl_readwrite)
   - [`Curl_done`](#Curl_done)
   - [`Curl_disconnect`](#Curl_disconnect)
 - [HTTP(S)](#http)
 - [FTP](#ftp)
   - [Kerberos](#kerberos)
 - [TELNET](#telnet)
 - [FILE](#file)
 - [SMB](#smb)
 - [LDAP](#ldap)
 - [E-mail](#email)
 - [General](#general)
 - [Persistent Connections](#persistent)
 - [multi interface/non-blocking](#multi)
 - [SSL libraries](#ssl)
 - [Library Symbols](#symbols)
 - [Return Codes and Informationals](#returncodes)
 - [AP/ABI](#abi)
 - [Client](#client)
 - [Memory Debugging](#memorydebug)
 - [Test Suite](#test)
 - [Asynchronous name resolves](#asyncdns)
   - [c-ares](#cares)
 - [`curl_off_t`](#curl_off_t)
 - [curlx](#curlx)
 - [Content Encoding](#contentencoding)
 - [hostip.c explained](#hostip)
 - [Track Down Memory Leaks](#memoryleak)
 - [`multi_socket`](#multi_socket)
 - [Structs in libcurl](#structs)

<a name="intro"></a>
Daniel Stenberg's avatar
Daniel Stenberg committed
Intro
=====

 This project is split in two. The library and the client. The client part
 uses the library, but the library is designed to allow other applications to
 use it.
Daniel Stenberg's avatar
Daniel Stenberg committed
 The largest amount of code and complexity is in the library part.

<a name="git"></a>
git
 All changes to the sources are committed to the git repository as soon as
 they're somewhat verified to work. Changes shall be committed as independently
 as possible so that individual changes can be easily spotted and tracked
 afterwards.

 Tagging shall be used extensively, and by the time we release new archives we
 should tag the sources with a name similar to the released version number.

<a name="Portability"></a>
Portability
===========

 We write curl and libcurl to compile with C89 compilers.  On 32bit and up
 machines. Most of libcurl assumes more or less POSIX compliance but that's
 not a requirement.

 We write libcurl to build and work with lots of third party tools, and we
 want it to remain functional and buildable with these and later versions
 (older versions may still work but is not what we work hard to maintain):

Dependencies
------------

 - OpenSSL      0.9.7
 - GnuTLS       1.2
 - zlib         1.1.4
 - libssh2      0.16
 - c-ares       1.6.0
 - libidn       0.4.1
 - cyassl       2.0.0
 - openldap     2.0
 - MIT Kerberos 1.2.4
 - GSKit        V5R3M0
 - NSS          3.14.x
 - axTLS        2.1.0
 - PolarSSL     1.3.0
 - Heimdal      ?
 - nghttp2      1.0.0

Operating Systems
-----------------

 On systems where configure runs, we aim at working on them all - if they have
 a suitable C compiler. On systems that don't run configure, we strive to keep
 curl running correctly on:
 - Windows      98
 - AS/400       V5R3M0
 - Symbian      9.1
 - Windows CE   ?
 - TPF          ?

Build tools
-----------
 When writing code (mostly for generating stuff included in release tarballs)
 we use a few "build tools" and we make sure that we remain functional with
 these versions:

 - GNU Libtool  1.4.2
 - GNU Autoconf 2.57
 - GNU Automake 1.7
 - GNU M4       1.4
 - perl         5.004
 - roffit       0.5
 - groff        ? (any version that supports "groff -Tps -man [in] [out]")
 - ps2pdf (gs)  ?
<a name="winvsunix"></a>
Windows vs Unix
===============

 There are a few differences in how to program curl the Unix way compared to
 the Windows way. Perhaps the four most notable details are:
 1. Different function names for socket operations.

   In curl, this is solved with defines and macros, so that the source looks
   the same in all places except for the header file that defines them. The
   macros in use are sclose(), sread() and swrite().
Daniel Stenberg's avatar
Daniel Stenberg committed
 2. Windows requires a couple of init calls for the socket stuff.
   That's taken care of by the `curl_global_init()` call, but if other libs
   also do it etc there might be reasons for applications to alter that
   behaviour.
 3. The file descriptors for network communication and file operations are
    not as easily interchangeable as in Unix.

   We avoid this by not trying any funny tricks on file descriptors.

 4. When writing data to stdout, Windows makes end-of-lines the DOS way, thus
    destroying binary data, although you do want that conversion if it is
    text coming through... (sigh)

   We set stdout to binary under windows
 Inside the source code, We make an effort to avoid `#ifdef [Your OS]`. All
 conditionals that deal with features *should* instead be in the format
 `#ifdef HAVE_THAT_WEIRD_FUNCTION`. Since Windows can't run configure scripts,
 we maintain a `curl_config-win32.h` file in lib directory that is supposed to
 look exactly like a `curl_config.h` file would have looked like on a Windows
 Generally speaking: always remember that this will be compiled on dozens of
 operating systems. Don't walk on the edge!
<a name="Library"></a>
 (See [Structs in libcurl](#structs) for the separate section describing all
 major internal structs and their purposes.)
 There are plenty of entry points to the library, namely each publicly defined
 function that libcurl offers to applications. All of those functions are
 rather small and easy-to-follow. All the ones prefixed with `curl_easy` are
 put in the lib/easy.c file.
 `curl_global_init()` and `curl_global_cleanup()` should be called by the
Daniel Stenberg's avatar
Daniel Stenberg committed
 application to initialize and clean up global stuff in the library. As of
 today, it can handle the global SSL initing if SSL is enabled and it can init
 the socket layer on windows machines. libcurl itself has no "global" scope.
 All printf()-style functions use the supplied clones in lib/mprintf.c. This
 makes sure we stay absolutely platform independent.
 [ `curl_easy_init()`][2] allocates an internal struct and makes some
 initializations.  The returned handle does not reveal internals. This is the
 `Curl_easy` struct which works as an "anchor" struct for all `curl_easy`
 functions. All connections performed will get connect-specific data allocated
 that should be used for things related to particular connections/requests.
 [`curl_easy_setopt()`][1] takes three arguments, where the option stuff must
 be passed in pairs: the parameter-ID and the parameter-value. The list of
 options is documented in the man page. This function mainly sets things in
 the `Curl_easy` struct.
 `curl_easy_perform()` is just a wrapper function that makes use of the multi
 API.  It basically calls `curl_multi_init()`, `curl_multi_add_handle()`,
 `curl_multi_wait()`, and `curl_multi_perform()` until the transfer is done
 and then returns.
Loading full blame...