/*=============================================================================| | PROJECT SNAP7 1.3.0 | |==============================================================================| | Copyright (C) 2013, 2015 Davide Nardella | | All rights reserved. | |==============================================================================| | SNAP7 is free software: you can redistribute it and/or modify | | it under the terms of the Lesser GNU General Public License as published by | | the Free Software Foundation, either version 3 of the License, or | | (at your option) any later version. | | | | It means that you can distribute your commercial software linked with | | SNAP7 without the requirement to distribute the source code of your | | application and without the requirement that your application be itself | | distributed under LGPL. | | | | SNAP7 is distributed in the hope that it will be useful, | | but WITHOUT ANY WARRANTY; without even the implied warranty of | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | Lesser GNU General Public License for more details. | | | | You should have received a copy of the GNU General Public License and a | | copy of Lesser GNU General Public License along with Snap7. | | If not, see http://www.gnu.org/licenses/ | |=============================================================================*/ #ifndef s7_server_h #define s7_server_h //--------------------------------------------------------------------------- #include "snap_tcpsrvr.h" #include "s7_types.h" #include "s7_isotcp.h" //--------------------------------------------------------------------------- // Maximum number of DB, change it to increase/decrease the limit. // The DB table size is 12*MaxDB bytes #define MaxDB 2048 // Like a S7 318 #define MinPduSize 240 #define CPU315PduSize 240 //--------------------------------------------------------------------------- // Server Interface errors const longword errSrvDBNullPointer = 0x00200000; // Pssed null as PData const longword errSrvAreaAlreadyExists = 0x00300000; // Area Re-registration const longword errSrvUnknownArea = 0x00400000; // Unknown area const longword errSrvInvalidParams = 0x00500000; // Invalid param(s) supplied const longword errSrvTooManyDB = 0x00600000; // Cannot register DB const longword errSrvInvalidParamNumber = 0x00700000; // Invalid param (srv_get/set_param) const longword errSrvCannotChangeParam = 0x00800000; // Cannot change because running // Server Area ID (use with Register/unregister - Lock/unlock Area) const int srvAreaPE = 0; const int srvAreaPA = 1; const int srvAreaMK = 2; const int srvAreaCT = 3; const int srvAreaTM = 4; const int srvAreaDB = 5; typedef struct{ word Number; // Number (only for DB) word Size; // Area size (in bytes) pbyte PData; // Pointer to area PSnapCriticalSection cs; }TS7Area, *PS7Area; //------------------------------------------------------------------------------ // ISOTCP WORKER CLASS //------------------------------------------------------------------------------ class TIsoTcpWorker : public TIsoTcpSocket { protected: virtual bool IsoPerformCommand(int &Size); virtual bool ExecuteSend(); virtual bool ExecuteRecv(); public: TIsoTcpWorker(){}; ~TIsoTcpWorker(){}; // Worker execution bool Execute(); }; //------------------------------------------------------------------------------ // S7 WORKER CLASS //------------------------------------------------------------------------------ // SZL frame typedef struct{ TS7Answer17 Answer; PReqFunReadSZLFirst ReqParams; PS7ReqSZLData ReqData; PS7ResParams7 ResParams; pbyte ResData; int ID; int Index; bool SZLDone; }TSZL; // Current Event Info typedef struct{ word EvRetCode; word EvArea; word EvIndex; word EvStart; word EvSize; }TEv; // Current Block info typedef struct{ PReqFunGetBlockInfo ReqParams; PResFunGetBlockInfo ResParams; TS7Answer17 Answer; word evError; word DataLength; }TCB; class TSnap7Server; // forward declaration class TS7Worker : public TIsoTcpWorker { private: PS7ReqHeader PDUH_in; int DBCnt; byte LastBlk; TSZL SZL; byte BCD(word Value); // Checks the consistence of the incoming PDU bool CheckPDU_in(int PayloadSize); void FillTime(PS7Time PTime); protected: int DataSizeByte(int WordLength); bool ExecuteRecv(); void DoEvent(longword Code, word RetCode, word Param1, word Param2, word Param3, word Param4); void DoReadEvent(longword Code, word RetCode, word Param1, word Param2, word Param3, word Param4); void FragmentSkipped(int Size); // Entry parse bool IsoPerformCommand(int &Size); // First stage parse bool PerformPDUAck(int &Size); bool PerformPDURequest(int &Size); bool PerformPDUUsrData(int &Size); // Second stage parse : PDU Request PS7Area GetArea(byte S7Code, word index); // Group Read Area bool PerformFunctionRead(); // Subfunctions Read Data word ReadArea(PResFunReadItem ResItemData, PReqFunReadItem ReqItemPar, int &PDURemainder,TEv &EV); word RA_NotFound(PResFunReadItem ResItem, TEv &EV); word RA_OutOfRange(PResFunReadItem ResItem, TEv &EV); word RA_SizeOverPDU(PResFunReadItem ResItem, TEv &EV); // Group Write Area bool PerformFunctionWrite(); // Subfunctions Write Data byte WriteArea(PReqFunWriteDataItem ReqItemData, PReqFunWriteItem ReqItemPar, TEv &EV); byte WA_NotFound(TEv &EV); byte WA_InvalidTransportSize(TEv &EV); byte WA_OutOfRange(TEv &EV); byte WA_DataSizeMismatch(TEv &EV); // Negotiate PDU Length bool PerformFunctionNegotiate(); // Control bool PerformFunctionControl(byte PduFun); // Up/Download bool PerformFunctionUpload(); bool PerformFunctionDownload(); // Second stage parse : PDU User data bool PerformGroupProgrammer(); bool PerformGroupCyclicData(); bool PerformGroupSecurity(); // Group Block(s) Info bool PerformGroupBlockInfo(); // Subfunctions Block info void BLK_ListAll(TCB &CB); void BLK_ListBoT(byte BlockType, bool Start, TCB &CB); void BLK_NoResource_ListBoT(PDataFunGetBot Data, TCB &CB); void BLK_GetBlkInfo(TCB &CB); void BLK_NoResource_GetBlkInfo(PResDataBlockInfo Data, TCB &CB); void BLK_GetBlockNum_GetBlkInfo(int &BlkNum, PReqDataBlockInfo ReqData); void BLK_DoBlockInfo_GetBlkInfo(PS7Area DB, PResDataBlockInfo Data, TCB &CB); // Clock Group bool PerformGetClock(); bool PerformSetClock(); // SZL Group bool PerformGroupSZL(); // Subfunctions (called by PerformGroupSZL) void SZLNotAvailable(); void SZLSystemState(); void SZLData(void *P, int len); void SZL_ID424(); void SZL_ID131_IDX003(); public: TSnap7Server *FServer; int FPDULength; TS7Worker(); ~TS7Worker(){}; }; typedef TS7Worker *PS7Worker; //------------------------------------------------------------------------------ // S7 SERVER CLASS //------------------------------------------------------------------------------ extern "C" { typedef int (S7API *pfn_RWAreaCallBack)(void *usrPtr, int Sender, int Operation, PS7Tag PTag, void *pUsrData); } const int OperationRead = 0; const int OperationWrite = 1; class TSnap7Server : public TCustomMsgServer { private: // Read Callback related pfn_SrvCallBack OnReadEvent; pfn_RWAreaCallBack OnRWArea; // Critical section to lock Read/Write Hook Area PSnapCriticalSection CSRWHook; void *FReadUsrPtr; void *FRWAreaUsrPtr; void DisposeAll(); int FindFirstFreeDB(); int IndexOfDB(word DBNumber); protected: int DBCount; int DBLimit; PS7Area DB[MaxDB]; // DB PS7Area HA[5]; // MK,PE,PA,TM,CT PS7Area FindDB(word DBNumber); PWorkerSocket CreateWorkerSocket(socket_t Sock); bool ResourceLess; word ForcePDU; int RegisterDB(word Number, void *pUsrData, word Size); int RegisterSys(int AreaCode, void *pUsrData, word Size); int UnregisterDB(word DBNumber); int UnregisterSys(int AreaCode); // The Read event void DoReadEvent(int Sender, longword Code, word RetCode, word Param1, word Param2, word Param3, word Param4); bool DoReadArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData); bool DoWriteArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData); public: int WorkInterval; byte CpuStatus; TSnap7Server(); ~TSnap7Server(); int StartTo(const char *Address); int GetParam(int ParamNumber, void *pValue); int SetParam(int ParamNumber, void *pValue); int RegisterArea(int AreaCode, word Index, void *pUsrData, word Size); int UnregisterArea(int AreaCode, word Index); int LockArea(int AreaCode, word DBNumber); int UnlockArea(int AreaCode, word DBNumber); // Sets Event callback int SetReadEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr); int SetRWAreaCallBack(pfn_RWAreaCallBack PCallBack, void *UsrPtr); friend class TS7Worker; }; typedef TSnap7Server *PSnap7Server; #endif // s7_server_h