/* ================================================================================== Copyright (c) 2020 Nokia Copyright (c) 2020 AT&T Intellectual Property. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================================================== */ /* Mnemonic: test_common_em.c Abstract: This supplies some dummy emulation functions that are common to any of the emulation code. This file should be inlucded by the emulation code, and not the test programme. This also includes dummy struct defs so that we can simulate returning messages and message buffers and some control functions which can be used to taylor the emulation behavour during the test. Date: 21 February 2020 Author: E. Scott Daniels */ #ifndef _em_common_c #define _em_common_c static int em_send_failures = 0; // test programme can set this to emulate eagain send failures static int em_timeout = -1; // set by set socket option static int em_mtc_msgs = 0; // set to generate 'received' messages with mt-call header data static int return_value = 0; // functions should return this value static int rcv_count = 0; // receive counter for transaction id to allow test to rest static int rcv_delay = 0; // forced delay before call to rcvmsg starts to work static int gates_ok = 0; static pthread_mutex_t rcv_gate; static int em_gen_long_hostname = 0; // if set the emulated hostname generates a longer name (>40 char) /* Simulated v1 message for receive to return. This needs to match the RMr header so that we can fill in length, type and xaction id things. #define MSG_VER 1 struct em_msg { int32_t mtype; // message type ("long" network integer) int32_t plen; // payload length int32_t rmr_ver; // our internal message version number unsigned char xid[32]; // space for user transaction id or somesuch unsigned char sid[32]; // sender ID for return to sender needs unsigned char src[16]; // name of the sender (source) unsigned char meid[32]; // managed element id. struct timespec ts; // timestamp ??? }; */ /* v2 message; should be able to use it for everything that is set up here as we don't add a payload even if setting a v1 type. */ #define ALT_MSG_VER 1 // alternate every so often #define MSG_VER 3 // default version to insert struct em_msg { int32_t mtype; // message type ("long" network integer) int32_t plen; // payload length int32_t rmr_ver; // our internal message version number unsigned char xid[32]; // space for user transaction id or somesuch unsigned char sid[32]; // sender ID for return to sender needs unsigned char src[64]; // name of the sender (source) unsigned char meid[32]; // managed element id. struct timespec ts; // timestamp ??? // V2 extension int32_t flags; // HFL_* constants int32_t len0; // length of the RMr header data int32_t len1; // length of the tracing data int32_t len2; // length of data 1 (d1) int32_t len3; // length of data 2 (d2) int32_t sub_id; // subscription id (-1 invalid) // V3 stuff unsigned char srcip[64]; // sender ID for return to sender needs }; // -- emulation control functions ------------------------------------------------------ /* Test app can call this to have all emulated functions return failure instead of success. */ static void en_set_return( int rv ) { return_value = rv; } static int em_nng_foo() { fprintf( stderr, "emulated functions in play" ); } /* Turns on/off the generation of multi-threaded call messages */ static int em_set_mtc_msgs( int state ) { em_mtc_msgs = state; } /* Returns the size of the header we inserted */ static int em_hdr_size() { if( em_mtc_msgs ) { return (int) sizeof( struct em_msg ) + 4; } return (int) sizeof( struct em_msg ); } static void em_set_rcvcount( int v ) { rcv_count = v; } static void em_set_rcvdelay( int v ) { if( v < 0 ) { fprintf( stderr, " ##ERR## attempt to set receive delay with invalid value was ignored: %d seconds\n", v ); return; } fprintf( stderr, " receive delay is now %d seconds\n", v ); rcv_delay = v; } static void em_start() { if( ! gates_ok ) { pthread_mutex_init( &rcv_gate, NULL ); gates_ok = 1; } } // ----------- gethostname emulation --------------------------------------- #define gethostname em_gethostname static int em_gethostname( char* buf, size_t len ) { if( len < 1 ) { errno = EINVAL; return 1; } if( em_gen_long_hostname ) { snprintf( buf, len, "hostname-which-is-long-a860430b890219-dfw82" ); } else { snprintf( buf, len, "em-hostname" ); } return 0; } static int em_set_long_hostname( int v ) { em_gen_long_hostname = !!v; } // ----------- epoll emulation --------------------------------------------- // CAUTION: sys/epoll.h must be included before these define for functions // to properly compile. // #include #define epoll_wait em_wait #define epoll_ctl em_ep_ctl #define epoll_create em_ep_create /* Every other call returns 1 ready; alternate calls return 0 ready. Mostly for testing the timeout receive call. First call should return something ready and the second should return nothing ready so we can drive both cases. */ static int em_wait( int fd, void* events, int n, int to ) { static int ready = 0; ready = !ready; return ready; } static int em_ep_ctl( int epfd, int op, int fd, struct epoll_event *event ) { return 0; } static int em_ep_create( int size ) { return 0; } #endif