1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* This file is part of the PCEPlib, a PCEP protocol library.
*
* Copyright (C) 2020 Volta Networks https://voltanet.io/
*
* Author : Brady Johnson <brady@voltanet.io>
*
*/
/*
* Declaration of public API functions.
*/
#ifndef INCLUDE_PCEPSOCKETCOMM_H_
#define INCLUDE_PCEPSOCKETCOMM_H_
#include "pcep.h"
#include <arpa/inet.h> // sockaddr_in
#include <netinet/tcp.h>
#include <stdbool.h>
#include "pcep_utils_queue.h"
#define MAX_RECVD_MSG_SIZE 2048
/*
* A socket_comm_session can be initialized with 1 of 2 types of mutually
* exclusive message callbacks:
* - message_received_handler : the socket_comm library reads the message and
* calls the callback with the message_data and message_length. this callback
* should be used for smaller/simpler messages.
* - message_ready_to_read_handler : the socket_comm library will call this
* callback when a message is ready to be read on a socket_fd. this callback
* should be used if the
*/
/* message received handler that receives the message data and message length */
typedef void (*message_received_handler)(void *session_data,
const char *message_data,
unsigned int message_length);
/* message ready received handler that should read the message on socket_fd
* and return the number of bytes read */
typedef int (*message_ready_to_read_handler)(void *session_data, int socket_fd);
/* callback handler called when a messages is sent */
typedef void (*message_sent_notifier)(void *session_data, int socket_fd);
/* callback handler called when the socket is closed */
typedef void (*connection_except_notifier)(void *session_data, int socket_fd);
/* Function pointers when an external socket infrastructure is used */
typedef int (*ext_socket_write)(void *infra_data, void **infra_socket_data,
int fd, void *data);
typedef int (*ext_socket_read)(void *infra_data, void **infra_socket_data,
int fd, void *data);
typedef int (*ext_socket_pthread_create_callback)(
pthread_t *pthread_id, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *data, const char *thread_name);
typedef struct pcep_socket_comm_session_ {
message_received_handler message_handler;
message_ready_to_read_handler message_ready_to_read_handler;
message_sent_notifier message_sent_handler;
connection_except_notifier conn_except_notifier;
union src_sock_addr {
struct sockaddr_in src_sock_addr_ipv4;
struct sockaddr_in6 src_sock_addr_ipv6;
} src_sock_addr;
union dest_sock_addr {
struct sockaddr_in dest_sock_addr_ipv4;
struct sockaddr_in6 dest_sock_addr_ipv6;
} dest_sock_addr;
bool is_ipv6;
uint32_t connect_timeout_millis;
int socket_fd;
void *session_data;
queue_handle *message_queue;
char received_message[MAX_RECVD_MSG_SIZE];
int received_bytes;
bool close_after_write;
void *external_socket_data; /* used for external socket infra */
/* should be used with is_tcp_auth_md5 flag */
char tcp_authentication_str[PCEP_MD5SIG_MAXKEYLEN + 1];
bool is_tcp_auth_md5; /* flag to distinguish between rfc 2385 (md5) and
rfc 5925 (tcp-ao) */
} pcep_socket_comm_session;
/* Need to document that when the msg_rcv_handler is called, the data needs
* to be handled in the same function call, else it may be overwritten by
* the next read from this socket */
/* Initialize the Socket Comm infrastructure, with either an internal pthread
* or with an external infrastructure.
* If an internal pthread infrastructure is to be used, then it is not necessary
* to explicitly call initialize_socket_comm_loop() as it will be called
* internally when a socket comm session is initialized. */
/* Initialize the Socket Comm infrastructure with an internal pthread */
bool initialize_socket_comm_loop(void);
/* Initialize the Socket Comm infrastructure with an external infrastructure.
* Notice: If the thread_create_func is set, then both the socket_read_cb
* and the socket_write_cb SHOULD be NULL. */
bool initialize_socket_comm_external_infra(
void *external_infra_data, ext_socket_read socket_read_cb,
ext_socket_write socket_write_cb,
ext_socket_pthread_create_callback thread_create_func);
/* The msg_rcv_handler and msg_ready_handler are mutually exclusive, and only
* one can be set (as explained above), else NULL will be returned. */
pcep_socket_comm_session *
socket_comm_session_initialize(message_received_handler msg_rcv_handler,
message_ready_to_read_handler msg_ready_handler,
message_sent_notifier msg_sent_notifier,
connection_except_notifier notifier,
struct in_addr *dst_ip, short dst_port,
uint32_t connect_timeout_millis,
const char *tcp_authentication_str,
bool is_tcp_auth_md5, void *session_data);
pcep_socket_comm_session *socket_comm_session_initialize_ipv6(
message_received_handler msg_rcv_handler,
message_ready_to_read_handler msg_ready_handler,
message_sent_notifier msg_sent_notifier,
connection_except_notifier notifier, struct in6_addr *dst_ip,
short dst_port, uint32_t connect_timeout_millis,
const char *tcp_authentication_str, bool is_tcp_auth_md5,
void *session_data);
pcep_socket_comm_session *socket_comm_session_initialize_with_src(
message_received_handler msg_rcv_handler,
message_ready_to_read_handler msg_ready_handler,
message_sent_notifier msg_sent_notifier,
connection_except_notifier notifier, struct in_addr *src_ip,
short src_port, struct in_addr *dst_ip, short dst_port,
uint32_t connect_timeout_millis, const char *tcp_authentication_str,
bool is_tcp_auth_md5, void *session_data);
pcep_socket_comm_session *socket_comm_session_initialize_with_src_ipv6(
message_received_handler msg_rcv_handler,
message_ready_to_read_handler msg_ready_handler,
message_sent_notifier msg_sent_notifier,
connection_except_notifier notifier, struct in6_addr *src_ip,
short src_port, struct in6_addr *dst_ip, short dst_port,
uint32_t connect_timeout_millis, const char *tcp_authentication_str,
bool is_tcp_auth_md5, void *session_data);
bool socket_comm_session_teardown(
pcep_socket_comm_session *socket_comm_session);
bool socket_comm_session_connect_tcp(
pcep_socket_comm_session *socket_comm_session);
/* Immediately close the TCP connection, irregardless if there are pending
* messages to be sent. */
bool socket_comm_session_close_tcp(
pcep_socket_comm_session *socket_comm_session);
/* Sets a flag to close the TCP connection either after all the pending messages
* are written, or if there are no pending messages, the next time the socket is
* checked to be writeable. */
bool socket_comm_session_close_tcp_after_write(
pcep_socket_comm_session *socket_comm_session);
void socket_comm_session_send_message(
pcep_socket_comm_session *socket_comm_session,
const char *encoded_message, unsigned int msg_length,
bool free_after_send);
/* If an external Socket infra like FRR is used, then these functions will
* be called when a socket is ready to read/write in the external infra.
* Implemented in pcep_socket_comm_loop.c */
int pceplib_external_socket_read(int fd, void *payload);
int pceplib_external_socket_write(int fd, void *payload);
/* the socket comm loop is started internally by
* socket_comm_session_initialize()
* but needs to be explicitly stopped with this call. */
bool destroy_socket_comm_loop(void);
int socket_fd_node_compare(void *list_entry, void *new_entry);
#endif /* INCLUDE_PCEPSOCKETCOMM_H_ */
|