msach@0: msach@0: /* msach@0: * For a detailed description see header file. msach@0: */ msach@0: msach@0: #include "LossyCom.h" msach@0: msach@0: #include "VMS_Implementations/VMS_impl/vmalloc.h" msach@0: msach@0: /* msach@0: * Initializes the central exchange structure. msach@0: * Allocates memory to fit the number of endpoints. msach@0: * Returns NULL if an error occurs. msach@0: */ msach@0: lossyCom__exchange_t* lossyCom__initialize(uint16_t numEndpoints) msach@0: { msach@0: lossyCom__exchange_t* exchange; msach@0: msach@0: exchange = VMS_WL__malloc(sizeof(lossyCom__exchange_t)); msach@0: if(exchange == NULL) msach@0: return NULL; msach@0: msach@0: exchange->triggerCounter = 0; msach@0: exchange->numEndpoints = numEndpoints; msach@0: exchange->outboxArray = VMS_WL__malloc(sizeof(lossyCom__msg_t)*numEndpoints); msach@0: if(exchange->outboxArray == NULL){ msach@0: VMS_WL__free(exchange); msach@0: return NULL; msach@0: } msach@0: msach@0: return exchange; msach@0: } msach@0: msach@1: /* msach@1: * Connects the local endpoint to the central exchange structure. msach@1: * This registers a message handler that handles all the incomming messages. msach@1: * Also an endpointID is set this ID has to be between 0 and total number of msach@1: * endpoints-1 and the number has to be unique. msach@1: */ msach@0: void lossyCom__initialize_endpoint(lossyCom__endpoint_t* localEndpoint, msach@0: lossyCom__exchange_t* centralExchange, msach@0: lossyCom__endpointID_t endpointID, msach@1: lossyCom__msgHandler msgHandler, msach@1: void* msgHandlerData) msach@0: { msach@0: localEndpoint->localTriggerCopy = 0; msach@0: localEndpoint->endpointID = endpointID; msach@1: localEndpoint->centralExchange = centralExchange; msach@1: localEndpoint->msgHandler = msgHandler; msach@1: localEndpoint->msgHandlerData = msgHandlerData; msach@0: } msach@0: msach@1: /* msach@1: * This broadcasts a message to all connected receivers msach@1: */ msach@0: void inline lossyCom__broadcastMsg(lossyCom__endpoint_t* localEndpoint, msach@0: lossyCom__msgBody_t msg) msach@0: { msach@0: lossyCom__sendMsg(localEndpoint, msach@0: BROADCAST_ID, msach@0: msg); msach@0: } msach@0: msach@1: /* msach@1: * This sends a message another endpoint. Again it is not guaranteed that the msach@1: * message is received. But in most cases it will. msach@1: */ msach@0: void inline lossyCom__sendMsg(lossyCom__endpoint_t* localEndpoint, msach@0: lossyCom__endpointID_t receiverEndpointID, msach@0: lossyCom__msgBody_t msg) msach@0: { msach@0: lossyCom__msg_t msgDraft; msach@0: uint16_t triggerCopy; msach@0: msach@1: //build message msach@0: msgDraft = (0 | msg); msach@0: msgDraft |= ((lossyCom__msg_t)receiverEndpointID << ENDPOINT_ID_SHIFT); msach@0: msach@1: triggerCopy = localEndpoint->centralExchange->triggerCounter +1; msach@0: msgDraft |= ((lossyCom__msg_t)triggerCopy << TRIGGER_SHIFT); msach@0: msach@0: //write msg to central exchange msach@1: localEndpoint->centralExchange->outboxArray[localEndpoint->endpointID] = msach@0: msgDraft; msach@0: msach@1: localEndpoint->centralExchange->triggerCounter = triggerCopy; msach@0: } msach@0: msach@0: void inline lossyCom__receiveMsg(lossyCom__endpoint_t* localEndpoint) msach@0: { msach@1: uint16_t currentTriggerCopy; msach@0: lossyCom__endpointID_t senderEndpointID; msach@0: lossyCom__msg_t msgCopy; msach@0: uint16_t msgTrigger; msach@0: lossyCom__msgBody_t msgBody; msach@0: msach@0: senderEndpointID = 0; msach@1: currentTriggerCopy = localEndpoint->centralExchange->triggerCounter; msach@1: msach@0: //new message arrived if trigger counter is higher than the last time read msach@1: while(senderEndpointID < localEndpoint->centralExchange->numEndpoints) msach@0: { msach@0: if(senderEndpointID != localEndpoint->endpointID) msach@0: { msach@1: msgCopy = localEndpoint->centralExchange->outboxArray[senderEndpointID]; msach@0: msgTrigger = 0xFFFF & (msgCopy >> TRIGGER_SHIFT); msach@1: // check if the message is new (msg trigger > archived trigger) msach@1: // and already valid (msgTrigger <= currentTriggerCopy) msach@0: if(msgTrigger > localEndpoint->localTriggerCopy && msach@1: msgTrigger <= currentTriggerCopy) msach@0: { msach@1: //let the message handler parse the message msach@0: msgBody = 0xFFFFFFFF & msgCopy; msach@1: (*(localEndpoint->msgHandler))(senderEndpointID, msach@1: msgBody, msach@1: localEndpoint->msgHandlerData); msach@0: } msach@0: } msach@0: senderEndpointID++; msach@0: } msach@0: //save last parsed msg msach@1: localEndpoint->localTriggerCopy = currentTriggerCopy; msach@0: }