GnuTLS -- Information about our contribution rules and coding style
Anyone is welcome to contribute to GnuTLS. You can either take up tasks from our planned list, or suprise us with enhancement we didn't plan for. In all cases be prepared to defend and justify your enhancements, and get through few rounds of changes.
We try to stick to the following rules, so when contributing please try to follow them too.
Note that when contributing code you will need to assert that the contribution is in accordance to the "Developer's Certificate of Origin" as found in the file DCO.txt.
To indicate that, make sure that your contributions (patches or merge requests), contain a "Signed-off-by" line, with your real name and e-mail address. To automate the process use "git am -s" to produce patches and/or set the a template to simplify this process, as follows.
$ cp devel/git-template ~/.git-template  $ git config commit.template ~/.git-template
New functionality should be accompanied by a test case which verifies the correctness of GnuTLS' operation on successful use of the new functionality, as well as on fail cases. The GnuTLS test suite is run on "make check" on every system GnuTLS is installed, except for the tests/suite part which is only run during development.
For testing functionality of gnutls we use two test unit testing frameworks:
- The gnutls testing framework as in utils.h, usually for high level tests such as testing a client against a server. See set_x509_key_mem.c.
- The cmocka unit testing framework, for unit testing of functions or interfaces. See dtls-sliding-window.c.
Certificates for testing purposes are available at cert-common.h. Note that we do not regenerate test certificates when they expire, but we rather fix the test's time using datefudge or gnutls_global_set_time_function(). For example, see x509cert-tl.c.
Files are split to directories according to the subsystem they belong to. Examples are x509/, minitasn1/, openpgp/, opencdk/ etc. The files in the root directory related to the main TLS protocol implementation.
While parts of GnuTLS were written in older dialects, new code in GnuTLS are expected to conform to C99. Exceptions could be made for C99 features that are not supported in popular platforms on a case by case basis.
In general, use the Linux kernel coding style. You may indent the source using GNU indent, e.g. "indent -linux *.c".
All the function names use underscore
_, to separate words,
gnutlsDoThat are not used. The exported function names
usually start with the
gnutls_ prefix, and the words that follow
specify the exact subsystem of gnutls that this function refers to.
gnutls_x509_crt_get_dn, refers to the X.509
certificate parsing part of gnutls. Some of the used prefixes are the
gnutls_x509_crt_for the X.509 certificate part
gnutls_openpgp_key_for the openpgp key part
gnutls_session_for the TLS session part (but this may be omited)
gnutls_handshake_for the TLS handshake part
gnutls_record_for the TLS record protocol part
gnutls_alert_for the TLS alert protocol part
gnutls_credentials_for the credentials structures
gnutls_global_for the global structures handling
Internal functions -- that are not exported in the API -- should
be prefixed with an underscore. E.g.
Internal structures should not be exported. Especially pointers to internal data. Doing so harms future reorganization/rewrite of subsystems.
All exported functions must be listed in libgnutls.map.in, in order to be exported.
The constructed types in gnutls always have the
Definitions, value defaults and enumerated values should be in
Structures should have the
_st suffix in their name even
if they are a typedef. One can use the sizeof() on types with
_st as suffix to get the structure's size.
Other constructed types should have the
_t suffix. A pointer
to a structure also has the
The gnutls functions accept parameters in the order:
- Input parameters
- Output parameters
When data and size is expected, a gnutls_datum structure should be used (or more precisely a pointer to the structure).
Callback function parameters:
Callback functions should be avoided, if this is possible. Callbacks that refer to a TLS session should include the current session as a parameter, in order for the called function to be able to retrieve the data associated with the session. This is not always done though -- see the push/pull callbacks.
Functions in gnutls return an int type, when possible. In that case 0 should be returned in case of success, or maybe a positive value, if some other indication is needed.
A negative value always indicates failure. All the available error codes are defined in gnutls.h and a description is available in gnutls_errors.c
Usage of assert()
The assert() macro --not to be confused with gnutls_assert()-- is used exceptionally on impossible situations to assist static analysis tools. That is, it should be used when the static analyzer used in CI (currently clang analyzer), detects an error which is on an impossible situation. In these cases assert() is used to rule out that case.
For example in the situation where a pointer is known to be non-null, but the static analyzer cannot rule it out, we use code like the following:
assert(ptr != NULL); ptr->deref = 3;
Since GnuTLS is a library no other uses of assert() macro are acceptable.
The NDEBUG macro is not used in GnuTLS compilation, so the assert() macros are always active.
Parts of the Guile bindings, such as types (aka. "SMOBs"), enum values, constants, are automatically generated. This is handled by the modules under `guile/modules/gnutls/build/'; these modules are only used at build-time and are not installed.
The Scheme variables they generate (e.g., constants, type predicates,
etc.) are exported to user programs through
gnutls/extra.scm', both of which are installed.
For instance, when adding/removing/renaming enumerates or constants, two things must be done:
Update the enum list in
build/enums.scm' (currently dependencies are not tracked, so you have to run "make clean all" inguile/' after).
Update the export list of
Note that, for constants and enums, "schemefied" names are used, as noted under the "Guile API Conventions" node of the manual.