Git Product home page Git Product logo

rnl's Introduction

Warning

RNL including its cryptography code is non-audited so far, thus RNL is only intended for real-time games and multimedia applications without processing of any with critical data, but not for serious applications with critical data!

Description

RNL stands for "Realtime Network Library"

RNL is an UDP-based network library for real-time applications and games, inspired by ENet, yojimbo, libgren, and so on.

RNL is designed around common patterns used in real-time games, which are simulation bound, not I/O bound, and completely stateful, so async IO does not make a lot of sense. Thus the RNL core design is single-threaded, not multi-threaded. But you can use multiple TRNLHost instances inside multiple different threads (one to very few instances per one thread), so that you can host multiple network game matches at the same machine, as long as this one machine is strong and fast enough for hosting multiple network game matches at the same time.

And at game client side, the whole network stuff should run, if possible, in an own (also if possible, CPU-core-pinned) thread, for possible few interferences and other similiar problems. (offtopic: the same also applies to the audio thread, unless one likes possible audio buffer underrun issues and so on, when it did not get enough CPU time at the right time points. :-) )

And for larger games with masses of clients in a single game world, you should use several subdivided TRNLHost instances, so that each TRNLHost must handle only few connected clients, in multiple threads and that in turn on multiple physical dedicated servers, which also in turn may communicate with each other to mimic the impression of a single very large game world. At least a single TRNLHost instance is rather designed for typical low client numbers, as these are the typical case for egoshooters, racing games, and so forth. Or in other words for large game worlds with masses of clients: Divide and conquer (for example with partially sector-border overlapping game world sectors for just as an example of an divide-and-conquer concept idea)

Support me

Support me at Patreon

Features

  • Mostly fully object oriented code design
  • IPv6 support
  • Cross platform
    • Windows (with FreePascal and Delphi)
    • Linux (with FreePascal)
    • *BSD (with FreePascal)
    • Android (with FreePascal and Delphi)
    • Darwin (MacOS(X) and iOS) (with FreePascal and Delphi)
  • UDP-based protocol
  • Sequencing
  • Channels
    • With following possible free configurable channel types:
      • Reliable ordered
      • Reliable unordered
      • Unreliable ordered
      • Unreliable unordered
  • Reliability
  • Fragmentation and reassembly
  • Aggregation
  • Adaptability
  • Portability
  • Possibility of using a peer-to-peer model or even a mixed peer-to-peer and client/server hybrid model instead only a pure client/server model, and of course also of a classic client/server model
  • Cryptographically secure pseudo-random number generator (CSPRNG)
    • Based on arc4random but with ChaCha20 instead RC4 as the basic building block
    • Multiple sources of entropy (because you should never trust a single source of entropy, as it may have a backdoor)
      • Including usage of the rdseed/rdrand instructions on newer x86 processors as an optional additional quasi-hardware-based entropy source, if these instructions are supported by the current running processor
  • Mutual authentication
    • Based on a Station-to-Station (STS) like protocol, which assumes that the parties have signature keys, which are used to sign messages, thereby providing minification security against man-in-the-middle attacks, unlike the basic plain Diffie-Hellman method without any so such extensions.
    • Long-term private/public keys are ED25519 keys and are used only for signing purposes
  • Forward secrecy using elliptic curve ephemeral Diffie-Hellman (curve 25519)
    • The consequence of this along other facts is that each connection always has new different private and public short-term keys on both sides and therefore also new shared secret short-term keys
    • Short-term private/public keys are X25519 keys and the short-term shared secret key is using only for AEAD-based ciphering purposes
  • Authenticated Encryption with Associated Data (AEAD) packet encryption
    • Based on ChaCha20 as cipher and Poly1305 as cryptographic message authentication code
  • Replay protection of application packet data
    • Based on various protection mechanisms at the connection establishment phase and encrypted packet sequence numbers
  • Delayed connection establishment mechanism as an additional attack surface minification mechanism
  • Connection and authentication tokens (as an optional option, where you should have a separate out-of-band communication channel, for example a HTTPS-based master backend for to generate and handle this stuff) as an additional attack surface minification mechanism against DDoS amplification attacks
    • Connection token are transferred in clear text, so that they are checked in a fast way at the first ever data packet from a connection attempt, without the need to decrypt the connection token first before it is possible to check the token, so in order to save CPU time in this point. This option is primarily for use in against DDoS amplification attacks, which means that the server will not respond straight away if the connection token does not match at the first ever data packet from a connection attempt, and thus DDoS amplification attacks would simply go into the nothing. Consequently, these tokens should only be valid for a short period of time, which also applies to the master backend side of your infrastructure.
    • Authentication tokens are transferred encrypted, after the private/public key exchange, shared secret key generation, etc. were successfully processed. Authentication tokens, in contrast to the connection token, are NOT a countermeasure against DDoS-category attacks, but rather authentication tokens are, as the name suggests, only for separate out-of-band communication channel authentication purposes, in other words, as additional protection against unauthorized connections, where you can check it in more detail on your master backend side of your infrastructure, before the "client" can connect to the real server, where all the real action happens.
  • Connection attempt rate limiter
    • Configurable with two constants, burst and period
  • Configurable bandwidth rate limiter
  • Optional virtual network feature (for example for fast network-API-less local loopback solution for singleplayer game matches, which should be still server/client concept based)
  • Network interference simulator (for example for testcases and so on)
    • Configurable simulated packet loss probability (each for incoming and outgoing packets)
    • Configurable simulated latency (each for incoming and outgoing packets)
    • Configurable simulated jitter (each for incoming and outgoing packets)
    • Configurable simulated duplicate packet probability (each for incoming and outgoing packets)
  • Dynamic connection challenge request response difficulty adjustment mechanism
    • Configurable with a factor value
    • Based on history-smoothing-frames-per-second-style determination mechanism, but just instead frames per second, connection attempts per second
  • More compression algorithms as choices
    • Deflate (a zlib bit-stream compatible LZ77 and canonical Huffman hybrid, only fixed-static-canonical-huffman in this implementation here on compressor side, but the decompressor side is full featured)
    • LZBRRC (a LZ77-style compressor together with an entropy range coder backend)
    • BRRC (a pure order 0 entropy range coder)
  • CRC32C instead CRC32 (without C at the end)
  • And a lot of more stuff . . .

Planned features (a.k.a Todo) in random order of priorities

  • TODO

General guidelines for code contributors

General guidelines for code contributors

License

zlib License

IRC channel

IRC channel #rnl on Freenode

Thanks

  • Thanks to Lee Salzman for ENet as inspiration for the base API design implementation ideas
  • Thanks to Glenn Fiedler for inspiration for security-oriented implementation ideas
  • Thanks to Sergey Ignatchenko ("No Bugs" Hare) for inspiration also for security-oriented implementation ideas

rnl's People

Contributors

bero1985 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rnl's Issues

Example project crashes under lazarus on this line

Works fine when compiled on lazarus x64 but crashes when compiled in x86 version.
Weird thing is it doesn't happen on my Win10 Home x64 development machine, crashes on remote Win10 Pro x64. CPU: Intel Core Processor (Broadwell)

rnl/src/RNL.pas

Line 9911 in 9e5c6d5

PStateQWords(TRNLPointer(State))^[Index]:=PStateQWords(TRNLPointer(State))^[Index] xor

Figured out I can just jmp through the asm code as this CPU clearly doesn't support this feature. This all happens on a VM btw.

Have more examples?

I want to use RNL, but I'm not familiar with RNL, can you write more documents or examples? Thank you.

Repeatedly connecting and breaking the client connection can lead to 1. unreliable messages, 2. server crash

I did some "stress testing" (aka "I was doing stupid things to see if something breaks" :) ). I was using the example examples/combinedexample/combinedexample.dpr , only minimally modified to display some additional information (patch below, although it probably doesn't matter).

If I exit the client gracefully (by pressing enter, so it disconnects nicely) things work always OK in my tests.

But if I start to kill the processes of the client (by Ctrl + C in console), I can break things. My test: I execute combinedexample Server in one console, and then repeatedly execute combinedexample Client in the other console, killing the client with Ctrl + C before executing the combinedexample Client again. There are two issues I can reproduce (after ~21 runs of the client) :

  1. Sometimes (seldom, but sometimes) some message is lost for a new client. It seems that sometimes the client does not receive all 4 messages. See how ""Hello another world in an world! Yet another hello world with an yet another hello world!" is missing for some client invocations in attached client.txt.

    I waited a bit -- I was not killing the process immediately with Ctrl + C. So it seems that the message was lost. If I understand correctly, this should not happen -- channel 0 is RNL_PEER_RELIABLE_ORDERED_CHANNEL , so message should be eventually always delivered?

  2. After ~21 executions of the client this way, the server crashes:

    Server thread failed with exception class ERangeError
    Exception Message: Out of index range
    Stack trace:
      $00000000004EC8D6 line 8272 of ../../src/RNL.pas
    

    A malicious user could crash the server this way (by repeatedly connecting + killing the client).

A attach a full log from server and client console. Note that, even though I was killing the client processes sequentially (I always killed the previous client before starting the new one), the server was receiving the "A client disconnected" with some delay, sometimes after the next client already connected. Possibly this is related to the observed problems.

My environment is FPC 3.0.2 on Linux x86_64.

Attachments:

client.txt

server.txt

unimportant_id_log.patch.txt

TRNLHostEvent - trashing variables

If -gt compiler option is used in freepascal, which i use frequent to identify uninitialized variables, RNL fails to function correctly:

Without -gt EnetHost.Service has correct data:
https://i.imgur.com/Y3BYB8H.png

With -gt, you can see that not all data is properly initialized to event parameter:
https://i.imgur.com/tbs3Gf4.png

This happens on call to fEventQueue.Dequeue within TRNLHost.DispatchIteration.

There is a call to: TRNLQueue.Dequeue - when fCount>0 fails, OUT parameter result becomes undefined.

In your example, you use (Server.Service(Event,1000)<>RNL_HOST_SERVICE_STATUS_ERROR) to check if event is to be processed, but not if it's RNL_HOST_SERVICE_STATUS_TIMEOUT - which is the case where event's message will be invalid data, your example would also crash if compiled with -gt switch, i'd recommend just leaving the event as-is if there's nothing to deque - maybe by changing parameter from out to var parameter, leaving the original, blank initialized struct in return.

only work on windows?

TRNLHost has TRNLInstance, but TRNLInstance has load kernel32.dll, so only work on windows?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.