262 lines
9.7 KiB
C++
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
|
|
|