= Introduction = The OpenVPN 2.4+ coding style is based on the Allman style, e.g.: {{{#!c void myfunction(int a, int b) { const char *dummy = "Hello world!"; if (a == b) { something_equals(dummy); } else { does_not_equal(dummy); } } }}} Summarizing: * Indentation is 4 spaces, no tabs ever. * Opening and closing brackets get their own line, and must match indentation. * Line length is 80 characters (soft limit) but may be extended up to 120 if wrapping makes the result less readable / more ugly * C99 is allowed. E.g. `for (int i = 0; i < max; i++)`. * Only use `/* */`-style comments = Line wrapping = The maximum line length is 80 characters. When statements exceed this length, wrap them by aligning with the appropriate `(`, or otherwise using a single indent (i.e. 4 spaces) on the new line. For example: {{{#!c void my_function(void) { if (variable_with_artificially_long_name_1 != 0 && variable_with_artificially_long_name_2 != 0) { return variable_with_artificially_long_name_1 + variable_with_artificially_long_name_2 + variable_with_artificially_long_name_3; } } }}} If you find yourself continuously exceeding the line limit, you might want to consider breaking up your function into smaller functions to reduce nesting. Single lines may use up to 120 characters if the resulting code is more readable than if wrapped. But this should be an exception, no whole code blocks should be written with "more than 80 as a general norm". = Some additional secure coding style rules = This are **style rules**, ''not'' general secure coding guide lines. See e.g. https://www.securecoding.cert.org/confluence/display/c/SEI+CERT+C+Coding+Standard for useful guidelines on writing secure C. == All branches must use braces == For example: {{{#!c if (a) { return true; } }}} We wouldn't be the first to not spot missing braces in an if statement, like what happened in Apple's [[https://www.imperialviolet.org/2014/02/22/applebug.html|goto fail;]] bug. Always using braces prevents this kind of mistake. == Cases in a switch statement should break or explicitly fall through == The only exception to this rule are empty case statements, to not overly clutter the code with comments. For example: {{{#!c switch (a) { case ONE: case TWO: one_or_two = true; /* Fall through */ case THREE: now_do_something(); break; default: ASSERT(0); } }}} This makes the intent immediately clear to the reader / reviewer. = Portability concerns = == Printing time_t and suseconds_t values == POSIX specifies that time_t is an integer type but does not specify its size. The underlying type might be `int`, `long` or `long long`, some systems might make it unsigned too. This makes it hard to portably print `time_t` values using printf-like APIs, as a mismatch between the format string and the actual `time_t` size can lead to crashes or bogus representations. The safest way is to print `time_t` values after casting to `int64_t` and using `PRIi64` as format specifier. Casting to a 64 bits wide `int` avoids y2038 problems and `PRIi64` is preferred over `%lld` as the latter is not supported in the windows runtime targeted by mingw. Similarly, POSIX specifies `suseconds_t` as a signed integer, but does not specify its size. Casting it as a long is enough. {{{#!c struct timeval now; gettimeofday(&now, NULL); printf("%"PRIi64".%06ld\n", (int64_t)now.tv_sec, (long)now.tv_usec); }}} = Windows specific = OpenVPN core uses UTF-8 encoding for strings. These may be converted to and from UTF-16 used in Windows as required. Declare all strings explicitly as `char *` or `wchar_t *`. Use of `TCHAR` is not allowed. Call Windows API functions using their explicit ANSI or wide character variants: e.g., {{{CreateFileW}}} or {{{CreateFileA}}} instead of {{{CreateFile}}}. The core executable for Windows is built without `-DUNICODE` and `-D_UNICODE`. Sources for Windows-only executables and libraries such as ''openvpnserv.exe'', ''tapctl.exe'' and ''openvpnmscia.dll'' partially depend on `UNICODE` (and in some cases `_UNICODE`) defined. Also there is a widespread use of `TCHAR` as well as function names that resolve to single-byte or wide character variants depending on whether `UNICODE` is defined or not. However, in spite of appearances to the contrary, non-unicode builds are no longer supported. In new code declare wide strings as `wchar_t *` or `WCHAR *`. One may implicitly assume that all existing `TCHAR` would evaluate to `WCHAR`. For runtime and API calls use explicit function names instead of depending on `UNICODE` and/or `_UNICODE` are defined or not. In particular, do not use `_tprintf` family of stdio functions. Instead, use `wprintf` or `printf` variants as required. Use `%ls` as the print format specifications for wide strings. For narrow strings, `%s` may be used in `printf` family of functions, but in `wprintf` family use `%hs`. Do not use `%S`. For example, given the existing function, {{{#!c MsgToEventLog(DWORD flags, LPCTSTR lpszMsg, ...); }}} a new code snippet that calls it would be written as {{{#!c const wchar_t *username; const char *config; ... MsgtoEvenLog(M_SYSERR, L"Failed to authorize profile <%hs> for user <%ls>", config, username); }}} = Uncrustify rules = The most fit tool for our purpose (because it can be told to just leave certain constructs alone, while changing others) seems to be {{{ uncrustify -c dev-tools/uncrustify.conf tun.c }}} You can find our current config in the `dev-tools` directory in the git repository: https://github.com/OpenVPN/openvpn/blob/master/dev-tools/uncrustify.conf