c2cf4cb45bcf920417bc737e8019135b411cc6dd
[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 nng 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 //--------------------------------------------------------------------------
47 /*
48         These are the current references in the RMR code; all others are internal
49         to the SI portion of the library
50
51         SIcbreg( ctx->si_ctx, 
52         SIwait( ctx->si_ctx );
53         SIinitialise( SI_OPT_FG );              // FIX ME: si needs to streamline and drop fork/bg stuff
54         SIlistener( ctx->si_ctx, TCP_DEVICE, bind_info )) < 0 ) {
55         SItp_stats( ctx->si_ctx );                      // dump some interesting stats
56         SIclose( ctx->nn_sock );
57         SIset_tflags( ctx->si_ctx, SI_TF_FASTACK );
58         SIconnect( si_ctx, conn_info )) < 0 ) {
59         SIsendt( ctx->si_ctx, nn_sock, msg->tp_buf, tot_len )) != SI_OK ) {
60 */
61
62 #define SIEM_BLOCKED    18
63 #define SIEM_ERROR              (-1)
64 #define SIEM_OK                 0
65
66 #define SOCKET_TYPE             int             // socket representation is different in each transport
67
68 struct ginfo_blk;                               // defined in SI things, but must exist here
69
70 #include "si95/socket_if.h"             // need to have the si context more than anything else
71
72
73 static void *em_sinew( int type ) {
74         return NULL;
75 }
76
77 static char *em_sigetname( int sid ) {
78         return "somename";
79 }
80
81 static int em_siaddress( void *src, void **dest, int type ) {
82         return 0;
83 }
84
85 static void em_sibldpoll( struct ginfo_blk* gptr ) {
86         return;
87 }
88
89 static struct tp_blk *em_siconn_prep( struct ginfo_blk *gptr, int type, char *abuf, int family ) {
90         return NULL;
91 }
92
93 /*
94         Caller passing a callback funciton for SI to drive; nothing to do.
95 */
96 void *em_cb_data = NULL;
97 static void em_sicbreg( struct ginfo_blk *gptr, int type, int ((*fptr)()), void * dptr ) {
98         if( em_cb_data == NULL ) {
99                 fprintf( stderr, "<SIEM> calldback dptr %p saved for type %d\n", dptr, type );
100                 em_cb_data = dptr;
101         }
102         return;
103 }
104
105 static void em_sicbstat( struct ginfo_blk *gptr, int status, int type ) {
106         return;
107 }
108
109 static int em_siclose( struct ginfo_blk *gptr, int fd ) {
110         return 0;
111 }
112
113 /*
114         If em_send_failures is true, this will fail a small part of the time
115         to simualte connection failures.
116 */
117 static int em_next_fd = 0;
118 static int em_siconnect( struct ginfo_blk *gptr, char *abuf ) {
119         static int count = 0;
120
121         if( em_send_failures && (count++ % 15 == 14) ) {
122                 //fprintf( stderr, "<SIEM> siem is failing connect attempt\n\n" );
123                 return -1;
124         }
125
126         fprintf( stderr, "<SIEM> siem is emulating connect attempt return fd=%d\n", em_next_fd );
127         em_next_fd++;
128         return em_next_fd-1;
129 }
130
131 static struct tp_blk *em_siestablish( int type, char *abuf, int family ) {
132         return NULL;
133 }
134
135 static int em_sigenaddr( char *target, int proto, int family, int socktype, struct sockaddr **rap ) {
136         return 0;
137 }
138
139 static int em_sigetaddr( struct ginfo_blk *gptr, char *buf ) {
140         return 0;
141 }
142
143 static struct tp_blk *em_silisten_prep( struct ginfo_blk *gptr, int type, char* abuf, int family ) {
144         return NULL;
145 }
146
147 /*
148         Called to open a listen port; returns the port fd or -1 on error.
149 */
150 static int em_silistener( struct ginfo_blk *gptr, int type, char *abuf ) {
151         return 100;
152 }
153
154 static void em_simap_fd( struct ginfo_blk *gptr, int fd, struct tp_blk* tpptr ) {
155         return;
156 }
157
158 static int em_sinewsession( struct ginfo_blk *gptr, struct tp_blk *tpptr ) {
159         return 0;
160 }
161
162 static int em_sipoll( struct ginfo_blk *gptr, int msdelay ) {
163         return 0;
164 }
165
166 static int em_sircv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char *abuf, int delay ) {
167         return 0;
168 }
169
170 static void em_sisend( struct ginfo_blk *gptr, struct tp_blk *tpptr ) {
171         return;
172 }
173
174 //  callback prototype to drive to simulate 'receive'
175 static int mt_data_cb( void* datap, int fd, char* buf, int buflen );
176 /*
177         Emulate sending a message. If the global em_send_failures is set,
178         then every so often we fail with an EAGAIN to drive that part
179         of the code in RMr.
180
181         "Send a message" by passing it to the callback if we have a non-nil cb data pointer.
182         We'll divide the data into two to test the concatination of the receiver.
183 */
184 static int em_sisendt( struct ginfo_blk *gptr, int fd, char *ubuf, int ulen ) {
185         static int count = 0;
186         static int uss = -1;            // ultra short send done
187
188         if( em_send_failures && ((count++ % 15) == 14) ) {
189                 //fprintf( stderr, "<SIEM> sendt is failing send with blocked/again\n\n" );
190                 errno = EAGAIN;
191                 return SIEM_BLOCKED;
192         }
193
194         uss++;
195
196         if( em_cb_data != NULL ) {
197                 if( uss == 1 ) {                                        // drive the reconstruction where a split in the msg length happens
198                         fprintf( stderr, "<SIEM> sendt is queuing ultra short first packet of a two packet sendh len=%d\n", ulen );
199                         mt_data_cb( em_cb_data, 0, ubuf, 3 );
200                         mt_data_cb( em_cb_data, 0, ubuf+3, ulen - 3 );
201                 } else {
202                         if( ulen > 100 ) {
203                                 fprintf( stderr, "<SIEM> sendt is queuing two packets with the callback len=%d\n", ulen );
204                                 mt_data_cb( em_cb_data, 0, ubuf, 100 );
205                                 mt_data_cb( em_cb_data, 0, ubuf+100, ulen - 100 );
206                         } else {
207                                 fprintf( stderr, "<SIEM> sendt is queuing one packet with the callback len=%d\n", ulen );
208                                 mt_data_cb( em_cb_data, 0, ubuf, ulen );
209                         }
210                 }
211         }
212
213         errno = 0;
214         //fprintf( stderr, "<SIEM> sendt is returning default reeturn status: %d\n", return_value );
215         return return_value;
216 }
217
218 /*
219         Sets flags; ignore.
220 */
221 static void em_siset_tflags( struct ginfo_blk *gp, int flags ) {
222         return;
223 }
224
225 static int em_sishow_version( ) {
226         return 0;
227 }
228
229 static void em_sishutdown( struct ginfo_blk *gptr ) {
230         return;
231 }
232
233 /*
234         This prints some SI stats -- ignore.
235 */
236 static void em_sitp_stats( void *vgp ) {
237         return;
238 }
239
240 static void em_siterm( struct ginfo_blk* gptr, struct tp_blk *tpptr ) {
241         return;
242 }
243
244 static void em_sitrash( int type, void *bp ) {
245         return;
246 }
247
248 /*
249         This will be tricky.  Wait receives raw packets from the network
250         and drives the callback(s) which are registered.  We'll need to 
251         simulate driving the callback with data that spans multiple FDs
252         and has messages split across buffers, but does not block foreaver
253         so the test can continue.
254         It won't be pretty.
255
256         For now We'll hard code the RMR callback functions and not 
257         try to use what it passes via the register function lest we
258         need to implement all of SI just to run unit tests.
259
260
261         Thinking: use rmr's alloc function to alloc a message buffer
262         which we fill in.  We can cheat and add the length as RMR does
263         on send, and then split the buffer as we feed it back to the 
264         callback function.
265 */
266 static int em_siwait( struct ginfo_blk *gptr ) {
267         return 0;
268 }
269
270 /*
271         The emulation doesn't use the global info stuff, so alloc something
272         to generate a pointer.
273 */
274 static struct ginfo_blk *em_siinitialise( int opts ) {
275         void *p;
276
277         p = malloc( 1024 );
278         return p;
279 }
280
281
282 // redefine all SI calls to reference functions here.
283 #define SInew em_sinew
284 #define sigetname em_sigetname
285 #define SIaddress em_siaddress
286 #define SIbldpoll em_sibldpoll
287 #define SIconn_prep em_siconn_prep
288 #define SIcbreg em_sicbreg
289 #define SIcbstat em_sicbstat
290 //#define SIclose em_siclose
291 #define SIconnect em_siconnect
292 #define SIestablish em_siestablish
293 #define SIgenaddr em_sigenaddr
294 #define SIgetaddr em_sigetaddr
295 #define SIlisten_prep em_silisten_prep
296 #define SIlistener em_silistener
297 #define SImap_fd em_simap_fd
298 #define SInewsession em_sinewsession
299 #define SIpoll em_sipoll
300 #define SIrcv em_sircv
301 #define SIsend em_sisend
302 #define SIsendt em_sisendt
303 #define SIset_tflags em_siset_tflags
304 #define SIshow_version em_sishow_version
305 #define SIshutdown em_sishutdown
306 #define SItp_stats em_sitp_stats
307 #define SIterm em_siterm
308 #define SItrash em_sitrash
309 #define SIwait em_siwait
310 #define SIinitialise em_siinitialise
311
312
313 #endif