Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into 136-include-files-not-…
Browse files Browse the repository at this point in the history
…installed-with-cmake
  • Loading branch information
Michael-M-Baron committed Nov 6, 2024
2 parents 9e78245 + cf009d0 commit 1f318f1
Show file tree
Hide file tree
Showing 6 changed files with 313 additions and 9 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,21 @@ A Makefile is generated. Run 'make' to build the libjapi libraries.

A shared and a static library is built. Tests are built by default. They can be disabled using the command `cmake -DLIBJAPI_ENABLE_TESTING=OFF ../` variable.

Install the shared and static japi library together with public header files:

$ make install

Make sure to add `/usr/local/include/japi/` to your local system environment `C_INCLUDE_PATH` or `CPLUS_INCLUDE_PATH` and that `/usr/local/lib/` is in the standard linker search path when compiling and linking your application against libjapi.
### Tests
To run the internal tests run

$ ctest

Install the shared and static japi library together with public header files:
The testsuite from [googletest](https://github.com/google/googletest) is used. To run tests, call

$ make install
$ cd build
$ make run_test

Make sure to add `/usr/local/include/japi/` to your local system environment `C_INCLUDE_PATH` or `CPLUS_INCLUDE_PATH` and that `/usr/local/lib/` is in the standard linker search path when compiling and linking your application against libjapi.

## Demo
You can clone the [demo project](https://git01.iis.fhg.de/ks-ip-lib/software/libjapi-demo), with examples for all features from the repository listed below:
Expand Down
31 changes: 31 additions & 0 deletions include/japi.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ typedef struct __japi_context {
void *userptr; /*!< Pointer to user data */
uint16_t num_clients; /*!< Number of connected clients */
uint16_t max_clients; /*!< Number of maximal allowed clients */
int tcp_keepalive_enable; /*!< Switch to enable keepalive mechanism in TCP server.
Configure using following attributes */
int tcp_keepalive_time; /*!< The number of seconds a connection needs to be idle
before TCP begins sending out keep-alive probes. */
int tcp_keepalive_intvl; /*!< The number of seconds between TCP keep-alive probes.
*/
int tcp_keepalive_probes; /*!< The maximum number of TCP keep-alive probes to send
before giving up and killing the connection if no
response is ob‐ tained from the other end. */
pthread_mutex_t lock; /*!< Mutual access lock */
struct __japi_request *requests; /*!< Pointer to the JAPI request list */
struct __japi_pushsrv_context
Expand Down Expand Up @@ -173,6 +182,28 @@ int japi_set_max_allowed_clients(japi_context *ctx, uint16_t num);
*/
int japi_include_args_in_response(japi_context *ctx, bool include_args);

/*!
* \brief Enable or disable TCP keepalive and set the relevant parameters.
*
* Default values depend on the system. E.g. for Debian 11 `tcp_keepalive_time
* = 7200`, `tcp_keepalive_intvl = 75`, `tcp_keepalive_probes = 9`
*
* \param ctx JAPI context
* \param tcp_keepalive_enable Switch to enable keepalive mechanism in TCP
* server. Configure using following attributes
* \param tcp_keepalive_time The number of seconds a connection needs to be
* idle before TCP begins sending out keep-alive probes.
* \param tcp_keepalive_intvl The number of seconds between TCP keep-alive probes.
* \param tcp_keepalive_probes The maximum number of TCP keep-alive probes to send
* before giving up and killing the connection if no
* response is obtained from the other end.
*
* \returns On success, zero is returned. On invalid parameters, -1 is returned.
*/
int japi_set_tcp_keepalive(japi_context *ctx, int tcp_keepalive_enable,
int tcp_keepalive_time, int tcp_keepalive_intvl,
int tcp_keepalive_probes);

/*!
* \brief Shutdown the JAPI server
*
Expand Down
24 changes: 24 additions & 0 deletions include/networking.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,30 @@ int tcp4_start_server(const char* port);
*/
int tcp6_start_server(const char* port);

/*!
* \brief Set socket options to enable TCP keepalive functions
*
* Change default values to ensure that lost connections are recognised and
* terminated.
*
* \param socket_file_descriptor Socket to which the changes are applied.
* \param tcp_keepalive_enable Switch to enable keepalive mechanism in TCP
* server. Configure using following attributes
* \param tcp_keepalive_time The number of seconds a connection needs to be
* idle before TCP begins sending out keep-alive probes.
* \param tcp_keepalive_intvl The number of seconds between TCP keep-alive probes.
* \param tcp_keepalive_probes The maximum number of TCP keep-alive probes to send
* before giving up and killing the connection if no
* response is obtained from the other end.
*
* \returns On success 0. On error -1.
*/
int enable_tcp_keepalive(int socket_file_descriptor,
int tcp_keepalive_enable,
int tcp_keepalive_time,
int tcp_keepalive_intvl,
int tcp_keepalive_probes);

#ifdef __cplusplus
}
#endif
Expand Down
46 changes: 46 additions & 0 deletions src/japi.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ japi_context *japi_init(void *userptr)
ctx->num_clients = 0;
ctx->max_clients = 0;
ctx->include_args_in_response = false;
ctx->tcp_keepalive_enable = 0;
ctx->tcp_keepalive_time = 7200;
ctx->tcp_keepalive_intvl = 75;
ctx->tcp_keepalive_probes = 9;
ctx->shutdown = false;

/* Initialize mutex */
Expand Down Expand Up @@ -370,6 +374,37 @@ int japi_include_args_in_response(japi_context *ctx, bool include_args)
return 0;
}

/* change defaults from tcp_keepalive_time = 7200, tcp_keepalive_intvl = 75,
* tcp_keepalive_probes = 9 */
int japi_set_tcp_keepalive(japi_context *ctx, int tcp_keepalive_enable,
int tcp_keepalive_time, int tcp_keepalive_intvl,
int tcp_keepalive_probes)
{
/* Error handling */
if (ctx == NULL) {
fprintf(stderr, "ERROR: JAPI context is NULL.\n");
return -1;
}
if (tcp_keepalive_time < 0) {
fprintf(stderr, "ERROR: tcp_keepalive_time has to be positive or 0.\n");
return -1;
}
if (tcp_keepalive_intvl <= 0) {
fprintf(stderr, "ERROR: tcp_keepalive_intvl has to be positive.\n");
return -1;
}
if (tcp_keepalive_probes < 0) {
fprintf(stderr, "ERROR: tcp_keepalive_probes has to be positive or 0.\n");
return -1;
}

ctx->tcp_keepalive_enable = tcp_keepalive_enable;
ctx->tcp_keepalive_time = tcp_keepalive_time;
ctx->tcp_keepalive_intvl = tcp_keepalive_intvl;
ctx->tcp_keepalive_probes = tcp_keepalive_probes;
return 0;
}

/*
* Add new client element to list
*/
Expand Down Expand Up @@ -497,6 +532,14 @@ int japi_start_server(japi_context *ctx, const char *port)
return -1;
}

if (ctx->tcp_keepalive_enable) {
if (enable_tcp_keepalive(server_socket, ctx->tcp_keepalive_enable,
ctx->tcp_keepalive_time, ctx->tcp_keepalive_intvl,
ctx->tcp_keepalive_probes) < 0) {
return -1;
}
}

int ret;
int nfds;
fd_set fdrd;
Expand Down Expand Up @@ -615,6 +658,9 @@ int japi_start_server(japi_context *ctx, const char *port)
perror("ERROR: accept() failed\n");
return -1;
}

prntdbg("Client socket to add: %d, current number of clients %d\n", client_socket, ctx->num_clients);

if (ctx->max_clients == 0 || ctx->num_clients < ctx->max_clients) {
japi_add_client(ctx, client_socket);
prntdbg("client %d added\n", client_socket);
Expand Down
38 changes: 38 additions & 0 deletions src/networking.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* THE SOFTWARE.
*/

#include <netinet/tcp.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
Expand Down Expand Up @@ -116,3 +117,40 @@ int tcp6_start_server(const char* port)
return tcp_start_server_on_addr_family(port, AF_INET6);
}

int enable_tcp_keepalive(int socket_file_descriptor,
int tcp_keepalive_enable,
int tcp_keepalive_time,
int tcp_keepalive_intvl,
int tcp_keepalive_probes)
{
if (setsockopt(socket_file_descriptor, SOL_SOCKET, SO_KEEPALIVE, &tcp_keepalive_enable, sizeof(tcp_keepalive_enable)) == -1)
{
perror("ERROR: setsocktop SO_KEEPALIVE");
fprintf(stderr, "WARNING: Keeping connection alive wont be possible. \n");
/* The programm can go on. */
};

if (!tcp_keepalive_enable)
{
return 0;
}

if (setsockopt(socket_file_descriptor, IPPROTO_TCP, TCP_KEEPIDLE, &tcp_keepalive_time, sizeof(tcp_keepalive_time)) == -1)
{
perror("setsockopt TCP_KEEPIDLE");
return -1;
}

if (setsockopt(socket_file_descriptor, IPPROTO_TCP, TCP_KEEPINTVL, &tcp_keepalive_intvl, sizeof(tcp_keepalive_intvl)) == -1)
{
perror("setsockopt TCP_KEEPINTVL");
return -1;
}

if (setsockopt(socket_file_descriptor, IPPROTO_TCP, TCP_KEEPCNT, &tcp_keepalive_probes, sizeof(tcp_keepalive_probes)) == -1)
{
perror("setsockopt TCP_KEEPCNT");
return -1;
}
return 0;
}
Loading

0 comments on commit 1f318f1

Please sign in to comment.