Address code analysis issues
[ric-plt/lib/rmr.git] / test / test_si95_em.c
1 /*
2 ==================================================================================
3         Copyright (c) 2020 Nokia
4         Copyright (c) 2020 AT&T Intellectual Property.
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10            http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17 ==================================================================================
18 */
19
20 /*
21         Mnemonic:       test_si95_em.c
22         Abstract:       This supplies a bunch of dummy SI95 functions which emulate
23                                 the sending/receiving of data such that modules can be tested
24                                 without the acutal backing of a network.
25
26                                 This module must be directly included to be used.
27         Date:           20 February 2020
28         Author:         E. Scott Daniels
29 */
30
31
32 #include "rmr.h"                                // we use some of rmr defs in building dummy messages, so we need these
33 #include "rmr_agnostic.h"
34
35 // ---------------------- emulated SI95 functions ---------------------------
36
37
38 #ifndef _em_si          // this is the same define as the nng emulation code uses to give warning if both included
39 #define _em_si
40
41 #include <arpa/inet.h>
42 #include <pthread.h>
43
44 #include "test_common_em.c"                     // common emulation needed for all (epoll, gethostname...)
45
46 // --- some globals --------------------------------------------------------
47 int em_reset_call_flag = 0;                     // allows a send to turn off the call flag (see em_disable_call_flg())
48
49 // ------------- emulated message header -----------------------------------
50
51 /*
52         This is a copy from agnostic.h. we need to reset flags in some situations
53         so we have to have this, under a different name to avoid disaster.
54 */
55 typedef struct {
56     int32_t mtype;                      // message type  ("long" network integer)
57     int32_t plen;                       // payload length (sender data length in payload)
58     int32_t rmr_ver;                    // our internal message version number
59     unsigned char xid[RMR_MAX_XID];     // space for user transaction id or somesuch
60     unsigned char sid[RMR_MAX_SID];     // sender ID for return to sender needs
61     unsigned char src[RMR_MAX_SRC];     // name:port of the sender (source)
62     unsigned char meid[RMR_MAX_MEID];   // managed element id.
63     struct timespec ts;                 // timestamp ???
64
65                                         // V2 extension
66     int32_t flags;                      // HFL_* constants
67     int32_t len0;                       // length of the RMr header data
68     int32_t len1;                       // length of the tracing data
69     int32_t len2;                       // length of data 1 (d1)
70     int32_t len3;                       // length of data 2 (d2)
71     int32_t sub_id;                     // subscription id (-1 invalid)
72
73                                         // v3 extension
74     unsigned char srcip[RMR_MAX_SRC];   // ip address and port of the source
75 } em_mhdr_t;
76
77 //--------------------------------------------------------------------------
78 /*
79         These are the current references in the RMR code; all others are internal
80         to the SI portion of the library
81
82         SIcbreg( ctx->si_ctx, 
83         SIwait( ctx->si_ctx );
84         SIinitialise( SI_OPT_FG );              // FIX ME: si needs to streamline and drop fork/bg stuff
85         SIlistener( ctx->si_ctx, TCP_DEVICE, bind_info )) < 0 ) {
86         SItp_stats( ctx->si_ctx );                      // dump some interesting stats
87         SIclose( ctx->nn_sock );
88         SIset_tflags( ctx->si_ctx, SI_TF_FASTACK );
89         SIconnect( si_ctx, conn_info )) < 0 ) {
90         SIsendt( ctx->si_ctx, nn_sock, msg->tp_buf, tot_len )) != SI_OK ) {
91 */
92
93 #define SIEM_BLOCKED    18
94 #define SIEM_ERROR              (-1)
95 #define SIEM_OK                 0
96
97 #define SOCKET_TYPE             int             // socket representation is different in each transport
98
99 struct ginfo_blk;                               // defined in SI things, but must exist here
100
101 #include "si95/socket_if.h"             // need to have the si context more than anything else
102
103
104 static void *em_sinew( int type ) {
105         return NULL;
106 }
107
108 static char *em_sigetname( int sid ) {
109         return "somename";
110 }
111
112 static int em_siaddress( void *src, void **dest, int type ) {
113         return 0;
114 }
115
116 static void em_sibldpoll( struct ginfo_blk* gptr ) {
117         return;
118 }
119
120 static struct tp_blk *em_siconn_prep( struct ginfo_blk *gptr, int type, char *abuf, int family ) {
121         return NULL;
122 }
123
124 /*
125         Caller passing a callback funciton for SI to drive; nothing to do.
126 */
127 void *em_cb_data = NULL;
128 static void em_sicbreg( struct ginfo_blk *gptr, int type, int ((*fptr)()), void * dptr ) {
129         if( em_cb_data == NULL ) {
130                 fprintf( stderr, "<SIEM> calldback dptr %p saved for type %d\n", dptr, type );
131                 em_cb_data = dptr;
132         }
133         return;
134 }
135
136 static void em_sicbstat( struct ginfo_blk *gptr, int status, int type ) {
137         return;
138 }
139
140 static int em_siclose( struct ginfo_blk *gptr, int fd ) {
141         return 0;
142 }
143
144 /*
145         If em_send_failures is true, this will fail a small part of the time
146         to simualte connection failures.
147 */
148 static int em_next_fd = 0;
149 static int em_siconnect( struct ginfo_blk *gptr, char *abuf ) {
150         static int count = 0;
151
152         if( em_send_failures && (count++ % 15 == 14) ) {
153                 //fprintf( stderr, "<SIEM> siem is failing connect attempt\n\n" );
154                 return -1;
155         }
156
157         fprintf( stderr, "<SIEM> siem is emulating connect to (%s) attempt return fd=%d\n", abuf, em_next_fd );
158         if( em_next_fd < 50 ) {
159                 em_next_fd++;
160         }
161         return em_next_fd-1;
162 }
163
164 static struct tp_blk *em_siestablish( int type, char *abuf, int family ) {
165         return NULL;
166 }
167
168 static int em_sigenaddr( char *target, int proto, int family, int socktype, struct sockaddr **rap ) {
169         return 0;
170 }
171
172 static int em_sigetaddr( struct ginfo_blk *gptr, char *buf ) {
173         return 0;
174 }
175
176 static struct tp_blk *em_silisten_prep( struct ginfo_blk *gptr, int type, char* abuf, int family ) {
177         return NULL;
178 }
179
180 /*
181         Called to open a listen port; returns the port fd or -1 on error.
182 */
183 static int em_silistener( struct ginfo_blk *gptr, int type, char *abuf ) {
184         return 100;
185 }
186
187 static void em_simap_fd( struct ginfo_blk *gptr, int fd, struct tp_blk* tpptr ) {
188         return;
189 }
190
191 static int em_sinewsession( struct ginfo_blk *gptr, struct tp_blk *tpptr ) {
192         return 0;
193 }
194
195 static int em_sipoll( struct ginfo_blk *gptr, int msdelay ) {
196         return 0;
197 }
198
199 static int em_sircv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char *abuf, int delay ) {
200         return 0;
201 }
202
203 static void em_sisend( struct ginfo_blk *gptr, struct tp_blk *tpptr ) {
204         return;
205 }
206
207 /*
208         Calling this function causes the send emulation to turn off the call
209         flag in the RMR header. Turning that flag off makes the arriving message
210         look as though it might be a response to a call rather than a call itself.
211         This is needed since we loop back messages.
212 */
213 static void em_disable_call_flg() {
214         em_reset_call_flag = 1;
215         fprintf( stderr, "<SIEM> reset call flag setting is: %d\n", em_reset_call_flag );
216 }
217
218 /*
219         Opposite of disable_call_flg; the flag is not touched.
220 */
221 static void em_allow_call_flg() {
222         em_reset_call_flag = 0;
223         fprintf( stderr, "<SIEM> reset call flag setting is: %d\n", em_reset_call_flag );
224 }
225
226 //  callback prototype to drive to simulate 'receive'
227 static int mt_data_cb( void* datap, int fd, char* buf, int buflen );
228
229 /*
230         Emulate sending a message. If the global em_send_failures is set,
231         then every so often we fail with an EAGAIN to drive that part
232         of the code in RMr.
233
234         "Send a message" by passing it to the callback if we have a non-nil cb data pointer.
235         We'll divide the data into two to test the concatination of the receiver.
236 */
237 static int em_sisendt( struct ginfo_blk *gptr, int fd, char *ubuf, int ulen ) {
238         static int count = 0;
239         static int uss = -1;            // ultra short send done
240
241         if( em_send_failures && ((count++ % 15) == 14) ) {
242                 //fprintf( stderr, "<SIEM> sendt is failing send with blocked/again\n\n" );
243                 errno = EAGAIN;
244                 return SIEM_BLOCKED;
245         }
246
247         if( em_reset_call_flag ) {              // for call testing we need to flip the flag off to see it "return"
248                 em_mhdr_t*      hdr;
249
250                 hdr = (em_mhdr_t *) (ubuf+50);          // past the transport header bytes
251                 hdr->flags &= ~HFL_CALL_MSG;            // flip off the call flag
252         }
253
254         uss++;
255
256         if( em_cb_data != NULL ) {
257                 if( uss == 1 ) {                                        // drive the reconstruction where a split in the msg length happens
258                         fprintf( stderr, "<SIEM> sendt is queuing ultra short first packet of a two packet sendh len=%d\n", ulen );
259                         mt_data_cb( em_cb_data, 0, ubuf, 3 );
260                         mt_data_cb( em_cb_data, 0, ubuf+3, ulen - 3 );
261                 } else {
262                         if( ulen > 100 ) {
263                                 fprintf( stderr, "<SIEM> sendt is queuing two packets with the callback len=%d\n", ulen );
264                                 mt_data_cb( em_cb_data, 0, ubuf, 100 );
265                                 mt_data_cb( em_cb_data, 0, ubuf+100, ulen - 100 );
266                         } else {
267                                 fprintf( stderr, "<SIEM> sendt is queuing one packet with the callback len=%d\n", ulen );
268                                 mt_data_cb( em_cb_data, 0, ubuf, ulen );
269                         }
270                 }
271         }
272
273         errno = 0;
274         //fprintf( stderr, "<SIEM> sendt is returning default reeturn status: %d\n", return_value );
275         return return_value;
276 }
277
278 /*
279         Sets flags; ignore.
280 */
281 static void em_siset_tflags( struct ginfo_blk *gp, int flags ) {
282         return;
283 }
284
285 static int em_sishow_version( ) {
286         return 0;
287 }
288
289 static void em_sishutdown( struct ginfo_blk *gptr ) {
290         return;
291 }
292
293 /*
294         This prints some SI stats -- ignore.
295 */
296 static void em_sitp_stats( void *vgp ) {
297         return;
298 }
299
300 static void em_siterm( struct ginfo_blk* gptr, struct tp_blk *tpptr ) {
301         return;
302 }
303
304 static void em_sitrash( int type, void *bp ) {
305         return;
306 }
307
308 /*
309         This will be tricky.  Wait receives raw packets from the network
310         and drives the callback(s) which are registered.  We'll need to 
311         simulate driving the callback with data that spans multiple FDs
312         and has messages split across buffers, but does not block foreaver
313         so the test can continue.
314         It won't be pretty.
315
316         For now We'll hard code the RMR callback functions and not 
317         try to use what it passes via the register function lest we
318         need to implement all of SI just to run unit tests.
319
320
321         Thinking: use rmr's alloc function to alloc a message buffer
322         which we fill in.  We can cheat and add the length as RMR does
323         on send, and then split the buffer as we feed it back to the 
324         callback function.
325 */
326 static int em_siwait( struct ginfo_blk *gptr ) {
327         return 0;
328 }
329
330 /*
331         The emulation doesn't use the global info stuff, so alloc something
332         to generate a pointer.
333 */
334 static struct ginfo_blk *em_siinitialise( int opts ) {
335         void *p;
336
337         p = malloc( 1024 );
338         return p;
339 }
340
341
342 // redefine all SI calls to reference functions here.
343 #define SInew em_sinew
344 #define sigetname em_sigetname
345 #define SIaddress em_siaddress
346 #define SIbldpoll em_sibldpoll
347 #define SIconn_prep em_siconn_prep
348 #define SIcbreg em_sicbreg
349 #define SIcbstat em_sicbstat
350 //#define SIclose em_siclose
351 #define SIconnect em_siconnect
352 #define SIestablish em_siestablish
353 #define SIgenaddr em_sigenaddr
354 #define SIgetaddr em_sigetaddr
355 #define SIlisten_prep em_silisten_prep
356 #define SIlistener em_silistener
357 #define SImap_fd em_simap_fd
358 #define SInewsession em_sinewsession
359 #define SIpoll em_sipoll
360 #define SIrcv em_sircv
361 #define SIsend em_sisend
362 #define SIsendt em_sisendt
363 #define SIset_tflags em_siset_tflags
364 #define SIshow_version em_sishow_version
365 #define SIshutdown em_sishutdown
366 #define SItp_stats em_sitp_stats
367 #define SIterm em_siterm
368 #define SItrash em_sitrash
369 #define SIwait em_siwait
370 #define SIinitialise em_siinitialise
371
372
373 #endif