Ejemplo n.º 1
0
void Global::launchBeacon()
{
  sendBeacon();
  if(mBeaconTimer)
  {
    mBeaconTimer->setSingleShot(false);
    connect(mBeaconTimer, SIGNAL(timeout()), this, SLOT(sendBeacon()) );
    mBeaconTimer->start(5000);
  }
}
Ejemplo n.º 2
0
int InterfaceController_beaconState(struct InterfaceController* ifc,
                                    int interfaceNumber,
                                    int newState)
{
    struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) ifc);
    struct InterfaceController_Iface_pvt* ici = ArrayList_OfIfaces_get(ic->icis, interfaceNumber);
    if (!ici) {
        return InterfaceController_beaconState_NO_SUCH_IFACE;
    }
    char* val = NULL;
    switch (newState) {
        default: return InterfaceController_beaconState_INVALID_STATE;
        case InterfaceController_beaconState_newState_OFF: val = "OFF"; break;
        case InterfaceController_beaconState_newState_ACCEPT: val = "ACCEPT"; break;
        case InterfaceController_beaconState_newState_SEND: val = "SEND"; break;
    }
    Log_debug(ic->logger, "InterfaceController_beaconState(%s, %s)", ici->name->bytes, val);
    ici->beaconState = newState;
    if (newState == InterfaceController_beaconState_newState_SEND) {
        // Send out a beacon right away so we don't have to wait.
        struct Allocator* alloc = Allocator_child(ici->alloc);
        sendBeacon(ici, alloc);
        Allocator_free(alloc);
    }
    return 0;
}
Ejemplo n.º 3
0
static void beaconInterval(void* vInterfaceController)
{
    struct InterfaceController_pvt* ic =
        Identity_check((struct InterfaceController_pvt*) vInterfaceController);

    struct Allocator* alloc = Allocator_child(ic->alloc);
    for (int i = 0; i < ic->icis->length; i++) {
        struct InterfaceController_Iface_pvt* ici = ArrayList_OfIfaces_get(ic->icis, i);
        sendBeacon(ici, alloc);
    }
    Allocator_free(alloc);

    if (ic->beaconTimeoutAlloc) {
        Allocator_free(ic->beaconTimeoutAlloc);
    }
    ic->beaconTimeoutAlloc = Allocator_child(ic->alloc);
    Timeout_setTimeout(
        beaconInterval, ic, ic->beaconInterval, ic->eventBase, ic->beaconTimeoutAlloc);
}
Ejemplo n.º 4
0
void vApplicationIdleHook(void)
{
	static char sending=0;
	static char state=0;
	static char* sendData=NULL;
	OBD2HW_Header* pobd2hw;

	#ifdef APPLICATION_START_TIME
		if(xTaskGetTickCount()-ob_app_start<APPLICATION_START_TIME) {
			usb_stat.stat_time 	  = ob_app_start + 2*APPLICATION_START_TIME;
			ob_int_mgmt.stat_time = ob_app_start + 2*APPLICATION_START_TIME + OPENBEACON_STATS_AUTO_SEND_TIME/2;

			return;
		}
	#endif

	// TODO: erforsche diesen Einfluss | nRFAPI_GetStatus()&STATUS_TX_DS
	if(xTaskGetTickCount()-ob_send_time > OPENBEACON_SEND_WIRELESS ) {
		AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_RED );
		sending=0;
		ob_switchRXMode();
	}

	#ifdef OPENBEACON_RECIVE_WIRELESS
		if( last_usb_sendmesg==NULL ) last_usb_sendmesg = pullFreeBlock();

		if(sending==0 && last_usb_sendmesg!=NULL) {
			// Wirless Packete empfangen
			pobd2hw = (OBD2HW_Header*) last_usb_sendmesg->pValue;
			pobd2hw->length=recvBeacon( &recv_buffer );

			if( pobd2hw->length>0 ) {
				sending=1;
				memcpy(last_usb_sendmesg->pValue+sizeof(OBD2HW_Header)+sizeof(Click2OBD_header)-OPENBEACON_MACSIZE, recv_buffer.payload, pobd2hw->length );

				// TODO: auswerten der Daten (ggf. weiterleiten an Click)
				pobd2hw->type=PACKET_DATA;
				pobd2hw->length += sizeof(Click2OBD_header);

				Click2OBD_header* pclick2obd = (Click2OBD_header*) (last_usb_recvmesg->pValue+sizeof(OBD2HW_Header) );
				pclick2obd->channel = ob_int_mgmt.TxChannel;
				pclick2obd->rate	= ob_int_mgmt.TxRate;
				pclick2obd->power 	= ob_int_mgmt.TxPowerLevel;
				#ifdef OPENBEACON_TRANSMIT_WIRELESS_TO_USB
					vUSBSendPacket( last_usb_sendmesg, pobd2hw->length+sizeof(OBD2HW_Header) );
					last_usb_sendmesg = NULL;
				#endif
			}
		}
	#endif
	#ifdef OPENBEACON_TEST_AUTO_SEND
		if(sending==0 && xTaskGetTickCount()-ob_send_time > OPENBEACON_SEND_WIRELESS) {
			if( ob_int_mgmt.test_hw_diff<255 && xTaskGetTickCount()-ob_send_time>ob_int_mgmt.test_hw_diff ) {
				// TODO: Testpacket einrichten
				HW_rxtx_Test *htestp = (HW_rxtx_Test *)send_buffer.payload;
				char i;

				for(i=0; i<OPENBEACON_MACSIZE; i++) htestp->openbeacon_smac[ i ] = 0xFF;
				htestp->prot_type[0] = ETHERNET_TEST_PROTOCOL_FIRST;
				htestp->prot_type[1] = ETHERNET_TEST_PROTOCOL_SECOND;
				increment(htestp->pID, 4);

				switch( sendBeacon( &send_buffer ) ) {
					case 0:	sending=1;
						AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED_RED );
						ob_send_time=xTaskGetTickCount();
						break;
					case -1:
					break;
				}
			}
		}
	#endif

	// Sendet USB-Statistics
	#ifdef USB_STATS_AUTO_SEND
		#ifdef USB_STATS_AUTO_SEND_TIME
			sendUSBStat( USB_STATS_AUTO_SEND_TIME );
		#else
			sendUSBStat( 1000 );
		#endif
	#endif

	// Sendet Wirless-Statistics
	#ifdef OPENBEACON_STATS_AUTO_SEND
		#ifdef OPENBEACON_STATS_AUTO_SEND_TIME
			sendBeaconStat( OPENBEACON_STATS_AUTO_SEND_TIME );
		#else
			sendBeaconStat( 1000 );
		#endif
	#endif



	// Shelleingaben verarbeiten
	#ifdef APPLICATION_USBSHELL
			useShell();
	#endif

	// verarbeiten der USB Packete ( Datenpackete )
	#ifdef OPENBEACON_SEND_USB_PACKET_DATA
		if(last_usb_recvmesg==NULL) vUSBRecivePacket( &last_usb_recvmesg );
		if(sending==0 && last_usb_recvmesg!=NULL && xTaskGetTickCount()-ob_send_time > OPENBEACON_SEND_WIRELESS) {
			OBD2HW_Header* pobd2hw = (OBD2HW_Header*) last_usb_recvmesg->pValue;

			if( pobd2hw->type==PACKET_DATA ) {
				Click2OBD_header* pclick2obd = (Click2OBD_header*) (last_usb_recvmesg->pValue+sizeof(OBD2HW_Header) );

				ob_setChannel( pclick2obd->channel );
				ob_setRate( pclick2obd->rate );
				ob_setPower( pclick2obd->power );
				ob_setNetID( pclick2obd->openbeacon_dmac );

				// TODO: den Payload ob_data richtig festlegen
				memcpy(send_buffer.payload, last_usb_recvmesg->pValue+sizeof(OBD2HW_Header)+sizeof(Click2OBD_header)-OPENBEACON_MACSIZE, OPENBEACON_MAX_DATA);

				switch( sendBeacon( &send_buffer ) ) {
					case 0:	sending=1;
							AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED_RED );
							pushFreeBlock( last_usb_recvmesg );
							last_usb_recvmesg=NULL;
						break;
					case -1:

						break;
				}
				ob_send_time=xTaskGetTickCount();
			} else {
				pushFreeBlock( last_usb_recvmesg );
				last_usb_recvmesg=NULL;
			}
		}
	#endif
}
Ejemplo n.º 5
0
boolean Layer3::addToSendingQueue( packet_t* packet ) {
	//do we have a packet to be acked?
	if(packet->data.type != PACKET_NUMBERED) {
		return false;
	}

	//do we already have this packet?

	packet_numbered_t* numberedPacket = (packet_numbered_t*) &packet->data.payload;
	seq_t seqNumber = numberedPacket->seqNumber;

	#ifdef ENABLE_EXTERNAL_RAM
		SPIRamManager::iterator it = SPIRamManager::iterator(&ram, memRegionIdSend);
		while(it.hasNext()) {
			packet_sending_queue_item_t* currentItem = (packet_sending_queue_item_t*) it.next();
	#else
		for(uint8_t i = 0; i < CONFIG_L3_SEND_BUFFER_LEN; i++) {
			packet_sending_queue_item_t* currentItem = &sendingNumberedBuffer[i];
	#endif
			if(currentItem->packet.data.destination == 0) {
				//no content here.
				continue;
			}

			packet_numbered_t* numberedQueuePacket = (packet_numbered_t*) &currentItem->packet.data.payload;
			seq_t numberedQueuePacketSeq = numberedQueuePacket->seqNumber;

			if(currentItem->packet.data.destination == packet->data.destination //same destination
				&& seqNumber == numberedQueuePacketSeq //same seq
			) {

				//#ifdef DEBUG_NETWORK_ENABLE
					//Serial.print(millis());
					//Serial.println(F(": L3::addToSQ: dup"));
				//#endif
//
				//break, this is a duplicate.
				return false;
			}
		}

	//search free buffer entry
	#ifdef ENABLE_EXTERNAL_RAM
		SPIRamManager::iterator it2 = SPIRamManager::iterator(&ram, memRegionIdSend);
		while(it2.hasNext()) {
			packet_sending_queue_item_t* currentItem = (packet_sending_queue_item_t*) it2.next();
	#else
		for(uint8_t i = 0; i < CONFIG_L3_SEND_BUFFER_LEN; i++) {
			packet_sending_queue_item_t* currentItem = &sendingNumberedBuffer[i];
	#endif
			if(currentItem->packet.data.destination == 0) {
				currentItem->lasttimestamp = millis();
				currentItem->retransmissions = 0;
				memcpy(&currentItem->packet, packet, sizeof(packet_t));

				#ifdef ENABLE_EXTERNAL_RAM
					it2.writeBack();
				#endif

				return true;
			}
		}

	return false;
}

void Layer3::updateSendingBuffer() {
	////#ifdef DEBUG_NETWORK_ENABLE
		////Serial.print(millis());
		////Serial.println(F(": L3::updateSendingBuffer()"));
	////#endif

	uint32_t now = millis();
	#ifdef ENABLE_EXTERNAL_RAM
		SPIRamManager::iterator it = SPIRamManager::iterator(&ram, memRegionIdSend);
		while(it.hasNext()) {
		packet_sending_queue_item_t* currentItem = (packet_sending_queue_item_t*) it.next();
	#else
		for(uint8_t i = 0; i < CONFIG_L3_SEND_BUFFER_LEN; i++) {
			packet_sending_queue_item_t* currentItem = &sendingNumberedBuffer[i];
	#endif
			//is this a packet to be retransmitted?
			if(currentItem->packet.data.destination != 0) {
				//do we exceed max retransmissions?
				if(currentItem->retransmissions > CONFIG_L3_NUMBERED_RETRANSMISSIONS) {
					#ifdef DEBUG_NETWORK_ENABLE
						//Serial.print(millis());
						//Serial.print(F(": resend index="));
						#ifdef ENABLE_EXTERNAL_RAM
							Serial.print(it.getIteratorIndex() - 1);
						#else
							Serial.print(i);
						#endif
						//Serial.println(F(" retrans exceeded"));
					#endif

					//clear.
					#ifdef ENABLE_EXTERNAL_RAM
						it.remove();
					#else
						memset(&sendingNumberedBuffer[i], 0, sizeof(packet_sending_queue_item_t));
					#endif

					//next packet.
					continue;
				}

				//has it timed out? - or it may also be new (timestamp 0)
				if(currentItem->lasttimestamp == 0
					|| (now > currentItem->lasttimestamp
						&& now - currentItem->lasttimestamp > CONFIG_L3_NUMBERED_TIMEOUT_MS
						&& now > CONFIG_L3_NUMBERED_TIMEOUT_MS))
				{
					//#ifdef DEBUG_NETWORK_ENABLE
						//Serial.print(millis());
						//Serial.print(F(": resend index="));
						//#ifdef ENABLE_EXTERNAL_RAM
							//Serial.print(it.getIteratorIndex()-1);
						//#else
							//Serial.print(i);
						//#endif
						//Serial.print(F(": (re)sending #"));
						//Serial.print(currentItem->retransmissions);
						//Serial.print(F(" lastTimestamp="));
						//Serial.println(currentItem->lasttimestamp);
					//#endif

					//linear backoff.
					currentItem->lasttimestamp = now + currentItem->retransmissions * 20;
					currentItem->retransmissions++;

					#ifdef ENABLE_EXTERNAL_RAM
						it.writeBack();
					#endif

					//yep, resend it.
					//boolean result =
					sendPacket(currentItem->packet);

					//optionally delay.
					//delay(50);
				}
				//#ifdef DEBUG_NETWORK_ENABLE
					//else
						//Serial.println(F("not timed out yet"));
				//#endif

			}
	}
}

boolean Layer3::handleAck( packet_t* packet ) {
	//do we have an ack?
	if(packet->data.type != PACKET_ACK)
		return false;

	//get seq number
	packet_ack_t* ptr = (packet_ack_t*) packet->data.payload;
	seq_t seq = ptr->ack;

	#ifdef DEBUG_NETWORK_ENABLE
		Serial.print(millis());
		Serial.println(F(": L3::hndlAck:"));
		Serial.print(F("\tseq="));
		Serial.print(seq);
	#endif


	//search index
	#ifdef ENABLE_EXTERNAL_RAM
		SPIRamManager::iterator it = SPIRamManager::iterator(&ram, memRegionIdSend);
		while(it.hasNext()) {
		packet_sending_queue_item_t* currentItem = (packet_sending_queue_item_t*) it.next();
	#else
		for(uint8_t i = 0; i < CONFIG_L3_SEND_BUFFER_LEN; i++) {
			packet_sending_queue_item_t* currentItem = &sendingNumberedBuffer[i];
	#endif
			packet_numbered_t* ptr = (packet_numbered_t*) currentItem->packet.data.payload;
			if(ptr->seqNumber == seq) {
				//#ifdef DEBUG_NETWORK_ENABLE
					//uint16_t rtt = millis() - currentItem->lasttimestamp;
					//Serial.print(F(" RTT="));
					//Serial.print(rtt);
					//Serial.println(F(" cleared."));
				//#endif

				//clear.
				#ifdef ENABLE_EXTERNAL_RAM
					it.remove();
				#else
					memset(&sendingNumberedBuffer[i], 0, sizeof(packet_sending_queue_item_t));
				#endif

				return true;
			}
		}
	return false;
}

void Layer3::Loop() {
	//l2 check, receive
	l2->receive();
	while(l2->receiveQueueSize() > 0) {
		//get l2 data frame
		Layer2rf24::frame_t f;
		l2->receiveQueuePop(&f);

		//receive on l3
		receive((uint8_t*) &f.data.payload);
	}

	//send pending packet
	updateSendingBuffer();

	//beacon - neighbour announcement.
	if(millis() - beaconLastTimestamp > CONFIG_L3_BEACON_PERIOD_MS)	{
		beaconLastTimestamp = millis();
		sendBeacon();
	}
}

seq_t Layer3::sendNumbered( l3_address_t destination, seq_t seq, void* payload, uint8_t payloadLen ) {
	if(payloadLen > CONFIG_L3_PACKET_NUMBERED_MAX_LEN)
		return 0;

	//create random sequence
	if(seq == 0)
		seq = random(1, 0xffffffff);

	//create enclosing numbered payload
	packet_numbered_t pn;
	memset(&pn, 0, sizeof(pn));
	pn.seqNumber = seq;
	pn.payloadLen = payloadLen;
	memcpy(&pn.payload, payload, payloadLen);

	//create packet
	packet_t p;
	createPacketGeneric(&p, destination, PACKET_NUMBERED, (uint8_t*) &pn, sizeof(packet_numbered_t));

	//send.
	if(sendPacket(p)) {
		return seq;
	}

	return 0;
}

seq_t Layer3::sendNumbered(l3_address_t destination, void* payload, uint8_t payloadLen) {
	return sendNumbered(destination, 0, payload, payloadLen);
};

boolean Layer3::sendUnnumbered(l3_address_t destination, void* payload, uint8_t payloadLen) {
	if(payloadLen > CONFIG_L3_PACKET_UNNUMBERED_MAX_LEN)
		return 0;

	//create enclosing unnumbered payload
	packet_unnumbered_t pun;
	memcpy(&pun.payload, payload, payloadLen);

	//create packet
	packet_t p;
	createPacketGeneric(&p, destination, PACKET_UNNUMBERED, (uint8_t*) &pun, sizeof(packet_numbered_t));

	//send.
	return sendPacket(p);
}

boolean Layer3::sendBroadcast(void* payload, uint8_t payloadLen) {
	return sendUnnumbered(CONFIG_L3_ADDRESS_BROADCAST, payload, payloadLen);
}

EventCallbackInterface* Layer3::getCallbackInterface() {
	return (EventCallbackInterface*) &eventCallbackClass;
}


/***********************************************************************************************************/

void Layer3::callbackClass::doCallback(packet_application_numbered_cmd_t* appLayerPacket, l3_address_t address, seq_t seq) {
	#ifdef DEBUG_HANDLER_ENABLE
		Serial.print(millis());
		Serial.println(F(": L3::callback::doCallback()"));
	#endif

	this->parent->sendNumbered(address, seq, (byte*) appLayerPacket, CONFIG_L3_PACKET_NUMBERED_MAX_LEN);
}

void Layer3::callbackClass::fail(seq_t seq, l3_address_t remote) {
}
Ejemplo n.º 6
0
static void handleBeacon(struct Message* msg, struct ETHInterface* context)
{
    if (!context->beaconState) {
        // accepting beacons disabled.
        Log_debug(context->logger, "Dropping beacon because beaconing is disabled");
        return;
    }

    struct sockaddr_ll addr;
    Bits_memcpyConst(&addr, &context->addrBase, sizeof(struct sockaddr_ll));
    Message_pop(msg, addr.sll_addr, 8);
    if (msg->length < Headers_Beacon_SIZE) {
        // Oversize messages are ok because beacons may contain more information in the future.
        Log_debug(context->logger, "Dropping wrong size beacon, expected [%d] got [%d]",
                  Headers_Beacon_SIZE, msg->length);
        return;
    }
    struct Headers_Beacon* beacon = (struct Headers_Beacon*) msg->bytes;

    uint32_t theirVersion = Endian_bigEndianToHost32(beacon->version_be);
    if (!Version_isCompatible(theirVersion, Version_CURRENT_PROTOCOL)) {
        #ifdef Log_DEBUG
            uint8_t mac[18];
            AddrTools_printMac(mac, addr.sll_addr);
            Log_debug(context->logger, "Dropped beacon from [%s] which was version [%d] "
                      "our version is [%d] making them incompatable",
                      mac, theirVersion, Version_CURRENT_PROTOCOL);
        #endif
        return;
    }

    #ifdef Log_DEBUG
        uint8_t mac[18];
        AddrTools_printMac(mac, addr.sll_addr);
        Log_debug(context->logger, "Got beacon from [%s]", mac);
    #endif

    String passStr = { .bytes = (char*) beacon->password, .len = Headers_Beacon_PASSWORD_LEN };
    struct Interface* iface = MultiInterface_ifaceForKey(context->multiIface, addr.sll_addr);
    int ret = InterfaceController_registerPeer(context->ic,
                                               beacon->publicKey,
                                               &passStr,
                                               false,
                                               true,
                                               iface);
    if (ret != 0) {
        uint8_t mac[18];
        AddrTools_printMac(mac, addr.sll_addr);
        Log_info(context->logger, "Got beacon from [%s] and registerPeer returned [%d]", mac, ret);
    }
}

static void sendBeacon(void* vcontext)
{
    struct ETHInterface* context = Identity_cast((struct ETHInterface*) vcontext);
    if (context->beaconState != ETHInterface_beacon_ACCEPTING_AND_SENDING) {
        // beaconing disabled
        return;
    }

    struct {
        struct sockaddr_ll addr;
        struct Headers_Beacon beacon;
    } content;

    Bits_memcpyConst(&content.addr, &context->addrBase, sizeof(struct sockaddr_ll));
    Bits_memset(content.addr.sll_addr, 0xff, 6);
    InterfaceController_populateBeacon(context->ic, &content.beacon);

    struct Message m = {
        .bytes=(uint8_t*)content.addr.sll_addr,
        .padding=0,
        .length=sizeof(struct Headers_Beacon) + 8
    };

    int ret;
    if ((ret = sendMessage(&m, &context->generic)) != 0) {
        Log_info(context->logger, "Got error [%d] sending beacon [%s]", ret, strerror(errno));
    }
}

static void handleEvent(void* vcontext)
{
    struct ETHInterface* context = Identity_cast((struct ETHInterface*) vcontext);

    struct Message message =
        { .bytes = context->messageBuff + PADDING, .padding = PADDING, .length = MAX_PACKET_SIZE };

    struct sockaddr_ll addr;
    uint32_t addrLen = sizeof(struct sockaddr_ll);

    // Knock it out of alignment by 2 bytes so that it will be
    // aligned when the idAndPadding is shifted off.
    Message_shift(&message, 2);

    int rc = recvfrom(context->socket,
                      message.bytes,
                      message.length,
                      0,
                      (struct sockaddr*) &addr,
                      &addrLen);

    if (rc < 0) {
        Log_debug(context->logger, "Failed to receive eth frame");
        return;
    }

    //Assert_true(addrLen == SOCKADDR_LL_LEN);

    // Pop the first 2 bytes of the message containing the node id and amount of padding.
    uint16_t idAndPadding_be;
    Message_pop(&message, &idAndPadding_be, 2);

    const uint16_t idAndPadding = Endian_bigEndianToHost16(idAndPadding_be);
    message.length = rc - 2 - ((idAndPadding & 7) * 8);
    const uint16_t id = idAndPadding >> 3;
    Message_push(&message, &id, 2);
    Message_push(&message, addr.sll_addr, 6);

    if (addr.sll_pkttype == PACKET_BROADCAST) {
        handleBeacon(&message, context);
        return;
    }

    /* Cut down on the noise
    uint8_t buff[sizeof(addr) * 2 + 1] = {0};
    Hex_encode(buff, sizeof(buff), (uint8_t*)&addr, sizeof(addr));
    Log_debug(context->logger, "Got ethernet frame from [%s]", buff);
    */

    context->generic.receiveMessage(&message, &context->generic);
}

int ETHInterface_beginConnection(const char* macAddress,
                                 uint8_t cryptoKey[32],
                                 String* password,
                                 struct ETHInterface* ethIf)
{
    Identity_check(ethIf);
    struct sockaddr_ll addr;
    Bits_memcpyConst(&addr, &ethIf->addrBase, sizeof(struct sockaddr_ll));
    if (AddrTools_parseMac(addr.sll_addr, (const uint8_t*)macAddress)) {
        return ETHInterface_beginConnection_BAD_MAC;
    }

    struct Interface* iface = MultiInterface_ifaceForKey(ethIf->multiIface, &addr);
    int ret = InterfaceController_registerPeer(ethIf->ic, cryptoKey, password, false, false, iface);
    if (ret) {
        Allocator_free(iface->allocator);
        switch(ret) {
            case InterfaceController_registerPeer_BAD_KEY:
                return ETHInterface_beginConnection_BAD_KEY;

            case InterfaceController_registerPeer_OUT_OF_SPACE:
                return ETHInterface_beginConnection_OUT_OF_SPACE;

            default:
                return ETHInterface_beginConnection_UNKNOWN_ERROR;
        }
    }
    return 0;
}

int ETHInterface_beacon(struct ETHInterface* ethIf, int* state)
{
    Identity_check(ethIf);
    if (state) {
        ethIf->beaconState = *state;
        // Send out a beacon right away so we don't have to wait.
        if (ethIf->beaconState == ETHInterface_beacon_ACCEPTING_AND_SENDING) {
            sendBeacon(ethIf);
        }
    }
    return ethIf->beaconState;
}

struct ETHInterface* ETHInterface_new(struct EventBase* base,
                                      const char* bindDevice,
                                      struct Allocator* allocator,
                                      struct Except* exHandler,
                                      struct Log* logger,
                                      struct InterfaceController* ic)
{
    struct ETHInterface* context = Allocator_clone(allocator, (&(struct ETHInterface) {
        .generic = {
            .sendMessage = sendMessage,
            .allocator = allocator
        },
        .logger = logger,
        .ic = ic,
        .id = getpid()
    }));