c-template
socket.h
Go to the documentation of this file.
1 /*! @file socket.h
2  * @author Bonedaddy
3  * @brief TCP socket servers, clients, and tooling for working with sockets
4  * @details uses wait_group.h to provide lightweight synchronization between pthreads
5  * @warning before use you must call setup_signal_handling() so that all threads get properly cleaned up on exit
6  * @note you will want to adjust `async_handle_conn_func` to suit your needs as right now it is just an echo client
7  * it is likely you will need to have `#define _POSIX_C_SOURCE 201112L`
8  * see the following for more information
9  * - https://stackoverflow.com/questions/39409846/why-does-gcc-not-complain-about-htons-but-complains-about-getaddrinfo-when-c/39410095#39410095
10  * - https://man7.org/linux/man-pages/man3/getaddrinfo.3.html
11 */
12 
13 #pragma once
14 
15 /*! @def _POSIX_C_SOURCE 201112L
16  * @brief fixes GCC not compiling correctly
17  * currently we are handling this via our cmake build system (see CMakeLists.txt)
18  * however you may want to define the macro in source yourself
19  * @note https://stackoverflow.com/questions/39409846/why-does-gcc-not-complain-about-htons-but-complains-about-getaddrinfo-when-c/39410095#39410095
20 */
21 
22 #include <pthread.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <netdb.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdbool.h>
34 #include <pthread.h>
35 #include <signal.h>
36 #include <fcntl.h>
37 // sys/time.h is needed for the timeval
38 // #include <time.h>
39 #include <sys/time.h>
40 #include "../../utils/logger.h"
41 
42 
43 /*! @brief used to lock writes for _do_exit
44  * @warning should not be called libraries using socket.c
45 */
46 pthread_mutex_t _signal_mutex;
47 /*! @brief used to indicate when threads need to cleanup
48  * @warning should not be called libraries using socket.c
49  * polled at the beginning of every async_listen_func loop and async_handle_conn_func
50  * when set to true causes active pthreads to exit after successfully cleaning up
51 */
52 bool _do_exit;
53 
54 
55 
56 /*! @typedef addr_info
57  * @struct addrinfo
58  * @brief alias for `struct addrinfo`
59 */
60 typedef struct addrinfo addr_info;
61 
62 /*! @typedef sock_addr
63  * @struct sockaddr
64  * @brief alias for `struct sockaddr`
65 */
66 typedef struct sockaddr sock_addr;
67 
68 /*! @typedef sock_addr_storage
69  * @struct sockaddr_storage
70  * @brief alias for `struct sockaddr_storage`
71 */
73 
74 /*! @enum SOCKET_OPTS
75  * @brief used to configure new sockets
76 */
77 typedef enum {
78  /*! sets socket with SO_REUSEADDR */
80  /*! sets socket to non-blocking mode */
82  /*! sets socket to blocking mode */
84 } SOCKET_OPTS;
85 
86 /*! @typedef socket_client
87  * @struct socket_client
88  * a generic tcp socket client
89 */
90 typedef struct socket_client {
93 
94 /*! @brief returns a new socket client connected to `addr:port`
95 */
96 socket_client *new_socket_client(thread_logger *thl, addr_info hints, char *addr, char *port);
97 
98 /*! @brief gets an available socket attached to bind_address
99  * @return Success: file descriptor socket number greater than 0
100  * @return Failure: -1
101  * initializers a socket attached to bind_address with sock_opts, and binds the address
102 */
103 int get_new_socket(thread_logger *thl, addr_info *bind_address, SOCKET_OPTS sock_opts[], int num_opts);
104 
105 /*! @brief prepares library for usage
106  * @warning must be called before using the library
107  * sets up internal mutex, and system signal handling for terminating the server
108  * listes to SIGINT, SIGTERM, and SIGQUIT which will terminate the server
109 */
110 void setup_signal_handling();
111 
112 /*! @brief used to enable/disable blocking sockets
113  * @return Failure: false
114  * @return Success: true
115  * @note see https://stackoverflow.com/questions/1543466/how-do-i-change-a-tcp-socket-to-be-non-blocking/1549344#1549344
116 */
117 bool set_socket_blocking_status(int fd, bool blocking);
118 
119 
120 /*! @brief callback function used to handle OS signals
121  * shouldn't be called directly and instead used as the func in `signal(SIGTERM, handler_fn)`
122 */
123 void signal_handler_fn(int signal_number);
124 
125 /*! @brief returns the address the client is connecting from
126 */
127 char *get_name_info(sock_addr *client_address);
128 
129 /*! @brief generates an addr_info struct with defaults
130  * defaults is IPv4, TCP, and AI_PASSIVE flags
131 */
133 
134 
socket_client
struct socket_client socket_client
default_hints
addr_info default_hints()
generates an addr_info struct with defaults defaults is IPv4, TCP, and AI_PASSIVE flags
REUSEADDR
@ REUSEADDR
Definition: socket.h:79
get_new_socket
int get_new_socket(thread_logger *thl, addr_info *bind_address, SOCKET_OPTS sock_opts[], int num_opts)
gets an available socket attached to bind_address
signal_handler_fn
void signal_handler_fn(int signal_number)
callback function used to handle OS signals shouldn't be called directly and instead used as the func...
socket_client
Definition: socket.h:90
sockaddr_storage
alias for struct sockaddr_storage
_signal_mutex
pthread_mutex_t _signal_mutex
used to lock writes for _do_exit
Definition: socket.h:46
setup_signal_handling
void setup_signal_handling()
prepares library for usage
sockaddr
alias for struct sockaddr
_do_exit
bool _do_exit
used to indicate when threads need to cleanup
Definition: socket.h:52
new_socket_client
socket_client * new_socket_client(thread_logger *thl, addr_info hints, char *addr, char *port)
returns a new socket client connected to addr:port
NOBLOCK
@ NOBLOCK
Definition: socket.h:81
thread_logger
Definition: logger.h:63
BLOCK
@ BLOCK
Definition: socket.h:83
set_socket_blocking_status
bool set_socket_blocking_status(int fd, bool blocking)
used to enable/disable blocking sockets
SOCKET_OPTS
SOCKET_OPTS
used to configure new sockets
Definition: socket.h:77
socket_client::socket_number
int socket_number
Definition: socket.h:91
addrinfo
alias for struct addrinfo
get_name_info
char * get_name_info(sock_addr *client_address)
returns the address the client is connecting from