1 /*=============================================================================|
2 |  PROJECT SNAP7                                                         1.3.0 |
3 |==============================================================================|
4 |  Copyright (C) 2013, 2015 Davide Nardella                                    |
5 |  All rights reserved.                                                        |
6 |==============================================================================|
7 |  SNAP7 is free software: you can redistribute it and/or modify               |
8 |  it under the terms of the Lesser GNU General Public License as published by |
9 |  the Free Software Foundation, either version 3 of the License, or           |
10 |  (at your option) any later version.                                         |
11 |                                                                              |
12 |  It means that you can distribute your commercial software linked with       |
13 |  SNAP7 without the requirement to distribute the source code of your         |
14 |  application and without the requirement that your application be itself     |
15 |  distributed under LGPL.                                                     |
16 |                                                                              |
17 |  SNAP7 is distributed in the hope that it will be useful,                    |
18 |  but WITHOUT ANY WARRANTY; without even the implied warranty of              |
19 |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
20 |  Lesser GNU General Public License for more details.                         |
21 |                                                                              |
22 |  You should have received a copy of the GNU General Public License and a     |
23 |  copy of Lesser GNU General Public License along with Snap7.                 |
24 |  If not, see  http://www.gnu.org/licenses/                                   |
25 |=============================================================================*/
26 #ifndef s7_server_h
27 #define s7_server_h
28 //---------------------------------------------------------------------------
29 #include "snap_tcpsrvr.h"
30 #include "s7_types.h"
31 #include "s7_isotcp.h"
32 //---------------------------------------------------------------------------
33 
34 // Maximum number of DB, change it to increase/decrease the limit.
35 // The DB table size is 12*MaxDB bytes
36 
37 #define MaxDB 2048    // Like a S7 318
38 #define MinPduSize 240
39 #define CPU315PduSize 240
40 //---------------------------------------------------------------------------
41 // Server Interface errors
42 const longword errSrvDBNullPointer      = 0x00200000; // Pssed null as PData
43 const longword errSrvAreaAlreadyExists  = 0x00300000; // Area Re-registration
44 const longword errSrvUnknownArea        = 0x00400000; // Unknown area
45 const longword errSrvInvalidParams      = 0x00500000; // Invalid param(s) supplied
46 const longword errSrvTooManyDB          = 0x00600000; // Cannot register DB
47 const longword errSrvInvalidParamNumber = 0x00700000; // Invalid param (srv_get/set_param)
48 const longword errSrvCannotChangeParam  = 0x00800000; // Cannot change because running
49 
50 // Server Area ID  (use with Register/unregister - Lock/unlock Area)
51 const int srvAreaPE = 0;
52 const int srvAreaPA = 1;
53 const int srvAreaMK = 2;
54 const int srvAreaCT = 3;
55 const int srvAreaTM = 4;
56 const int srvAreaDB = 5;
57 
58 typedef struct{
59 	word   Number; // Number (only for DB)
60 	word   Size;   // Area size (in bytes)
61 	pbyte  PData;  // Pointer to area
62 	PSnapCriticalSection cs;
63 }TS7Area, *PS7Area;
64 
65 //------------------------------------------------------------------------------
66 // ISOTCP WORKER CLASS
67 //------------------------------------------------------------------------------
68 class TIsoTcpWorker : public TIsoTcpSocket
69 {
70 protected:
71 	virtual bool IsoPerformCommand(int &Size);
72 	virtual bool ExecuteSend();
73 	virtual bool ExecuteRecv();
74 public:
TIsoTcpWorker()75 	TIsoTcpWorker(){};
~TIsoTcpWorker()76 	~TIsoTcpWorker(){};
77 	// Worker execution
78 	bool Execute();
79 };
80 //------------------------------------------------------------------------------
81 // S7 WORKER CLASS
82 //------------------------------------------------------------------------------
83 
84 // SZL frame
85 typedef struct{
86     TS7Answer17         Answer;
87     PReqFunReadSZLFirst ReqParams;
88     PS7ReqSZLData       ReqData;
89     PS7ResParams7       ResParams;
90     pbyte               ResData;
91     int                 ID;
92     int                 Index;
93     bool                SZLDone;
94 }TSZL;
95 
96 // Current Event Info
97 typedef struct{
98     word EvRetCode;
99     word EvArea;
100     word EvIndex;
101     word EvStart;
102     word EvSize;
103 }TEv;
104 
105 // Current Block info
106 typedef struct{
107   PReqFunGetBlockInfo ReqParams;
108   PResFunGetBlockInfo ResParams;
109   TS7Answer17         Answer;
110   word                evError;
111   word                DataLength;
112 }TCB;
113 
114 class TSnap7Server; // forward declaration
115 
116 class TS7Worker : public TIsoTcpWorker
117 {
118 private:
119     PS7ReqHeader PDUH_in;
120 	int DBCnt;
121     byte LastBlk;
122     TSZL SZL;
123     byte BCD(word Value);
124     // Checks the consistence of the incoming PDU
125     bool CheckPDU_in(int PayloadSize);
126     void FillTime(PS7Time PTime);
127 protected:
128     int DataSizeByte(int WordLength);
129     bool ExecuteRecv();
130     void DoEvent(longword Code, word RetCode, word Param1, word Param2,
131       word Param3, word Param4);
132     void DoReadEvent(longword Code, word RetCode, word Param1, word Param2,
133       word Param3, word Param4);
134     void FragmentSkipped(int Size);
135     // Entry parse
136     bool IsoPerformCommand(int &Size);
137     // First stage parse
138     bool PerformPDUAck(int &Size);
139     bool PerformPDURequest(int &Size);
140     bool PerformPDUUsrData(int &Size);
141     // Second stage parse : PDU Request
142     PS7Area GetArea(byte S7Code, word index);
143     // Group Read Area
144     bool PerformFunctionRead();
145     // Subfunctions Read Data
146     word ReadArea(PResFunReadItem ResItemData, PReqFunReadItem ReqItemPar,
147     int &PDURemainder,TEv &EV);
148     word RA_NotFound(PResFunReadItem ResItem, TEv &EV);
149     word RA_OutOfRange(PResFunReadItem ResItem, TEv &EV);
150     word RA_SizeOverPDU(PResFunReadItem ResItem, TEv &EV);
151     // Group Write Area
152     bool PerformFunctionWrite();
153     // Subfunctions Write Data
154     byte WriteArea(PReqFunWriteDataItem ReqItemData, PReqFunWriteItem ReqItemPar,
155          TEv &EV);
156     byte WA_NotFound(TEv &EV);
157     byte WA_InvalidTransportSize(TEv &EV);
158     byte WA_OutOfRange(TEv &EV);
159     byte WA_DataSizeMismatch(TEv &EV);
160     // Negotiate PDU Length
161     bool PerformFunctionNegotiate();
162     // Control
163     bool PerformFunctionControl(byte PduFun);
164     // Up/Download
165 	bool PerformFunctionUpload();
166     bool PerformFunctionDownload();
167     // Second stage parse : PDU User data
168     bool PerformGroupProgrammer();
169     bool PerformGroupCyclicData();
170     bool PerformGroupSecurity();
171     // Group Block(s) Info
172     bool PerformGroupBlockInfo();
173     // Subfunctions Block info
174     void BLK_ListAll(TCB &CB);
175     void BLK_ListBoT(byte BlockType, bool Start, TCB &CB);
176     void BLK_NoResource_ListBoT(PDataFunGetBot Data, TCB &CB);
177     void BLK_GetBlkInfo(TCB &CB);
178     void BLK_NoResource_GetBlkInfo(PResDataBlockInfo Data, TCB &CB);
179     void BLK_GetBlockNum_GetBlkInfo(int &BlkNum, PReqDataBlockInfo ReqData);
180     void BLK_DoBlockInfo_GetBlkInfo(PS7Area DB, PResDataBlockInfo Data, TCB &CB);
181     // Clock Group
182     bool PerformGetClock();
183     bool PerformSetClock();
184     // SZL Group
185     bool PerformGroupSZL();
186     // Subfunctions (called by PerformGroupSZL)
187     void SZLNotAvailable();
188 	void SZLSystemState();
189 	void SZLData(void *P, int len);
190 	void SZL_ID424();
191 	void SZL_ID131_IDX003();
192 public:
193     TSnap7Server *FServer;
194     int FPDULength;
195     TS7Worker();
~TS7Worker()196     ~TS7Worker(){};
197 };
198 
199 typedef TS7Worker *PS7Worker;
200 //------------------------------------------------------------------------------
201 // S7 SERVER CLASS
202 //------------------------------------------------------------------------------
203 extern "C"
204 {
205 	typedef int (S7API *pfn_RWAreaCallBack)(void *usrPtr, int Sender, int Operation, PS7Tag PTag, void *pUsrData);
206 }
207 const int OperationRead  = 0;
208 const int OperationWrite = 1;
209 
210 class TSnap7Server : public TCustomMsgServer
211 {
212 private:
213     // Read Callback related
214     pfn_SrvCallBack OnReadEvent;
215 	pfn_RWAreaCallBack OnRWArea;
216 	// Critical section to lock Read/Write Hook Area
217 	PSnapCriticalSection CSRWHook;
218 	void *FReadUsrPtr;
219 	void *FRWAreaUsrPtr;
220 	void DisposeAll();
221     int FindFirstFreeDB();
222     int IndexOfDB(word DBNumber);
223 protected:
224     int DBCount;
225     int DBLimit;
226     PS7Area DB[MaxDB]; // DB
227     PS7Area HA[5];     // MK,PE,PA,TM,CT
228     PS7Area FindDB(word DBNumber);
229     PWorkerSocket CreateWorkerSocket(socket_t Sock);
230 	bool ResourceLess;
231 	word ForcePDU;
232     int RegisterDB(word Number, void *pUsrData, word Size);
233     int RegisterSys(int AreaCode, void *pUsrData, word Size);
234     int UnregisterDB(word DBNumber);
235     int UnregisterSys(int AreaCode);
236     // The Read event
237     void DoReadEvent(int Sender, longword Code, word RetCode, word Param1,
238       word Param2, word Param3, word Param4);
239 	bool DoReadArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData);
240 	bool DoWriteArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData);
241 public:
242     int WorkInterval;
243     byte CpuStatus;
244     TSnap7Server();
245     ~TSnap7Server();
246     int StartTo(const char *Address);
247     int GetParam(int ParamNumber, void *pValue);
248     int SetParam(int ParamNumber, void *pValue);
249     int RegisterArea(int AreaCode, word Index, void *pUsrData, word Size);
250     int UnregisterArea(int AreaCode, word Index);
251     int LockArea(int AreaCode, word DBNumber);
252     int UnlockArea(int AreaCode, word DBNumber);
253     // Sets Event callback
254     int SetReadEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr);
255 	int SetRWAreaCallBack(pfn_RWAreaCallBack PCallBack, void *UsrPtr);
256     friend class TS7Worker;
257 };
258 typedef TSnap7Server *PSnap7Server;
259 
260 #endif // s7_server_h
261 
262