internal void HandleMessage(FunctionCodeSecondary fcs, bool acd, bool dfc, int addr, byte[] msg, int userDataStart, int userDataLength) { PrimaryLinkLayerState newState = primaryState; if (dfc) { //stop sending ASDUs; only send Status of link requests dontSendMessages = true; switch (primaryState) { case PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK: case PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK: newState = PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK; break; case PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM: //TODO message must be handled and switched to BUSY state later! case PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY: newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY; break; } SetState(LinkLayerState.BUSY); primaryState = newState; return; } else { // unblock transmission of application layer messages dontSendMessages = false; } switch (fcs) { case FunctionCodeSecondary.ACK: DebugLog("[SLAVE " + address + "] PLL - received ACK"); if (primaryState == PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK) { newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE; SetState(LinkLayerState.AVAILABLE); } else if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM) { if (sendLinkLayerTestFunction) { sendLinkLayerTestFunction = false; } SetState(LinkLayerState.AVAILABLE); newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE; } else if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND) { /* single char ACK is interpreted as RESP NO DATA */ requestClass1Data = false; requestClass2Data = false; SetState(LinkLayerState.AVAILABLE); newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE; } waitingForResponse = false; break; case FunctionCodeSecondary.NACK: DebugLog("[SLAVE " + address + "] PLL - received NACK"); if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM) { SetState(LinkLayerState.BUSY); newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY; } waitingForResponse = false; break; case FunctionCodeSecondary.STATUS_OF_LINK_OR_ACCESS_DEMAND: DebugLog("[SLAVE " + address + "] PLL - received STATUS OF LINK"); if (primaryState == PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK) { DebugLog("[SLAVE " + address + "] PLL - SEND RESET REMOTE LINK"); linkLayer.SendFixedFramePrimary(FunctionCodePrimary.RESET_REMOTE_LINK, address, false, false); nextFcb = true; lastSendTime = SystemUtils.currentTimeMillis(); waitingForResponse = true; newState = PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK; SetState(LinkLayerState.BUSY); } else { /* illegal message */ newState = PrimaryLinkLayerState.IDLE; SetState(LinkLayerState.ERROR); waitingForResponse = false; } break; case FunctionCodeSecondary.RESP_USER_DATA: DebugLog("[SLAVE " + address + "] PLL - received USER DATA"); if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND) { linkLayerUnbalanced.callbacks.UserData(address, msg, userDataStart, userDataLength); requestClass1Data = false; requestClass2Data = false; newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE; SetState(LinkLayerState.AVAILABLE); } else { /* illegal message */ newState = PrimaryLinkLayerState.IDLE; SetState(LinkLayerState.ERROR); } waitingForResponse = false; break; case FunctionCodeSecondary.RESP_NACK_NO_DATA: DebugLog("[SLAVE " + address + "] PLL - received RESP NO DATA"); if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND) { newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE; requestClass1Data = false; requestClass2Data = false; SetState(LinkLayerState.AVAILABLE); } else { /* illegal message */ newState = PrimaryLinkLayerState.IDLE; SetState(LinkLayerState.ERROR); } waitingForResponse = false; break; case FunctionCodeSecondary.LINK_SERVICE_NOT_FUNCTIONING: case FunctionCodeSecondary.LINK_SERVICE_NOT_IMPLEMENTED: DebugLog("[SLAVE " + address + "] PLL - link layer service not functioning/not implemented in secondary station "); if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM) { newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE; SetState(LinkLayerState.AVAILABLE); } waitingForResponse = false; break; default: DebugLog("[SLAVE " + address + "] UNEXPECTED SECONDARY LINK LAYER MESSAGE"); break; } if (acd) { if (linkLayerUnbalanced.callbacks != null) { linkLayerUnbalanced.callbacks.AccessDemand(address); } } DebugLog("[SLAVE " + address + "] PLL RECV - old state: " + primaryState.ToString() + " new state: " + newState.ToString()); primaryState = newState; }
public override void HandleMessage(FunctionCodeSecondary fcs, bool dir, bool dfc, int address, byte[] msg, int userDataStart, int userDataLength) { PrimaryLinkLayerState newState = primaryState; if (dfc) { //TODO stop sending ASDUs; only send Status of link requests switch (primaryState) { case PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK: case PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK: newState = PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK; break; case PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM: //TODO message must be handled and switched to BUSY state later! case PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY: newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY; break; } SetNewState(LinkLayerState.BUSY); primaryState = newState; return; } switch (fcs) { case FunctionCodeSecondary.ACK: //TODO what to do if we are not waiting for a response? DebugLog("PLL - received ACK"); if (primaryState == PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK) { newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE; SetNewState(LinkLayerState.AVAILABLE); } else if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM) { if (sendLinkLayerTestFunction) { sendLinkLayerTestFunction = false; } newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE; SetNewState(LinkLayerState.AVAILABLE); } waitingForResponse = false; break; case FunctionCodeSecondary.NACK: DebugLog("PLL - received NACK"); if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM) { newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY; SetNewState(LinkLayerState.BUSY); } break; case FunctionCodeSecondary.RESP_USER_DATA: newState = PrimaryLinkLayerState.IDLE; SetNewState(LinkLayerState.ERROR); break; case FunctionCodeSecondary.RESP_NACK_NO_DATA: newState = PrimaryLinkLayerState.IDLE; SetNewState(LinkLayerState.ERROR); break; case FunctionCodeSecondary.STATUS_OF_LINK_OR_ACCESS_DEMAND: DebugLog("PLL - received STATUS OF LINK"); if (primaryState == PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK) { DebugLog("PLL - SEND RESET REMOTE LINK to address " + linkLayerAddressOtherStation); linkLayer.SendFixedFramePrimary(FunctionCodePrimary.RESET_REMOTE_LINK, linkLayerAddressOtherStation, false, false); lastSendTime = SystemUtils.currentTimeMillis(); waitingForResponse = true; newState = PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK; SetNewState(LinkLayerState.BUSY); } else /* illegal message */ { newState = PrimaryLinkLayerState.IDLE; SetNewState(LinkLayerState.ERROR); } break; case FunctionCodeSecondary.LINK_SERVICE_NOT_FUNCTIONING: case FunctionCodeSecondary.LINK_SERVICE_NOT_IMPLEMENTED: DebugLog("PLL - link layer service not functioning/not implemented in secondary station"); if (sendLinkLayerTestFunction) { sendLinkLayerTestFunction = false; } if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM) { newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE; SetNewState(LinkLayerState.AVAILABLE); } break; default: DebugLog("UNEXPECTED SECONDARY LINK LAYER MESSAGE"); break; } DebugLog("PLL RECV - old state: " + primaryState.ToString() + " new state: " + newState.ToString()); primaryState = newState; }