2 ==================================================================================
3 Copyright (c) 2020 Nokia
4 Copyright (c) 2020 AT&T Intellectual Property.
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
10 http://www.apache.org/licenses/LICENSE-2.0
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 ==================================================================================
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.
26 This module must be directly included to be used.
27 Date: 20 February 2020
28 Author: E. Scott Daniels
32 #include "rmr.h" // we use some of rmr defs in building dummy messages, so we need these
33 #include "rmr_agnostic.h"
35 // ---------------------- emulated nng functions ---------------------------
38 #ifndef _em_si // this is the same define as the nng emulation code uses to give warning if both included
41 #include <arpa/inet.h>
44 #include "test_common_em.c" // common emulation needed for all (epoll, gethostname...)
46 //--------------------------------------------------------------------------
48 These are the current references in the RMR code; all others are internal
49 to the SI portion of the library
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 ) {
62 #define SIEM_BLOCKED 18
63 #define SIEM_ERROR (-1)
66 #define SOCKET_TYPE int // socket representation is different in each transport
68 struct ginfo_blk; // defined in SI things, but must exist here
70 #include "si95/socket_if.h" // need to have the si context more than anything else
73 static void *em_sinew( int type ) {
77 static char *em_sigetname( int sid ) {
81 static int em_siaddress( void *src, void **dest, int type ) {
85 static void em_sibldpoll( struct ginfo_blk* gptr ) {
89 static struct tp_blk *em_siconn_prep( struct ginfo_blk *gptr, int type, char *abuf, int family ) {
94 Caller passing a callback funciton for SI to drive; nothing to do.
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 );
105 static void em_sicbstat( struct ginfo_blk *gptr, int status, int type ) {
109 static int em_siclose( struct ginfo_blk *gptr, int fd ) {
114 If em_send_failures is true, this will fail a small part of the time
115 to simualte connection failures.
117 static int em_next_fd = 0;
118 static int em_siconnect( struct ginfo_blk *gptr, char *abuf ) {
119 static int count = 0;
121 if( em_send_failures && (count++ % 15 == 14) ) {
122 //fprintf( stderr, "<SIEM> siem is failing connect attempt\n\n" );
126 fprintf( stderr, "<SIEM> siem is emulating connect attempt return fd=%d\n", em_next_fd );
131 static struct tp_blk *em_siestablish( int type, char *abuf, int family ) {
135 static int em_sigenaddr( char *target, int proto, int family, int socktype, struct sockaddr **rap ) {
139 static int em_sigetaddr( struct ginfo_blk *gptr, char *buf ) {
143 static struct tp_blk *em_silisten_prep( struct ginfo_blk *gptr, int type, char* abuf, int family ) {
148 Called to open a listen port; returns the port fd or -1 on error.
150 static int em_silistener( struct ginfo_blk *gptr, int type, char *abuf ) {
154 static void em_simap_fd( struct ginfo_blk *gptr, int fd, struct tp_blk* tpptr ) {
158 static int em_sinewsession( struct ginfo_blk *gptr, struct tp_blk *tpptr ) {
162 static int em_sipoll( struct ginfo_blk *gptr, int msdelay ) {
166 static int em_sircv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char *abuf, int delay ) {
170 static void em_sisend( struct ginfo_blk *gptr, struct tp_blk *tpptr ) {
174 // callback prototype to drive to simulate 'receive'
175 static int mt_data_cb( void* datap, int fd, char* buf, int buflen );
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
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.
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
188 if( em_send_failures && ((count++ % 15) == 14) ) {
189 //fprintf( stderr, "<SIEM> sendt is failing send with blocked/again\n\n" );
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 );
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 );
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 );
214 //fprintf( stderr, "<SIEM> sendt is returning default reeturn status: %d\n", return_value );
221 static void em_siset_tflags( struct ginfo_blk *gp, int flags ) {
225 static int em_sishow_version( ) {
229 static void em_sishutdown( struct ginfo_blk *gptr ) {
234 This prints some SI stats -- ignore.
236 static void em_sitp_stats( void *vgp ) {
240 static void em_siterm( struct ginfo_blk* gptr, struct tp_blk *tpptr ) {
244 static void em_sitrash( int type, void *bp ) {
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.
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.
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
266 static int em_siwait( struct ginfo_blk *gptr ) {
271 The emulation doesn't use the global info stuff, so alloc something
272 to generate a pointer.
274 static struct ginfo_blk *em_siinitialise( int opts ) {
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