NoxVR Documentation
Relay Protocol

Overview

Système de communication réseau de NOX pour gérer les connexions entre clients et serveurs

Le Relay Protocol est un système de communication réseau utilisé par NOX pour gérer les connexions entre les clients et les serveurs.

Il utilise à la fois TCP et UDP pour permettre la compatibilité de connexion des clients.

Architecture Générale

Le Relay NOX fonctionne comme un serveur proxy intelligent qui :

  • Reçoit les connexions TCP et UDP des clients
  • Route les messages entre les clients connectés
  • Gère l'authentification et les sessions

Format des Paquets

Tous les paquets suivent une structure commune :

Structure de Base

Pour plus de clareté, les structures de base sont présentées sous le format si dessous, L'explication du format est détaillée en bas de page.

[length: ushort]
[uid: ushort]
[type: byte]
[payload: byte[]]

Structure détaillée

TypeNomDescription
ushortLengthTaille totale du paquet (inclut Length)
ushortUIDIdentifiant unique (optionnel)
byteTypeType de requête/réponse
byte[]PayloadDonnées du message

Constantes Importantes

  • Version du protocole : 1
  • Taille max paquet : 1024 bytes
  • Port par défaut : 23032
  • Timeout connexion : 15 secondes
  • Intervalle keep-alive : 5 secondes
  • Timeout segmentation : 30 secondes

Unique Identifier (UID)

Le champ UID permet de faire un callback d'une requête spécifique. Si le message vient du serveur, le client doit répondre avec le même UID. Et l'UID de 0x0000 pour indiquer qu'il n'attend pas de réponse ou par défaut.

Timeout et Keep-Alive

Le timeout est réinitialisé à chaque réception de paquet valide. En cas d'absence de paquets à envoyer, c'est le client qui doit envoyer un packet (ex: Latency) dans un délai inférieur à la valeur de timeout pour maintenir la connexion active. C'est le client qui doit gérer l'envoi de keep-alive.

Exemple de Flux de Communication

  1. Handshake : Le client initie la connexion avec un message Handshake.
  2. Authentification : Le client s'authentifie avec un message Authentification.
  3. Session : Pour obtenir des informations sur une instance.
  4. Enter : Pour rejoindre une instance.
  5. Disconnect : Pour une déconnexion propre, le client sera automatiquement retiré des sessions auxquelles il est connecté.

Système de Priorités

Le protocole utilise un système de priorités pour optimiser les performances :

  • Critical : Handshake, Disconnect
  • High : Authentification, Enter/Quit
  • Normal : Transform, Status
  • Low : Custom messages (ces packets risquent d'être retardés ou perdus en cas de congestion)

Sécurité

  • Validation de protocole lors du handshake
  • Authentification requise avant toute action (sauf si le serveur est en offline mode)
  • Limitation de taille des paquets (1024 bytes max, ou personnalisé par le serveur)

Types de Messages (Client → Serveur)

Le protocole supporte les types de messages suivants que les clients peuvent envoyer au serveur :

TypeNomDescriptionPriorité
0x00DisconnectDéconnexion propreCritical
0x01HandshakeInitialisation de connexionCritical
0x02SegmentationFragmentation de gros messagesNormal
0x03ReliableMessages fiablesNormal
0x04LatencyTest de latenceNormal
0x05AuthentificationValidation d'identitéHigh
0x06EnterRejoindre une instanceHigh
0x07QuitQuitter une instanceHigh
0x08CustomMessages personnalisésNormal
0x09PasswordRequirementDemande de mot de passeHigh
0x0ATravelingDéplacement entre instancesNormal
0x0BTransformPosition/rotation en temps réelNormal
0x0CTeleportTéléportation instantanéeHigh
0x0DAvatarChangedChangement d'avatarNormal
0x0EServerConfigConfiguration serveurHigh
0x0FAvatarParamsParamètres d'avatarNormal
0x11SessionsPermet d'obtenir les informations des sessionsNormal

Types de Réponses (Serveur → Client)

Le serveur utilise un ensemble différent de types pour ses réponses et notifications :

TypeNomDescriptionOrigine
0x00DisconnectConfirmation/notification de déconnexionRéponse
0x01HandshakeConfirmation du handshakeRéponse
0x02SegmentationFragmentation de réponsesRéponse
0x03ReliableRéponses fiablesRéponse
0x04LatencyRéponse de test de latenceRéponse
0x05AuthentificationRésultat d'authentificationRéponse
0x06EnterRésultat d'entrée dans instanceRéponse
0x07QuitConfirmation de sortieRéponse
0x08CustomRéponses personnaliséesRéponse
0x09PasswordRequirementRéponse mot de passeRéponse
0x0ATravelingConfirmation de déplacementRéponse
0x0BTransformSynchronisation de positionRéponse/Notification
0x0CTeleportConfirmation de téléportationRéponse
0x0DAvatarChangedNotification changement avatarRéponse/Notification
0x0EServerConfigNotification changement configRéponse/Notification
0x0FAvatarParamsNotification paramètres avatarRéponse/Notification
0x10JoinNotification arrivée joueurNotification
0x11LeaveNotification départ joueurNotification
0x12SessionsInformations des sessionsRéponse

Informations importantes :

  • Réponses : Messages envoyés en réaction directe à une requête client (même UID)
  • Notifications : Messages automatiques envoyés par le serveur (UID = 0x0000)

Chaque type de message a sa propre page de documentation détaillée avec les formats d'entrée et de sortie spécifiques.

Types des Données

Le protocole utilise plusieurs types de données pour structurer les messages. Voici les types supportés :

TypeTaille (bytes)Description
byte1Entier non signé 8 bits
short2Entier signé 16 bits (big-endian)
ushort2Entier non signé 16 bits (big-endian)
int4Entier signé 32 bits (big-endian)
uint4Entier non signé 32 bits (big-endian)
long8Entier signé 64 bits (big-endian)
ulong8Entier non signé 64 bits (big-endian)
float4Nombre flottant simple précision (big-endian)
double8Nombre flottant double précision (big-endian)
string2 + NChaîne UTF-8 avec préfixe de longueur (ushort)
DateTime8Timestamp Unix en millisecondes
Vector3123 composants float (X, Y, Z)
Quaternion164 composants float (X, Y, Z, W)
byte[]NTableau d'octets
EnumVariableÉnumération/Flags (selon le type sous-jacent)

Notes Importantes

  • Ordre des octets : Tous les types multi-octets utilisent l'ordre big-endian (byte de poids fort en premier)
  • Chaînes de caractères : Encodées en UTF-8 avec un préfixe ushort indiquant la longueur
  • Timestamps : Stockés comme des timestamps Unix en millisecondes (long)
  • Énumérations : Sérialisées selon leur type sous-jacent (byte, ushort, uint)

Dans le protocol, la lecture se fait octet par octet. Donc certains types de données ne sont pas permit comme les booléens qu'il faut convertir en byte ou en flags avec d'autres booléens.

Syntaxe des Packets dans la Documentation

Chaque message dans la documentation est présenté avec une syntaxe claire pour le format des paquets.

[Length: ushort]
[UID: ushort]
[Type: byte]
[Payload?: byte[]]
(0x01 in Type ? [Reason?: string])
(Latency == Type ? (
    [ClientTimestamp: DateTime]
    [ServerTimestamp: DateTime]
))

Chaque champ est décrit sous forme d'entrée entre crochets [] avec le nom du champ, son type. Quand un champ est optionnel, un ? est ajouté avant les :. Quand on regroupe une liste de champs, on les mets entre parenthèses (). De même quand il y a une condition, on utilise la même syntaxe (Condition ? [Field]) ou (Condition1 ? [Field1] : [Field2]). Les champs sont listés dans l'ordre d'apparition dans le paquet.