website/docs/dev/network.md
This document describes how the network layer of Garnet server is designed and the various classes it uses to perform network operations to communicate with the client.
On initialization, GarnetServer instantiates GarnetServerTcp object to handle incoming network connections.
Its Start method, invoked when the GarnetServer starts, binds to the IP address and port as specified in the config (See Configuration page) and begins accepting new connections from clients. It also registers AcceptEventArg_Completed as the callback function to be invoked on receiving a new connection.
The AcceptEventArg_Completed method that is called when a new connection is accepted, handles the new connection by creating a new ServerTcpNetworkHandler object and adding it to the activeHandlers dictionary using the HandleNewConnection method.
The ServerTcpNetworkHandler performs the following steps to receive and process the incoming data.
LimitedFixedBufferPool class. See LimitedFixedBufferPool for details.RecvEventArg_Completed as the callback method to receive data from the socket.SslStream.AuthenticateAsServerAsync method, depending on whether TLS encryption is enabled.The base class NetworkHandler provides functionality for handling network communication, including sending and receiving data over a network connection.
The main parts of the class:
Start and StartAsync methods are used to begin the network handler, including the authentication phase if TLS is enabled. These methods take optional parameters such as TLS options and remote endpoint name. They internally call the AuthenticateAsServerAsync or AuthenticateAsClientAsync methods to perform authentication.AuthenticateAsServerAsync and AuthenticateAsClientAsync methods handle authentication process for TLS connections. They use the sslStream object to perform the authentication and establish a secure connection. These methods also handle reading any extra bytes left over after authentication.OnNetworkReceive method is called when data is received from the network. This method is responsible for processing the received data. It first checks the status of the TLS reader and performs the necessary transformations on the network and transport receive buffers. Then, it calls the Process method to handle the received data.Process method is responsible for processing the received data. It checks if there is any data in the transport receive buffer and if there is a message consumer available. If so, it tries to process the request by calling the TryProcessRequest method. The message consumer is responsible for retrieving the session provider based on the wire protocol - ASCII is the only format supported currently. The session provider is previously registered when the Garnet server is initialized. The retrieved session provider is then used to create a new session object, if one doesn't exist already. For processing messages, the GarnetProvider class is registered as the session provider and is used to create objects of RespServerSession class to handle RESP messages.The GarnetTcpNetworkSender class is a TCP network sender that inherits from the NetworkSenderBase class. It is responsible for sending network data over a TCP connection for response messages back to the client. This is instantiated as part of creation of the ServerTcpNetworkHandler object.
GarnetSaeaBuffer objects to manage reusable send buffers. These buffers are created using a networkPool field of type LimitedFixedBufferPool. These buffers are used to store the data that is to be sent over the network.The LimitedFixedBufferPool class is a memory pool implementation that provides a pool of memory segments of varying sizes. It is designed to efficiently manage memory allocations and deallocations for improved performance in scenarios where frequent memory allocation and deallocation operations are required. It does this using an array of concurrent queues. Each concurrent queue represents a memory segment of a specific size range. The class provides methods to allocate and deallocate memory segments from the pool.
LimitedFixedBufferPool class is designed to be thread-safe and can be used in multi-threaded scenarios.LimitedFixedBufferPool class is disposable and should be disposed when no longer needed to release allocated memory segments.The Get method allocates a memory segment from the pool for the requested size. It returns a PoolEntry object representing the allocated memory segment.
The Return method returns a memory segment to the pool for reuse.
The LimitedFixedBufferPool class internally uses the PoolEntry class to represent memory segments. The PoolEntry class provides methods to reuse and manage the allocated memory segments.