fc45429fab8de573aabae9b4216a4d64e184089b
[ric-plt/lib/rmr.git] / src / common / include / rmr_agnostic.h
1 // : vi ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4         Copyright (c) 2019 Nokia 
5         Copyright (c) 2018-2019 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20
21 /*
22         Mnemonic:       rmr_agnostic.h
23         Abstract:       Header file for things that are agnostic to the underlying transport
24                                 mechanism.
25         Author:         E. Scott Daniels
26         Date:           28 February 2018
27 */
28
29 #ifndef _rmr_agnostic_h
30 #define _rmr_agnostic_h
31
32 typedef struct endpoint endpoint_t;             // place holder for structs defined in nano/nng private.h
33 typedef struct uta_ctx  uta_ctx_t;
34
35 // allow testing to override without changing this
36 #ifndef DEBUG
37 #define DEBUG 0
38 #endif
39
40 #define FALSE 0
41 #define TRUE  1
42
43 #define QUOTE(a) #a                             // allow a constant to be quoted
44 #define QUOTE_DEF(a) QUOTE(a)   // allow a #define value to be quoted (e.g. QUOTE(MAJOR_VERSION) )
45
46
47 #define RMR_MSG_VER     2                       // message version this code was designed to handle
48
49                                                                         // environment variable names we'll suss out
50 #define ENV_BIND_IF "RMR_BIND_IF"       // the interface to bind to for both normal comma and RTG (0.0.0.0 if missing) 
51 #define ENV_RTG_PORT "RMR_RTG_SVC"      // the port we'll listen on for rtg connections
52 #define ENV_SEED_RT     "RMR_SEED_RT"   // where we expect to find the name of the seed route table
53 #define ENV_RTG_RAW "RMR_RTG_ISRAW"     // if > 0 we expect route table gen messages as raw (not sent from an RMr application)
54 #define ENV_VERBOSE_FILE "RMR_VCTL_FILE"        // file where vlevel may be managed for some (non-time critical) functions
55
56 #define NO_FLAGS        0                               // no flags to pass to a function
57
58 #define FL_NOTHREAD     0x01                    // do not start an additional thread (must be 'user land' to support rtg
59 #define UFL_MASK                0xff            // mask applied to some flag parms passed by the user to remove any internal flags
60                                                                         // internal flags, must be > than UFLAG_MASK
61 //#define IFL_....
62
63                                                                         // msg buffer flags
64 #define MFL_ZEROCOPY    0x01            // the message is an allocated zero copy message and can be sent.
65 #define MFL_NOALLOC             0x02            // send should NOT allocate a new buffer before returning
66 #define MFL_ADDSRC              0x04            // source must be added on send
67 #define MFL_RAW                 0x08            // message is 'raw' and not from an RMr based sender (no header)
68
69 #define MAX_EP_GROUP    32                      // max number of endpoints in a group
70 #define MAX_RTG_MSG_SZ  2048            // max expected message size from route generator
71
72 //#define DEF_RTG_MSGID ""                              // default to pick up all messages from rtg
73 #define DEF_RTG_PORT    "tcp:4561"              // default port that we accept rtg connections on
74 #define DEF_COMM_PORT   "tcp:4560"              // default port we use for normal communications
75
76 // -- header length/offset macros which ensure network conversion ----
77 #define RMR_HDR_LEN(h)          (ntohl(((uta_mhdr_t *)h)->len0)+htonl(((uta_mhdr_t *)h)->len1)+htonl(((uta_mhdr_t *)h)->len2)+htonl(((uta_mhdr_t *)h)->len3))   // convert from net byte order
78 #define PAYLOAD_OFFSET(h)       (ntohl(((uta_mhdr_t *)h)->len0)+htonl(((uta_mhdr_t *)h)->len1)+htonl(((uta_mhdr_t *)h)->len2)+htonl(((uta_mhdr_t *)h)->len3))
79 #define TRACE_OFFSET(h)         (ntohl(((uta_mhdr_t *)h)->len0))
80 #define DATA1_OFFSET(h)         (ntohl(((uta_mhdr_t *)h)->len0)+htonl(((uta_mhdr_t *)h)->len1))
81 #define DATA2_OFFSET(h)         (ntohl(((uta_mhdr_t *)h)->len0)+htonl(((uta_mhdr_t *)h)->len1)+htonl((uta_mhdr_t *)h)->len2)
82 #define RMR_TR_LEN(h)           (ntohl(((uta_mhdr_t *)h)->len1))
83 #define RMR_D1_LEN(h)           (ntohl(((uta_mhdr_t *)h)->len2))
84 #define RMR_D2_LEN(h)           (ntohl(((uta_mhdr_t *)h)->len3))
85
86 #define SET_HDR_LEN(h)          (((uta_mhdr_t *)h)->len0=htonl((int32_t)sizeof(uta_mhdr_t)))            // convert to network byte order on insert
87 #define SET_HDR_TR_LEN(h,l)     (((uta_mhdr_t *)h)->len1=htonl((int32_t)l))
88 #define SET_HDR_D1_LEN(h,l)     (((uta_mhdr_t *)h)->len2=htonl((int32_t)l))
89 #define SET_HDR_D2_LEN(h,l)     (((uta_mhdr_t *)h)->len3=htonl((int32_t)l))
90
91
92 #define V1_PAYLOAD_OFFSET(h)    (sizeof(uta_v1mhdr_t))
93
94                                                                                 // v2 header flags
95 #define HFL_HAS_TRACE   0x01                    // Trace data is populated
96 #define HFL_SUBID               0x02                    // subscription ID is populated
97
98 /*
99         Message header; interpreted by the other side, but never seen by
100         the user application.
101
102         DANGER: Add new fields AT THE END of the struct. Adding them any where else
103                         will break any code that is currently running.
104
105         The transport layer buffer allocated will be divided this way:
106                 | RMr header | Trace data | data1 | data2 | User paylaod |
107
108                 Len 0 is the length of the RMr header
109                 Len 1 is the length of the trace data
110                 Len 2 and 3 are lengths of data1 and data2 and are unused at the moment
111
112         To point at the payload, we take the address of the header and add all 4 lengths.
113 */
114 typedef struct {
115         int32_t mtype;                                          // message type  ("long" network integer)
116         int32_t plen;                                           // payload length
117         int32_t rmr_ver;                                        // our internal message version number
118         unsigned char xid[RMR_MAX_XID];         // space for user transaction id or somesuch
119         unsigned char sid[RMR_MAX_SID];         // sender ID for return to sender needs
120         unsigned char src[RMR_MAX_SRC];         // name:port of the sender (source)
121         unsigned char meid[RMR_MAX_MEID];       // managed element id.
122         struct timespec ts;                                     // timestamp ???
123
124                                                                                 // V2 extension
125         int32_t flags;                                          // HFL_* constants      
126         int32_t len0;                                           // length of the RMr header data
127         int32_t len1;                                           // length of the tracing data
128         int32_t len2;                                           // length of data 1 (d1)
129         int32_t len3;                                           // length of data 2 (d2)
130
131 } uta_mhdr_t;
132
133
134 typedef struct {                                                // old (inflexible) v1 header
135         int32_t mtype;                                          // message type  ("long" network integer)
136         int32_t plen;                                           // payload length
137         int32_t rmr_ver;                                        // our internal message version number
138         unsigned char xid[RMR_MAX_XID];         // space for user transaction id or somesuch
139         unsigned char sid[RMR_MAX_SID];         // sender ID for return to sender needs
140         unsigned char src[16];                          // name of the sender (source) (old size was 16)
141         unsigned char meid[RMR_MAX_MEID];       // managed element id.
142         struct timespec ts;                                     // timestamp ???
143 } uta_v1mhdr_t;
144
145 /*
146         Round robin group.
147 */
148 typedef struct {
149         int     ep_idx;                         // next endpoint to send to
150         int nused;                              // number of endpoints in the list
151         int nendpts;                    // number allocated
152         endpoint_t **epts;              // the list of endpoints that we RR over
153 } rrgroup_t;
154
155 /*
156         Routing table entry. This is a list of endpoints that can be sent
157         messages of the given mtype.  If there is more than one, we will
158         round robin messags across the list.
159 */
160 typedef struct {
161         int mtype;                              // the message type for this list
162         int     nrrgroups;                      // number of rr groups to send to
163         rrgroup_t**     rrgroups;       // one or more set of endpoints to round robin messages to
164 } rtable_ent_t;
165
166 /*
167         The route table.
168 */
169 typedef struct {
170         void*   hash;                   // hash table.
171 } route_table_t;
172
173 /*
174         A wormhole is a direct connection between two endpoints that the user app can 
175         send to without message type based routing.
176 */
177 typedef struct {
178         int     nalloc;                         // number of ep pointers allocated
179         endpoint_t** eps;               // end points directly referenced
180 } wh_mgt_t;
181
182
183 /*
184         This manages an array of pointers to IP addresses that are associated with one of our interfaces.
185         For now, we don't need to map the addr to a specific interface, just know that it is one of ours.
186 */
187 typedef struct {
188         char**  addrs;                  // all ip addresses we found
189         int             naddrs;                 // num actually used
190 } if_addrs_t;
191
192 // --------------- ring things  -------------------------------------------------
193 typedef struct ring {
194         uint16_t head;                          // index of the head of the ring (insert point)
195         uint16_t tail;                          // index of the tail (extract point)
196         uint16_t nelements;                     // number of elements in the ring
197         void**  data;                           // the ring data (pointers to blobs of stuff)
198 } ring_t;
199
200
201
202 // -------------- common static prototypes --------------------------------------
203
204 //---- tools ----------------------------------
205 static int has_myip( char const* buf, if_addrs_t* list, char sep, int max );
206 static int uta_tokenise( char* buf, char** tokens, int max, char sep );
207 static char* uta_h2ip( char const* hname );
208 static int uta_lookup_rtg( uta_ctx_t* ctx );
209 static int uta_has_str( char const* buf, char const* str, char sep, int max );
210
211 // --- message ring --------------------------
212 static void* uta_mk_ring( int size );
213 static void uta_ring_free( void* vr );
214 static inline void* uta_ring_extract( void* vr );
215 static inline int uta_ring_insert( void* vr, void* new_data );
216
217 // --- message and context management --------
218 static int ie_test( void* r, int i_factor, long inserts );
219
220
221 // ----- route table generic static things ---------
222 static void collect_things( void* st, void* entry, char const* name, void* thing, void* vthing_list );
223 static void del_rte( void* st, void* entry, char const* name, void* thing, void* data );
224 static char* uta_fib( char* fname );
225 static route_table_t* uta_rt_init( );
226 static route_table_t* uta_rt_clone( route_table_t* srt );
227 static void uta_rt_drop( route_table_t* rt );
228 static endpoint_t*  uta_add_ep( route_table_t* rt, rtable_ent_t* rte, char* ep_name, int group  );
229 static rtable_ent_t* uta_add_rte( route_table_t* rt, int mtype, int nrrgroups );
230 static endpoint_t* uta_get_ep( route_table_t* rt, char const* ep_name );
231 static void read_static_rt( uta_ctx_t* ctx, int vlevel );
232 static void parse_rt_rec( uta_ctx_t* ctx, char* buf, int vlevel );
233 static void* rtc( void* vctx );
234 static endpoint_t* rt_ensure_ep( route_table_t* rt, char const* ep_name );
235
236 #endif