1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
|
/*=============================================================================|
| 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
|