blob: c5f6a63b489b974bf6440818cd286ace41c10b05 [file] [log] [blame]
/**
* @author generated by eTrice
*
* Source File of ActorClass ATcpServer
*
*/
#include "ATcpServer.h"
#include "modelbase/etActor.h"
#include "debugging/etLogger.h"
#include "debugging/etMSCLogger.h"
#include "etUnit/etUnit.h"
#include "base/etMemory.h"
#include "etrice/api/tcp/PTcpControl.h"
#include "etrice/api/tcp/PTcpPayload.h"
#include "ATcpServer_Utils.h"
/*--------------------- begin user code ---------------------*/
static int8* bufferProvider(void* slf, int* size) {
ATcpServer* self = (ATcpServer*) slf;
*size = DTcpPayload_getMaxLength(&payloadRecvBuffer);
return payloadRecvBuffer.data;
}
static int socketReceiver(void* slf, int channel, int size, const int8* data) {
ATcpServer* self = (ATcpServer*) slf;
DTcpPayload_setData(&payloadRecvBuffer, data, size);
payloadPort_dataPackage(&payloadRecvBuffer);
return ETSOCKET_OK;
}
/*--------------------- end user code ---------------------*/
/* interface item IDs */
enum interface_items {
IFITEM_controlPort = 1,
IFITEM_payloadPort = 2
};
/* state IDs */
enum state_ids {
NO_STATE = 0,
STATE_TOP = 1,
STATE_connected = 2,
STATE_unconnected = 3,
STATE_initError = 4,
STATE_MAX = 5
};
/* transition chains */
enum ChainIDs {
CHAIN_TRANS_INITIAL_TO__cp0 = 1,
CHAIN_TRANS_tr5_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr5 = 2,
CHAIN_TRANS_tr6_FROM_connected_TO_unconnected_BY_disconnectcontrolPort = 3,
CHAIN_TRANS_tr7_FROM_unconnected_TO_cp1_BY_connectcontrolPort = 4,
CHAIN_TRANS_tr2_FROM_initError_TO_initError_BY_connectcontrolPort_tr2 = 5
};
/* triggers */
enum triggers {
POLLING = 0,
TRIG_controlPort__connect = IFITEM_controlPort + EVT_SHIFT*PTcpControl_IN_connect,
TRIG_controlPort__disconnect = IFITEM_controlPort + EVT_SHIFT*PTcpControl_IN_disconnect,
TRIG_payloadPort__dataPackage = IFITEM_payloadPort + EVT_SHIFT*PTcpPayload_IN_dataPackage
};
/* state names */
static const char* stateStrings[] = {"<no state>","<top>","connected",
"unconnected",
"initError"
};
static void setState(ATcpServer* self, etInt16 new_state) {
self->state = new_state;
ET_MSC_LOGGER_CHANGE_STATE(self->constData->instName, stateStrings[new_state]);
}
static etInt16 getState(ATcpServer* self) {
return self->state;
}
/* Entry and Exit Codes */
static void entry_initError(ATcpServer* self) {
controlPort_error();
}
/* Action Codes */
static void action_TRANS_tr5_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr5(ATcpServer* self, const InterfaceItemBase* ifitem, DTcpPayload* transitionData) {
/* send payload to connection */
setErrorCode(etWriteServerSocket(server, transitionData->connectionId, transitionData->length, transitionData->data));
if(hasError())
controlPort_error();
}
static void action_TRANS_tr6_FROM_connected_TO_unconnected_BY_disconnectcontrolPort(ATcpServer* self, const InterfaceItemBase* ifitem) {
/* close accept thread */
etCloseAllServerSockets(server);
etStopSocketServer(server);
controlPort_disconnected();
}
static void action_TRANS_tr7_FROM_unconnected_TO_cp1_BY_connectcontrolPort(ATcpServer* self, const InterfaceItemBase* ifitem, DTcpControl* transitionData) {
/* start accept thread */
setErrorCode(etStartListening(server, transitionData->TcpPort));
}
static void action_TRANS_tr4_FROM_cp1_TO_connected(ATcpServer* self, const InterfaceItemBase* ifitem, DTcpControl* transitionData) {
controlPort_connected();
}
static void action_TRANS_tr8_FROM_cp1_TO_unconnected_COND_tr8(ATcpServer* self, const InterfaceItemBase* ifitem, DTcpControl* transitionData) {
controlPort_error();
}
/* State Switch Methods */
/**
* calls exit codes while exiting from the current state to one of its
* parent states while remembering the history
* @param current__et - the current state
* @param to - the final parent state
*/
static void exitTo(ATcpServer* self, etInt16 current__et, etInt16 to) {
while (current__et!=to) {
switch (current__et) {
case STATE_connected:
self->history[STATE_TOP] = STATE_connected;
current__et = STATE_TOP;
break;
case STATE_initError:
self->history[STATE_TOP] = STATE_initError;
current__et = STATE_TOP;
break;
case STATE_unconnected:
self->history[STATE_TOP] = STATE_unconnected;
current__et = STATE_TOP;
break;
default:
/* should not occur */
break;
}
}
}
/**
* calls action, entry and exit codes along a transition chain. The generic data are cast to typed data
* matching the trigger of this chain. The ID of the final state is returned
* @param chain__et - the chain ID
* @param generic_data__et - the generic data pointer
* @return the +/- ID of the final state either with a positive sign, that indicates to execute the state's entry code, or a negative sign vice versa
*/
static etInt16 executeTransitionChain(ATcpServer* self, int chain__et, const InterfaceItemBase* ifitem, void* generic_data__et) {
switch (chain__et) {
case CHAIN_TRANS_INITIAL_TO__cp0:
{
if (hasError()) {
return STATE_initError;}
else {
return STATE_unconnected;}
}
case CHAIN_TRANS_tr2_FROM_initError_TO_initError_BY_connectcontrolPort_tr2:
{
DTcpControl* transitionData = ((DTcpControl*) generic_data__et);
return STATE_initError;
}
case CHAIN_TRANS_tr5_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr5:
{
DTcpPayload* transitionData = ((DTcpPayload*) generic_data__et);
action_TRANS_tr5_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr5(self, ifitem, transitionData);
return STATE_connected;
}
case CHAIN_TRANS_tr6_FROM_connected_TO_unconnected_BY_disconnectcontrolPort:
{
action_TRANS_tr6_FROM_connected_TO_unconnected_BY_disconnectcontrolPort(self, ifitem);
return STATE_unconnected;
}
case CHAIN_TRANS_tr7_FROM_unconnected_TO_cp1_BY_connectcontrolPort:
{
DTcpControl* transitionData = ((DTcpControl*) generic_data__et);
action_TRANS_tr7_FROM_unconnected_TO_cp1_BY_connectcontrolPort(self, ifitem, transitionData);
if (hasError()) {
action_TRANS_tr8_FROM_cp1_TO_unconnected_COND_tr8(self, ifitem, transitionData);
return STATE_unconnected;}
else {
action_TRANS_tr4_FROM_cp1_TO_connected(self, ifitem, transitionData);
return STATE_connected;}
}
default:
/* should not occur */
break;
}
return NO_STATE;
}
/**
* calls entry codes while entering a state's history. The ID of the final leaf state is returned
* @param state__et - the state which is entered
* @return - the ID of the final leaf state
*/
static etInt16 enterHistory(ATcpServer* self, etInt16 state__et) {
etBool skip_entry__et = ET_FALSE;
if (state__et >= STATE_MAX) {
state__et = (etInt16) (state__et - STATE_MAX);
skip_entry__et = ET_TRUE;
}
while (ET_TRUE) {
switch (state__et) {
case STATE_connected:
/* in leaf state: return state id */
return STATE_connected;
case STATE_initError:
if (!(skip_entry__et)) entry_initError(self);
/* in leaf state: return state id */
return STATE_initError;
case STATE_unconnected:
/* in leaf state: return state id */
return STATE_unconnected;
case STATE_TOP:
state__et = self->history[STATE_TOP];
break;
default:
/* should not occur */
break;
}
skip_entry__et = ET_FALSE;
}
/* return NO_STATE; // required by CDT but detected as unreachable by JDT because of while (true) */
}
static void ATcpServer_executeInitTransition(ATcpServer* self) {
int chain__et = CHAIN_TRANS_INITIAL_TO__cp0;
etInt16 next__et = executeTransitionChain(self, chain__et, NULL, NULL);
next__et = enterHistory(self, next__et);
setState(self, next__et);
}
/* receiveEvent contains the main implementation of the FSM */
static void ATcpServer_receiveEventInternal(ATcpServer* self, InterfaceItemBase* ifitem, int localId, int evt, void* generic_data__et) {
int trigger__et = localId + EVT_SHIFT*evt;
int chain__et = NOT_CAUGHT;
etInt16 catching_state__et = NO_STATE;
((void)trigger__et); /* avoids unused warning */
if (!handleSystemEvent(ifitem, evt, generic_data__et)) {
switch (getState(self)) {
case STATE_connected:
switch(trigger__et) {
case TRIG_controlPort__disconnect:
{
chain__et = CHAIN_TRANS_tr6_FROM_connected_TO_unconnected_BY_disconnectcontrolPort;
catching_state__et = STATE_TOP;
}
break;
case TRIG_payloadPort__dataPackage:
{
chain__et = CHAIN_TRANS_tr5_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr5;
catching_state__et = STATE_TOP;
}
break;
default:
/* should not occur */
break;
}
break;
case STATE_initError:
switch(trigger__et) {
case TRIG_controlPort__connect:
{
chain__et = CHAIN_TRANS_tr2_FROM_initError_TO_initError_BY_connectcontrolPort_tr2;
catching_state__et = STATE_TOP;
}
break;
default:
/* should not occur */
break;
}
break;
case STATE_unconnected:
switch(trigger__et) {
case TRIG_controlPort__connect:
{
chain__et = CHAIN_TRANS_tr7_FROM_unconnected_TO_cp1_BY_connectcontrolPort;
catching_state__et = STATE_TOP;
}
break;
default:
/* should not occur */
break;
}
break;
default:
/* should not occur */
break;
}
}
if (chain__et != NOT_CAUGHT) {
exitTo(self, getState(self), catching_state__et);
{
etInt16 next__et = executeTransitionChain(self, chain__et, ifitem, generic_data__et);
next__et = enterHistory(self, next__et);
setState(self, next__et);
}
}
}
static void ATcpServer_receiveEvent(ATcpServer* self, InterfaceItemBase* ifitem, int evt, void* generic_data__et) {
int localId = (ifitem==NULL)? 0 : ifitem->localId;
ATcpServer_receiveEventInternal(self, ifitem, localId, evt, generic_data__et);
}
void ATcpServer_init(ATcpServer* self){
ET_MSC_LOGGER_SYNC_ENTRY("ATcpServer", "init")
self->state = STATE_TOP;
{
int i;
for (i=0; i<ATCPSERVER_HISTORY_SIZE; ++i)
self->history[i] = NO_STATE;
}
ATcpServer_executeInitTransition(self);
ET_MSC_LOGGER_SYNC_EXIT
}
void ATcpServer_receiveMessage(void* self, const void* ifitem, const etMessage* msg){
ET_MSC_LOGGER_SYNC_ENTRY("ATcpServer", "_receiveMessage")
ATcpServer_receiveEvent((ATcpServer*) self, (etPort*)ifitem, msg->evtID, (void*)(((char*)msg)+MEM_CEIL(sizeof(etMessage))));
ET_MSC_LOGGER_SYNC_EXIT
}
/*--------------------- user constructor/destructor ---------------------*/
void ATcpServer_ctor(ATcpServer* self){
/* user defined constructor body */
setErrorCode(etInitSockets());
server = etCreateSocketServerData();
server->receiver = socketReceiver;
server->bufferProvider = bufferProvider;
server->userData = self;
}
void ATcpServer_dtor(ATcpServer* self){
/* user defined destructor body */
etCleanupSockets();
etFreeSocketServerData(server);
}
/*--------------------- operations ---------------------*/
bool ATcpServer_hasError(ATcpServer* self) {
return lastError != ETSOCKET_OK;
}
void ATcpServer_setErrorCode(ATcpServer* self, int32 value) {
lastError = value;
}