Skip to content

Commit

Permalink
chore: copy basic socket stuff from c-template
Browse files Browse the repository at this point in the history
  • Loading branch information
postables committed Jul 21, 2020
1 parent fe5e334 commit 9180ebc
Show file tree
Hide file tree
Showing 12 changed files with 817 additions and 1 deletion.
22 changes: 22 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/include",
"/usr/include",
"/usr/include"
],
"defines": [
"__linux__",
"__x86_64__",
"_GNU_SOURCE"
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c18",
"intelliSenseMode": "gcc-x64"
}
],
"version": 4
}
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ include(cmake/pkgs/valgrind.cmake)

include(cmake/libraries/multicodec.cmake)

# networking #

include(cmake/libraries/network.cmake)

#########################
# END COMPILE LIBRARIES #
#########################
Expand Down
13 changes: 13 additions & 0 deletions cmake/libraries/network.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
file(GLOB_RECURSE NETWORK_SOURCES
./include/network/*.h
./src/network/*.c
)

add_library(libnetwork
SHARED
${NETWORK_SOURCES}
)

target_compile_options(libnetwork PRIVATE ${flags})
target_link_libraries(libnetwork pthread)
target_link_libraries(libnetwork libutils)
3 changes: 2 additions & 1 deletion cmake/libraries/utils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ add_library(libutils
${UTIL_SOURCES}
)

target_compile_options(libutils PRIVATE ${flags})
target_compile_options(libutils PRIVATE ${flags})
target_link_libraries(libutils pthread)
64 changes: 64 additions & 0 deletions include/network/socket.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*! @file socket.h
* @brief general socket related tooling
*/

#pragma once

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "utils/logger.h"

/*! @typedef addr_info
* @struct addrinfo
* @brief alias for `struct addrinfo`
*/
typedef struct addrinfo addr_info;

/*! @typedef sock_addr
* @struct sockaddr
* @brief alias for `struct sockaddr`
*/
typedef struct sockaddr sock_addr;

/*! @typedef sock_addr_storage
* @struct sockaddr_storage
* @brief alias for `struct sockaddr_storage`
*/
typedef struct sockaddr_storage sock_addr_storage;

/*! @enum SOCKET_OPTS
* @brief used to configure new sockets
*/
typedef enum {
/*! sets socket with SO_REUSEADDR */
REUSEADDR,
/*! sets socket to non-blocking mode */
NOBLOCK,
/*! sets socket to blocking mode */
BLOCK,
} SOCKET_OPTS;

/*! @brief gets an available socket attached to bind_address
* @return Success: file descriptor socket number greater than 0
* @return Failure: -1
* initializers a socket attached to bind_address with sock_opts, and binds the address
*/
int get_new_socket(thread_logger *thl, addr_info *bind_address, SOCKET_OPTS sock_opts[], int num_opts);

/*! @brief used to enable/disable blocking sockets
* @return Failure: false
* @return Success: true
* @note see https://stackoverflow.com/questions/1543466/how-do-i-change-a-tcp-socket-to-be-non-blocking/1549344#1549344
*/
bool set_socket_blocking_status(int fd, bool blocking);

/*! @brief returns the address the client is connecting from
*/
char *get_name_info(sock_addr *client_address);

/*! @brief generates an addr_info struct with defaults
* defaults is IPv4, TCP, and AI_PASSIVE flags
*/
addr_info default_hints();
28 changes: 28 additions & 0 deletions include/network/socket_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*! @file socket_client.h
* @brief stuff related to socket clients (ie, connecting to socket servers)
*/

#pragma once

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <pthread.h>
#include <stdbool.h>
#include "socket.h"


/*! @typedef socket_client
* @struct socket_client
* a generic tcp/udp socket client
*/
typedef struct socket_client {
int socket_number;
} socket_client_t;


/*! @brief returns a new socket client connected to `addr:port`
*/
socket_client_t *new_socket_client(addr_info hints, char *addr, char *port);
78 changes: 78 additions & 0 deletions include/network/socket_server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*! @file socket_server.h
* @brief used to create a tcp/udp socket server listening on multiaddrs
*/

#pragma once

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <pthread.h>
#include <stdbool.h>
#include "socket_client.h" // this also imports socket.h

typedef struct socket_server_config {
char *udp_port_number;
char *tcp_port_number;
char *listen_address;
int max_connections;
} socket_server_config_t;

typedef struct socket_server {
int udp_socket_number;
int tcp_socket_number;
pthread_t thread;
} socket_server_t;

/*! @typedef client_conn
* @struct client_conn
* @brief a structure containing a file descriptor and address information
* @todo
* - enable a queue/list of these
*/
typedef struct client_conn {
int socket_number;
sock_addr_storage *address;
} client_conn_t;

/*! @typedef conn_handle_data
* @struct conn_handle_data
* @brief struct containing arguments passed into pthread
*/
typedef struct conn_handle_data {
pthread_t thread;
socket_server_t *srv;
client_conn_t *conn;
} conn_handle_data_t;

/*! @brief returns a new socket server bound to the port number and ready to accept connections
*/
socket_server_t *new_socket_server(addr_info hints, socket_server_config_t config);

/*! @brief listens for new connections and spawns a thread to process the connection
* thread that is created to process the connection runs as a detached thread
* will poll for new connections to accept every 500 miliseconds
* @param data void pointer to a socket_server struct
* @note detached thread created calling async_handle_conn_func
* @warning may change the 500 milisecond sleep
*/
void *async_listen_func(void *data);

/*! @brief handles connections in a dedicated pthread
* is laucnched in a pthread by async_listen_func when any new connection is received
* @param data `void *` to a conn_handle_data object
* @note uses `select` to determine if we can read data from the connection
* @note select runs for 3 seconds before timing out and releasing resources with the connection
* @warning currently implements an example echo client
* @warning you will want to adapt to your specific use case
*/
void *async_handle_conn_func(void *data);

/*! @brief helper function for accepting client connections
* times out new attempts if they take 3 seconds or more
* @return Failure: NULL client conn failed
* @return Success: non-NULL populated client_conn object
*/
client_conn_t *accept_client_conn(socket_server_t *srv);
45 changes: 45 additions & 0 deletions include/utils/colors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*! @file colors.h
* @brief macros and utilities for printing color to stdout
* from https://www.quora.com/How-do-I-print-a-colored-output-in-C
* Pass a `COLORS_x` enum value into `print_colored` and the color will be printed on stdout
* Note that if you want to disable printing of that color you'll have to send the `COLORS_RESET` enum value through
* to make non-bold change 0->1 (0;31m red) vs (1;31m bold red)
*/

#pragma once

#include <stdbool.h>

#define ANSI_COLOR_RED "\x1b[1;31m"
#define ANSI_COLOR_SOFT_RED "\x1b[1;38;5;210m"
#define ANSI_COLOR_GREEN "\x1b[1;32m"
#define ANSI_COLOR_YELLOW "\x1b[1;33m"
#define ANSI_COLOR_BLUE "\x1b[1;34m"
#define ANSI_COLOR_MAGENTA "\x1b[1;35m"
#define ANSI_COLOR_CYAN "\x1b[1;36m"
#define ANSI_COLOR_RESET "\x1b[1;0m"

/*! @brief allows short-handed references to ANSI color schemes, and enables easier color selection
* anytime you want to extend the available colors with an additional enum, add a switch case in get_ansi_color_scheme
*/
typedef enum {
COLORS_RED, COLORS_SOFT_RED, COLORS_GREEN, COLORS_YELLOW, COLORS_BLUE, COLORS_MAGENTA, COLORS_CYAN, COLORS_RESET
} COLORS;

/*! @brief returns a `char *` with the message formatted with ansi colors
*/
char *format_colored(COLORS color, char *message);

/*! @brief returns an ansi color string to be used with printf
*/
char *get_ansi_color_scheme(COLORS color);

/*! @brief prints message to stdout with the given color
*/
void print_colored(COLORS color, char *message);

/*! @brief writes a message to fh with the given color
* For "sync writes" and to always flush logs to disk immediately set do_flush to true
* returns 0 if no error, returns 1 if error
*/
int write_colored(COLORS color, int file_descriptor, char *message);
Loading

0 comments on commit 9180ebc

Please sign in to comment.