src/openvpn/reliable.h
6fbf66fa
 /*
  *  OpenVPN -- An application to securely tunnel IP networks
  *             over a single UDP port, with support for SSL/TLS-based
  *             session authentication and key exchange,
  *             packet encryption, packet authentication, and
  *             packet compression.
  *
49979459
  *  Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
6fbf66fa
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2
  *  as published by the Free Software Foundation.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
caa54ac3
  *  You should have received a copy of the GNU General Public License along
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6fbf66fa
  */
 
0332b951
 
 /**
  * @file
  * Reliability Layer module header file.
6fbf66fa
  */
 
0332b951
 
6fbf66fa
 #ifndef RELIABLE_H
 #define RELIABLE_H
 
 #include "basic.h"
 #include "buffer.h"
 #include "packet_id.h"
 #include "session_id.h"
 #include "mtu.h"
 
0332b951
 /** @addtogroup reliable
  *  @{ */
 
 
8c47de7d
 #define EXPONENTIAL_BACKOFF
6fbf66fa
 
0332b951
 #define RELIABLE_ACK_SIZE 8     /**< The maximum number of packet IDs
                                  *   waiting to be acknowledged which can
                                  *   be stored in one \c reliable_ack
                                  *   structure. */
 
81d882d5
 #define RELIABLE_CAPACITY 8     /**< The maximum number of packets that
0332b951
                                  *   the reliability layer for one VPN
                                  *   tunnel in one direction can store. */
6fbf66fa
 
0332b951
 /**
  * The acknowledgment structure in which packet IDs are stored for later
  * acknowledgment.
  */
6fbf66fa
 struct reliable_ack
 {
81d882d5
     int len;
     packet_id_type packet_id[RELIABLE_ACK_SIZE];
6fbf66fa
 };
 
0332b951
 /**
  * The structure in which the reliability layer stores a single incoming
  * or outgoing packet.
  */
6fbf66fa
 struct reliable_entry
 {
81d882d5
     bool active;
     interval_t timeout;
     time_t next_try;
     packet_id_type packet_id;
     int opcode;
     struct buffer buf;
6fbf66fa
 };
 
0332b951
 /**
  * The reliability layer storage structure for one VPN tunnel's control
  * channel in one direction.
  */
6fbf66fa
 struct reliable
 {
81d882d5
     int size;
     interval_t initial_timeout;
     packet_id_type packet_id;
     int offset;
     bool hold; /* don't xmit until reliable_schedule_now is called */
     struct reliable_entry array[RELIABLE_CAPACITY];
6fbf66fa
 };
 
 
0332b951
 /**************************************************************************/
 /** @name Functions for processing incoming acknowledgments
  *  @{ */
 
 /**
  * Read an acknowledgment record from a received packet.
  *
  * This function reads the packet ID acknowledgment record from the packet
  * contained in \a buf.  If the record contains acknowledgments, these are
  * stored in \a ack.  This function also compares the packet's session ID
  * with the expected session ID \a sid, which should be equal.
  *
  * @param ack The acknowledgment structure in which received
  *     acknowledgments are to be stored.
  * @param buf The buffer containing the packet.
  * @param sid The expected session ID to compare to the session ID in
  *     the packet.
  *
  * @return
  * @li True, if processing was successful.
  * @li False, if an error occurs during processing.
  */
81d882d5
 bool reliable_ack_read(struct reliable_ack *ack,
                        struct buffer *buf, const struct session_id *sid);
0332b951
 
 /**
  * Remove acknowledged packets from a reliable structure.
  *
  * @param rel The reliable structure storing sent packets.
  * @param ack The acknowledgment structure containing received
  *     acknowledgments.
  */
81d882d5
 void reliable_send_purge(struct reliable *rel, struct reliable_ack *ack);
0332b951
 
 /** @} name Functions for processing incoming acknowledgments */
 
 
 /**************************************************************************/
 /** @name Functions for processing outgoing acknowledgments
  *  @{ */
 
 /**
  * Check whether an acknowledgment structure contains any
  *     packet IDs to be acknowledged.
  *
  * @param ack The acknowledgment structure to check.
  *
  * @return
  * @li True, if the acknowledgment structure is empty.
  * @li False, if there are packet IDs to be acknowledged.
  */
 static inline bool
81d882d5
 reliable_ack_empty(struct reliable_ack *ack)
6fbf66fa
 {
81d882d5
     return !ack->len;
6fbf66fa
 }
 
0332b951
 /**
  * Write a packet ID acknowledgment record to a buffer.
  *
  * @param ack The acknowledgment structure containing packet IDs to be
  *     acknowledged.
  * @param buf The buffer into which the acknowledgment record will be
  *     written.
  * @param sid The session ID of the VPN tunnel associated with the
  *     packet IDs to be acknowledged.
  * @param max The maximum number of acknowledgments to be written in
  *     the record.
  * @param prepend If true, prepend the acknowledgment record in the
  *     buffer; if false, write into the buffer's current position.
  *
  * @return
  * @li True, if processing was successful.
  * @li False, if an error occurs during processing.
  */
81d882d5
 bool reliable_ack_write(struct reliable_ack *ack,
                         struct buffer *buf,
                         const struct session_id *sid, int max, bool prepend);
0332b951
 
 /** @} name Functions for processing outgoing acknowledgments */
 
 
 /**************************************************************************/
 /** @name Functions for initialization and cleanup
  *  @{ */
 
 /**
  * Initialize a reliable structure.
  *
  * @param rel The reliable structure to initialize.
  * @param buf_size The size of the buffers in which packets will be
  *     stored.
  * @param offset The size of reserved space at the beginning of the
  *     buffers to allow efficient header prepending.
  * @param array_size The number of packets that this reliable
  *     structure can store simultaneously.
  * @param hold description
  */
81d882d5
 void reliable_init(struct reliable *rel, int buf_size, int offset, int array_size, bool hold);
6fbf66fa
 
0332b951
 /**
  * Free allocated memory associated with a reliable structure.
  *
  * @param rel The reliable structured to clean up.
  */
81d882d5
 void reliable_free(struct reliable *rel);
6fbf66fa
 
0332b951
 /* add to extra_frame the maximum number of bytes we will need for reliable_ack_write */
81d882d5
 void reliable_ack_adjust_frame_parameters(struct frame *frame, int max);
6fbf66fa
 
0332b951
 /** @} name Functions for initialization and cleanup */
6fbf66fa
 
 
0332b951
 /**************************************************************************/
 /** @name Functions for inserting incoming packets
  *  @{ */
 
 /**
  * Check whether a reliable structure has any free buffers
  *     available for use.
  *
  * @param rel The reliable structure to check.
  *
  * @return
  * @li True, if at least one buffer is available for use.
  * @li False, if all the buffers are active.
  */
81d882d5
 bool reliable_can_get(const struct reliable *rel);
6fbf66fa
 
0332b951
 /**
  * Check that a received packet's ID is not a replay.
  *
  * @param rel The reliable structure for handling this VPN tunnel's
  *     received packets.
  * @param id The packet ID of the received packet.
  *
  * @return
  * @li True, if the packet ID is not a replay.
  * @li False, if the packet ID is a replay.
  */
81d882d5
 bool reliable_not_replay(const struct reliable *rel, packet_id_type id);
6fbf66fa
 
0332b951
 /**
  * Check that a received packet's ID can safely be stored in
  *     the reliable structure's processing window.
  *
  * This function checks the difference between the received packet's ID
  * and the lowest non-acknowledged packet ID in the given reliable
  * structure.  If that difference is larger than the total number of
  * packets which can be stored, then this packet cannot be stored safely,
  * because the reliable structure could possibly fill up without leaving
  * room for all intervening packets.  In that case, this received packet
  * could break the reliable structure's sequentiality, and must therefore
  * be discarded.
  *
  * @param rel The reliable structure for handling this VPN tunnel's
  *     received packets.
  * @param id The packet ID of the received packet.
  *
  * @return
  * @li True, if the packet can safely be stored.
  * @li False, if the packet does not fit safely in the reliable
  *     structure's processing window.
  */
81d882d5
 bool reliable_wont_break_sequentiality(const struct reliable *rel, packet_id_type id);
6fbf66fa
 
0332b951
 /**
  * Read the packet ID of a received packet.
  *
  * @param buf The buffer containing the received packet.
  * @param pid A pointer where the packet's packet ID will be written.
  *
  * @return
  * @li True, if processing was successful.
  * @li False, if an error occurs during processing.
  */
81d882d5
 bool reliable_ack_read_packet_id(struct buffer *buf, packet_id_type *pid);
0332b951
 
 /**
  * Get the buffer of a free %reliable entry in which to store a
  *     packet.
  *
  * @param rel The reliable structure in which to search for a free
  *     entry.
  *
  * @return A pointer to a buffer of a free entry in the \a rel
  *     reliable structure.  If there are no free entries available, this
  *     function returns NULL.
  */
81d882d5
 struct buffer *reliable_get_buf(struct reliable *rel);
6fbf66fa
 
0332b951
 /**
  * Mark the %reliable entry associated with the given buffer as active
  * incoming.
  *
  * @param rel The reliable structure associated with this packet.
  * @param buf The buffer into which the packet has been copied.
  * @param pid The packet's packet ID.
  * @param opcode The packet's opcode.
  */
81d882d5
 void reliable_mark_active_incoming(struct reliable *rel, struct buffer *buf,
                                    packet_id_type pid, int opcode);
0332b951
 
 /**
  * Record a packet ID for later acknowledgment.
  *
  * @param ack The acknowledgment structure which stores this VPN
  *     tunnel's packet IDs for later acknowledgment.
  * @param pid The packet ID of the received packet which should be
  *     acknowledged.
  *
  * @return
  * @li True, if the packet ID was added to \a ack.
  * @li False, if the packet ID was already present in \a ack or \a ack
  *     has no free space to store any more packet IDs.
  */
81d882d5
 bool reliable_ack_acknowledge_packet_id(struct reliable_ack *ack, packet_id_type pid);
0332b951
 
 /** @} name Functions for inserting incoming packets */
6fbf66fa
 
0332b951
 
 /**************************************************************************/
 /** @name Functions for extracting incoming packets
  *  @{ */
 
 /**
  * Get the buffer of the next sequential and active entry.
  *
  * @param rel The reliable structure from which to retrieve the
  *     buffer.
  *
  * @return A pointer to the buffer of the entry with the next
  *     sequential key ID.  If no such entry is present, this function
  *     returns NULL.
  */
81d882d5
 struct buffer *reliable_get_buf_sequenced(struct reliable *rel);
6fbf66fa
 
0332b951
 /**
  * Remove an entry from a reliable structure.
  *
  * @param rel The reliable structure associated with the given buffer.
  * @param buf The buffer of the reliable entry which is to be removed.
  * @param inc_pid If true, the reliable structure's packet ID counter
  *     will be incremented.
  */
81d882d5
 void reliable_mark_deleted(struct reliable *rel, struct buffer *buf, bool inc_pid);
0332b951
 
 /** @} name Functions for extracting incoming packets */
 
 
 /**************************************************************************/
 /** @name Functions for inserting outgoing packets
  *  @{ */
 
 /**
  * Get the buffer of free reliable entry and check whether the
  *     outgoing acknowledgment sequence is still okay.
  *
  * @param rel The reliable structure in which to search for a free
  *     entry.
  *
  * @return A pointer to a buffer of a free entry in the \a rel
  *     reliable structure.  If there are no free entries available, this
  *     function returns NULL.  If the outgoing acknowledgment sequence is
  *     broken, this function also returns NULL.
  */
81d882d5
 struct buffer *reliable_get_buf_output_sequenced(struct reliable *rel);
0332b951
 
 /**
  * Mark the reliable entry associated with the given buffer as
  *     active outgoing.
  *
  * @param rel The reliable structure for handling this VPN tunnel's
  *     outgoing packets.
  * @param buf The buffer previously returned by \c
  *     reliable_get_buf_output_sequenced() into which the packet has been
  *     copied.
  * @param opcode The packet's opcode.
  */
81d882d5
 void reliable_mark_active_outgoing(struct reliable *rel, struct buffer *buf, int opcode);
0332b951
 
 /** @} name Functions for inserting outgoing packets */
 
 
 /**************************************************************************/
 /** @name Functions for extracting outgoing packets
  *  @{ */
 
 /**
  * Check whether a reliable structure has any active entries
  *     ready to be (re)sent.
  *
  * @param rel The reliable structure to check.
  *
  * @return
  * @li True, if there are active entries ready to be (re)sent
  *     president.
  * @li False, if there are no active entries, or the active entries
  *     are not yet ready for resending.
  */
81d882d5
 bool reliable_can_send(const struct reliable *rel);
6fbf66fa
 
0332b951
 /**
  * Get the next packet to send to the remote peer.
  *
  * This function looks for the active entry ready for (re)sending with the
  * lowest packet ID, and returns the buffer associated with it.  This
  * function also resets the timeout after which that entry will become
  * ready for resending again.
  *
  * @param rel The reliable structure to check.
  * @param opcode A pointer to an integer in which this function will
  *     store the opcode of the next packet to be sent.
  *
  * @return A pointer to the buffer of the next entry to be sent, or
  *     NULL if there are no entries ready for (re)sending present in the
  *     reliable structure.  If a valid pointer is returned, then \a opcode
  *     will point to the opcode of that packet.
  */
81d882d5
 struct buffer *reliable_send(struct reliable *rel, int *opcode);
6fbf66fa
 
0332b951
 /** @} name Functions for extracting outgoing packets */
 
 
 /**************************************************************************/
 /** @name Miscellaneous functions
  *  @{ */
 
 /**
  * Check whether a reliable structure is empty.
  *
  * @param rel The reliable structure to check.
  *
  * @return
  * @li True, if there are no active entries in the given reliable
  *     structure.
  * @li False, if there is at least one active entry present.
  */
81d882d5
 bool reliable_empty(const struct reliable *rel);
0332b951
 
 /**
  * Determined how many seconds until the earliest resend should
  *     be attempted.
  *
  * @param rel The reliable structured to check.
  *
  * @return The interval in seconds until the earliest resend attempt
  *     of the outgoing packets stored in the \a rel reliable structure. If
  *     the next time for attempting resending of one or more packets has
  *     already passed, this function will return 0.
  */
81d882d5
 interval_t reliable_send_timeout(const struct reliable *rel);
0332b951
 
 /**
  * Reschedule all entries of a reliable structure to be ready
  *     for (re)sending immediately.
  *
  * @param rel The reliable structure of which the entries should be
  *     modified.
  */
81d882d5
 void reliable_schedule_now(struct reliable *rel);
6fbf66fa
 
81d882d5
 void reliable_debug_print(const struct reliable *rel, char *desc);
6fbf66fa
 
0332b951
 /* set sending timeout (after this time we send again until ACK) */
 static inline void
81d882d5
 reliable_set_timeout(struct reliable *rel, interval_t timeout)
0332b951
 {
81d882d5
     rel->initial_timeout = timeout;
0332b951
 }
 
 /* print a reliable ACK record coming off the wire */
81d882d5
 const char *reliable_ack_print(struct buffer *buf, bool verbose, struct gc_arena *gc);
0332b951
 
81d882d5
 void reliable_ack_debug_print(const struct reliable_ack *ack, char *desc);
0332b951
 
 /** @} name Miscellaneous functions */
 
 
 /** @} addtogroup reliable */
6fbf66fa
 
 
 #endif /* RELIABLE_H */