Tip of the day: You can add a Webhook that is called on certain log events.

This can be used to automate things or to notify you in case of trouble.

Dev:Coding guidelines

From UnrealIRCd documentation wiki
Jump to navigation Jump to search

This article explains how to setup your development environment and how to contribute code to UnrealIRCd.

Getting started

Setting up the development environment

When developing, always build with AddressSanitizer enabled. See the question near the end of ./Config. AddressSanitizer (ASan) catches memory issues the moment they happen. Without ASan the IRCd may crash hours later without any meaningful trace.

If you are going to use Visual Studio Code - like the main dev - then check out Dev:Visual Studio Code. This also helps you with automatic indent/formatting.

Navigating around the source

The Doxygen docs show the UnrealIRCd API. This may be a good place to start if you are looking for something in particular (used as a reference guide).

Most of our docs regarded to programming assume you are writing a 3rd party module, eg:

  • Dev:Module has some good words on how to start, including an howto on writing your first 3rd party mod
  • Dev:Module API contains some of the module API

In general, reading existing UnrealIRCd code may help understanding how things work in UnrealIRCd. It's usually best to read something clear and self-contained, like a module (or a 3rd party module).

When to discuss first

At UnrealIRCd, a PR is for code that is ready to be merged, it is not intended to propose or discuss a change.

Please discuss the following changes on the bugtracker before you start working:

  • Feature suggestions
  • Major cleaning/rewriting of existing code
  • Changes to the protocol (both client and server), no matter how small the change is
  • Breaking the module API

This way, the main coders may still suggest to do things in a particular way or indicate that we don't want such a change.

Anything not in the list above, such as bugfixes and small improvements, can be submitted as a patch/PR immediately.

Code style

Code formatting

Code formatting is fully automated. The rules live in the .clang-format file in the source and you apply them by running make format (this requires clang-format major version 21). The easiest way is to let your editor format on save, see Dev:Visual Studio Code. Pull requests containing unformatted code will be rejected by the CI.

A few things are deliberately not auto-formatted: hand-formatted tables and similar are surrounded by /* clang-format off */ and /* clang-format on */ markers. Only use these markers when manual layout genuinely is more readable, such as in large data tables.

Git pre-commit hook

Developers with commit access are assumed to have a git pre-commit hook that refuses unformatted code. Save the following as .git/hooks/pre-commit and make it executable (chmod +x):

#!/bin/sh
# Check-only hook: refuse to commit code that is not clang-formatted.
# Never modifies anything. Bypass once with: git commit --no-verify
output=$(git clang-format --staged --diff 2>/dev/null)
case "$output" in
	""|"no modified files to format"*|"clang-format did not modify any files"*)
		exit 0
		;;
	*)
		echo "ERROR: Commit rejected: staged changes are not clang-formatted."
		echo "Run 'make format', review the result, and commit again."
		echo "(Bypass once with: git commit --no-verify)"
		exit 1
		;;
esac

This requires git-clang-format, which comes with clang-format on most distributions.

Again, you should use clang version 21 here. If you have multiple clang versions installed, then tell it which one to use with: git config clangFormat.binary clang-format-21

Major restructuring or cleanups

If you want to restructure or clean up existing code beyond a bug or isolated feature you are working on, then you MUST discuss it first. The stable tree is often not really suitable for such things, especially if we are talking multiple files etc.

Also be careful with cleanups in general: if something looks redundant or useless at first sight, look again. It may indeed be useless, but it may also be a subtle thing that creates great bugs when 'cleaned up'.

Comments

Comment your code. It will help the next person reading it, and it will help you when you look at your own code two years later. If there is some obscure pitfall in the code, then DO mention it. Don't just hope the next author will see it like you did.

For documenting functions and struct members we use doxygen style comments: /** Like this */. Regular comments use /* this style */. Using // is acceptable for a short single-line remark, but multi-line comments always use /* */. Don't mass-convert comments from one style to the other.

Writing good code

String handling

Be careful about overflows, do not do any unchecked string copies. Instead of strcpy, strcat and sprintf, use the length-checking functions: strlcpy, strlcat and snprintf/ircsnprintf. If you are copying or writing character-by-character in a loop, for example using *p++ = x;, then be very sure about your size counting. Often it is better to avoid such code altogether and simply use strlcat and similar functions for everything.

Memory

Use safe_alloc, safe_free, safe_strdup and safe_strldup. These functions properly initialize memory (such as structs) with zeroes.

Do NOT use malloc, calloc, free or strdup directly.

Logging

All (new) code uses unreal_log() for logging and server notices (snomasks, etc). Don't use legacy calls. Exceptions are config_warn/config_error in config code.

Readability comes first

When writing or optimizing code, readability and stability come FIRST, speed comes after that.

We prefer readable code over a highly optimized routine that nobody understands, is difficult to extend, and might have several bugs.

Portability

The minimum is a C99 compiler, which ./configure enforces. In practice the code is built as C17 with GNU extensions on *NIX.

Code must also compile on Windows with Visual Studio 2019, so don't use exotic compiler-specific extensions.

Enums

  • Use enums rather than #define constants whenever possible. It is cleaner and it aids debugging. For bit flags, we still use defines.

Before you commit

Test your code

Very important: TEST your code before committing or doing a Pull Request. Not just that it compiles, but also that it does what you want. Yes, also that one line change that you are 100% sure about breaks nothing :-)

For bigger changes or if you are dealing with any memory stuff, please run with AddressSanitizer (see ./Config).

There is also a test suite which the CI runs on every push and pull request.

Copyright

  • New files must contain a proper copyright header. UnrealIRCd is GNU GPLv2 or later, so it must be compatible.
  • If code from other people or projects is used, it MUST be properly credited (and again, the license must permit it).

Security issues

If you found a security issue, then do NOT report or discuss it on the public bug tracker. Also do not submit a fix as a PR. See Policy: Handling of security issues for how to report it privately.

IMPORTANT: A crash issue that a regular user can trigger is considered a security issue! Follow the procedure above.

Submitting patches

You can submit patches either as a Pull Request (PR) on GitHub or by attaching a patch file (diff -u) at a bug item at the bugtracker.

It really helps if your pull request references an entry on https://bugs.unrealircd.org/, since that is where development is coordinated and discussion takes place. If there is no bug# then a PR is more likely to be overlooked (sorry).

Make sure you target your PR for UnrealIRCd 6, so the unreal60_dev branch

Use of AI

Did you use AI? Don't worry, we use AI ourselves as well. But please check out our policy on the use of AI to see if you need to disclose this. It also contains a FAQ covering three common cases.

Developers with commit access

The following applies to developers who commit directly to the repository, including when merging someone else's pull request.

Changes that need prior discussion

The rules about discussing changes also apply to developers. Especially since commits go in directly, without any review.

Commit messages

The following applies to commits from yourself and if you merge someones PR:

  • The first line of the commit message is a short summary of max 70 characters. This is what GitHub and git log --oneline show in commit overviews, so it must make sense on its own.
  • The rest of the commit message should explain what you changed and why.
  • If there is a related item on bugs.unrealircd.org you end the commit message with:
    Reported by XYZ in https://bugs.unrealircd.org/view.php?id=####
    It is important to credit people: they have taken the time to report an issue/feature so they deserve credit.

After committing

If the commit relates to a bug# on bugs.unrealircd.org:

  • Mark the issue as 'Resolved' and set the 'Fixed in version' to the future release
  • In the comment on the bug tracker copy-paste the commit reference: at least the github URL to the commit, but preferably the copy-paste of 'git log' that is relevant

Version files

Do not touch version.c.SH or version.h. Those are for the head coders, as part of doing releases.