void Global::launchBeacon() { sendBeacon(); if(mBeaconTimer) { mBeaconTimer->setSingleShot(false); connect(mBeaconTimer, SIGNAL(timeout()), this, SLOT(sendBeacon()) ); mBeaconTimer->start(5000); } }
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; }
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); }
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 }
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*) ¤tItem->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(¤tItem->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) { }
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, ðIf->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() }));