extern EOtransmitter* eo_transmitter_New(const eo_transmitter_cfg_t *cfg) { EOtransmitter *retptr = NULL; if(NULL == cfg) { cfg = &eo_transmitter_cfg_default; } // i get the memory for the object retptr = eo_mempool_GetMemory(eo_mempool_GetHandle(), eo_mempool_align_32bit, sizeof(EOtransmitter), 1); retptr->txpacket = eo_packet_New(cfg->capacityoftxpacket); retptr->ropframereadytotx = eo_ropframe_New(); retptr->ropframeregulars = eo_ropframe_New(); retptr->ropframeoccasionals = eo_ropframe_New(); retptr->ropframereplies = eo_ropframe_New(); retptr->roptmp = eo_rop_New(cfg->capacityofrop); retptr->nvscfg = cfg->nvscfg; retptr->theagent = eo_agent_Initialise(NULL); retptr->ipv4addr = cfg->ipv4addr; retptr->ipv4port = cfg->ipv4port; retptr->bufferropframeregulars = eo_mempool_GetMemory(eo_mempool_GetHandle(), eo_mempool_align_32bit, cfg->capacityofropframeregulars, 1); retptr->bufferropframeoccasionals = eo_mempool_GetMemory(eo_mempool_GetHandle(), eo_mempool_align_32bit, cfg->capacityofropframeoccasionals, 1); retptr->bufferropframereplies = eo_mempool_GetMemory(eo_mempool_GetHandle(), eo_mempool_align_32bit, cfg->capacityofropframereplies, 1); retptr->listofregropinfo = (0 == cfg->maxnumberofregularrops) ? (NULL) : (eo_list_New(sizeof(eo_transm_regrop_info_t), cfg->maxnumberofregularrops, NULL, 0, NULL, NULL)); retptr->currenttime = 0; retptr->tx_seqnum = 0; eo_ropframe_Load(retptr->ropframeregulars, retptr->bufferropframeregulars, eo_ropframe_sizeforZEROrops, cfg->capacityofropframeregulars); eo_ropframe_Clear(retptr->ropframeregulars); eo_ropframe_Load(retptr->ropframeoccasionals, retptr->bufferropframeoccasionals, eo_ropframe_sizeforZEROrops, cfg->capacityofropframeoccasionals); eo_ropframe_Clear(retptr->ropframeoccasionals); eo_ropframe_Load(retptr->ropframereplies, retptr->bufferropframereplies, eo_ropframe_sizeforZEROrops, cfg->capacityofropframereplies); eo_ropframe_Clear(retptr->ropframereplies); { // we set the content of ropframereadytotx with the same memory used by txpacket, so that when we operate on // ropframereadytotx then we prepare the txpacket. uint8_t *data; uint16_t size; uint16_t capacity; eo_packet_Payload_Get(retptr->txpacket, &data, &size); eo_packet_Capacity_Get(retptr->txpacket, &capacity); eo_ropframe_Load(retptr->ropframereadytotx, data, eo_ropframe_sizeforZEROrops, capacity); // dont use size because size is now zero. eo_ropframe_Clear(retptr->ropframereadytotx); if(eobool_true != eo_ropframe_IsValid(retptr->ropframereadytotx)) { eo_errman_Error(eo_errman_GetHandle(), eo_errortype_fatal, s_eobj_ownname, "the ropframeready2tx is not valid... cannot continue"); } // the destination ipv4addr and ipv4port are constant and are the ones passed through configuration eo_packet_Addressing_Set(retptr->txpacket, retptr->ipv4addr, retptr->ipv4port); } if((NULL != cfg->mutex_fn_new) && (eo_transmitter_protection_total == cfg->protection)) { retptr->mtx_replies = cfg->mutex_fn_new(); retptr->mtx_regulars = cfg->mutex_fn_new(); retptr->mtx_occasionals = cfg->mutex_fn_new(); } else { retptr->mtx_replies = NULL; retptr->mtx_regulars = NULL; retptr->mtx_occasionals = NULL; } #if defined(USE_DEBUG_EOTRANSMITTER) // DEBUG retptr->debug.txropframeistoobigforthepacket = 0; #endif return(retptr); }
extern eOresult_t eo_receiver_Process(EOreceiver *p, EOpacket *packet, uint16_t *numberofrops, eObool_t *thereisareply, eOabstime_t *transmittedtime) { uint16_t rxremainingbytes = 0; uint16_t txremainingbytes = 0; uint8_t* payload; uint16_t size; uint16_t capacity; uint16_t nrops; uint16_t i; eOresult_t res; eOipv4addr_t remipv4addr; eOipv4port_t remipv4port; uint64_t rec_seqnum; uint64_t rec_ageoframe; uint16_t numofprocessedrops = 0; if((NULL == p) || (NULL == packet)) { return(eores_NOK_nullpointer); } // clear the ropframereply w/ eo_ropframe_Clear(). the clear operation also makes it safe to manipulate p->ropframereplay with *_quickversion eo_ropframe_Clear(p->ropframereply); // we get the ip address and port of the incoming packet. // the remaddr can be any. however, if the eo_receiver_Process() is called by the EOtransceiver, it will be only the one of the remotehost eo_packet_Addressing_Get(packet, &remipv4addr, &remipv4port); // then we assign them to the ones of the EOreceiver. by doing so we force the receive to accept packets from everyboby. //p->ipv4addr = remipv4addr; //p->ipv4port = remipv4port; // retrieve payload from the incoming packet and load the ropframe with it eo_packet_Payload_Get(packet, &payload, &size); eo_packet_Capacity_Get(packet, &capacity); eo_ropframe_Load(p->ropframeinput, payload, size, capacity); // verify if the ropframeinput is valid w/ eo_ropframe_IsValid() if(eobool_false == eo_ropframe_IsValid(p->ropframeinput)) { #if defined(USE_DEBUG_EORECEIVER) { // DEBUG p->debug.rxinvalidropframes ++; } #endif p->error_invalidframe.remipv4addr = remipv4addr; p->error_invalidframe.ropframe = p->ropframeinput; s_eo_receiver_on_error_invalidframe(p); if(NULL != thereisareply) { *thereisareply = eobool_false; } return(eores_NOK_generic); } // check sequence number rec_seqnum = eo_ropframe_seqnum_Get(p->ropframeinput); rec_ageoframe = eo_ropframe_age_Get(p->ropframeinput); if(p->rx_seqnum == eok_uint64dummy) { //this is the first received ropframe or ... the sender uses dummy seqnum p->rx_seqnum = rec_seqnum; p->tx_ageofframe = rec_ageoframe; } else { if(rec_seqnum != (p->rx_seqnum+1)) { #if defined(USE_DEBUG_EORECEIVER) { p->debug.errorsinsequencenumber ++; } #endif // must set values p->error_seqnumber.remipv4addr = remipv4addr; p->error_seqnumber.rec_seqnum = rec_seqnum; p->error_seqnumber.exp_seqnum = p->rx_seqnum+1; p->error_seqnumber.timeoftxofcurrent = rec_ageoframe; p->error_seqnumber.timeoftxofprevious = p->tx_ageofframe; s_eo_receiver_on_error_seqnumber(p); } p->rx_seqnum = rec_seqnum; p->tx_ageofframe = rec_ageoframe; } nrops = eo_ropframe_ROP_NumberOf_quickversion(p->ropframeinput); for(i=0; i<nrops; i++) { // - get the rop w/ eo_ropframe_ROP_Parse() // if we have a valid ropinput the following eo_ropframe_ROP_Parse() returns OK. // in all cases rxremainingbytes contains the number of bytes we still need to parse. in case of // unrecoverable error in the ropframe res is NOK and rxremainingbytes is 0. res = eo_ropframe_ROP_Parse(p->ropframeinput, p->ropinput, &rxremainingbytes); if(eores_OK == res) { // we have a valid ropinput numofprocessedrops++; // - use the agent w/ eo_agent_InpROPprocess() and retrieve the ropreply. eo_agent_InpROPprocess(p->agent, p->ropinput, remipv4addr, p->ropreply); // - if ropreply is ok w/ eo_rop_GetROPcode() then add it to ropframereply w/ eo_ropframe_ROP_Add() if(eo_ropcode_none != eo_rop_GetROPcode(p->ropreply)) { res = eo_ropframe_ROP_Add(p->ropframereply, p->ropreply, NULL, NULL, &txremainingbytes); #if defined(USE_DEBUG_EORECEIVER) { // DEBUG if(eores_OK != res) { p->debug.lostreplies ++; } } #endif } } // we stop the decoding if rxremainingbytes has reached zero if(0 == rxremainingbytes) { break; } } if(NULL != numberofrops) { *numberofrops = numofprocessedrops; } // if any rop inside ropframereply w/ eo_ropframe_ROP_NumberOf() then sets thereisareply if(NULL != thereisareply) { *thereisareply = (0 == eo_ropframe_ROP_NumberOf(p->ropframereply)) ? (eobool_false) : (eobool_true); // dont use the quickversion because it may be that ropframereply is dummy //*thereisareply = (0 == eo_ropframe_ROP_NumberOf_quickversion(p->ropframereply)) ? (eobool_false) : (eobool_true); } if(NULL != transmittedtime) { *transmittedtime = eo_ropframe_age_Get(p->ropframeinput); } return(eores_OK); }