2024-03-19 17:45:12 +08:00

262 lines
9.7 KiB
C++

/*=============================================================================|
| 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